Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media updates from Mauro Carvalho Chehab:
 "The main set of series of patches for media subsystem, including:
   - document RC sysfs class
   - added an API to setup scancode to allow waking up systems using the
     Remote Controller
   - add API for SDR devices.  Drivers are still on staging
   - some API improvements for getting EDID data from media
     inputs/outputs
   - new DVB frontend driver for drx-j (ATSC)
   - one driver (it913x/it9137) got removed, in favor of an improvement
     on another driver (af9035)
   - added a skeleton V4L2 PCI driver at documentation
   - added a dual flash driver (lm3646)
   - added a new IR driver (img-ir)
   - added an IR scancode decoder for the Sharp protocol
   - some improvements at the usbtv driver, to allow its core to be
     reused.
   - added a new SDR driver (rtl2832u_sdr)
   - added a new tuner driver (msi001)
   - several improvements at em28xx driver to fix PM support, device
     removal and to split the V4L2 specific bits into a separate
     sub-driver
   - one driver got converted to videobuf2 (s2255drv)
   - the e4000 tuner driver now follows an improved binding model
   - some fixes at V4L2 compat32 code
   - several fixes and enhancements at videobuf2 code
   - some cleanups at V4L2 API documentation
   - usual driver enhancements, new board additions and misc fixups"

[ NOTE! This merge effective drops commit 4329b93b283c ("of: Reduce
  indentation in of_graph_get_next_endpoint").

  The of_graph_get_next_endpoint() function was moved and renamed by
  commit fd9fdb78a9bf ("[media] of: move graph helpers from
  drivers/media/v4l2-core to drivers/of").  It was originally called
  v4l2_of_get_next_endpoint() and lived in the file
  drivers/media/v4l2-core/v4l2-of.c.

  In that original location, it was then fixed to support empty port
  nodes by commit b9db140c1e46 ("[media] v4l: of: Support empty port
  nodes"), and that commit clashes badly with the dropped "Reduce
  intendation" commit.  I had to choose one or the other, and decided
  that the "Support empty port nodes" commit was more important ]

* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (426 commits)
  [media] em28xx-dvb: fix PCTV 461e tuner I2C binding
  Revert "[media] em28xx-dvb: fix PCTV 461e tuner I2C binding"
  [media] em28xx: fix PCTV 290e LNA oops
  [media] em28xx-dvb: fix PCTV 461e tuner I2C binding
  [media] m88ds3103: fix bug on .set_tone()
  [media] saa7134: fix WARN_ON during resume
  [media] v4l2-dv-timings: add module name, description, license
  [media] videodev2.h: add parenthesis around macro arguments
  [media] saa6752hs: depends on CRC32
  [media] si4713: fix Kconfig dependencies
  [media] Sensoray 2255 uses videobuf2
  [media] adv7180: free an interrupt on failure paths in init_device()
  [media] e4000: make VIDEO_V4L2 dependency optional
  [media] af9033: Don't export functions for the hardware filter
  [media] af9035: use af9033 PID filters
  [media] af9033: implement PID filter
  [media] rtl2832_sdr: do not use dynamic stack allocation
  [media] e4000: fix 32-bit build error
  [media] em28xx-audio: make sure audio is unmuted on open()
  [media] DocBook media: v4l2_format_sdr was renamed to v4l2_sdr_format
  ...
diff --git a/CREDITS b/CREDITS
index 61eabf7..c322dcf 100644
--- a/CREDITS
+++ b/CREDITS
@@ -630,6 +630,13 @@
 E: mec@shout.net
 D: Configure, Menuconfig, xconfig
 
+N: Mauro Carvalho Chehab
+E: m.chehab@samsung.org
+E: mchehab@infradead.org
+D: Media subsystem (V4L/DVB) drivers and core
+D: EDAC drivers and EDAC 3.0 core rework
+S: Brazil
+
 N: Raymond Chen
 E: raymondc@microsoft.com
 D: Author of Configure script
diff --git a/Documentation/ABI/testing/sysfs-class-rc b/Documentation/ABI/testing/sysfs-class-rc
new file mode 100644
index 0000000..b65674d
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-rc
@@ -0,0 +1,111 @@
+What:		/sys/class/rc/
+Date:		Apr 2010
+KernelVersion:	2.6.35
+Contact:	Mauro Carvalho Chehab <m.chehab@samsung.com>
+Description:
+		The rc/ class sub-directory belongs to the Remote Controller
+		core and provides a sysfs interface for configuring infrared
+		remote controller receivers.
+
+What:		/sys/class/rc/rcN/
+Date:		Apr 2010
+KernelVersion:	2.6.35
+Contact:	Mauro Carvalho Chehab <m.chehab@samsung.com>
+Description:
+		A /sys/class/rc/rcN directory is created for each remote
+		control receiver device where N is the number of the receiver.
+
+What:		/sys/class/rc/rcN/protocols
+Date:		Jun 2010
+KernelVersion:	2.6.36
+Contact:	Mauro Carvalho Chehab <m.chehab@samsung.com>
+Description:
+		Reading this file returns a list of available protocols,
+		something like:
+		    "rc5 [rc6] nec jvc [sony]"
+		Enabled protocols are shown in [] brackets.
+		Writing "+proto" will add a protocol to the list of enabled
+		protocols.
+		Writing "-proto" will remove a protocol from the list of enabled
+		protocols.
+		Writing "proto" will enable only "proto".
+		Writing "none" will disable all protocols.
+		Write fails with EINVAL if an invalid protocol combination or
+		unknown protocol name is used.
+
+What:		/sys/class/rc/rcN/filter
+Date:		Jan 2014
+KernelVersion:	3.15
+Contact:	Mauro Carvalho Chehab <m.chehab@samsung.com>
+Description:
+		Sets the scancode filter expected value.
+		Use in combination with /sys/class/rc/rcN/filter_mask to set the
+		expected value of the bits set in the filter mask.
+		If the hardware supports it then scancodes which do not match
+		the filter will be ignored. Otherwise the write will fail with
+		an error.
+		This value may be reset to 0 if the current protocol is altered.
+
+What:		/sys/class/rc/rcN/filter_mask
+Date:		Jan 2014
+KernelVersion:	3.15
+Contact:	Mauro Carvalho Chehab <m.chehab@samsung.com>
+Description:
+		Sets the scancode filter mask of bits to compare.
+		Use in combination with /sys/class/rc/rcN/filter to set the bits
+		of the scancode which should be compared against the expected
+		value. A value of 0 disables the filter to allow all valid
+		scancodes to be processed.
+		If the hardware supports it then scancodes which do not match
+		the filter will be ignored. Otherwise the write will fail with
+		an error.
+		This value may be reset to 0 if the current protocol is altered.
+
+What:		/sys/class/rc/rcN/wakeup_protocols
+Date:		Feb 2014
+KernelVersion:	3.15
+Contact:	Mauro Carvalho Chehab <m.chehab@samsung.com>
+Description:
+		Reading this file returns a list of available protocols to use
+		for the wakeup filter, something like:
+		    "rc5 rc6 nec jvc [sony]"
+		The enabled wakeup protocol is shown in [] brackets.
+		Writing "+proto" will add a protocol to the list of enabled
+		wakeup protocols.
+		Writing "-proto" will remove a protocol from the list of enabled
+		wakeup protocols.
+		Writing "proto" will use "proto" for wakeup events.
+		Writing "none" will disable wakeup.
+		Write fails with EINVAL if an invalid protocol combination or
+		unknown protocol name is used, or if wakeup is not supported by
+		the hardware.
+
+What:		/sys/class/rc/rcN/wakeup_filter
+Date:		Jan 2014
+KernelVersion:	3.15
+Contact:	Mauro Carvalho Chehab <m.chehab@samsung.com>
+Description:
+		Sets the scancode wakeup filter expected value.
+		Use in combination with /sys/class/rc/rcN/wakeup_filter_mask to
+		set the expected value of the bits set in the wakeup filter mask
+		to trigger a system wake event.
+		If the hardware supports it and wakeup_filter_mask is not 0 then
+		scancodes which match the filter will wake the system from e.g.
+		suspend to RAM or power off.
+		Otherwise the write will fail with an error.
+		This value may be reset to 0 if the wakeup protocol is altered.
+
+What:		/sys/class/rc/rcN/wakeup_filter_mask
+Date:		Jan 2014
+KernelVersion:	3.15
+Contact:	Mauro Carvalho Chehab <m.chehab@samsung.com>
+Description:
+		Sets the scancode wakeup filter mask of bits to compare.
+		Use in combination with /sys/class/rc/rcN/wakeup_filter to set
+		the bits of the scancode which should be compared against the
+		expected value to trigger a system wake event.
+		If the hardware supports it and wakeup_filter_mask is not 0 then
+		scancodes which match the filter will wake the system from e.g.
+		suspend to RAM or power off.
+		Otherwise the write will fail with an error.
+		This value may be reset to 0 if the wakeup protocol is altered.
diff --git a/Documentation/DocBook/media/dvb/demux.xml b/Documentation/DocBook/media/dvb/demux.xml
index 86de89c..c8683d6 100644
--- a/Documentation/DocBook/media/dvb/demux.xml
+++ b/Documentation/DocBook/media/dvb/demux.xml
@@ -1042,7 +1042,14 @@
 </para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
-<para>This ioctl is undocumented. Documentation is welcome.</para>
+<para>This ioctl call allows to add multiple PIDs to a transport stream filter
+previously set up with DMX_SET_PES_FILTER and output equal to DMX_OUT_TSDEMUX_TAP.
+</para></entry></row><row><entry align="char"><para>
+It is used by readers of /dev/dvb/adapterX/demuxY.
+</para></entry></row><row><entry align="char"><para>
+It may be called at any time, i.e. before or after the first filter on the
+shared file descriptor was started. It makes it possible to record multiple
+services without the need to de-multiplex or re-multiplex TS packets.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
 <para>SYNOPSIS
@@ -1075,7 +1082,7 @@
 </para>
 </entry><entry
  align="char">
-<para>Undocumented.</para>
+<para>PID number to be filtered.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
 &return-value-dvb;
@@ -1087,7 +1094,15 @@
 </para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
-<para>This ioctl is undocumented. Documentation is welcome.</para>
+<para>This ioctl call allows to remove a PID when multiple PIDs are set on a
+transport stream filter, e. g. a filter previously set up with output equal to
+DMX_OUT_TSDEMUX_TAP, created via either DMX_SET_PES_FILTER or DMX_ADD_PID.
+</para></entry></row><row><entry align="char"><para>
+It is used by readers of /dev/dvb/adapterX/demuxY.
+</para></entry></row><row><entry align="char"><para>
+It may be called at any time, i.e. before or after the first filter on the
+shared file descriptor was started. It makes it possible to record multiple
+services without the need to de-multiplex or re-multiplex TS packets.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
 <para>SYNOPSIS
@@ -1120,7 +1135,7 @@
 </para>
 </entry><entry
  align="char">
-<para>Undocumented.</para>
+<para>PID of the PES filter to be removed.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
 &return-value-dvb;
diff --git a/Documentation/DocBook/media/dvb/dvbapi.xml b/Documentation/DocBook/media/dvb/dvbapi.xml
index 0197bcc..4c15396 100644
--- a/Documentation/DocBook/media/dvb/dvbapi.xml
+++ b/Documentation/DocBook/media/dvb/dvbapi.xml
@@ -18,7 +18,7 @@
 <firstname>Mauro</firstname>
 <othername role="mi">Carvalho</othername>
 <surname>Chehab</surname>
-<affiliation><address><email>mchehab@redhat.com</email></address></affiliation>
+<affiliation><address><email>m.chehab@samsung.com</email></address></affiliation>
 <contrib>Ported document to Docbook XML.</contrib>
 </author>
 </authorgroup>
@@ -28,7 +28,7 @@
 	<holder>Convergence GmbH</holder>
 </copyright>
 <copyright>
-	<year>2009-2012</year>
+	<year>2009-2014</year>
 	<holder>Mauro Carvalho Chehab</holder>
 </copyright>
 
diff --git a/Documentation/DocBook/media/dvb/frontend.xml b/Documentation/DocBook/media/dvb/frontend.xml
index 0d6e81b..8a6a6ff 100644
--- a/Documentation/DocBook/media/dvb/frontend.xml
+++ b/Documentation/DocBook/media/dvb/frontend.xml
@@ -744,7 +744,7 @@
 </para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
-<para>int ioctl(int fd, int request = <link linkend="FE_READ_SNR">FE_READ_SNR</link>, int16_t
+<para>int ioctl(int fd, int request = <link linkend="FE_READ_SNR">FE_READ_SNR</link>, uint16_t
  &#x22C6;snr);</para>
 </entry>
  </row></tbody></tgroup></informaltable>
@@ -766,7 +766,7 @@
 </entry>
  </row><row><entry
  align="char">
-<para>int16_t *snr</para>
+<para>uint16_t *snr</para>
 </entry><entry
  align="char">
 <para>The signal-to-noise ratio is stored into *snr.</para>
@@ -791,7 +791,7 @@
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>int ioctl( int fd, int request =
- <link linkend="FE_READ_SIGNAL_STRENGTH">FE_READ_SIGNAL_STRENGTH</link>, int16_t &#x22C6;strength);</para>
+ <link linkend="FE_READ_SIGNAL_STRENGTH">FE_READ_SIGNAL_STRENGTH</link>, uint16_t &#x22C6;strength);</para>
 </entry>
  </row></tbody></tgroup></informaltable>
 
@@ -814,7 +814,7 @@
 </entry>
  </row><row><entry
  align="char">
-<para>int16_t *strength</para>
+<para>uint16_t *strength</para>
 </entry><entry
  align="char">
 <para>The signal strength value is stored into *strength.</para>
diff --git a/Documentation/DocBook/media/v4l/common.xml b/Documentation/DocBook/media/v4l/common.xml
index 1ddf354..71f6bf9 100644
--- a/Documentation/DocBook/media/v4l/common.xml
+++ b/Documentation/DocBook/media/v4l/common.xml
@@ -38,70 +38,41 @@
 
       <para>V4L2 drivers are implemented as kernel modules, loaded
 manually by the system administrator or automatically when a device is
-first opened. The driver modules plug into the "videodev" kernel
+first discovered. The driver modules plug into the "videodev" kernel
 module. It provides helper functions and a common application
 interface specified in this document.</para>
 
       <para>Each driver thus loaded registers one or more device nodes
-with major number 81 and a minor number between 0 and 255. Assigning
-minor numbers to V4L2 devices is entirely up to the system administrator,
-this is primarily intended to solve conflicts between devices.<footnote>
-	  <para>Access permissions are associated with character
-device special files, hence we must ensure device numbers cannot
-change with the module load order. To this end minor numbers are no
-longer automatically assigned by the "videodev" module as in V4L but
-requested by the driver. The defaults will suffice for most people
-unless two drivers compete for the same minor numbers.</para>
-	</footnote> The module options to select minor numbers are named
-after the device special file with a "_nr" suffix. For example "video_nr"
-for <filename>/dev/video</filename> video capture devices. The number is
-an offset to the base minor number associated with the device type.
-<footnote>
-	  <para>In earlier versions of the V4L2 API the module options
-where named after the device special file with a "unit_" prefix, expressing
-the minor number itself, not an offset. Rationale for this change is unknown.
-Lastly the naming and semantics are just a convention among driver writers,
-the point to note is that minor numbers are not supposed to be hardcoded
-into drivers.</para>
-	</footnote> When the driver supports multiple devices of the same
-type more than one minor number can be assigned, separated by commas:
-<informalexample>
+with major number 81 and a minor number between 0 and 255. Minor numbers
+are allocated dynamically unless the kernel is compiled with the kernel
+option CONFIG_VIDEO_FIXED_MINOR_RANGES. In that case minor numbers are
+allocated in ranges depending on the device node type (video, radio, etc.).</para>
+
+      <para>Many drivers support "video_nr", "radio_nr" or "vbi_nr"
+module options to select specific video/radio/vbi node numbers. This allows
+the user to request that the device node is named e.g. /dev/video5 instead
+of leaving it to chance. When the driver supports multiple devices of the same
+type more than one device node number can be assigned, separated by commas:
+	<informalexample>
 	  <screen>
-&gt; insmod mydriver.o video_nr=0,1 radio_nr=0,1</screen>
+&gt; modprobe mydriver video_nr=0,1 radio_nr=0,1</screen>
 	</informalexample></para>
 
       <para>In <filename>/etc/modules.conf</filename> this may be
 written as: <informalexample>
 	  <screen>
-alias char-major-81-0 mydriver
-alias char-major-81-1 mydriver
-alias char-major-81-64 mydriver              <co id="alias" />
-options mydriver video_nr=0,1 radio_nr=0,1   <co id="options" />
+options mydriver video_nr=0,1 radio_nr=0,1
 	  </screen>
-	  <calloutlist>
-	    <callout arearefs="alias">
-	      <para>When an application attempts to open a device
-special file with major number 81 and minor number 0, 1, or 64, load
-"mydriver" (and the "videodev" module it depends upon).</para>
-	    </callout>
-	    <callout arearefs="options">
-	      <para>Register the first two video capture devices with
-minor number 0 and 1 (base number is 0), the first two radio device
-with minor number 64 and 65 (base 64).</para>
-	    </callout>
-	  </calloutlist>
-	</informalexample> When no minor number is given as module
-option the driver supplies a default. <xref linkend="devices" />
-recommends the base minor numbers to be used for the various device
-types. Obviously minor numbers must be unique. When the number is
-already in use the <emphasis>offending device</emphasis> will not be
-registered. <!-- Blessed by Linus Torvalds on
-linux-kernel@vger.kernel.org, 2002-11-20. --></para>
+	</informalexample> When no device node number is given as module
+option the driver supplies a default.</para>
 
-      <para>By convention system administrators create various
-character device special files with these major and minor numbers in
-the <filename>/dev</filename> directory. The names recommended for the
-different V4L2 device types are listed in <xref linkend="devices" />.
+      <para>Normally udev will create the device nodes in /dev automatically
+for you. If udev is not installed, then you need to enable the
+CONFIG_VIDEO_FIXED_MINOR_RANGES kernel option in order to be able to correctly
+relate a minor number to a device node number. I.e., you need to be certain
+that minor number 5 maps to device node name video5. With this kernel option
+different device types have different minor number ranges. These ranges are
+listed in <xref linkend="devices" />.
 </para>
 
       <para>The creation of character special files (with
@@ -110,85 +81,66 @@
 applications cannot <emphasis>reliable</emphasis> scan for loaded or
 installed drivers. The user must enter a device name, or the
 application can try the conventional device names.</para>
-
-      <para>Under the device filesystem (devfs) the minor number
-options are ignored. V4L2 drivers (or by proxy the "videodev" module)
-automatically create the required device files in the
-<filename>/dev/v4l</filename> directory using the conventional device
-names above.</para>
     </section>
 
     <section id="related">
       <title>Related Devices</title>
 
-      <para>Devices can support several related functions. For example
-video capturing, video overlay and VBI capturing are related because
-these functions share, amongst other, the same video input and tuner
-frequency. V4L and earlier versions of V4L2 used the same device name
-and minor number for video capturing and overlay, but different ones
-for VBI. Experience showed this approach has several problems<footnote>
-	  <para>Given a device file name one cannot reliable find
-related devices. For once names are arbitrary and in a system with
-multiple devices, where only some support VBI capturing, a
-<filename>/dev/video2</filename> is not necessarily related to
-<filename>/dev/vbi2</filename>. The V4L
-<constant>VIDIOCGUNIT</constant> ioctl would require a search for a
-device file with a particular major and minor number.</para>
-	</footnote>, and to make things worse the V4L videodev module
-used to prohibit multiple opens of a device.</para>
+      <para>Devices can support several functions. For example
+video capturing, VBI capturing and radio support.</para>
 
-      <para>As a remedy the present version of the V4L2 API relaxed the
-concept of device types with specific names and minor numbers. For
-compatibility with old applications drivers must still register different
-minor numbers to assign a default function to the device. But if related
-functions are supported by the driver they must be available under all
-registered minor numbers. The desired function can be selected after
-opening the device as described in <xref linkend="devices" />.</para>
+      <para>The V4L2 API creates different nodes for each of these functions.</para>
 
-      <para>Imagine a driver supporting video capturing, video
-overlay, raw VBI capturing, and FM radio reception. It registers three
-devices with minor number 0, 64 and 224 (this numbering scheme is
-inherited from the V4L API). Regardless if
-<filename>/dev/video</filename> (81, 0) or
-<filename>/dev/vbi</filename> (81, 224) is opened the application can
-select any one of the video capturing, overlay or VBI capturing
-functions. Without programming (e.&nbsp;g. reading from the device
-with <application>dd</application> or <application>cat</application>)
-<filename>/dev/video</filename> captures video images, while
-<filename>/dev/vbi</filename> captures raw VBI data.
-<filename>/dev/radio</filename> (81, 64) is invariable a radio device,
-unrelated to the video functions. Being unrelated does not imply the
-devices can be used at the same time, however. The &func-open;
-function may very well return an &EBUSY;.</para>
+      <para>The V4L2 API was designed with the idea that one device node could support
+all functions. However, in practice this never worked: this 'feature'
+was never used by applications and many drivers did not support it and if
+they did it was certainly never tested. In addition, switching a device
+node between different functions only works when using the streaming I/O
+API, not with the read()/write() API.</para>
+
+      <para>Today each device node supports just one function.</para>
 
       <para>Besides video input or output the hardware may also
 support audio sampling or playback. If so, these functions are
-implemented as OSS or ALSA PCM devices and eventually OSS or ALSA
-audio mixer. The V4L2 API makes no provisions yet to find these
-related devices. If you have an idea please write to the linux-media
-mailing list: &v4l-ml;.</para>
+implemented as ALSA PCM devices with optional ALSA audio mixer
+devices.</para>
+
+      <para>One problem with all these devices is that the V4L2 API
+makes no provisions to find these related devices. Some really
+complex devices use the Media Controller (see <xref linkend="media_controller" />)
+which can be used for this purpose. But most drivers do not use it,
+and while some code exists that uses sysfs to discover related devices
+(see libmedia_dev in the <ulink url="http://git.linuxtv.org/v4l-utils/">v4l-utils</ulink>
+git repository), there is no library yet that can provide a single API towards
+both Media Controller-based devices and devices that do not use the Media Controller.
+If you want to work on this please write to the linux-media mailing list: &v4l-ml;.</para>
     </section>
 
     <section>
       <title>Multiple Opens</title>
 
-      <para>In general, V4L2 devices can be opened more than once.
+      <para>V4L2 devices can be opened more than once.<footnote><para>
+There are still some old and obscure drivers that have not been updated to
+allow for multiple opens. This implies that for such drivers &func-open; can
+return an &EBUSY; when the device is already in use.</para></footnote>
 When this is supported by the driver, users can for example start a
 "panel" application to change controls like brightness or audio
 volume, while another application captures video and audio. In other words, panel
-applications are comparable to an OSS or ALSA audio mixer application.
-When a device supports multiple functions like capturing and overlay
-<emphasis>simultaneously</emphasis>, multiple opens allow concurrent
-use of the device by forked processes or specialized applications.</para>
+applications are comparable to an ALSA audio mixer application.
+Just opening a V4L2 device should not change the state of the device.<footnote>
+<para>Unfortunately, opening a radio device often switches the state of the
+device to radio mode in many drivers. This behavior should be fixed eventually
+as it violates the V4L2 specification.</para></footnote></para>
 
-      <para>Multiple opens are optional, although drivers should
-permit at least concurrent accesses without data exchange, &ie; panel
-applications. This implies &func-open; can return an &EBUSY; when the
-device is already in use, as well as &func-ioctl; functions initiating
-data exchange (namely the &VIDIOC-S-FMT; ioctl), and the &func-read;
-and &func-write; functions.</para>
+      <para>Once an application has allocated the memory buffers needed for
+streaming data (by calling the &VIDIOC-REQBUFS; or &VIDIOC-CREATE-BUFS; ioctls,
+or implicitly by calling the &func-read; or &func-write; functions) that
+application (filehandle) becomes the owner of the device. It is no longer
+allowed to make changes that would affect the buffer sizes (e.g. by calling
+the &VIDIOC-S-FMT; ioctl) and other applications are no longer allowed to allocate
+buffers or start or stop streaming. The &EBUSY; will be returned instead.</para>
 
-      <para>Mere opening a V4L2 device does not grant exclusive
+      <para>Merely opening a V4L2 device does not grant exclusive
 access.<footnote>
 	  <para>Drivers could recognize the
 <constant>O_EXCL</constant> open flag. Presently this is not required,
@@ -206,12 +158,7 @@
       <para>V4L2 drivers should not support multiple applications
 reading or writing the same data stream on a device by copying
 buffers, time multiplexing or similar means. This is better handled by
-a proxy application in user space. When the driver supports stream
-sharing anyway it must be implemented transparently. The V4L2 API does
-not specify how conflicts are solved. <!-- For example O_EXCL when the
-application does not want to be preempted, PROT_READ mmapped buffers
-which can be mapped twice, what happens when image formats do not
-match etc.--></para>
+a proxy application in user space.</para>
     </section>
 
     <section>
@@ -240,15 +187,15 @@
 
     <para>Starting with kernel version 3.1, VIDIOC-QUERYCAP will return the
 V4L2 API version used by the driver, with generally matches the Kernel version.
-There's no need of using &VIDIOC-QUERYCAP; to check if an specific ioctl is
-supported, the V4L2 core now returns ENOIOCTLCMD if a driver doesn't provide
+There's no need of using &VIDIOC-QUERYCAP; to check if a specific ioctl is
+supported, the V4L2 core now returns ENOTTY if a driver doesn't provide
 support for an ioctl.</para>
 
     <para>Other features can be queried
 by calling the respective ioctl, for example &VIDIOC-ENUMINPUT;
 to learn about the number, types and names of video connectors on the
 device. Although abstraction is a major objective of this API, the
-ioctl also allows driver specific applications to reliable identify
+&VIDIOC-QUERYCAP; ioctl also allows driver specific applications to reliably identify
 the driver.</para>
 
     <para>All V4L2 drivers must support
@@ -278,9 +225,7 @@
 the &VIDIOC-QUERYCAP; ioctl.</para>
 
     <para>Ioctls changing driver properties, such as &VIDIOC-S-INPUT;,
-return an &EBUSY; after another application obtained higher priority.
-An event mechanism to notify applications about asynchronous property
-changes has been proposed but not added yet.</para>
+return an &EBUSY; after another application obtained higher priority.</para>
   </section>
 
   <section id="video">
@@ -288,9 +233,9 @@
 
     <para>Video inputs and outputs are physical connectors of a
 device. These can be for example RF connectors (antenna/cable), CVBS
-a.k.a. Composite Video, S-Video or RGB connectors. Only video and VBI
-capture devices have inputs, output devices have outputs, at least one
-each. Radio devices have no video inputs or outputs.</para>
+a.k.a. Composite Video, S-Video or RGB connectors. Video and VBI
+capture devices have inputs. Video and VBI output devices have outputs,
+at least one each. Radio devices have no video inputs or outputs.</para>
 
     <para>To learn about the number and attributes of the
 available inputs and outputs applications can enumerate them with the
@@ -299,30 +244,13 @@
 ioctl also contains signal status information applicable when the
 current video input is queried.</para>
 
-    <para>The &VIDIOC-G-INPUT; and &VIDIOC-G-OUTPUT; ioctl return the
+    <para>The &VIDIOC-G-INPUT; and &VIDIOC-G-OUTPUT; ioctls return the
 index of the current video input or output. To select a different
 input or output applications call the &VIDIOC-S-INPUT; and
-&VIDIOC-S-OUTPUT; ioctl. Drivers must implement all the input ioctls
+&VIDIOC-S-OUTPUT; ioctls. Drivers must implement all the input ioctls
 when the device has one or more inputs, all the output ioctls when the
 device has one or more outputs.</para>
 
-    <!--
-    <figure id=io-tree>
-      <title>Input and output enumeration is the root of most device properties.</title>
-      <mediaobject>
-	<imageobject>
-	  <imagedata fileref="links.pdf" format="ps" />
-	</imageobject>
-	<imageobject>
-	  <imagedata fileref="links.gif" format="gif" />
-	</imageobject>
-	<textobject>
-	  <phrase>Links between various device property structures.</phrase>
-	</textobject>
-      </mediaobject>
-    </figure>
-    -->
-
     <example>
       <title>Information about the current video input</title>
 
@@ -330,20 +258,20 @@
 &v4l2-input; input;
 int index;
 
-if (-1 == ioctl (fd, &VIDIOC-G-INPUT;, &amp;index)) {
-	perror ("VIDIOC_G_INPUT");
-	exit (EXIT_FAILURE);
+if (-1 == ioctl(fd, &VIDIOC-G-INPUT;, &amp;index)) {
+	perror("VIDIOC_G_INPUT");
+	exit(EXIT_FAILURE);
 }
 
-memset (&amp;input, 0, sizeof (input));
+memset(&amp;input, 0, sizeof(input));
 input.index = index;
 
-if (-1 == ioctl (fd, &VIDIOC-ENUMINPUT;, &amp;input)) {
-	perror ("VIDIOC_ENUMINPUT");
-	exit (EXIT_FAILURE);
+if (-1 == ioctl(fd, &VIDIOC-ENUMINPUT;, &amp;input)) {
+	perror("VIDIOC_ENUMINPUT");
+	exit(EXIT_FAILURE);
 }
 
-printf ("Current input: %s\n", input.name);
+printf("Current input: %s\n", input.name);
       </programlisting>
     </example>
 
@@ -355,9 +283,9 @@
 
 index = 0;
 
-if (-1 == ioctl (fd, &VIDIOC-S-INPUT;, &amp;index)) {
-	perror ("VIDIOC_S_INPUT");
-	exit (EXIT_FAILURE);
+if (-1 == ioctl(fd, &VIDIOC-S-INPUT;, &amp;index)) {
+	perror("VIDIOC_S_INPUT");
+	exit(EXIT_FAILURE);
 }
       </programlisting>
     </example>
@@ -397,7 +325,7 @@
 also contains signal status information applicable when the current
 audio input is queried.</para>
 
-    <para>The &VIDIOC-G-AUDIO; and &VIDIOC-G-AUDOUT; ioctl report
+    <para>The &VIDIOC-G-AUDIO; and &VIDIOC-G-AUDOUT; ioctls report
 the current audio input and output, respectively. Note that, unlike
 &VIDIOC-G-INPUT; and &VIDIOC-G-OUTPUT; these ioctls return a structure
 as <constant>VIDIOC_ENUMAUDIO</constant> and
@@ -408,11 +336,11 @@
 output (which presently has no changeable properties) applications
 call the &VIDIOC-S-AUDOUT; ioctl.</para>
 
-    <para>Drivers must implement all input ioctls when the device
-has one or more inputs, all output ioctls when the device has one
-or more outputs. When the device has any audio inputs or outputs the
-driver must set the <constant>V4L2_CAP_AUDIO</constant> flag in the
-&v4l2-capability; returned by the &VIDIOC-QUERYCAP; ioctl.</para>
+    <para>Drivers must implement all audio input ioctls when the device
+has multiple selectable audio inputs, all audio output ioctls when the
+device has multiple selectable audio outputs. When the device has any
+audio inputs or outputs the driver must set the <constant>V4L2_CAP_AUDIO</constant>
+flag in the &v4l2-capability; returned by the &VIDIOC-QUERYCAP; ioctl.</para>
 
     <example>
       <title>Information about the current audio input</title>
@@ -420,14 +348,14 @@
       <programlisting>
 &v4l2-audio; audio;
 
-memset (&amp;audio, 0, sizeof (audio));
+memset(&amp;audio, 0, sizeof(audio));
 
-if (-1 == ioctl (fd, &VIDIOC-G-AUDIO;, &amp;audio)) {
-	perror ("VIDIOC_G_AUDIO");
-	exit (EXIT_FAILURE);
+if (-1 == ioctl(fd, &VIDIOC-G-AUDIO;, &amp;audio)) {
+	perror("VIDIOC_G_AUDIO");
+	exit(EXIT_FAILURE);
 }
 
-printf ("Current input: %s\n", audio.name);
+printf("Current input: %s\n", audio.name);
       </programlisting>
     </example>
 
@@ -437,13 +365,13 @@
       <programlisting>
 &v4l2-audio; audio;
 
-memset (&amp;audio, 0, sizeof (audio)); /* clear audio.mode, audio.reserved */
+memset(&amp;audio, 0, sizeof(audio)); /* clear audio.mode, audio.reserved */
 
 audio.index = 0;
 
-if (-1 == ioctl (fd, &VIDIOC-S-AUDIO;, &amp;audio)) {
-	perror ("VIDIOC_S_AUDIO");
-	exit (EXIT_FAILURE);
+if (-1 == ioctl(fd, &VIDIOC-S-AUDIO;, &amp;audio)) {
+	perror("VIDIOC_S_AUDIO");
+	exit(EXIT_FAILURE);
 }
       </programlisting>
     </example>
@@ -468,7 +396,7 @@
 video inputs.</para>
 
       <para>To query and change tuner properties applications use the
-&VIDIOC-G-TUNER; and &VIDIOC-S-TUNER; ioctl, respectively. The
+&VIDIOC-G-TUNER; and &VIDIOC-S-TUNER; ioctls, respectively. The
 &v4l2-tuner; returned by <constant>VIDIOC_G_TUNER</constant> also
 contains signal status information applicable when the tuner of the
 current video or radio input is queried. Note that
@@ -533,7 +461,7 @@
 support another set of standards. This set is reported by the
 <structfield>std</structfield> field of &v4l2-input; and
 &v4l2-output; returned by the &VIDIOC-ENUMINPUT; and
-&VIDIOC-ENUMOUTPUT; ioctl, respectively.</para>
+&VIDIOC-ENUMOUTPUT; ioctls, respectively.</para>
 
     <para>V4L2 defines one bit for each analog video standard
 currently in use worldwide, and sets aside bits for driver defined
@@ -564,28 +492,10 @@
     <para>To query and select the standard used by the current video
 input or output applications call the &VIDIOC-G-STD; and
 &VIDIOC-S-STD; ioctl, respectively. The <emphasis>received</emphasis>
-standard can be sensed with the &VIDIOC-QUERYSTD; ioctl. Note that the parameter of all these ioctls is a pointer to a &v4l2-std-id; type (a standard set), <emphasis>not</emphasis> an index into the standard enumeration.<footnote>
-	<para>An alternative to the current scheme is to use pointers
-to indices as arguments of <constant>VIDIOC_G_STD</constant> and
-<constant>VIDIOC_S_STD</constant>, the &v4l2-input; and
-&v4l2-output; <structfield>std</structfield> field would be a set of
-indices like <structfield>audioset</structfield>.</para>
-	<para>Indices are consistent with the rest of the API
-and identify the standard unambiguously. In the present scheme of
-things an enumerated standard is looked up by &v4l2-std-id;. Now the
-standards supported by the inputs of a device can overlap. Just
-assume the tuner and composite input in the example above both
-exist on a device. An enumeration of "PAL-B/G", "PAL-H/I" suggests
-a choice which does not exist. We cannot merge or omit sets, because
-applications would be unable to find the standards reported by
-<constant>VIDIOC_G_STD</constant>. That leaves separate enumerations
-for each input. Also selecting a standard by &v4l2-std-id; can be
-ambiguous. Advantage of this method is that applications need not
-identify the standard indirectly, after enumerating.</para><para>So in
-summary, the lookup itself is unavoidable. The difference is only
-whether the lookup is necessary to find an enumerated standard or to
-switch to a standard by &v4l2-std-id;.</para>
-      </footnote> Drivers must implement all video standard ioctls
+standard can be sensed with the &VIDIOC-QUERYSTD; ioctl. Note that the
+parameter of all these ioctls is a pointer to a &v4l2-std-id; type
+(a standard set), <emphasis>not</emphasis> an index into the standard
+enumeration. Drivers must implement all video standard ioctls
 when the device has one or more video inputs or outputs.</para>
 
     <para>Special rules apply to devices such as USB cameras where the notion of video
@@ -604,17 +514,10 @@
 <constant>VIDIOC_S_STD</constant>,
 <constant>VIDIOC_QUERYSTD</constant> and
 <constant>VIDIOC_ENUMSTD</constant> ioctls shall return the
-&ENOTTY;.<footnote>
-	<para>See <xref linkend="buffer" /> for a rationale.</para>
+&ENOTTY; or the &EINVAL;.</para>
 	<para>Applications can make use of the <xref linkend="input-capabilities" /> and
 <xref linkend="output-capabilities"/> flags to determine whether the video standard ioctls
-are available for the device.</para>
-
-	<para>See <xref linkend="buffer" /> for a rationale. Probably
-even USB cameras follow some well known video standard. It might have
-been better to explicitly indicate elsewhere if a device cannot live
-up to normal expectations, instead of this exception.</para>
-	    </footnote></para>
+can be used with the given input or output.</para>
 
     <example>
       <title>Information about the current video standard</title>
@@ -623,22 +526,22 @@
 &v4l2-std-id; std_id;
 &v4l2-standard; standard;
 
-if (-1 == ioctl (fd, &VIDIOC-G-STD;, &amp;std_id)) {
+if (-1 == ioctl(fd, &VIDIOC-G-STD;, &amp;std_id)) {
 	/* Note when VIDIOC_ENUMSTD always returns ENOTTY this
 	   is no video device or it falls under the USB exception,
 	   and VIDIOC_G_STD returning ENOTTY is no error. */
 
-	perror ("VIDIOC_G_STD");
-	exit (EXIT_FAILURE);
+	perror("VIDIOC_G_STD");
+	exit(EXIT_FAILURE);
 }
 
-memset (&amp;standard, 0, sizeof (standard));
+memset(&amp;standard, 0, sizeof(standard));
 standard.index = 0;
 
-while (0 == ioctl (fd, &VIDIOC-ENUMSTD;, &amp;standard)) {
+while (0 == ioctl(fd, &VIDIOC-ENUMSTD;, &amp;standard)) {
 	if (standard.id &amp; std_id) {
-	       printf ("Current video standard: %s\n", standard.name);
-	       exit (EXIT_SUCCESS);
+	       printf("Current video standard: %s\n", standard.name);
+	       exit(EXIT_SUCCESS);
 	}
 
 	standard.index++;
@@ -648,8 +551,8 @@
    empty unless this device falls under the USB exception. */
 
 if (errno == EINVAL || standard.index == 0) {
-	perror ("VIDIOC_ENUMSTD");
-	exit (EXIT_FAILURE);
+	perror("VIDIOC_ENUMSTD");
+	exit(EXIT_FAILURE);
 }
       </programlisting>
     </example>
@@ -662,26 +565,26 @@
 &v4l2-input; input;
 &v4l2-standard; standard;
 
-memset (&amp;input, 0, sizeof (input));
+memset(&amp;input, 0, sizeof(input));
 
-if (-1 == ioctl (fd, &VIDIOC-G-INPUT;, &amp;input.index)) {
-	perror ("VIDIOC_G_INPUT");
-	exit (EXIT_FAILURE);
+if (-1 == ioctl(fd, &VIDIOC-G-INPUT;, &amp;input.index)) {
+	perror("VIDIOC_G_INPUT");
+	exit(EXIT_FAILURE);
 }
 
-if (-1 == ioctl (fd, &VIDIOC-ENUMINPUT;, &amp;input)) {
-	perror ("VIDIOC_ENUM_INPUT");
-	exit (EXIT_FAILURE);
+if (-1 == ioctl(fd, &VIDIOC-ENUMINPUT;, &amp;input)) {
+	perror("VIDIOC_ENUM_INPUT");
+	exit(EXIT_FAILURE);
 }
 
-printf ("Current input %s supports:\n", input.name);
+printf("Current input %s supports:\n", input.name);
 
-memset (&amp;standard, 0, sizeof (standard));
+memset(&amp;standard, 0, sizeof(standard));
 standard.index = 0;
 
-while (0 == ioctl (fd, &VIDIOC-ENUMSTD;, &amp;standard)) {
+while (0 == ioctl(fd, &VIDIOC-ENUMSTD;, &amp;standard)) {
 	if (standard.id &amp; input.std)
-		printf ("%s\n", standard.name);
+		printf("%s\n", standard.name);
 
 	standard.index++;
 }
@@ -690,8 +593,8 @@
    empty unless this device falls under the USB exception. */
 
 if (errno != EINVAL || standard.index == 0) {
-	perror ("VIDIOC_ENUMSTD");
-	exit (EXIT_FAILURE);
+	perror("VIDIOC_ENUMSTD");
+	exit(EXIT_FAILURE);
 }
       </programlisting>
     </example>
@@ -703,21 +606,21 @@
 &v4l2-input; input;
 &v4l2-std-id; std_id;
 
-memset (&amp;input, 0, sizeof (input));
+memset(&amp;input, 0, sizeof(input));
 
-if (-1 == ioctl (fd, &VIDIOC-G-INPUT;, &amp;input.index)) {
-	perror ("VIDIOC_G_INPUT");
-	exit (EXIT_FAILURE);
+if (-1 == ioctl(fd, &VIDIOC-G-INPUT;, &amp;input.index)) {
+	perror("VIDIOC_G_INPUT");
+	exit(EXIT_FAILURE);
 }
 
-if (-1 == ioctl (fd, &VIDIOC-ENUMINPUT;, &amp;input)) {
-	perror ("VIDIOC_ENUM_INPUT");
-	exit (EXIT_FAILURE);
+if (-1 == ioctl(fd, &VIDIOC-ENUMINPUT;, &amp;input)) {
+	perror("VIDIOC_ENUM_INPUT");
+	exit(EXIT_FAILURE);
 }
 
 if (0 == (input.std &amp; V4L2_STD_PAL_BG)) {
-	fprintf (stderr, "Oops. B/G PAL is not supported.\n");
-	exit (EXIT_FAILURE);
+	fprintf(stderr, "Oops. B/G PAL is not supported.\n");
+	exit(EXIT_FAILURE);
 }
 
 /* Note this is also supposed to work when only B
@@ -725,9 +628,9 @@
 
 std_id = V4L2_STD_PAL_BG;
 
-if (-1 == ioctl (fd, &VIDIOC-S-STD;, &amp;std_id)) {
-	perror ("VIDIOC_S_STD");
-	exit (EXIT_FAILURE);
+if (-1 == ioctl(fd, &VIDIOC-S-STD;, &amp;std_id)) {
+	perror("VIDIOC_S_STD");
+	exit(EXIT_FAILURE);
 }
       </programlisting>
     </example>
@@ -740,26 +643,25 @@
 such as High Definition TV interfaces (HDMI), VGA, DVI connectors etc., that carry
 video signals and there is a need to extend the API to select the video timings
 for these interfaces. Since it is not possible to extend the &v4l2-std-id; due to
-the limited bits available, a new set of IOCTLs was added to set/get video timings at
-the input and output: </para><itemizedlist>
-	<listitem>
-	<para>DV Timings: This will allow applications to define detailed
-video timings for the interface. This includes parameters such as width, height,
-polarities, frontporch, backporch etc. The <filename>linux/v4l2-dv-timings.h</filename>
+the limited bits available, a new set of ioctls was added to set/get video timings at
+the input and output.</para>
+
+	<para>These ioctls deal with the detailed digital video timings that define
+each video format. This includes parameters such as the active video width and height,
+signal polarities, frontporches, backporches, sync widths etc. The <filename>linux/v4l2-dv-timings.h</filename>
 header can be used to get the timings of the formats in the <xref linkend="cea861" /> and
 <xref linkend="vesadmt" /> standards.
 	</para>
-	</listitem>
-	</itemizedlist>
-	<para>To enumerate and query the attributes of the DV timings supported by a device,
+
+	<para>To enumerate and query the attributes of the DV timings supported by a device
 	applications use the &VIDIOC-ENUM-DV-TIMINGS; and &VIDIOC-DV-TIMINGS-CAP; ioctls.
-	To set DV timings for the device, applications use the
+	To set DV timings for the device applications use the
 &VIDIOC-S-DV-TIMINGS; ioctl and to get current DV timings they use the
 &VIDIOC-G-DV-TIMINGS; ioctl. To detect the DV timings as seen by the video receiver applications
 use the &VIDIOC-QUERY-DV-TIMINGS; ioctl.</para>
 	<para>Applications can make use of the <xref linkend="input-capabilities" /> and
-<xref linkend="output-capabilities"/> flags to decide what ioctls are available to set the
-video timings for the device.</para>
+<xref linkend="output-capabilities"/> flags to determine whether the digital video ioctls
+can be used with the given input or output.</para>
   </section>
 
   &sub-controls;
diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml
index 86c6dd2..eee6f0f 100644
--- a/Documentation/DocBook/media/v4l/compat.xml
+++ b/Documentation/DocBook/media/v4l/compat.xml
@@ -2535,6 +2535,16 @@
       </orderedlist>
     </section>
 
+    <section>
+      <title>V4L2 in Linux 3.15</title>
+      <orderedlist>
+        <listitem>
+	  <para>Added Software Defined Radio (SDR) Interface.
+	  </para>
+        </listitem>
+      </orderedlist>
+    </section>
+
     <section id="other">
       <title>Relation of V4L2 to other Linux multimedia APIs</title>
 
@@ -2651,6 +2661,9 @@
         <listitem>
 	  <para>Exporting DMABUF files using &VIDIOC-EXPBUF; ioctl.</para>
         </listitem>
+        <listitem>
+	  <para>Software Defined Radio (SDR) Interface, <xref linkend="sdr" />.</para>
+        </listitem>
       </itemizedlist>
     </section>
 
diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index a5a3188..47198ee 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -2258,6 +2258,26 @@
 VBV buffer control.</entry>
 	      </row>
 
+		  <row><entry></entry></row>
+	      <row id="v4l2-mpeg-video-hor-search-range">
+		<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE</constant>&nbsp;</entry>
+		<entry>integer</entry>
+	      </row>
+		<row><entry spanname="descr">Horizontal search range defines maximum horizontal search area in pixels
+to search and match for the present Macroblock (MB) in the reference picture. This V4L2 control macro is used to set
+horizontal search range for motion estimation module in video encoder.</entry>
+	      </row>
+
+		 <row><entry></entry></row>
+	      <row id="v4l2-mpeg-video-vert-search-range">
+		<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE</constant>&nbsp;</entry>
+		<entry>integer</entry>
+	      </row>
+		<row><entry spanname="descr">Vertical search range defines maximum vertical search area in pixels
+to search and match for the present Macroblock (MB) in the reference picture. This V4L2 control macro is used to set
+vertical search range for motion estimation module in video encoder.</entry>
+	      </row>
+
 	      <row><entry></entry></row>
 	      <row>
 		<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE</constant>&nbsp;</entry>
@@ -4370,6 +4390,24 @@
     		  <entry>The flash controller has detected a short or open
     		  circuit condition on the indicator LED.</entry>
     		</row>
+		<row>
+		  <entry><constant>V4L2_FLASH_FAULT_UNDER_VOLTAGE</constant></entry>
+		  <entry>Flash controller voltage to the flash LED
+		  has been below the minimum limit specific to the flash
+		  controller.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_FLASH_FAULT_INPUT_VOLTAGE</constant></entry>
+		  <entry>The input voltage of the flash controller is below
+		  the limit under which strobing the flash at full current
+		  will not be possible.The condition persists until this flag
+		  is no longer set.</entry>
+		</row>
+		<row>
+		  <entry><constant>V4L2_FLASH_FAULT_LED_OVER_TEMPERATURE</constant></entry>
+		  <entry>The temperature of the LED has exceeded its
+		  allowed upper limit.</entry>
+		</row>
     	      </tbody>
     	    </entrytbl>
     	  </row>
@@ -4971,4 +5009,142 @@
       </table>
 
       </section>
+
+    <section id="rf-tuner-controls">
+      <title>RF Tuner Control Reference</title>
+
+      <para>
+The RF Tuner (RF_TUNER) class includes controls for common features of devices
+having RF tuner.
+      </para>
+      <para>
+In this context, RF tuner is radio receiver circuit between antenna and
+demodulator. It receives radio frequency (RF) from the antenna and converts that
+received signal to lower intermediate frequency (IF) or baseband frequency (BB).
+Tuners that could do baseband output are often called Zero-IF tuners. Older
+tuners were typically simple PLL tuners inside a metal box, whilst newer ones
+are highly integrated chips without a metal box "silicon tuners". These controls
+are mostly applicable for new feature rich silicon tuners, just because older
+tuners does not have much adjustable features.
+      </para>
+      <para>
+For more information about RF tuners see
+<ulink url="http://en.wikipedia.org/wiki/Tuner_%28radio%29">Tuner (radio)</ulink>
+and
+<ulink url="http://en.wikipedia.org/wiki/RF_front_end">RF front end</ulink>
+from Wikipedia.
+      </para>
+
+      <table pgwide="1" frame="none" id="rf-tuner-control-id">
+        <title>RF_TUNER 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_RF_TUNER_CLASS</constant>&nbsp;</entry>
+              <entry>class</entry>
+            </row><row><entry spanname="descr">The RF_TUNER class
+descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a
+description of this control class.</entry>
+            </row>
+            <row>
+              <entry spanname="id"><constant>V4L2_CID_RF_TUNER_BANDWIDTH_AUTO</constant>&nbsp;</entry>
+              <entry>boolean</entry>
+            </row>
+            <row>
+              <entry spanname="descr">Enables/disables tuner radio channel
+bandwidth configuration. In automatic mode bandwidth configuration is performed
+by the driver.</entry>
+            </row>
+            <row>
+              <entry spanname="id"><constant>V4L2_CID_RF_TUNER_BANDWIDTH</constant>&nbsp;</entry>
+              <entry>integer</entry>
+            </row>
+            <row>
+              <entry spanname="descr">Filter(s) on tuner signal path are used to
+filter signal according to receiving party needs. Driver configures filters to
+fulfill desired bandwidth requirement. Used when V4L2_CID_RF_TUNER_BANDWIDTH_AUTO is not
+set. Unit is in Hz. The range and step are driver-specific.</entry>
+            </row>
+            <row>
+              <entry spanname="id"><constant>V4L2_CID_RF_TUNER_LNA_GAIN_AUTO</constant>&nbsp;</entry>
+              <entry>boolean</entry>
+            </row>
+            <row>
+              <entry spanname="descr">Enables/disables LNA automatic gain control (AGC)</entry>
+            </row>
+            <row>
+              <entry spanname="id"><constant>V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO</constant>&nbsp;</entry>
+              <entry>boolean</entry>
+            </row>
+            <row>
+              <entry spanname="descr">Enables/disables mixer automatic gain control (AGC)</entry>
+            </row>
+            <row>
+              <entry spanname="id"><constant>V4L2_CID_RF_TUNER_IF_GAIN_AUTO</constant>&nbsp;</entry>
+              <entry>boolean</entry>
+            </row>
+            <row>
+              <entry spanname="descr">Enables/disables IF automatic gain control (AGC)</entry>
+            </row>
+            <row>
+              <entry spanname="id"><constant>V4L2_CID_RF_TUNER_LNA_GAIN</constant>&nbsp;</entry>
+              <entry>integer</entry>
+            </row>
+            <row>
+              <entry spanname="descr">LNA (low noise amplifier) gain is first
+gain stage on the RF tuner signal path. It is located very close to tuner
+antenna input. Used when <constant>V4L2_CID_RF_TUNER_LNA_GAIN_AUTO</constant> is not set.
+The range and step are driver-specific.</entry>
+            </row>
+            <row>
+              <entry spanname="id"><constant>V4L2_CID_RF_TUNER_MIXER_GAIN</constant>&nbsp;</entry>
+              <entry>integer</entry>
+            </row>
+            <row>
+              <entry spanname="descr">Mixer gain is second gain stage on the RF
+tuner signal path. It is located inside mixer block, where RF signal is
+down-converted by the mixer. Used when <constant>V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO</constant>
+is not set. The range and step are driver-specific.</entry>
+            </row>
+            <row>
+              <entry spanname="id"><constant>V4L2_CID_RF_TUNER_IF_GAIN</constant>&nbsp;</entry>
+              <entry>integer</entry>
+            </row>
+            <row>
+              <entry spanname="descr">IF gain is last gain stage on the RF tuner
+signal path. It is located on output of RF tuner. It controls signal level of
+intermediate frequency output or baseband output. Used when
+<constant>V4L2_CID_RF_TUNER_IF_GAIN_AUTO</constant> is not set. The range and step are
+driver-specific.</entry>
+            </row>
+            <row>
+              <entry spanname="id"><constant>V4L2_CID_RF_TUNER_PLL_LOCK</constant>&nbsp;</entry>
+              <entry>boolean</entry>
+            </row>
+            <row>
+              <entry spanname="descr">Is synthesizer PLL locked? RF tuner is
+receiving given frequency when that control is set. This is a read-only control.
+</entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </table>
+    </section>
 </section>
diff --git a/Documentation/DocBook/media/v4l/dev-osd.xml b/Documentation/DocBook/media/v4l/dev-osd.xml
index dd91d61..5485332 100644
--- a/Documentation/DocBook/media/v4l/dev-osd.xml
+++ b/Documentation/DocBook/media/v4l/dev-osd.xml
@@ -56,18 +56,18 @@
 unsigned int i;
 int fb_fd;
 
-if (-1 == ioctl (fd, VIDIOC_G_FBUF, &amp;fbuf)) {
-	perror ("VIDIOC_G_FBUF");
-	exit (EXIT_FAILURE);
+if (-1 == ioctl(fd, VIDIOC_G_FBUF, &amp;fbuf)) {
+	perror("VIDIOC_G_FBUF");
+	exit(EXIT_FAILURE);
 }
 
-for (i = 0; i &gt; 30; ++i) {
+for (i = 0; i &lt; 30; i++) {
 	char dev_name[16];
 	struct fb_fix_screeninfo si;
 
-	snprintf (dev_name, sizeof (dev_name), "/dev/fb%u", i);
+	snprintf(dev_name, sizeof(dev_name), "/dev/fb%u", i);
 
-	fb_fd = open (dev_name, O_RDWR);
+	fb_fd = open(dev_name, O_RDWR);
 	if (-1 == fb_fd) {
 		switch (errno) {
 		case ENOENT: /* no such file */
@@ -75,19 +75,19 @@
 			continue;
 
 		default:
-			perror ("open");
-			exit (EXIT_FAILURE);
+			perror("open");
+			exit(EXIT_FAILURE);
 		}
 	}
 
-	if (0 == ioctl (fb_fd, FBIOGET_FSCREENINFO, &amp;si)) {
-		if (si.smem_start == (unsigned long) fbuf.base)
+	if (0 == ioctl(fb_fd, FBIOGET_FSCREENINFO, &amp;si)) {
+		if (si.smem_start == (unsigned long)fbuf.base)
 			break;
 	} else {
 		/* Apparently not a framebuffer device. */
 	}
 
-	close (fb_fd);
+	close(fb_fd);
 	fb_fd = -1;
 }
 
diff --git a/Documentation/DocBook/media/v4l/dev-sdr.xml b/Documentation/DocBook/media/v4l/dev-sdr.xml
new file mode 100644
index 0000000..dc14804
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/dev-sdr.xml
@@ -0,0 +1,110 @@
+  <title>Software Defined Radio Interface (SDR)</title>
+
+  <note>
+    <title>Experimental</title>
+    <para>This is an <link linkend="experimental"> experimental </link>
+    interface and may change in the future.</para>
+  </note>
+
+  <para>
+SDR is an abbreviation of Software Defined Radio, the radio device
+which uses application software for modulation or demodulation. This interface
+is intended for controlling and data streaming of such devices.
+  </para>
+
+  <para>
+SDR devices are accessed through character device special files named
+<filename>/dev/swradio0</filename> to <filename>/dev/swradio255</filename>
+with major number 81 and dynamically allocated minor numbers 0 to 255.
+  </para>
+
+  <section>
+    <title>Querying Capabilities</title>
+
+    <para>
+Devices supporting the SDR receiver interface set the
+<constant>V4L2_CAP_SDR_CAPTURE</constant> and
+<constant>V4L2_CAP_TUNER</constant> flag in the
+<structfield>capabilities</structfield> field of &v4l2-capability;
+returned by the &VIDIOC-QUERYCAP; ioctl. That flag means the device has an
+Analog to Digital Converter (ADC), which is a mandatory element for the SDR receiver.
+At least one of the read/write, streaming or asynchronous I/O methods must
+be supported.
+    </para>
+  </section>
+
+  <section>
+    <title>Supplemental Functions</title>
+
+    <para>
+SDR devices can support <link linkend="control">controls</link>, and must
+support the <link linkend="tuner">tuner</link> ioctls. Tuner ioctls are used
+for setting the ADC sampling rate (sampling frequency) and the possible RF tuner
+frequency.
+    </para>
+
+    <para>
+The <constant>V4L2_TUNER_ADC</constant> tuner type is used for ADC tuners, and
+the <constant>V4L2_TUNER_RF</constant> tuner type is used for RF tuners. The
+tuner index of the RF tuner (if any) must always follow the ADC tuner index.
+Normally the ADC tuner is #0 and the RF tuner is #1.
+    </para>
+
+    <para>
+The &VIDIOC-S-HW-FREQ-SEEK; ioctl is not supported.
+    </para>
+  </section>
+
+  <section>
+    <title>Data Format Negotiation</title>
+
+    <para>
+The SDR capture device uses the <link linkend="format">format</link> ioctls to
+select the capture format. Both the sampling resolution and the data streaming
+format are bound to that selectable format. In addition to the basic
+<link linkend="format">format</link> ioctls, the &VIDIOC-ENUM-FMT; ioctl
+must be supported as well.
+    </para>
+
+    <para>
+To use the <link linkend="format">format</link> ioctls applications set the
+<structfield>type</structfield> field of a &v4l2-format; to
+<constant>V4L2_BUF_TYPE_SDR_CAPTURE</constant> and use the &v4l2-sdr-format;
+<structfield>sdr</structfield> member of the <structfield>fmt</structfield>
+union as needed per the desired operation.
+Currently only the <structfield>pixelformat</structfield> field of
+&v4l2-sdr-format; is used. The content of that field is the V4L2 fourcc code
+of the data format.
+    </para>
+
+    <table pgwide="1" frame="none" id="v4l2-sdr-format">
+      <title>struct <structname>v4l2_sdr_format</structname></title>
+      <tgroup cols="3">
+        &cs-str;
+        <tbody valign="top">
+          <row>
+            <entry>__u32</entry>
+            <entry><structfield>pixelformat</structfield></entry>
+            <entry>
+The data format or type of compression, set by the application. This is a
+little endian <link linkend="v4l2-fourcc">four character code</link>.
+V4L2 defines SDR formats in <xref linkend="sdr-formats" />.
+           </entry>
+          </row>
+          <row>
+            <entry>__u8</entry>
+            <entry><structfield>reserved[28]</structfield></entry>
+            <entry>This array is reserved for future extensions.
+Drivers and applications must set it to zero.</entry>
+          </row>
+        </tbody>
+      </tgroup>
+    </table>
+
+    <para>
+An SDR device may support <link linkend="rw">read/write</link>
+and/or streaming (<link linkend="mmap">memory mapping</link>
+or <link linkend="userp">user pointer</link>) I/O.
+    </para>
+
+  </section>
diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
index 2c4c068..97a69bf 100644
--- a/Documentation/DocBook/media/v4l/io.xml
+++ b/Documentation/DocBook/media/v4l/io.xml
@@ -339,8 +339,8 @@
 queues as a side effect. Since there is no notion of doing anything
 "now" on a multitasking system, if an application needs to synchronize
 with another event it should examine the &v4l2-buffer;
-<structfield>timestamp</structfield> of captured buffers, or set the
-field before enqueuing buffers for output.</para>
+<structfield>timestamp</structfield> of captured or outputted buffers.
+</para>
 
     <para>Drivers implementing memory mapping I/O must
 support the <constant>VIDIOC_REQBUFS</constant>,
@@ -457,7 +457,7 @@
 notion of doing anything "now" on a multitasking system, if an
 application needs to synchronize with another event it should examine
 the &v4l2-buffer; <structfield>timestamp</structfield> of captured
-buffers, or set the field before enqueuing buffers for output.</para>
+or outputted buffers.</para>
 
     <para>Drivers implementing user pointer I/O must
 support the <constant>VIDIOC_REQBUFS</constant>,
@@ -620,8 +620,7 @@
 unlocks all buffers as a side effect. Since there is no notion of doing
 anything "now" on a multitasking system, if an application needs to synchronize
 with another event it should examine the &v4l2-buffer;
-<structfield>timestamp</structfield> of captured buffers, or set the field
-before enqueuing buffers for output.</para>
+<structfield>timestamp</structfield> of captured or outputted buffers.</para>
 
     <para>Drivers implementing DMABUF importing I/O must support the
 <constant>VIDIOC_REQBUFS</constant>, <constant>VIDIOC_QBUF</constant>,
@@ -654,38 +653,19 @@
 In that case, struct <structname>v4l2_buffer</structname> contains an array of
 plane structures.</para>
 
-      <para>Nominally timestamps refer to the first data byte transmitted.
-In practice however the wide range of hardware covered by the V4L2 API
-limits timestamp accuracy. Often an interrupt routine will
-sample the system clock shortly after the field or frame was stored
-completely in memory. So applications must expect a constant
-difference up to one field or frame period plus a small (few scan
-lines) random error. The delay and error can be much
-larger due to compression or transmission over an external bus when
-the frames are not properly stamped by the sender. This is frequently
-the case with USB cameras. Here timestamps refer to the instant the
-field or frame was received by the driver, not the capture time. These
-devices identify by not enumerating any video standards, see <xref
-linkend="standard" />.</para>
-
-      <para>Similar limitations apply to output timestamps. Typically
-the video hardware locks to a clock controlling the video timing, the
-horizontal and vertical synchronization pulses. At some point in the
-line sequence, possibly the vertical blanking, an interrupt routine
-samples the system clock, compares against the timestamp and programs
-the hardware to repeat the previous field or frame, or to display the
-buffer contents.</para>
-
-      <para>Apart of limitations of the video device and natural
-inaccuracies of all clocks, it should be noted system time itself is
-not perfectly stable. It can be affected by power saving cycles,
-warped to insert leap seconds, or even turned back or forth by the
-system administrator affecting long term measurements. <footnote>
-	  <para>Since no other Linux multimedia
-API supports unadjusted time it would be foolish to introduce here. We
-must use a universally supported clock to synchronize different media,
-hence time of day.</para>
-	</footnote></para>
+    <para>Dequeued video buffers come with timestamps. The driver
+    decides at which part of the frame and with which clock the
+    timestamp is taken. Please see flags in the masks
+    <constant>V4L2_BUF_FLAG_TIMESTAMP_MASK</constant> and
+    <constant>V4L2_BUF_FLAG_TSTAMP_SRC_MASK</constant> in <xref
+    linkend="buffer-flags" />. These flags are always valid and constant
+    across all buffers during the whole video stream. Changes in these
+    flags may take place as a side effect of &VIDIOC-S-INPUT; or
+    &VIDIOC-S-OUTPUT; however. The
+    <constant>V4L2_BUF_FLAG_TIMESTAMP_COPY</constant> timestamp type
+    which is used by e.g. on mem-to-mem devices is an exception to the
+    rule: the timestamp source flags are copied from the OUTPUT video
+    buffer to the CAPTURE video buffer.</para>
 
     <table frame="none" pgwide="1" id="v4l2-buffer">
       <title>struct <structname>v4l2_buffer</structname></title>
@@ -696,10 +676,11 @@
 	    <entry>__u32</entry>
 	    <entry><structfield>index</structfield></entry>
 	    <entry></entry>
-	    <entry>Number of the buffer, set by the application. This
-field is only used for <link linkend="mmap">memory mapping</link> I/O
-and can range from zero to the number of buffers allocated
-with the &VIDIOC-REQBUFS; ioctl (&v4l2-requestbuffers; <structfield>count</structfield>) minus one.</entry>
+	    <entry>Number of the buffer, set by the application except
+when calling &VIDIOC-DQBUF;, then it is set by the driver.
+This field can range from zero to the number of buffers allocated
+with the &VIDIOC-REQBUFS; ioctl (&v4l2-requestbuffers; <structfield>count</structfield>),
+plus any buffers allocated with &VIDIOC-CREATE-BUFS; minus one.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
@@ -718,7 +699,7 @@
 buffer. It depends on the negotiated data format and may change with
 each buffer for compressed variable size data like JPEG images.
 Drivers must set this field when <structfield>type</structfield>
-refers to an input stream, applications when an output stream.</entry>
+refers to an input stream, applications when it refers to an output stream.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
@@ -735,7 +716,7 @@
 buffer, see <xref linkend="v4l2-field" />. This field is not used when
 the buffer contains VBI data. Drivers must set it when
 <structfield>type</structfield> refers to an input stream,
-applications when an output stream.</entry>
+applications when it refers to an output stream.</entry>
 	  </row>
 	  <row>
 	    <entry>struct timeval</entry>
@@ -745,15 +726,13 @@
 	    byte was captured, as returned by the
 	    <function>clock_gettime()</function> function for the relevant
 	    clock id; see <constant>V4L2_BUF_FLAG_TIMESTAMP_*</constant> in
-	    <xref linkend="buffer-flags" />. For output streams the data
-	    will not be displayed before this time, secondary to the nominal
-	    frame rate determined by the current video standard in enqueued
-	    order. Applications can for example zero this field to display
-	    frames as soon as possible. The driver stores the time at which
-	    the first data byte was actually sent out in the
-	    <structfield>timestamp</structfield> field. This permits
+	    <xref linkend="buffer-flags" />. For output streams the driver
+	    stores the time at which the last data byte was actually sent out
+	    in the  <structfield>timestamp</structfield> field. This permits
 	    applications to monitor the drift between the video and system
-	    clock.</para></entry>
+	    clock. For output streams that use <constant>V4L2_BUF_FLAG_TIMESTAMP_COPY</constant>
+	    the application has to fill in the timestamp which will be copied
+	    by the driver to the capture stream.</para></entry>
 	  </row>
 	  <row>
 	    <entry>&v4l2-timecode;</entry>
@@ -846,7 +825,8 @@
 	    <entry><structfield>length</structfield></entry>
 	    <entry></entry>
 	    <entry>Size of the buffer (not the payload) in bytes for the
-	    single-planar API. For the multi-planar API the application sets
+	    single-planar API. This is set by the driver based on the calls to
+	    &VIDIOC-REQBUFS; and/or &VIDIOC-CREATE-BUFS;. For the multi-planar API the application sets
 	    this to the number of elements in the <structfield>planes</structfield>
 	    array. The driver will fill in the actual number of valid elements in
 	    that array.
@@ -880,13 +860,15 @@
 	    <entry><structfield>bytesused</structfield></entry>
 	    <entry></entry>
 	    <entry>The number of bytes occupied by data in the plane
-	    (its payload).</entry>
+	      (its payload). Drivers must set this field when <structfield>type</structfield>
+	      refers to an input stream, applications when it refers to an output stream.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
 	    <entry><structfield>length</structfield></entry>
 	    <entry></entry>
-	    <entry>Size in bytes of the plane (not its payload).</entry>
+	    <entry>Size in bytes of the plane (not its payload). This is set by the driver
+	    based on the calls to &VIDIOC-REQBUFS; and/or &VIDIOC-CREATE-BUFS;.</entry>
 	  </row>
 	  <row>
 	    <entry>union</entry>
@@ -925,7 +907,9 @@
 	    <entry>__u32</entry>
 	    <entry><structfield>data_offset</structfield></entry>
 	    <entry></entry>
-	    <entry>Offset in bytes to video data in the plane, if applicable.
+	    <entry>Offset in bytes to video data in the plane.
+	      Drivers must set this field when <structfield>type</structfield>
+	      refers to an input stream, applications when it refers to an output stream.
 	    </entry>
 	  </row>
 	  <row>
@@ -1005,6 +989,12 @@
 	    <entry>Buffer for video output overlay (OSD), see <xref
 		linkend="osd" />.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_TYPE_SDR_CAPTURE</constant></entry>
+	    <entry>11</entry>
+	    <entry>Buffer for Software Defined Radio (SDR), see <xref
+		linkend="sdr" />.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
@@ -1016,7 +1006,7 @@
 	<tbody valign="top">
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_MAPPED</constant></entry>
-	    <entry>0x0001</entry>
+	    <entry>0x00000001</entry>
 	    <entry>The buffer resides in device memory and has been mapped
 into the application's address space, see <xref linkend="mmap" /> for details.
 Drivers set or clear this flag when the
@@ -1026,7 +1016,7 @@
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_QUEUED</constant></entry>
-	    <entry>0x0002</entry>
+	    <entry>0x00000002</entry>
 	  <entry>Internally drivers maintain two buffer queues, an
 incoming and outgoing queue. When this flag is set, the buffer is
 currently on the incoming queue. It automatically moves to the
@@ -1039,7 +1029,7 @@
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_DONE</constant></entry>
-	    <entry>0x0004</entry>
+	    <entry>0x00000004</entry>
 	    <entry>When this flag is set, the buffer is currently on
 the outgoing queue, ready to be dequeued from the driver. Drivers set
 or clear this flag when the <constant>VIDIOC_QUERYBUF</constant> ioctl
@@ -1049,11 +1039,11 @@
 <constant>V4L2_BUF_FLAG_QUEUED</constant> and
 <constant>V4L2_BUF_FLAG_DONE</constant> flag are mutually exclusive.
 They can be both cleared however, then the buffer is in "dequeued"
-state, in the application domain to say so.</entry>
+state, in the application domain so to say.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_ERROR</constant></entry>
-	    <entry>0x0040</entry>
+	    <entry>0x00000040</entry>
 	    <entry>When this flag is set, the buffer has been dequeued
 	    successfully, although the data might have been corrupted.
 	    This is recoverable, streaming may continue as normal and
@@ -1063,35 +1053,43 @@
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_KEYFRAME</constant></entry>
-	    <entry>0x0008</entry>
+	    <entry>0x00000008</entry>
 	  <entry>Drivers set or clear this flag when calling the
 <constant>VIDIOC_DQBUF</constant> ioctl. It may be set by video
 capture devices when the buffer contains a compressed image which is a
-key frame (or field), &ie; can be decompressed on its own.</entry>
+key frame (or field), &ie; can be decompressed on its own. Also know as
+an I-frame.  Applications can set this bit when <structfield>type</structfield>
+refers to an output stream.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_PFRAME</constant></entry>
-	    <entry>0x0010</entry>
+	    <entry>0x00000010</entry>
 	    <entry>Similar to <constant>V4L2_BUF_FLAG_KEYFRAME</constant>
 this flags predicted frames or fields which contain only differences to a
-previous key frame.</entry>
+previous key frame. Applications can set this bit when <structfield>type</structfield>
+refers to an output stream.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_BFRAME</constant></entry>
-	    <entry>0x0020</entry>
-	    <entry>Similar to <constant>V4L2_BUF_FLAG_PFRAME</constant>
-	this is a bidirectional predicted frame or field. [ooc tbd]</entry>
+	    <entry>0x00000020</entry>
+	    <entry>Similar to <constant>V4L2_BUF_FLAG_KEYFRAME</constant>
+this flags a bi-directional predicted frame or field which contains only
+the differences between the current frame and both the preceding and following
+key frames to specify its content. Applications can set this bit when
+<structfield>type</structfield> refers to an output stream.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_TIMECODE</constant></entry>
-	    <entry>0x0100</entry>
+	    <entry>0x00000100</entry>
 	    <entry>The <structfield>timecode</structfield> field is valid.
 Drivers set or clear this flag when the <constant>VIDIOC_DQBUF</constant>
-ioctl is called.</entry>
+ioctl is called.  Applications can set this bit and the corresponding
+<structfield>timecode</structfield> structure when <structfield>type</structfield>
+refers to an output stream.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_PREPARED</constant></entry>
-	    <entry>0x0400</entry>
+	    <entry>0x00000400</entry>
 	    <entry>The buffer has been prepared for I/O and can be queued by the
 application. Drivers set or clear this flag when the
 <link linkend="vidioc-querybuf">VIDIOC_QUERYBUF</link>, <link
@@ -1101,7 +1099,7 @@
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant></entry>
-	    <entry>0x0800</entry>
+	    <entry>0x00000800</entry>
 	    <entry>Caches do not have to be invalidated for this buffer.
 Typically applications shall use this flag if the data captured in the buffer
 is not going to be touched by the CPU, instead the buffer will, probably, be
@@ -1110,7 +1108,7 @@
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant></entry>
-	    <entry>0x1000</entry>
+	    <entry>0x00001000</entry>
 	    <entry>Caches do not have to be cleaned for this buffer.
 Typically applications shall use this flag for output buffers if the data
 in this buffer has not been created by the CPU but by some DMA-capable unit,
@@ -1118,7 +1116,7 @@
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_TIMESTAMP_MASK</constant></entry>
-	    <entry>0xe000</entry>
+	    <entry>0x0000e000</entry>
 	    <entry>Mask for timestamp types below. To test the
 	    timestamp type, mask out bits not belonging to timestamp
 	    type by performing a logical and operation with buffer
@@ -1126,7 +1124,7 @@
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN</constant></entry>
-	    <entry>0x0000</entry>
+	    <entry>0x00000000</entry>
 	    <entry>Unknown timestamp type. This type is used by
 	    drivers before Linux 3.9 and may be either monotonic (see
 	    below) or realtime (wall clock). Monotonic clock has been
@@ -1139,7 +1137,7 @@
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC</constant></entry>
-	    <entry>0x2000</entry>
+	    <entry>0x00002000</entry>
 	    <entry>The buffer timestamp has been taken from the
 	    <constant>CLOCK_MONOTONIC</constant> clock. To access the
 	    same clock outside V4L2, use
@@ -1147,10 +1145,42 @@
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_FLAG_TIMESTAMP_COPY</constant></entry>
-	    <entry>0x4000</entry>
+	    <entry>0x00004000</entry>
 	    <entry>The CAPTURE buffer timestamp has been taken from the
 	    corresponding OUTPUT buffer. This flag applies only to mem2mem devices.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_FLAG_TSTAMP_SRC_MASK</constant></entry>
+	    <entry>0x00070000</entry>
+	    <entry>Mask for timestamp sources below. The timestamp source
+	    defines the point of time the timestamp is taken in relation to
+	    the frame. Logical 'and' operation between the
+	    <structfield>flags</structfield> field and
+	    <constant>V4L2_BUF_FLAG_TSTAMP_SRC_MASK</constant> produces the
+	    value of the timestamp source. Applications must set the timestamp
+	    source when <structfield>type</structfield> refers to an output stream
+	    and <constant>V4L2_BUF_FLAG_TIMESTAMP_COPY</constant> is set.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_FLAG_TSTAMP_SRC_EOF</constant></entry>
+	    <entry>0x00000000</entry>
+	    <entry>End Of Frame. The buffer timestamp has been taken
+	    when the last pixel of the frame has been received or the
+	    last pixel of the frame has been transmitted. In practice,
+	    software generated timestamps will typically be read from
+	    the clock a small amount of time after the last pixel has
+	    been received or transmitten, depending on the system and
+	    other activity in it.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_FLAG_TSTAMP_SRC_SOE</constant></entry>
+	    <entry>0x00010000</entry>
+	    <entry>Start Of Exposure. The buffer timestamp has been
+	    taken when the exposure of the frame has begun. This is
+	    only valid for the
+	    <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> buffer
+	    type.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
@@ -1440,10 +1470,9 @@
 <constant>V4L2_FIELD_BOTTOM</constant>. Any two successive fields pair
 to build a frame. If fields are successive, without any dropped fields
 between them (fields can drop individually), can be determined from
-the &v4l2-buffer; <structfield>sequence</structfield> field. Image
-sizes refer to the frame, not fields. This format cannot be selected
-when using the read/write I/O method.<!-- Where it's indistinguishable
-from V4L2_FIELD_SEQ_*. --></entry>
+the &v4l2-buffer; <structfield>sequence</structfield> field. This format
+cannot be selected when using the read/write I/O method since there
+is no way to communicate if a field was a top or bottom field.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_FIELD_INTERLACED_TB</constant></entry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-nv16m.xml b/Documentation/DocBook/media/v4l/pixfmt-nv16m.xml
index c51d5a4..fb2b5e3 100644
--- a/Documentation/DocBook/media/v4l/pixfmt-nv16m.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt-nv16m.xml
@@ -12,18 +12,17 @@
       <refsect1>
 	<title>Description</title>
 
-	<para>This is a multi-planar, two-plane version of the YUV 4:2:0 format.
+	<para>This is a multi-planar, two-plane version of the YUV 4:2:2 format.
 The three components are separated into two sub-images or planes.
 <constant>V4L2_PIX_FMT_NV16M</constant> differs from <constant>V4L2_PIX_FMT_NV16
 </constant> in that the two planes are non-contiguous in memory, i.e. the chroma
-plane does not necessarily immediately follows the luma plane.
+plane does not necessarily immediately follow the luma plane.
 The luminance data occupies the first plane. The Y plane has one byte per pixel.
 In the second plane there is chrominance data with alternating chroma samples.
 The CbCr plane is the same width and height, in bytes, as the Y plane.
-Each CbCr pair belongs to four pixels. For example,
+Each CbCr pair belongs to two pixels. For example,
 Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to
-Y'<subscript>00</subscript>, Y'<subscript>01</subscript>,
-Y'<subscript>10</subscript>, Y'<subscript>11</subscript>.
+Y'<subscript>00</subscript>, Y'<subscript>01</subscript>.
 <constant>V4L2_PIX_FMT_NV61M</constant> is the same as <constant>V4L2_PIX_FMT_NV16M</constant>
 except the Cb and Cr bytes are swapped, the CrCb plane starts with a Cr byte.</para>
 
diff --git a/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml b/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
index 166c8d6..e1c4f8b 100644
--- a/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
@@ -121,14 +121,14 @@
 	    <entry><constant>V4L2_PIX_FMT_RGB332</constant></entry>
 	    <entry>'RGB1'</entry>
 	    <entry></entry>
-	    <entry>b<subscript>1</subscript></entry>
-	    <entry>b<subscript>0</subscript></entry>
-	    <entry>g<subscript>2</subscript></entry>
-	    <entry>g<subscript>1</subscript></entry>
-	    <entry>g<subscript>0</subscript></entry>
 	    <entry>r<subscript>2</subscript></entry>
 	    <entry>r<subscript>1</subscript></entry>
 	    <entry>r<subscript>0</subscript></entry>
+	    <entry>g<subscript>2</subscript></entry>
+	    <entry>g<subscript>1</subscript></entry>
+	    <entry>g<subscript>0</subscript></entry>
+	    <entry>b<subscript>1</subscript></entry>
+	    <entry>b<subscript>0</subscript></entry>
 	  </row>
 	  <row id="V4L2-PIX-FMT-RGB444">
 	    <entry><constant>V4L2_PIX_FMT_RGB444</constant></entry>
@@ -159,18 +159,18 @@
 	    <entry>g<subscript>2</subscript></entry>
 	    <entry>g<subscript>1</subscript></entry>
 	    <entry>g<subscript>0</subscript></entry>
-	    <entry>r<subscript>4</subscript></entry>
-	    <entry>r<subscript>3</subscript></entry>
-	    <entry>r<subscript>2</subscript></entry>
-	    <entry>r<subscript>1</subscript></entry>
-	    <entry>r<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry>a</entry>
 	    <entry>b<subscript>4</subscript></entry>
 	    <entry>b<subscript>3</subscript></entry>
 	    <entry>b<subscript>2</subscript></entry>
 	    <entry>b<subscript>1</subscript></entry>
 	    <entry>b<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>a</entry>
+	    <entry>r<subscript>4</subscript></entry>
+	    <entry>r<subscript>3</subscript></entry>
+	    <entry>r<subscript>2</subscript></entry>
+	    <entry>r<subscript>1</subscript></entry>
+	    <entry>r<subscript>0</subscript></entry>
 	    <entry>g<subscript>4</subscript></entry>
 	    <entry>g<subscript>3</subscript></entry>
 	  </row>
@@ -181,17 +181,17 @@
 	    <entry>g<subscript>2</subscript></entry>
 	    <entry>g<subscript>1</subscript></entry>
 	    <entry>g<subscript>0</subscript></entry>
-	    <entry>r<subscript>4</subscript></entry>
-	    <entry>r<subscript>3</subscript></entry>
-	    <entry>r<subscript>2</subscript></entry>
-	    <entry>r<subscript>1</subscript></entry>
-	    <entry>r<subscript>0</subscript></entry>
-	    <entry></entry>
 	    <entry>b<subscript>4</subscript></entry>
 	    <entry>b<subscript>3</subscript></entry>
 	    <entry>b<subscript>2</subscript></entry>
 	    <entry>b<subscript>1</subscript></entry>
 	    <entry>b<subscript>0</subscript></entry>
+	    <entry></entry>
+	    <entry>r<subscript>4</subscript></entry>
+	    <entry>r<subscript>3</subscript></entry>
+	    <entry>r<subscript>2</subscript></entry>
+	    <entry>r<subscript>1</subscript></entry>
+	    <entry>r<subscript>0</subscript></entry>
 	    <entry>g<subscript>5</subscript></entry>
 	    <entry>g<subscript>4</subscript></entry>
 	    <entry>g<subscript>3</subscript></entry>
@@ -201,32 +201,32 @@
 	    <entry>'RGBQ'</entry>
 	    <entry></entry>
 	    <entry>a</entry>
-	    <entry>b<subscript>4</subscript></entry>
-	    <entry>b<subscript>3</subscript></entry>
-	    <entry>b<subscript>2</subscript></entry>
-	    <entry>b<subscript>1</subscript></entry>
-	    <entry>b<subscript>0</subscript></entry>
+	    <entry>r<subscript>4</subscript></entry>
+	    <entry>r<subscript>3</subscript></entry>
+	    <entry>r<subscript>2</subscript></entry>
+	    <entry>r<subscript>1</subscript></entry>
+	    <entry>r<subscript>0</subscript></entry>
 	    <entry>g<subscript>4</subscript></entry>
 	    <entry>g<subscript>3</subscript></entry>
 	    <entry></entry>
 	    <entry>g<subscript>2</subscript></entry>
 	    <entry>g<subscript>1</subscript></entry>
 	    <entry>g<subscript>0</subscript></entry>
-	    <entry>r<subscript>4</subscript></entry>
-	    <entry>r<subscript>3</subscript></entry>
-	    <entry>r<subscript>2</subscript></entry>
-	    <entry>r<subscript>1</subscript></entry>
-	    <entry>r<subscript>0</subscript></entry>
-	  </row>
-	  <row id="V4L2-PIX-FMT-RGB565X">
-	    <entry><constant>V4L2_PIX_FMT_RGB565X</constant></entry>
-	    <entry>'RGBR'</entry>
-	    <entry></entry>
 	    <entry>b<subscript>4</subscript></entry>
 	    <entry>b<subscript>3</subscript></entry>
 	    <entry>b<subscript>2</subscript></entry>
 	    <entry>b<subscript>1</subscript></entry>
 	    <entry>b<subscript>0</subscript></entry>
+	  </row>
+	  <row id="V4L2-PIX-FMT-RGB565X">
+	    <entry><constant>V4L2_PIX_FMT_RGB565X</constant></entry>
+	    <entry>'RGBR'</entry>
+	    <entry></entry>
+	    <entry>r<subscript>4</subscript></entry>
+	    <entry>r<subscript>3</subscript></entry>
+	    <entry>r<subscript>2</subscript></entry>
+	    <entry>r<subscript>1</subscript></entry>
+	    <entry>r<subscript>0</subscript></entry>
 	    <entry>g<subscript>5</subscript></entry>
 	    <entry>g<subscript>4</subscript></entry>
 	    <entry>g<subscript>3</subscript></entry>
@@ -234,11 +234,11 @@
 	    <entry>g<subscript>2</subscript></entry>
 	    <entry>g<subscript>1</subscript></entry>
 	    <entry>g<subscript>0</subscript></entry>
-	    <entry>r<subscript>4</subscript></entry>
-	    <entry>r<subscript>3</subscript></entry>
-	    <entry>r<subscript>2</subscript></entry>
-	    <entry>r<subscript>1</subscript></entry>
-	    <entry>r<subscript>0</subscript></entry>
+	    <entry>b<subscript>4</subscript></entry>
+	    <entry>b<subscript>3</subscript></entry>
+	    <entry>b<subscript>2</subscript></entry>
+	    <entry>b<subscript>1</subscript></entry>
+	    <entry>b<subscript>0</subscript></entry>
 	  </row>
 	  <row id="V4L2-PIX-FMT-BGR666">
 	    <entry><constant>V4L2_PIX_FMT_BGR666</constant></entry>
@@ -385,6 +385,15 @@
 	    <entry><constant>V4L2_PIX_FMT_RGB32</constant></entry>
 	    <entry>'RGB4'</entry>
 	    <entry></entry>
+	    <entry>a<subscript>7</subscript></entry>
+	    <entry>a<subscript>6</subscript></entry>
+	    <entry>a<subscript>5</subscript></entry>
+	    <entry>a<subscript>4</subscript></entry>
+	    <entry>a<subscript>3</subscript></entry>
+	    <entry>a<subscript>2</subscript></entry>
+	    <entry>a<subscript>1</subscript></entry>
+	    <entry>a<subscript>0</subscript></entry>
+	    <entry></entry>
 	    <entry>r<subscript>7</subscript></entry>
 	    <entry>r<subscript>6</subscript></entry>
 	    <entry>r<subscript>5</subscript></entry>
@@ -411,25 +420,16 @@
 	    <entry>b<subscript>2</subscript></entry>
 	    <entry>b<subscript>1</subscript></entry>
 	    <entry>b<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry>a<subscript>7</subscript></entry>
-	    <entry>a<subscript>6</subscript></entry>
-	    <entry>a<subscript>5</subscript></entry>
-	    <entry>a<subscript>4</subscript></entry>
-	    <entry>a<subscript>3</subscript></entry>
-	    <entry>a<subscript>2</subscript></entry>
-	    <entry>a<subscript>1</subscript></entry>
-	    <entry>a<subscript>0</subscript></entry>
 	  </row>
 	</tbody>
       </tgroup>
     </table>
 
-    <para>Bit 7 is the most significant bit. The value of a = alpha
+    <para>Bit 7 is the most significant bit. The value of the a = alpha
 bits is undefined when reading from the driver, ignored when writing
 to the driver, except when alpha blending has been negotiated for a
 <link linkend="overlay">Video Overlay</link> or <link linkend="osd">
-Video Output Overlay</link> or when alpha component has been configured
+Video Output Overlay</link> or when the alpha component has been configured
 for a <link linkend="capture">Video Capture</link> by means of <link
 linkend="v4l2-alpha-component"> <constant>V4L2_CID_ALPHA_COMPONENT
 </constant> </link> control.</para>
@@ -512,421 +512,6 @@
       </formalpara>
     </example>
 
-    <important>
-      <para>Drivers may interpret these formats differently.</para>
-    </important>
-
-    <para>Some RGB formats above are uncommon and were probably
-defined in error. Drivers may interpret them as in <xref
-	linkend="rgb-formats-corrected" />.</para>
-
-    <table pgwide="1" frame="none" id="rgb-formats-corrected">
-      <title>Packed RGB Image Formats (corrected)</title>
-      <tgroup cols="37" align="center">
-	<colspec colname="id" align="left" />
-	<colspec colname="fourcc" />
-	<colspec colname="bit" />
-
-	<colspec colnum="4" colname="b07" align="center" />
-	<colspec colnum="5" colname="b06" align="center" />
-	<colspec colnum="6" colname="b05" align="center" />
-	<colspec colnum="7" colname="b04" align="center" />
-	<colspec colnum="8" colname="b03" align="center" />
-	<colspec colnum="9" colname="b02" align="center" />
-	<colspec colnum="10" colname="b01" align="center" />
-	<colspec colnum="11" colname="b00" align="center" />
-
-	<colspec colnum="13" colname="b17" align="center" />
-	<colspec colnum="14" colname="b16" align="center" />
-	<colspec colnum="15" colname="b15" align="center" />
-	<colspec colnum="16" colname="b14" align="center" />
-	<colspec colnum="17" colname="b13" align="center" />
-	<colspec colnum="18" colname="b12" align="center" />
-	<colspec colnum="19" colname="b11" align="center" />
-	<colspec colnum="20" colname="b10" align="center" />
-
-	<colspec colnum="22" colname="b27" align="center" />
-	<colspec colnum="23" colname="b26" align="center" />
-	<colspec colnum="24" colname="b25" align="center" />
-	<colspec colnum="25" colname="b24" align="center" />
-	<colspec colnum="26" colname="b23" align="center" />
-	<colspec colnum="27" colname="b22" align="center" />
-	<colspec colnum="28" colname="b21" align="center" />
-	<colspec colnum="29" colname="b20" align="center" />
-
-	<colspec colnum="31" colname="b37" align="center" />
-	<colspec colnum="32" colname="b36" align="center" />
-	<colspec colnum="33" colname="b35" align="center" />
-	<colspec colnum="34" colname="b34" align="center" />
-	<colspec colnum="35" colname="b33" align="center" />
-	<colspec colnum="36" colname="b32" align="center" />
-	<colspec colnum="37" colname="b31" align="center" />
-	<colspec colnum="38" colname="b30" align="center" />
-
-	<spanspec namest="b07" nameend="b00" spanname="b0" />
-	<spanspec namest="b17" nameend="b10" spanname="b1" />
-	<spanspec namest="b27" nameend="b20" spanname="b2" />
-	<spanspec namest="b37" nameend="b30" spanname="b3" />
-	<thead>
-	  <row>
-	    <entry>Identifier</entry>
-	    <entry>Code</entry>
-	    <entry>&nbsp;</entry>
-	    <entry spanname="b0">Byte&nbsp;0 in memory</entry>
-	    <entry spanname="b1">Byte&nbsp;1</entry>
-	    <entry spanname="b2">Byte&nbsp;2</entry>
-	    <entry spanname="b3">Byte&nbsp;3</entry>
-	  </row>
-	  <row>
-	    <entry>&nbsp;</entry>
-	    <entry>&nbsp;</entry>
-	    <entry>Bit</entry>
-	    <entry>7</entry>
-	    <entry>6</entry>
-	    <entry>5</entry>
-	    <entry>4</entry>
-	    <entry>3</entry>
-	    <entry>2</entry>
-	    <entry>1</entry>
-	    <entry>0</entry>
-	    <entry>&nbsp;</entry>
-	    <entry>7</entry>
-	    <entry>6</entry>
-	    <entry>5</entry>
-	    <entry>4</entry>
-	    <entry>3</entry>
-	    <entry>2</entry>
-	    <entry>1</entry>
-	    <entry>0</entry>
-	    <entry>&nbsp;</entry>
-	    <entry>7</entry>
-	    <entry>6</entry>
-	    <entry>5</entry>
-	    <entry>4</entry>
-	    <entry>3</entry>
-	    <entry>2</entry>
-	    <entry>1</entry>
-	    <entry>0</entry>
-	    <entry>&nbsp;</entry>
-	    <entry>7</entry>
-	    <entry>6</entry>
-	    <entry>5</entry>
-	    <entry>4</entry>
-	    <entry>3</entry>
-	    <entry>2</entry>
-	    <entry>1</entry>
-	    <entry>0</entry>
-	  </row>
-	</thead>
-	<tbody valign="top">
-	  <row><!-- id="V4L2-PIX-FMT-RGB332" -->
-	    <entry><constant>V4L2_PIX_FMT_RGB332</constant></entry>
-	    <entry>'RGB1'</entry>
-	    <entry></entry>
-	    <entry>r<subscript>2</subscript></entry>
-	    <entry>r<subscript>1</subscript></entry>
-	    <entry>r<subscript>0</subscript></entry>
-	    <entry>g<subscript>2</subscript></entry>
-	    <entry>g<subscript>1</subscript></entry>
-	    <entry>g<subscript>0</subscript></entry>
-	    <entry>b<subscript>1</subscript></entry>
-	    <entry>b<subscript>0</subscript></entry>
-	  </row>
-	  <row><!-- id="V4L2-PIX-FMT-RGB444" -->
-	    <entry><constant>V4L2_PIX_FMT_RGB444</constant></entry>
-	    <entry>'R444'</entry>
-	    <entry></entry>
-	    <entry>g<subscript>3</subscript></entry>
-	    <entry>g<subscript>2</subscript></entry>
-	    <entry>g<subscript>1</subscript></entry>
-	    <entry>g<subscript>0</subscript></entry>
-	    <entry>b<subscript>3</subscript></entry>
-	    <entry>b<subscript>2</subscript></entry>
-	    <entry>b<subscript>1</subscript></entry>
-	    <entry>b<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry>a<subscript>3</subscript></entry>
-	    <entry>a<subscript>2</subscript></entry>
-	    <entry>a<subscript>1</subscript></entry>
-	    <entry>a<subscript>0</subscript></entry>
-	    <entry>r<subscript>3</subscript></entry>
-	    <entry>r<subscript>2</subscript></entry>
-	    <entry>r<subscript>1</subscript></entry>
-	    <entry>r<subscript>0</subscript></entry>
-	  </row>
-	  <row><!-- id="V4L2-PIX-FMT-RGB555" -->
-	    <entry><constant>V4L2_PIX_FMT_RGB555</constant></entry>
-	    <entry>'RGBO'</entry>
-	    <entry></entry>
-	    <entry>g<subscript>2</subscript></entry>
-	    <entry>g<subscript>1</subscript></entry>
-	    <entry>g<subscript>0</subscript></entry>
-	    <entry>b<subscript>4</subscript></entry>
-	    <entry>b<subscript>3</subscript></entry>
-	    <entry>b<subscript>2</subscript></entry>
-	    <entry>b<subscript>1</subscript></entry>
-	    <entry>b<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry>a</entry>
-	    <entry>r<subscript>4</subscript></entry>
-	    <entry>r<subscript>3</subscript></entry>
-	    <entry>r<subscript>2</subscript></entry>
-	    <entry>r<subscript>1</subscript></entry>
-	    <entry>r<subscript>0</subscript></entry>
-	    <entry>g<subscript>4</subscript></entry>
-	    <entry>g<subscript>3</subscript></entry>
-	  </row>
-	  <row><!-- id="V4L2-PIX-FMT-RGB565" -->
-	    <entry><constant>V4L2_PIX_FMT_RGB565</constant></entry>
-	    <entry>'RGBP'</entry>
-	    <entry></entry>
-	    <entry>g<subscript>2</subscript></entry>
-	    <entry>g<subscript>1</subscript></entry>
-	    <entry>g<subscript>0</subscript></entry>
-	    <entry>b<subscript>4</subscript></entry>
-	    <entry>b<subscript>3</subscript></entry>
-	    <entry>b<subscript>2</subscript></entry>
-	    <entry>b<subscript>1</subscript></entry>
-	    <entry>b<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry>r<subscript>4</subscript></entry>
-	    <entry>r<subscript>3</subscript></entry>
-	    <entry>r<subscript>2</subscript></entry>
-	    <entry>r<subscript>1</subscript></entry>
-	    <entry>r<subscript>0</subscript></entry>
-	    <entry>g<subscript>5</subscript></entry>
-	    <entry>g<subscript>4</subscript></entry>
-	    <entry>g<subscript>3</subscript></entry>
-	  </row>
-	  <row><!-- id="V4L2-PIX-FMT-RGB555X" -->
-	    <entry><constant>V4L2_PIX_FMT_RGB555X</constant></entry>
-	    <entry>'RGBQ'</entry>
-	    <entry></entry>
-	    <entry>a</entry>
-	    <entry>r<subscript>4</subscript></entry>
-	    <entry>r<subscript>3</subscript></entry>
-	    <entry>r<subscript>2</subscript></entry>
-	    <entry>r<subscript>1</subscript></entry>
-	    <entry>r<subscript>0</subscript></entry>
-	    <entry>g<subscript>4</subscript></entry>
-	    <entry>g<subscript>3</subscript></entry>
-	    <entry></entry>
-	    <entry>g<subscript>2</subscript></entry>
-	    <entry>g<subscript>1</subscript></entry>
-	    <entry>g<subscript>0</subscript></entry>
-	    <entry>b<subscript>4</subscript></entry>
-	    <entry>b<subscript>3</subscript></entry>
-	    <entry>b<subscript>2</subscript></entry>
-	    <entry>b<subscript>1</subscript></entry>
-	    <entry>b<subscript>0</subscript></entry>
-	  </row>
-	  <row><!-- id="V4L2-PIX-FMT-RGB565X" -->
-	    <entry><constant>V4L2_PIX_FMT_RGB565X</constant></entry>
-	    <entry>'RGBR'</entry>
-	    <entry></entry>
-	    <entry>r<subscript>4</subscript></entry>
-	    <entry>r<subscript>3</subscript></entry>
-	    <entry>r<subscript>2</subscript></entry>
-	    <entry>r<subscript>1</subscript></entry>
-	    <entry>r<subscript>0</subscript></entry>
-	    <entry>g<subscript>5</subscript></entry>
-	    <entry>g<subscript>4</subscript></entry>
-	    <entry>g<subscript>3</subscript></entry>
-	    <entry></entry>
-	    <entry>g<subscript>2</subscript></entry>
-	    <entry>g<subscript>1</subscript></entry>
-	    <entry>g<subscript>0</subscript></entry>
-	    <entry>b<subscript>4</subscript></entry>
-	    <entry>b<subscript>3</subscript></entry>
-	    <entry>b<subscript>2</subscript></entry>
-	    <entry>b<subscript>1</subscript></entry>
-	    <entry>b<subscript>0</subscript></entry>
-	  </row>
-	  <row><!-- id="V4L2-PIX-FMT-BGR666" -->
-	    <entry><constant>V4L2_PIX_FMT_BGR666</constant></entry>
-	    <entry>'BGRH'</entry>
-	    <entry></entry>
-	    <entry>b<subscript>5</subscript></entry>
-	    <entry>b<subscript>4</subscript></entry>
-	    <entry>b<subscript>3</subscript></entry>
-	    <entry>b<subscript>2</subscript></entry>
-	    <entry>b<subscript>1</subscript></entry>
-	    <entry>b<subscript>0</subscript></entry>
-	    <entry>g<subscript>5</subscript></entry>
-	    <entry>g<subscript>4</subscript></entry>
-	    <entry></entry>
-	    <entry>g<subscript>3</subscript></entry>
-	    <entry>g<subscript>2</subscript></entry>
-	    <entry>g<subscript>1</subscript></entry>
-	    <entry>g<subscript>0</subscript></entry>
-	    <entry>r<subscript>5</subscript></entry>
-	    <entry>r<subscript>4</subscript></entry>
-	    <entry>r<subscript>3</subscript></entry>
-	    <entry>r<subscript>2</subscript></entry>
-	    <entry></entry>
-	    <entry>r<subscript>1</subscript></entry>
-	    <entry>r<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	  </row>
-	  <row><!-- id="V4L2-PIX-FMT-BGR24" -->
-	    <entry><constant>V4L2_PIX_FMT_BGR24</constant></entry>
-	    <entry>'BGR3'</entry>
-	    <entry></entry>
-	    <entry>b<subscript>7</subscript></entry>
-	    <entry>b<subscript>6</subscript></entry>
-	    <entry>b<subscript>5</subscript></entry>
-	    <entry>b<subscript>4</subscript></entry>
-	    <entry>b<subscript>3</subscript></entry>
-	    <entry>b<subscript>2</subscript></entry>
-	    <entry>b<subscript>1</subscript></entry>
-	    <entry>b<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry>g<subscript>7</subscript></entry>
-	    <entry>g<subscript>6</subscript></entry>
-	    <entry>g<subscript>5</subscript></entry>
-	    <entry>g<subscript>4</subscript></entry>
-	    <entry>g<subscript>3</subscript></entry>
-	    <entry>g<subscript>2</subscript></entry>
-	    <entry>g<subscript>1</subscript></entry>
-	    <entry>g<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry>r<subscript>7</subscript></entry>
-	    <entry>r<subscript>6</subscript></entry>
-	    <entry>r<subscript>5</subscript></entry>
-	    <entry>r<subscript>4</subscript></entry>
-	    <entry>r<subscript>3</subscript></entry>
-	    <entry>r<subscript>2</subscript></entry>
-	    <entry>r<subscript>1</subscript></entry>
-	    <entry>r<subscript>0</subscript></entry>
-	  </row>
-	  <row><!-- id="V4L2-PIX-FMT-RGB24" -->
-	    <entry><constant>V4L2_PIX_FMT_RGB24</constant></entry>
-	    <entry>'RGB3'</entry>
-	    <entry></entry>
-	    <entry>r<subscript>7</subscript></entry>
-	    <entry>r<subscript>6</subscript></entry>
-	    <entry>r<subscript>5</subscript></entry>
-	    <entry>r<subscript>4</subscript></entry>
-	    <entry>r<subscript>3</subscript></entry>
-	    <entry>r<subscript>2</subscript></entry>
-	    <entry>r<subscript>1</subscript></entry>
-	    <entry>r<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry>g<subscript>7</subscript></entry>
-	    <entry>g<subscript>6</subscript></entry>
-	    <entry>g<subscript>5</subscript></entry>
-	    <entry>g<subscript>4</subscript></entry>
-	    <entry>g<subscript>3</subscript></entry>
-	    <entry>g<subscript>2</subscript></entry>
-	    <entry>g<subscript>1</subscript></entry>
-	    <entry>g<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry>b<subscript>7</subscript></entry>
-	    <entry>b<subscript>6</subscript></entry>
-	    <entry>b<subscript>5</subscript></entry>
-	    <entry>b<subscript>4</subscript></entry>
-	    <entry>b<subscript>3</subscript></entry>
-	    <entry>b<subscript>2</subscript></entry>
-	    <entry>b<subscript>1</subscript></entry>
-	    <entry>b<subscript>0</subscript></entry>
-	  </row>
-	  <row><!-- id="V4L2-PIX-FMT-BGR32" -->
-	    <entry><constant>V4L2_PIX_FMT_BGR32</constant></entry>
-	    <entry>'BGR4'</entry>
-	    <entry></entry>
-	    <entry>b<subscript>7</subscript></entry>
-	    <entry>b<subscript>6</subscript></entry>
-	    <entry>b<subscript>5</subscript></entry>
-	    <entry>b<subscript>4</subscript></entry>
-	    <entry>b<subscript>3</subscript></entry>
-	    <entry>b<subscript>2</subscript></entry>
-	    <entry>b<subscript>1</subscript></entry>
-	    <entry>b<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry>g<subscript>7</subscript></entry>
-	    <entry>g<subscript>6</subscript></entry>
-	    <entry>g<subscript>5</subscript></entry>
-	    <entry>g<subscript>4</subscript></entry>
-	    <entry>g<subscript>3</subscript></entry>
-	    <entry>g<subscript>2</subscript></entry>
-	    <entry>g<subscript>1</subscript></entry>
-	    <entry>g<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry>r<subscript>7</subscript></entry>
-	    <entry>r<subscript>6</subscript></entry>
-	    <entry>r<subscript>5</subscript></entry>
-	    <entry>r<subscript>4</subscript></entry>
-	    <entry>r<subscript>3</subscript></entry>
-	    <entry>r<subscript>2</subscript></entry>
-	    <entry>r<subscript>1</subscript></entry>
-	    <entry>r<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry>a<subscript>7</subscript></entry>
-	    <entry>a<subscript>6</subscript></entry>
-	    <entry>a<subscript>5</subscript></entry>
-	    <entry>a<subscript>4</subscript></entry>
-	    <entry>a<subscript>3</subscript></entry>
-	    <entry>a<subscript>2</subscript></entry>
-	    <entry>a<subscript>1</subscript></entry>
-	    <entry>a<subscript>0</subscript></entry>
-	  </row>
-	  <row><!-- id="V4L2-PIX-FMT-RGB32" -->
-	    <entry><constant>V4L2_PIX_FMT_RGB32</constant></entry>
-	    <entry>'RGB4'</entry>
-	    <entry></entry>
-	    <entry>a<subscript>7</subscript></entry>
-	    <entry>a<subscript>6</subscript></entry>
-	    <entry>a<subscript>5</subscript></entry>
-	    <entry>a<subscript>4</subscript></entry>
-	    <entry>a<subscript>3</subscript></entry>
-	    <entry>a<subscript>2</subscript></entry>
-	    <entry>a<subscript>1</subscript></entry>
-	    <entry>a<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry>r<subscript>7</subscript></entry>
-	    <entry>r<subscript>6</subscript></entry>
-	    <entry>r<subscript>5</subscript></entry>
-	    <entry>r<subscript>4</subscript></entry>
-	    <entry>r<subscript>3</subscript></entry>
-	    <entry>r<subscript>2</subscript></entry>
-	    <entry>r<subscript>1</subscript></entry>
-	    <entry>r<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry>g<subscript>7</subscript></entry>
-	    <entry>g<subscript>6</subscript></entry>
-	    <entry>g<subscript>5</subscript></entry>
-	    <entry>g<subscript>4</subscript></entry>
-	    <entry>g<subscript>3</subscript></entry>
-	    <entry>g<subscript>2</subscript></entry>
-	    <entry>g<subscript>1</subscript></entry>
-	    <entry>g<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry>b<subscript>7</subscript></entry>
-	    <entry>b<subscript>6</subscript></entry>
-	    <entry>b<subscript>5</subscript></entry>
-	    <entry>b<subscript>4</subscript></entry>
-	    <entry>b<subscript>3</subscript></entry>
-	    <entry>b<subscript>2</subscript></entry>
-	    <entry>b<subscript>1</subscript></entry>
-	    <entry>b<subscript>0</subscript></entry>
-	  </row>
-	</tbody>
-      </tgroup>
-    </table>
-
     <para>A test utility to determine which RGB formats a driver
 actually supports is available from the LinuxTV v4l-dvb repository.
 See &v4l-dvb; for access instructions.</para>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sdr-cu08.xml b/Documentation/DocBook/media/v4l/pixfmt-sdr-cu08.xml
new file mode 100644
index 0000000..2d80104
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/pixfmt-sdr-cu08.xml
@@ -0,0 +1,44 @@
+<refentry id="V4L2-SDR-FMT-CU08">
+  <refmeta>
+    <refentrytitle>V4L2_SDR_FMT_CU8 ('CU08')</refentrytitle>
+    &manvol;
+  </refmeta>
+    <refnamediv>
+      <refname>
+        <constant>V4L2_SDR_FMT_CU8</constant>
+      </refname>
+      <refpurpose>Complex unsigned 8-bit IQ sample</refpurpose>
+    </refnamediv>
+    <refsect1>
+      <title>Description</title>
+      <para>
+This format contains sequence of complex number samples. Each complex number
+consist two parts, called In-phase and Quadrature (IQ). Both I and Q are
+represented as a 8 bit unsigned number. I value comes first and Q value after
+that.
+      </para>
+    <example>
+      <title><constant>V4L2_SDR_FMT_CU8</constant> 1 sample</title>
+      <formalpara>
+        <title>Byte Order.</title>
+        <para>Each cell is one byte.
+          <informaltable frame="none">
+            <tgroup cols="2" align="center">
+              <colspec align="left" colwidth="2*" />
+              <tbody valign="top">
+                <row>
+                  <entry>start&nbsp;+&nbsp;0:</entry>
+                  <entry>I'<subscript>0</subscript></entry>
+                </row>
+                <row>
+                  <entry>start&nbsp;+&nbsp;1:</entry>
+                  <entry>Q'<subscript>0</subscript></entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        </para>
+      </formalpara>
+    </example>
+  </refsect1>
+</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sdr-cu16le.xml b/Documentation/DocBook/media/v4l/pixfmt-sdr-cu16le.xml
new file mode 100644
index 0000000..26288ff
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/pixfmt-sdr-cu16le.xml
@@ -0,0 +1,46 @@
+<refentry id="V4L2-SDR-FMT-CU16LE">
+  <refmeta>
+    <refentrytitle>V4L2_SDR_FMT_CU16LE ('CU16')</refentrytitle>
+    &manvol;
+  </refmeta>
+    <refnamediv>
+      <refname>
+        <constant>V4L2_SDR_FMT_CU16LE</constant>
+      </refname>
+      <refpurpose>Complex unsigned 16-bit little endian IQ sample</refpurpose>
+    </refnamediv>
+    <refsect1>
+      <title>Description</title>
+      <para>
+This format contains sequence of complex number samples. Each complex number
+consist two parts, called In-phase and Quadrature (IQ). Both I and Q are
+represented as a 16 bit unsigned little endian number. I value comes first
+and Q value after that.
+      </para>
+    <example>
+      <title><constant>V4L2_SDR_FMT_CU16LE</constant> 1 sample</title>
+      <formalpara>
+        <title>Byte Order.</title>
+        <para>Each cell is one byte.
+          <informaltable frame="none">
+            <tgroup cols="3" align="center">
+              <colspec align="left" colwidth="2*" />
+              <tbody valign="top">
+                <row>
+                  <entry>start&nbsp;+&nbsp;0:</entry>
+                  <entry>I'<subscript>0[7:0]</subscript></entry>
+                  <entry>I'<subscript>0[15:8]</subscript></entry>
+                </row>
+                <row>
+                  <entry>start&nbsp;+&nbsp;2:</entry>
+                  <entry>Q'<subscript>0[7:0]</subscript></entry>
+                  <entry>Q'<subscript>0[15:8]</subscript></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 72d72bd..ea514d6 100644
--- a/Documentation/DocBook/media/v4l/pixfmt.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt.xml
@@ -25,7 +25,12 @@
 	<row>
 	  <entry>__u32</entry>
 	  <entry><structfield>height</structfield></entry>
-	  <entry>Image height in pixels.</entry>
+	  <entry>Image height in pixels. If <structfield>field</structfield> is
+	  one of <constant>V4L2_FIELD_TOP</constant>, <constant>V4L2_FIELD_BOTTOM</constant>
+	  or <constant>V4L2_FIELD_ALTERNATE</constant> then height refers to the
+	  number of lines in the field, otherwise it refers to the number of
+	  lines in the frame (which is twice the field height for interlaced
+	  formats).</entry>
 	</row>
 	<row>
 	  <entry spanname="hspan">Applications set these fields to
@@ -54,7 +59,7 @@
 can request to capture or output only the top or bottom field, or both
 fields interlaced or sequentially stored in one buffer or alternating
 in separate buffers. Drivers return the actual field order selected.
-For details see <xref linkend="field-order" />.</entry>
+For more details on fields see <xref linkend="field-order" />.</entry>
 	</row>
 	<row>
 	  <entry>__u32</entry>
@@ -81,7 +86,10 @@
 example the Cb and Cr planes of a YUV 4:2:0 image have half as many
 padding bytes following each line as the Y plane. To avoid ambiguities
 drivers must return a <structfield>bytesperline</structfield> value
-rounded up to a multiple of the scale factor.</para></entry>
+rounded up to a multiple of the scale factor.</para>
+<para>For compressed formats the <structfield>bytesperline</structfield>
+value makes no sense. Applications and drivers must set this to 0 in
+that case.</para></entry>
 	</row>
 	<row>
 	  <entry>__u32</entry>
@@ -97,7 +105,8 @@
 	  <entry>&v4l2-colorspace;</entry>
 	  <entry><structfield>colorspace</structfield></entry>
 	  <entry>This information supplements the
-<structfield>pixelformat</structfield> and must be set by the driver,
+<structfield>pixelformat</structfield> and must be set by the driver for
+capture streams and by the application for output streams,
 see <xref linkend="colorspaces" />.</entry>
 	</row>
 	<row>
@@ -135,7 +144,7 @@
           <entry>__u16</entry>
           <entry><structfield>bytesperline</structfield></entry>
           <entry>Distance in bytes between the leftmost pixels in two adjacent
-            lines.</entry>
+            lines. See &v4l2-pix-format;.</entry>
         </row>
         <row>
           <entry>__u16</entry>
@@ -154,12 +163,12 @@
         <row>
           <entry>__u32</entry>
           <entry><structfield>width</structfield></entry>
-          <entry>Image width in pixels.</entry>
+          <entry>Image width in pixels. See &v4l2-pix-format;.</entry>
         </row>
         <row>
           <entry>__u32</entry>
           <entry><structfield>height</structfield></entry>
-          <entry>Image height in pixels.</entry>
+          <entry>Image height in pixels. See &v4l2-pix-format;.</entry>
         </row>
         <row>
           <entry>__u32</entry>
@@ -811,6 +820,17 @@
     </table>
   </section>
 
+  <section id="sdr-formats">
+    <title>SDR Formats</title>
+
+    <para>These formats are used for <link linkend="sdr">SDR Capture</link>
+interface only.</para>
+
+    &sub-sdr-cu08;
+    &sub-sdr-cu16le;
+
+  </section>
+
   <section id="pixfmt-reserved">
     <title>Reserved Format Identifiers</title>
 
diff --git a/Documentation/DocBook/media/v4l/remote_controllers.xml b/Documentation/DocBook/media/v4l/remote_controllers.xml
index 160e464..5124a6c 100644
--- a/Documentation/DocBook/media/v4l/remote_controllers.xml
+++ b/Documentation/DocBook/media/v4l/remote_controllers.xml
@@ -1,10 +1,152 @@
+<partinfo>
+<authorgroup>
+<author>
+<firstname>Mauro</firstname>
+<surname>Chehab</surname>
+<othername role="mi">Carvalho</othername>
+<affiliation><address><email>m.chehab@samsung.com</email></address></affiliation>
+<contrib>Initial version.</contrib>
+</author>
+</authorgroup>
+<copyright>
+	<year>2009-2014</year>
+        <holder>Mauro Carvalho Chehab</holder>
+</copyright>
+
+<revhistory>
+<!-- Put document revisions here, newest first. -->
+<revision>
+<revnumber>3.15</revnumber>
+<date>2014-02-06</date>
+<authorinitials>mcc</authorinitials>
+<revremark>Added the interface description and the RC sysfs class description.</revremark>
+</revision>
+<revision>
+<revnumber>1.0</revnumber>
+<date>2009-09-06</date>
+<authorinitials>mcc</authorinitials>
+<revremark>Initial revision</revremark>
+</revision>
+</revhistory>
+</partinfo>
+
+ <title>Remote Controller API</title>
+ <chapter id="remote_controllers">
+
 <title>Remote Controllers</title>
+
 <section id="Remote_controllers_Intro">
 <title>Introduction</title>
 
 <para>Currently, most analog and digital devices have a Infrared input for remote controllers. Each
 manufacturer has their own type of control. It is not rare for the same manufacturer to ship different
 types of controls, depending on the device.</para>
+<para>A Remote Controller interface is mapped as a normal evdev/input interface, just like a keyboard or a mouse.
+So, it uses all ioctls already defined for any other input devices.</para>
+<para>However, remove controllers are more flexible than a normal input device, as the IR
+receiver (and/or transmitter) can be used in conjunction with a wide variety of different IR remotes.</para>
+<para>In order to allow flexibility, the Remote Controller subsystem allows controlling the
+RC-specific attributes via <link linkend="remote_controllers_sysfs_nodes">the sysfs class nodes</link>.</para>
+</section>
+
+<section id="remote_controllers_sysfs_nodes">
+<title>Remote Controller's sysfs nodes</title>
+<para>As defined at <constant>Documentation/ABI/testing/sysfs-class-rc</constant>, those are the sysfs nodes that control the Remote Controllers:</para>
+
+<section id="sys_class_rc">
+<title>/sys/class/rc/</title>
+<para>The <constant>/sys/class/rc/</constant> class sub-directory belongs to the Remote Controller
+core and provides a sysfs interface for configuring infrared remote controller receivers.
+</para>
+
+</section>
+<section id="sys_class_rc_rcN">
+<title>/sys/class/rc/rcN/</title>
+<para>A <constant>/sys/class/rc/rcN</constant> directory is created for each remote
+  control receiver device where N is the number of the receiver.</para>
+
+</section>
+<section id="sys_class_rc_rcN_protocols">
+<title>/sys/class/rc/rcN/protocols</title>
+<para>Reading this file returns a list of available protocols, something like:</para>
+<para><constant>rc5 [rc6] nec jvc [sony]</constant></para>
+<para>Enabled protocols are shown in [] brackets.</para>
+<para>Writing "+proto" will add a protocol to the list of enabled protocols.</para>
+<para>Writing "-proto" will remove a protocol from the list of enabled protocols.</para>
+<para>Writing "proto" will enable only "proto".</para>
+<para>Writing "none" will disable all protocols.</para>
+<para>Write fails with EINVAL if an invalid protocol combination or unknown protocol name is used.</para>
+
+</section>
+<section id="sys_class_rc_rcN_filter">
+<title>/sys/class/rc/rcN/filter</title>
+<para>Sets the scancode filter expected value.</para>
+<para>Use in combination with <constant>/sys/class/rc/rcN/filter_mask</constant> to set the
+expected value of the bits set in the filter mask.
+If the hardware supports it then scancodes which do not match
+the filter will be ignored. Otherwise the write will fail with
+an error.</para>
+<para>This value may be reset to 0 if the current protocol is altered.</para>
+
+</section>
+<section id="sys_class_rc_rcN_filter_mask">
+<title>/sys/class/rc/rcN/filter_mask</title>
+<para>Sets the scancode filter mask of bits to compare.
+Use in combination with <constant>/sys/class/rc/rcN/filter</constant> to set the bits
+of the scancode which should be compared against the expected
+value. A value of 0 disables the filter to allow all valid
+scancodes to be processed.</para>
+<para>If the hardware supports it then scancodes which do not match
+the filter will be ignored. Otherwise the write will fail with
+an error.</para>
+<para>This value may be reset to 0 if the current protocol is altered.</para>
+
+</section>
+<section id="sys_class_rc_rcN_wakeup_protocols">
+<title>/sys/class/rc/rcN/wakeup_protocols</title>
+<para>Reading this file returns a list of available protocols to use for the
+wakeup filter, something like:</para>
+<para><constant>rc5 rc6 nec jvc [sony]</constant></para>
+<para>The enabled wakeup protocol is shown in [] brackets.</para>
+<para>Writing "+proto" will add a protocol to the list of enabled wakeup
+protocols.</para>
+<para>Writing "-proto" will remove a protocol from the list of enabled wakeup
+protocols.</para>
+<para>Writing "proto" will use "proto" for wakeup events.</para>
+<para>Writing "none" will disable wakeup.</para>
+<para>Write fails with EINVAL if an invalid protocol combination or unknown
+protocol name is used, or if wakeup is not supported by the hardware.</para>
+
+</section>
+<section id="sys_class_rc_rcN_wakeup_filter">
+<title>/sys/class/rc/rcN/wakeup_filter</title>
+<para>Sets the scancode wakeup filter expected value.
+Use in combination with <constant>/sys/class/rc/rcN/wakeup_filter_mask</constant> to
+set the expected value of the bits set in the wakeup filter mask
+to trigger a system wake event.</para>
+<para>If the hardware supports it and wakeup_filter_mask is not 0 then
+scancodes which match the filter will wake the system from e.g.
+suspend to RAM or power off.
+Otherwise the write will fail with an error.</para>
+<para>This value may be reset to 0 if the wakeup protocol is altered.</para>
+
+</section>
+<section id="sys_class_rc_rcN_wakeup_filter_mask">
+<title>/sys/class/rc/rcN/wakeup_filter_mask</title>
+<para>Sets the scancode wakeup filter mask of bits to compare.
+Use in combination with <constant>/sys/class/rc/rcN/wakeup_filter</constant> to set
+the bits of the scancode which should be compared against the
+expected value to trigger a system wake event.</para>
+<para>If the hardware supports it and wakeup_filter_mask is not 0 then
+scancodes which match the filter will wake the system from e.g.
+suspend to RAM or power off.
+Otherwise the write will fail with an error.</para>
+<para>This value may be reset to 0 if the wakeup protocol is altered.</para>
+</section>
+</section>
+
+<section id="Remote_controllers_tables">
+<title>Remote controller tables</title>
 <para>Unfortunately, for several years, there was no effort to create uniform IR keycodes for
 different devices.  This caused the same IR keyname to be mapped completely differently on
 different IR devices. This resulted that the same IR keyname to be mapped completely different on
@@ -175,3 +317,4 @@
 </section>
 
 &sub-lirc_device_interface;
+</chapter>
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml
index 74b7f27..b445161 100644
--- a/Documentation/DocBook/media/v4l/v4l2.xml
+++ b/Documentation/DocBook/media/v4l/v4l2.xml
@@ -70,7 +70,7 @@
 Remote Controller chapter.</contrib>
 	<affiliation>
 	  <address>
-	    <email>mchehab@redhat.com</email>
+	    <email>m.chehab@samsung.com</email>
 	  </address>
 	</affiliation>
       </author>
@@ -107,6 +107,16 @@
 	  </address>
 	</affiliation>
       </author>
+      <author>
+	<firstname>Antti</firstname>
+	<surname>Palosaari</surname>
+	<contrib>SDR API.</contrib>
+	<affiliation>
+	  <address>
+	    <email>crope@iki.fi</email>
+	  </address>
+	</affiliation>
+      </author>
     </authorgroup>
 
     <copyright>
@@ -125,6 +135,7 @@
       <year>2011</year>
       <year>2012</year>
       <year>2013</year>
+      <year>2014</year>
       <holder>Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin
 Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab,
 	Pawel Osciak</holder>
@@ -141,6 +152,16 @@
 applications. -->
 
       <revision>
+	<revnumber>3.15</revnumber>
+	<date>2014-02-03</date>
+	<authorinitials>hv, ap</authorinitials>
+	<revremark>Update several sections of "Common API Elements": "Opening and Closing Devices"
+"Querying Capabilities", "Application Priority", "Video Inputs and Outputs", "Audio Inputs and Outputs"
+"Tuners and Modulators", "Video Standards" and "Digital Video (DV) Timings". Added SDR API.
+	</revremark>
+      </revision>
+
+      <revision>
 	<revnumber>3.14</revnumber>
 	<date>2013-11-25</date>
 	<authorinitials>rr</authorinitials>
@@ -537,6 +558,7 @@
     <section id="ttx"> &sub-dev-teletext; </section>
     <section id="radio"> &sub-dev-radio; </section>
     <section id="rds"> &sub-dev-rds; </section>
+    <section id="sdr"> &sub-dev-sdr; </section>
     <section id="event"> &sub-dev-event; </section>
     <section id="subdev"> &sub-dev-subdev; </section>
   </chapter>
@@ -585,6 +607,7 @@
     &sub-g-crop;
     &sub-g-ctrl;
     &sub-g-dv-timings;
+    &sub-g-edid;
     &sub-g-enc-index;
     &sub-g-ext-ctrls;
     &sub-g-fbuf;
@@ -616,7 +639,6 @@
     &sub-subdev-enum-frame-size;
     &sub-subdev-enum-mbus-code;
     &sub-subdev-g-crop;
-    &sub-subdev-g-edid;
     &sub-subdev-g-fmt;
     &sub-subdev-g-frame-interval;
     &sub-subdev-g-selection;
diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml b/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml
index 6541ba0..4e8ea65 100644
--- a/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml
@@ -100,7 +100,7 @@
 	    <entry><structfield>capability</structfield></entry>
 	    <entry spanname="hspan">The tuner/modulator capability flags for
 this frequency band, see <xref linkend="tuner-capability" />. The <constant>V4L2_TUNER_CAP_LOW</constant>
-capability must be the same for all frequency bands of the selected tuner/modulator.
+or <constant>V4L2_TUNER_CAP_1HZ</constant> capability must be the same for all frequency bands of the selected tuner/modulator.
 So either all bands have that capability set, or none of them have that capability.</entry>
 	  </row>
 	  <row>
@@ -109,7 +109,8 @@
 	    <entry spanname="hspan">The lowest tunable frequency in
 units of 62.5 kHz, or if the <structfield>capability</structfield>
 flag <constant>V4L2_TUNER_CAP_LOW</constant> is set, in units of 62.5
-Hz, for this frequency band.</entry>
+Hz, for this frequency band. A 1 Hz unit is used when the <structfield>capability</structfield> flag
+<constant>V4L2_TUNER_CAP_1HZ</constant> is set.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
@@ -117,7 +118,8 @@
 	    <entry spanname="hspan">The highest tunable frequency in
 units of 62.5 kHz, or if the <structfield>capability</structfield>
 flag <constant>V4L2_TUNER_CAP_LOW</constant> is set, in units of 62.5
-Hz, for this frequency band.</entry>
+Hz, for this frequency band. A 1 Hz unit is used when the <structfield>capability</structfield> flag
+<constant>V4L2_TUNER_CAP_1HZ</constant> is set.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-edid.xml b/Documentation/DocBook/media/v4l/vidioc-g-edid.xml
similarity index 77%
rename from Documentation/DocBook/media/v4l/vidioc-subdev-g-edid.xml
rename to Documentation/DocBook/media/v4l/vidioc-g-edid.xml
index bbd18f0..ce4563b 100644
--- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-edid.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-edid.xml
@@ -1,12 +1,12 @@
-<refentry id="vidioc-subdev-g-edid">
+<refentry id="vidioc-g-edid">
   <refmeta>
-    <refentrytitle>ioctl VIDIOC_SUBDEV_G_EDID, VIDIOC_SUBDEV_S_EDID</refentrytitle>
+    <refentrytitle>ioctl VIDIOC_G_EDID, VIDIOC_S_EDID</refentrytitle>
     &manvol;
   </refmeta>
 
   <refnamediv>
-    <refname>VIDIOC_SUBDEV_G_EDID</refname>
-    <refname>VIDIOC_SUBDEV_S_EDID</refname>
+    <refname>VIDIOC_G_EDID</refname>
+    <refname>VIDIOC_S_EDID</refname>
     <refpurpose>Get or set the EDID of a video receiver/transmitter</refpurpose>
   </refnamediv>
 
@@ -16,7 +16,7 @@
 	<funcdef>int <function>ioctl</function></funcdef>
 	<paramdef>int <parameter>fd</parameter></paramdef>
 	<paramdef>int <parameter>request</parameter></paramdef>
-	<paramdef>struct v4l2_subdev_edid *<parameter>argp</parameter></paramdef>
+	<paramdef>struct v4l2_edid *<parameter>argp</parameter></paramdef>
       </funcprototype>
     </funcsynopsis>
     <funcsynopsis>
@@ -24,7 +24,7 @@
 	<funcdef>int <function>ioctl</function></funcdef>
 	<paramdef>int <parameter>fd</parameter></paramdef>
 	<paramdef>int <parameter>request</parameter></paramdef>
-	<paramdef>const struct v4l2_subdev_edid *<parameter>argp</parameter></paramdef>
+	<paramdef>const struct v4l2_edid *<parameter>argp</parameter></paramdef>
       </funcprototype>
     </funcsynopsis>
   </refsynopsisdiv>
@@ -42,7 +42,7 @@
       <varlistentry>
 	<term><parameter>request</parameter></term>
 	<listitem>
-	  <para>VIDIOC_SUBDEV_G_EDID, VIDIOC_SUBDEV_S_EDID</para>
+	  <para>VIDIOC_G_EDID, VIDIOC_S_EDID</para>
 	</listitem>
       </varlistentry>
       <varlistentry>
@@ -56,12 +56,20 @@
 
   <refsect1>
     <title>Description</title>
-    <para>These ioctls can be used to get or set an EDID associated with an input pad
-    from a receiver or an output pad of a transmitter subdevice.</para>
+    <para>These ioctls can be used to get or set an EDID associated with an input
+    from a receiver or an output of a transmitter device. They can be
+    used with subdevice nodes (/dev/v4l-subdevX) or with video nodes (/dev/videoX).</para>
+
+    <para>When used with video nodes the <structfield>pad</structfield> field represents the
+    input (for video capture devices) or output (for video output devices) index as
+    is returned by &VIDIOC-ENUMINPUT; and &VIDIOC-ENUMOUTPUT; respectively. When used
+    with subdevice nodes the <structfield>pad</structfield> field represents the
+    input or output pad of the subdevice. If there is no EDID support for the given
+    <structfield>pad</structfield> value, then the &EINVAL; will be returned.</para>
 
     <para>To get the EDID data the application has to fill in the <structfield>pad</structfield>,
     <structfield>start_block</structfield>, <structfield>blocks</structfield> and <structfield>edid</structfield>
-    fields and call <constant>VIDIOC_SUBDEV_G_EDID</constant>. The current EDID from block
+    fields and call <constant>VIDIOC_G_EDID</constant>. The current EDID from block
     <structfield>start_block</structfield> and of size <structfield>blocks</structfield>
     will be placed in the memory <structfield>edid</structfield> points to. The <structfield>edid</structfield>
     pointer must point to memory at least <structfield>blocks</structfield>&nbsp;*&nbsp;128 bytes
@@ -91,15 +99,17 @@
     data in some way. In any case, the end result is the same: the EDID is no longer available.
     </para>
 
-    <table pgwide="1" frame="none" id="v4l2-subdev-edid">
-      <title>struct <structname>v4l2_subdev_edid</structname></title>
+    <table pgwide="1" frame="none" id="v4l2-edid">
+      <title>struct <structname>v4l2_edid</structname></title>
       <tgroup cols="3">
         &cs-str;
 	<tbody valign="top">
 	  <row>
 	    <entry>__u32</entry>
 	    <entry><structfield>pad</structfield></entry>
-	    <entry>Pad for which to get/set the EDID blocks.</entry>
+	    <entry>Pad for which to get/set the EDID blocks. When used with a video device
+	    node the pad represents the input or output index as returned by
+	    &VIDIOC-ENUMINPUT; and &VIDIOC-ENUMOUTPUT; respectively.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
index b3bb957..e9f6735 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
@@ -327,7 +327,12 @@
 These controls are described in <xref
 		linkend="fm-rx-controls" />.</entry>
 	  </row>
-
+	  <row>
+	    <entry><constant>V4L2_CTRL_CLASS_RF_TUNER</constant></entry>
+	    <entry>0xa20000</entry>
+	    <entry>The class containing RF tuner controls.
+These controls are described in <xref linkend="rf-tuner-controls" />.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-fmt.xml b/Documentation/DocBook/media/v4l/vidioc-g-fmt.xml
index ee8f56e..4fe19a7a 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-fmt.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-fmt.xml
@@ -172,6 +172,13 @@
 	  </row>
 	  <row>
 	    <entry></entry>
+	    <entry>&v4l2-sdr-format;</entry>
+	    <entry><structfield>sdr</structfield></entry>
+	    <entry>Definition of a data format, see
+<xref linkend="pixfmt" />, used by SDR capture devices.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
 	    <entry>__u8</entry>
 	    <entry><structfield>raw_data</structfield>[200]</entry>
 	    <entry>Place holder for future extensions.</entry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml b/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml
index c7a1c46..d1034fb 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml
@@ -109,9 +109,10 @@
 	    <entry>__u32</entry>
 	    <entry><structfield>frequency</structfield></entry>
 	    <entry>Tuning frequency in units of 62.5 kHz, or if the
-&v4l2-tuner; or &v4l2-modulator; <structfield>capabilities</structfield> flag
+&v4l2-tuner; or &v4l2-modulator; <structfield>capability</structfield> flag
 <constant>V4L2_TUNER_CAP_LOW</constant> is set, in units of 62.5
-Hz.</entry>
+Hz. A 1 Hz unit is used when the <structfield>capability</structfield> flag
+<constant>V4L2_TUNER_CAP_1HZ</constant> is set.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-modulator.xml b/Documentation/DocBook/media/v4l/vidioc-g-modulator.xml
index 7f4ac7e..7068b59 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-modulator.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-modulator.xml
@@ -113,7 +113,8 @@
 	    <entry>The lowest tunable frequency in units of 62.5
 KHz, or if the <structfield>capability</structfield> flag
 <constant>V4L2_TUNER_CAP_LOW</constant> is set, in units of 62.5
-Hz.</entry>
+Hz, or if the <structfield>capability</structfield> flag
+<constant>V4L2_TUNER_CAP_1HZ</constant> is set, in units of 1 Hz.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
@@ -121,7 +122,8 @@
 	    <entry>The highest tunable frequency in units of 62.5
 KHz, or if the <structfield>capability</structfield> flag
 <constant>V4L2_TUNER_CAP_LOW</constant> is set, in units of 62.5
-Hz.</entry>
+Hz, or if the <structfield>capability</structfield> flag
+<constant>V4L2_TUNER_CAP_1HZ</constant> is set, in units of 1 Hz.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
index 6cc8201..b0d8659 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
@@ -134,7 +134,9 @@
 	    <entry spanname="hspan">The lowest tunable frequency in
 units of 62.5 kHz, or if the <structfield>capability</structfield>
 flag <constant>V4L2_TUNER_CAP_LOW</constant> is set, in units of 62.5
-Hz. If multiple frequency bands are supported, then
+Hz, or if the <structfield>capability</structfield> flag
+<constant>V4L2_TUNER_CAP_1HZ</constant> is set, in units of 1 Hz.
+If multiple frequency bands are supported, then
 <structfield>rangelow</structfield> is the lowest frequency
 of all the frequency bands.</entry>
 	  </row>
@@ -144,7 +146,9 @@
 	    <entry spanname="hspan">The highest tunable frequency in
 units of 62.5 kHz, or if the <structfield>capability</structfield>
 flag <constant>V4L2_TUNER_CAP_LOW</constant> is set, in units of 62.5
-Hz. If multiple frequency bands are supported, then
+Hz, or if the <structfield>capability</structfield> flag
+<constant>V4L2_TUNER_CAP_1HZ</constant> is set, in units of 1 Hz.
+If multiple frequency bands are supported, then
 <structfield>rangehigh</structfield> is the highest frequency
 of all the frequency bands.</entry>
 	  </row>
@@ -270,7 +274,7 @@
 	    <entry><constant>V4L2_TUNER_CAP_LOW</constant></entry>
 	    <entry>0x0001</entry>
 	    <entry>When set, tuning frequencies are expressed in units of
-62.5&nbsp;Hz, otherwise in units of 62.5&nbsp;kHz.</entry>
+62.5 Hz instead of 62.5 kHz.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_TUNER_CAP_NORM</constant></entry>
@@ -360,6 +364,11 @@
 	<entry>The range to search when using the hardware seek functionality
 	is programmable, see &VIDIOC-S-HW-FREQ-SEEK; for details.</entry>
 	  </row>
+	  <row>
+	<entry><constant>V4L2_TUNER_CAP_1HZ</constant></entry>
+	<entry>0x1000</entry>
+	<entry>When set, tuning frequencies are expressed in units of 1 Hz instead of 62.5 kHz.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff --git a/Documentation/DocBook/media/v4l/vidioc-querycap.xml b/Documentation/DocBook/media/v4l/vidioc-querycap.xml
index d5a3c97..370d49d 100644
--- a/Documentation/DocBook/media/v4l/vidioc-querycap.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-querycap.xml
@@ -296,6 +296,12 @@
 <xref linkend="tuner" />.</entry>
 	  </row>
 	  <row>
+	    <entry><constant>V4L2_CAP_SDR_CAPTURE</constant></entry>
+	    <entry>0x00100000</entry>
+	    <entry>The device supports the
+<link linkend="sdr">SDR Capture</link> interface.</entry>
+	  </row>
+	  <row>
 	    <entry><constant>V4L2_CAP_READWRITE</constant></entry>
 	    <entry>0x01000000</entry>
 	    <entry>The device supports the <link
diff --git a/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml b/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml
index 5b379e7..a5fc4c4 100644
--- a/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml
@@ -121,7 +121,9 @@
 	    <entry>If non-zero, the lowest tunable frequency of the band to
 search in units of 62.5 kHz, or if the &v4l2-tuner;
 <structfield>capability</structfield> field has the
-<constant>V4L2_TUNER_CAP_LOW</constant> flag set, in units of 62.5 Hz.
+<constant>V4L2_TUNER_CAP_LOW</constant> flag set, in units of 62.5 Hz or if the &v4l2-tuner;
+<structfield>capability</structfield> field has the
+<constant>V4L2_TUNER_CAP_1HZ</constant> flag set, in units of 1 Hz.
 If <structfield>rangelow</structfield> is zero a reasonable default value
 is used.</entry>
 	  </row>
@@ -131,7 +133,9 @@
 	    <entry>If non-zero, the highest tunable frequency of the band to
 search in units of 62.5 kHz, or if the &v4l2-tuner;
 <structfield>capability</structfield> field has the
-<constant>V4L2_TUNER_CAP_LOW</constant> flag set, in units of 62.5 Hz.
+<constant>V4L2_TUNER_CAP_LOW</constant> flag set, in units of 62.5 Hz or if the &v4l2-tuner;
+<structfield>capability</structfield> field has the
+<constant>V4L2_TUNER_CAP_1HZ</constant> flag set, in units of 1 Hz.
 If <structfield>rangehigh</structfield> is zero a reasonable default value
 is used.</entry>
 	  </row>
diff --git a/Documentation/DocBook/media/v4l/vidioc-streamon.xml b/Documentation/DocBook/media/v4l/vidioc-streamon.xml
index 65dff55..df2c63d 100644
--- a/Documentation/DocBook/media/v4l/vidioc-streamon.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-streamon.xml
@@ -52,16 +52,24 @@
     <para>The <constant>VIDIOC_STREAMON</constant> and
 <constant>VIDIOC_STREAMOFF</constant> ioctl start and stop the capture
 or output process during streaming (<link linkend="mmap">memory
-mapping</link> or <link linkend="userp">user pointer</link>) I/O.</para>
+mapping</link>, <link linkend="userp">user pointer</link> or
+<link linkend="dmabuf">DMABUF</link>) I/O.</para>
 
-    <para>Specifically the capture hardware is disabled and no input
+    <para>Capture hardware is disabled and no input
 buffers are filled (if there are any empty buffers in the incoming
 queue) until <constant>VIDIOC_STREAMON</constant> has been called.
-Accordingly the output hardware is disabled, no video signal is
+Output hardware is disabled and no video signal is
 produced until <constant>VIDIOC_STREAMON</constant> has been called.
 The ioctl will succeed when at least one output buffer is in the
 incoming queue.</para>
 
+    <para>Memory-to-memory devices will not start until
+<constant>VIDIOC_STREAMON</constant> has been called for both the capture
+and output stream types.</para>
+
+    <para>If <constant>VIDIOC_STREAMON</constant> fails then any already
+queued buffers will remain queued.</para>
+
     <para>The <constant>VIDIOC_STREAMOFF</constant> ioctl, apart of
 aborting or finishing any DMA in progress, unlocks any user pointer
 buffers locked in physical memory, and it removes all buffers from the
@@ -70,14 +78,22 @@
 not transmitted yet. I/O returns to the same state as after calling
 &VIDIOC-REQBUFS; and can be restarted accordingly.</para>
 
+    <para>If buffers have been queued with &VIDIOC-QBUF; and
+<constant>VIDIOC_STREAMOFF</constant> is called without ever having
+called <constant>VIDIOC_STREAMON</constant>, then those queued buffers
+will also be removed from the incoming queue and all are returned to the
+same state as after calling &VIDIOC-REQBUFS; and can be restarted
+accordingly.</para>
+
     <para>Both ioctls take a pointer to an integer, the desired buffer or
 stream type. This is the same as &v4l2-requestbuffers;
 <structfield>type</structfield>.</para>
 
     <para>If <constant>VIDIOC_STREAMON</constant> is called when streaming
 is already in progress, or if <constant>VIDIOC_STREAMOFF</constant> is called
-when streaming is already stopped, then the ioctl does nothing and 0 is
-returned.</para>
+when streaming is already stopped, then 0 is returned. Nothing happens in the
+case of <constant>VIDIOC_STREAMON</constant>, but <constant>VIDIOC_STREAMOFF</constant>
+will return queued buffers to their starting state as mentioned above.</para>
 
     <para>Note that applications can be preempted for unknown periods right
 before or after the <constant>VIDIOC_STREAMON</constant> or
@@ -93,7 +109,7 @@
       <varlistentry>
 	<term><errorcode>EINVAL</errorcode></term>
 	<listitem>
-	  <para>The buffer<structfield>type</structfield> is not supported,
+	  <para>The buffer <structfield>type</structfield> is not supported,
 	  or no buffers have been allocated (memory mapping) or enqueued
 	  (output) yet.</para>
 	</listitem>
diff --git a/Documentation/DocBook/media_api.tmpl b/Documentation/DocBook/media_api.tmpl
index ab56f89c..4decb46 100644
--- a/Documentation/DocBook/media_api.tmpl
+++ b/Documentation/DocBook/media_api.tmpl
@@ -34,22 +34,20 @@
 
 <book id="media_api">
 <bookinfo>
-<title>LINUX MEDIA INFRASTRUCTURE API</title>
+	<title>LINUX MEDIA INFRASTRUCTURE API</title>
 
-<copyright>
-	<year>2009-2012</year>
-	<holder>LinuxTV Developers</holder>
-</copyright>
+	<copyright>
+		<year>2009-2014</year>
+		<holder>LinuxTV Developers</holder>
+	</copyright>
 
-<legalnotice>
-
-<para>Permission is granted to copy, distribute and/or modify
-this document under the terms of the GNU Free Documentation License,
-Version 1.1 or any later version published by the Free Software
-Foundation. A copy of the license is included in the chapter entitled
-"GNU Free Documentation License"</para>
-</legalnotice>
-
+	<legalnotice>
+		<para>Permission is granted to copy, distribute and/or modify
+		this document under the terms of the GNU Free Documentation License,
+		Version 1.1 or any later version published by the Free Software
+		Foundation. A copy of the license is included in the chapter entitled
+		"GNU Free Documentation License"</para>
+	</legalnotice>
 </bookinfo>
 
 <toc></toc> <!-- autogenerated -->
@@ -60,10 +58,11 @@
 	<para>This document covers the Linux Kernel to Userspace API's used by
 		video and radio streaming devices, including video cameras,
 		analog and digital TV receiver cards, AM/FM receiver cards,
-		streaming capture devices.</para>
+		streaming capture and output devices, codec devices and remote
+		controllers.</para>
 	<para>It is divided into four parts.</para>
-	<para>The first part covers radio, capture,
-		cameras and analog TV devices.</para>
+	<para>The first part covers radio, video capture and output,
+		cameras, analog TV devices and codecs.</para>
 	<para>The second part covers the
 		API used for digital TV and Internet reception via one of the
 		several digital tv standards. While it is called as DVB API,
@@ -75,55 +74,14 @@
 	<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>
-
 </preface>
 
-<part id="v4l2spec">
-&sub-v4l2;
-</part>
-<part id="dvbapi">
-&sub-dvbapi;
-</part>
-<part id="v4ldvb_common">
-<partinfo>
-<authorgroup>
-<author>
-<firstname>Mauro</firstname>
-<surname>Chehab</surname>
-<othername role="mi">Carvalho</othername>
-<affiliation><address><email>mchehab@redhat.com</email></address></affiliation>
-<contrib>Initial version.</contrib>
-</author>
-</authorgroup>
-<copyright>
-	<year>2009-2012</year>
-	<holder>Mauro Carvalho Chehab</holder>
-</copyright>
+<part id="v4l2spec">&sub-v4l2;</part>
+<part id="dvbapi">&sub-dvbapi;</part>
+<part id="remotes">&sub-remote_controllers;</part>
+<part id="media_common">&sub-media-controller;</part>
 
-<revhistory>
-<!-- Put document revisions here, newest first. -->
-<revision>
-<revnumber>1.0.0</revnumber>
-<date>2009-09-06</date>
-<authorinitials>mcc</authorinitials>
-<revremark>Initial revision</revremark>
-</revision>
-</revhistory>
-</partinfo>
-
-<title>Remote Controller API</title>
-<chapter id="remote_controllers">
-&sub-remote_controllers;
-</chapter>
-</part>
-<part id="media_common">
-&sub-media-controller;
-</part>
-
-<chapter id="gen_errors">
-&sub-gen-errors;
-</chapter>
-
+<chapter id="gen_errors">&sub-gen-errors;</chapter>
 
 &sub-fdl-appendix;
 
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index d154147..87b4c5e 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -1494,10 +1494,17 @@
 		 64 = /dev/radio0	Radio device
 		    ...
 		127 = /dev/radio63	Radio device
+		128 = /dev/swradio0	Software Defined Radio device
+		    ...
+		191 = /dev/swradio63	Software Defined Radio device
 		224 = /dev/vbi0		Vertical blank interrupt
 		    ...
 		255 = /dev/vbi31	Vertical blank interrupt
 
+		Minor numbers are allocated dynamically unless
+		CONFIG_VIDEO_FIXED_MINOR_RANGES (default n)
+		configuration option is set.
+
  81 block	I2O hard disk
 		  0 = /dev/i2o/hdq	17th I2O hard disk, whole disk
 		 16 = /dev/i2o/hdr	18th I2O hard disk, whole disk
diff --git a/Documentation/devicetree/bindings/media/img-ir-rev1.txt b/Documentation/devicetree/bindings/media/img-ir-rev1.txt
new file mode 100644
index 0000000..5434ce6
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/img-ir-rev1.txt
@@ -0,0 +1,34 @@
+* ImgTec Infrared (IR) decoder version 1
+
+This binding is for Imagination Technologies' Infrared decoder block,
+specifically major revision 1.
+
+Required properties:
+- compatible:		Should be "img,ir-rev1"
+- reg:			Physical base address of the controller and length of
+			memory mapped region.
+- interrupts:		The interrupt specifier to the cpu.
+
+Optional properties:
+- clocks:		List of clock specifiers as described in standard
+			clock bindings.
+			Up to 3 clocks may be specified in the following order:
+			1st:	Core clock (defaults to 32.768KHz if omitted).
+			2nd:	System side (fast) clock.
+			3rd:	Power modulation clock.
+- clock-names:		List of clock names corresponding to the clocks
+			specified in the clocks property.
+			Accepted clock names are:
+			"core":	Core clock.
+			"sys":	System clock.
+			"mod":	Power modulation clock.
+
+Example:
+
+	ir@02006200 {
+		compatible = "img,ir-rev1";
+		reg = <0x02006200 0x100>;
+		interrupts = <29 4>;
+		clocks = <&clk_32khz>;
+		clock-names =  "core";
+	};
diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware
index 5d5ee4c..d91b8be 100755
--- a/Documentation/dvb/get_dvb_firmware
+++ b/Documentation/dvb/get_dvb_firmware
@@ -28,8 +28,8 @@
 		"opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718",
 		"af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395",
 		"lme2510c_s7395_old", "drxk", "drxk_terratec_h5",
-		"drxk_hauppauge_hvr930c", "tda10071", "it9135", "it9137",
-		"drxk_pctv", "drxk_terratec_htc_stick", "sms1xxx_hcw");
+		"drxk_hauppauge_hvr930c", "tda10071", "it9135", "drxk_pctv",
+		"drxk_terratec_htc_stick", "sms1xxx_hcw");
 
 # Check args
 syntax() if (scalar(@ARGV) != 1);
@@ -727,24 +727,6 @@
 	"$fwfile1 $fwfile2"
 }
 
-sub it9137 {
-    my $url = "http://kworld.server261.com/kworld/CD/ITE_TiVme/V1.00/";
-    my $zipfile = "Driver_V10.323.1.0412.100412.zip";
-    my $hash = "79b597dc648698ed6820845c0c9d0d37";
-    my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 0);
-    my $drvfile = "Driver_V10.323.1.0412.100412/Data/x86/IT9135BDA.sys";
-    my $fwfile = "dvb-usb-it9137-01.fw";
-
-    checkstandard();
-
-    wgetfile($zipfile, $url . $zipfile);
-    verify($zipfile, $hash);
-    unzip($zipfile, $tmpdir);
-    extract("$tmpdir/$drvfile", 69632, 5731, "$fwfile");
-
-    "$fwfile"
-}
-
 sub tda10071 {
     my $sourcefile = "PCTV_460e_reference.zip";
     my $url = "ftp://ftp.pctvsystems.com/TV/driver/PCTV%2070e%2080e%20100e%20320e%20330e%20800e/";
diff --git a/Documentation/dvb/it9137.txt b/Documentation/dvb/it9137.txt
deleted file mode 100644
index 9e6726e..0000000
--- a/Documentation/dvb/it9137.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-To extract firmware for Kworld UB499-2T (id 1b80:e409) you need to copy the
-following file(s) to this directory.
-
-IT9135BDA.sys Dated Mon 22 Mar 2010 02:20:08 GMT
-
-extract using dd
-dd if=IT9135BDA.sys ibs=1 skip=69632 count=5731 of=dvb-usb-it9137-01.fw
-
-copy to default firmware location.
diff --git a/Documentation/edac.txt b/Documentation/edac.txt
index 56c7e93..cb4c2cef 100644
--- a/Documentation/edac.txt
+++ b/Documentation/edac.txt
@@ -6,7 +6,7 @@
 7 Dec 2005
 17 Jul 2007	Updated
 
-(c) Mauro Carvalho Chehab <mchehab@redhat.com>
+(c) Mauro Carvalho Chehab
 05 Aug 2009	Nehalem interface
 
 EDAC is maintained and written by:
diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv
index f144750..2f6e935 100644
--- a/Documentation/video4linux/CARDLIST.bttv
+++ b/Documentation/video4linux/CARDLIST.bttv
@@ -163,3 +163,4 @@
 162 -> Adlink MPG24
 163 -> Bt848 Capture 14MHz
 164 -> CyberVision CV06 (SV)
+165 -> Kworld V-Stream Xpert TV PVR878
diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885
index 9f056d5..fc009d0 100644
--- a/Documentation/video4linux/CARDLIST.cx23885
+++ b/Documentation/video4linux/CARDLIST.cx23885
@@ -31,10 +31,13 @@
  30 -> NetUP Dual DVB-T/C-CI RF                            [1b55:e2e4]
  31 -> Leadtek Winfast PxDVR3200 H XC4000                  [107d:6f39]
  32 -> MPX-885
- 33 -> Mygica X8507                                        [14f1:8502]
+ 33 -> Mygica X8502/X8507 ISDB-T                           [14f1:8502]
  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]
  38 -> Hauppauge WinTV-HVR4400                             [0070:c108,0070:c138,0070:c12a,0070:c1f8]
  39 -> AVerTV Hybrid Express Slim HC81R                    [1461:d939]
+ 40 -> TurboSight TBS 6981                                 [6981:8888]
+ 41 -> TurboSight TBS 6980                                 [6980:8888]
+ 42 -> Leadtek Winfast PxPVR2200                           [107d:6f21]
diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx
index e818644..e085b12 100644
--- a/Documentation/video4linux/CARDLIST.em28xx
+++ b/Documentation/video4linux/CARDLIST.em28xx
@@ -57,6 +57,7 @@
  56 -> Pinnacle Hybrid Pro (330e)               (em2882)        [2304:0226]
  57 -> Kworld PlusTV HD Hybrid 330              (em2883)        [eb1a:a316]
  58 -> Compro VideoMate ForYou/Stereo           (em2820/em2840) [185b:2041]
+ 59 -> Pinnacle PCTV HD Mini                    (em2874)        [2304:023f]
  60 -> Hauppauge WinTV HVR 850                  (em2883)        [2040:651f]
  61 -> Pixelview PlayTV Box 4 USB 2.0           (em2820/em2840)
  62 -> Gadmei TVR200                            (em2820/em2840)
@@ -86,3 +87,8 @@
  86 -> PCTV QuatroStick nano (520e)             (em2884)        [2013:0251]
  87 -> Terratec Cinergy HTC USB XS              (em2884)        [0ccd:008e,0ccd:00ac]
  88 -> C3 Tech Digital Duo HDTV/SDTV USB        (em2884)        [1b80:e755]
+ 89 -> Delock 61959                             (em2874)        [1b80:e1cc]
+ 90 -> KWorld USB ATSC TV Stick UB435-Q V2      (em2874)        [1b80:e346]
+ 91 -> SpeedLink Vicious And Devine Laplace webcam (em2765)        [1ae7:9003,1ae7:9004]
+ 92 -> PCTV DVB-S2 Stick (461e)                 (em28178)
+ 93 -> KWorld USB ATSC TV Stick UB435-Q V3      (em2874)        [1b80:e34c]
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
index 1e6b653..d2ba80b 100644
--- a/Documentation/video4linux/gspca.txt
+++ b/Documentation/video4linux/gspca.txt
@@ -55,6 +55,7 @@
 sonixj		0458:7025	Genius Eye 311Q
 sn9c20x		0458:7029	Genius Look 320s
 sonixj		0458:702e	Genius Slim 310 NB
+sn9c20x		0458:7045	Genius Look 1320 V2
 sn9c20x		0458:704a	Genius Slim 1320
 sn9c20x		0458:704c	Genius i-Look 1321
 sn9c20x		045e:00f4	LifeCam VX-6000 (SN9C20x + OV9650)
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
index 6c4866b..667a433 100644
--- a/Documentation/video4linux/v4l2-framework.txt
+++ b/Documentation/video4linux/v4l2-framework.txt
@@ -34,6 +34,10 @@
 need and this same framework should make it much easier to refactor
 common code into utility functions shared by all drivers.
 
+A good example to look at as a reference is the v4l2-pci-skeleton.c
+source that is available in this directory. It is a skeleton driver for
+a PCI capture card, and demonstrates how to use the V4L2 driver
+framework. It can be used as a template for real PCI video capture driver.
 
 Structure of a driver
 ---------------------
@@ -768,6 +772,7 @@
 VFL_TYPE_GRABBER: videoX for video input/output devices
 VFL_TYPE_VBI: vbiX for vertical blank data (i.e. closed captions, teletext)
 VFL_TYPE_RADIO: radioX for radio tuners
+VFL_TYPE_SDR: swradioX for Software Defined Radio tuners
 
 The last argument gives you a certain amount of control over the device
 device node number used (i.e. the X in videoX). Normally you will pass -1
diff --git a/Documentation/video4linux/v4l2-pci-skeleton.c b/Documentation/video4linux/v4l2-pci-skeleton.c
new file mode 100644
index 0000000..3a1c0d2
--- /dev/null
+++ b/Documentation/video4linux/v4l2-pci-skeleton.c
@@ -0,0 +1,913 @@
+/*
+ * This is a V4L2 PCI Skeleton Driver. It gives an initial skeleton source
+ * for use with other PCI drivers.
+ *
+ * This skeleton PCI driver assumes that the card has an S-Video connector as
+ * input 0 and an HDMI connector as input 1.
+ *
+ * Copyright 2014 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.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kmod.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/videodev2.h>
+#include <linux/v4l2-dv-timings.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-dv-timings.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-dma-contig.h>
+
+MODULE_DESCRIPTION("V4L2 PCI Skeleton Driver");
+MODULE_AUTHOR("Hans Verkuil");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(pci, skeleton_pci_tbl);
+
+/**
+ * struct skeleton - All internal data for one instance of device
+ * @pdev: PCI device
+ * @v4l2_dev: top-level v4l2 device struct
+ * @vdev: video node structure
+ * @ctrl_handler: control handler structure
+ * @lock: ioctl serialization mutex
+ * @std: current SDTV standard
+ * @timings: current HDTV timings
+ * @format: current pix format
+ * @input: current video input (0 = SDTV, 1 = HDTV)
+ * @queue: vb2 video capture queue
+ * @alloc_ctx: vb2 contiguous DMA context
+ * @qlock: spinlock controlling access to buf_list and sequence
+ * @buf_list: list of buffers queued for DMA
+ * @sequence: frame sequence counter
+ */
+struct skeleton {
+	struct pci_dev *pdev;
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	struct v4l2_ctrl_handler ctrl_handler;
+	struct mutex lock;
+	v4l2_std_id std;
+	struct v4l2_dv_timings timings;
+	struct v4l2_pix_format format;
+	unsigned input;
+
+	struct vb2_queue queue;
+	struct vb2_alloc_ctx *alloc_ctx;
+
+	spinlock_t qlock;
+	struct list_head buf_list;
+	unsigned int sequence;
+};
+
+struct skel_buffer {
+	struct vb2_buffer vb;
+	struct list_head list;
+};
+
+static inline struct skel_buffer *to_skel_buffer(struct vb2_buffer *vb2)
+{
+	return container_of(vb2, struct skel_buffer, vb);
+}
+
+static const struct pci_device_id skeleton_pci_tbl[] = {
+	/* { PCI_DEVICE(PCI_VENDOR_ID_, PCI_DEVICE_ID_) }, */
+	{ 0, }
+};
+
+/*
+ * HDTV: this structure has the capabilities of the HDTV receiver.
+ * It is used to constrain the huge list of possible formats based
+ * upon the hardware capabilities.
+ */
+static const struct v4l2_dv_timings_cap skel_timings_cap = {
+	.type = V4L2_DV_BT_656_1120,
+	/* keep this initialization for compatibility with GCC < 4.4.6 */
+	.reserved = { 0 },
+	V4L2_INIT_BT_TIMINGS(
+		720, 1920,		/* min/max width */
+		480, 1080,		/* min/max height */
+		27000000, 74250000,	/* min/max pixelclock*/
+		V4L2_DV_BT_STD_CEA861,	/* Supported standards */
+		/* capabilities */
+		V4L2_DV_BT_CAP_INTERLACED | V4L2_DV_BT_CAP_PROGRESSIVE
+	)
+};
+
+/*
+ * Supported SDTV standards. This does the same job as skel_timings_cap, but
+ * for standard TV formats.
+ */
+#define SKEL_TVNORMS V4L2_STD_ALL
+
+/*
+ * Interrupt handler: typically interrupts happen after a new frame has been
+ * captured. It is the job of the handler to remove the new frame from the
+ * internal list and give it back to the vb2 framework, updating the sequence
+ * counter and timestamp at the same time.
+ */
+static irqreturn_t skeleton_irq(int irq, void *dev_id)
+{
+#ifdef TODO
+	struct skeleton *skel = dev_id;
+
+	/* handle interrupt */
+
+	/* Once a new frame has been captured, mark it as done like this: */
+	if (captured_new_frame) {
+		...
+		spin_lock(&skel->qlock);
+		list_del(&new_buf->list);
+		spin_unlock(&skel->qlock);
+		new_buf->vb.v4l2_buf.sequence = skel->sequence++;
+		v4l2_get_timestamp(&new_buf->vb.v4l2_buf.timestamp);
+		vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_DONE);
+	}
+#endif
+	return IRQ_HANDLED;
+}
+
+/*
+ * Setup the constraints of the queue: besides setting the number of planes
+ * per buffer and the size and allocation context of each plane, it also
+ * checks if sufficient buffers have been allocated. Usually 3 is a good
+ * minimum number: many DMA engines need a minimum of 2 buffers in the
+ * queue and you need to have another available for userspace processing.
+ */
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+		       unsigned int *nbuffers, unsigned int *nplanes,
+		       unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct skeleton *skel = vb2_get_drv_priv(vq);
+
+	if (vq->num_buffers + *nbuffers < 3)
+		*nbuffers = 3 - vq->num_buffers;
+
+	if (fmt && fmt->fmt.pix.sizeimage < skel->format.sizeimage)
+		return -EINVAL;
+	*nplanes = 1;
+	sizes[0] = fmt ? fmt->fmt.pix.sizeimage : skel->format.sizeimage;
+	alloc_ctxs[0] = skel->alloc_ctx;
+	return 0;
+}
+
+/*
+ * Prepare the buffer for queueing to the DMA engine: check and set the
+ * payload size and fill in the field. Note: if the format's field is
+ * V4L2_FIELD_ALTERNATE, then vb->v4l2_buf.field should be set in the
+ * interrupt handler since that's usually where you know if the TOP or
+ * BOTTOM field has been captured.
+ */
+static int buffer_prepare(struct vb2_buffer *vb)
+{
+	struct skeleton *skel = vb2_get_drv_priv(vb->vb2_queue);
+	unsigned long size = skel->format.sizeimage;
+
+	if (vb2_plane_size(vb, 0) < size) {
+		dev_err(&skel->pdev->dev, "buffer too small (%lu < %lu)\n",
+			 vb2_plane_size(vb, 0), size);
+		return -EINVAL;
+	}
+
+	vb2_set_plane_payload(vb, 0, size);
+	vb->v4l2_buf.field = skel->format.field;
+	return 0;
+}
+
+/*
+ * Queue this buffer to the DMA engine.
+ */
+static void buffer_queue(struct vb2_buffer *vb)
+{
+	struct skeleton *skel = vb2_get_drv_priv(vb->vb2_queue);
+	struct skel_buffer *buf = to_skel_buffer(vb);
+	unsigned long flags;
+
+	spin_lock_irqsave(&skel->qlock, flags);
+	list_add_tail(&buf->list, &skel->buf_list);
+
+	/* TODO: Update any DMA pointers if necessary */
+
+	spin_unlock_irqrestore(&skel->qlock, flags);
+}
+
+static void return_all_buffers(struct skeleton *skel,
+			       enum vb2_buffer_state state)
+{
+	struct skel_buffer *buf, *node;
+	unsigned long flags;
+
+	spin_lock_irqsave(&skel->qlock, flags);
+	list_for_each_entry_safe(buf, node, &skel->buf_list, list) {
+		vb2_buffer_done(&buf->vb, state);
+		list_del(&buf->list);
+	}
+	spin_unlock_irqrestore(&skel->qlock, flags);
+}
+
+/*
+ * Start streaming. First check if the minimum number of buffers have been
+ * queued. If not, then return -ENOBUFS and the vb2 framework will call
+ * this function again the next time a buffer has been queued until enough
+ * buffers are available to actually start the DMA engine.
+ */
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct skeleton *skel = vb2_get_drv_priv(vq);
+	int ret = 0;
+
+	skel->sequence = 0;
+
+	/* TODO: start DMA */
+
+	if (ret) {
+		/*
+		 * In case of an error, return all active buffers to the
+		 * QUEUED state
+		 */
+		return_all_buffers(skel, VB2_BUF_STATE_QUEUED);
+	}
+	return ret;
+}
+
+/*
+ * Stop the DMA engine. Any remaining buffers in the DMA queue are dequeued
+ * and passed on to the vb2 framework marked as STATE_ERROR.
+ */
+static int stop_streaming(struct vb2_queue *vq)
+{
+	struct skeleton *skel = vb2_get_drv_priv(vq);
+
+	/* TODO: stop DMA */
+
+	/* Release all active buffers */
+	return_all_buffers(skel, VB2_BUF_STATE_ERROR);
+	return 0;
+}
+
+/*
+ * The vb2 queue ops. Note that since q->lock is set we can use the standard
+ * vb2_ops_wait_prepare/finish helper functions. If q->lock would be NULL,
+ * then this driver would have to provide these ops.
+ */
+static struct vb2_ops skel_qops = {
+	.queue_setup		= queue_setup,
+	.buf_prepare		= buffer_prepare,
+	.buf_queue		= buffer_queue,
+	.start_streaming	= start_streaming,
+	.stop_streaming		= stop_streaming,
+	.wait_prepare		= vb2_ops_wait_prepare,
+	.wait_finish		= vb2_ops_wait_finish,
+};
+
+/*
+ * Required ioctl querycap. Note that the version field is prefilled with
+ * the version of the kernel.
+ */
+static int skeleton_querycap(struct file *file, void *priv,
+			     struct v4l2_capability *cap)
+{
+	struct skeleton *skel = video_drvdata(file);
+
+	strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
+	strlcpy(cap->card, "V4L2 PCI Skeleton", sizeof(cap->card));
+	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
+		 pci_name(skel->pdev));
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
+			   V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+/*
+ * Helper function to check and correct struct v4l2_pix_format. It's used
+ * not only in VIDIOC_TRY/S_FMT, but also elsewhere if changes to the SDTV
+ * standard, HDTV timings or the video input would require updating the
+ * current format.
+ */
+static void skeleton_fill_pix_format(struct skeleton *skel,
+				     struct v4l2_pix_format *pix)
+{
+	pix->pixelformat = V4L2_PIX_FMT_YUYV;
+	if (skel->input == 0) {
+		/* S-Video input */
+		pix->width = 720;
+		pix->height = (skel->std & V4L2_STD_525_60) ? 480 : 576;
+		pix->field = V4L2_FIELD_INTERLACED;
+		pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	} else {
+		/* HDMI input */
+		pix->width = skel->timings.bt.width;
+		pix->height = skel->timings.bt.height;
+		if (skel->timings.bt.interlaced)
+			pix->field = V4L2_FIELD_INTERLACED;
+		else
+			pix->field = V4L2_FIELD_NONE;
+		pix->colorspace = V4L2_COLORSPACE_REC709;
+	}
+
+	/*
+	 * The YUYV format is four bytes for every two pixels, so bytesperline
+	 * is width * 2.
+	 */
+	pix->bytesperline = pix->width * 2;
+	pix->sizeimage = pix->bytesperline * pix->height;
+	pix->priv = 0;
+}
+
+static int skeleton_try_fmt_vid_cap(struct file *file, void *priv,
+				    struct v4l2_format *f)
+{
+	struct skeleton *skel = video_drvdata(file);
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+
+	/*
+	 * Due to historical reasons providing try_fmt with an unsupported
+	 * pixelformat will return -EINVAL for video receivers. Webcam drivers,
+	 * however, will silently correct the pixelformat. Some video capture
+	 * applications rely on this behavior...
+	 */
+	if (pix->pixelformat != V4L2_PIX_FMT_YUYV)
+		return -EINVAL;
+	skeleton_fill_pix_format(skel, pix);
+	return 0;
+}
+
+static int skeleton_s_fmt_vid_cap(struct file *file, void *priv,
+				  struct v4l2_format *f)
+{
+	struct skeleton *skel = video_drvdata(file);
+	int ret;
+
+	ret = skeleton_try_fmt_vid_cap(file, priv, f);
+	if (ret)
+		return ret;
+
+	/*
+	 * It is not allowed to change the format while buffers for use with
+	 * streaming have already been allocated.
+	 */
+	if (vb2_is_busy(&skel->queue))
+		return -EBUSY;
+
+	/* TODO: change format */
+	skel->format = f->fmt.pix;
+	return 0;
+}
+
+static int skeleton_g_fmt_vid_cap(struct file *file, void *priv,
+				  struct v4l2_format *f)
+{
+	struct skeleton *skel = video_drvdata(file);
+
+	f->fmt.pix = skel->format;
+	return 0;
+}
+
+static int skeleton_enum_fmt_vid_cap(struct file *file, void *priv,
+				     struct v4l2_fmtdesc *f)
+{
+	if (f->index != 0)
+		return -EINVAL;
+
+	strlcpy(f->description, "4:2:2, packed, YUYV", sizeof(f->description));
+	f->pixelformat = V4L2_PIX_FMT_YUYV;
+	f->flags = 0;
+	return 0;
+}
+
+static int skeleton_s_std(struct file *file, void *priv, v4l2_std_id std)
+{
+	struct skeleton *skel = video_drvdata(file);
+
+	/* S_STD is not supported on the HDMI input */
+	if (skel->input)
+		return -ENODATA;
+
+	/*
+	 * No change, so just return. Some applications call S_STD again after
+	 * the buffers for streaming have been set up, so we have to allow for
+	 * this behavior.
+	 */
+	if (std == skel->std)
+		return 0;
+
+	/*
+	 * Changing the standard implies a format change, which is not allowed
+	 * while buffers for use with streaming have already been allocated.
+	 */
+	if (vb2_is_busy(&skel->queue))
+		return -EBUSY;
+
+	/* TODO: handle changing std */
+
+	skel->std = std;
+
+	/* Update the internal format */
+	skeleton_fill_pix_format(skel, &skel->format);
+	return 0;
+}
+
+static int skeleton_g_std(struct file *file, void *priv, v4l2_std_id *std)
+{
+	struct skeleton *skel = video_drvdata(file);
+
+	/* G_STD is not supported on the HDMI input */
+	if (skel->input)
+		return -ENODATA;
+
+	*std = skel->std;
+	return 0;
+}
+
+/*
+ * Query the current standard as seen by the hardware. This function shall
+ * never actually change the standard, it just detects and reports.
+ * The framework will initially set *std to tvnorms (i.e. the set of
+ * supported standards by this input), and this function should just AND
+ * this value. If there is no signal, then *std should be set to 0.
+ */
+static int skeleton_querystd(struct file *file, void *priv, v4l2_std_id *std)
+{
+	struct skeleton *skel = video_drvdata(file);
+
+	/* QUERY_STD is not supported on the HDMI input */
+	if (skel->input)
+		return -ENODATA;
+
+#ifdef TODO
+	/*
+	 * Query currently seen standard. Initial value of *std is
+	 * V4L2_STD_ALL. This function should look something like this:
+	 */
+	get_signal_info();
+	if (no_signal) {
+		*std = 0;
+		return 0;
+	}
+	/* Use signal information to reduce the number of possible standards */
+	if (signal_has_525_lines)
+		*std &= V4L2_STD_525_60;
+	else
+		*std &= V4L2_STD_625_50;
+#endif
+	return 0;
+}
+
+static int skeleton_s_dv_timings(struct file *file, void *_fh,
+				 struct v4l2_dv_timings *timings)
+{
+	struct skeleton *skel = video_drvdata(file);
+
+	/* S_DV_TIMINGS is not supported on the S-Video input */
+	if (skel->input == 0)
+		return -ENODATA;
+
+	/* Quick sanity check */
+	if (!v4l2_valid_dv_timings(timings, &skel_timings_cap, NULL, NULL))
+		return -EINVAL;
+
+	/* Check if the timings are part of the CEA-861 timings. */
+	if (!v4l2_find_dv_timings_cap(timings, &skel_timings_cap,
+				      0, NULL, NULL))
+		return -EINVAL;
+
+	/* Return 0 if the new timings are the same as the current timings. */
+	if (v4l2_match_dv_timings(timings, &skel->timings, 0))
+		return 0;
+
+	/*
+	 * Changing the timings implies a format change, which is not allowed
+	 * while buffers for use with streaming have already been allocated.
+	 */
+	if (vb2_is_busy(&skel->queue))
+		return -EBUSY;
+
+	/* TODO: Configure new timings */
+
+	/* Save timings */
+	skel->timings = *timings;
+
+	/* Update the internal format */
+	skeleton_fill_pix_format(skel, &skel->format);
+	return 0;
+}
+
+static int skeleton_g_dv_timings(struct file *file, void *_fh,
+				 struct v4l2_dv_timings *timings)
+{
+	struct skeleton *skel = video_drvdata(file);
+
+	/* G_DV_TIMINGS is not supported on the S-Video input */
+	if (skel->input == 0)
+		return -ENODATA;
+
+	*timings = skel->timings;
+	return 0;
+}
+
+static int skeleton_enum_dv_timings(struct file *file, void *_fh,
+				    struct v4l2_enum_dv_timings *timings)
+{
+	struct skeleton *skel = video_drvdata(file);
+
+	/* ENUM_DV_TIMINGS is not supported on the S-Video input */
+	if (skel->input == 0)
+		return -ENODATA;
+
+	return v4l2_enum_dv_timings_cap(timings, &skel_timings_cap,
+					NULL, NULL);
+}
+
+/*
+ * Query the current timings as seen by the hardware. This function shall
+ * never actually change the timings, it just detects and reports.
+ * If no signal is detected, then return -ENOLINK. If the hardware cannot
+ * lock to the signal, then return -ENOLCK. If the signal is out of range
+ * of the capabilities of the system (e.g., it is possible that the receiver
+ * can lock but that the DMA engine it is connected to cannot handle
+ * pixelclocks above a certain frequency), then -ERANGE is returned.
+ */
+static int skeleton_query_dv_timings(struct file *file, void *_fh,
+				     struct v4l2_dv_timings *timings)
+{
+	struct skeleton *skel = video_drvdata(file);
+
+	/* QUERY_DV_TIMINGS is not supported on the S-Video input */
+	if (skel->input == 0)
+		return -ENODATA;
+
+#ifdef TODO
+	/*
+	 * Query currently seen timings. This function should look
+	 * something like this:
+	 */
+	detect_timings();
+	if (no_signal)
+		return -ENOLINK;
+	if (cannot_lock_to_signal)
+		return -ENOLCK;
+	if (signal_out_of_range_of_capabilities)
+		return -ERANGE;
+
+	/* Useful for debugging */
+	v4l2_print_dv_timings(skel->v4l2_dev.name, "query_dv_timings:",
+			timings, true);
+#endif
+	return 0;
+}
+
+static int skeleton_dv_timings_cap(struct file *file, void *fh,
+				   struct v4l2_dv_timings_cap *cap)
+{
+	struct skeleton *skel = video_drvdata(file);
+
+	/* DV_TIMINGS_CAP is not supported on the S-Video input */
+	if (skel->input == 0)
+		return -ENODATA;
+	*cap = skel_timings_cap;
+	return 0;
+}
+
+static int skeleton_enum_input(struct file *file, void *priv,
+			       struct v4l2_input *i)
+{
+	if (i->index > 1)
+		return -EINVAL;
+
+	i->type = V4L2_INPUT_TYPE_CAMERA;
+	if (i->index == 0) {
+		i->std = SKEL_TVNORMS;
+		strlcpy(i->name, "S-Video", sizeof(i->name));
+		i->capabilities = V4L2_IN_CAP_STD;
+	} else {
+		i->std = 0;
+		strlcpy(i->name, "HDMI", sizeof(i->name));
+		i->capabilities = V4L2_IN_CAP_DV_TIMINGS;
+	}
+	return 0;
+}
+
+static int skeleton_s_input(struct file *file, void *priv, unsigned int i)
+{
+	struct skeleton *skel = video_drvdata(file);
+
+	if (i > 1)
+		return -EINVAL;
+
+	/*
+	 * Changing the input implies a format change, which is not allowed
+	 * while buffers for use with streaming have already been allocated.
+	 */
+	if (vb2_is_busy(&skel->queue))
+		return -EBUSY;
+
+	skel->input = i;
+	/*
+	 * Update tvnorms. The tvnorms value is used by the core to implement
+	 * VIDIOC_ENUMSTD so it has to be correct. If tvnorms == 0, then
+	 * ENUMSTD will return -ENODATA.
+	 */
+	skel->vdev.tvnorms = i ? 0 : SKEL_TVNORMS;
+
+	/* Update the internal format */
+	skeleton_fill_pix_format(skel, &skel->format);
+	return 0;
+}
+
+static int skeleton_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	struct skeleton *skel = video_drvdata(file);
+
+	*i = skel->input;
+	return 0;
+}
+
+/* The control handler. */
+static int skeleton_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	/*struct skeleton *skel =
+		container_of(ctrl->handler, struct skeleton, ctrl_handler);*/
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		/* TODO: set brightness to ctrl->val */
+		break;
+	case V4L2_CID_CONTRAST:
+		/* TODO: set contrast to ctrl->val */
+		break;
+	case V4L2_CID_SATURATION:
+		/* TODO: set saturation to ctrl->val */
+		break;
+	case V4L2_CID_HUE:
+		/* TODO: set hue to ctrl->val */
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* ------------------------------------------------------------------
+	File operations for the device
+   ------------------------------------------------------------------*/
+
+static const struct v4l2_ctrl_ops skel_ctrl_ops = {
+	.s_ctrl = skeleton_s_ctrl,
+};
+
+/*
+ * The set of all supported ioctls. Note that all the streaming ioctls
+ * use the vb2 helper functions that take care of all the locking and
+ * that also do ownership tracking (i.e. only the filehandle that requested
+ * the buffers can call the streaming ioctls, all other filehandles will
+ * receive -EBUSY if they attempt to call the same streaming ioctls).
+ *
+ * The last three ioctls also use standard helper functions: these implement
+ * standard behavior for drivers with controls.
+ */
+static const struct v4l2_ioctl_ops skel_ioctl_ops = {
+	.vidioc_querycap = skeleton_querycap,
+	.vidioc_try_fmt_vid_cap = skeleton_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap = skeleton_s_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap = skeleton_g_fmt_vid_cap,
+	.vidioc_enum_fmt_vid_cap = skeleton_enum_fmt_vid_cap,
+
+	.vidioc_g_std = skeleton_g_std,
+	.vidioc_s_std = skeleton_s_std,
+	.vidioc_querystd = skeleton_querystd,
+
+	.vidioc_s_dv_timings = skeleton_s_dv_timings,
+	.vidioc_g_dv_timings = skeleton_g_dv_timings,
+	.vidioc_enum_dv_timings = skeleton_enum_dv_timings,
+	.vidioc_query_dv_timings = skeleton_query_dv_timings,
+	.vidioc_dv_timings_cap = skeleton_dv_timings_cap,
+
+	.vidioc_enum_input = skeleton_enum_input,
+	.vidioc_g_input = skeleton_g_input,
+	.vidioc_s_input = skeleton_s_input,
+
+	.vidioc_reqbufs = vb2_ioctl_reqbufs,
+	.vidioc_create_bufs = vb2_ioctl_create_bufs,
+	.vidioc_querybuf = vb2_ioctl_querybuf,
+	.vidioc_qbuf = vb2_ioctl_qbuf,
+	.vidioc_dqbuf = vb2_ioctl_dqbuf,
+	.vidioc_expbuf = vb2_ioctl_expbuf,
+	.vidioc_streamon = vb2_ioctl_streamon,
+	.vidioc_streamoff = vb2_ioctl_streamoff,
+
+	.vidioc_log_status = v4l2_ctrl_log_status,
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+/*
+ * The set of file operations. Note that all these ops are standard core
+ * helper functions.
+ */
+static const struct v4l2_file_operations skel_fops = {
+	.owner = THIS_MODULE,
+	.open = v4l2_fh_open,
+	.release = vb2_fop_release,
+	.unlocked_ioctl = video_ioctl2,
+	.read = vb2_fop_read,
+	.mmap = vb2_fop_mmap,
+	.poll = vb2_fop_poll,
+};
+
+/*
+ * The initial setup of this device instance. Note that the initial state of
+ * the driver should be complete. So the initial format, standard, timings
+ * and video input should all be initialized to some reasonable value.
+ */
+static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	/* The initial timings are chosen to be 720p60. */
+	static const struct v4l2_dv_timings timings_def =
+		V4L2_DV_BT_CEA_1280X720P60;
+	struct skeleton *skel;
+	struct video_device *vdev;
+	struct v4l2_ctrl_handler *hdl;
+	struct vb2_queue *q;
+	int ret;
+
+	/* Enable PCI */
+	ret = pci_enable_device(pdev);
+	if (ret)
+		return ret;
+	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (ret) {
+		dev_err(&pdev->dev, "no suitable DMA available.\n");
+		goto disable_pci;
+	}
+
+	/* Allocate a new instance */
+	skel = devm_kzalloc(&pdev->dev, sizeof(struct skeleton), GFP_KERNEL);
+	if (!skel)
+		return -ENOMEM;
+
+	/* Allocate the interrupt */
+	ret = devm_request_irq(&pdev->dev, pdev->irq,
+			       skeleton_irq, 0, KBUILD_MODNAME, skel);
+	if (ret) {
+		dev_err(&pdev->dev, "request_irq failed\n");
+		goto disable_pci;
+	}
+	skel->pdev = pdev;
+
+	/* Fill in the initial format-related settings */
+	skel->timings = timings_def;
+	skel->std = V4L2_STD_625_50;
+	skeleton_fill_pix_format(skel, &skel->format);
+
+	/* Initialize the top-level structure */
+	ret = v4l2_device_register(&pdev->dev, &skel->v4l2_dev);
+	if (ret)
+		goto disable_pci;
+
+	mutex_init(&skel->lock);
+
+	/* Add the controls */
+	hdl = &skel->ctrl_handler;
+	v4l2_ctrl_handler_init(hdl, 4);
+	v4l2_ctrl_new_std(hdl, &skel_ctrl_ops,
+			  V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
+	v4l2_ctrl_new_std(hdl, &skel_ctrl_ops,
+			  V4L2_CID_CONTRAST, 0, 255, 1, 16);
+	v4l2_ctrl_new_std(hdl, &skel_ctrl_ops,
+			  V4L2_CID_SATURATION, 0, 255, 1, 127);
+	v4l2_ctrl_new_std(hdl, &skel_ctrl_ops,
+			  V4L2_CID_HUE, -128, 127, 1, 0);
+	if (hdl->error) {
+		ret = hdl->error;
+		goto free_hdl;
+	}
+	skel->v4l2_dev.ctrl_handler = hdl;
+
+	/* Initialize the vb2 queue */
+	q = &skel->queue;
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
+	q->drv_priv = skel;
+	q->buf_struct_size = sizeof(struct skel_buffer);
+	q->ops = &skel_qops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	/*
+	 * Assume that this DMA engine needs to have at least two buffers
+	 * available before it can be started. The start_streaming() op
+	 * won't be called until at least this many buffers are queued up.
+	 */
+	q->min_buffers_needed = 2;
+	/*
+	 * The serialization lock for the streaming ioctls. This is the same
+	 * as the main serialization lock, but if some of the non-streaming
+	 * ioctls could take a long time to execute, then you might want to
+	 * have a different lock here to prevent VIDIOC_DQBUF from being
+	 * blocked while waiting for another action to finish. This is
+	 * generally not needed for PCI devices, but USB devices usually do
+	 * want a separate lock here.
+	 */
+	q->lock = &skel->lock;
+	/*
+	 * Since this driver can only do 32-bit DMA we must make sure that
+	 * the vb2 core will allocate the buffers in 32-bit DMA memory.
+	 */
+	q->gfp_flags = GFP_DMA32;
+	ret = vb2_queue_init(q);
+	if (ret)
+		goto free_hdl;
+
+	skel->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	if (IS_ERR(skel->alloc_ctx)) {
+		dev_err(&pdev->dev, "Can't allocate buffer context");
+		ret = PTR_ERR(skel->alloc_ctx);
+		goto free_hdl;
+	}
+	INIT_LIST_HEAD(&skel->buf_list);
+	spin_lock_init(&skel->qlock);
+
+	/* Initialize the video_device structure */
+	vdev = &skel->vdev;
+	strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name));
+	/*
+	 * There is nothing to clean up, so release is set to an empty release
+	 * function. The release callback must be non-NULL.
+	 */
+	vdev->release = video_device_release_empty;
+	vdev->fops = &skel_fops,
+	vdev->ioctl_ops = &skel_ioctl_ops,
+	/*
+	 * The main serialization lock. All ioctls are serialized by this
+	 * lock. Exception: if q->lock is set, then the streaming ioctls
+	 * are serialized by that separate lock.
+	 */
+	vdev->lock = &skel->lock;
+	vdev->queue = q;
+	vdev->v4l2_dev = &skel->v4l2_dev;
+	/* Supported SDTV standards, if any */
+	vdev->tvnorms = SKEL_TVNORMS;
+	/* If this bit is set, then the v4l2 core will provide the support
+	 * for the VIDIOC_G/S_PRIORITY ioctls. This flag will eventually
+	 * go away once all drivers have been converted to use struct v4l2_fh.
+	 */
+	set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
+	video_set_drvdata(vdev, skel);
+
+	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+	if (ret)
+		goto free_ctx;
+
+	dev_info(&pdev->dev, "V4L2 PCI Skeleton Driver loaded\n");
+	return 0;
+
+free_ctx:
+	vb2_dma_contig_cleanup_ctx(skel->alloc_ctx);
+free_hdl:
+	v4l2_ctrl_handler_free(&skel->ctrl_handler);
+	v4l2_device_unregister(&skel->v4l2_dev);
+disable_pci:
+	pci_disable_device(pdev);
+	return ret;
+}
+
+static void skeleton_remove(struct pci_dev *pdev)
+{
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
+	struct skeleton *skel = container_of(v4l2_dev, struct skeleton, v4l2_dev);
+
+	video_unregister_device(&skel->vdev);
+	v4l2_ctrl_handler_free(&skel->ctrl_handler);
+	vb2_dma_contig_cleanup_ctx(skel->alloc_ctx);
+	v4l2_device_unregister(&skel->v4l2_dev);
+	pci_disable_device(skel->pdev);
+}
+
+static struct pci_driver skeleton_driver = {
+	.name = KBUILD_MODNAME,
+	.probe = skeleton_probe,
+	.remove = skeleton_remove,
+	.id_table = skeleton_pci_tbl,
+};
+
+module_pci_driver(skeleton_driver);
diff --git a/MAINTAINERS b/MAINTAINERS
index 9eeeddf..8774f79 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4860,22 +4860,6 @@
 F:	drivers/hwmon/it87.c
 
 IT913X MEDIA DRIVER
-M:	Malcolm Priestley <tvboxspy@gmail.com>
-L:	linux-media@vger.kernel.org
-W:	http://linuxtv.org/
-Q:	http://patchwork.linuxtv.org/project/linux-media/list/
-S:	Maintained
-F:	drivers/media/usb/dvb-usb-v2/it913x*
-
-IT913X FE MEDIA DRIVER
-M:	Malcolm Priestley <tvboxspy@gmail.com>
-L:	linux-media@vger.kernel.org
-W:	http://linuxtv.org/
-Q:	http://patchwork.linuxtv.org/project/linux-media/list/
-S:	Maintained
-F:	drivers/media/dvb-frontends/it913x-fe*
-
-IT913X MEDIA DRIVER
 M:	Antti Palosaari <crope@iki.fi>
 L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org/
@@ -5855,6 +5839,26 @@
 S:	Supported
 F:	drivers/platform/x86/msi-wmi.c
 
+MSI001 MEDIA DRIVER
+M:	Antti Palosaari <crope@iki.fi>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org/
+W:	http://palosaari.fi/linux/
+Q:	http://patchwork.linuxtv.org/project/linux-media/list/
+T:	git git://linuxtv.org/anttip/media_tree.git
+S:	Maintained
+F:	drivers/staging/media/msi3101/msi001*
+
+MSI3101 MEDIA DRIVER
+M:	Antti Palosaari <crope@iki.fi>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org/
+W:	http://palosaari.fi/linux/
+Q:	http://patchwork.linuxtv.org/project/linux-media/list/
+T:	git git://linuxtv.org/anttip/media_tree.git
+S:	Maintained
+F:	drivers/staging/media/msi3101/sdr-msi3101*
+
 MT9M032 APTINA SENSOR DRIVER
 M:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 L:	linux-media@vger.kernel.org
@@ -7422,6 +7426,16 @@
 S:	Maintained
 F:	drivers/media/dvb-frontends/rtl2832*
 
+RTL2832_SDR MEDIA DRIVER
+M:	Antti Palosaari <crope@iki.fi>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org/
+W:	http://palosaari.fi/linux/
+Q:	http://patchwork.linuxtv.org/project/linux-media/list/
+T:	git git://linuxtv.org/anttip/media_tree.git
+S:	Maintained
+F:	drivers/staging/media/rtl2832u_sdr/rtl2832_sdr*
+
 RTL8180 WIRELESS DRIVER
 M:	"John W. Linville" <linville@tuxdriver.com>
 L:	linux-wireless@vger.kernel.org
@@ -7954,15 +7968,13 @@
 F:	drivers/media/mmc/siano/
 
 SH_VEU V4L2 MEM2MEM DRIVER
-M:	Guennadi Liakhovetski <g.liakhovetski@gmx.de>
 L:	linux-media@vger.kernel.org
-S:	Maintained
+S:	Orphan
 F:	drivers/media/platform/sh_veu.c
 
 SH_VOU V4L2 OUTPUT DRIVER
-M:	Guennadi Liakhovetski <g.liakhovetski@gmx.de>
 L:	linux-media@vger.kernel.org
-S:	Odd Fixes
+S:	Orphan
 F:	drivers/media/platform/sh_vou.c
 F:	include/media/sh_vou.h
 
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 8dd0ec8..018353d 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -16,6 +16,8 @@
  *
  */
 
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -542,8 +544,22 @@
 	.subdevs = cm_t35_isp_subdevs,
 };
 
+static struct regulator_consumer_supply cm_t35_camera_supplies[] = {
+	REGULATOR_SUPPLY("vaa", "3-005d"),
+	REGULATOR_SUPPLY("vdd", "3-005d"),
+};
+
 static void __init cm_t35_init_camera(void)
 {
+	struct clk *clk;
+
+	clk = clk_register_fixed_rate(NULL, "mt9t001-clkin", NULL, CLK_IS_ROOT,
+				      48000000);
+	clk_register_clkdev(clk, NULL, "3-005d");
+
+	regulator_register_fixed(2, cm_t35_camera_supplies,
+				 ARRAY_SIZE(cm_t35_camera_supplies));
+
 	if (omap3_init_camera(&cm_t35_isp_pdata) < 0)
 		pr_warn("CM-T3x: Failed registering camera device!\n");
 }
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index b335c6a..01fae82 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -7,7 +7,7 @@
  *
  * Written Doug Thompson <norsk5@xmission.com> www.softwarebitmaker.com
  *
- * (c) 2012-2013 - Mauro Carvalho Chehab <mchehab@redhat.com>
+ * (c) 2012-2013 - Mauro Carvalho Chehab
  *	The entire API were re-written, and ported to use struct device
  *
  */
diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
index d5a98a4..8399b4e 100644
--- a/drivers/edac/ghes_edac.c
+++ b/drivers/edac/ghes_edac.c
@@ -4,7 +4,7 @@
  * This file may be distributed under the terms of the GNU General Public
  * License version 2.
  *
- * Copyright (c) 2013 by Mauro Carvalho Chehab <mchehab@redhat.com>
+ * Copyright (c) 2013 by Mauro Carvalho Chehab
  *
  * Red Hat Inc. http://www.redhat.com
  */
diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c
index 5381e98..6ef6ad1 100644
--- a/drivers/edac/i5400_edac.c
+++ b/drivers/edac/i5400_edac.c
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 2008 by:
  *	 Ben Woodard <woodard@redhat.com>
- *	 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *	 Mauro Carvalho Chehab
  *
  * Red Hat Inc. http://www.redhat.com
  *
@@ -1469,7 +1469,7 @@
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ben Woodard <woodard@redhat.com>");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Mauro Carvalho Chehab");
 MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
 MODULE_DESCRIPTION("MC Driver for Intel I5400 memory controllers - "
 		   I5400_REVISION);
diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c
index 57e96a3..dcac982 100644
--- a/drivers/edac/i7300_edac.c
+++ b/drivers/edac/i7300_edac.c
@@ -5,7 +5,7 @@
  * GNU General Public License version 2 only.
  *
  * Copyright (c) 2010 by:
- *	 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *	 Mauro Carvalho Chehab
  *
  * Red Hat Inc. http://www.redhat.com
  *
@@ -1209,7 +1209,7 @@
 module_exit(i7300_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Mauro Carvalho Chehab");
 MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
 MODULE_DESCRIPTION("MC Driver for Intel I7300 memory controllers - "
 		   I7300_REVISION);
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 8bc83b9..9cd0b30 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -9,7 +9,7 @@
  * GNU General Public License version 2 only.
  *
  * Copyright (c) 2009-2010 by:
- *	 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *	 Mauro Carvalho Chehab
  *
  * Red Hat Inc. http://www.redhat.com
  *
@@ -2457,7 +2457,7 @@
 module_exit(i7core_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Mauro Carvalho Chehab");
 MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
 MODULE_DESCRIPTION("MC Driver for Intel i7 Core memory controllers - "
 		   I7CORE_REVISION);
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index c460ba5..deea0dc 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -7,7 +7,7 @@
  * GNU General Public License version 2 only.
  *
  * Copyright (c) 2011 by:
- *	 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *	 Mauro Carvalho Chehab
  */
 
 #include <linux/module.h>
@@ -2183,7 +2183,7 @@
 MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Mauro Carvalho Chehab");
 MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
 MODULE_DESCRIPTION("MC Driver for Intel Sandy Bridge and Ivy Bridge memory controllers - "
 		   SBRIDGE_REVISION);
diff --git a/drivers/hid/hid-picolcd_cir.c b/drivers/hid/hid-picolcd_cir.c
index 59d5eb1..cf1a9f1 100644
--- a/drivers/hid/hid-picolcd_cir.c
+++ b/drivers/hid/hid-picolcd_cir.c
@@ -114,7 +114,7 @@
 
 	rdev->priv             = data;
 	rdev->driver_type      = RC_DRIVER_IR_RAW;
-	rdev->allowed_protos   = RC_BIT_ALL;
+	rc_set_allowed_protocols(rdev, RC_BIT_ALL);
 	rdev->open             = picolcd_cir_open;
 	rdev->close            = picolcd_cir_close;
 	rdev->input_name       = data->hdev->name;
diff --git a/drivers/media/common/siano/smsdvb-debugfs.c b/drivers/media/common/siano/smsdvb-debugfs.c
index 0bb4430..2408d7e 100644
--- a/drivers/media/common/siano/smsdvb-debugfs.c
+++ b/drivers/media/common/siano/smsdvb-debugfs.c
@@ -1,6 +1,6 @@
 /***********************************************************************
  *
- * Copyright(c) 2013 Mauro Carvalho Chehab <mchehab@redhat.com>
+ * Copyright(c) 2013 Mauro Carvalho Chehab
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/media/common/siano/smsir.c b/drivers/media/common/siano/smsir.c
index b8c5cad..6d7c0c8 100644
--- a/drivers/media/common/siano/smsir.c
+++ b/drivers/media/common/siano/smsir.c
@@ -88,7 +88,7 @@
 
 	dev->priv = coredev;
 	dev->driver_type = RC_DRIVER_IR_RAW;
-	dev->allowed_protos = RC_BIT_ALL;
+	rc_set_allowed_protocols(dev, RC_BIT_ALL);
 	dev->map_name = sms_get_board(board_id)->rc_codes;
 	dev->driver_name = MODULE_NAME;
 
diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h
index f19a2cc..1bdc0e7 100644
--- a/drivers/media/dvb-core/dvb-usb-ids.h
+++ b/drivers/media/dvb-core/dvb-usb-ids.h
@@ -257,6 +257,7 @@
 #define USB_PID_TERRATEC_T5				0x10a1
 #define USB_PID_NOXON_DAB_STICK				0x00b3
 #define USB_PID_NOXON_DAB_STICK_REV2			0x00e0
+#define USB_PID_NOXON_DAB_STICK_REV3			0x00b4
 #define USB_PID_PINNACLE_EXPRESSCARD_320CX		0x022e
 #define USB_PID_PINNACLE_PCTV2000E			0x022c
 #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH		0x0228
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index 1f925e8..6ce435a 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -1279,7 +1279,7 @@
 	switch(tvp->cmd) {
 	case DTV_ENUM_DELSYS:
 		ncaps = 0;
-		while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+		while (ncaps < MAX_DELSYS && fe->ops.delsys[ncaps]) {
 			tvp->u.buffer.data[ncaps] = fe->ops.delsys[ncaps];
 			ncaps++;
 		}
@@ -1596,7 +1596,7 @@
 	 * supported
 	 */
 	ncaps = 0;
-	while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+	while (ncaps < MAX_DELSYS && fe->ops.delsys[ncaps]) {
 		if (fe->ops.delsys[ncaps] == desired_system) {
 			c->delivery_system = desired_system;
 			dev_dbg(fe->dvb->device,
@@ -1628,7 +1628,7 @@
 	* of the desired system
 	*/
 	ncaps = 0;
-	while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+	while (ncaps < MAX_DELSYS && fe->ops.delsys[ncaps]) {
 		if (dvbv3_type(fe->ops.delsys[ncaps]) == type)
 			delsys = fe->ops.delsys[ncaps];
 		ncaps++;
@@ -1703,7 +1703,7 @@
 	 * DVBv3 standard
 	 */
 	ncaps = 0;
-	while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+	while (ncaps < MAX_DELSYS && fe->ops.delsys[ncaps]) {
 		if (dvbv3_type(fe->ops.delsys[ncaps]) != DVBV3_UNKNOWN) {
 			delsys = fe->ops.delsys[ncaps];
 			break;
@@ -1882,6 +1882,8 @@
 		c->lna = tvp->u.data;
 		if (fe->ops.set_lna)
 			r = fe->ops.set_lna(fe);
+		if (r < 0)
+			c->lna = LNA_AUTO;
 		break;
 
 	default:
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index dd12a1e..025fc54 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -441,7 +441,7 @@
 
 config DVB_RTL2832
 	tristate "Realtek RTL2832 DVB-T"
-	depends on DVB_CORE && I2C
+	depends on DVB_CORE && I2C && I2C_MUX
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
 	  Say Y when you want to support this frontend.
@@ -650,6 +650,8 @@
 comment "SEC control devices for DVB-S"
 	depends on DVB_CORE
 
+source "drivers/media/dvb-frontends/drx39xyj/Kconfig"
+
 config DVB_LNBP21
 	tristate "LNBP21/LNBH24 SEC controllers"
 	depends on DVB_CORE && I2C
@@ -733,14 +735,6 @@
 	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
diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
index 0c75a6a..282aba2 100644
--- a/drivers/media/dvb-frontends/Makefile
+++ b/drivers/media/dvb-frontends/Makefile
@@ -92,13 +92,13 @@
 obj-$(CONFIG_DVB_DS3000) += ds3000.o
 obj-$(CONFIG_DVB_TS2020) += ts2020.o
 obj-$(CONFIG_DVB_MB86A16) += mb86a16.o
+obj-$(CONFIG_DVB_DRX39XYJ) += drx39xyj/
 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
diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c
index 65728c2..be4bec2 100644
--- a/drivers/media/dvb-frontends/af9033.c
+++ b/drivers/media/dvb-frontends/af9033.c
@@ -989,10 +989,62 @@
 	return ret;
 }
 
+static int af9033_pid_filter_ctrl(struct dvb_frontend *fe, int onoff)
+{
+	struct af9033_state *state = fe->demodulator_priv;
+	int ret;
+
+	dev_dbg(&state->i2c->dev, "%s: onoff=%d\n", __func__, onoff);
+
+	ret = af9033_wr_reg_mask(state, 0x80f993, onoff, 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_pid_filter(struct dvb_frontend *fe, int index, u16 pid, int onoff)
+{
+	struct af9033_state *state = fe->demodulator_priv;
+	int ret;
+	u8 wbuf[2] = {(pid >> 0) & 0xff, (pid >> 8) & 0xff};
+
+	dev_dbg(&state->i2c->dev, "%s: index=%d pid=%04x onoff=%d\n",
+			__func__, index, pid, onoff);
+
+	if (pid > 0x1fff)
+		return 0;
+
+	ret = af9033_wr_regs(state, 0x80f996, wbuf, 2);
+	if (ret < 0)
+		goto err;
+
+	ret = af9033_wr_reg(state, 0x80f994, onoff);
+	if (ret < 0)
+		goto err;
+
+	ret = af9033_wr_reg(state, 0x80f995, index);
+	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)
+				   struct i2c_adapter *i2c,
+				   struct af9033_ops *ops)
 {
 	int ret;
 	struct af9033_state *state;
@@ -1067,6 +1119,11 @@
 	memcpy(&state->fe.ops, &af9033_ops, sizeof(struct dvb_frontend_ops));
 	state->fe.demodulator_priv = state;
 
+	if (ops) {
+		ops->pid_filter = af9033_pid_filter;
+		ops->pid_filter_ctrl = af9033_pid_filter_ctrl;
+	}
+
 	return &state->fe;
 
 err:
diff --git a/drivers/media/dvb-frontends/af9033.h b/drivers/media/dvb-frontends/af9033.h
index c286e8f..539f4db 100644
--- a/drivers/media/dvb-frontends/af9033.h
+++ b/drivers/media/dvb-frontends/af9033.h
@@ -78,16 +78,42 @@
 };
 
 
+struct af9033_ops {
+	int (*pid_filter_ctrl)(struct dvb_frontend *fe, int onoff);
+	int (*pid_filter)(struct dvb_frontend *fe, int index, u16 pid,
+			  int onoff);
+};
+
+
 #if IS_ENABLED(CONFIG_DVB_AF9033)
-extern struct dvb_frontend *af9033_attach(const struct af9033_config *config,
-	struct i2c_adapter *i2c);
+extern
+struct dvb_frontend *af9033_attach(const struct af9033_config *config,
+				   struct i2c_adapter *i2c,
+				   struct af9033_ops *ops);
+
 #else
-static inline struct dvb_frontend *af9033_attach(
-	const struct af9033_config *config, struct i2c_adapter *i2c)
+static inline
+struct dvb_frontend *af9033_attach(const struct af9033_config *config,
+				   struct i2c_adapter *i2c,
+				   struct af9033_ops *ops)
 {
 	pr_warn("%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 }
+
+static inline int af9033_pid_filter_ctrl(struct dvb_frontend *fe, int onoff)
+{
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int af9033_pid_filter(struct dvb_frontend *fe, int index, u16 pid,
+	int onoff)
+{
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
 #endif
 
 #endif /* AF9033_H */
diff --git a/drivers/media/dvb-frontends/drx39xyj/Kconfig b/drivers/media/dvb-frontends/drx39xyj/Kconfig
new file mode 100644
index 0000000..15628eb
--- /dev/null
+++ b/drivers/media/dvb-frontends/drx39xyj/Kconfig
@@ -0,0 +1,7 @@
+config DVB_DRX39XYJ
+	tristate "Micronas DRX-J demodulator"
+	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.
diff --git a/drivers/media/dvb-frontends/drx39xyj/Makefile b/drivers/media/dvb-frontends/drx39xyj/Makefile
new file mode 100644
index 0000000..672e077
--- /dev/null
+++ b/drivers/media/dvb-frontends/drx39xyj/Makefile
@@ -0,0 +1,6 @@
+drx39xyj-objs := drxj.o
+
+obj-$(CONFIG_DVB_DRX39XYJ) += drx39xyj.o
+
+ccflags-y += -I$(srctree)/drivers/media/dvb-core/
+ccflags-y += -I$(srctree)/drivers/media/tuners/
diff --git a/drivers/media/dvb-frontends/drx39xyj/bsp_i2c.h b/drivers/media/dvb-frontends/drx39xyj/bsp_i2c.h
new file mode 100644
index 0000000..5b5421f
--- /dev/null
+++ b/drivers/media/dvb-frontends/drx39xyj/bsp_i2c.h
@@ -0,0 +1,139 @@
+/*
+  I2C API, implementation depends on board specifics
+
+  Copyright (c), 2004-2005,2007-2010 Trident Microsystems, Inc.
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+	and/or other materials provided with the distribution.
+  * Neither the name of Trident Microsystems nor Hauppauge Computer Works
+    nor the names of its contributors may be used to endorse or promote
+	products derived from this software without specific prior written
+	permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+  This module encapsulates I2C access.In some applications several devices
+  share one I2C bus. If these devices have the same I2C address some kind
+  off "switch" must be implemented to ensure error free communication with
+  one device.  In case such a "switch" is used, the device ID can be used
+  to implement control over this "switch".
+*/
+
+#ifndef __BSPI2C_H__
+#define __BSPI2C_H__
+
+#include "bsp_types.h"
+
+/*
+ * This structure contains the I2C address, the device ID and a user_data pointer.
+ * The user_data pointer can be used for application specific purposes.
+ */
+struct i2c_device_addr {
+	u16 i2c_addr;		/* The I2C address of the device. */
+	u16 i2c_dev_id;		/* The device identifier. */
+	void *user_data;		/* User data pointer */
+};
+
+
+/**
+* \def IS_I2C_10BIT( addr )
+* \brief Determine if I2C address 'addr' is a 10 bits address or not.
+* \param addr The I2C address.
+* \return int.
+* \retval 0 if address is not a 10 bits I2C address.
+* \retval 1 if address is a 10 bits I2C address.
+*/
+#define IS_I2C_10BIT(addr) \
+	 (((addr) & 0xF8) == 0xF0)
+
+/*------------------------------------------------------------------------------
+Exported FUNCTIONS
+------------------------------------------------------------------------------*/
+
+/**
+* \fn drxbsp_i2c_init()
+* \brief Initialize I2C communication module.
+* \return drx_status_t Return status.
+* \retval 0 Initialization successful.
+* \retval -EIO Initialization failed.
+*/
+	drx_status_t drxbsp_i2c_init(void);
+
+/**
+* \fn drxbsp_i2c_term()
+* \brief Terminate I2C communication module.
+* \return drx_status_t Return status.
+* \retval 0 Termination successful.
+* \retval -EIO Termination failed.
+*/
+	drx_status_t drxbsp_i2c_term(void);
+
+/**
+* \fn drx_status_t drxbsp_i2c_write_read( struct i2c_device_addr *w_dev_addr,
+*                                       u16 w_count,
+*                                       u8 *wData,
+*                                       struct i2c_device_addr *r_dev_addr,
+*                                       u16 r_count,
+*                                       u8 *r_data)
+* \brief Read and/or write count bytes from I2C bus, store them in data[].
+* \param w_dev_addr The device i2c address and the device ID to write to
+* \param w_count   The number of bytes to write
+* \param wData    The array to write the data to
+* \param r_dev_addr The device i2c address and the device ID to read from
+* \param r_count   The number of bytes to read
+* \param r_data    The array to read the data from
+* \return drx_status_t Return status.
+* \retval 0 Succes.
+* \retval -EIO Failure.
+* \retval -EINVAL Parameter 'wcount' is not zero but parameter
+*                                       'wdata' contains NULL.
+*                                       Idem for 'rcount' and 'rdata'.
+*                                       Both w_dev_addr and r_dev_addr are NULL.
+*
+* This function must implement an atomic write and/or read action on the I2C bus
+* No other process may use the I2C bus when this function is executing.
+* The critical section of this function runs from and including the I2C
+* write, up to and including the I2C read action.
+*
+* The device ID can be useful if several devices share an I2C address.
+* It can be used to control a "switch" on the I2C bus to the correct device.
+*/
+	drx_status_t drxbsp_i2c_write_read(struct i2c_device_addr *w_dev_addr,
+					 u16 w_count,
+					 u8 *w_data,
+					 struct i2c_device_addr *r_dev_addr,
+					 u16 r_count, u8 *r_data);
+
+/**
+* \fn drxbsp_i2c_error_text()
+* \brief Returns a human readable error.
+* Counter part of numerical drx_i2c_error_g.
+*
+* \return char* Pointer to human readable error text.
+*/
+	char *drxbsp_i2c_error_text(void);
+
+/**
+* \var drx_i2c_error_g;
+* \brief I2C specific error codes, platform dependent.
+*/
+	extern int drx_i2c_error_g;
+
+#endif				/* __BSPI2C_H__ */
diff --git a/drivers/media/dvb-frontends/drx39xyj/drx39xxj.h b/drivers/media/dvb-frontends/drx39xyj/drx39xxj.h
new file mode 100644
index 0000000..cfd0b96
--- /dev/null
+++ b/drivers/media/dvb-frontends/drx39xyj/drx39xxj.h
@@ -0,0 +1,45 @@
+/*
+ *  Driver for Micronas DRX39xx family (drx3933j)
+ *
+ *  Written by Devin Heitmueller <devin.heitmueller@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 DRX39XXJ_H
+#define DRX39XXJ_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+#include "drx_driver.h"
+
+struct drx39xxj_state {
+	struct i2c_adapter *i2c;
+	struct drx_demod_instance *demod;
+	struct dvb_frontend frontend;
+	unsigned int i2c_gate_open:1;
+	const struct firmware *fw;
+};
+
+#if IS_ENABLED(CONFIG_DVB_DRX39XYJ)
+struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c) {
+	return NULL;
+};
+#endif
+
+#endif /* DVB_DUMMY_FE_H */
diff --git a/drivers/media/dvb-frontends/drx39xyj/drx_dap_fasi.h b/drivers/media/dvb-frontends/drx39xyj/drx_dap_fasi.h
new file mode 100644
index 0000000..354ec07
--- /dev/null
+++ b/drivers/media/dvb-frontends/drx39xyj/drx_dap_fasi.h
@@ -0,0 +1,256 @@
+/*
+  Copyright (c), 2004-2005,2007-2010 Trident Microsystems, Inc.
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+	and/or other materials provided with the distribution.
+  * Neither the name of Trident Microsystems nor Hauppauge Computer Works
+    nor the names of its contributors may be used to endorse or promote
+	products derived from this software without specific prior written
+	permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*******************************************************************************
+* FILENAME: $Id: drx_dap_fasi.h,v 1.5 2009/07/07 14:21:40 justin Exp $
+*
+* DESCRIPTION:
+* Part of DRX driver.
+* Data access protocol: Fast Access Sequential Interface (fasi)
+* Fast access, because of short addressing format (16 instead of 32 bits addr)
+* Sequential, because of I2C.
+*
+* USAGE:
+* Include.
+*
+* NOTES:
+*
+*
+*******************************************************************************/
+
+/*-------- compilation control switches --------------------------------------*/
+
+#ifndef __DRX_DAP_FASI_H__
+#define __DRX_DAP_FASI_H__
+
+/*-------- Required includes -------------------------------------------------*/
+
+#include "drx_driver.h"
+
+/*-------- Defines, configuring the API --------------------------------------*/
+
+/********************************************
+* Allowed address formats
+********************************************/
+
+/*
+* Comments about short/long addressing format:
+*
+* The DAP FASI offers long address format (4 bytes) and short address format
+* (2 bytes). The DAP can operate in 3 modes:
+* (1) only short
+* (2) only long
+* (3) both long and short but short preferred and long only when necesarry
+*
+* These modes must be selected compile time via compile switches.
+* Compile switch settings for the diffrent modes:
+* (1) DRXDAPFASI_LONG_ADDR_ALLOWED=0, DRXDAPFASI_SHORT_ADDR_ALLOWED=1
+* (2) DRXDAPFASI_LONG_ADDR_ALLOWED=1, DRXDAPFASI_SHORT_ADDR_ALLOWED=0
+* (3) DRXDAPFASI_LONG_ADDR_ALLOWED=1, DRXDAPFASI_SHORT_ADDR_ALLOWED=1
+*
+* The default setting will be (3) both long and short.
+* The default setting will need no compile switches.
+* The default setting must be overridden if compile switches are already
+* defined.
+*
+*/
+
+/* set default */
+#if !defined(DRXDAPFASI_LONG_ADDR_ALLOWED)
+#define  DRXDAPFASI_LONG_ADDR_ALLOWED 1
+#endif
+
+/* set default */
+#if !defined(DRXDAPFASI_SHORT_ADDR_ALLOWED)
+#define  DRXDAPFASI_SHORT_ADDR_ALLOWED 1
+#endif
+
+/* check */
+#if ((DRXDAPFASI_LONG_ADDR_ALLOWED == 0) && \
+      (DRXDAPFASI_SHORT_ADDR_ALLOWED == 0))
+#error  At least one of short- or long-addressing format must be allowed.
+*;				/* illegal statement to force compiler error */
+#endif
+
+/********************************************
+* Single/master multi master setting
+********************************************/
+/*
+* Comments about SINGLE MASTER/MULTI MASTER  modes:
+*
+* Consider the two sides:1) the master and 2)the slave.
+*
+* Master:
+* Single/multimaster operation set via DRXDAP_SINGLE_MASTER compile switch
+*  + single master mode means no use of repeated starts
+*  + multi master mode means use of repeated starts
+*  Default is single master.
+*  Default can be overriden by setting the compile switch DRXDAP_SINGLE_MASTER.
+*
+* Slave:
+* Single/multi master selected via the flags in the FASI protocol.
+*  + single master means remember memory address between i2c packets
+*  + multimaster means flush memory address between i2c packets
+*  Default is single master, DAP FASI changes multi-master setting silently
+*  into single master setting. This cannot be overrriden.
+*
+*/
+/* set default */
+#ifndef DRXDAP_SINGLE_MASTER
+#define DRXDAP_SINGLE_MASTER 0
+#endif
+
+/********************************************
+* Chunk/mode checking
+********************************************/
+/*
+* Comments about DRXDAP_MAX_WCHUNKSIZE in single or multi master mode and
+* in combination with short and long addressing format. All text below
+* assumes long addressing format. The table also includes information
+* for short ADDRessing format.
+*
+* In single master mode, data can be written by sending the register address
+* first, then two or four bytes of data in the next packet.
+* Because the device address plus a register address equals five bytes,
+* the mimimum chunk size must be five.
+* If ten-bit I2C device addresses are used, the minimum chunk size must be six,
+* because the I2C device address will then occupy two bytes when writing.
+*
+* Data in single master mode is transferred as follows:
+* <S> <devW>  a0  a1  a2  a3  <P>
+* <S> <devW>  d0  d1 [d2  d3] <P>
+* ..
+* or
+* ..
+* <S> <devW>  a0  a1  a2  a3  <P>
+* <S> <devR> --- <P>
+*
+* In multi-master mode, the data must immediately follow the address (an I2C
+* stop resets the internal address), and hence the minimum chunk size is
+* 1 <I2C address> + 4 (register address) + 2 (data to send) = 7 bytes (8 if
+* 10-bit I2C device addresses are used).
+*
+* The 7-bit or 10-bit i2c address parameters is a runtime parameter.
+* The other parameters can be limited via compile time switches.
+*
+*-------------------------------------------------------------------------------
+*
+*  Minimum chunk size table (in bytes):
+*
+*       +----------------+----------------+
+*       | 7b i2c addr    | 10b i2c addr   |
+*       +----------------+----------------+
+*       | single | multi | single | multi |
+* ------+--------+-------+--------+-------+
+* short | 3      | 5     | 4      | 6     |
+* long  | 5      | 7     | 6      | 8     |
+* ------+--------+-------+--------+-------+
+*
+*/
+
+/* set default */
+#if !defined(DRXDAP_MAX_WCHUNKSIZE)
+#define  DRXDAP_MAX_WCHUNKSIZE 254
+#endif
+
+/* check */
+#if ((DRXDAPFASI_LONG_ADDR_ALLOWED == 0) && (DRXDAPFASI_SHORT_ADDR_ALLOWED == 1))
+#if DRXDAP_SINGLE_MASTER
+#define  DRXDAP_MAX_WCHUNKSIZE_MIN 3
+#else
+#define  DRXDAP_MAX_WCHUNKSIZE_MIN 5
+#endif
+#else
+#if DRXDAP_SINGLE_MASTER
+#define  DRXDAP_MAX_WCHUNKSIZE_MIN 5
+#else
+#define  DRXDAP_MAX_WCHUNKSIZE_MIN 7
+#endif
+#endif
+
+#if  DRXDAP_MAX_WCHUNKSIZE <  DRXDAP_MAX_WCHUNKSIZE_MIN
+#if ((DRXDAPFASI_LONG_ADDR_ALLOWED == 0) && (DRXDAPFASI_SHORT_ADDR_ALLOWED == 1))
+#if DRXDAP_SINGLE_MASTER
+#error  DRXDAP_MAX_WCHUNKSIZE must be at least 3 in single master mode
+*;				/* illegal statement to force compiler error */
+#else
+#error  DRXDAP_MAX_WCHUNKSIZE must be at least 5 in multi master mode
+*;				/* illegal statement to force compiler error */
+#endif
+#else
+#if DRXDAP_SINGLE_MASTER
+#error  DRXDAP_MAX_WCHUNKSIZE must be at least 5 in single master mode
+*;				/* illegal statement to force compiler error */
+#else
+#error  DRXDAP_MAX_WCHUNKSIZE must be at least 7 in multi master mode
+*;				/* illegal statement to force compiler error */
+#endif
+#endif
+#endif
+
+/* set default */
+#if !defined(DRXDAP_MAX_RCHUNKSIZE)
+#define  DRXDAP_MAX_RCHUNKSIZE 254
+#endif
+
+/* check */
+#if  DRXDAP_MAX_RCHUNKSIZE < 2
+#error  DRXDAP_MAX_RCHUNKSIZE must be at least 2
+*;				/* illegal statement to force compiler error */
+#endif
+
+/* check */
+#if  DRXDAP_MAX_RCHUNKSIZE & 1
+#error  DRXDAP_MAX_RCHUNKSIZE must be even
+*;				/* illegal statement to force compiler error */
+#endif
+
+/*-------- Public API functions ----------------------------------------------*/
+
+extern struct drx_access_func drx_dap_fasi_funct_g;
+
+#define DRXDAP_FASI_RMW           0x10000000
+#define DRXDAP_FASI_BROADCAST     0x20000000
+#define DRXDAP_FASI_CLEARCRC      0x80000000
+#define DRXDAP_FASI_SINGLE_MASTER 0xC0000000
+#define DRXDAP_FASI_MULTI_MASTER  0x40000000
+#define DRXDAP_FASI_SMM_SWITCH    0x40000000	/* single/multi master switch */
+#define DRXDAP_FASI_MODEFLAGS     0xC0000000
+#define DRXDAP_FASI_FLAGS         0xF0000000
+
+#define DRXDAP_FASI_ADDR2BLOCK(addr)  (((addr)>>22)&0x3F)
+#define DRXDAP_FASI_ADDR2BANK(addr)   (((addr)>>16)&0x3F)
+#define DRXDAP_FASI_ADDR2OFFSET(addr) ((addr)&0x7FFF)
+
+#define DRXDAP_FASI_SHORT_FORMAT(addr)     (((addr) & 0xFC30FF80) == 0)
+#define DRXDAP_FASI_LONG_FORMAT(addr)      (((addr) & 0xFC30FF80) != 0)
+#define DRXDAP_FASI_OFFSET_TOO_LARGE(addr) (((addr) & 0x00008000) != 0)
+
+#endif				/* __DRX_DAP_FASI_H__ */
diff --git a/drivers/media/dvb-frontends/drx39xyj/drx_driver.h b/drivers/media/dvb-frontends/drx39xyj/drx_driver.h
new file mode 100644
index 0000000..9076bf2
--- /dev/null
+++ b/drivers/media/dvb-frontends/drx39xyj/drx_driver.h
@@ -0,0 +1,2343 @@
+/*
+  Copyright (c), 2004-2005,2007-2010 Trident Microsystems, Inc.
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+	and/or other materials provided with the distribution.
+  * Neither the name of Trident Microsystems nor Hauppauge Computer Works
+    nor the names of its contributors may be used to endorse or promote
+	products derived from this software without specific prior written
+	permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DRXDRIVER_H__
+#define __DRXDRIVER_H__
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+
+/*
+ * This structure contains the I2C address, the device ID and a user_data pointer.
+ * The user_data pointer can be used for application specific purposes.
+ */
+struct i2c_device_addr {
+	u16 i2c_addr;		/* The I2C address of the device. */
+	u16 i2c_dev_id;		/* The device identifier. */
+	void *user_data;		/* User data pointer */
+};
+
+/**
+* \def IS_I2C_10BIT( addr )
+* \brief Determine if I2C address 'addr' is a 10 bits address or not.
+* \param addr The I2C address.
+* \return int.
+* \retval 0 if address is not a 10 bits I2C address.
+* \retval 1 if address is a 10 bits I2C address.
+*/
+#define IS_I2C_10BIT(addr) \
+	 (((addr) & 0xF8) == 0xF0)
+
+/*------------------------------------------------------------------------------
+Exported FUNCTIONS
+------------------------------------------------------------------------------*/
+
+/**
+* \fn drxbsp_i2c_init()
+* \brief Initialize I2C communication module.
+* \return int Return status.
+* \retval 0 Initialization successful.
+* \retval -EIO Initialization failed.
+*/
+int drxbsp_i2c_init(void);
+
+/**
+* \fn drxbsp_i2c_term()
+* \brief Terminate I2C communication module.
+* \return int Return status.
+* \retval 0 Termination successful.
+* \retval -EIO Termination failed.
+*/
+int drxbsp_i2c_term(void);
+
+/**
+* \fn int drxbsp_i2c_write_read( struct i2c_device_addr *w_dev_addr,
+*                                       u16 w_count,
+*                                       u8 * wData,
+*                                       struct i2c_device_addr *r_dev_addr,
+*                                       u16 r_count,
+*                                       u8 * r_data)
+* \brief Read and/or write count bytes from I2C bus, store them in data[].
+* \param w_dev_addr The device i2c address and the device ID to write to
+* \param w_count   The number of bytes to write
+* \param wData    The array to write the data to
+* \param r_dev_addr The device i2c address and the device ID to read from
+* \param r_count   The number of bytes to read
+* \param r_data    The array to read the data from
+* \return int Return status.
+* \retval 0 Succes.
+* \retval -EIO Failure.
+* \retval -EINVAL Parameter 'wcount' is not zero but parameter
+*                                       'wdata' contains NULL.
+*                                       Idem for 'rcount' and 'rdata'.
+*                                       Both w_dev_addr and r_dev_addr are NULL.
+*
+* This function must implement an atomic write and/or read action on the I2C bus
+* No other process may use the I2C bus when this function is executing.
+* The critical section of this function runs from and including the I2C
+* write, up to and including the I2C read action.
+*
+* The device ID can be useful if several devices share an I2C address.
+* It can be used to control a "switch" on the I2C bus to the correct device.
+*/
+int drxbsp_i2c_write_read(struct i2c_device_addr *w_dev_addr,
+					u16 w_count,
+					u8 *wData,
+					struct i2c_device_addr *r_dev_addr,
+					u16 r_count, u8 *r_data);
+
+/**
+* \fn drxbsp_i2c_error_text()
+* \brief Returns a human readable error.
+* Counter part of numerical drx_i2c_error_g.
+*
+* \return char* Pointer to human readable error text.
+*/
+char *drxbsp_i2c_error_text(void);
+
+/**
+* \var drx_i2c_error_g;
+* \brief I2C specific error codes, platform dependent.
+*/
+extern int drx_i2c_error_g;
+
+#define TUNER_MODE_SUB0    0x0001	/* for sub-mode (e.g. RF-AGC setting) */
+#define TUNER_MODE_SUB1    0x0002	/* for sub-mode (e.g. RF-AGC setting) */
+#define TUNER_MODE_SUB2    0x0004	/* for sub-mode (e.g. RF-AGC setting) */
+#define TUNER_MODE_SUB3    0x0008	/* for sub-mode (e.g. RF-AGC setting) */
+#define TUNER_MODE_SUB4    0x0010	/* for sub-mode (e.g. RF-AGC setting) */
+#define TUNER_MODE_SUB5    0x0020	/* for sub-mode (e.g. RF-AGC setting) */
+#define TUNER_MODE_SUB6    0x0040	/* for sub-mode (e.g. RF-AGC setting) */
+#define TUNER_MODE_SUB7    0x0080	/* for sub-mode (e.g. RF-AGC setting) */
+
+#define TUNER_MODE_DIGITAL 0x0100	/* for digital channel (e.g. DVB-T)   */
+#define TUNER_MODE_ANALOG  0x0200	/* for analog channel  (e.g. PAL)     */
+#define TUNER_MODE_SWITCH  0x0400	/* during channel switch & scanning   */
+#define TUNER_MODE_LOCK    0x0800	/* after tuner has locked             */
+#define TUNER_MODE_6MHZ    0x1000	/* for 6MHz bandwidth channels        */
+#define TUNER_MODE_7MHZ    0x2000	/* for 7MHz bandwidth channels        */
+#define TUNER_MODE_8MHZ    0x4000	/* for 8MHz bandwidth channels        */
+
+#define TUNER_MODE_SUB_MAX 8
+#define TUNER_MODE_SUBALL  (TUNER_MODE_SUB0 | TUNER_MODE_SUB1 | \
+			      TUNER_MODE_SUB2 | TUNER_MODE_SUB3 | \
+			      TUNER_MODE_SUB4 | TUNER_MODE_SUB5 | \
+			      TUNER_MODE_SUB6 | TUNER_MODE_SUB7)
+
+
+enum tuner_lock_status {
+	TUNER_LOCKED,
+	TUNER_NOT_LOCKED
+};
+
+struct tuner_common {
+	char *name;	/* Tuner brand & type name */
+	s32 min_freq_rf;	/* Lowest  RF input frequency, in kHz */
+	s32 max_freq_rf;	/* Highest RF input frequency, in kHz */
+
+	u8 sub_mode;	/* Index to sub-mode in use */
+	char ***sub_mode_descriptions;	/* Pointer to description of sub-modes */
+	u8 sub_modes;	/* Number of available sub-modes      */
+
+	/* The following fields will be either 0, NULL or false and do not need
+		initialisation */
+	void *self_check;	/* gives proof of initialization  */
+	bool programmed;	/* only valid if self_check is OK  */
+	s32 r_ffrequency;	/* only valid if programmed       */
+	s32 i_ffrequency;	/* only valid if programmed       */
+
+	void *my_user_data;	/* pointer to associated demod instance */
+	u16 my_capabilities;	/* value for storing application flags  */
+};
+
+struct tuner_instance;
+
+typedef int(*tuner_open_func_t) (struct tuner_instance *tuner);
+typedef int(*tuner_close_func_t) (struct tuner_instance *tuner);
+
+typedef int(*tuner_set_frequency_func_t) (struct tuner_instance *tuner,
+						u32 mode,
+						s32
+						frequency);
+
+typedef int(*tuner_get_frequency_func_t) (struct tuner_instance *tuner,
+						u32 mode,
+						s32 *
+						r_ffrequency,
+						s32 *
+						i_ffrequency);
+
+typedef int(*tuner_lock_status_func_t) (struct tuner_instance *tuner,
+						enum tuner_lock_status *
+						lock_stat);
+
+typedef int(*tune_ri2c_write_read_func_t) (struct tuner_instance *tuner,
+						struct i2c_device_addr *
+						w_dev_addr, u16 w_count,
+						u8 *wData,
+						struct i2c_device_addr *
+						r_dev_addr, u16 r_count,
+						u8 *r_data);
+
+struct tuner_ops {
+	tuner_open_func_t open_func;
+	tuner_close_func_t close_func;
+	tuner_set_frequency_func_t set_frequency_func;
+	tuner_get_frequency_func_t get_frequency_func;
+	tuner_lock_status_func_t lock_status_func;
+	tune_ri2c_write_read_func_t i2c_write_read_func;
+
+};
+
+struct tuner_instance {
+	struct i2c_device_addr my_i2c_dev_addr;
+	struct tuner_common *my_common_attr;
+	void *my_ext_attr;
+	struct tuner_ops *my_funct;
+};
+
+int drxbsp_tuner_set_frequency(struct tuner_instance *tuner,
+					u32 mode,
+					s32 frequency);
+
+int drxbsp_tuner_get_frequency(struct tuner_instance *tuner,
+					u32 mode,
+					s32 *r_ffrequency,
+					s32 *i_ffrequency);
+
+int drxbsp_tuner_default_i2c_write_read(struct tuner_instance *tuner,
+						struct i2c_device_addr *w_dev_addr,
+						u16 w_count,
+						u8 *wData,
+						struct i2c_device_addr *r_dev_addr,
+						u16 r_count, u8 *r_data);
+
+/**************
+*
+* This section configures the DRX Data Access Protocols (DAPs).
+*
+**************/
+
+/**
+* \def DRXDAP_SINGLE_MASTER
+* \brief Enable I2C single or I2C multimaster mode on host.
+*
+* Set to 1 to enable single master mode
+* Set to 0 to enable multi master mode
+*
+* The actual DAP implementation may be restricted to only one of the modes.
+* A compiler warning or error will be generated if the DAP implementation
+* overides or cannot handle the mode defined below.
+*
+*/
+#ifndef DRXDAP_SINGLE_MASTER
+#define DRXDAP_SINGLE_MASTER 1
+#endif
+
+/**
+* \def DRXDAP_MAX_WCHUNKSIZE
+* \brief Defines maximum chunksize of an i2c write action by host.
+*
+* This indicates the maximum size of data the I2C device driver is able to
+* write at a time. This includes I2C device address and register addressing.
+*
+* This maximum size may be restricted by the actual DAP implementation.
+* A compiler warning or error will be generated if the DAP implementation
+* overides or cannot handle the chunksize defined below.
+*
+* Beware that the DAP uses  DRXDAP_MAX_WCHUNKSIZE to create a temporary data
+* buffer. Do not undefine or choose too large, unless your system is able to
+* handle a stack buffer of that size.
+*
+*/
+#ifndef DRXDAP_MAX_WCHUNKSIZE
+#define  DRXDAP_MAX_WCHUNKSIZE 60
+#endif
+
+/**
+* \def DRXDAP_MAX_RCHUNKSIZE
+* \brief Defines maximum chunksize of an i2c read action by host.
+*
+* This indicates the maximum size of data the I2C device driver is able to read
+* at a time. Minimum value is 2. Also, the read chunk size must be even.
+*
+* This maximum size may be restricted by the actual DAP implementation.
+* A compiler warning or error will be generated if the DAP implementation
+* overides or cannot handle the chunksize defined below.
+*
+*/
+#ifndef DRXDAP_MAX_RCHUNKSIZE
+#define  DRXDAP_MAX_RCHUNKSIZE 60
+#endif
+
+/**************
+*
+* This section describes drxdriver defines.
+*
+**************/
+
+/**
+* \def DRX_UNKNOWN
+* \brief Generic UNKNOWN value for DRX enumerated types.
+*
+* Used to indicate that the parameter value is unknown or not yet initalized.
+*/
+#ifndef DRX_UNKNOWN
+#define DRX_UNKNOWN (254)
+#endif
+
+/**
+* \def DRX_AUTO
+* \brief Generic AUTO value for DRX enumerated types.
+*
+* Used to instruct the driver to automatically determine the value of the
+* parameter.
+*/
+#ifndef DRX_AUTO
+#define DRX_AUTO    (255)
+#endif
+
+/**************
+*
+* This section describes flag definitions for the device capbilities.
+*
+**************/
+
+/**
+* \brief LNA capability flag
+*
+* Device has a Low Noise Amplifier
+*
+*/
+#define DRX_CAPABILITY_HAS_LNA           (1UL <<  0)
+/**
+* \brief OOB-RX capability flag
+*
+* Device has OOB-RX
+*
+*/
+#define DRX_CAPABILITY_HAS_OOBRX         (1UL <<  1)
+/**
+* \brief ATV capability flag
+*
+* Device has ATV
+*
+*/
+#define DRX_CAPABILITY_HAS_ATV           (1UL <<  2)
+/**
+* \brief DVB-T capability flag
+*
+* Device has DVB-T
+*
+*/
+#define DRX_CAPABILITY_HAS_DVBT          (1UL <<  3)
+/**
+* \brief  ITU-B capability flag
+*
+* Device has ITU-B
+*
+*/
+#define DRX_CAPABILITY_HAS_ITUB          (1UL <<  4)
+/**
+* \brief  Audio capability flag
+*
+* Device has Audio
+*
+*/
+#define DRX_CAPABILITY_HAS_AUD           (1UL <<  5)
+/**
+* \brief  SAW switch capability flag
+*
+* Device has SAW switch
+*
+*/
+#define DRX_CAPABILITY_HAS_SAWSW         (1UL <<  6)
+/**
+* \brief  GPIO1 capability flag
+*
+* Device has GPIO1
+*
+*/
+#define DRX_CAPABILITY_HAS_GPIO1         (1UL <<  7)
+/**
+* \brief  GPIO2 capability flag
+*
+* Device has GPIO2
+*
+*/
+#define DRX_CAPABILITY_HAS_GPIO2         (1UL <<  8)
+/**
+* \brief  IRQN capability flag
+*
+* Device has IRQN
+*
+*/
+#define DRX_CAPABILITY_HAS_IRQN          (1UL <<  9)
+/**
+* \brief  8VSB capability flag
+*
+* Device has 8VSB
+*
+*/
+#define DRX_CAPABILITY_HAS_8VSB          (1UL << 10)
+/**
+* \brief  SMA-TX capability flag
+*
+* Device has SMATX
+*
+*/
+#define DRX_CAPABILITY_HAS_SMATX         (1UL << 11)
+/**
+* \brief  SMA-RX capability flag
+*
+* Device has SMARX
+*
+*/
+#define DRX_CAPABILITY_HAS_SMARX         (1UL << 12)
+/**
+* \brief  ITU-A/C capability flag
+*
+* Device has ITU-A/C
+*
+*/
+#define DRX_CAPABILITY_HAS_ITUAC         (1UL << 13)
+
+/*-------------------------------------------------------------------------
+MACROS
+-------------------------------------------------------------------------*/
+/* Macros to stringify the version number */
+#define DRX_VERSIONSTRING(MAJOR, MINOR, PATCH) \
+	 DRX_VERSIONSTRING_HELP(MAJOR)"." \
+	 DRX_VERSIONSTRING_HELP(MINOR)"." \
+	 DRX_VERSIONSTRING_HELP(PATCH)
+#define DRX_VERSIONSTRING_HELP(NUM) #NUM
+
+/**
+* \brief Macro to create byte array elements from 16 bit integers.
+* This macro is used to create byte arrays for block writes.
+* Block writes speed up I2C traffic between host and demod.
+* The macro takes care of the required byte order in a 16 bits word.
+* x->lowbyte(x), highbyte(x)
+*/
+#define DRX_16TO8(x) ((u8) (((u16)x) & 0xFF)), \
+			((u8)((((u16)x)>>8)&0xFF))
+
+/**
+* \brief Macro to sign extend signed 9 bit value to signed  16 bit value
+*/
+#define DRX_S9TOS16(x) ((((u16)x)&0x100) ? ((s16)((u16)(x)|0xFF00)) : (x))
+
+/**
+* \brief Macro to sign extend signed 9 bit value to signed  16 bit value
+*/
+#define DRX_S24TODRXFREQ(x) ((((u32) x) & 0x00800000UL) ? \
+				 ((s32) \
+				    (((u32) x) | 0xFF000000)) : \
+				 ((s32) x))
+
+/**
+* \brief Macro to convert 16 bit register value to a s32
+*/
+#define DRX_U16TODRXFREQ(x)   ((x & 0x8000) ? \
+				 ((s32) \
+				    (((u32) x) | 0xFFFF0000)) : \
+				 ((s32) x))
+
+/*-------------------------------------------------------------------------
+ENUM
+-------------------------------------------------------------------------*/
+
+/**
+* \enum enum drx_standard
+* \brief Modulation standards.
+*/
+enum drx_standard {
+	DRX_STANDARD_DVBT = 0, /**< Terrestrial DVB-T.               */
+	DRX_STANDARD_8VSB,     /**< Terrestrial 8VSB.                */
+	DRX_STANDARD_NTSC,     /**< Terrestrial\Cable analog NTSC.   */
+	DRX_STANDARD_PAL_SECAM_BG,
+				/**< Terrestrial analog PAL/SECAM B/G */
+	DRX_STANDARD_PAL_SECAM_DK,
+				/**< Terrestrial analog PAL/SECAM D/K */
+	DRX_STANDARD_PAL_SECAM_I,
+				/**< Terrestrial analog PAL/SECAM I   */
+	DRX_STANDARD_PAL_SECAM_L,
+				/**< Terrestrial analog PAL/SECAM L
+					with negative modulation        */
+	DRX_STANDARD_PAL_SECAM_LP,
+				/**< Terrestrial analog PAL/SECAM L
+					with positive modulation        */
+	DRX_STANDARD_ITU_A,    /**< Cable ITU ANNEX A.               */
+	DRX_STANDARD_ITU_B,    /**< Cable ITU ANNEX B.               */
+	DRX_STANDARD_ITU_C,    /**< Cable ITU ANNEX C.               */
+	DRX_STANDARD_ITU_D,    /**< Cable ITU ANNEX D.               */
+	DRX_STANDARD_FM,       /**< Terrestrial\Cable FM radio       */
+	DRX_STANDARD_DTMB,     /**< Terrestrial DTMB standard (China)*/
+	DRX_STANDARD_UNKNOWN = DRX_UNKNOWN,
+				/**< Standard unknown.                */
+	DRX_STANDARD_AUTO = DRX_AUTO
+				/**< Autodetect standard.             */
+};
+
+/**
+* \enum enum drx_standard
+* \brief Modulation sub-standards.
+*/
+enum drx_substandard {
+	DRX_SUBSTANDARD_MAIN = 0, /**< Main subvariant of standard   */
+	DRX_SUBSTANDARD_ATV_BG_SCANDINAVIA,
+	DRX_SUBSTANDARD_ATV_DK_POLAND,
+	DRX_SUBSTANDARD_ATV_DK_CHINA,
+	DRX_SUBSTANDARD_UNKNOWN = DRX_UNKNOWN,
+					/**< Sub-standard unknown.         */
+	DRX_SUBSTANDARD_AUTO = DRX_AUTO
+					/**< Auto (default) sub-standard   */
+};
+
+/**
+* \enum enum drx_bandwidth
+* \brief Channel bandwidth or channel spacing.
+*/
+enum drx_bandwidth {
+	DRX_BANDWIDTH_8MHZ = 0,	 /**< Bandwidth 8 MHz.   */
+	DRX_BANDWIDTH_7MHZ,	 /**< Bandwidth 7 MHz.   */
+	DRX_BANDWIDTH_6MHZ,	 /**< Bandwidth 6 MHz.   */
+	DRX_BANDWIDTH_UNKNOWN = DRX_UNKNOWN,
+					/**< Bandwidth unknown. */
+	DRX_BANDWIDTH_AUTO = DRX_AUTO
+					/**< Auto Set Bandwidth */
+};
+
+/**
+* \enum enum drx_mirror
+* \brief Indicate if channel spectrum is mirrored or not.
+*/
+enum drx_mirror {
+	DRX_MIRROR_NO = 0,   /**< Spectrum is not mirrored.           */
+	DRX_MIRROR_YES,	     /**< Spectrum is mirrored.               */
+	DRX_MIRROR_UNKNOWN = DRX_UNKNOWN,
+				/**< Unknown if spectrum is mirrored.    */
+	DRX_MIRROR_AUTO = DRX_AUTO
+				/**< Autodetect if spectrum is mirrored. */
+};
+
+/**
+* \enum enum drx_modulation
+* \brief Constellation type of the channel.
+*/
+enum drx_modulation {
+	DRX_CONSTELLATION_BPSK = 0,  /**< Modulation is BPSK.       */
+	DRX_CONSTELLATION_QPSK,	     /**< Constellation is QPSK.    */
+	DRX_CONSTELLATION_PSK8,	     /**< Constellation is PSK8.    */
+	DRX_CONSTELLATION_QAM16,     /**< Constellation is QAM16.   */
+	DRX_CONSTELLATION_QAM32,     /**< Constellation is QAM32.   */
+	DRX_CONSTELLATION_QAM64,     /**< Constellation is QAM64.   */
+	DRX_CONSTELLATION_QAM128,    /**< Constellation is QAM128.  */
+	DRX_CONSTELLATION_QAM256,    /**< Constellation is QAM256.  */
+	DRX_CONSTELLATION_QAM512,    /**< Constellation is QAM512.  */
+	DRX_CONSTELLATION_QAM1024,   /**< Constellation is QAM1024. */
+	DRX_CONSTELLATION_QPSK_NR,   /**< Constellation is QPSK_NR  */
+	DRX_CONSTELLATION_UNKNOWN = DRX_UNKNOWN,
+					/**< Constellation unknown.    */
+	DRX_CONSTELLATION_AUTO = DRX_AUTO
+					/**< Autodetect constellation. */
+};
+
+/**
+* \enum enum drx_hierarchy
+* \brief Hierarchy of the channel.
+*/
+enum drx_hierarchy {
+	DRX_HIERARCHY_NONE = 0,	/**< None hierarchical channel.     */
+	DRX_HIERARCHY_ALPHA1,	/**< Hierarchical channel, alpha=1. */
+	DRX_HIERARCHY_ALPHA2,	/**< Hierarchical channel, alpha=2. */
+	DRX_HIERARCHY_ALPHA4,	/**< Hierarchical channel, alpha=4. */
+	DRX_HIERARCHY_UNKNOWN = DRX_UNKNOWN,
+				/**< Hierarchy unknown.             */
+	DRX_HIERARCHY_AUTO = DRX_AUTO
+				/**< Autodetect hierarchy.          */
+};
+
+/**
+* \enum enum drx_priority
+* \brief Channel priority in case of hierarchical transmission.
+*/
+enum drx_priority {
+	DRX_PRIORITY_LOW = 0,  /**< Low priority channel.  */
+	DRX_PRIORITY_HIGH,     /**< High priority channel. */
+	DRX_PRIORITY_UNKNOWN = DRX_UNKNOWN
+				/**< Priority unknown.      */
+};
+
+/**
+* \enum enum drx_coderate
+* \brief Channel priority in case of hierarchical transmission.
+*/
+enum drx_coderate {
+		DRX_CODERATE_1DIV2 = 0,	/**< Code rate 1/2nd.      */
+		DRX_CODERATE_2DIV3,	/**< Code rate 2/3nd.      */
+		DRX_CODERATE_3DIV4,	/**< Code rate 3/4nd.      */
+		DRX_CODERATE_5DIV6,	/**< Code rate 5/6nd.      */
+		DRX_CODERATE_7DIV8,	/**< Code rate 7/8nd.      */
+		DRX_CODERATE_UNKNOWN = DRX_UNKNOWN,
+					/**< Code rate unknown.    */
+		DRX_CODERATE_AUTO = DRX_AUTO
+					/**< Autodetect code rate. */
+};
+
+/**
+* \enum enum drx_guard
+* \brief Guard interval of a channel.
+*/
+enum drx_guard {
+	DRX_GUARD_1DIV32 = 0, /**< Guard interval 1/32nd.     */
+	DRX_GUARD_1DIV16,     /**< Guard interval 1/16th.     */
+	DRX_GUARD_1DIV8,      /**< Guard interval 1/8th.      */
+	DRX_GUARD_1DIV4,      /**< Guard interval 1/4th.      */
+	DRX_GUARD_UNKNOWN = DRX_UNKNOWN,
+				/**< Guard interval unknown.    */
+	DRX_GUARD_AUTO = DRX_AUTO
+				/**< Autodetect guard interval. */
+};
+
+/**
+* \enum enum drx_fft_mode
+* \brief FFT mode.
+*/
+enum drx_fft_mode {
+	DRX_FFTMODE_2K = 0,    /**< 2K FFT mode.         */
+	DRX_FFTMODE_4K,	       /**< 4K FFT mode.         */
+	DRX_FFTMODE_8K,	       /**< 8K FFT mode.         */
+	DRX_FFTMODE_UNKNOWN = DRX_UNKNOWN,
+				/**< FFT mode unknown.    */
+	DRX_FFTMODE_AUTO = DRX_AUTO
+				/**< Autodetect FFT mode. */
+};
+
+/**
+* \enum enum drx_classification
+* \brief Channel classification.
+*/
+enum drx_classification {
+	DRX_CLASSIFICATION_GAUSS = 0, /**< Gaussion noise.            */
+	DRX_CLASSIFICATION_HVY_GAUSS, /**< Heavy Gaussion noise.      */
+	DRX_CLASSIFICATION_COCHANNEL, /**< Co-channel.                */
+	DRX_CLASSIFICATION_STATIC,    /**< Static echo.               */
+	DRX_CLASSIFICATION_MOVING,    /**< Moving echo.               */
+	DRX_CLASSIFICATION_ZERODB,    /**< Zero dB echo.              */
+	DRX_CLASSIFICATION_UNKNOWN = DRX_UNKNOWN,
+					/**< Unknown classification     */
+	DRX_CLASSIFICATION_AUTO = DRX_AUTO
+					/**< Autodetect classification. */
+};
+
+/**
+* /enum enum drx_interleave_mode
+* /brief Interleave modes
+*/
+enum drx_interleave_mode {
+	DRX_INTERLEAVEMODE_I128_J1 = 0,
+	DRX_INTERLEAVEMODE_I128_J1_V2,
+	DRX_INTERLEAVEMODE_I128_J2,
+	DRX_INTERLEAVEMODE_I64_J2,
+	DRX_INTERLEAVEMODE_I128_J3,
+	DRX_INTERLEAVEMODE_I32_J4,
+	DRX_INTERLEAVEMODE_I128_J4,
+	DRX_INTERLEAVEMODE_I16_J8,
+	DRX_INTERLEAVEMODE_I128_J5,
+	DRX_INTERLEAVEMODE_I8_J16,
+	DRX_INTERLEAVEMODE_I128_J6,
+	DRX_INTERLEAVEMODE_RESERVED_11,
+	DRX_INTERLEAVEMODE_I128_J7,
+	DRX_INTERLEAVEMODE_RESERVED_13,
+	DRX_INTERLEAVEMODE_I128_J8,
+	DRX_INTERLEAVEMODE_RESERVED_15,
+	DRX_INTERLEAVEMODE_I12_J17,
+	DRX_INTERLEAVEMODE_I5_J4,
+	DRX_INTERLEAVEMODE_B52_M240,
+	DRX_INTERLEAVEMODE_B52_M720,
+	DRX_INTERLEAVEMODE_B52_M48,
+	DRX_INTERLEAVEMODE_B52_M0,
+	DRX_INTERLEAVEMODE_UNKNOWN = DRX_UNKNOWN,
+					/**< Unknown interleave mode    */
+	DRX_INTERLEAVEMODE_AUTO = DRX_AUTO
+					/**< Autodetect interleave mode */
+};
+
+/**
+* \enum enum drx_carrier_mode
+* \brief Channel Carrier Mode.
+*/
+enum drx_carrier_mode {
+	DRX_CARRIER_MULTI = 0,		/**< Multi carrier mode       */
+	DRX_CARRIER_SINGLE,		/**< Single carrier mode      */
+	DRX_CARRIER_UNKNOWN = DRX_UNKNOWN,
+					/**< Carrier mode unknown.    */
+	DRX_CARRIER_AUTO = DRX_AUTO	/**< Autodetect carrier mode  */
+};
+
+/**
+* \enum enum drx_frame_mode
+* \brief Channel Frame Mode.
+*/
+enum drx_frame_mode {
+	DRX_FRAMEMODE_420 = 0,	 /**< 420 with variable PN  */
+	DRX_FRAMEMODE_595,	 /**< 595                   */
+	DRX_FRAMEMODE_945,	 /**< 945 with variable PN  */
+	DRX_FRAMEMODE_420_FIXED_PN,
+					/**< 420 with fixed PN     */
+	DRX_FRAMEMODE_945_FIXED_PN,
+					/**< 945 with fixed PN     */
+	DRX_FRAMEMODE_UNKNOWN = DRX_UNKNOWN,
+					/**< Frame mode unknown.   */
+	DRX_FRAMEMODE_AUTO = DRX_AUTO
+					/**< Autodetect frame mode */
+};
+
+/**
+* \enum enum drx_tps_frame
+* \brief Frame number in current super-frame.
+*/
+enum drx_tps_frame {
+	DRX_TPS_FRAME1 = 0,	  /**< TPS frame 1.       */
+	DRX_TPS_FRAME2,		  /**< TPS frame 2.       */
+	DRX_TPS_FRAME3,		  /**< TPS frame 3.       */
+	DRX_TPS_FRAME4,		  /**< TPS frame 4.       */
+	DRX_TPS_FRAME_UNKNOWN = DRX_UNKNOWN
+					/**< TPS frame unknown. */
+};
+
+/**
+* \enum enum drx_ldpc
+* \brief TPS LDPC .
+*/
+enum drx_ldpc {
+	DRX_LDPC_0_4 = 0,	  /**< LDPC 0.4           */
+	DRX_LDPC_0_6,		  /**< LDPC 0.6           */
+	DRX_LDPC_0_8,		  /**< LDPC 0.8           */
+	DRX_LDPC_UNKNOWN = DRX_UNKNOWN,
+					/**< LDPC unknown.      */
+	DRX_LDPC_AUTO = DRX_AUTO  /**< Autodetect LDPC    */
+};
+
+/**
+* \enum enum drx_pilot_mode
+* \brief Pilot modes in DTMB.
+*/
+enum drx_pilot_mode {
+	DRX_PILOT_ON = 0,	  /**< Pilot On             */
+	DRX_PILOT_OFF,		  /**< Pilot Off            */
+	DRX_PILOT_UNKNOWN = DRX_UNKNOWN,
+					/**< Pilot unknown.       */
+	DRX_PILOT_AUTO = DRX_AUTO /**< Autodetect Pilot     */
+};
+
+/**
+ * enum drxu_code_action - indicate if firmware has to be uploaded or verified.
+ * @UCODE_UPLOAD:	Upload the microcode image to device
+ * @UCODE_VERIFY:	Compare microcode image with code on device
+ */
+enum drxu_code_action {
+	UCODE_UPLOAD,
+	UCODE_VERIFY
+};
+
+/**
+* \enum enum drx_lock_status * \brief Used to reflect current lock status of demodulator.
+*
+* The generic lock states have device dependent semantics.
+
+		DRX_NEVER_LOCK = 0,
+			      **< Device will never lock on this signal *
+		DRX_NOT_LOCKED,
+			      **< Device has no lock at all             *
+		DRX_LOCK_STATE_1,
+			      **< Generic lock state                    *
+		DRX_LOCK_STATE_2,
+			      **< Generic lock state                    *
+		DRX_LOCK_STATE_3,
+			      **< Generic lock state                    *
+		DRX_LOCK_STATE_4,
+			      **< Generic lock state                    *
+		DRX_LOCK_STATE_5,
+			      **< Generic lock state                    *
+		DRX_LOCK_STATE_6,
+			      **< Generic lock state                    *
+		DRX_LOCK_STATE_7,
+			      **< Generic lock state                    *
+		DRX_LOCK_STATE_8,
+			      **< Generic lock state                    *
+		DRX_LOCK_STATE_9,
+			      **< Generic lock state                    *
+		DRX_LOCKED    **< Device is in lock                     *
+*/
+
+enum drx_lock_status {
+	DRX_NEVER_LOCK = 0,
+	DRX_NOT_LOCKED,
+	DRX_LOCK_STATE_1,
+	DRX_LOCK_STATE_2,
+	DRX_LOCK_STATE_3,
+	DRX_LOCK_STATE_4,
+	DRX_LOCK_STATE_5,
+	DRX_LOCK_STATE_6,
+	DRX_LOCK_STATE_7,
+	DRX_LOCK_STATE_8,
+	DRX_LOCK_STATE_9,
+	DRX_LOCKED
+};
+
+/**
+* \enum enum drx_uio* \brief Used to address a User IO (UIO).
+*/
+enum drx_uio {
+	DRX_UIO1,
+	DRX_UIO2,
+	DRX_UIO3,
+	DRX_UIO4,
+	DRX_UIO5,
+	DRX_UIO6,
+	DRX_UIO7,
+	DRX_UIO8,
+	DRX_UIO9,
+	DRX_UIO10,
+	DRX_UIO11,
+	DRX_UIO12,
+	DRX_UIO13,
+	DRX_UIO14,
+	DRX_UIO15,
+	DRX_UIO16,
+	DRX_UIO17,
+	DRX_UIO18,
+	DRX_UIO19,
+	DRX_UIO20,
+	DRX_UIO21,
+	DRX_UIO22,
+	DRX_UIO23,
+	DRX_UIO24,
+	DRX_UIO25,
+	DRX_UIO26,
+	DRX_UIO27,
+	DRX_UIO28,
+	DRX_UIO29,
+	DRX_UIO30,
+	DRX_UIO31,
+	DRX_UIO32,
+	DRX_UIO_MAX = DRX_UIO32
+};
+
+/**
+* \enum enum drxuio_mode * \brief Used to configure the modus oprandi of a UIO.
+*
+* DRX_UIO_MODE_FIRMWARE is an old uio mode.
+* It is replaced by the modes DRX_UIO_MODE_FIRMWARE0 .. DRX_UIO_MODE_FIRMWARE9.
+* To be backward compatible DRX_UIO_MODE_FIRMWARE is equivalent to
+* DRX_UIO_MODE_FIRMWARE0.
+*/
+enum drxuio_mode {
+	DRX_UIO_MODE_DISABLE = 0x01,
+			    /**< not used, pin is configured as input */
+	DRX_UIO_MODE_READWRITE = 0x02,
+			    /**< used for read/write by application   */
+	DRX_UIO_MODE_FIRMWARE = 0x04,
+			    /**< controlled by firmware, function 0   */
+	DRX_UIO_MODE_FIRMWARE0 = DRX_UIO_MODE_FIRMWARE,
+					    /**< same as above        */
+	DRX_UIO_MODE_FIRMWARE1 = 0x08,
+			    /**< controlled by firmware, function 1   */
+	DRX_UIO_MODE_FIRMWARE2 = 0x10,
+			    /**< controlled by firmware, function 2   */
+	DRX_UIO_MODE_FIRMWARE3 = 0x20,
+			    /**< controlled by firmware, function 3   */
+	DRX_UIO_MODE_FIRMWARE4 = 0x40,
+			    /**< controlled by firmware, function 4   */
+	DRX_UIO_MODE_FIRMWARE5 = 0x80
+			    /**< controlled by firmware, function 5   */
+};
+
+/**
+* \enum enum drxoob_downstream_standard * \brief Used to select OOB standard.
+*
+* Based on ANSI 55-1 and 55-2
+*/
+enum drxoob_downstream_standard {
+	DRX_OOB_MODE_A = 0,
+		       /**< ANSI 55-1   */
+	DRX_OOB_MODE_B_GRADE_A,
+		       /**< ANSI 55-2 A */
+	DRX_OOB_MODE_B_GRADE_B
+		       /**< ANSI 55-2 B */
+};
+
+/*-------------------------------------------------------------------------
+STRUCTS
+-------------------------------------------------------------------------*/
+
+/*============================================================================*/
+/*============================================================================*/
+/*== CTRL CFG related data structures ========================================*/
+/*============================================================================*/
+/*============================================================================*/
+
+#ifndef DRX_CFG_BASE
+#define DRX_CFG_BASE          0
+#endif
+
+#define DRX_CFG_MPEG_OUTPUT         (DRX_CFG_BASE +  0)	/* MPEG TS output    */
+#define DRX_CFG_PKTERR              (DRX_CFG_BASE +  1)	/* Packet Error      */
+#define DRX_CFG_SYMCLK_OFFS         (DRX_CFG_BASE +  2)	/* Symbol Clk Offset */
+#define DRX_CFG_SMA                 (DRX_CFG_BASE +  3)	/* Smart Antenna     */
+#define DRX_CFG_PINSAFE             (DRX_CFG_BASE +  4)	/* Pin safe mode     */
+#define DRX_CFG_SUBSTANDARD         (DRX_CFG_BASE +  5)	/* substandard       */
+#define DRX_CFG_AUD_VOLUME          (DRX_CFG_BASE +  6)	/* volume            */
+#define DRX_CFG_AUD_RDS             (DRX_CFG_BASE +  7)	/* rds               */
+#define DRX_CFG_AUD_AUTOSOUND       (DRX_CFG_BASE +  8)	/* ASS & ASC         */
+#define DRX_CFG_AUD_ASS_THRES       (DRX_CFG_BASE +  9)	/* ASS Thresholds    */
+#define DRX_CFG_AUD_DEVIATION       (DRX_CFG_BASE + 10)	/* Deviation         */
+#define DRX_CFG_AUD_PRESCALE        (DRX_CFG_BASE + 11)	/* Prescale          */
+#define DRX_CFG_AUD_MIXER           (DRX_CFG_BASE + 12)	/* Mixer             */
+#define DRX_CFG_AUD_AVSYNC          (DRX_CFG_BASE + 13)	/* AVSync            */
+#define DRX_CFG_AUD_CARRIER         (DRX_CFG_BASE + 14)	/* Audio carriers    */
+#define DRX_CFG_I2S_OUTPUT          (DRX_CFG_BASE + 15)	/* I2S output        */
+#define DRX_CFG_ATV_STANDARD        (DRX_CFG_BASE + 16)	/* ATV standard      */
+#define DRX_CFG_SQI_SPEED           (DRX_CFG_BASE + 17)	/* SQI speed         */
+#define DRX_CTRL_CFG_MAX            (DRX_CFG_BASE + 18)	/* never to be used  */
+
+#define DRX_CFG_PINS_SAFE_MODE      DRX_CFG_PINSAFE
+/*============================================================================*/
+/*============================================================================*/
+/*== CTRL related data structures ============================================*/
+/*============================================================================*/
+/*============================================================================*/
+
+/**
+ * struct drxu_code_info	Parameters for microcode upload and verfiy.
+ *
+ * @mc_file:	microcode file name
+ *
+ * Used by DRX_CTRL_LOAD_UCODE and DRX_CTRL_VERIFY_UCODE
+ */
+struct drxu_code_info {
+	char 			*mc_file;
+};
+
+/**
+* \struct drx_mc_version_rec_t
+* \brief Microcode version record
+* Version numbers are stored in BCD format, as usual:
+*   o major number = bits 31-20 (first three nibbles of MSW)
+*   o minor number = bits 19-16 (fourth nibble of MSW)
+*   o patch number = bits 15-0  (remaining nibbles in LSW)
+*
+* The device type indicates for which the device is meant. It is based on the
+* JTAG ID, using everything except the bond ID and the metal fix.
+*
+* Special values:
+* - mc_dev_type == 0         => any device allowed
+* - mc_base_version == 0.0.0 => full microcode (mc_version is the version)
+* - mc_base_version != 0.0.0 => patch microcode, the base microcode version
+*                             (mc_version is the version)
+*/
+#define AUX_VER_RECORD 0x8000
+
+struct drx_mc_version_rec {
+	u16 aux_type;	/* type of aux data - 0x8000 for version record     */
+	u32 mc_dev_type;	/* device type, based on JTAG ID                    */
+	u32 mc_version;	/* version of microcode                             */
+	u32 mc_base_version;	/* in case of patch: the original microcode version */
+};
+
+/*========================================*/
+
+/**
+* \struct drx_filter_info_t
+* \brief Parameters for loading filter coefficients
+*
+* Used by DRX_CTRL_LOAD_FILTER
+*/
+struct drx_filter_info {
+	u8 *data_re;
+	      /**< pointer to coefficients for RE */
+	u8 *data_im;
+	      /**< pointer to coefficients for IM */
+	u16 size_re;
+	      /**< size of coefficients for RE    */
+	u16 size_im;
+	      /**< size of coefficients for IM    */
+};
+
+/*========================================*/
+
+/**
+* \struct struct drx_channel * \brief The set of parameters describing a single channel.
+*
+* Used by DRX_CTRL_SET_CHANNEL and DRX_CTRL_GET_CHANNEL.
+* Only certain fields need to be used for a specfic standard.
+*
+*/
+struct drx_channel {
+	s32 frequency;
+				/**< frequency in kHz                 */
+	enum drx_bandwidth bandwidth;
+				/**< bandwidth                        */
+	enum drx_mirror mirror;	/**< mirrored or not on RF            */
+	enum drx_modulation constellation;
+				/**< constellation                    */
+	enum drx_hierarchy hierarchy;
+				/**< hierarchy                        */
+	enum drx_priority priority;	/**< priority                         */
+	enum drx_coderate coderate;	/**< coderate                         */
+	enum drx_guard guard;	/**< guard interval                   */
+	enum drx_fft_mode fftmode;	/**< fftmode                          */
+	enum drx_classification classification;
+				/**< classification                   */
+	u32 symbolrate;
+				/**< symbolrate in symbols/sec        */
+	enum drx_interleave_mode interleavemode;
+				/**< interleaveMode QAM               */
+	enum drx_ldpc ldpc;		/**< ldpc                             */
+	enum drx_carrier_mode carrier;	/**< carrier                          */
+	enum drx_frame_mode framemode;
+				/**< frame mode                       */
+	enum drx_pilot_mode pilot;	/**< pilot mode                       */
+};
+
+/*========================================*/
+
+enum drx_cfg_sqi_speed {
+	DRX_SQI_SPEED_FAST = 0,
+	DRX_SQI_SPEED_MEDIUM,
+	DRX_SQI_SPEED_SLOW,
+	DRX_SQI_SPEED_UNKNOWN = DRX_UNKNOWN
+};
+
+/*========================================*/
+
+/**
+* \struct struct drx_complex * A complex number.
+*
+* Used by DRX_CTRL_CONSTEL.
+*/
+struct drx_complex {
+	s16 im;
+     /**< Imaginary part. */
+	s16 re;
+     /**< Real part.      */
+};
+
+/*========================================*/
+
+/**
+* \struct struct drx_frequency_plan * Array element of a frequency plan.
+*
+* Used by DRX_CTRL_SCAN_INIT.
+*/
+struct drx_frequency_plan {
+	s32 first;
+		     /**< First centre frequency in this band        */
+	s32 last;
+		     /**< Last centre frequency in this band         */
+	s32 step;
+		     /**< Stepping frequency in this band            */
+	enum drx_bandwidth bandwidth;
+		     /**< Bandwidth within this frequency band       */
+	u16 ch_number;
+		     /**< First channel number in this band, or first
+			    index in ch_names                         */
+	char **ch_names;
+		     /**< Optional list of channel names in this
+			    band                                     */
+};
+
+/*========================================*/
+
+/**
+* \struct struct drx_scan_param * Parameters for channel scan.
+*
+* Used by DRX_CTRL_SCAN_INIT.
+*/
+struct drx_scan_param {
+	struct drx_frequency_plan *frequency_plan;
+				  /**< Frequency plan (array)*/
+	u16 frequency_plan_size;  /**< Number of bands       */
+	u32 num_tries;		  /**< Max channels tried    */
+	s32 skip;	  /**< Minimum frequency step to take
+					after a channel is found */
+	void *ext_params;	  /**< Standard specific params */
+};
+
+/*========================================*/
+
+/**
+* \brief Scan commands.
+* Used by scanning algorithms.
+*/
+enum drx_scan_command {
+		DRX_SCAN_COMMAND_INIT = 0,/**< Initialize scanning */
+		DRX_SCAN_COMMAND_NEXT,	  /**< Next scan           */
+		DRX_SCAN_COMMAND_STOP	  /**< Stop scanning       */
+};
+
+/*========================================*/
+
+/**
+* \brief Inner scan function prototype.
+*/
+typedef int(*drx_scan_func_t) (void *scan_context,
+				     enum drx_scan_command scan_command,
+				     struct drx_channel *scan_channel,
+				     bool *get_next_channel);
+
+/*========================================*/
+
+/**
+* \struct struct drxtps_info * TPS information, DVB-T specific.
+*
+* Used by DRX_CTRL_TPS_INFO.
+*/
+	struct drxtps_info {
+		enum drx_fft_mode fftmode;	/**< Fft mode       */
+		enum drx_guard guard;	/**< Guard interval */
+		enum drx_modulation constellation;
+					/**< Constellation  */
+		enum drx_hierarchy hierarchy;
+					/**< Hierarchy      */
+		enum drx_coderate high_coderate;
+					/**< High code rate */
+		enum drx_coderate low_coderate;
+					/**< Low cod rate   */
+		enum drx_tps_frame frame;	/**< Tps frame      */
+		u8 length;		/**< Length         */
+		u16 cell_id;		/**< Cell id        */
+	};
+
+/*========================================*/
+
+/**
+* \brief Power mode of device.
+*
+* Used by DRX_CTRL_SET_POWER_MODE.
+*/
+	enum drx_power_mode {
+		DRX_POWER_UP = 0,
+			 /**< Generic         , Power Up Mode   */
+		DRX_POWER_MODE_1,
+			 /**< Device specific , Power Up Mode   */
+		DRX_POWER_MODE_2,
+			 /**< Device specific , Power Up Mode   */
+		DRX_POWER_MODE_3,
+			 /**< Device specific , Power Up Mode   */
+		DRX_POWER_MODE_4,
+			 /**< Device specific , Power Up Mode   */
+		DRX_POWER_MODE_5,
+			 /**< Device specific , Power Up Mode   */
+		DRX_POWER_MODE_6,
+			 /**< Device specific , Power Up Mode   */
+		DRX_POWER_MODE_7,
+			 /**< Device specific , Power Up Mode   */
+		DRX_POWER_MODE_8,
+			 /**< Device specific , Power Up Mode   */
+
+		DRX_POWER_MODE_9,
+			 /**< Device specific , Power Down Mode */
+		DRX_POWER_MODE_10,
+			 /**< Device specific , Power Down Mode */
+		DRX_POWER_MODE_11,
+			 /**< Device specific , Power Down Mode */
+		DRX_POWER_MODE_12,
+			 /**< Device specific , Power Down Mode */
+		DRX_POWER_MODE_13,
+			 /**< Device specific , Power Down Mode */
+		DRX_POWER_MODE_14,
+			 /**< Device specific , Power Down Mode */
+		DRX_POWER_MODE_15,
+			 /**< Device specific , Power Down Mode */
+		DRX_POWER_MODE_16,
+			 /**< Device specific , Power Down Mode */
+		DRX_POWER_DOWN = 255
+			 /**< Generic         , Power Down Mode */
+	};
+
+/*========================================*/
+
+/**
+* \enum enum drx_module * \brief Software module identification.
+*
+* Used by DRX_CTRL_VERSION.
+*/
+	enum drx_module {
+		DRX_MODULE_DEVICE,
+		DRX_MODULE_MICROCODE,
+		DRX_MODULE_DRIVERCORE,
+		DRX_MODULE_DEVICEDRIVER,
+		DRX_MODULE_DAP,
+		DRX_MODULE_BSP_I2C,
+		DRX_MODULE_BSP_TUNER,
+		DRX_MODULE_BSP_HOST,
+		DRX_MODULE_UNKNOWN
+	};
+
+/**
+* \enum struct drx_version * \brief Version information of one software module.
+*
+* Used by DRX_CTRL_VERSION.
+*/
+	struct drx_version {
+		enum drx_module module_type;
+			       /**< Type identifier of the module */
+		char *module_name;
+			       /**< Name or description of module */
+		u16 v_major;  /**< Major version number          */
+		u16 v_minor;  /**< Minor version number          */
+		u16 v_patch;  /**< Patch version number          */
+		char *v_string; /**< Version as text string        */
+	};
+
+/**
+* \enum struct drx_version_list * \brief List element of NULL terminated, linked list for version information.
+*
+* Used by DRX_CTRL_VERSION.
+*/
+struct drx_version_list {
+	struct drx_version *version;/**< Version information */
+	struct drx_version_list *next;
+			      /**< Next list element   */
+};
+
+/*========================================*/
+
+/**
+* \brief Parameters needed to confiugure a UIO.
+*
+* Used by DRX_CTRL_UIO_CFG.
+*/
+	struct drxuio_cfg {
+		enum drx_uio uio;
+		       /**< UIO identifier       */
+		enum drxuio_mode mode;
+		       /**< UIO operational mode */
+	};
+
+/*========================================*/
+
+/**
+* \brief Parameters needed to read from or write to a UIO.
+*
+* Used by DRX_CTRL_UIO_READ and DRX_CTRL_UIO_WRITE.
+*/
+	struct drxuio_data {
+		enum drx_uio uio;
+		   /**< UIO identifier              */
+		bool value;
+		   /**< UIO value (true=1, false=0) */
+	};
+
+/*========================================*/
+
+/**
+* \brief Parameters needed to configure OOB.
+*
+* Used by DRX_CTRL_SET_OOB.
+*/
+	struct drxoob {
+		s32 frequency;	   /**< Frequency in kHz      */
+		enum drxoob_downstream_standard standard;
+						   /**< OOB standard          */
+		bool spectrum_inverted;	   /**< If true, then spectrum
+							 is inverted          */
+	};
+
+/*========================================*/
+
+/**
+* \brief Metrics from OOB.
+*
+* Used by DRX_CTRL_GET_OOB.
+*/
+	struct drxoob_status {
+		s32 frequency; /**< Frequency in Khz         */
+		enum drx_lock_status lock;	  /**< Lock status              */
+		u32 mer;		  /**< MER                      */
+		s32 symbol_rate_offset;	  /**< Symbolrate offset in ppm */
+	};
+
+/*========================================*/
+
+/**
+* \brief Device dependent configuration data.
+*
+* Used by DRX_CTRL_SET_CFG and DRX_CTRL_GET_CFG.
+* A sort of nested drx_ctrl() functionality for device specific controls.
+*/
+	struct drx_cfg {
+		u32 cfg_type;
+			  /**< Function identifier */
+		void *cfg_data;
+			  /**< Function data */
+	};
+
+/*========================================*/
+
+/**
+* /struct DRXMpegStartWidth_t
+* MStart width [nr MCLK cycles] for serial MPEG output.
+*/
+
+	enum drxmpeg_str_width {
+		DRX_MPEG_STR_WIDTH_1,
+		DRX_MPEG_STR_WIDTH_8
+	};
+
+/* CTRL CFG MPEG ouput */
+/**
+* \struct struct drx_cfg_mpeg_output * \brief Configuartion parameters for MPEG output control.
+*
+* Used by DRX_CFG_MPEG_OUTPUT, in combination with DRX_CTRL_SET_CFG and
+* DRX_CTRL_GET_CFG.
+*/
+
+	struct drx_cfg_mpeg_output {
+		bool enable_mpeg_output;/**< If true, enable MPEG output      */
+		bool insert_rs_byte;	/**< If true, insert RS byte          */
+		bool enable_parallel;	/**< If true, parallel out otherwise
+								     serial   */
+		bool invert_data;	/**< If true, invert DATA signals     */
+		bool invert_err;	/**< If true, invert ERR signal       */
+		bool invert_str;	/**< If true, invert STR signals      */
+		bool invert_val;	/**< If true, invert VAL signals      */
+		bool invert_clk;	/**< If true, invert CLK signals      */
+		bool static_clk;	/**< If true, static MPEG clockrate
+					     will be used, otherwise clockrate
+					     will adapt to the bitrate of the
+					     TS                               */
+		u32 bitrate;		/**< Maximum bitrate in b/s in case
+					     static clockrate is selected     */
+		enum drxmpeg_str_width width_str;
+					/**< MPEG start width                 */
+	};
+
+
+/*========================================*/
+
+/**
+* \struct struct drxi2c_data * \brief Data for I2C via 2nd or 3rd or etc I2C port.
+*
+* Used by DRX_CTRL_I2C_READWRITE.
+* If port_nr is equal to primairy port_nr BSPI2C will be used.
+*
+*/
+	struct drxi2c_data {
+		u16 port_nr;	/**< I2C port number               */
+		struct i2c_device_addr *w_dev_addr;
+				/**< Write device address          */
+		u16 w_count;	/**< Size of write data in bytes   */
+		u8 *wData;	/**< Pointer to write data         */
+		struct i2c_device_addr *r_dev_addr;
+				/**< Read device address           */
+		u16 r_count;	/**< Size of data to read in bytes */
+		u8 *r_data;	/**< Pointer to read buffer        */
+	};
+
+/*========================================*/
+
+/**
+* \enum enum drx_aud_standard * \brief Audio standard identifier.
+*
+* Used by DRX_CTRL_SET_AUD.
+*/
+	enum drx_aud_standard {
+		DRX_AUD_STANDARD_BTSC,	   /**< set BTSC standard (USA)       */
+		DRX_AUD_STANDARD_A2,	   /**< set A2-Korea FM Stereo        */
+		DRX_AUD_STANDARD_EIAJ,	   /**< set to Japanese FM Stereo     */
+		DRX_AUD_STANDARD_FM_STEREO,/**< set to FM-Stereo Radio        */
+		DRX_AUD_STANDARD_M_MONO,   /**< for 4.5 MHz mono detected     */
+		DRX_AUD_STANDARD_D_K_MONO, /**< for 6.5 MHz mono detected     */
+		DRX_AUD_STANDARD_BG_FM,	   /**< set BG_FM standard            */
+		DRX_AUD_STANDARD_D_K1,	   /**< set D_K1 standard             */
+		DRX_AUD_STANDARD_D_K2,	   /**< set D_K2 standard             */
+		DRX_AUD_STANDARD_D_K3,	   /**< set D_K3 standard             */
+		DRX_AUD_STANDARD_BG_NICAM_FM,
+					   /**< set BG_NICAM_FM standard      */
+		DRX_AUD_STANDARD_L_NICAM_AM,
+					   /**< set L_NICAM_AM standard       */
+		DRX_AUD_STANDARD_I_NICAM_FM,
+					   /**< set I_NICAM_FM standard       */
+		DRX_AUD_STANDARD_D_K_NICAM_FM,
+					   /**< set D_K_NICAM_FM standard     */
+		DRX_AUD_STANDARD_NOT_READY,/**< used to detect audio standard */
+		DRX_AUD_STANDARD_AUTO = DRX_AUTO,
+					   /**< Automatic Standard Detection  */
+		DRX_AUD_STANDARD_UNKNOWN = DRX_UNKNOWN
+					   /**< used as auto and for readback */
+	};
+
+/* CTRL_AUD_GET_STATUS    - struct drx_aud_status */
+/**
+* \enum enum drx_aud_nicam_status * \brief Status of NICAM carrier.
+*/
+	enum drx_aud_nicam_status {
+		DRX_AUD_NICAM_DETECTED = 0,
+					  /**< NICAM carrier detected         */
+		DRX_AUD_NICAM_NOT_DETECTED,
+					  /**< NICAM carrier not detected     */
+		DRX_AUD_NICAM_BAD	  /**< NICAM carrier bad quality      */
+	};
+
+/**
+* \struct struct drx_aud_status * \brief Audio status characteristics.
+*/
+	struct drx_aud_status {
+		bool stereo;		  /**< stereo detection               */
+		bool carrier_a;	  /**< carrier A detected             */
+		bool carrier_b;	  /**< carrier B detected             */
+		bool sap;		  /**< sap / bilingual detection      */
+		bool rds;		  /**< RDS data array present         */
+		enum drx_aud_nicam_status nicam_status;
+					  /**< status of NICAM carrier        */
+		s8 fm_ident;		  /**< FM Identification value        */
+	};
+
+/* CTRL_AUD_READ_RDS       - DRXRDSdata_t */
+
+/**
+* \struct DRXRDSdata_t
+* \brief Raw RDS data array.
+*/
+	struct drx_cfg_aud_rds {
+		bool valid;		  /**< RDS data validation            */
+		u16 data[18];		  /**< data from one RDS data array   */
+	};
+
+/* DRX_CFG_AUD_VOLUME      - struct drx_cfg_aud_volume - set/get */
+/**
+* \enum DRXAudAVCDecayTime_t
+* \brief Automatic volume control configuration.
+*/
+	enum drx_aud_avc_mode {
+		DRX_AUD_AVC_OFF,	  /**< Automatic volume control off   */
+		DRX_AUD_AVC_DECAYTIME_8S, /**< level volume in  8 seconds     */
+		DRX_AUD_AVC_DECAYTIME_4S, /**< level volume in  4 seconds     */
+		DRX_AUD_AVC_DECAYTIME_2S, /**< level volume in  2 seconds     */
+		DRX_AUD_AVC_DECAYTIME_20MS/**< level volume in 20 millisec    */
+	};
+
+/**
+* /enum DRXAudMaxAVCGain_t
+* /brief Automatic volume control max gain in audio baseband.
+*/
+	enum drx_aud_avc_max_gain {
+		DRX_AUD_AVC_MAX_GAIN_0DB, /**< maximum AVC gain  0 dB         */
+		DRX_AUD_AVC_MAX_GAIN_6DB, /**< maximum AVC gain  6 dB         */
+		DRX_AUD_AVC_MAX_GAIN_12DB /**< maximum AVC gain 12 dB         */
+	};
+
+/**
+* /enum DRXAudMaxAVCAtten_t
+* /brief Automatic volume control max attenuation in audio baseband.
+*/
+	enum drx_aud_avc_max_atten {
+		DRX_AUD_AVC_MAX_ATTEN_12DB,
+					  /**< maximum AVC attenuation 12 dB  */
+		DRX_AUD_AVC_MAX_ATTEN_18DB,
+					  /**< maximum AVC attenuation 18 dB  */
+		DRX_AUD_AVC_MAX_ATTEN_24DB/**< maximum AVC attenuation 24 dB  */
+	};
+/**
+* \struct struct drx_cfg_aud_volume * \brief Audio volume configuration.
+*/
+	struct drx_cfg_aud_volume {
+		bool mute;		  /**< mute overrides volume setting  */
+		s16 volume;		  /**< volume, range -114 to 12 dB    */
+		enum drx_aud_avc_mode avc_mode;  /**< AVC auto volume control mode   */
+		u16 avc_ref_level;	  /**< AVC reference level            */
+		enum drx_aud_avc_max_gain avc_max_gain;
+					  /**< AVC max gain selection         */
+		enum drx_aud_avc_max_atten avc_max_atten;
+					  /**< AVC max attenuation selection  */
+		s16 strength_left;	  /**< quasi-peak, left speaker       */
+		s16 strength_right;	  /**< quasi-peak, right speaker      */
+	};
+
+/* DRX_CFG_I2S_OUTPUT      - struct drx_cfg_i2s_output - set/get */
+/**
+* \enum enum drxi2s_mode * \brief I2S output mode.
+*/
+	enum drxi2s_mode {
+		DRX_I2S_MODE_MASTER,	  /**< I2S is in master mode          */
+		DRX_I2S_MODE_SLAVE	  /**< I2S is in slave mode           */
+	};
+
+/**
+* \enum enum drxi2s_word_length * \brief Width of I2S data.
+*/
+	enum drxi2s_word_length {
+		DRX_I2S_WORDLENGTH_32 = 0,/**< I2S data is 32 bit wide        */
+		DRX_I2S_WORDLENGTH_16 = 1 /**< I2S data is 16 bit wide        */
+	};
+
+/**
+* \enum enum drxi2s_format * \brief Data wordstrobe alignment for I2S.
+*/
+	enum drxi2s_format {
+		DRX_I2S_FORMAT_WS_WITH_DATA,
+				    /**< I2S data and wordstrobe are aligned  */
+		DRX_I2S_FORMAT_WS_ADVANCED
+				    /**< I2S data one cycle after wordstrobe  */
+	};
+
+/**
+* \enum enum drxi2s_polarity * \brief Polarity of I2S data.
+*/
+	enum drxi2s_polarity {
+		DRX_I2S_POLARITY_RIGHT,/**< wordstrobe - right high, left low */
+		DRX_I2S_POLARITY_LEFT  /**< wordstrobe - right low, left high */
+	};
+
+/**
+* \struct struct drx_cfg_i2s_output * \brief I2S output configuration.
+*/
+	struct drx_cfg_i2s_output {
+		bool output_enable;	  /**< I2S output enable              */
+		u32 frequency;	  /**< range from 8000-48000 Hz       */
+		enum drxi2s_mode mode;	  /**< I2S mode, master or slave      */
+		enum drxi2s_word_length word_length;
+					  /**< I2S wordlength, 16 or 32 bits  */
+		enum drxi2s_polarity polarity;/**< I2S wordstrobe polarity        */
+		enum drxi2s_format format;	  /**< I2S wordstrobe delay to data   */
+	};
+
+/* ------------------------------expert interface-----------------------------*/
+/**
+* /enum enum drx_aud_fm_deemphasis * setting for FM-Deemphasis in audio demodulator.
+*
+*/
+	enum drx_aud_fm_deemphasis {
+		DRX_AUD_FM_DEEMPH_50US,
+		DRX_AUD_FM_DEEMPH_75US,
+		DRX_AUD_FM_DEEMPH_OFF
+	};
+
+/**
+* /enum DRXAudDeviation_t
+* setting for deviation mode in audio demodulator.
+*
+*/
+	enum drx_cfg_aud_deviation {
+		DRX_AUD_DEVIATION_NORMAL,
+		DRX_AUD_DEVIATION_HIGH
+	};
+
+/**
+* /enum enum drx_no_carrier_option * setting for carrier, mute/noise.
+*
+*/
+	enum drx_no_carrier_option {
+		DRX_NO_CARRIER_MUTE,
+		DRX_NO_CARRIER_NOISE
+	};
+
+/**
+* \enum DRXAudAutoSound_t
+* \brief Automatic Sound
+*/
+	enum drx_cfg_aud_auto_sound {
+		DRX_AUD_AUTO_SOUND_OFF = 0,
+		DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_ON,
+		DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_OFF
+	};
+
+/**
+* \enum DRXAudASSThres_t
+* \brief Automatic Sound Select Thresholds
+*/
+	struct drx_cfg_aud_ass_thres {
+		u16 a2;	/* A2 Threshold for ASS configuration */
+		u16 btsc;	/* BTSC Threshold for ASS configuration */
+		u16 nicam;	/* Nicam Threshold for ASS configuration */
+	};
+
+/**
+* \struct struct drx_aud_carrier * \brief Carrier detection related parameters
+*/
+	struct drx_aud_carrier {
+		u16 thres;	/* carrier detetcion threshold for primary carrier (A) */
+		enum drx_no_carrier_option opt;	/* Mute or noise at no carrier detection (A) */
+		s32 shift;	/* DC level of incoming signal (A) */
+		s32 dco;	/* frequency adjustment (A) */
+	};
+
+/**
+* \struct struct drx_cfg_aud_carriers * \brief combining carrier A & B to one struct
+*/
+	struct drx_cfg_aud_carriers {
+		struct drx_aud_carrier a;
+		struct drx_aud_carrier b;
+	};
+
+/**
+* /enum enum drx_aud_i2s_src * Selection of audio source
+*/
+	enum drx_aud_i2s_src {
+		DRX_AUD_SRC_MONO,
+		DRX_AUD_SRC_STEREO_OR_AB,
+		DRX_AUD_SRC_STEREO_OR_A,
+		DRX_AUD_SRC_STEREO_OR_B};
+
+/**
+* \enum enum drx_aud_i2s_matrix * \brief Used for selecting I2S output.
+*/
+	enum drx_aud_i2s_matrix {
+		DRX_AUD_I2S_MATRIX_A_MONO,
+					/**< A sound only, stereo or mono     */
+		DRX_AUD_I2S_MATRIX_B_MONO,
+					/**< B sound only, stereo or mono     */
+		DRX_AUD_I2S_MATRIX_STEREO,
+					/**< A+B sound, transparant           */
+		DRX_AUD_I2S_MATRIX_MONO	/**< A+B mixed to mono sum, (L+R)/2   */};
+
+/**
+* /enum enum drx_aud_fm_matrix * setting for FM-Matrix in audio demodulator.
+*
+*/
+	enum drx_aud_fm_matrix {
+		DRX_AUD_FM_MATRIX_NO_MATRIX,
+		DRX_AUD_FM_MATRIX_GERMAN,
+		DRX_AUD_FM_MATRIX_KOREAN,
+		DRX_AUD_FM_MATRIX_SOUND_A,
+		DRX_AUD_FM_MATRIX_SOUND_B};
+
+/**
+* \struct DRXAudMatrices_t
+* \brief Mixer settings
+*/
+struct drx_cfg_aud_mixer {
+	enum drx_aud_i2s_src source_i2s;
+	enum drx_aud_i2s_matrix matrix_i2s;
+	enum drx_aud_fm_matrix matrix_fm;
+};
+
+/**
+* \enum DRXI2SVidSync_t
+* \brief Audio/video synchronization, interacts with I2S mode.
+* AUTO_1 and AUTO_2 are for automatic video standard detection with preference
+* for NTSC or Monochrome, because the frequencies are too close (59.94 & 60 Hz)
+*/
+	enum drx_cfg_aud_av_sync {
+		DRX_AUD_AVSYNC_OFF,/**< audio/video synchronization is off   */
+		DRX_AUD_AVSYNC_NTSC,
+				   /**< it is an NTSC system                 */
+		DRX_AUD_AVSYNC_MONOCHROME,
+				   /**< it is a MONOCHROME system            */
+		DRX_AUD_AVSYNC_PAL_SECAM
+				   /**< it is a PAL/SECAM system             */};
+
+/**
+* \struct struct drx_cfg_aud_prescale * \brief Prescalers
+*/
+struct drx_cfg_aud_prescale {
+	u16 fm_deviation;
+	s16 nicam_gain;
+};
+
+/**
+* \struct struct drx_aud_beep * \brief Beep
+*/
+struct drx_aud_beep {
+	s16 volume;	/* dB */
+	u16 frequency;	/* Hz */
+	bool mute;
+};
+
+/**
+* \enum enum drx_aud_btsc_detect * \brief BTSC detetcion mode
+*/
+	enum drx_aud_btsc_detect {
+		DRX_BTSC_STEREO,
+		DRX_BTSC_MONO_AND_SAP};
+
+/**
+* \struct struct drx_aud_data * \brief Audio data structure
+*/
+struct drx_aud_data {
+	/* audio storage */
+	bool audio_is_active;
+	enum drx_aud_standard audio_standard;
+	struct drx_cfg_i2s_output i2sdata;
+	struct drx_cfg_aud_volume volume;
+	enum drx_cfg_aud_auto_sound auto_sound;
+	struct drx_cfg_aud_ass_thres ass_thresholds;
+	struct drx_cfg_aud_carriers carriers;
+	struct drx_cfg_aud_mixer mixer;
+	enum drx_cfg_aud_deviation deviation;
+	enum drx_cfg_aud_av_sync av_sync;
+	struct drx_cfg_aud_prescale prescale;
+	enum drx_aud_fm_deemphasis deemph;
+	enum drx_aud_btsc_detect btsc_detect;
+	/* rds */
+	u16 rds_data_counter;
+	bool rds_data_present;
+};
+
+/**
+* \enum enum drx_qam_lock_range * \brief QAM lock range mode
+*/
+	enum drx_qam_lock_range {
+		DRX_QAM_LOCKRANGE_NORMAL,
+		DRX_QAM_LOCKRANGE_EXTENDED};
+
+/*============================================================================*/
+/*============================================================================*/
+/*== Data access structures ==================================================*/
+/*============================================================================*/
+/*============================================================================*/
+
+/* Address on device */
+	typedef u32 dr_xaddr_t, *pdr_xaddr_t;
+
+/* Protocol specific flags */
+	typedef u32 dr_xflags_t, *pdr_xflags_t;
+
+/* Write block of data to device */
+	typedef int(*drx_write_block_func_t) (struct i2c_device_addr *dev_addr,	/* address of I2C device        */
+						   u32 addr,	/* address of register/memory   */
+						   u16 datasize,	/* size of data in bytes        */
+						   u8 *data,	/* data to send                 */
+						   u32 flags);
+
+/* Read block of data from device */
+	typedef int(*drx_read_block_func_t) (struct i2c_device_addr *dev_addr,	/* address of I2C device        */
+						  u32 addr,	/* address of register/memory   */
+						  u16 datasize,	/* size of data in bytes        */
+						  u8 *data,	/* receive buffer               */
+						  u32 flags);
+
+/* Write 8-bits value to device */
+	typedef int(*drx_write_reg8func_t) (struct i2c_device_addr *dev_addr,	/* address of I2C device        */
+						  u32 addr,	/* address of register/memory   */
+						  u8 data,	/* data to send                 */
+						  u32 flags);
+
+/* Read 8-bits value to device */
+	typedef int(*drx_read_reg8func_t) (struct i2c_device_addr *dev_addr,	/* address of I2C device        */
+						 u32 addr,	/* address of register/memory   */
+						 u8 *data,	/* receive buffer               */
+						 u32 flags);
+
+/* Read modify write 8-bits value to device */
+	typedef int(*drx_read_modify_write_reg8func_t) (struct i2c_device_addr *dev_addr,	/* address of I2C device       */
+							    u32 waddr,	/* write address of register   */
+							    u32 raddr,	/* read  address of register   */
+							    u8 wdata,	/* data to write               */
+							    u8 *rdata);	/* data to read                */
+
+/* Write 16-bits value to device */
+	typedef int(*drx_write_reg16func_t) (struct i2c_device_addr *dev_addr,	/* address of I2C device        */
+						   u32 addr,	/* address of register/memory   */
+						   u16 data,	/* data to send                 */
+						   u32 flags);
+
+/* Read 16-bits value to device */
+	typedef int(*drx_read_reg16func_t) (struct i2c_device_addr *dev_addr,	/* address of I2C device        */
+						  u32 addr,	/* address of register/memory   */
+						  u16 *data,	/* receive buffer               */
+						  u32 flags);
+
+/* Read modify write 16-bits value to device */
+	typedef int(*drx_read_modify_write_reg16func_t) (struct i2c_device_addr *dev_addr,	/* address of I2C device       */
+							     u32 waddr,	/* write address of register   */
+							     u32 raddr,	/* read  address of register   */
+							     u16 wdata,	/* data to write               */
+							     u16 *rdata);	/* data to read                */
+
+/* Write 32-bits value to device */
+	typedef int(*drx_write_reg32func_t) (struct i2c_device_addr *dev_addr,	/* address of I2C device        */
+						   u32 addr,	/* address of register/memory   */
+						   u32 data,	/* data to send                 */
+						   u32 flags);
+
+/* Read 32-bits value to device */
+	typedef int(*drx_read_reg32func_t) (struct i2c_device_addr *dev_addr,	/* address of I2C device        */
+						  u32 addr,	/* address of register/memory   */
+						  u32 *data,	/* receive buffer               */
+						  u32 flags);
+
+/* Read modify write 32-bits value to device */
+	typedef int(*drx_read_modify_write_reg32func_t) (struct i2c_device_addr *dev_addr,	/* address of I2C device       */
+							     u32 waddr,	/* write address of register   */
+							     u32 raddr,	/* read  address of register   */
+							     u32 wdata,	/* data to write               */
+							     u32 *rdata);	/* data to read                */
+
+/**
+* \struct struct drx_access_func * \brief Interface to an access protocol.
+*/
+struct drx_access_func {
+	drx_write_block_func_t write_block_func;
+	drx_read_block_func_t read_block_func;
+	drx_write_reg8func_t write_reg8func;
+	drx_read_reg8func_t read_reg8func;
+	drx_read_modify_write_reg8func_t read_modify_write_reg8func;
+	drx_write_reg16func_t write_reg16func;
+	drx_read_reg16func_t read_reg16func;
+	drx_read_modify_write_reg16func_t read_modify_write_reg16func;
+	drx_write_reg32func_t write_reg32func;
+	drx_read_reg32func_t read_reg32func;
+	drx_read_modify_write_reg32func_t read_modify_write_reg32func;
+};
+
+/* Register address and data for register dump function */
+struct drx_reg_dump {
+	u32 address;
+	u32 data;
+};
+
+/*============================================================================*/
+/*============================================================================*/
+/*== Demod instance data structures ==========================================*/
+/*============================================================================*/
+/*============================================================================*/
+
+/**
+* \struct struct drx_common_attr * \brief Set of common attributes, shared by all DRX devices.
+*/
+	struct drx_common_attr {
+		/* Microcode (firmware) attributes */
+		char *microcode_file;   /**<  microcode filename           */
+		bool verify_microcode;
+				   /**< Use microcode verify or not.          */
+		struct drx_mc_version_rec mcversion;
+				   /**< Version record of microcode from file */
+
+		/* Clocks and tuner attributes */
+		s32 intermediate_freq;
+				     /**< IF,if tuner instance not used. (kHz)*/
+		s32 sys_clock_freq;
+				     /**< Systemclock frequency.  (kHz)       */
+		s32 osc_clock_freq;
+				     /**< Oscillator clock frequency.  (kHz)  */
+		s16 osc_clock_deviation;
+				     /**< Oscillator clock deviation.  (ppm)  */
+		bool mirror_freq_spect;
+				     /**< Mirror IF frequency spectrum or not.*/
+
+		/* Initial MPEG output attributes */
+		struct drx_cfg_mpeg_output mpeg_cfg;
+				     /**< MPEG configuration                  */
+
+		bool is_opened;     /**< if true instance is already opened. */
+
+		/* Channel scan */
+		struct drx_scan_param *scan_param;
+				      /**< scan parameters                    */
+		u16 scan_freq_plan_index;
+				      /**< next index in freq plan            */
+		s32 scan_next_frequency;
+				      /**< next freq to scan                  */
+		bool scan_ready;     /**< scan ready flag                    */
+		u32 scan_max_channels;/**< number of channels in freqplan     */
+		u32 scan_channels_scanned;
+					/**< number of channels scanned       */
+		/* Channel scan - inner loop: demod related */
+		drx_scan_func_t scan_function;
+				      /**< function to check channel          */
+		/* Channel scan - inner loop: SYSObj related */
+		void *scan_context;    /**< Context Pointer of SYSObj          */
+		/* Channel scan - parameters for default DTV scan function in core driver  */
+		u16 scan_demod_lock_timeout;
+					 /**< millisecs to wait for lock      */
+		enum drx_lock_status scan_desired_lock;
+				      /**< lock requirement for channel found */
+		/* scan_active can be used by SetChannel to decide how to program the tuner,
+		   fast or slow (but stable). Usually fast during scan. */
+		bool scan_active;    /**< true when scan routines are active */
+
+		/* Power management */
+		enum drx_power_mode current_power_mode;
+				      /**< current power management mode      */
+
+		/* Tuner */
+		u8 tuner_port_nr;     /**< nr of I2C port to wich tuner is    */
+		s32 tuner_min_freq_rf;
+				      /**< minimum RF input frequency, in kHz */
+		s32 tuner_max_freq_rf;
+				      /**< maximum RF input frequency, in kHz */
+		bool tuner_rf_agc_pol; /**< if true invert RF AGC polarity     */
+		bool tuner_if_agc_pol; /**< if true invert IF AGC polarity     */
+		bool tuner_slow_mode; /**< if true invert IF AGC polarity     */
+
+		struct drx_channel current_channel;
+				      /**< current channel parameters         */
+		enum drx_standard current_standard;
+				      /**< current standard selection         */
+		enum drx_standard prev_standard;
+				      /**< previous standard selection        */
+		enum drx_standard di_cache_standard;
+				      /**< standard in DI cache if available  */
+		bool use_bootloader; /**< use bootloader in open             */
+		u32 capabilities;   /**< capabilities flags                 */
+		u32 product_id;      /**< product ID inc. metal fix number   */};
+
+/*
+* Generic functions for DRX devices.
+*/
+
+struct drx_demod_instance;
+
+/**
+* \struct struct drx_demod_instance * \brief Top structure of demodulator instance.
+*/
+struct drx_demod_instance {
+				/**< data access protocol functions       */
+	struct i2c_device_addr *my_i2c_dev_addr;
+				/**< i2c address and device identifier    */
+	struct drx_common_attr *my_common_attr;
+				/**< common DRX attributes                */
+	void *my_ext_attr;    /**< device specific attributes           */
+	/* generic demodulator data */
+
+	struct i2c_adapter	*i2c;
+	const struct firmware	*firmware;
+};
+
+/*-------------------------------------------------------------------------
+MACROS
+Conversion from enum values to human readable form.
+-------------------------------------------------------------------------*/
+
+/* standard */
+
+#define DRX_STR_STANDARD(x) ( \
+	(x == DRX_STANDARD_DVBT)  ? "DVB-T"            : \
+	(x == DRX_STANDARD_8VSB)  ? "8VSB"             : \
+	(x == DRX_STANDARD_NTSC)  ? "NTSC"             : \
+	(x == DRX_STANDARD_PAL_SECAM_BG)  ? "PAL/SECAM B/G"    : \
+	(x == DRX_STANDARD_PAL_SECAM_DK)  ? "PAL/SECAM D/K"    : \
+	(x == DRX_STANDARD_PAL_SECAM_I)  ? "PAL/SECAM I"      : \
+	(x == DRX_STANDARD_PAL_SECAM_L)  ? "PAL/SECAM L"      : \
+	(x == DRX_STANDARD_PAL_SECAM_LP)  ? "PAL/SECAM LP"     : \
+	(x == DRX_STANDARD_ITU_A)  ? "ITU-A"            : \
+	(x == DRX_STANDARD_ITU_B)  ? "ITU-B"            : \
+	(x == DRX_STANDARD_ITU_C)  ? "ITU-C"            : \
+	(x == DRX_STANDARD_ITU_D)  ? "ITU-D"            : \
+	(x == DRX_STANDARD_FM)  ? "FM"               : \
+	(x == DRX_STANDARD_DTMB)  ? "DTMB"             : \
+	(x == DRX_STANDARD_AUTO)  ? "Auto"             : \
+	(x == DRX_STANDARD_UNKNOWN)  ? "Unknown"          : \
+	"(Invalid)")
+
+/* channel */
+
+#define DRX_STR_BANDWIDTH(x) ( \
+	(x == DRX_BANDWIDTH_8MHZ)  ?  "8 MHz"            : \
+	(x == DRX_BANDWIDTH_7MHZ)  ?  "7 MHz"            : \
+	(x == DRX_BANDWIDTH_6MHZ)  ?  "6 MHz"            : \
+	(x == DRX_BANDWIDTH_AUTO)  ?  "Auto"             : \
+	(x == DRX_BANDWIDTH_UNKNOWN)  ?  "Unknown"          : \
+	"(Invalid)")
+#define DRX_STR_FFTMODE(x) ( \
+	(x == DRX_FFTMODE_2K)  ?  "2k"               : \
+	(x == DRX_FFTMODE_4K)  ?  "4k"               : \
+	(x == DRX_FFTMODE_8K)  ?  "8k"               : \
+	(x == DRX_FFTMODE_AUTO)  ?  "Auto"             : \
+	(x == DRX_FFTMODE_UNKNOWN)  ?  "Unknown"          : \
+	"(Invalid)")
+#define DRX_STR_GUARD(x) ( \
+	(x == DRX_GUARD_1DIV32)  ?  "1/32nd"           : \
+	(x == DRX_GUARD_1DIV16)  ?  "1/16th"           : \
+	(x == DRX_GUARD_1DIV8)  ?  "1/8th"            : \
+	(x == DRX_GUARD_1DIV4)  ?  "1/4th"            : \
+	(x == DRX_GUARD_AUTO)  ?  "Auto"             : \
+	(x == DRX_GUARD_UNKNOWN)  ?  "Unknown"          : \
+	"(Invalid)")
+#define DRX_STR_CONSTELLATION(x) ( \
+	(x == DRX_CONSTELLATION_BPSK)  ?  "BPSK"            : \
+	(x == DRX_CONSTELLATION_QPSK)  ?  "QPSK"            : \
+	(x == DRX_CONSTELLATION_PSK8)  ?  "PSK8"            : \
+	(x == DRX_CONSTELLATION_QAM16)  ?  "QAM16"           : \
+	(x == DRX_CONSTELLATION_QAM32)  ?  "QAM32"           : \
+	(x == DRX_CONSTELLATION_QAM64)  ?  "QAM64"           : \
+	(x == DRX_CONSTELLATION_QAM128)  ?  "QAM128"          : \
+	(x == DRX_CONSTELLATION_QAM256)  ?  "QAM256"          : \
+	(x == DRX_CONSTELLATION_QAM512)  ?  "QAM512"          : \
+	(x == DRX_CONSTELLATION_QAM1024)  ?  "QAM1024"         : \
+	(x == DRX_CONSTELLATION_QPSK_NR)  ?  "QPSK_NR"            : \
+	(x == DRX_CONSTELLATION_AUTO)  ?  "Auto"            : \
+	(x == DRX_CONSTELLATION_UNKNOWN)  ?  "Unknown"         : \
+	"(Invalid)")
+#define DRX_STR_CODERATE(x) ( \
+	(x == DRX_CODERATE_1DIV2)  ?  "1/2nd"           : \
+	(x == DRX_CODERATE_2DIV3)  ?  "2/3rd"           : \
+	(x == DRX_CODERATE_3DIV4)  ?  "3/4th"           : \
+	(x == DRX_CODERATE_5DIV6)  ?  "5/6th"           : \
+	(x == DRX_CODERATE_7DIV8)  ?  "7/8th"           : \
+	(x == DRX_CODERATE_AUTO)  ?  "Auto"            : \
+	(x == DRX_CODERATE_UNKNOWN)  ?  "Unknown"         : \
+	"(Invalid)")
+#define DRX_STR_HIERARCHY(x) ( \
+	(x == DRX_HIERARCHY_NONE)  ?  "None"            : \
+	(x == DRX_HIERARCHY_ALPHA1)  ?  "Alpha=1"         : \
+	(x == DRX_HIERARCHY_ALPHA2)  ?  "Alpha=2"         : \
+	(x == DRX_HIERARCHY_ALPHA4)  ?  "Alpha=4"         : \
+	(x == DRX_HIERARCHY_AUTO)  ?  "Auto"            : \
+	(x == DRX_HIERARCHY_UNKNOWN)  ?  "Unknown"         : \
+	"(Invalid)")
+#define DRX_STR_PRIORITY(x) ( \
+	(x == DRX_PRIORITY_LOW)  ?  "Low"             : \
+	(x == DRX_PRIORITY_HIGH)  ?  "High"            : \
+	(x == DRX_PRIORITY_UNKNOWN)  ?  "Unknown"         : \
+	"(Invalid)")
+#define DRX_STR_MIRROR(x) ( \
+	(x == DRX_MIRROR_NO)  ?  "Normal"          : \
+	(x == DRX_MIRROR_YES)  ?  "Mirrored"        : \
+	(x == DRX_MIRROR_AUTO)  ?  "Auto"            : \
+	(x == DRX_MIRROR_UNKNOWN)  ?  "Unknown"         : \
+	"(Invalid)")
+#define DRX_STR_CLASSIFICATION(x) ( \
+	(x == DRX_CLASSIFICATION_GAUSS)  ?  "Gaussion"        : \
+	(x == DRX_CLASSIFICATION_HVY_GAUSS)  ?  "Heavy Gaussion"  : \
+	(x == DRX_CLASSIFICATION_COCHANNEL)  ?  "Co-channel"      : \
+	(x == DRX_CLASSIFICATION_STATIC)  ?  "Static echo"     : \
+	(x == DRX_CLASSIFICATION_MOVING)  ?  "Moving echo"     : \
+	(x == DRX_CLASSIFICATION_ZERODB)  ?  "Zero dB echo"    : \
+	(x == DRX_CLASSIFICATION_UNKNOWN)  ?  "Unknown"         : \
+	(x == DRX_CLASSIFICATION_AUTO)  ?  "Auto"            : \
+	"(Invalid)")
+
+#define DRX_STR_INTERLEAVEMODE(x) ( \
+	(x == DRX_INTERLEAVEMODE_I128_J1) ? "I128_J1"         : \
+	(x == DRX_INTERLEAVEMODE_I128_J1_V2) ? "I128_J1_V2"      : \
+	(x == DRX_INTERLEAVEMODE_I128_J2) ? "I128_J2"         : \
+	(x == DRX_INTERLEAVEMODE_I64_J2) ? "I64_J2"          : \
+	(x == DRX_INTERLEAVEMODE_I128_J3) ? "I128_J3"         : \
+	(x == DRX_INTERLEAVEMODE_I32_J4) ? "I32_J4"          : \
+	(x == DRX_INTERLEAVEMODE_I128_J4) ? "I128_J4"         : \
+	(x == DRX_INTERLEAVEMODE_I16_J8) ? "I16_J8"          : \
+	(x == DRX_INTERLEAVEMODE_I128_J5) ? "I128_J5"         : \
+	(x == DRX_INTERLEAVEMODE_I8_J16) ? "I8_J16"          : \
+	(x == DRX_INTERLEAVEMODE_I128_J6) ? "I128_J6"         : \
+	(x == DRX_INTERLEAVEMODE_RESERVED_11) ? "Reserved 11"     : \
+	(x == DRX_INTERLEAVEMODE_I128_J7) ? "I128_J7"         : \
+	(x == DRX_INTERLEAVEMODE_RESERVED_13) ? "Reserved 13"     : \
+	(x == DRX_INTERLEAVEMODE_I128_J8) ? "I128_J8"         : \
+	(x == DRX_INTERLEAVEMODE_RESERVED_15) ? "Reserved 15"     : \
+	(x == DRX_INTERLEAVEMODE_I12_J17) ? "I12_J17"         : \
+	(x == DRX_INTERLEAVEMODE_I5_J4) ? "I5_J4"           : \
+	(x == DRX_INTERLEAVEMODE_B52_M240) ? "B52_M240"        : \
+	(x == DRX_INTERLEAVEMODE_B52_M720) ? "B52_M720"        : \
+	(x == DRX_INTERLEAVEMODE_B52_M48) ? "B52_M48"         : \
+	(x == DRX_INTERLEAVEMODE_B52_M0) ? "B52_M0"          : \
+	(x == DRX_INTERLEAVEMODE_UNKNOWN) ? "Unknown"         : \
+	(x == DRX_INTERLEAVEMODE_AUTO) ? "Auto"            : \
+	"(Invalid)")
+
+#define DRX_STR_LDPC(x) ( \
+	(x == DRX_LDPC_0_4) ? "0.4"             : \
+	(x == DRX_LDPC_0_6) ? "0.6"             : \
+	(x == DRX_LDPC_0_8) ? "0.8"             : \
+	(x == DRX_LDPC_AUTO) ? "Auto"            : \
+	(x == DRX_LDPC_UNKNOWN) ? "Unknown"         : \
+	"(Invalid)")
+
+#define DRX_STR_CARRIER(x) ( \
+	(x == DRX_CARRIER_MULTI) ? "Multi"           : \
+	(x == DRX_CARRIER_SINGLE) ? "Single"          : \
+	(x == DRX_CARRIER_AUTO) ? "Auto"            : \
+	(x == DRX_CARRIER_UNKNOWN) ? "Unknown"         : \
+	"(Invalid)")
+
+#define DRX_STR_FRAMEMODE(x) ( \
+	(x == DRX_FRAMEMODE_420)  ? "420"                : \
+	(x == DRX_FRAMEMODE_595)  ? "595"                : \
+	(x == DRX_FRAMEMODE_945)  ? "945"                : \
+	(x == DRX_FRAMEMODE_420_FIXED_PN)  ? "420 with fixed PN"  : \
+	(x == DRX_FRAMEMODE_945_FIXED_PN)  ? "945 with fixed PN"  : \
+	(x == DRX_FRAMEMODE_AUTO)  ? "Auto"               : \
+	(x == DRX_FRAMEMODE_UNKNOWN)  ? "Unknown"            : \
+	"(Invalid)")
+
+#define DRX_STR_PILOT(x) ( \
+	(x == DRX_PILOT_ON) ?   "On"              : \
+	(x == DRX_PILOT_OFF) ?   "Off"             : \
+	(x == DRX_PILOT_AUTO) ?   "Auto"            : \
+	(x == DRX_PILOT_UNKNOWN) ?   "Unknown"         : \
+	"(Invalid)")
+/* TPS */
+
+#define DRX_STR_TPS_FRAME(x)  ( \
+	(x == DRX_TPS_FRAME1)  ?  "Frame1"          : \
+	(x == DRX_TPS_FRAME2)  ?  "Frame2"          : \
+	(x == DRX_TPS_FRAME3)  ?  "Frame3"          : \
+	(x == DRX_TPS_FRAME4)  ?  "Frame4"          : \
+	(x == DRX_TPS_FRAME_UNKNOWN)  ?  "Unknown"         : \
+	"(Invalid)")
+
+/* lock status */
+
+#define DRX_STR_LOCKSTATUS(x) ( \
+	(x == DRX_NEVER_LOCK)  ?  "Never"           : \
+	(x == DRX_NOT_LOCKED)  ?  "No"              : \
+	(x == DRX_LOCKED)  ?  "Locked"          : \
+	(x == DRX_LOCK_STATE_1)  ?  "Lock state 1"    : \
+	(x == DRX_LOCK_STATE_2)  ?  "Lock state 2"    : \
+	(x == DRX_LOCK_STATE_3)  ?  "Lock state 3"    : \
+	(x == DRX_LOCK_STATE_4)  ?  "Lock state 4"    : \
+	(x == DRX_LOCK_STATE_5)  ?  "Lock state 5"    : \
+	(x == DRX_LOCK_STATE_6)  ?  "Lock state 6"    : \
+	(x == DRX_LOCK_STATE_7)  ?  "Lock state 7"    : \
+	(x == DRX_LOCK_STATE_8)  ?  "Lock state 8"    : \
+	(x == DRX_LOCK_STATE_9)  ?  "Lock state 9"    : \
+	"(Invalid)")
+
+/* version information , modules */
+#define DRX_STR_MODULE(x) ( \
+	(x == DRX_MODULE_DEVICE)  ?  "Device"                : \
+	(x == DRX_MODULE_MICROCODE)  ?  "Microcode"             : \
+	(x == DRX_MODULE_DRIVERCORE)  ?  "CoreDriver"            : \
+	(x == DRX_MODULE_DEVICEDRIVER)  ?  "DeviceDriver"          : \
+	(x == DRX_MODULE_BSP_I2C)  ?  "BSP I2C"               : \
+	(x == DRX_MODULE_BSP_TUNER)  ?  "BSP Tuner"             : \
+	(x == DRX_MODULE_BSP_HOST)  ?  "BSP Host"              : \
+	(x == DRX_MODULE_DAP)  ?  "Data Access Protocol"  : \
+	(x == DRX_MODULE_UNKNOWN)  ?  "Unknown"               : \
+	"(Invalid)")
+
+#define DRX_STR_POWER_MODE(x) ( \
+	(x == DRX_POWER_UP)  ?  "DRX_POWER_UP    "  : \
+	(x == DRX_POWER_MODE_1)  ?  "DRX_POWER_MODE_1"  : \
+	(x == DRX_POWER_MODE_2)  ?  "DRX_POWER_MODE_2"  : \
+	(x == DRX_POWER_MODE_3)  ?  "DRX_POWER_MODE_3"  : \
+	(x == DRX_POWER_MODE_4)  ?  "DRX_POWER_MODE_4"  : \
+	(x == DRX_POWER_MODE_5)  ?  "DRX_POWER_MODE_5"  : \
+	(x == DRX_POWER_MODE_6)  ?  "DRX_POWER_MODE_6"  : \
+	(x == DRX_POWER_MODE_7)  ?  "DRX_POWER_MODE_7"  : \
+	(x == DRX_POWER_MODE_8)  ?  "DRX_POWER_MODE_8"  : \
+	(x == DRX_POWER_MODE_9)  ?  "DRX_POWER_MODE_9"  : \
+	(x == DRX_POWER_MODE_10)  ?  "DRX_POWER_MODE_10" : \
+	(x == DRX_POWER_MODE_11)  ?  "DRX_POWER_MODE_11" : \
+	(x == DRX_POWER_MODE_12)  ?  "DRX_POWER_MODE_12" : \
+	(x == DRX_POWER_MODE_13)  ?  "DRX_POWER_MODE_13" : \
+	(x == DRX_POWER_MODE_14)  ?  "DRX_POWER_MODE_14" : \
+	(x == DRX_POWER_MODE_15)  ?  "DRX_POWER_MODE_15" : \
+	(x == DRX_POWER_MODE_16)  ?  "DRX_POWER_MODE_16" : \
+	(x == DRX_POWER_DOWN)  ?  "DRX_POWER_DOWN  " : \
+	"(Invalid)")
+
+#define DRX_STR_OOB_STANDARD(x) ( \
+	(x == DRX_OOB_MODE_A)  ?  "ANSI 55-1  " : \
+	(x == DRX_OOB_MODE_B_GRADE_A)  ?  "ANSI 55-2 A" : \
+	(x == DRX_OOB_MODE_B_GRADE_B)  ?  "ANSI 55-2 B" : \
+	"(Invalid)")
+
+#define DRX_STR_AUD_STANDARD(x) ( \
+	(x == DRX_AUD_STANDARD_BTSC)  ? "BTSC"                     : \
+	(x == DRX_AUD_STANDARD_A2)  ? "A2"                       : \
+	(x == DRX_AUD_STANDARD_EIAJ)  ? "EIAJ"                     : \
+	(x == DRX_AUD_STANDARD_FM_STEREO)  ? "FM Stereo"                : \
+	(x == DRX_AUD_STANDARD_AUTO)  ? "Auto"                     : \
+	(x == DRX_AUD_STANDARD_M_MONO)  ? "M-Standard Mono"          : \
+	(x == DRX_AUD_STANDARD_D_K_MONO)  ? "D/K Mono FM"              : \
+	(x == DRX_AUD_STANDARD_BG_FM)  ? "B/G-Dual Carrier FM (A2)" : \
+	(x == DRX_AUD_STANDARD_D_K1)  ? "D/K1-Dual Carrier FM"     : \
+	(x == DRX_AUD_STANDARD_D_K2)  ? "D/K2-Dual Carrier FM"     : \
+	(x == DRX_AUD_STANDARD_D_K3)  ? "D/K3-Dual Carrier FM"     : \
+	(x == DRX_AUD_STANDARD_BG_NICAM_FM)  ? "B/G-NICAM-FM"             : \
+	(x == DRX_AUD_STANDARD_L_NICAM_AM)  ? "L-NICAM-AM"               : \
+	(x == DRX_AUD_STANDARD_I_NICAM_FM)  ? "I-NICAM-FM"               : \
+	(x == DRX_AUD_STANDARD_D_K_NICAM_FM)  ? "D/K-NICAM-FM"             : \
+	(x == DRX_AUD_STANDARD_UNKNOWN)  ? "Unknown"                  : \
+	"(Invalid)")
+#define DRX_STR_AUD_STEREO(x) ( \
+	(x == true)  ? "Stereo"           : \
+	(x == false)  ? "Mono"             : \
+	"(Invalid)")
+
+#define DRX_STR_AUD_SAP(x) ( \
+	(x == true)  ? "Present"          : \
+	(x == false)  ? "Not present"      : \
+	"(Invalid)")
+
+#define DRX_STR_AUD_CARRIER(x) ( \
+	(x == true)  ? "Present"          : \
+	(x == false)  ? "Not present"      : \
+	"(Invalid)")
+
+#define DRX_STR_AUD_RDS(x) ( \
+	(x == true)  ? "Available"        : \
+	(x == false)  ? "Not Available"    : \
+	"(Invalid)")
+
+#define DRX_STR_AUD_NICAM_STATUS(x) ( \
+	(x == DRX_AUD_NICAM_DETECTED)  ? "Detected"         : \
+	(x == DRX_AUD_NICAM_NOT_DETECTED)  ? "Not detected"     : \
+	(x == DRX_AUD_NICAM_BAD)  ? "Bad"              : \
+	"(Invalid)")
+
+#define DRX_STR_RDS_VALID(x) ( \
+	(x == true)  ? "Valid"            : \
+	(x == false)  ? "Not Valid"        : \
+	"(Invalid)")
+
+/*-------------------------------------------------------------------------
+Access macros
+-------------------------------------------------------------------------*/
+
+/**
+* \brief Create a compilable reference to the microcode attribute
+* \param d pointer to demod instance
+*
+* Used as main reference to an attribute field.
+* Used by both macro implementation and function implementation.
+* These macros are defined to avoid duplication of code in macro and function
+* definitions that handle access of demod common or extended attributes.
+*
+*/
+
+#define DRX_ATTR_MCRECORD(d)        ((d)->my_common_attr->mcversion)
+#define DRX_ATTR_MIRRORFREQSPECT(d) ((d)->my_common_attr->mirror_freq_spect)
+#define DRX_ATTR_CURRENTPOWERMODE(d)((d)->my_common_attr->current_power_mode)
+#define DRX_ATTR_ISOPENED(d)        ((d)->my_common_attr->is_opened)
+#define DRX_ATTR_USEBOOTLOADER(d)   ((d)->my_common_attr->use_bootloader)
+#define DRX_ATTR_CURRENTSTANDARD(d) ((d)->my_common_attr->current_standard)
+#define DRX_ATTR_PREVSTANDARD(d)    ((d)->my_common_attr->prev_standard)
+#define DRX_ATTR_CACHESTANDARD(d)   ((d)->my_common_attr->di_cache_standard)
+#define DRX_ATTR_CURRENTCHANNEL(d)  ((d)->my_common_attr->current_channel)
+#define DRX_ATTR_MICROCODE(d)       ((d)->my_common_attr->microcode)
+#define DRX_ATTR_VERIFYMICROCODE(d) ((d)->my_common_attr->verify_microcode)
+#define DRX_ATTR_CAPABILITIES(d)    ((d)->my_common_attr->capabilities)
+#define DRX_ATTR_PRODUCTID(d)       ((d)->my_common_attr->product_id)
+#define DRX_ATTR_INTERMEDIATEFREQ(d) ((d)->my_common_attr->intermediate_freq)
+#define DRX_ATTR_SYSCLOCKFREQ(d)     ((d)->my_common_attr->sys_clock_freq)
+#define DRX_ATTR_TUNERRFAGCPOL(d)   ((d)->my_common_attr->tuner_rf_agc_pol)
+#define DRX_ATTR_TUNERIFAGCPOL(d)    ((d)->my_common_attr->tuner_if_agc_pol)
+#define DRX_ATTR_TUNERSLOWMODE(d)    ((d)->my_common_attr->tuner_slow_mode)
+#define DRX_ATTR_TUNERSPORTNR(d)     ((d)->my_common_attr->tuner_port_nr)
+#define DRX_ATTR_I2CADDR(d)         ((d)->my_i2c_dev_addr->i2c_addr)
+#define DRX_ATTR_I2CDEVID(d)        ((d)->my_i2c_dev_addr->i2c_dev_id)
+#define DRX_ISMCVERTYPE(x) ((x) == AUX_VER_RECORD)
+
+/**************************/
+
+/* Macros with device-specific handling are converted to CFG functions */
+
+#define DRX_ACCESSMACRO_SET(demod, value, cfg_name, data_type)             \
+	do {                                                               \
+		struct drx_cfg config;                                     \
+		data_type cfg_data;                                        \
+		config.cfg_type = cfg_name;                                \
+		config.cfg_data = &cfg_data;                               \
+		cfg_data = value;                                          \
+		drx_ctrl(demod, DRX_CTRL_SET_CFG, &config);                \
+	} while (0)
+
+#define DRX_ACCESSMACRO_GET(demod, value, cfg_name, data_type, error_value) \
+	do {                                                                \
+		int cfg_status;                                             \
+		struct drx_cfg config;                                      \
+		data_type    cfg_data;                                      \
+		config.cfg_type = cfg_name;                                 \
+		config.cfg_data = &cfg_data;                                \
+		cfg_status = drx_ctrl(demod, DRX_CTRL_GET_CFG, &config);    \
+		if (cfg_status == 0) {                                      \
+			value = cfg_data;                                   \
+		} else {                                                    \
+			value = (data_type)error_value;                     \
+		}                                                           \
+	} while (0)
+
+/* Configuration functions for usage by Access (XS) Macros */
+
+#ifndef DRX_XS_CFG_BASE
+#define DRX_XS_CFG_BASE (500)
+#endif
+
+#define DRX_XS_CFG_PRESET          (DRX_XS_CFG_BASE + 0)
+#define DRX_XS_CFG_AUD_BTSC_DETECT (DRX_XS_CFG_BASE + 1)
+#define DRX_XS_CFG_QAM_LOCKRANGE   (DRX_XS_CFG_BASE + 2)
+
+/* Access Macros with device-specific handling */
+
+#define DRX_SET_PRESET(d, x) \
+	DRX_ACCESSMACRO_SET((d), (x), DRX_XS_CFG_PRESET, char*)
+#define DRX_GET_PRESET(d, x) \
+	DRX_ACCESSMACRO_GET((d), (x), DRX_XS_CFG_PRESET, char*, "ERROR")
+
+#define DRX_SET_AUD_BTSC_DETECT(d, x) DRX_ACCESSMACRO_SET((d), (x), \
+	 DRX_XS_CFG_AUD_BTSC_DETECT, enum drx_aud_btsc_detect)
+#define DRX_GET_AUD_BTSC_DETECT(d, x) DRX_ACCESSMACRO_GET((d), (x), \
+	 DRX_XS_CFG_AUD_BTSC_DETECT, enum drx_aud_btsc_detect, DRX_UNKNOWN)
+
+#define DRX_SET_QAM_LOCKRANGE(d, x) DRX_ACCESSMACRO_SET((d), (x), \
+	 DRX_XS_CFG_QAM_LOCKRANGE, enum drx_qam_lock_range)
+#define DRX_GET_QAM_LOCKRANGE(d, x) DRX_ACCESSMACRO_GET((d), (x), \
+	 DRX_XS_CFG_QAM_LOCKRANGE, enum drx_qam_lock_range, DRX_UNKNOWN)
+
+/**
+* \brief Macro to check if std is an ATV standard
+* \retval true std is an ATV standard
+* \retval false std is an ATV standard
+*/
+#define DRX_ISATVSTD(std) (((std) == DRX_STANDARD_PAL_SECAM_BG) || \
+			      ((std) == DRX_STANDARD_PAL_SECAM_DK) || \
+			      ((std) == DRX_STANDARD_PAL_SECAM_I) || \
+			      ((std) == DRX_STANDARD_PAL_SECAM_L) || \
+			      ((std) == DRX_STANDARD_PAL_SECAM_LP) || \
+			      ((std) == DRX_STANDARD_NTSC) || \
+			      ((std) == DRX_STANDARD_FM))
+
+/**
+* \brief Macro to check if std is an QAM standard
+* \retval true std is an QAM standards
+* \retval false std is an QAM standards
+*/
+#define DRX_ISQAMSTD(std) (((std) == DRX_STANDARD_ITU_A) || \
+			      ((std) == DRX_STANDARD_ITU_B) || \
+			      ((std) == DRX_STANDARD_ITU_C) || \
+			      ((std) == DRX_STANDARD_ITU_D))
+
+/**
+* \brief Macro to check if std is VSB standard
+* \retval true std is VSB standard
+* \retval false std is not VSB standard
+*/
+#define DRX_ISVSBSTD(std) ((std) == DRX_STANDARD_8VSB)
+
+/**
+* \brief Macro to check if std is DVBT standard
+* \retval true std is DVBT standard
+* \retval false std is not DVBT standard
+*/
+#define DRX_ISDVBTSTD(std) ((std) == DRX_STANDARD_DVBT)
+
+/*-------------------------------------------------------------------------
+THE END
+-------------------------------------------------------------------------*/
+#endif				/* __DRXDRIVER_H__ */
diff --git a/drivers/media/dvb-frontends/drx39xyj/drx_driver_version.h b/drivers/media/dvb-frontends/drx39xyj/drx_driver_version.h
new file mode 100644
index 0000000..ff05a4f
--- /dev/null
+++ b/drivers/media/dvb-frontends/drx39xyj/drx_driver_version.h
@@ -0,0 +1,72 @@
+/*
+ *******************************************************************************
+ * WARNING - THIS FILE HAS BEEN GENERATED - DO NOT CHANGE
+ *
+ * Filename:        drx_driver_version.h
+ * Generated on:    Mon Jan 18 12:09:23 2010
+ * Generated by:    IDF:x 1.3.0
+ * Generated from:  ../../../device/drxj/version
+ * Output start:    [entry point]
+ *
+ * filename         last modified               re-use
+ *
+  Copyright (c), 2004-2005,2007-2010 Trident Microsystems, Inc.
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+	and/or other materials provided with the distribution.
+  * Neither the name of Trident Microsystems nor Hauppauge Computer Works
+    nor the names of its contributors may be used to endorse or promote
+	products derived from this software without specific prior written
+	permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* -----------------------------------------------------
+ * version.idf      Mon Jan 18 11:56:10 2010    -
+ *
+ */
+
+#ifndef __DRX_DRIVER_VERSION__H__
+#define __DRX_DRIVER_VERSION__H__ INCLUDED
+
+#ifdef _REGISTERTABLE_
+#include <registertable.h>
+	extern register_table_t drx_driver_version[];
+	extern register_table_info_t drx_driver_version_info[];
+#endif				/* _REGISTERTABLE_ */
+
+/*
+ *==============================================================================
+ * VERSION
+ * version@/var/cvs/projects/drxj.cvsroot/hostcode/drxdriver/device/drxj
+ *==============================================================================
+ */
+
+#define VERSION__A      0x0
+#define   VERSION_MAJOR 1
+#define   VERSION_MINOR 0
+#define   VERSION_PATCH 56
+
+#endif				/* __DRX_DRIVER_VERSION__H__ */
+/*
+ * End of file (drx_driver_version.h)
+ *******************************************************************************
+ */
diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.c b/drivers/media/dvb-frontends/drx39xyj/drxj.c
new file mode 100644
index 0000000..9482954
--- /dev/null
+++ b/drivers/media/dvb-frontends/drx39xyj/drxj.c
@@ -0,0 +1,12400 @@
+/*
+  Copyright (c), 2004-2005,2007-2010 Trident Microsystems, Inc.
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+	and/or other materials provided with the distribution.
+  * Neither the name of Trident Microsystems nor Hauppauge Computer Works
+    nor the names of its contributors may be used to endorse or promote
+	products derived from this software without specific prior written
+	permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+  DRXJ specific implementation of DRX driver
+  authors: Dragan Savic, Milos Nikolic, Mihajlo Katona, Tao Ding, Paul Janssen
+
+  The Linux DVB Driver for Micronas DRX39xx family (drx3933j) was
+  written by Devin Heitmueller <devin.heitmueller@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 FILES
+----------------------------------------------------------------------------*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "drx39xxj.h"
+
+#include "drxj.h"
+#include "drxj_map.h"
+
+/*============================================================================*/
+/*=== DEFINES ================================================================*/
+/*============================================================================*/
+
+#define DRX39XX_MAIN_FIRMWARE "dvb-fe-drxj-mc-1.0.8.fw"
+
+/**
+* \brief Maximum u32 value.
+*/
+#ifndef MAX_U32
+#define MAX_U32  ((u32) (0xFFFFFFFFL))
+#endif
+
+/* Customer configurable hardware settings, etc */
+#ifndef MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH
+#define MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH 0x02
+#endif
+
+#ifndef MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH
+#define MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH 0x02
+#endif
+
+#ifndef MPEG_OUTPUT_CLK_DRIVE_STRENGTH
+#define MPEG_OUTPUT_CLK_DRIVE_STRENGTH 0x06
+#endif
+
+#ifndef OOB_CRX_DRIVE_STRENGTH
+#define OOB_CRX_DRIVE_STRENGTH 0x02
+#endif
+
+#ifndef OOB_DRX_DRIVE_STRENGTH
+#define OOB_DRX_DRIVE_STRENGTH 0x02
+#endif
+/**** START DJCOMBO patches to DRXJ registermap constants *********************/
+/**** registermap 200706071303 from drxj **************************************/
+#define   ATV_TOP_CR_AMP_TH_FM                                              0x0
+#define   ATV_TOP_CR_AMP_TH_L                                               0xA
+#define   ATV_TOP_CR_AMP_TH_LP                                              0xA
+#define   ATV_TOP_CR_AMP_TH_BG                                              0x8
+#define   ATV_TOP_CR_AMP_TH_DK                                              0x8
+#define   ATV_TOP_CR_AMP_TH_I                                               0x8
+#define     ATV_TOP_CR_CONT_CR_D_MN                                         0x18
+#define     ATV_TOP_CR_CONT_CR_D_FM                                         0x0
+#define     ATV_TOP_CR_CONT_CR_D_L                                          0x20
+#define     ATV_TOP_CR_CONT_CR_D_LP                                         0x20
+#define     ATV_TOP_CR_CONT_CR_D_BG                                         0x18
+#define     ATV_TOP_CR_CONT_CR_D_DK                                         0x18
+#define     ATV_TOP_CR_CONT_CR_D_I                                          0x18
+#define     ATV_TOP_CR_CONT_CR_I_MN                                         0x80
+#define     ATV_TOP_CR_CONT_CR_I_FM                                         0x0
+#define     ATV_TOP_CR_CONT_CR_I_L                                          0x80
+#define     ATV_TOP_CR_CONT_CR_I_LP                                         0x80
+#define     ATV_TOP_CR_CONT_CR_I_BG                                         0x80
+#define     ATV_TOP_CR_CONT_CR_I_DK                                         0x80
+#define     ATV_TOP_CR_CONT_CR_I_I                                          0x80
+#define     ATV_TOP_CR_CONT_CR_P_MN                                         0x4
+#define     ATV_TOP_CR_CONT_CR_P_FM                                         0x0
+#define     ATV_TOP_CR_CONT_CR_P_L                                          0x4
+#define     ATV_TOP_CR_CONT_CR_P_LP                                         0x4
+#define     ATV_TOP_CR_CONT_CR_P_BG                                         0x4
+#define     ATV_TOP_CR_CONT_CR_P_DK                                         0x4
+#define     ATV_TOP_CR_CONT_CR_P_I                                          0x4
+#define   ATV_TOP_CR_OVM_TH_MN                                              0xA0
+#define   ATV_TOP_CR_OVM_TH_FM                                              0x0
+#define   ATV_TOP_CR_OVM_TH_L                                               0xA0
+#define   ATV_TOP_CR_OVM_TH_LP                                              0xA0
+#define   ATV_TOP_CR_OVM_TH_BG                                              0xA0
+#define   ATV_TOP_CR_OVM_TH_DK                                              0xA0
+#define   ATV_TOP_CR_OVM_TH_I                                               0xA0
+#define     ATV_TOP_EQU0_EQU_C0_FM                                          0x0
+#define     ATV_TOP_EQU0_EQU_C0_L                                           0x3
+#define     ATV_TOP_EQU0_EQU_C0_LP                                          0x3
+#define     ATV_TOP_EQU0_EQU_C0_BG                                          0x7
+#define     ATV_TOP_EQU0_EQU_C0_DK                                          0x0
+#define     ATV_TOP_EQU0_EQU_C0_I                                           0x3
+#define     ATV_TOP_EQU1_EQU_C1_FM                                          0x0
+#define     ATV_TOP_EQU1_EQU_C1_L                                           0x1F6
+#define     ATV_TOP_EQU1_EQU_C1_LP                                          0x1F6
+#define     ATV_TOP_EQU1_EQU_C1_BG                                          0x197
+#define     ATV_TOP_EQU1_EQU_C1_DK                                          0x198
+#define     ATV_TOP_EQU1_EQU_C1_I                                           0x1F6
+#define     ATV_TOP_EQU2_EQU_C2_FM                                          0x0
+#define     ATV_TOP_EQU2_EQU_C2_L                                           0x28
+#define     ATV_TOP_EQU2_EQU_C2_LP                                          0x28
+#define     ATV_TOP_EQU2_EQU_C2_BG                                          0xC5
+#define     ATV_TOP_EQU2_EQU_C2_DK                                          0xB0
+#define     ATV_TOP_EQU2_EQU_C2_I                                           0x28
+#define     ATV_TOP_EQU3_EQU_C3_FM                                          0x0
+#define     ATV_TOP_EQU3_EQU_C3_L                                           0x192
+#define     ATV_TOP_EQU3_EQU_C3_LP                                          0x192
+#define     ATV_TOP_EQU3_EQU_C3_BG                                          0x12E
+#define     ATV_TOP_EQU3_EQU_C3_DK                                          0x18E
+#define     ATV_TOP_EQU3_EQU_C3_I                                           0x192
+#define     ATV_TOP_STD_MODE_MN                                             0x0
+#define     ATV_TOP_STD_MODE_FM                                             0x1
+#define     ATV_TOP_STD_MODE_L                                              0x0
+#define     ATV_TOP_STD_MODE_LP                                             0x0
+#define     ATV_TOP_STD_MODE_BG                                             0x0
+#define     ATV_TOP_STD_MODE_DK                                             0x0
+#define     ATV_TOP_STD_MODE_I                                              0x0
+#define     ATV_TOP_STD_VID_POL_MN                                          0x0
+#define     ATV_TOP_STD_VID_POL_FM                                          0x0
+#define     ATV_TOP_STD_VID_POL_L                                           0x2
+#define     ATV_TOP_STD_VID_POL_LP                                          0x2
+#define     ATV_TOP_STD_VID_POL_BG                                          0x0
+#define     ATV_TOP_STD_VID_POL_DK                                          0x0
+#define     ATV_TOP_STD_VID_POL_I                                           0x0
+#define   ATV_TOP_VID_AMP_MN                                                0x380
+#define   ATV_TOP_VID_AMP_FM                                                0x0
+#define   ATV_TOP_VID_AMP_L                                                 0xF50
+#define   ATV_TOP_VID_AMP_LP                                                0xF50
+#define   ATV_TOP_VID_AMP_BG                                                0x380
+#define   ATV_TOP_VID_AMP_DK                                                0x394
+#define   ATV_TOP_VID_AMP_I                                                 0x3D8
+#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
+/**** END DJCOMBO patches to DRXJ registermap *********************************/
+
+#include "drx_driver_version.h"
+
+/* #define DRX_DEBUG */
+#ifdef DRX_DEBUG
+#include <stdio.h>
+#endif
+
+/*-----------------------------------------------------------------------------
+ENUMS
+----------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------
+DEFINES
+----------------------------------------------------------------------------*/
+#ifndef DRXJ_WAKE_UP_KEY
+#define DRXJ_WAKE_UP_KEY (demod->my_i2c_dev_addr->i2c_addr)
+#endif
+
+/**
+* \def DRXJ_DEF_I2C_ADDR
+* \brief Default I2C addres of a demodulator instance.
+*/
+#define DRXJ_DEF_I2C_ADDR (0x52)
+
+/**
+* \def DRXJ_DEF_DEMOD_DEV_ID
+* \brief Default device identifier of a demodultor instance.
+*/
+#define DRXJ_DEF_DEMOD_DEV_ID      (1)
+
+/**
+* \def DRXJ_SCAN_TIMEOUT
+* \brief Timeout value for waiting on demod lock during channel scan (millisec).
+*/
+#define DRXJ_SCAN_TIMEOUT    1000
+
+/**
+* \def HI_I2C_DELAY
+* \brief HI timing delay for I2C timing (in nano seconds)
+*
+*  Used to compute HI_CFG_DIV
+*/
+#define HI_I2C_DELAY    42
+
+/**
+* \def HI_I2C_BRIDGE_DELAY
+* \brief HI timing delay for I2C timing (in nano seconds)
+*
+*  Used to compute HI_CFG_BDL
+*/
+#define HI_I2C_BRIDGE_DELAY   750
+
+/**
+* \brief Time Window for MER and SER Measurement in Units of Segment duration.
+*/
+#define VSB_TOP_MEASUREMENT_PERIOD  64
+#define SYMBOLS_PER_SEGMENT         832
+
+/**
+* \brief bit rate and segment rate constants used for SER and BER.
+*/
+/* values taken from the QAM microcode */
+#define DRXJ_QAM_SL_SIG_POWER_QAM_UNKNOWN 0
+#define DRXJ_QAM_SL_SIG_POWER_QPSK        32768
+#define DRXJ_QAM_SL_SIG_POWER_QAM8        24576
+#define DRXJ_QAM_SL_SIG_POWER_QAM16       40960
+#define DRXJ_QAM_SL_SIG_POWER_QAM32       20480
+#define DRXJ_QAM_SL_SIG_POWER_QAM64       43008
+#define DRXJ_QAM_SL_SIG_POWER_QAM128      20992
+#define DRXJ_QAM_SL_SIG_POWER_QAM256      43520
+/**
+* \brief Min supported symbolrates.
+*/
+#ifndef DRXJ_QAM_SYMBOLRATE_MIN
+#define DRXJ_QAM_SYMBOLRATE_MIN          (520000)
+#endif
+
+/**
+* \brief Max supported symbolrates.
+*/
+#ifndef DRXJ_QAM_SYMBOLRATE_MAX
+#define DRXJ_QAM_SYMBOLRATE_MAX         (7233000)
+#endif
+
+/**
+* \def DRXJ_QAM_MAX_WAITTIME
+* \brief Maximal wait time for QAM auto constellation in ms
+*/
+#ifndef DRXJ_QAM_MAX_WAITTIME
+#define DRXJ_QAM_MAX_WAITTIME 900
+#endif
+
+#ifndef DRXJ_QAM_FEC_LOCK_WAITTIME
+#define DRXJ_QAM_FEC_LOCK_WAITTIME 150
+#endif
+
+#ifndef DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME
+#define DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME 200
+#endif
+
+/**
+* \def SCU status and results
+* \brief SCU
+*/
+#define DRX_SCU_READY               0
+#define DRXJ_MAX_WAITTIME           100	/* ms */
+#define FEC_RS_MEASUREMENT_PERIOD   12894	/* 1 sec */
+#define FEC_RS_MEASUREMENT_PRESCALE 1	/* n sec */
+
+/**
+* \def DRX_AUD_MAX_DEVIATION
+* \brief Needed for calculation of prescale feature in AUD
+*/
+#ifndef DRXJ_AUD_MAX_FM_DEVIATION
+#define DRXJ_AUD_MAX_FM_DEVIATION  100	/* kHz */
+#endif
+
+/**
+* \brief Needed for calculation of NICAM prescale feature in AUD
+*/
+#ifndef DRXJ_AUD_MAX_NICAM_PRESCALE
+#define DRXJ_AUD_MAX_NICAM_PRESCALE  (9)	/* dB */
+#endif
+
+/**
+* \brief Needed for calculation of NICAM prescale feature in AUD
+*/
+#ifndef DRXJ_AUD_MAX_WAITTIME
+#define DRXJ_AUD_MAX_WAITTIME  250	/* ms */
+#endif
+
+/* ATV config changed flags */
+#define DRXJ_ATV_CHANGED_COEF          (0x00000001UL)
+#define DRXJ_ATV_CHANGED_PEAK_FLT      (0x00000008UL)
+#define DRXJ_ATV_CHANGED_NOISE_FLT     (0x00000010UL)
+#define DRXJ_ATV_CHANGED_OUTPUT        (0x00000020UL)
+#define DRXJ_ATV_CHANGED_SIF_ATT       (0x00000040UL)
+
+/* UIO define */
+#define DRX_UIO_MODE_FIRMWARE_SMA DRX_UIO_MODE_FIRMWARE0
+#define DRX_UIO_MODE_FIRMWARE_SAW DRX_UIO_MODE_FIRMWARE1
+
+/*
+ * MICROCODE RELATED DEFINES
+ */
+
+/* Magic word for checking correct Endianess of microcode data */
+#define DRX_UCODE_MAGIC_WORD         ((((u16)'H')<<8)+((u16)'L'))
+
+/* CRC flag in ucode header, flags field. */
+#define DRX_UCODE_CRC_FLAG           (0x0001)
+
+/*
+ * Maximum size of buffer used to verify the microcode.
+ * Must be an even number
+ */
+#define DRX_UCODE_MAX_BUF_SIZE       (DRXDAP_MAX_RCHUNKSIZE)
+
+#if DRX_UCODE_MAX_BUF_SIZE & 1
+#error DRX_UCODE_MAX_BUF_SIZE must be an even number
+#endif
+
+/*
+ * Power mode macros
+ */
+
+#define DRX_ISPOWERDOWNMODE(mode) ((mode == DRX_POWER_MODE_9) || \
+				       (mode == DRX_POWER_MODE_10) || \
+				       (mode == DRX_POWER_MODE_11) || \
+				       (mode == DRX_POWER_MODE_12) || \
+				       (mode == DRX_POWER_MODE_13) || \
+				       (mode == DRX_POWER_MODE_14) || \
+				       (mode == DRX_POWER_MODE_15) || \
+				       (mode == DRX_POWER_MODE_16) || \
+				       (mode == DRX_POWER_DOWN))
+
+/* Pin safe mode macro */
+#define DRXJ_PIN_SAFE_MODE 0x0000
+/*============================================================================*/
+/*=== GLOBAL VARIABLEs =======================================================*/
+/*============================================================================*/
+/**
+*/
+
+/**
+* \brief Temporary register definitions.
+*        (register definitions that are not yet available in register master)
+*/
+
+/******************************************************************************/
+/* Audio block 0x103 is write only. To avoid shadowing in driver accessing    */
+/* RAM adresses directly. This must be READ ONLY to avoid problems.           */
+/* Writing to the interface adresses is more than only writing the RAM        */
+/* locations                                                                  */
+/******************************************************************************/
+/**
+* \brief RAM location of MODUS registers
+*/
+#define AUD_DEM_RAM_MODUS_HI__A              0x10204A3
+#define AUD_DEM_RAM_MODUS_HI__M              0xF000
+
+#define AUD_DEM_RAM_MODUS_LO__A              0x10204A4
+#define AUD_DEM_RAM_MODUS_LO__M              0x0FFF
+
+/**
+* \brief RAM location of I2S config registers
+*/
+#define AUD_DEM_RAM_I2S_CONFIG1__A           0x10204B1
+#define AUD_DEM_RAM_I2S_CONFIG2__A           0x10204B2
+
+/**
+* \brief RAM location of DCO config registers
+*/
+#define AUD_DEM_RAM_DCO_B_HI__A              0x1020461
+#define AUD_DEM_RAM_DCO_B_LO__A              0x1020462
+#define AUD_DEM_RAM_DCO_A_HI__A              0x1020463
+#define AUD_DEM_RAM_DCO_A_LO__A              0x1020464
+
+/**
+* \brief RAM location of Threshold registers
+*/
+#define AUD_DEM_RAM_NICAM_THRSHLD__A         0x102045A
+#define AUD_DEM_RAM_A2_THRSHLD__A            0x10204BB
+#define AUD_DEM_RAM_BTSC_THRSHLD__A          0x10204A6
+
+/**
+* \brief RAM location of Carrier Threshold registers
+*/
+#define AUD_DEM_RAM_CM_A_THRSHLD__A          0x10204AF
+#define AUD_DEM_RAM_CM_B_THRSHLD__A          0x10204B0
+
+/**
+* \brief FM Matrix register fix
+*/
+#ifdef AUD_DEM_WR_FM_MATRIX__A
+#undef  AUD_DEM_WR_FM_MATRIX__A
+#endif
+#define AUD_DEM_WR_FM_MATRIX__A              0x105006F
+
+/*============================================================================*/
+/**
+* \brief Defines required for audio
+*/
+#define AUD_VOLUME_ZERO_DB                      115
+#define AUD_VOLUME_DB_MIN                       -60
+#define AUD_VOLUME_DB_MAX                       12
+#define AUD_CARRIER_STRENGTH_QP_0DB             0x4000
+#define AUD_CARRIER_STRENGTH_QP_0DB_LOG10T100   421
+#define AUD_MAX_AVC_REF_LEVEL                   15
+#define AUD_I2S_FREQUENCY_MAX                   48000UL
+#define AUD_I2S_FREQUENCY_MIN                   12000UL
+#define AUD_RDS_ARRAY_SIZE                      18
+
+/**
+* \brief Needed for calculation of prescale feature in AUD
+*/
+#ifndef DRX_AUD_MAX_FM_DEVIATION
+#define DRX_AUD_MAX_FM_DEVIATION  (100)	/* kHz */
+#endif
+
+/**
+* \brief Needed for calculation of NICAM prescale feature in AUD
+*/
+#ifndef DRX_AUD_MAX_NICAM_PRESCALE
+#define DRX_AUD_MAX_NICAM_PRESCALE  (9)	/* dB */
+#endif
+
+/*============================================================================*/
+/* Values for I2S Master/Slave pin configurations */
+#define SIO_PDR_I2S_CL_CFG_MODE__MASTER      0x0004
+#define SIO_PDR_I2S_CL_CFG_DRIVE__MASTER     0x0008
+#define SIO_PDR_I2S_CL_CFG_MODE__SLAVE       0x0004
+#define SIO_PDR_I2S_CL_CFG_DRIVE__SLAVE      0x0000
+
+#define SIO_PDR_I2S_DA_CFG_MODE__MASTER      0x0003
+#define SIO_PDR_I2S_DA_CFG_DRIVE__MASTER     0x0008
+#define SIO_PDR_I2S_DA_CFG_MODE__SLAVE       0x0003
+#define SIO_PDR_I2S_DA_CFG_DRIVE__SLAVE      0x0008
+
+#define SIO_PDR_I2S_WS_CFG_MODE__MASTER      0x0004
+#define SIO_PDR_I2S_WS_CFG_DRIVE__MASTER     0x0008
+#define SIO_PDR_I2S_WS_CFG_MODE__SLAVE       0x0004
+#define SIO_PDR_I2S_WS_CFG_DRIVE__SLAVE      0x0000
+
+/*============================================================================*/
+/*=== REGISTER ACCESS MACROS =================================================*/
+/*============================================================================*/
+
+/**
+* This macro is used to create byte arrays for block writes.
+* Block writes speed up I2C traffic between host and demod.
+* The macro takes care of the required byte order in a 16 bits word.
+* x -> lowbyte(x), highbyte(x)
+*/
+#define DRXJ_16TO8(x) ((u8) (((u16)x) & 0xFF)), \
+		       ((u8)((((u16)x)>>8)&0xFF))
+/**
+* This macro is used to convert byte array to 16 bit register value for block read.
+* Block read speed up I2C traffic between host and demod.
+* The macro takes care of the required byte order in a 16 bits word.
+*/
+#define DRXJ_8TO16(x) ((u16) (x[0] | (x[1] << 8)))
+
+/*============================================================================*/
+/*=== MISC DEFINES ===========================================================*/
+/*============================================================================*/
+
+/*============================================================================*/
+/*=== HI COMMAND RELATED DEFINES =============================================*/
+/*============================================================================*/
+
+/**
+* \brief General maximum number of retries for ucode command interfaces
+*/
+#define DRXJ_MAX_RETRIES (100)
+
+/*============================================================================*/
+/*=== STANDARD RELATED MACROS ================================================*/
+/*============================================================================*/
+
+#define DRXJ_ISATVSTD(std) ((std == DRX_STANDARD_PAL_SECAM_BG) || \
+			       (std == DRX_STANDARD_PAL_SECAM_DK) || \
+			       (std == DRX_STANDARD_PAL_SECAM_I) || \
+			       (std == DRX_STANDARD_PAL_SECAM_L) || \
+			       (std == DRX_STANDARD_PAL_SECAM_LP) || \
+			       (std == DRX_STANDARD_NTSC) || \
+			       (std == DRX_STANDARD_FM))
+
+#define DRXJ_ISQAMSTD(std) ((std == DRX_STANDARD_ITU_A) || \
+			       (std == DRX_STANDARD_ITU_B) || \
+			       (std == DRX_STANDARD_ITU_C) || \
+			       (std == DRX_STANDARD_ITU_D))
+
+/*-----------------------------------------------------------------------------
+GLOBAL VARIABLES
+----------------------------------------------------------------------------*/
+/*
+ * DRXJ DAP structures
+ */
+
+static int drxdap_fasi_read_block(struct i2c_device_addr *dev_addr,
+				      u32 addr,
+				      u16 datasize,
+				      u8 *data, u32 flags);
+
+
+static int drxj_dap_read_modify_write_reg16(struct i2c_device_addr *dev_addr,
+						 u32 waddr,
+						 u32 raddr,
+						 u16 wdata, u16 *rdata);
+
+static int drxj_dap_read_reg16(struct i2c_device_addr *dev_addr,
+				      u32 addr,
+				      u16 *data, u32 flags);
+
+static int drxdap_fasi_read_reg32(struct i2c_device_addr *dev_addr,
+				      u32 addr,
+				      u32 *data, u32 flags);
+
+static int drxdap_fasi_write_block(struct i2c_device_addr *dev_addr,
+				       u32 addr,
+				       u16 datasize,
+				       u8 *data, u32 flags);
+
+static int drxj_dap_write_reg16(struct i2c_device_addr *dev_addr,
+				       u32 addr,
+				       u16 data, u32 flags);
+
+static int drxdap_fasi_write_reg32(struct i2c_device_addr *dev_addr,
+				       u32 addr,
+				       u32 data, u32 flags);
+
+static struct drxj_data drxj_data_g = {
+	false,			/* has_lna : true if LNA (aka PGA) present      */
+	false,			/* has_oob : true if OOB supported              */
+	false,			/* has_ntsc: true if NTSC supported             */
+	false,			/* has_btsc: true if BTSC supported             */
+	false,			/* has_smatx: true if SMA_TX pin is available   */
+	false,			/* has_smarx: true if SMA_RX pin is available   */
+	false,			/* has_gpio : true if GPIO pin is available     */
+	false,			/* has_irqn : true if IRQN pin is available     */
+	0,			/* mfx A1/A2/A... */
+
+	/* tuner settings */
+	false,			/* tuner mirrors RF signal    */
+	/* standard/channel settings */
+	DRX_STANDARD_UNKNOWN,	/* current standard           */
+	DRX_CONSTELLATION_AUTO,	/* constellation              */
+	0,			/* frequency in KHz           */
+	DRX_BANDWIDTH_UNKNOWN,	/* curr_bandwidth              */
+	DRX_MIRROR_NO,		/* mirror                     */
+
+	/* signal quality information: */
+	/* default values taken from the QAM Programming guide */
+	/*   fec_bits_desired should not be less than 4000000    */
+	4000000,		/* fec_bits_desired    */
+	5,			/* fec_vd_plen         */
+	4,			/* qam_vd_prescale     */
+	0xFFFF,			/* qamVDPeriod       */
+	204 * 8,		/* fec_rs_plen annex A */
+	1,			/* fec_rs_prescale     */
+	FEC_RS_MEASUREMENT_PERIOD,	/* fec_rs_period     */
+	true,			/* reset_pkt_err_acc    */
+	0,			/* pkt_err_acc_start    */
+
+	/* HI configuration */
+	0,			/* hi_cfg_timing_div    */
+	0,			/* hi_cfg_bridge_delay  */
+	0,			/* hi_cfg_wake_up_key    */
+	0,			/* hi_cfg_ctrl         */
+	0,			/* HICfgTimeout      */
+	/* UIO configuartion */
+	DRX_UIO_MODE_DISABLE,	/* uio_sma_rx_mode      */
+	DRX_UIO_MODE_DISABLE,	/* uio_sma_tx_mode      */
+	DRX_UIO_MODE_DISABLE,	/* uioASELMode       */
+	DRX_UIO_MODE_DISABLE,	/* uio_irqn_mode       */
+	/* FS setting */
+	0UL,			/* iqm_fs_rate_ofs      */
+	false,			/* pos_image          */
+	/* RC setting */
+	0UL,			/* iqm_rc_rate_ofs      */
+	/* AUD information */
+/*   false,                  * flagSetAUDdone    */
+/*   false,                  * detectedRDS       */
+/*   true,                   * flagASDRequest    */
+/*   false,                  * flagHDevClear     */
+/*   false,                  * flagHDevSet       */
+/*   (u16) 0xFFF,          * rdsLastCount      */
+
+	/* ATV configuartion */
+	0UL,			/* flags cfg changes */
+	/* shadow of ATV_TOP_EQU0__A */
+	{-5,
+	 ATV_TOP_EQU0_EQU_C0_FM,
+	 ATV_TOP_EQU0_EQU_C0_L,
+	 ATV_TOP_EQU0_EQU_C0_LP,
+	 ATV_TOP_EQU0_EQU_C0_BG,
+	 ATV_TOP_EQU0_EQU_C0_DK,
+	 ATV_TOP_EQU0_EQU_C0_I},
+	/* shadow of ATV_TOP_EQU1__A */
+	{-50,
+	 ATV_TOP_EQU1_EQU_C1_FM,
+	 ATV_TOP_EQU1_EQU_C1_L,
+	 ATV_TOP_EQU1_EQU_C1_LP,
+	 ATV_TOP_EQU1_EQU_C1_BG,
+	 ATV_TOP_EQU1_EQU_C1_DK,
+	 ATV_TOP_EQU1_EQU_C1_I},
+	/* shadow of ATV_TOP_EQU2__A */
+	{210,
+	 ATV_TOP_EQU2_EQU_C2_FM,
+	 ATV_TOP_EQU2_EQU_C2_L,
+	 ATV_TOP_EQU2_EQU_C2_LP,
+	 ATV_TOP_EQU2_EQU_C2_BG,
+	 ATV_TOP_EQU2_EQU_C2_DK,
+	 ATV_TOP_EQU2_EQU_C2_I},
+	/* shadow of ATV_TOP_EQU3__A */
+	{-160,
+	 ATV_TOP_EQU3_EQU_C3_FM,
+	 ATV_TOP_EQU3_EQU_C3_L,
+	 ATV_TOP_EQU3_EQU_C3_LP,
+	 ATV_TOP_EQU3_EQU_C3_BG,
+	 ATV_TOP_EQU3_EQU_C3_DK,
+	 ATV_TOP_EQU3_EQU_C3_I},
+	false,			/* flag: true=bypass             */
+	ATV_TOP_VID_PEAK__PRE,	/* shadow of ATV_TOP_VID_PEAK__A */
+	ATV_TOP_NOISE_TH__PRE,	/* shadow of ATV_TOP_NOISE_TH__A */
+	true,			/* flag CVBS ouput enable        */
+	false,			/* flag SIF ouput enable         */
+	DRXJ_SIF_ATTENUATION_0DB,	/* current SIF att setting       */
+	{			/* qam_rf_agc_cfg */
+	 DRX_STANDARD_ITU_B,	/* standard            */
+	 DRX_AGC_CTRL_AUTO,	/* ctrl_mode            */
+	 0,			/* output_level         */
+	 0,			/* min_output_level      */
+	 0xFFFF,		/* max_output_level      */
+	 0x0000,		/* speed               */
+	 0x0000,		/* top                 */
+	 0x0000			/* c.o.c.              */
+	 },
+	{			/* qam_if_agc_cfg */
+	 DRX_STANDARD_ITU_B,	/* standard            */
+	 DRX_AGC_CTRL_AUTO,	/* ctrl_mode            */
+	 0,			/* output_level         */
+	 0,			/* min_output_level      */
+	 0xFFFF,		/* max_output_level      */
+	 0x0000,		/* speed               */
+	 0x0000,		/* top    (don't care) */
+	 0x0000			/* c.o.c. (don't care) */
+	 },
+	{			/* vsb_rf_agc_cfg */
+	 DRX_STANDARD_8VSB,	/* standard       */
+	 DRX_AGC_CTRL_AUTO,	/* ctrl_mode       */
+	 0,			/* output_level    */
+	 0,			/* min_output_level */
+	 0xFFFF,		/* max_output_level */
+	 0x0000,		/* speed          */
+	 0x0000,		/* top    (don't care) */
+	 0x0000			/* c.o.c. (don't care) */
+	 },
+	{			/* vsb_if_agc_cfg */
+	 DRX_STANDARD_8VSB,	/* standard       */
+	 DRX_AGC_CTRL_AUTO,	/* ctrl_mode       */
+	 0,			/* output_level    */
+	 0,			/* min_output_level */
+	 0xFFFF,		/* max_output_level */
+	 0x0000,		/* speed          */
+	 0x0000,		/* top    (don't care) */
+	 0x0000			/* c.o.c. (don't care) */
+	 },
+	0,			/* qam_pga_cfg */
+	0,			/* vsb_pga_cfg */
+	{			/* qam_pre_saw_cfg */
+	 DRX_STANDARD_ITU_B,	/* standard  */
+	 0,			/* reference */
+	 false			/* use_pre_saw */
+	 },
+	{			/* vsb_pre_saw_cfg */
+	 DRX_STANDARD_8VSB,	/* standard  */
+	 0,			/* reference */
+	 false			/* use_pre_saw */
+	 },
+
+	/* Version information */
+#ifndef _CH_
+	{
+	 "01234567890",		/* human readable version microcode             */
+	 "01234567890"		/* human readable version device specific code  */
+	 },
+	{
+	 {			/* struct drx_version for microcode                   */
+	  DRX_MODULE_UNKNOWN,
+	  (char *)(NULL),
+	  0,
+	  0,
+	  0,
+	  (char *)(NULL)
+	  },
+	 {			/* struct drx_version for device specific code */
+	  DRX_MODULE_UNKNOWN,
+	  (char *)(NULL),
+	  0,
+	  0,
+	  0,
+	  (char *)(NULL)
+	  }
+	 },
+	{
+	 {			/* struct drx_version_list for microcode */
+	  (struct drx_version *) (NULL),
+	  (struct drx_version_list *) (NULL)
+	  },
+	 {			/* struct drx_version_list for device specific code */
+	  (struct drx_version *) (NULL),
+	  (struct drx_version_list *) (NULL)
+	  }
+	 },
+#endif
+	false,			/* smart_ant_inverted */
+	/* Tracking filter setting for OOB  */
+	{
+	 12000,
+	 9300,
+	 6600,
+	 5280,
+	 3700,
+	 3000,
+	 2000,
+	 0},
+	false,			/* oob_power_on           */
+	0,			/* mpeg_ts_static_bitrate  */
+	false,			/* disable_te_ihandling   */
+	false,			/* bit_reverse_mpeg_outout */
+	DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO,	/* mpeg_output_clock_rate */
+	DRXJ_MPEG_START_WIDTH_1CLKCYC,	/* mpeg_start_width */
+
+	/* Pre SAW & Agc configuration for ATV */
+	{
+	 DRX_STANDARD_NTSC,	/* standard     */
+	 7,			/* reference    */
+	 true			/* use_pre_saw    */
+	 },
+	{			/* ATV RF-AGC */
+	 DRX_STANDARD_NTSC,	/* standard              */
+	 DRX_AGC_CTRL_AUTO,	/* ctrl_mode              */
+	 0,			/* output_level           */
+	 0,			/* min_output_level (d.c.) */
+	 0,			/* max_output_level (d.c.) */
+	 3,			/* speed                 */
+	 9500,			/* top                   */
+	 4000			/* cut-off current       */
+	 },
+	{			/* ATV IF-AGC */
+	 DRX_STANDARD_NTSC,	/* standard              */
+	 DRX_AGC_CTRL_AUTO,	/* ctrl_mode              */
+	 0,			/* output_level           */
+	 0,			/* min_output_level (d.c.) */
+	 0,			/* max_output_level (d.c.) */
+	 3,			/* speed                 */
+	 2400,			/* top                   */
+	 0			/* c.o.c.         (d.c.) */
+	 },
+	140,			/* ATV PGA config */
+	0,			/* curr_symbol_rate */
+
+	false,			/* pdr_safe_mode     */
+	SIO_PDR_GPIO_CFG__PRE,	/* pdr_safe_restore_val_gpio  */
+	SIO_PDR_VSYNC_CFG__PRE,	/* pdr_safe_restore_val_v_sync */
+	SIO_PDR_SMA_RX_CFG__PRE,	/* pdr_safe_restore_val_sma_rx */
+	SIO_PDR_SMA_TX_CFG__PRE,	/* pdr_safe_restore_val_sma_tx */
+
+	4,			/* oob_pre_saw            */
+	DRXJ_OOB_LO_POW_MINUS10DB,	/* oob_lo_pow             */
+	{
+	 false			/* aud_data, only first member */
+	 },
+};
+
+/**
+* \var drxj_default_addr_g
+* \brief Default I2C address and device identifier.
+*/
+static struct i2c_device_addr drxj_default_addr_g = {
+	DRXJ_DEF_I2C_ADDR,	/* i2c address */
+	DRXJ_DEF_DEMOD_DEV_ID	/* device id */
+};
+
+/**
+* \var drxj_default_comm_attr_g
+* \brief Default common attributes of a drxj demodulator instance.
+*/
+static struct drx_common_attr drxj_default_comm_attr_g = {
+	NULL,			/* ucode file           */
+	true,			/* ucode verify switch  */
+	{0},			/* version record       */
+
+	44000,			/* IF in kHz in case no tuner instance is used  */
+	(151875 - 0),		/* system clock frequency in kHz                */
+	0,			/* oscillator frequency kHz                     */
+	0,			/* oscillator deviation in ppm, signed          */
+	false,			/* If true mirror frequency spectrum            */
+	{
+	 /* MPEG output configuration */
+	 true,			/* If true, enable MPEG ouput    */
+	 false,			/* If true, insert RS byte       */
+	 false,			/* If true, parallel out otherwise serial */
+	 false,			/* If true, invert DATA signals  */
+	 false,			/* If true, invert ERR signal    */
+	 false,			/* If true, invert STR signals   */
+	 false,			/* If true, invert VAL signals   */
+	 false,			/* If true, invert CLK signals   */
+	 true,			/* If true, static MPEG clockrate will
+				   be used, otherwise clockrate will
+				   adapt to the bitrate of the TS */
+	 19392658UL,		/* Maximum bitrate in b/s in case
+				   static clockrate is selected */
+	 DRX_MPEG_STR_WIDTH_1	/* MPEG Start width in clock cycles */
+	 },
+	/* Initilisations below can be ommited, they require no user input and
+	   are initialy 0, NULL or false. The compiler will initialize them to these
+	   values when ommited.  */
+	false,			/* is_opened */
+
+	/* SCAN */
+	NULL,			/* no scan params yet               */
+	0,			/* current scan index               */
+	0,			/* next scan frequency              */
+	false,			/* scan ready flag                  */
+	0,			/* max channels to scan             */
+	0,			/* nr of channels scanned           */
+	NULL,			/* default scan function            */
+	NULL,			/* default context pointer          */
+	0,			/* millisec to wait for demod lock  */
+	DRXJ_DEMOD_LOCK,	/* desired lock               */
+	false,
+
+	/* Power management */
+	DRX_POWER_UP,
+
+	/* Tuner */
+	1,			/* nr of I2C port to wich tuner is     */
+	0L,			/* minimum RF input frequency, in kHz  */
+	0L,			/* maximum RF input frequency, in kHz  */
+	false,			/* Rf Agc Polarity                     */
+	false,			/* If Agc Polarity                     */
+	false,			/* tuner slow mode                     */
+
+	{			/* current channel (all 0)             */
+	 0UL			/* channel.frequency */
+	 },
+	DRX_STANDARD_UNKNOWN,	/* current standard */
+	DRX_STANDARD_UNKNOWN,	/* previous standard */
+	DRX_STANDARD_UNKNOWN,	/* di_cache_standard   */
+	false,			/* use_bootloader */
+	0UL,			/* capabilities */
+	0			/* mfx */
+};
+
+/**
+* \var drxj_default_demod_g
+* \brief Default drxj demodulator instance.
+*/
+static struct drx_demod_instance drxj_default_demod_g = {
+	&drxj_default_addr_g,	/* i2c address & device id */
+	&drxj_default_comm_attr_g,	/* demod common attributes */
+	&drxj_data_g		/* demod device specific attributes */
+};
+
+/**
+* \brief Default audio data structure for DRK demodulator instance.
+*
+* This structure is DRXK specific.
+*
+*/
+static struct drx_aud_data drxj_default_aud_data_g = {
+	false,			/* audio_is_active */
+	DRX_AUD_STANDARD_AUTO,	/* audio_standard  */
+
+	/* i2sdata */
+	{
+	 false,			/* output_enable   */
+	 48000,			/* frequency      */
+	 DRX_I2S_MODE_MASTER,	/* mode           */
+	 DRX_I2S_WORDLENGTH_32,	/* word_length     */
+	 DRX_I2S_POLARITY_RIGHT,	/* polarity       */
+	 DRX_I2S_FORMAT_WS_WITH_DATA	/* format         */
+	 },
+	/* volume            */
+	{
+	 true,			/* mute;          */
+	 0,			/* volume         */
+	 DRX_AUD_AVC_OFF,	/* avc_mode        */
+	 0,			/* avc_ref_level    */
+	 DRX_AUD_AVC_MAX_GAIN_12DB,	/* avc_max_gain     */
+	 DRX_AUD_AVC_MAX_ATTEN_24DB,	/* avc_max_atten    */
+	 0,			/* strength_left   */
+	 0			/* strength_right  */
+	 },
+	DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_ON,	/* auto_sound */
+	/*  ass_thresholds */
+	{
+	 440,			/* A2    */
+	 12,			/* BTSC  */
+	 700,			/* NICAM */
+	 },
+	/* carrier */
+	{
+	 /* a */
+	 {
+	  42,			/* thres */
+	  DRX_NO_CARRIER_NOISE,	/* opt   */
+	  0,			/* shift */
+	  0			/* dco   */
+	  },
+	 /* b */
+	 {
+	  42,			/* thres */
+	  DRX_NO_CARRIER_MUTE,	/* opt   */
+	  0,			/* shift */
+	  0			/* dco   */
+	  },
+
+	 },
+	/* mixer */
+	{
+	 DRX_AUD_SRC_STEREO_OR_A,	/* source_i2s */
+	 DRX_AUD_I2S_MATRIX_STEREO,	/* matrix_i2s */
+	 DRX_AUD_FM_MATRIX_SOUND_A	/* matrix_fm  */
+	 },
+	DRX_AUD_DEVIATION_NORMAL,	/* deviation */
+	DRX_AUD_AVSYNC_OFF,	/* av_sync */
+
+	/* prescale */
+	{
+	 DRX_AUD_MAX_FM_DEVIATION,	/* fm_deviation */
+	 DRX_AUD_MAX_NICAM_PRESCALE	/* nicam_gain */
+	 },
+	DRX_AUD_FM_DEEMPH_75US,	/* deemph */
+	DRX_BTSC_STEREO,	/* btsc_detect */
+	0,			/* rds_data_counter */
+	false			/* rds_data_present */
+};
+
+/*-----------------------------------------------------------------------------
+STRUCTURES
+----------------------------------------------------------------------------*/
+struct drxjeq_stat {
+	u16 eq_mse;
+	u8 eq_mode;
+	u8 eq_ctrl;
+	u8 eq_stat;
+};
+
+/* HI command */
+struct drxj_hi_cmd {
+	u16 cmd;
+	u16 param1;
+	u16 param2;
+	u16 param3;
+	u16 param4;
+	u16 param5;
+	u16 param6;
+};
+
+/*============================================================================*/
+/*=== MICROCODE RELATED STRUCTURES ===========================================*/
+/*============================================================================*/
+
+/**
+ * struct drxu_code_block_hdr - Structure of the microcode block headers
+ *
+ * @addr:	Destination address of the data in this block
+ * @size:	Size of the block data following this header counted in
+ *		16 bits words
+ * @CRC:	CRC value of the data block, only valid if CRC flag is
+ *		set.
+ */
+struct drxu_code_block_hdr {
+	u32 addr;
+	u16 size;
+	u16 flags;
+	u16 CRC;
+};
+
+/*-----------------------------------------------------------------------------
+FUNCTIONS
+----------------------------------------------------------------------------*/
+/* Some prototypes */
+static int
+hi_command(struct i2c_device_addr *dev_addr,
+	   const struct drxj_hi_cmd *cmd, u16 *result);
+
+static int
+ctrl_lock_status(struct drx_demod_instance *demod, enum drx_lock_status *lock_stat);
+
+static int
+ctrl_power_mode(struct drx_demod_instance *demod, enum drx_power_mode *mode);
+
+static int power_down_aud(struct drx_demod_instance *demod);
+
+static int
+ctrl_set_cfg_pre_saw(struct drx_demod_instance *demod, struct drxj_cfg_pre_saw *pre_saw);
+
+static int
+ctrl_set_cfg_afe_gain(struct drx_demod_instance *demod, struct drxj_cfg_afe_gain *afe_gain);
+
+/*============================================================================*/
+/*============================================================================*/
+/*==                          HELPER FUNCTIONS                              ==*/
+/*============================================================================*/
+/*============================================================================*/
+
+
+/*============================================================================*/
+
+/*
+* \fn u32 frac28(u32 N, u32 D)
+* \brief Compute: (1<<28)*N/D
+* \param N 32 bits
+* \param D 32 bits
+* \return (1<<28)*N/D
+* This function is used to avoid floating-point calculations as they may
+* not be present on the target platform.
+
+* frac28 performs an unsigned 28/28 bits division to 32-bit fixed point
+* fraction used for setting the Frequency Shifter registers.
+* N and D can hold numbers up to width: 28-bits.
+* The 4 bits integer part and the 28 bits fractional part are calculated.
+
+* Usage condition: ((1<<28)*n)/d < ((1<<32)-1) => (n/d) < 15.999
+
+* N: 0...(1<<28)-1 = 268435454
+* D: 0...(1<<28)-1
+* Q: 0...(1<<32)-1
+*/
+static u32 frac28(u32 N, u32 D)
+{
+	int i = 0;
+	u32 Q1 = 0;
+	u32 R0 = 0;
+
+	R0 = (N % D) << 4;	/* 32-28 == 4 shifts possible at max */
+	Q1 = N / D;		/* 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 / D;
+		R0 = (R0 % D) << 4;
+	}
+	/* rounding */
+	if ((R0 >> 3) >= D)
+		Q1++;
+
+	return Q1;
+}
+
+/**
+* \fn u32 log1_times100( u32 x)
+* \brief Compute: 100*log10(x)
+* \param x 32 bits
+* \return 100*log10(x)
+*
+* 100*log10(x)
+* = 100*(log2(x)/log2(10)))
+* = (100*(2^15)*log2(x))/((2^15)*log2(10))
+* = ((200*(2^15)*log2(x))/((2^15)*log2(10)))/2
+* = ((200*(2^15)*(log2(x/y)+log2(y)))/((2^15)*log2(10)))/2
+* = ((200*(2^15)*log2(x/y))+(200*(2^15)*log2(y)))/((2^15)*log2(10)))/2
+*
+* where y = 2^k and 1<= (x/y) < 2
+*/
+
+static u32 log1_times100(u32 x)
+{
+	static const u8 scale = 15;
+	static const u8 index_width = 5;
+	/*
+	   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 */
+	};
+
+	u8 i = 0;
+	u32 y = 0;
+	u32 d = 0;
+	u32 k = 0;
+	u32 r = 0;
+
+	if (x == 0)
+		return 0;
+
+	/* Scale x (normalize) */
+	/* computing y in log(x/y) = log(x) - log(y) */
+	if ((x & (((u32) (-1)) << (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 - index_width));
+	/* compute delta (x-a) */
+	d = x & ((((u32) 1) << (scale - index_width)) - 1);
+	/* compute log, multiplication ( d* (.. )) must be within range ! */
+	y += log2lut[i] +
+	    ((d * (log2lut[i + 1] - log2lut[i])) >> (scale - index_width));
+	/* Conver to log10() */
+	y /= 108853;		/* (log2(10) << scale) */
+	r = (y >> 1);
+	/* rounding */
+	if (y & ((u32)1))
+		r++;
+
+	return r;
+
+}
+
+/**
+* \fn u32 frac_times1e6( u16 N, u32 D)
+* \brief Compute: (N/D) * 1000000.
+* \param N nominator 16-bits.
+* \param D denominator 32-bits.
+* \return u32
+* \retval ((N/D) * 1000000), 32 bits
+*
+* No check on D=0!
+*/
+static u32 frac_times1e6(u32 N, u32 D)
+{
+	u32 remainder = 0;
+	u32 frac = 0;
+
+	/*
+	   frac = (N * 1000000) / D
+	   To let it fit in a 32 bits computation:
+	   frac = (N * (1000000 >> 4)) / (D >> 4)
+	   This would result in a problem in case D < 16 (div by 0).
+	   So we do it more elaborate as shown below.
+	 */
+	frac = (((u32) N) * (1000000 >> 4)) / D;
+	frac <<= 4;
+	remainder = (((u32) N) * (1000000 >> 4)) % D;
+	remainder <<= 4;
+	frac += remainder / D;
+	remainder = remainder % D;
+	if ((remainder * 2) > D)
+		frac++;
+
+	return frac;
+}
+
+/*============================================================================*/
+
+
+/**
+* \brief Values for NICAM prescaler gain. Computed from dB to integer
+*        and rounded. For calc used formula: 16*10^(prescaleGain[dB]/20).
+*
+*/
+static const u16 nicam_presc_table_val[43] = {
+	1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4,
+	5, 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16,
+	18, 20, 23, 25, 28, 32, 36, 40, 45,
+	51, 57, 64, 71, 80, 90, 101, 113, 127
+};
+
+/*============================================================================*/
+/*==                        END HELPER FUNCTIONS                            ==*/
+/*============================================================================*/
+
+/*============================================================================*/
+/*============================================================================*/
+/*==                      DRXJ DAP FUNCTIONS                                ==*/
+/*============================================================================*/
+/*============================================================================*/
+
+/*
+   This layer takes care of some device specific register access protocols:
+   -conversion to short address format
+   -access to audio block
+   This layer is placed between the drx_dap_fasi and the rest of the drxj
+   specific implementation. This layer can use address map knowledge whereas
+   dap_fasi may not use memory map knowledge.
+
+   * For audio currently only 16 bits read and write register access is
+     supported. More is not needed. RMW and 32 or 8 bit access on audio
+     registers will have undefined behaviour. Flags (RMW, CRC reset, broadcast
+     single/multi master) will be ignored.
+
+   TODO: check ignoring single/multimaster is ok for AUD access ?
+*/
+
+#define DRXJ_ISAUDWRITE(addr) (((((addr)>>16)&1) == 1) ? true : false)
+#define DRXJ_DAP_AUDTRIF_TIMEOUT 80	/* millisec */
+/*============================================================================*/
+
+/**
+* \fn bool is_handled_by_aud_tr_if( u32 addr )
+* \brief Check if this address is handled by the audio token ring interface.
+* \param addr
+* \return bool
+* \retval true  Yes, handled by audio token ring interface
+* \retval false No, not handled by audio token ring interface
+*
+*/
+static
+bool is_handled_by_aud_tr_if(u32 addr)
+{
+	bool retval = false;
+
+	if ((DRXDAP_FASI_ADDR2BLOCK(addr) == 4) &&
+	    (DRXDAP_FASI_ADDR2BANK(addr) > 1) &&
+	    (DRXDAP_FASI_ADDR2BANK(addr) < 6)) {
+		retval = true;
+	}
+
+	return retval;
+}
+
+/*============================================================================*/
+
+int drxbsp_i2c_write_read(struct i2c_device_addr *w_dev_addr,
+				 u16 w_count,
+				 u8 *wData,
+				 struct i2c_device_addr *r_dev_addr,
+				 u16 r_count, u8 *r_data)
+{
+	struct drx39xxj_state *state;
+	struct i2c_msg msg[2];
+	unsigned int num_msgs;
+
+	if (w_dev_addr == NULL) {
+		/* Read only */
+		state = r_dev_addr->user_data;
+		msg[0].addr = r_dev_addr->i2c_addr >> 1;
+		msg[0].flags = I2C_M_RD;
+		msg[0].buf = r_data;
+		msg[0].len = r_count;
+		num_msgs = 1;
+	} else if (r_dev_addr == NULL) {
+		/* Write only */
+		state = w_dev_addr->user_data;
+		msg[0].addr = w_dev_addr->i2c_addr >> 1;
+		msg[0].flags = 0;
+		msg[0].buf = wData;
+		msg[0].len = w_count;
+		num_msgs = 1;
+	} else {
+		/* Both write and read */
+		state = w_dev_addr->user_data;
+		msg[0].addr = w_dev_addr->i2c_addr >> 1;
+		msg[0].flags = 0;
+		msg[0].buf = wData;
+		msg[0].len = w_count;
+		msg[1].addr = r_dev_addr->i2c_addr >> 1;
+		msg[1].flags = I2C_M_RD;
+		msg[1].buf = r_data;
+		msg[1].len = r_count;
+		num_msgs = 2;
+	}
+
+	if (state->i2c == NULL) {
+		pr_err("i2c was zero, aborting\n");
+		return 0;
+	}
+	if (i2c_transfer(state->i2c, msg, num_msgs) != num_msgs) {
+		pr_warn("drx3933: I2C write/read failed\n");
+		return -EREMOTEIO;
+	}
+
+#ifdef DJH_DEBUG
+	if (w_dev_addr == NULL || r_dev_addr == NULL)
+		return 0;
+
+	state = w_dev_addr->user_data;
+
+	if (state->i2c == NULL)
+		return 0;
+
+	msg[0].addr = w_dev_addr->i2c_addr;
+	msg[0].flags = 0;
+	msg[0].buf = wData;
+	msg[0].len = w_count;
+	msg[1].addr = r_dev_addr->i2c_addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].buf = r_data;
+	msg[1].len = r_count;
+	num_msgs = 2;
+
+	pr_debug("drx3933 i2c operation addr=%x i2c=%p, wc=%x rc=%x\n",
+	       w_dev_addr->i2c_addr, state->i2c, w_count, r_count);
+
+	if (i2c_transfer(state->i2c, msg, 2) != 2) {
+		pr_warn("drx3933: I2C write/read failed\n");
+		return -EREMOTEIO;
+	}
+#endif
+	return 0;
+}
+
+/*============================================================================*/
+
+/******************************
+*
+* int drxdap_fasi_read_block (
+*      struct i2c_device_addr *dev_addr,      -- address of I2C device
+*      u32 addr,         -- address of chip register/memory
+*      u16            datasize,     -- number of bytes to read
+*      u8 *data,         -- data to receive
+*      u32 flags)        -- special device flags
+*
+* Read block data from chip address. Because the chip is word oriented,
+* the number of bytes to read must be even.
+*
+* Make sure that the buffer to receive the data is large enough.
+*
+* Although this function expects an even number of bytes, it is still byte
+* oriented, and the data read back is NOT translated to the endianness of
+* the target platform.
+*
+* Output:
+* - 0     if reading was successful
+*                  in that case: data read is in *data.
+* - -EIO  if anything went wrong
+*
+******************************/
+
+static int drxdap_fasi_read_block(struct i2c_device_addr *dev_addr,
+					 u32 addr,
+					 u16 datasize,
+					 u8 *data, u32 flags)
+{
+	u8 buf[4];
+	u16 bufx;
+	int rc;
+	u16 overhead_size = 0;
+
+	/* Check parameters ******************************************************* */
+	if (dev_addr == NULL)
+		return -EINVAL;
+
+	overhead_size = (IS_I2C_10BIT(dev_addr->i2c_addr) ? 2 : 1) +
+	    (DRXDAP_FASI_LONG_FORMAT(addr) ? 4 : 2);
+
+	if ((DRXDAP_FASI_OFFSET_TOO_LARGE(addr)) ||
+	    ((!(DRXDAPFASI_LONG_ADDR_ALLOWED)) &&
+	     DRXDAP_FASI_LONG_FORMAT(addr)) ||
+	    (overhead_size > (DRXDAP_MAX_WCHUNKSIZE)) ||
+	    ((datasize != 0) && (data == NULL)) || ((datasize & 1) == 1)) {
+		return -EINVAL;
+	}
+
+	/* ReadModifyWrite & mode flag bits are not allowed */
+	flags &= (~DRXDAP_FASI_RMW & ~DRXDAP_FASI_MODEFLAGS);
+#if DRXDAP_SINGLE_MASTER
+	flags |= DRXDAP_FASI_SINGLE_MASTER;
+#endif
+
+	/* Read block from I2C **************************************************** */
+	do {
+		u16 todo = (datasize < DRXDAP_MAX_RCHUNKSIZE ?
+			      datasize : DRXDAP_MAX_RCHUNKSIZE);
+
+		bufx = 0;
+
+		addr &= ~DRXDAP_FASI_FLAGS;
+		addr |= flags;
+
+#if ((DRXDAPFASI_LONG_ADDR_ALLOWED == 1) && (DRXDAPFASI_SHORT_ADDR_ALLOWED == 1))
+		/* short format address preferred but long format otherwise */
+		if (DRXDAP_FASI_LONG_FORMAT(addr)) {
+#endif
+#if (DRXDAPFASI_LONG_ADDR_ALLOWED == 1)
+			buf[bufx++] = (u8) (((addr << 1) & 0xFF) | 0x01);
+			buf[bufx++] = (u8) ((addr >> 16) & 0xFF);
+			buf[bufx++] = (u8) ((addr >> 24) & 0xFF);
+			buf[bufx++] = (u8) ((addr >> 7) & 0xFF);
+#endif
+#if ((DRXDAPFASI_LONG_ADDR_ALLOWED == 1) && (DRXDAPFASI_SHORT_ADDR_ALLOWED == 1))
+		} else {
+#endif
+#if (DRXDAPFASI_SHORT_ADDR_ALLOWED == 1)
+			buf[bufx++] = (u8) ((addr << 1) & 0xFF);
+			buf[bufx++] =
+			    (u8) (((addr >> 16) & 0x0F) |
+				    ((addr >> 18) & 0xF0));
+#endif
+#if ((DRXDAPFASI_LONG_ADDR_ALLOWED == 1) && (DRXDAPFASI_SHORT_ADDR_ALLOWED == 1))
+		}
+#endif
+
+#if DRXDAP_SINGLE_MASTER
+		/*
+		 * In single master mode, split the read and write actions.
+		 * No special action is needed for write chunks here.
+		 */
+		rc = drxbsp_i2c_write_read(dev_addr, bufx, buf,
+					   NULL, 0, NULL);
+		if (rc == 0)
+			rc = drxbsp_i2c_write_read(NULL, 0, NULL, dev_addr, todo, data);
+#else
+		/* In multi master mode, do everything in one RW action */
+		rc = drxbsp_i2c_write_read(dev_addr, bufx, buf, dev_addr, todo,
+					  data);
+#endif
+		data += todo;
+		addr += (todo >> 1);
+		datasize -= todo;
+	} while (datasize && rc == 0);
+
+	return rc;
+}
+
+
+/******************************
+*
+* int drxdap_fasi_read_reg16 (
+*     struct i2c_device_addr *dev_addr, -- address of I2C device
+*     u32 addr,    -- address of chip register/memory
+*     u16 *data,    -- data to receive
+*     u32 flags)   -- special device flags
+*
+* Read one 16-bit register or memory location. The data received back is
+* converted back to the target platform's endianness.
+*
+* Output:
+* - 0     if reading was successful
+*                  in that case: read data is at *data
+* - -EIO  if anything went wrong
+*
+******************************/
+
+static int drxdap_fasi_read_reg16(struct i2c_device_addr *dev_addr,
+					 u32 addr,
+					 u16 *data, u32 flags)
+{
+	u8 buf[sizeof(*data)];
+	int rc;
+
+	if (!data)
+		return -EINVAL;
+
+	rc = drxdap_fasi_read_block(dev_addr, addr, sizeof(*data), buf, flags);
+	*data = buf[0] + (((u16) buf[1]) << 8);
+	return rc;
+}
+
+/******************************
+*
+* int drxdap_fasi_read_reg32 (
+*     struct i2c_device_addr *dev_addr, -- address of I2C device
+*     u32 addr,    -- address of chip register/memory
+*     u32 *data,    -- data to receive
+*     u32 flags)   -- special device flags
+*
+* Read one 32-bit register or memory location. The data received back is
+* converted back to the target platform's endianness.
+*
+* Output:
+* - 0     if reading was successful
+*                  in that case: read data is at *data
+* - -EIO  if anything went wrong
+*
+******************************/
+
+static int drxdap_fasi_read_reg32(struct i2c_device_addr *dev_addr,
+					 u32 addr,
+					 u32 *data, u32 flags)
+{
+	u8 buf[sizeof(*data)];
+	int rc;
+
+	if (!data)
+		return -EINVAL;
+
+	rc = drxdap_fasi_read_block(dev_addr, addr, sizeof(*data), buf, flags);
+	*data = (((u32) buf[0]) << 0) +
+	    (((u32) buf[1]) << 8) +
+	    (((u32) buf[2]) << 16) + (((u32) buf[3]) << 24);
+	return rc;
+}
+
+/******************************
+*
+* int drxdap_fasi_write_block (
+*      struct i2c_device_addr *dev_addr,    -- address of I2C device
+*      u32 addr,       -- address of chip register/memory
+*      u16            datasize,   -- number of bytes to read
+*      u8 *data,       -- data to receive
+*      u32 flags)      -- special device flags
+*
+* Write block data to chip address. Because the chip is word oriented,
+* the number of bytes to write must be even.
+*
+* Although this function expects an even number of bytes, it is still byte
+* oriented, and the data being written is NOT translated from the endianness of
+* the target platform.
+*
+* Output:
+* - 0     if writing was successful
+* - -EIO  if anything went wrong
+*
+******************************/
+
+static int drxdap_fasi_write_block(struct i2c_device_addr *dev_addr,
+					  u32 addr,
+					  u16 datasize,
+					  u8 *data, u32 flags)
+{
+	u8 buf[DRXDAP_MAX_WCHUNKSIZE];
+	int st = -EIO;
+	int first_err = 0;
+	u16 overhead_size = 0;
+	u16 block_size = 0;
+
+	/* Check parameters ******************************************************* */
+	if (dev_addr == NULL)
+		return -EINVAL;
+
+	overhead_size = (IS_I2C_10BIT(dev_addr->i2c_addr) ? 2 : 1) +
+	    (DRXDAP_FASI_LONG_FORMAT(addr) ? 4 : 2);
+
+	if ((DRXDAP_FASI_OFFSET_TOO_LARGE(addr)) ||
+	    ((!(DRXDAPFASI_LONG_ADDR_ALLOWED)) &&
+	     DRXDAP_FASI_LONG_FORMAT(addr)) ||
+	    (overhead_size > (DRXDAP_MAX_WCHUNKSIZE)) ||
+	    ((datasize != 0) && (data == NULL)) || ((datasize & 1) == 1))
+		return -EINVAL;
+
+	flags &= DRXDAP_FASI_FLAGS;
+	flags &= ~DRXDAP_FASI_MODEFLAGS;
+#if DRXDAP_SINGLE_MASTER
+	flags |= DRXDAP_FASI_SINGLE_MASTER;
+#endif
+
+	/* Write block to I2C ***************************************************** */
+	block_size = ((DRXDAP_MAX_WCHUNKSIZE) - overhead_size) & ~1;
+	do {
+		u16 todo = 0;
+		u16 bufx = 0;
+
+		/* Buffer device address */
+		addr &= ~DRXDAP_FASI_FLAGS;
+		addr |= flags;
+#if (((DRXDAPFASI_LONG_ADDR_ALLOWED) == 1) && ((DRXDAPFASI_SHORT_ADDR_ALLOWED) == 1))
+		/* short format address preferred but long format otherwise */
+		if (DRXDAP_FASI_LONG_FORMAT(addr)) {
+#endif
+#if ((DRXDAPFASI_LONG_ADDR_ALLOWED) == 1)
+			buf[bufx++] = (u8) (((addr << 1) & 0xFF) | 0x01);
+			buf[bufx++] = (u8) ((addr >> 16) & 0xFF);
+			buf[bufx++] = (u8) ((addr >> 24) & 0xFF);
+			buf[bufx++] = (u8) ((addr >> 7) & 0xFF);
+#endif
+#if (((DRXDAPFASI_LONG_ADDR_ALLOWED) == 1) && ((DRXDAPFASI_SHORT_ADDR_ALLOWED) == 1))
+		} else {
+#endif
+#if ((DRXDAPFASI_SHORT_ADDR_ALLOWED) == 1)
+			buf[bufx++] = (u8) ((addr << 1) & 0xFF);
+			buf[bufx++] =
+			    (u8) (((addr >> 16) & 0x0F) |
+				    ((addr >> 18) & 0xF0));
+#endif
+#if (((DRXDAPFASI_LONG_ADDR_ALLOWED) == 1) && ((DRXDAPFASI_SHORT_ADDR_ALLOWED) == 1))
+		}
+#endif
+
+		/*
+		   In single master mode block_size can be 0. In such a case this I2C
+		   sequense will be visible: (1) write address {i2c addr,
+		   4 bytes chip address} (2) write data {i2c addr, 4 bytes data }
+		   (3) write address (4) write data etc...
+		   Addres must be rewriten because HI is reset after data transport and
+		   expects an address.
+		 */
+		todo = (block_size < datasize ? block_size : datasize);
+		if (todo == 0) {
+			u16 overhead_size_i2c_addr = 0;
+			u16 data_block_size = 0;
+
+			overhead_size_i2c_addr =
+			    (IS_I2C_10BIT(dev_addr->i2c_addr) ? 2 : 1);
+			data_block_size =
+			    (DRXDAP_MAX_WCHUNKSIZE - overhead_size_i2c_addr) & ~1;
+
+			/* write device address */
+			st = drxbsp_i2c_write_read(dev_addr,
+						  (u16) (bufx),
+						  buf,
+						  (struct i2c_device_addr *)(NULL),
+						  0, (u8 *)(NULL));
+
+			if ((st != 0) && (first_err == 0)) {
+				/* at the end, return the first error encountered */
+				first_err = st;
+			}
+			bufx = 0;
+			todo =
+			    (data_block_size <
+			     datasize ? data_block_size : datasize);
+		}
+		memcpy(&buf[bufx], data, todo);
+		/* write (address if can do and) data */
+		st = drxbsp_i2c_write_read(dev_addr,
+					  (u16) (bufx + todo),
+					  buf,
+					  (struct i2c_device_addr *)(NULL),
+					  0, (u8 *)(NULL));
+
+		if ((st != 0) && (first_err == 0)) {
+			/* at the end, return the first error encountered */
+			first_err = st;
+		}
+		datasize -= todo;
+		data += todo;
+		addr += (todo >> 1);
+	} while (datasize);
+
+	return first_err;
+}
+
+/******************************
+*
+* int drxdap_fasi_write_reg16 (
+*     struct i2c_device_addr *dev_addr, -- address of I2C device
+*     u32 addr,    -- address of chip register/memory
+*     u16            data,    -- data to send
+*     u32 flags)   -- special device flags
+*
+* Write one 16-bit register or memory location. The data being written is
+* converted from the target platform's endianness to little endian.
+*
+* Output:
+* - 0     if writing was successful
+* - -EIO  if anything went wrong
+*
+******************************/
+
+static int drxdap_fasi_write_reg16(struct i2c_device_addr *dev_addr,
+					  u32 addr,
+					  u16 data, u32 flags)
+{
+	u8 buf[sizeof(data)];
+
+	buf[0] = (u8) ((data >> 0) & 0xFF);
+	buf[1] = (u8) ((data >> 8) & 0xFF);
+
+	return drxdap_fasi_write_block(dev_addr, addr, sizeof(data), buf, flags);
+}
+
+/******************************
+*
+* int drxdap_fasi_read_modify_write_reg16 (
+*      struct i2c_device_addr *dev_addr,   -- address of I2C device
+*      u32 waddr,     -- address of chip register/memory
+*      u32 raddr,     -- chip address to read back from
+*      u16            wdata,     -- data to send
+*      u16 *rdata)     -- data to receive back
+*
+* Write 16-bit data, then read back the original contents of that location.
+* Requires long addressing format to be allowed.
+*
+* Before sending data, the data is converted to little endian. The
+* data received back is converted back to the target platform's endianness.
+*
+* WARNING: This function is only guaranteed to work if there is one
+* master on the I2C bus.
+*
+* Output:
+* - 0     if reading was successful
+*                  in that case: read back data is at *rdata
+* - -EIO  if anything went wrong
+*
+******************************/
+
+static int drxdap_fasi_read_modify_write_reg16(struct i2c_device_addr *dev_addr,
+						    u32 waddr,
+						    u32 raddr,
+						    u16 wdata, u16 *rdata)
+{
+	int rc = -EIO;
+
+#if (DRXDAPFASI_LONG_ADDR_ALLOWED == 1)
+	if (rdata == NULL)
+		return -EINVAL;
+
+	rc = drxdap_fasi_write_reg16(dev_addr, waddr, wdata, DRXDAP_FASI_RMW);
+	if (rc == 0)
+		rc = drxdap_fasi_read_reg16(dev_addr, raddr, rdata, 0);
+#endif
+
+	return rc;
+}
+
+/******************************
+*
+* int drxdap_fasi_write_reg32 (
+*     struct i2c_device_addr *dev_addr, -- address of I2C device
+*     u32 addr,    -- address of chip register/memory
+*     u32            data,    -- data to send
+*     u32 flags)   -- special device flags
+*
+* Write one 32-bit register or memory location. The data being written is
+* converted from the target platform's endianness to little endian.
+*
+* Output:
+* - 0     if writing was successful
+* - -EIO  if anything went wrong
+*
+******************************/
+
+static int drxdap_fasi_write_reg32(struct i2c_device_addr *dev_addr,
+					  u32 addr,
+					  u32 data, u32 flags)
+{
+	u8 buf[sizeof(data)];
+
+	buf[0] = (u8) ((data >> 0) & 0xFF);
+	buf[1] = (u8) ((data >> 8) & 0xFF);
+	buf[2] = (u8) ((data >> 16) & 0xFF);
+	buf[3] = (u8) ((data >> 24) & 0xFF);
+
+	return drxdap_fasi_write_block(dev_addr, addr, sizeof(data), buf, flags);
+}
+
+/*============================================================================*/
+
+/**
+* \fn int drxj_dap_rm_write_reg16short
+* \brief Read modify write 16 bits audio register using short format only.
+* \param dev_addr
+* \param waddr    Address to write to
+* \param raddr    Address to read from (usually SIO_HI_RA_RAM_S0_RMWBUF__A)
+* \param wdata    Data to write
+* \param rdata    Buffer for data to read
+* \return int
+* \retval 0 Succes
+* \retval -EIO Timeout, I2C error, illegal bank
+*
+* 16 bits register read modify write access using short addressing format only.
+* Requires knowledge of the registermap, thus device dependent.
+* Using DAP FASI directly to avoid endless recursion of RMWs to audio registers.
+*
+*/
+
+/* TODO correct define should be #if ( DRXDAPFASI_SHORT_ADDR_ALLOWED==1 )
+   See comments drxj_dap_read_modify_write_reg16 */
+#if (DRXDAPFASI_LONG_ADDR_ALLOWED == 0)
+static int drxj_dap_rm_write_reg16short(struct i2c_device_addr *dev_addr,
+					      u32 waddr,
+					      u32 raddr,
+					      u16 wdata, u16 *rdata)
+{
+	int rc;
+
+	if (rdata == NULL)
+		return -EINVAL;
+
+	/* Set RMW flag */
+	rc = drxdap_fasi_write_reg16(dev_addr,
+					      SIO_HI_RA_RAM_S0_FLG_ACC__A,
+					      SIO_HI_RA_RAM_S0_FLG_ACC_S0_RWM__M,
+					      0x0000);
+	if (rc == 0) {
+		/* Write new data: triggers RMW */
+		rc = drxdap_fasi_write_reg16(dev_addr, waddr, wdata,
+						      0x0000);
+	}
+	if (rc == 0) {
+		/* Read old data */
+		rc = drxdap_fasi_read_reg16(dev_addr, raddr, rdata,
+						     0x0000);
+	}
+	if (rc == 0) {
+		/* Reset RMW flag */
+		rc = drxdap_fasi_write_reg16(dev_addr,
+						      SIO_HI_RA_RAM_S0_FLG_ACC__A,
+						      0, 0x0000);
+	}
+
+	return rc;
+}
+#endif
+
+/*============================================================================*/
+
+static int drxj_dap_read_modify_write_reg16(struct i2c_device_addr *dev_addr,
+						 u32 waddr,
+						 u32 raddr,
+						 u16 wdata, u16 *rdata)
+{
+	/* TODO: correct short/long addressing format decision,
+	   now long format has higher prio then short because short also
+	   needs virt bnks (not impl yet) for certain audio registers */
+#if (DRXDAPFASI_LONG_ADDR_ALLOWED == 1)
+	return drxdap_fasi_read_modify_write_reg16(dev_addr,
+							  waddr,
+							  raddr, wdata, rdata);
+#else
+	return drxj_dap_rm_write_reg16short(dev_addr, waddr, raddr, wdata, rdata);
+#endif
+}
+
+
+/*============================================================================*/
+
+/**
+* \fn int drxj_dap_read_aud_reg16
+* \brief Read 16 bits audio register
+* \param dev_addr
+* \param addr
+* \param data
+* \return int
+* \retval 0 Succes
+* \retval -EIO Timeout, I2C error, illegal bank
+*
+* 16 bits register read access via audio token ring interface.
+*
+*/
+static int drxj_dap_read_aud_reg16(struct i2c_device_addr *dev_addr,
+					 u32 addr, u16 *data)
+{
+	u32 start_timer = 0;
+	u32 current_timer = 0;
+	u32 delta_timer = 0;
+	u16 tr_status = 0;
+	int stat = -EIO;
+
+	/* No read possible for bank 3, return with error */
+	if (DRXDAP_FASI_ADDR2BANK(addr) == 3) {
+		stat = -EINVAL;
+	} else {
+		const u32 write_bit = ((dr_xaddr_t) 1) << 16;
+
+		/* Force reset write bit */
+		addr &= (~write_bit);
+
+		/* Set up read */
+		start_timer = jiffies_to_msecs(jiffies);
+		do {
+			/* RMW to aud TR IF until request is granted or timeout */
+			stat = drxj_dap_read_modify_write_reg16(dev_addr,
+							     addr,
+							     SIO_HI_RA_RAM_S0_RMWBUF__A,
+							     0x0000, &tr_status);
+
+			if (stat != 0)
+				break;
+
+			current_timer = jiffies_to_msecs(jiffies);
+			delta_timer = current_timer - start_timer;
+			if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) {
+				stat = -EIO;
+				break;
+			}
+
+		} while (((tr_status & AUD_TOP_TR_CTR_FIFO_LOCK__M) ==
+			  AUD_TOP_TR_CTR_FIFO_LOCK_LOCKED) ||
+			 ((tr_status & AUD_TOP_TR_CTR_FIFO_FULL__M) ==
+			  AUD_TOP_TR_CTR_FIFO_FULL_FULL));
+	}			/* if ( DRXDAP_FASI_ADDR2BANK(addr)!=3 ) */
+
+	/* Wait for read ready status or timeout */
+	if (stat == 0) {
+		start_timer = jiffies_to_msecs(jiffies);
+
+		while ((tr_status & AUD_TOP_TR_CTR_FIFO_RD_RDY__M) !=
+		       AUD_TOP_TR_CTR_FIFO_RD_RDY_READY) {
+			stat = drxj_dap_read_reg16(dev_addr,
+						  AUD_TOP_TR_CTR__A,
+						  &tr_status, 0x0000);
+			if (stat != 0)
+				break;
+
+			current_timer = jiffies_to_msecs(jiffies);
+			delta_timer = current_timer - start_timer;
+			if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) {
+				stat = -EIO;
+				break;
+			}
+		}		/* while ( ... ) */
+	}
+
+	/* Read value */
+	if (stat == 0)
+		stat = drxj_dap_read_modify_write_reg16(dev_addr,
+						     AUD_TOP_TR_RD_REG__A,
+						     SIO_HI_RA_RAM_S0_RMWBUF__A,
+						     0x0000, data);
+	return stat;
+}
+
+/*============================================================================*/
+
+static int drxj_dap_read_reg16(struct i2c_device_addr *dev_addr,
+				      u32 addr,
+				      u16 *data, u32 flags)
+{
+	int stat = -EIO;
+
+	/* Check param */
+	if ((dev_addr == NULL) || (data == NULL))
+		return -EINVAL;
+
+	if (is_handled_by_aud_tr_if(addr))
+		stat = drxj_dap_read_aud_reg16(dev_addr, addr, data);
+	else
+		stat = drxdap_fasi_read_reg16(dev_addr, addr, data, flags);
+
+	return stat;
+}
+/*============================================================================*/
+
+/**
+* \fn int drxj_dap_write_aud_reg16
+* \brief Write 16 bits audio register
+* \param dev_addr
+* \param addr
+* \param data
+* \return int
+* \retval 0 Succes
+* \retval -EIO Timeout, I2C error, illegal bank
+*
+* 16 bits register write access via audio token ring interface.
+*
+*/
+static int drxj_dap_write_aud_reg16(struct i2c_device_addr *dev_addr,
+					  u32 addr, u16 data)
+{
+	int stat = -EIO;
+
+	/* No write possible for bank 2, return with error */
+	if (DRXDAP_FASI_ADDR2BANK(addr) == 2) {
+		stat = -EINVAL;
+	} else {
+		u32 start_timer = 0;
+		u32 current_timer = 0;
+		u32 delta_timer = 0;
+		u16 tr_status = 0;
+		const u32 write_bit = ((dr_xaddr_t) 1) << 16;
+
+		/* Force write bit */
+		addr |= write_bit;
+		start_timer = jiffies_to_msecs(jiffies);
+		do {
+			/* RMW to aud TR IF until request is granted or timeout */
+			stat = drxj_dap_read_modify_write_reg16(dev_addr,
+							     addr,
+							     SIO_HI_RA_RAM_S0_RMWBUF__A,
+							     data, &tr_status);
+			if (stat != 0)
+				break;
+
+			current_timer = jiffies_to_msecs(jiffies);
+			delta_timer = current_timer - start_timer;
+			if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) {
+				stat = -EIO;
+				break;
+			}
+
+		} while (((tr_status & AUD_TOP_TR_CTR_FIFO_LOCK__M) ==
+			  AUD_TOP_TR_CTR_FIFO_LOCK_LOCKED) ||
+			 ((tr_status & AUD_TOP_TR_CTR_FIFO_FULL__M) ==
+			  AUD_TOP_TR_CTR_FIFO_FULL_FULL));
+
+	}			/* if ( DRXDAP_FASI_ADDR2BANK(addr)!=2 ) */
+
+	return stat;
+}
+
+/*============================================================================*/
+
+static int drxj_dap_write_reg16(struct i2c_device_addr *dev_addr,
+				       u32 addr,
+				       u16 data, u32 flags)
+{
+	int stat = -EIO;
+
+	/* Check param */
+	if (dev_addr == NULL)
+		return -EINVAL;
+
+	if (is_handled_by_aud_tr_if(addr))
+		stat = drxj_dap_write_aud_reg16(dev_addr, addr, data);
+	else
+		stat = drxdap_fasi_write_reg16(dev_addr,
+							    addr, data, flags);
+
+	return stat;
+}
+
+/*============================================================================*/
+
+/* 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 DRXJ_HI_ATOMIC_BUF_START (SIO_HI_RA_RAM_USR_BEGIN__A)
+#define DRXJ_HI_ATOMIC_BUF_END   (SIO_HI_RA_RAM_USR_BEGIN__A + 7)
+#define DRXJ_HI_ATOMIC_READ      SIO_HI_RA_RAM_PAR_3_ACP_RW_READ
+#define DRXJ_HI_ATOMIC_WRITE     SIO_HI_RA_RAM_PAR_3_ACP_RW_WRITE
+
+/**
+* \fn int drxj_dap_atomic_read_write_block()
+* \brief Basic access routine for atomic read or write access
+* \param dev_addr  pointer to i2c dev address
+* \param addr     destination/source address
+* \param datasize size of data buffer in bytes
+* \param data     pointer to data buffer
+* \return int
+* \retval 0 Succes
+* \retval -EIO Timeout, I2C error, illegal bank
+*
+*/
+static
+int drxj_dap_atomic_read_write_block(struct i2c_device_addr *dev_addr,
+					  u32 addr,
+					  u16 datasize,
+					  u8 *data, bool read_flag)
+{
+	struct drxj_hi_cmd hi_cmd;
+	int rc;
+	u16 word;
+	u16 dummy = 0;
+	u16 i = 0;
+
+	/* Parameter check */
+	if (!data || !dev_addr || ((datasize % 2)) || ((datasize / 2) > 8))
+		return -EINVAL;
+
+	/* Set up HI parameters to read or write n bytes */
+	hi_cmd.cmd = SIO_HI_RA_RAM_CMD_ATOMIC_COPY;
+	hi_cmd.param1 =
+	    (u16) ((DRXDAP_FASI_ADDR2BLOCK(DRXJ_HI_ATOMIC_BUF_START) << 6) +
+		     DRXDAP_FASI_ADDR2BANK(DRXJ_HI_ATOMIC_BUF_START));
+	hi_cmd.param2 =
+	    (u16) DRXDAP_FASI_ADDR2OFFSET(DRXJ_HI_ATOMIC_BUF_START);
+	hi_cmd.param3 = (u16) ((datasize / 2) - 1);
+	if (!read_flag)
+		hi_cmd.param3 |= DRXJ_HI_ATOMIC_WRITE;
+	else
+		hi_cmd.param3 |= DRXJ_HI_ATOMIC_READ;
+	hi_cmd.param4 = (u16) ((DRXDAP_FASI_ADDR2BLOCK(addr) << 6) +
+				DRXDAP_FASI_ADDR2BANK(addr));
+	hi_cmd.param5 = (u16) DRXDAP_FASI_ADDR2OFFSET(addr);
+
+	if (!read_flag) {
+		/* write data to buffer */
+		for (i = 0; i < (datasize / 2); i++) {
+
+			word = ((u16) data[2 * i]);
+			word += (((u16) data[(2 * i) + 1]) << 8);
+			drxj_dap_write_reg16(dev_addr,
+					     (DRXJ_HI_ATOMIC_BUF_START + i),
+					    word, 0);
+		}
+	}
+
+	rc = hi_command(dev_addr, &hi_cmd, &dummy);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	if (read_flag) {
+		/* read data from buffer */
+		for (i = 0; i < (datasize / 2); i++) {
+			drxj_dap_read_reg16(dev_addr,
+					    (DRXJ_HI_ATOMIC_BUF_START + i),
+					   &word, 0);
+			data[2 * i] = (u8) (word & 0xFF);
+			data[(2 * i) + 1] = (u8) (word >> 8);
+		}
+	}
+
+	return 0;
+
+rw_error:
+	return -EIO;
+
+}
+
+/*============================================================================*/
+
+/**
+* \fn int drxj_dap_atomic_read_reg32()
+* \brief Atomic read of 32 bits words
+*/
+static
+int drxj_dap_atomic_read_reg32(struct i2c_device_addr *dev_addr,
+				     u32 addr,
+				     u32 *data, u32 flags)
+{
+	u8 buf[sizeof(*data)];
+	int rc = -EIO;
+	u32 word = 0;
+
+	if (!data)
+		return -EINVAL;
+
+	rc = drxj_dap_atomic_read_write_block(dev_addr, addr,
+					      sizeof(*data), buf, true);
+
+	if (rc < 0)
+		return 0;
+
+	word = (u32) buf[3];
+	word <<= 8;
+	word |= (u32) buf[2];
+	word <<= 8;
+	word |= (u32) buf[1];
+	word <<= 8;
+	word |= (u32) buf[0];
+
+	*data = word;
+
+	return rc;
+}
+
+/*============================================================================*/
+
+/*============================================================================*/
+/*==                        END DRXJ DAP FUNCTIONS                          ==*/
+/*============================================================================*/
+
+/*============================================================================*/
+/*============================================================================*/
+/*==                      HOST INTERFACE FUNCTIONS                          ==*/
+/*============================================================================*/
+/*============================================================================*/
+
+/**
+* \fn int hi_cfg_command()
+* \brief Configure HI with settings stored in the demod structure.
+* \param demod Demodulator.
+* \return int.
+*
+* This routine was created because to much orthogonal settings have
+* been put into one HI API function (configure). Especially the I2C bridge
+* enable/disable should not need re-configuration of the HI.
+*
+*/
+static int hi_cfg_command(const struct drx_demod_instance *demod)
+{
+	struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
+	struct drxj_hi_cmd hi_cmd;
+	u16 result = 0;
+	int rc;
+
+	ext_attr = (struct drxj_data *) demod->my_ext_attr;
+
+	hi_cmd.cmd = SIO_HI_RA_RAM_CMD_CONFIG;
+	hi_cmd.param1 = SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY;
+	hi_cmd.param2 = ext_attr->hi_cfg_timing_div;
+	hi_cmd.param3 = ext_attr->hi_cfg_bridge_delay;
+	hi_cmd.param4 = ext_attr->hi_cfg_wake_up_key;
+	hi_cmd.param5 = ext_attr->hi_cfg_ctrl;
+	hi_cmd.param6 = ext_attr->hi_cfg_transmit;
+
+	rc = hi_command(demod->my_i2c_dev_addr, &hi_cmd, &result);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	/* Reset power down flag (set one call only) */
+	ext_attr->hi_cfg_ctrl &= (~(SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ));
+
+	return 0;
+
+rw_error:
+	return -EIO;
+}
+
+/**
+* \fn int hi_command()
+* \brief Configure HI with settings stored in the demod structure.
+* \param dev_addr I2C address.
+* \param cmd HI command.
+* \param result HI command result.
+* \return int.
+*
+* Sends command to HI
+*
+*/
+static int
+hi_command(struct i2c_device_addr *dev_addr, const struct drxj_hi_cmd *cmd, u16 *result)
+{
+	u16 wait_cmd = 0;
+	u16 nr_retries = 0;
+	bool powerdown_cmd = false;
+	int rc;
+
+	/* Write parameters */
+	switch (cmd->cmd) {
+
+	case SIO_HI_RA_RAM_CMD_CONFIG:
+	case SIO_HI_RA_RAM_CMD_ATOMIC_COPY:
+		rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_6__A, cmd->param6, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_5__A, cmd->param5, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_4__A, cmd->param4, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_3__A, cmd->param3, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		/* fallthrough */
+	case SIO_HI_RA_RAM_CMD_BRDCTRL:
+		rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_2__A, cmd->param2, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_1__A, cmd->param1, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		/* fallthrough */
+	case SIO_HI_RA_RAM_CMD_NULL:
+		/* No parameters */
+		break;
+
+	default:
+		return -EINVAL;
+		break;
+	}
+
+	/* Write command */
+	rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_CMD__A, cmd->cmd, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	if ((cmd->cmd) == SIO_HI_RA_RAM_CMD_RESET)
+		msleep(1);
+
+	/* Detect power down to ommit reading result */
+	powerdown_cmd = (bool) ((cmd->cmd == SIO_HI_RA_RAM_CMD_CONFIG) &&
+				  (((cmd->
+				     param5) & SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M)
+				   == SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ));
+	if (!powerdown_cmd) {
+		/* Wait until command rdy */
+		do {
+			nr_retries++;
+			if (nr_retries > DRXJ_MAX_RETRIES) {
+				pr_err("timeout\n");
+				goto rw_error;
+			}
+
+			rc = drxj_dap_read_reg16(dev_addr, SIO_HI_RA_RAM_CMD__A, &wait_cmd, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+		} while (wait_cmd != 0);
+
+		/* Read result */
+		rc = drxj_dap_read_reg16(dev_addr, SIO_HI_RA_RAM_RES__A, result, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+
+	}
+	/* if ( powerdown_cmd == true ) */
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/**
+* \fn int init_hi( const struct drx_demod_instance *demod )
+* \brief Initialise and configurate HI.
+* \param demod pointer to demod data.
+* \return int Return status.
+* \retval 0 Success.
+* \retval -EIO Failure.
+*
+* Needs to know Psys (System Clock period) and Posc (Osc Clock period)
+* Need to store configuration in driver because of the way I2C
+* bridging is controlled.
+*
+*/
+static int init_hi(const struct drx_demod_instance *demod)
+{
+	struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
+	struct drx_common_attr *common_attr = (struct drx_common_attr *) (NULL);
+	struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
+	int rc;
+
+	ext_attr = (struct drxj_data *) demod->my_ext_attr;
+	common_attr = (struct drx_common_attr *) demod->my_common_attr;
+	dev_addr = demod->my_i2c_dev_addr;
+
+	/* PATCH for bug 5003, HI ucode v3.1.0 */
+	rc = drxj_dap_write_reg16(dev_addr, 0x4301D7, 0x801, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	/* Timing div, 250ns/Psys */
+	/* Timing div, = ( delay (nano seconds) * sysclk (kHz) )/ 1000 */
+	ext_attr->hi_cfg_timing_div =
+	    (u16) ((common_attr->sys_clock_freq / 1000) * HI_I2C_DELAY) / 1000;
+	/* Clipping */
+	if ((ext_attr->hi_cfg_timing_div) > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M)
+		ext_attr->hi_cfg_timing_div = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M;
+	/* Bridge delay, uses oscilator clock */
+	/* Delay = ( delay (nano seconds) * oscclk (kHz) )/ 1000 */
+	/* SDA brdige delay */
+	ext_attr->hi_cfg_bridge_delay =
+	    (u16) ((common_attr->osc_clock_freq / 1000) * HI_I2C_BRIDGE_DELAY) /
+	    1000;
+	/* Clipping */
+	if ((ext_attr->hi_cfg_bridge_delay) > SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M)
+		ext_attr->hi_cfg_bridge_delay = SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M;
+	/* SCL bridge delay, same as SDA for now */
+	ext_attr->hi_cfg_bridge_delay += ((ext_attr->hi_cfg_bridge_delay) <<
+				      SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B);
+	/* Wakeup key, setting the read flag (as suggest in the documentation) does
+	   not always result into a working solution (barebones worked VI2C failed).
+	   Not setting the bit works in all cases . */
+	ext_attr->hi_cfg_wake_up_key = DRXJ_WAKE_UP_KEY;
+	/* port/bridge/power down ctrl */
+	ext_attr->hi_cfg_ctrl = (SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE);
+	/* transit mode time out delay and watch dog divider */
+	ext_attr->hi_cfg_transmit = SIO_HI_RA_RAM_PAR_6__PRE;
+
+	rc = hi_cfg_command(demod);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	return 0;
+
+rw_error:
+	return -EIO;
+}
+
+/*============================================================================*/
+/*==                   END HOST INTERFACE FUNCTIONS                         ==*/
+/*============================================================================*/
+
+/*============================================================================*/
+/*============================================================================*/
+/*==                        AUXILIARY FUNCTIONS                             ==*/
+/*============================================================================*/
+/*============================================================================*/
+
+/**
+* \fn int get_device_capabilities()
+* \brief Get and store device capabilities.
+* \param demod  Pointer to demodulator instance.
+* \return int.
+* \return 0    Success
+* \retval -EIO Failure
+*
+* Depending on pulldowns on MDx pins the following internals are set:
+*  * common_attr->osc_clock_freq
+*  * ext_attr->has_lna
+*  * ext_attr->has_ntsc
+*  * ext_attr->has_btsc
+*  * ext_attr->has_oob
+*
+*/
+static int get_device_capabilities(struct drx_demod_instance *demod)
+{
+	struct drx_common_attr *common_attr = (struct drx_common_attr *) (NULL);
+	struct drxj_data *ext_attr = (struct drxj_data *) NULL;
+	struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
+	u16 sio_pdr_ohw_cfg = 0;
+	u32 sio_top_jtagid_lo = 0;
+	u16 bid = 0;
+	int rc;
+
+	common_attr = (struct drx_common_attr *) demod->my_common_attr;
+	ext_attr = (struct drxj_data *) demod->my_ext_attr;
+	dev_addr = demod->my_i2c_dev_addr;
+
+	rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_read_reg16(dev_addr, SIO_PDR_OHW_CFG__A, &sio_pdr_ohw_cfg, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY__PRE, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	switch ((sio_pdr_ohw_cfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) {
+	case 0:
+		/* ignore (bypass ?) */
+		break;
+	case 1:
+		/* 27 MHz */
+		common_attr->osc_clock_freq = 27000;
+		break;
+	case 2:
+		/* 20.25 MHz */
+		common_attr->osc_clock_freq = 20250;
+		break;
+	case 3:
+		/* 4 MHz */
+		common_attr->osc_clock_freq = 4000;
+		break;
+	default:
+		return -EIO;
+	}
+
+	/*
+	   Determine device capabilities
+	   Based on pinning v47
+	 */
+	rc = drxdap_fasi_read_reg32(dev_addr, SIO_TOP_JTAGID_LO__A, &sio_top_jtagid_lo, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	ext_attr->mfx = (u8) ((sio_top_jtagid_lo >> 29) & 0xF);
+
+	switch ((sio_top_jtagid_lo >> 12) & 0xFF) {
+	case 0x31:
+		rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_read_reg16(dev_addr, SIO_PDR_UIO_IN_HI__A, &bid, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		bid = (bid >> 10) & 0xf;
+		rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY__PRE, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+
+		ext_attr->has_lna = true;
+		ext_attr->has_ntsc = false;
+		ext_attr->has_btsc = false;
+		ext_attr->has_oob = false;
+		ext_attr->has_smatx = true;
+		ext_attr->has_smarx = false;
+		ext_attr->has_gpio = false;
+		ext_attr->has_irqn = false;
+		break;
+	case 0x33:
+		ext_attr->has_lna = false;
+		ext_attr->has_ntsc = false;
+		ext_attr->has_btsc = false;
+		ext_attr->has_oob = false;
+		ext_attr->has_smatx = true;
+		ext_attr->has_smarx = false;
+		ext_attr->has_gpio = false;
+		ext_attr->has_irqn = false;
+		break;
+	case 0x45:
+		ext_attr->has_lna = true;
+		ext_attr->has_ntsc = true;
+		ext_attr->has_btsc = false;
+		ext_attr->has_oob = false;
+		ext_attr->has_smatx = true;
+		ext_attr->has_smarx = true;
+		ext_attr->has_gpio = true;
+		ext_attr->has_irqn = false;
+		break;
+	case 0x46:
+		ext_attr->has_lna = false;
+		ext_attr->has_ntsc = true;
+		ext_attr->has_btsc = false;
+		ext_attr->has_oob = false;
+		ext_attr->has_smatx = true;
+		ext_attr->has_smarx = true;
+		ext_attr->has_gpio = true;
+		ext_attr->has_irqn = false;
+		break;
+	case 0x41:
+		ext_attr->has_lna = true;
+		ext_attr->has_ntsc = true;
+		ext_attr->has_btsc = true;
+		ext_attr->has_oob = false;
+		ext_attr->has_smatx = true;
+		ext_attr->has_smarx = true;
+		ext_attr->has_gpio = true;
+		ext_attr->has_irqn = false;
+		break;
+	case 0x43:
+		ext_attr->has_lna = false;
+		ext_attr->has_ntsc = true;
+		ext_attr->has_btsc = true;
+		ext_attr->has_oob = false;
+		ext_attr->has_smatx = true;
+		ext_attr->has_smarx = true;
+		ext_attr->has_gpio = true;
+		ext_attr->has_irqn = false;
+		break;
+	case 0x32:
+		ext_attr->has_lna = true;
+		ext_attr->has_ntsc = false;
+		ext_attr->has_btsc = false;
+		ext_attr->has_oob = true;
+		ext_attr->has_smatx = true;
+		ext_attr->has_smarx = true;
+		ext_attr->has_gpio = true;
+		ext_attr->has_irqn = true;
+		break;
+	case 0x34:
+		ext_attr->has_lna = false;
+		ext_attr->has_ntsc = true;
+		ext_attr->has_btsc = true;
+		ext_attr->has_oob = true;
+		ext_attr->has_smatx = true;
+		ext_attr->has_smarx = true;
+		ext_attr->has_gpio = true;
+		ext_attr->has_irqn = true;
+		break;
+	case 0x42:
+		ext_attr->has_lna = true;
+		ext_attr->has_ntsc = true;
+		ext_attr->has_btsc = true;
+		ext_attr->has_oob = true;
+		ext_attr->has_smatx = true;
+		ext_attr->has_smarx = true;
+		ext_attr->has_gpio = true;
+		ext_attr->has_irqn = true;
+		break;
+	case 0x44:
+		ext_attr->has_lna = false;
+		ext_attr->has_ntsc = true;
+		ext_attr->has_btsc = true;
+		ext_attr->has_oob = true;
+		ext_attr->has_smatx = true;
+		ext_attr->has_smarx = true;
+		ext_attr->has_gpio = true;
+		ext_attr->has_irqn = true;
+		break;
+	default:
+		/* Unknown device variant */
+		return -EIO;
+		break;
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/**
+* \fn int power_up_device()
+* \brief Power up device.
+* \param demod  Pointer to demodulator instance.
+* \return int.
+* \return 0    Success
+* \retval -EIO Failure, I2C or max retries reached
+*
+*/
+
+#ifndef DRXJ_MAX_RETRIES_POWERUP
+#define DRXJ_MAX_RETRIES_POWERUP 10
+#endif
+
+static int power_up_device(struct drx_demod_instance *demod)
+{
+	struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
+	u8 data = 0;
+	u16 retry_count = 0;
+	struct i2c_device_addr wake_up_addr;
+
+	dev_addr = demod->my_i2c_dev_addr;
+	wake_up_addr.i2c_addr = DRXJ_WAKE_UP_KEY;
+	wake_up_addr.i2c_dev_id = dev_addr->i2c_dev_id;
+	wake_up_addr.user_data = dev_addr->user_data;
+	/*
+	 * I2C access may fail in this case: no ack
+	 * dummy write must be used to wake uop device, dummy read must be used to
+	 * reset HI state machine (avoiding actual writes)
+	 */
+	do {
+		data = 0;
+		drxbsp_i2c_write_read(&wake_up_addr, 1, &data,
+				      (struct i2c_device_addr *)(NULL), 0,
+				     (u8 *)(NULL));
+		msleep(10);
+		retry_count++;
+	} while ((drxbsp_i2c_write_read
+		  ((struct i2c_device_addr *) (NULL), 0, (u8 *)(NULL), dev_addr, 1,
+		   &data)
+		  != 0) && (retry_count < DRXJ_MAX_RETRIES_POWERUP));
+
+	/* Need some recovery time .... */
+	msleep(10);
+
+	if (retry_count == DRXJ_MAX_RETRIES_POWERUP)
+		return -EIO;
+
+	return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+/* MPEG Output Configuration Functions - begin                                */
+/*----------------------------------------------------------------------------*/
+/**
+* \fn int ctrl_set_cfg_mpeg_output()
+* \brief Set MPEG output configuration of the device.
+* \param devmod  Pointer to demodulator instance.
+* \param cfg_data Pointer to mpeg output configuaration.
+* \return int.
+*
+*  Configure MPEG output parameters.
+*
+*/
+static int
+ctrl_set_cfg_mpeg_output(struct drx_demod_instance *demod, struct drx_cfg_mpeg_output *cfg_data)
+{
+	struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
+	struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
+	struct drx_common_attr *common_attr = (struct drx_common_attr *) (NULL);
+	int rc;
+	u16 fec_oc_reg_mode = 0;
+	u16 fec_oc_reg_ipr_mode = 0;
+	u16 fec_oc_reg_ipr_invert = 0;
+	u32 max_bit_rate = 0;
+	u32 rcn_rate = 0;
+	u32 nr_bits = 0;
+	u16 sio_pdr_md_cfg = 0;
+	/* data mask for the output data byte */
+	u16 invert_data_mask =
+	    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;
+
+	/* check arguments */
+	if ((demod == NULL) || (cfg_data == NULL))
+		return -EINVAL;
+
+	dev_addr = demod->my_i2c_dev_addr;
+	ext_attr = (struct drxj_data *) demod->my_ext_attr;
+	common_attr = (struct drx_common_attr *) demod->my_common_attr;
+
+	if (cfg_data->enable_mpeg_output == true) {
+		/* quick and dirty patch to set MPEG incase current std is not
+		   producing MPEG */
+		switch (ext_attr->standard) {
+		case DRX_STANDARD_8VSB:
+		case DRX_STANDARD_ITU_A:
+		case DRX_STANDARD_ITU_B:
+		case DRX_STANDARD_ITU_C:
+			break;
+		default:
+			return 0;
+		}
+
+		rc = drxj_dap_write_reg16(dev_addr, FEC_OC_OCR_INVERT__A, 0, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		switch (ext_attr->standard) {
+		case DRX_STANDARD_8VSB:
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_FCT_USAGE__A, 7, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}	/* 2048 bytes fifo ram */
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_TMD_CTL_UPD_RATE__A, 10, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_TMD_INT_UPD_RATE__A, 10, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_AVR_PARM_A__A, 5, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_AVR_PARM_B__A, 7, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_RCN_GAIN__A, 10, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			/* Low Water Mark for synchronization  */
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_LWM__A, 3, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			/* High Water Mark for synchronization */
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_HWM__A, 5, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			break;
+		case DRX_STANDARD_ITU_A:
+		case DRX_STANDARD_ITU_C:
+			switch (ext_attr->constellation) {
+			case DRX_CONSTELLATION_QAM256:
+				nr_bits = 8;
+				break;
+			case DRX_CONSTELLATION_QAM128:
+				nr_bits = 7;
+				break;
+			case DRX_CONSTELLATION_QAM64:
+				nr_bits = 6;
+				break;
+			case DRX_CONSTELLATION_QAM32:
+				nr_bits = 5;
+				break;
+			case DRX_CONSTELLATION_QAM16:
+				nr_bits = 4;
+				break;
+			default:
+				return -EIO;
+			}	/* ext_attr->constellation */
+			/* max_bit_rate = symbol_rate * nr_bits * coef */
+			/* coef = 188/204                          */
+			max_bit_rate =
+			    (ext_attr->curr_symbol_rate / 8) * nr_bits * 188;
+			/* pass through b/c Annex A/c need following settings */
+		case DRX_STANDARD_ITU_B:
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_FCT_USAGE__A, FEC_OC_FCT_USAGE__PRE, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_TMD_CTL_UPD_RATE__A, FEC_OC_TMD_CTL_UPD_RATE__PRE, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_TMD_INT_UPD_RATE__A, 5, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_AVR_PARM_A__A, FEC_OC_AVR_PARM_A__PRE, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_AVR_PARM_B__A, FEC_OC_AVR_PARM_B__PRE, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			if (cfg_data->static_clk == true) {
+				rc = drxj_dap_write_reg16(dev_addr, FEC_OC_RCN_GAIN__A, 0xD, 0);
+				if (rc != 0) {
+					pr_err("error %d\n", rc);
+					goto rw_error;
+				}
+			} else {
+				rc = drxj_dap_write_reg16(dev_addr, FEC_OC_RCN_GAIN__A, FEC_OC_RCN_GAIN__PRE, 0);
+				if (rc != 0) {
+					pr_err("error %d\n", rc);
+					goto rw_error;
+				}
+			}
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_LWM__A, 2, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_HWM__A, 12, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			break;
+		default:
+			break;
+		}		/* swtich (standard) */
+
+		/* Check insertion of the Reed-Solomon parity bytes */
+		rc = drxj_dap_read_reg16(dev_addr, FEC_OC_MODE__A, &fec_oc_reg_mode, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_read_reg16(dev_addr, FEC_OC_IPR_MODE__A, &fec_oc_reg_ipr_mode, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		if (cfg_data->insert_rs_byte == true) {
+			/* enable parity symbol forward */
+			fec_oc_reg_mode |= FEC_OC_MODE_PARITY__M;
+			/* MVAL disable during parity bytes */
+			fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M;
+			switch (ext_attr->standard) {
+			case DRX_STANDARD_8VSB:
+				rcn_rate = 0x004854D3;
+				break;
+			case DRX_STANDARD_ITU_B:
+				fec_oc_reg_mode |= FEC_OC_MODE_TRANSPARENT__M;
+				switch (ext_attr->constellation) {
+				case DRX_CONSTELLATION_QAM256:
+					rcn_rate = 0x008945E7;
+					break;
+				case DRX_CONSTELLATION_QAM64:
+					rcn_rate = 0x005F64D4;
+					break;
+				default:
+					return -EIO;
+				}
+				break;
+			case DRX_STANDARD_ITU_A:
+			case DRX_STANDARD_ITU_C:
+				/* insert_rs_byte = true -> coef = 188/188 -> 1, RS bits are in MPEG output */
+				rcn_rate =
+				    (frac28
+				     (max_bit_rate,
+				      (u32) (common_attr->sys_clock_freq / 8))) /
+				    188;
+				break;
+			default:
+				return -EIO;
+			}	/* ext_attr->standard */
+		} else {	/* insert_rs_byte == false */
+
+			/* disable parity symbol forward */
+			fec_oc_reg_mode &= (~FEC_OC_MODE_PARITY__M);
+			/* MVAL enable during parity bytes */
+			fec_oc_reg_ipr_mode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M);
+			switch (ext_attr->standard) {
+			case DRX_STANDARD_8VSB:
+				rcn_rate = 0x0041605C;
+				break;
+			case DRX_STANDARD_ITU_B:
+				fec_oc_reg_mode &= (~FEC_OC_MODE_TRANSPARENT__M);
+				switch (ext_attr->constellation) {
+				case DRX_CONSTELLATION_QAM256:
+					rcn_rate = 0x0082D6A0;
+					break;
+				case DRX_CONSTELLATION_QAM64:
+					rcn_rate = 0x005AEC1A;
+					break;
+				default:
+					return -EIO;
+				}
+				break;
+			case DRX_STANDARD_ITU_A:
+			case DRX_STANDARD_ITU_C:
+				/* insert_rs_byte = false -> coef = 188/204, RS bits not in MPEG output */
+				rcn_rate =
+				    (frac28
+				     (max_bit_rate,
+				      (u32) (common_attr->sys_clock_freq / 8))) /
+				    204;
+				break;
+			default:
+				return -EIO;
+			}	/* ext_attr->standard */
+		}
+
+		if (cfg_data->enable_parallel == true) {	/* MPEG data output is paralel -> clear ipr_mode[0] */
+			fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M));
+		} else {	/* MPEG data output is serial -> set ipr_mode[0] */
+			fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M;
+		}
+
+		/* Control slective inversion of output bits */
+		if (cfg_data->invert_data == true)
+			fec_oc_reg_ipr_invert |= invert_data_mask;
+		else
+			fec_oc_reg_ipr_invert &= (~(invert_data_mask));
+
+		if (cfg_data->invert_err == true)
+			fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MERR__M;
+		else
+			fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MERR__M));
+
+		if (cfg_data->invert_str == true)
+			fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MSTRT__M;
+		else
+			fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MSTRT__M));
+
+		if (cfg_data->invert_val == true)
+			fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MVAL__M;
+		else
+			fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MVAL__M));
+
+		if (cfg_data->invert_clk == true)
+			fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MCLK__M;
+		else
+			fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MCLK__M));
+
+
+		if (cfg_data->static_clk == true) {	/* Static mode */
+			u32 dto_rate = 0;
+			u32 bit_rate = 0;
+			u16 fec_oc_dto_burst_len = 0;
+			u16 fec_oc_dto_period = 0;
+
+			fec_oc_dto_burst_len = FEC_OC_DTO_BURST_LEN__PRE;
+
+			switch (ext_attr->standard) {
+			case DRX_STANDARD_8VSB:
+				fec_oc_dto_period = 4;
+				if (cfg_data->insert_rs_byte == true)
+					fec_oc_dto_burst_len = 208;
+				break;
+			case DRX_STANDARD_ITU_A:
+				{
+					u32 symbol_rate_th = 6400000;
+					if (cfg_data->insert_rs_byte == true) {
+						fec_oc_dto_burst_len = 204;
+						symbol_rate_th = 5900000;
+					}
+					if (ext_attr->curr_symbol_rate >=
+					    symbol_rate_th) {
+						fec_oc_dto_period = 0;
+					} else {
+						fec_oc_dto_period = 1;
+					}
+				}
+				break;
+			case DRX_STANDARD_ITU_B:
+				fec_oc_dto_period = 1;
+				if (cfg_data->insert_rs_byte == true)
+					fec_oc_dto_burst_len = 128;
+				break;
+			case DRX_STANDARD_ITU_C:
+				fec_oc_dto_period = 1;
+				if (cfg_data->insert_rs_byte == true)
+					fec_oc_dto_burst_len = 204;
+				break;
+			default:
+				return -EIO;
+			}
+			bit_rate =
+			    common_attr->sys_clock_freq * 1000 / (fec_oc_dto_period +
+							       2);
+			dto_rate =
+			    frac28(bit_rate, common_attr->sys_clock_freq * 1000);
+			dto_rate >>= 3;
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DTO_RATE_HI__A, (u16)((dto_rate >> 16) & FEC_OC_DTO_RATE_HI__M), 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DTO_RATE_LO__A, (u16)(dto_rate & FEC_OC_DTO_RATE_LO_RATE_LO__M), 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DTO_MODE__A, FEC_OC_DTO_MODE_DYNAMIC__M | FEC_OC_DTO_MODE_OFFSET_ENABLE__M, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_FCT_MODE__A, FEC_OC_FCT_MODE_RAT_ENA__M | FEC_OC_FCT_MODE_VIRT_ENA__M, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DTO_BURST_LEN__A, fec_oc_dto_burst_len, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			if (ext_attr->mpeg_output_clock_rate != DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO)
+				fec_oc_dto_period = ext_attr->mpeg_output_clock_rate - 1;
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DTO_PERIOD__A, fec_oc_dto_period, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+		} else {	/* Dynamic mode */
+
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DTO_MODE__A, FEC_OC_DTO_MODE_DYNAMIC__M, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, FEC_OC_FCT_MODE__A, 0, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+		}
+
+		rc = drxdap_fasi_write_reg32(dev_addr, FEC_OC_RCN_CTL_RATE_LO__A, rcn_rate, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+
+		/* Write appropriate registers with requested configuration */
+		rc = drxj_dap_write_reg16(dev_addr, FEC_OC_MODE__A, fec_oc_reg_mode, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, FEC_OC_IPR_MODE__A, fec_oc_reg_ipr_mode, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, FEC_OC_IPR_INVERT__A, fec_oc_reg_ipr_invert, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+
+		/* enabling for both parallel and serial now */
+		/*  Write magic word to enable pdr reg write */
+		rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		/*  Set MPEG TS pads to outputmode */
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MSTRT_CFG__A, 0x0013, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MERR_CFG__A, 0x0013, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MCLK_CFG__A, MPEG_OUTPUT_CLK_DRIVE_STRENGTH << SIO_PDR_MCLK_CFG_DRIVE__B | 0x03 << SIO_PDR_MCLK_CFG_MODE__B, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MVAL_CFG__A, 0x0013, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		sio_pdr_md_cfg =
+		    MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH <<
+		    SIO_PDR_MD0_CFG_DRIVE__B | 0x03 << SIO_PDR_MD0_CFG_MODE__B;
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD0_CFG__A, sio_pdr_md_cfg, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		if (cfg_data->enable_parallel == true) {	/* MPEG data output is paralel -> set MD1 to MD7 to output mode */
+			sio_pdr_md_cfg =
+			    MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH <<
+			    SIO_PDR_MD0_CFG_DRIVE__B | 0x03 <<
+			    SIO_PDR_MD0_CFG_MODE__B;
+			rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD0_CFG__A, sio_pdr_md_cfg, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD1_CFG__A, sio_pdr_md_cfg, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD2_CFG__A, sio_pdr_md_cfg, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD3_CFG__A, sio_pdr_md_cfg, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD4_CFG__A, sio_pdr_md_cfg, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD5_CFG__A, sio_pdr_md_cfg, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD6_CFG__A, sio_pdr_md_cfg, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD7_CFG__A, sio_pdr_md_cfg, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+		} else {	/* MPEG data output is serial -> set MD1 to MD7 to tri-state */
+			rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD1_CFG__A, 0x0000, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD2_CFG__A, 0x0000, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD3_CFG__A, 0x0000, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD4_CFG__A, 0x0000, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD5_CFG__A, 0x0000, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD6_CFG__A, 0x0000, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD7_CFG__A, 0x0000, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+		}
+		/*  Enable Monitor Bus output over MPEG pads and ctl input */
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MON_CFG__A, 0x0000, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		/*  Write nomagic word to enable pdr reg write */
+		rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+	} else {
+		/*  Write magic word to enable pdr reg write */
+		rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		/*  Set MPEG TS pads to inputmode */
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MSTRT_CFG__A, 0x0000, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MERR_CFG__A, 0x0000, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MCLK_CFG__A, 0x0000, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MVAL_CFG__A, 0x0000, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD0_CFG__A, 0x0000, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD1_CFG__A, 0x0000, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD2_CFG__A, 0x0000, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD3_CFG__A, 0x0000, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD4_CFG__A, 0x0000, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD5_CFG__A, 0x0000, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD6_CFG__A, 0x0000, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD7_CFG__A, 0x0000, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		/* Enable Monitor Bus output over MPEG pads and ctl input */
+		rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MON_CFG__A, 0x0000, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		/* Write nomagic word to enable pdr reg write */
+		rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+	}
+
+	/* save values for restore after re-acquire */
+	common_attr->mpeg_cfg.enable_mpeg_output = cfg_data->enable_mpeg_output;
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/*----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------*/
+/* MPEG Output Configuration Functions - end                                  */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* miscellaneous configuartions - begin                           */
+/*----------------------------------------------------------------------------*/
+
+/**
+* \fn int set_mpegtei_handling()
+* \brief Activate MPEG TEI handling settings.
+* \param devmod  Pointer to demodulator instance.
+* \return int.
+*
+* This routine should be called during a set channel of QAM/VSB
+*
+*/
+static int set_mpegtei_handling(struct drx_demod_instance *demod)
+{
+	struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
+	struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
+	int rc;
+	u16 fec_oc_dpr_mode = 0;
+	u16 fec_oc_snc_mode = 0;
+	u16 fec_oc_ems_mode = 0;
+
+	dev_addr = demod->my_i2c_dev_addr;
+	ext_attr = (struct drxj_data *) demod->my_ext_attr;
+
+	rc = drxj_dap_read_reg16(dev_addr, FEC_OC_DPR_MODE__A, &fec_oc_dpr_mode, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_read_reg16(dev_addr, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_read_reg16(dev_addr, FEC_OC_EMS_MODE__A, &fec_oc_ems_mode, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	/* reset to default, allow TEI bit to be changed */
+	fec_oc_dpr_mode &= (~FEC_OC_DPR_MODE_ERR_DISABLE__M);
+	fec_oc_snc_mode &= (~(FEC_OC_SNC_MODE_ERROR_CTL__M |
+			   FEC_OC_SNC_MODE_CORR_DISABLE__M));
+	fec_oc_ems_mode &= (~FEC_OC_EMS_MODE_MODE__M);
+
+	if (ext_attr->disable_te_ihandling) {
+		/* do not change TEI bit */
+		fec_oc_dpr_mode |= FEC_OC_DPR_MODE_ERR_DISABLE__M;
+		fec_oc_snc_mode |= FEC_OC_SNC_MODE_CORR_DISABLE__M |
+		    ((0x2) << (FEC_OC_SNC_MODE_ERROR_CTL__B));
+		fec_oc_ems_mode |= ((0x01) << (FEC_OC_EMS_MODE_MODE__B));
+	}
+
+	rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DPR_MODE__A, fec_oc_dpr_mode, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_MODE__A, fec_oc_snc_mode, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, FEC_OC_EMS_MODE__A, fec_oc_ems_mode, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+* \fn int bit_reverse_mpeg_output()
+* \brief Set MPEG output bit-endian settings.
+* \param devmod  Pointer to demodulator instance.
+* \return int.
+*
+* This routine should be called during a set channel of QAM/VSB
+*
+*/
+static int bit_reverse_mpeg_output(struct drx_demod_instance *demod)
+{
+	struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
+	struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
+	int rc;
+	u16 fec_oc_ipr_mode = 0;
+
+	dev_addr = demod->my_i2c_dev_addr;
+	ext_attr = (struct drxj_data *) demod->my_ext_attr;
+
+	rc = drxj_dap_read_reg16(dev_addr, FEC_OC_IPR_MODE__A, &fec_oc_ipr_mode, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	/* reset to default (normal bit order) */
+	fec_oc_ipr_mode &= (~FEC_OC_IPR_MODE_REVERSE_ORDER__M);
+
+	if (ext_attr->bit_reverse_mpeg_outout)
+		fec_oc_ipr_mode |= FEC_OC_IPR_MODE_REVERSE_ORDER__M;
+
+	rc = drxj_dap_write_reg16(dev_addr, FEC_OC_IPR_MODE__A, fec_oc_ipr_mode, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+* \fn int set_mpeg_start_width()
+* \brief Set MPEG start width.
+* \param devmod  Pointer to demodulator instance.
+* \return int.
+*
+* This routine should be called during a set channel of QAM/VSB
+*
+*/
+static int set_mpeg_start_width(struct drx_demod_instance *demod)
+{
+	struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
+	struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
+	struct drx_common_attr *common_attr = (struct drx_common_attr *) NULL;
+	int rc;
+	u16 fec_oc_comm_mb = 0;
+
+	dev_addr = demod->my_i2c_dev_addr;
+	ext_attr = (struct drxj_data *) demod->my_ext_attr;
+	common_attr = demod->my_common_attr;
+
+	if ((common_attr->mpeg_cfg.static_clk == true)
+	    && (common_attr->mpeg_cfg.enable_parallel == false)) {
+		rc = drxj_dap_read_reg16(dev_addr, FEC_OC_COMM_MB__A, &fec_oc_comm_mb, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		fec_oc_comm_mb &= ~FEC_OC_COMM_MB_CTL_ON;
+		if (ext_attr->mpeg_start_width == DRXJ_MPEG_START_WIDTH_8CLKCYC)
+			fec_oc_comm_mb |= FEC_OC_COMM_MB_CTL_ON;
+		rc = drxj_dap_write_reg16(dev_addr, FEC_OC_COMM_MB__A, fec_oc_comm_mb, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/*----------------------------------------------------------------------------*/
+/* miscellaneous configuartions - end                             */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* UIO Configuration Functions - begin                                        */
+/*----------------------------------------------------------------------------*/
+/**
+* \fn int ctrl_set_uio_cfg()
+* \brief Configure modus oprandi UIO.
+* \param demod Pointer to demodulator instance.
+* \param uio_cfg Pointer to a configuration setting for a certain UIO.
+* \return int.
+*/
+static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg *uio_cfg)
+{
+	struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
+	int rc;
+
+	if ((uio_cfg == NULL) || (demod == NULL))
+		return -EINVAL;
+
+	ext_attr = (struct drxj_data *) demod->my_ext_attr;
+
+	/*  Write magic word to enable pdr reg write               */
+	rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	switch (uio_cfg->uio) {
+      /*====================================================================*/
+	case DRX_UIO1:
+		/* DRX_UIO1: SMA_TX UIO-1 */
+		if (!ext_attr->has_smatx)
+			return -EIO;
+		switch (uio_cfg->mode) {
+		case DRX_UIO_MODE_FIRMWARE_SMA:	/* falltrough */
+		case DRX_UIO_MODE_FIRMWARE_SAW:	/* falltrough */
+		case DRX_UIO_MODE_READWRITE:
+			ext_attr->uio_sma_tx_mode = uio_cfg->mode;
+			break;
+		case DRX_UIO_MODE_DISABLE:
+			ext_attr->uio_sma_tx_mode = uio_cfg->mode;
+			/* pad configuration register is set 0 - input mode */
+			rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, 0, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			break;
+		default:
+			return -EINVAL;
+		}		/* switch ( uio_cfg->mode ) */
+		break;
+      /*====================================================================*/
+	case DRX_UIO2:
+		/* DRX_UIO2: SMA_RX UIO-2 */
+		if (!ext_attr->has_smarx)
+			return -EIO;
+		switch (uio_cfg->mode) {
+		case DRX_UIO_MODE_FIRMWARE0:	/* falltrough */
+		case DRX_UIO_MODE_READWRITE:
+			ext_attr->uio_sma_rx_mode = uio_cfg->mode;
+			break;
+		case DRX_UIO_MODE_DISABLE:
+			ext_attr->uio_sma_rx_mode = uio_cfg->mode;
+			/* pad configuration register is set 0 - input mode */
+			rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_RX_CFG__A, 0, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			break;
+		default:
+			return -EINVAL;
+			break;
+		}		/* switch ( uio_cfg->mode ) */
+		break;
+      /*====================================================================*/
+	case DRX_UIO3:
+		/* DRX_UIO3: GPIO UIO-3 */
+		if (!ext_attr->has_gpio)
+			return -EIO;
+		switch (uio_cfg->mode) {
+		case DRX_UIO_MODE_FIRMWARE0:	/* falltrough */
+		case DRX_UIO_MODE_READWRITE:
+			ext_attr->uio_gpio_mode = uio_cfg->mode;
+			break;
+		case DRX_UIO_MODE_DISABLE:
+			ext_attr->uio_gpio_mode = uio_cfg->mode;
+			/* pad configuration register is set 0 - input mode */
+			rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_GPIO_CFG__A, 0, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			break;
+		default:
+			return -EINVAL;
+			break;
+		}		/* switch ( uio_cfg->mode ) */
+		break;
+      /*====================================================================*/
+	case DRX_UIO4:
+		/* DRX_UIO4: IRQN UIO-4 */
+		if (!ext_attr->has_irqn)
+			return -EIO;
+		switch (uio_cfg->mode) {
+		case DRX_UIO_MODE_READWRITE:
+			ext_attr->uio_irqn_mode = uio_cfg->mode;
+			break;
+		case DRX_UIO_MODE_DISABLE:
+			/* pad configuration register is set 0 - input mode */
+			rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_IRQN_CFG__A, 0, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			ext_attr->uio_irqn_mode = uio_cfg->mode;
+			break;
+		case DRX_UIO_MODE_FIRMWARE0:	/* falltrough */
+		default:
+			return -EINVAL;
+			break;
+		}		/* switch ( uio_cfg->mode ) */
+		break;
+      /*====================================================================*/
+	default:
+		return -EINVAL;
+	}			/* switch ( uio_cfg->uio ) */
+
+	/*  Write magic word to disable pdr reg write               */
+	rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/**
+* \fn int ctrl_uio_write()
+* \brief Write to a UIO.
+* \param demod Pointer to demodulator instance.
+* \param uio_data Pointer to data container for a certain UIO.
+* \return int.
+*/
+static int
+ctrl_uio_write(struct drx_demod_instance *demod, struct drxuio_data *uio_data)
+{
+	struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
+	int rc;
+	u16 pin_cfg_value = 0;
+	u16 value = 0;
+
+	if ((uio_data == NULL) || (demod == NULL))
+		return -EINVAL;
+
+	ext_attr = (struct drxj_data *) demod->my_ext_attr;
+
+	/*  Write magic word to enable pdr reg write               */
+	rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	switch (uio_data->uio) {
+      /*====================================================================*/
+	case DRX_UIO1:
+		/* DRX_UIO1: SMA_TX UIO-1 */
+		if (!ext_attr->has_smatx)
+			return -EIO;
+		if ((ext_attr->uio_sma_tx_mode != DRX_UIO_MODE_READWRITE)
+		    && (ext_attr->uio_sma_tx_mode != DRX_UIO_MODE_FIRMWARE_SAW)) {
+			return -EIO;
+		}
+		pin_cfg_value = 0;
+		/* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
+		pin_cfg_value |= 0x0113;
+		/* io_pad_cfg_mode output mode is drive always */
+		/* io_pad_cfg_drive is set to power 2 (23 mA) */
+
+		/* write to io pad configuration register - output mode */
+		rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, pin_cfg_value, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+
+		/* use corresponding bit in io data output registar */
+		rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, &value, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		if (!uio_data->value)
+			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 */
+		rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		break;
+   /*======================================================================*/
+	case DRX_UIO2:
+		/* DRX_UIO2: SMA_RX UIO-2 */
+		if (!ext_attr->has_smarx)
+			return -EIO;
+		if (ext_attr->uio_sma_rx_mode != DRX_UIO_MODE_READWRITE)
+			return -EIO;
+
+		pin_cfg_value = 0;
+		/* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
+		pin_cfg_value |= 0x0113;
+		/* io_pad_cfg_mode output mode is drive always */
+		/* io_pad_cfg_drive is set to power 2 (23 mA) */
+
+		/* write to io pad configuration register - output mode */
+		rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_RX_CFG__A, pin_cfg_value, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+
+		/* use corresponding bit in io data output registar */
+		rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, &value, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		if (!uio_data->value)
+			value &= 0xBFFF;	/* write zero to 14th bit - 2nd UIO */
+		else
+			value |= 0x4000;	/* write one to 14th bit - 2nd UIO */
+
+		/* write back to io data output register */
+		rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		break;
+   /*====================================================================*/
+	case DRX_UIO3:
+		/* DRX_UIO3: ASEL UIO-3 */
+		if (!ext_attr->has_gpio)
+			return -EIO;
+		if (ext_attr->uio_gpio_mode != DRX_UIO_MODE_READWRITE)
+			return -EIO;
+
+		pin_cfg_value = 0;
+		/* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
+		pin_cfg_value |= 0x0113;
+		/* io_pad_cfg_mode output mode is drive always */
+		/* io_pad_cfg_drive is set to power 2 (23 mA) */
+
+		/* write to io pad configuration register - output mode */
+		rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_GPIO_CFG__A, pin_cfg_value, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+
+		/* use corresponding bit in io data output registar */
+		rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_HI__A, &value, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		if (!uio_data->value)
+			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 */
+		rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_HI__A, value, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		break;
+   /*=====================================================================*/
+	case DRX_UIO4:
+		/* DRX_UIO4: IRQN UIO-4 */
+		if (!ext_attr->has_irqn)
+			return -EIO;
+
+		if (ext_attr->uio_irqn_mode != DRX_UIO_MODE_READWRITE)
+			return -EIO;
+
+		pin_cfg_value = 0;
+		/* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
+		pin_cfg_value |= 0x0113;
+		/* io_pad_cfg_mode output mode is drive always */
+		/* io_pad_cfg_drive is set to power 2 (23 mA) */
+
+		/* write to io pad configuration register - output mode */
+		rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_IRQN_CFG__A, pin_cfg_value, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+
+		/* use corresponding bit in io data output registar */
+		rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, &value, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		if (uio_data->value == false)
+			value &= 0xEFFF;	/* write zero to 12th bit - 4th UIO */
+		else
+			value |= 0x1000;	/* write one to 12th bit - 4th UIO */
+
+		/* write back to io data output register */
+		rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		break;
+      /*=====================================================================*/
+	default:
+		return -EINVAL;
+	}			/* switch ( uio_data->uio ) */
+
+	/*  Write magic word to disable pdr reg write               */
+	rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/*---------------------------------------------------------------------------*/
+/* UIO Configuration Functions - end                                         */
+/*---------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* I2C Bridge Functions - begin                                               */
+/*----------------------------------------------------------------------------*/
+/**
+* \fn int ctrl_i2c_bridge()
+* \brief Open or close the I2C switch to tuner.
+* \param demod Pointer to demodulator instance.
+* \param bridge_closed Pointer to bool indication if bridge is closed not.
+* \return int.
+
+*/
+static int
+ctrl_i2c_bridge(struct drx_demod_instance *demod, bool *bridge_closed)
+{
+	struct drxj_hi_cmd hi_cmd;
+	u16 result = 0;
+
+	/* check arguments */
+	if (bridge_closed == NULL)
+		return -EINVAL;
+
+	hi_cmd.cmd = SIO_HI_RA_RAM_CMD_BRDCTRL;
+	hi_cmd.param1 = SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY;
+	if (*bridge_closed)
+		hi_cmd.param2 = SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED;
+	else
+		hi_cmd.param2 = SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN;
+
+	return hi_command(demod->my_i2c_dev_addr, &hi_cmd, &result);
+}
+
+/*----------------------------------------------------------------------------*/
+/* I2C Bridge Functions - end                                                 */
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* Smart antenna Functions - begin                                            */
+/*----------------------------------------------------------------------------*/
+/**
+* \fn int smart_ant_init()
+* \brief Initialize Smart Antenna.
+* \param pointer to struct drx_demod_instance.
+* \return int.
+*
+*/
+static int smart_ant_init(struct drx_demod_instance *demod)
+{
+	struct drxj_data *ext_attr = NULL;
+	struct i2c_device_addr *dev_addr = NULL;
+	struct drxuio_cfg uio_cfg = { DRX_UIO1, DRX_UIO_MODE_FIRMWARE_SMA };
+	int rc;
+	u16 data = 0;
+
+	dev_addr = demod->my_i2c_dev_addr;
+	ext_attr = (struct drxj_data *) demod->my_ext_attr;
+
+	/*  Write magic word to enable pdr reg write               */
+	rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	/* init smart antenna */
+	rc = drxj_dap_read_reg16(dev_addr, SIO_SA_TX_COMMAND__A, &data, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	if (ext_attr->smart_ant_inverted) {
+		rc = drxj_dap_write_reg16(dev_addr, SIO_SA_TX_COMMAND__A, (data | SIO_SA_TX_COMMAND_TX_INVERT__M) | SIO_SA_TX_COMMAND_TX_ENABLE__M, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+	} else {
+		rc = drxj_dap_write_reg16(dev_addr, SIO_SA_TX_COMMAND__A, (data & (~SIO_SA_TX_COMMAND_TX_INVERT__M)) | SIO_SA_TX_COMMAND_TX_ENABLE__M, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+	}
+
+	/* config SMA_TX pin to smart antenna mode */
+	rc = ctrl_set_uio_cfg(demod, &uio_cfg);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, 0x13, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_GPIO_FNC__A, 0x03, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	/*  Write magic word to disable pdr reg write               */
+	rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+static int scu_command(struct i2c_device_addr *dev_addr, struct drxjscu_cmd *cmd)
+{
+	int rc;
+	u16 cur_cmd = 0;
+	unsigned long timeout;
+
+	/* Check param */
+	if (cmd == NULL)
+		return -EINVAL;
+
+	/* Wait until SCU command interface is ready to receive command */
+	rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_COMMAND__A, &cur_cmd, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	if (cur_cmd != DRX_SCU_READY)
+		return -EIO;
+
+	switch (cmd->parameter_len) {
+	case 5:
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_4__A, *(cmd->parameter + 4), 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}	/* fallthrough */
+	case 4:
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_3__A, *(cmd->parameter + 3), 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}	/* fallthrough */
+	case 3:
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_2__A, *(cmd->parameter + 2), 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}	/* fallthrough */
+	case 2:
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_1__A, *(cmd->parameter + 1), 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}	/* fallthrough */
+	case 1:
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_0__A, *(cmd->parameter + 0), 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}	/* fallthrough */
+	case 0:
+		/* do nothing */
+		break;
+	default:
+		/* this number of parameters is not supported */
+		return -EIO;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_COMMAND__A, cmd->command, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	/* Wait until SCU has processed command */
+	timeout = jiffies + msecs_to_jiffies(DRXJ_MAX_WAITTIME);
+	while (time_is_after_jiffies(timeout)) {
+		rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_COMMAND__A, &cur_cmd, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		if (cur_cmd == DRX_SCU_READY)
+			break;
+		usleep_range(1000, 2000);
+	}
+
+	if (cur_cmd != DRX_SCU_READY)
+		return -EIO;
+
+	/* read results */
+	if ((cmd->result_len > 0) && (cmd->result != NULL)) {
+		s16 err;
+
+		switch (cmd->result_len) {
+		case 4:
+			rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_PARAM_3__A, cmd->result + 3, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}	/* fallthrough */
+		case 3:
+			rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_PARAM_2__A, cmd->result + 2, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}	/* fallthrough */
+		case 2:
+			rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_PARAM_1__A, cmd->result + 1, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}	/* fallthrough */
+		case 1:
+			rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_PARAM_0__A, cmd->result + 0, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}	/* fallthrough */
+		case 0:
+			/* do nothing */
+			break;
+		default:
+			/* this number of parameters is not supported */
+			return -EIO;
+		}
+
+		/* Check if an error was reported by SCU */
+		err = cmd->result[0];
+
+		/* check a few fixed error codes */
+		if ((err == (s16) SCU_RAM_PARAM_0_RESULT_UNKSTD)
+		    || (err == (s16) SCU_RAM_PARAM_0_RESULT_UNKCMD)
+		    || (err == (s16) SCU_RAM_PARAM_0_RESULT_INVPAR)
+		    || (err == (s16) SCU_RAM_PARAM_0_RESULT_SIZE)
+		    ) {
+			return -EINVAL;
+		}
+		/* here it is assumed that negative means error, and positive no error */
+		else if (err < 0)
+			return -EIO;
+		else
+			return 0;
+	}
+
+	return 0;
+
+rw_error:
+	return -EIO;
+}
+
+/**
+* \fn int DRXJ_DAP_SCUAtomicReadWriteBlock()
+* \brief Basic access routine for SCU atomic read or write access
+* \param dev_addr  pointer to i2c dev address
+* \param addr     destination/source address
+* \param datasize size of data buffer in bytes
+* \param data     pointer to data buffer
+* \return int
+* \retval 0 Succes
+* \retval -EIO Timeout, I2C error, illegal bank
+*
+*/
+#define ADDR_AT_SCU_SPACE(x) ((x - 0x82E000) * 2)
+static
+int drxj_dap_scu_atomic_read_write_block(struct i2c_device_addr *dev_addr, u32 addr, u16 datasize,	/* max 30 bytes because the limit of SCU parameter */
+					      u8 *data, bool read_flag)
+{
+	struct drxjscu_cmd scu_cmd;
+	int rc;
+	u16 set_param_parameters[15];
+	u16 cmd_result[15];
+
+	/* Parameter check */
+	if (!data || !dev_addr || (datasize % 2) || ((datasize / 2) > 16))
+		return -EINVAL;
+
+	set_param_parameters[1] = (u16) ADDR_AT_SCU_SPACE(addr);
+	if (read_flag) {		/* read */
+		set_param_parameters[0] = ((~(0x0080)) & datasize);
+		scu_cmd.parameter_len = 2;
+		scu_cmd.result_len = datasize / 2 + 2;
+	} else {
+		int i = 0;
+
+		set_param_parameters[0] = 0x0080 | datasize;
+		for (i = 0; i < (datasize / 2); i++) {
+			set_param_parameters[i + 2] =
+			    (data[2 * i] | (data[(2 * i) + 1] << 8));
+		}
+		scu_cmd.parameter_len = datasize / 2 + 2;
+		scu_cmd.result_len = 1;
+	}
+
+	scu_cmd.command =
+	    SCU_RAM_COMMAND_STANDARD_TOP |
+	    SCU_RAM_COMMAND_CMD_AUX_SCU_ATOMIC_ACCESS;
+	scu_cmd.result = cmd_result;
+	scu_cmd.parameter = set_param_parameters;
+	rc = scu_command(dev_addr, &scu_cmd);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	if (read_flag) {
+		int i = 0;
+		/* read data from buffer */
+		for (i = 0; i < (datasize / 2); i++) {
+			data[2 * i] = (u8) (scu_cmd.result[i + 2] & 0xFF);
+			data[(2 * i) + 1] = (u8) (scu_cmd.result[i + 2] >> 8);
+		}
+	}
+
+	return 0;
+
+rw_error:
+	return -EIO;
+
+}
+
+/*============================================================================*/
+
+/**
+* \fn int DRXJ_DAP_AtomicReadReg16()
+* \brief Atomic read of 16 bits words
+*/
+static
+int drxj_dap_scu_atomic_read_reg16(struct i2c_device_addr *dev_addr,
+					 u32 addr,
+					 u16 *data, u32 flags)
+{
+	u8 buf[2];
+	int rc = -EIO;
+	u16 word = 0;
+
+	if (!data)
+		return -EINVAL;
+
+	rc = drxj_dap_scu_atomic_read_write_block(dev_addr, addr, 2, buf, true);
+	if (rc < 0)
+		return rc;
+
+	word = (u16) (buf[0] + (buf[1] << 8));
+
+	*data = word;
+
+	return rc;
+}
+
+/*============================================================================*/
+/**
+* \fn int drxj_dap_scu_atomic_write_reg16()
+* \brief Atomic read of 16 bits words
+*/
+static
+int drxj_dap_scu_atomic_write_reg16(struct i2c_device_addr *dev_addr,
+					  u32 addr,
+					  u16 data, u32 flags)
+{
+	u8 buf[2];
+	int rc = -EIO;
+
+	buf[0] = (u8) (data & 0xff);
+	buf[1] = (u8) ((data >> 8) & 0xff);
+
+	rc = drxj_dap_scu_atomic_read_write_block(dev_addr, addr, 2, buf, false);
+
+	return rc;
+}
+
+/* -------------------------------------------------------------------------- */
+/**
+* \brief Measure result of ADC synchronisation
+* \param demod demod instance
+* \param count (returned) count
+* \return int.
+* \retval 0    Success
+* \retval -EIO Failure: I2C error
+*
+*/
+static int adc_sync_measurement(struct drx_demod_instance *demod, u16 *count)
+{
+	struct i2c_device_addr *dev_addr = NULL;
+	int rc;
+	u16 data = 0;
+
+	dev_addr = demod->my_i2c_dev_addr;
+
+	/* Start measurement */
+	rc = drxj_dap_write_reg16(dev_addr, IQM_AF_COMM_EXEC__A, IQM_AF_COMM_EXEC_ACTIVE, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_AF_START_LOCK__A, 1, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	/* Wait at least 3*128*(1/sysclk) <<< 1 millisec */
+	msleep(1);
+
+	*count = 0;
+	rc = drxj_dap_read_reg16(dev_addr, IQM_AF_PHASE0__A, &data, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	if (data == 127)
+		*count = *count + 1;
+	rc = drxj_dap_read_reg16(dev_addr, IQM_AF_PHASE1__A, &data, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	if (data == 127)
+		*count = *count + 1;
+	rc = drxj_dap_read_reg16(dev_addr, IQM_AF_PHASE2__A, &data, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	if (data == 127)
+		*count = *count + 1;
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/**
+* \brief Synchronize analog and digital clock domains
+* \param demod demod instance
+* \return int.
+* \retval 0    Success
+* \retval -EIO Failure: I2C error or failure to synchronize
+*
+* An IQM reset will also reset the results of this synchronization.
+* After an IQM reset this routine needs to be called again.
+*
+*/
+
+static int adc_synchronization(struct drx_demod_instance *demod)
+{
+	struct i2c_device_addr *dev_addr = NULL;
+	int rc;
+	u16 count = 0;
+
+	dev_addr = demod->my_i2c_dev_addr;
+
+	rc = adc_sync_measurement(demod, &count);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	if (count == 1) {
+		/* Try sampling on a diffrent edge */
+		u16 clk_neg = 0;
+
+		rc = drxj_dap_read_reg16(dev_addr, IQM_AF_CLKNEG__A, &clk_neg, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+
+		clk_neg ^= IQM_AF_CLKNEG_CLKNEGDATA__M;
+		rc = drxj_dap_write_reg16(dev_addr, IQM_AF_CLKNEG__A, clk_neg, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+
+		rc = adc_sync_measurement(demod, &count);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+	}
+
+	/* TODO: implement fallback scenarios */
+	if (count < 2)
+		return -EIO;
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/*============================================================================*/
+/*==                      END AUXILIARY FUNCTIONS                           ==*/
+/*============================================================================*/
+
+/*============================================================================*/
+/*============================================================================*/
+/*==                8VSB & QAM COMMON DATAPATH FUNCTIONS                    ==*/
+/*============================================================================*/
+/*============================================================================*/
+/**
+* \fn int init_agc ()
+* \brief Initialize AGC for all standards.
+* \param demod instance of demodulator.
+* \param channel pointer to channel data.
+* \return int.
+*/
+static int init_agc(struct drx_demod_instance *demod)
+{
+	struct i2c_device_addr *dev_addr = NULL;
+	struct drx_common_attr *common_attr = NULL;
+	struct drxj_data *ext_attr = NULL;
+	struct drxj_cfg_agc *p_agc_rf_settings = NULL;
+	struct drxj_cfg_agc *p_agc_if_settings = NULL;
+	int rc;
+	u16 ingain_tgt_max = 0;
+	u16 clp_dir_to = 0;
+	u16 sns_sum_max = 0;
+	u16 clp_sum_max = 0;
+	u16 sns_dir_to = 0;
+	u16 ki_innergain_min = 0;
+	u16 agc_ki = 0;
+	u16 ki_max = 0;
+	u16 if_iaccu_hi_tgt_min = 0;
+	u16 data = 0;
+	u16 agc_ki_dgain = 0;
+	u16 ki_min = 0;
+	u16 clp_ctrl_mode = 0;
+	u16 agc_rf = 0;
+	u16 agc_if = 0;
+
+	dev_addr = demod->my_i2c_dev_addr;
+	common_attr = (struct drx_common_attr *) demod->my_common_attr;
+	ext_attr = (struct drxj_data *) demod->my_ext_attr;
+
+	switch (ext_attr->standard) {
+	case DRX_STANDARD_8VSB:
+		clp_sum_max = 1023;
+		clp_dir_to = (u16) (-9);
+		sns_sum_max = 1023;
+		sns_dir_to = (u16) (-9);
+		ki_innergain_min = (u16) (-32768);
+		ki_max = 0x032C;
+		agc_ki_dgain = 0xC;
+		if_iaccu_hi_tgt_min = 2047;
+		ki_min = 0x0117;
+		ingain_tgt_max = 16383;
+		clp_ctrl_mode = 0;
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_SUM__A, 0, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_CYCCNT__A, 0, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_DIR_WD__A, 0, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_DIR_STP__A, 1, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_SUM__A, 0, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_CYCCNT__A, 0, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_DIR_WD__A, 0, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_DIR_STP__A, 1, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN__A, 1024, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_VSB_AGC_POW_TGT__A, 22600, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, 13200, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		p_agc_if_settings = &(ext_attr->vsb_if_agc_cfg);
+		p_agc_rf_settings = &(ext_attr->vsb_rf_agc_cfg);
+		break;
+#ifndef DRXJ_VSB_ONLY
+	case DRX_STANDARD_ITU_A:
+	case DRX_STANDARD_ITU_C:
+	case DRX_STANDARD_ITU_B:
+		ingain_tgt_max = 5119;
+		clp_sum_max = 1023;
+		clp_dir_to = (u16) (-5);
+		sns_sum_max = 127;
+		sns_dir_to = (u16) (-3);
+		ki_innergain_min = 0;
+		ki_max = 0x0657;
+		if_iaccu_hi_tgt_min = 2047;
+		agc_ki_dgain = 0x7;
+		ki_min = 0x0117;
+		clp_ctrl_mode = 0;
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_SUM__A, 0, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_CYCCNT__A, 0, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_DIR_WD__A, 0, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_DIR_STP__A, 1, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_SUM__A, 0, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_CYCCNT__A, 0, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_DIR_WD__A, 0, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_DIR_STP__A, 1, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		p_agc_if_settings = &(ext_attr->qam_if_agc_cfg);
+		p_agc_rf_settings = &(ext_attr->qam_rf_agc_cfg);
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, p_agc_if_settings->top, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+
+		rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_AGC_KI__A, &agc_ki, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		agc_ki &= 0xf000;
+		rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI__A, agc_ki, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		break;
+#endif
+	default:
+		return -EINVAL;
+	}
+
+	/* for new AGC interface */
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN_TGT_MIN__A, p_agc_if_settings->top, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN__A, p_agc_if_settings->top, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}	/* Gain fed from inner to outer AGC */
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingain_tgt_max, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, if_iaccu_hi_tgt_min, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_IF_IACCU_HI__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}	/* set to p_agc_settings->top before */
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_IF_IACCU_LO__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_RF_IACCU_HI__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_RF_IACCU_LO__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_RF_MAX__A, 32767, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_SUM_MAX__A, clp_sum_max, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_SUM_MAX__A, sns_sum_max, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, ki_innergain_min, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_FAST_SNS_CTRL_DELAY__A, 50, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_CYCLEN__A, 500, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_CYCLEN__A, 500, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MAXMINGAIN_TH__A, 20, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MIN__A, ki_min, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MAX__A, ki_max, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_RED__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_SUM_MIN__A, 8, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_CYCLEN__A, 500, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_DIR_TO__A, clp_dir_to, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_SUM_MIN__A, 8, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_DIR_TO__A, sns_dir_to, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, 50, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_CTRL_MODE__A, clp_ctrl_mode, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	agc_rf = 0x800 + p_agc_rf_settings->cut_off_current;
+	if (common_attr->tuner_rf_agc_pol == true)
+		agc_rf = 0x87ff - agc_rf;
+
+	agc_if = 0x800;
+	if (common_attr->tuner_if_agc_pol == true)
+		agc_rf = 0x87ff - agc_rf;
+
+	rc = drxj_dap_write_reg16(dev_addr, IQM_AF_AGC_RF__A, agc_rf, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_AF_AGC_IF__A, agc_if, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	/* Set/restore Ki DGAIN factor */
+	rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	data &= ~SCU_RAM_AGC_KI_DGAIN__M;
+	data |= (agc_ki_dgain << SCU_RAM_AGC_KI_DGAIN__B);
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/**
+* \fn int set_frequency ()
+* \brief Set frequency shift.
+* \param demod instance of demodulator.
+* \param channel pointer to channel data.
+* \param tuner_freq_offset residual frequency from tuner.
+* \return int.
+*/
+static int
+set_frequency(struct drx_demod_instance *demod,
+	      struct drx_channel *channel, s32 tuner_freq_offset)
+{
+	struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
+	struct drxj_data *ext_attr = demod->my_ext_attr;
+	int rc;
+	s32 sampling_frequency = 0;
+	s32 frequency_shift = 0;
+	s32 if_freq_actual = 0;
+	s32 rf_freq_residual = -1 * tuner_freq_offset;
+	s32 adc_freq = 0;
+	s32 intermediate_freq = 0;
+	u32 iqm_fs_rate_ofs = 0;
+	bool adc_flip = true;
+	bool select_pos_image = false;
+	bool rf_mirror;
+	bool tuner_mirror;
+	bool image_to_select = true;
+	s32 fm_frequency_shift = 0;
+
+	rf_mirror = (ext_attr->mirror == DRX_MIRROR_YES) ? true : false;
+	tuner_mirror = demod->my_common_attr->mirror_freq_spect ? false : true;
+	/*
+	   Program frequency shifter
+	   No need to account for mirroring on RF
+	 */
+	switch (ext_attr->standard) {
+	case DRX_STANDARD_ITU_A:	/* fallthrough */
+	case DRX_STANDARD_ITU_C:	/* fallthrough */
+	case DRX_STANDARD_PAL_SECAM_LP:	/* fallthrough */
+	case DRX_STANDARD_8VSB:
+		select_pos_image = true;
+		break;
+	case DRX_STANDARD_FM:
+		/* After IQM FS sound carrier must appear at 4 Mhz in spect.
+		   Sound carrier is already 3Mhz above centre frequency due
+		   to tuner setting so now add an extra shift of 1MHz... */
+		fm_frequency_shift = 1000;
+	case DRX_STANDARD_ITU_B:	/* fallthrough */
+	case DRX_STANDARD_NTSC:	/* fallthrough */
+	case DRX_STANDARD_PAL_SECAM_BG:	/* fallthrough */
+	case DRX_STANDARD_PAL_SECAM_DK:	/* fallthrough */
+	case DRX_STANDARD_PAL_SECAM_I:	/* fallthrough */
+	case DRX_STANDARD_PAL_SECAM_L:
+		select_pos_image = false;
+		break;
+	default:
+		return -EINVAL;
+	}
+	intermediate_freq = demod->my_common_attr->intermediate_freq;
+	sampling_frequency = demod->my_common_attr->sys_clock_freq / 3;
+	if (tuner_mirror)
+		if_freq_actual = intermediate_freq + rf_freq_residual + fm_frequency_shift;
+	else
+		if_freq_actual = intermediate_freq - rf_freq_residual - fm_frequency_shift;
+	if (if_freq_actual > sampling_frequency / 2) {
+		/* adc mirrors */
+		adc_freq = sampling_frequency - if_freq_actual;
+		adc_flip = true;
+	} else {
+		/* adc doesn't mirror */
+		adc_freq = if_freq_actual;
+		adc_flip = false;
+	}
+
+	frequency_shift = adc_freq;
+	image_to_select =
+	    (bool) (rf_mirror ^ tuner_mirror ^ adc_flip ^ select_pos_image);
+	iqm_fs_rate_ofs = frac28(frequency_shift, sampling_frequency);
+
+	if (image_to_select)
+		iqm_fs_rate_ofs = ~iqm_fs_rate_ofs + 1;
+
+	/* Program frequency shifter with tuner offset compensation */
+	/* frequency_shift += tuner_freq_offset; TODO */
+	rc = drxdap_fasi_write_reg32(dev_addr, IQM_FS_RATE_OFS_LO__A, iqm_fs_rate_ofs, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	ext_attr->iqm_fs_rate_ofs = iqm_fs_rate_ofs;
+	ext_attr->pos_image = (bool) (rf_mirror ^ tuner_mirror ^ select_pos_image);
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/**
+* \fn int get_acc_pkt_err()
+* \brief Retrieve signal strength for VSB and QAM.
+* \param demod Pointer to demod instance
+* \param packet_err Pointer to packet error
+* \return int.
+* \retval 0 sig_strength contains valid data.
+* \retval -EINVAL sig_strength is NULL.
+* \retval -EIO Erroneous data, sig_strength contains invalid data.
+*/
+#ifdef DRXJ_SIGNAL_ACCUM_ERR
+static int get_acc_pkt_err(struct drx_demod_instance *demod, u16 *packet_err)
+{
+	int rc;
+	static u16 pkt_err;
+	static u16 last_pkt_err;
+	u16 data = 0;
+	struct drxj_data *ext_attr = NULL;
+	struct i2c_device_addr *dev_addr = NULL;
+
+	ext_attr = (struct drxj_data *) demod->my_ext_attr;
+	dev_addr = demod->my_i2c_dev_addr;
+
+	rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, &data, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	if (ext_attr->reset_pkt_err_acc) {
+		last_pkt_err = data;
+		pkt_err = 0;
+		ext_attr->reset_pkt_err_acc = false;
+	}
+
+	if (data < last_pkt_err) {
+		pkt_err += 0xffff - last_pkt_err;
+		pkt_err += data;
+	} else {
+		pkt_err += (data - last_pkt_err);
+	}
+	*packet_err = pkt_err;
+	last_pkt_err = data;
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+#endif
+
+
+/*============================================================================*/
+
+/**
+* \fn int set_agc_rf ()
+* \brief Configure RF AGC
+* \param demod instance of demodulator.
+* \param agc_settings AGC configuration structure
+* \return int.
+*/
+static int
+set_agc_rf(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings, bool atomic)
+{
+	struct i2c_device_addr *dev_addr = NULL;
+	struct drxj_data *ext_attr = NULL;
+	struct drxj_cfg_agc *p_agc_settings = NULL;
+	struct drx_common_attr *common_attr = NULL;
+	int rc;
+	drx_write_reg16func_t scu_wr16 = NULL;
+	drx_read_reg16func_t scu_rr16 = NULL;
+
+	common_attr = (struct drx_common_attr *) demod->my_common_attr;
+	dev_addr = demod->my_i2c_dev_addr;
+	ext_attr = (struct drxj_data *) demod->my_ext_attr;
+
+	if (atomic) {
+		scu_rr16 = drxj_dap_scu_atomic_read_reg16;
+		scu_wr16 = drxj_dap_scu_atomic_write_reg16;
+	} else {
+		scu_rr16 = drxj_dap_read_reg16;
+		scu_wr16 = drxj_dap_write_reg16;
+	}
+
+	/* Configure AGC only if standard is currently active */
+	if ((ext_attr->standard == agc_settings->standard) ||
+	    (DRXJ_ISQAMSTD(ext_attr->standard) &&
+	     DRXJ_ISQAMSTD(agc_settings->standard)) ||
+	    (DRXJ_ISATVSTD(ext_attr->standard) &&
+	     DRXJ_ISATVSTD(agc_settings->standard))) {
+		u16 data = 0;
+
+		switch (agc_settings->ctrl_mode) {
+		case DRX_AGC_CTRL_AUTO:
+
+			/* Enable RF AGC DAC */
+			rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			data |= IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE;
+			rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+
+			/* Enable SCU RF AGC loop */
+			rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			data &= ~SCU_RAM_AGC_KI_RF__M;
+			if (ext_attr->standard == DRX_STANDARD_8VSB)
+				data |= (2 << SCU_RAM_AGC_KI_RF__B);
+			else if (DRXJ_ISQAMSTD(ext_attr->standard))
+				data |= (5 << SCU_RAM_AGC_KI_RF__B);
+			else
+				data |= (4 << SCU_RAM_AGC_KI_RF__B);
+
+			if (common_attr->tuner_rf_agc_pol)
+				data |= SCU_RAM_AGC_KI_INV_RF_POL__M;
+			else
+				data &= ~SCU_RAM_AGC_KI_INV_RF_POL__M;
+			rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+
+			/* Set speed ( using complementary reduction value ) */
+			rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI_RED__A, &data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			data &= ~SCU_RAM_AGC_KI_RED_RAGC_RED__M;
+			rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI_RED__A, (~(agc_settings->speed << SCU_RAM_AGC_KI_RED_RAGC_RED__B) & SCU_RAM_AGC_KI_RED_RAGC_RED__M) | data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+
+			if (agc_settings->standard == DRX_STANDARD_8VSB)
+				p_agc_settings = &(ext_attr->vsb_if_agc_cfg);
+			else if (DRXJ_ISQAMSTD(agc_settings->standard))
+				p_agc_settings = &(ext_attr->qam_if_agc_cfg);
+			else if (DRXJ_ISATVSTD(agc_settings->standard))
+				p_agc_settings = &(ext_attr->atv_if_agc_cfg);
+			else
+				return -EINVAL;
+
+			/* Set TOP, only if IF-AGC is in AUTO mode */
+			if (p_agc_settings->ctrl_mode == DRX_AGC_CTRL_AUTO) {
+				rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, agc_settings->top, 0);
+				if (rc != 0) {
+					pr_err("error %d\n", rc);
+					goto rw_error;
+				}
+				rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, agc_settings->top, 0);
+				if (rc != 0) {
+					pr_err("error %d\n", rc);
+					goto rw_error;
+				}
+			}
+
+			/* Cut-Off current */
+			rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_RF_IACCU_HI_CO__A, agc_settings->cut_off_current, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			break;
+		case DRX_AGC_CTRL_USER:
+
+			/* Enable RF AGC DAC */
+			rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			data |= IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE;
+			rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+
+			/* Disable SCU RF AGC loop */
+			rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			data &= ~SCU_RAM_AGC_KI_RF__M;
+			if (common_attr->tuner_rf_agc_pol)
+				data |= SCU_RAM_AGC_KI_INV_RF_POL__M;
+			else
+				data &= ~SCU_RAM_AGC_KI_INV_RF_POL__M;
+			rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+
+			/* Write value to output pin */
+			rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_RF_IACCU_HI__A, agc_settings->output_level, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			break;
+		case DRX_AGC_CTRL_OFF:
+
+			/* Disable RF AGC DAC */
+			rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			data &= (~IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE);
+			rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+
+			/* Disable SCU RF AGC loop */
+			rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			data &= ~SCU_RAM_AGC_KI_RF__M;
+			rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			break;
+		default:
+			return -EINVAL;
+		}		/* switch ( agcsettings->ctrl_mode ) */
+	}
+
+	/* Store rf agc settings */
+	switch (agc_settings->standard) {
+	case DRX_STANDARD_8VSB:
+		ext_attr->vsb_rf_agc_cfg = *agc_settings;
+		break;
+#ifndef DRXJ_VSB_ONLY
+	case DRX_STANDARD_ITU_A:
+	case DRX_STANDARD_ITU_B:
+	case DRX_STANDARD_ITU_C:
+		ext_attr->qam_rf_agc_cfg = *agc_settings;
+		break;
+#endif
+	default:
+		return -EIO;
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/**
+* \fn int set_agc_if ()
+* \brief Configure If AGC
+* \param demod instance of demodulator.
+* \param agc_settings AGC configuration structure
+* \return int.
+*/
+static int
+set_agc_if(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings, bool atomic)
+{
+	struct i2c_device_addr *dev_addr = NULL;
+	struct drxj_data *ext_attr = NULL;
+	struct drxj_cfg_agc *p_agc_settings = NULL;
+	struct drx_common_attr *common_attr = NULL;
+	drx_write_reg16func_t scu_wr16 = NULL;
+	drx_read_reg16func_t scu_rr16 = NULL;
+	int rc;
+
+	common_attr = (struct drx_common_attr *) demod->my_common_attr;
+	dev_addr = demod->my_i2c_dev_addr;
+	ext_attr = (struct drxj_data *) demod->my_ext_attr;
+
+	if (atomic) {
+		scu_rr16 = drxj_dap_scu_atomic_read_reg16;
+		scu_wr16 = drxj_dap_scu_atomic_write_reg16;
+	} else {
+		scu_rr16 = drxj_dap_read_reg16;
+		scu_wr16 = drxj_dap_write_reg16;
+	}
+
+	/* Configure AGC only if standard is currently active */
+	if ((ext_attr->standard == agc_settings->standard) ||
+	    (DRXJ_ISQAMSTD(ext_attr->standard) &&
+	     DRXJ_ISQAMSTD(agc_settings->standard)) ||
+	    (DRXJ_ISATVSTD(ext_attr->standard) &&
+	     DRXJ_ISATVSTD(agc_settings->standard))) {
+		u16 data = 0;
+
+		switch (agc_settings->ctrl_mode) {
+		case DRX_AGC_CTRL_AUTO:
+			/* Enable IF AGC DAC */
+			rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			data |= IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE;
+			rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+
+			/* Enable SCU IF AGC loop */
+			rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
+			data &= ~SCU_RAM_AGC_KI_IF__M;
+			if (ext_attr->standard == DRX_STANDARD_8VSB)
+				data |= (3 << SCU_RAM_AGC_KI_IF__B);
+			else if (DRXJ_ISQAMSTD(ext_attr->standard))
+				data |= (6 << SCU_RAM_AGC_KI_IF__B);
+			else
+				data |= (5 << SCU_RAM_AGC_KI_IF__B);
+
+			if (common_attr->tuner_if_agc_pol)
+				data |= SCU_RAM_AGC_KI_INV_IF_POL__M;
+			else
+				data &= ~SCU_RAM_AGC_KI_INV_IF_POL__M;
+			rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+
+			/* Set speed (using complementary reduction value) */
+			rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI_RED__A, &data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			data &= ~SCU_RAM_AGC_KI_RED_IAGC_RED__M;
+			rc = (*scu_wr16) (dev_addr, SCU_RAM_AGC_KI_RED__A, (~(agc_settings->speed << SCU_RAM_AGC_KI_RED_IAGC_RED__B) & SCU_RAM_AGC_KI_RED_IAGC_RED__M) | data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+
+			if (agc_settings->standard == DRX_STANDARD_8VSB)
+				p_agc_settings = &(ext_attr->vsb_rf_agc_cfg);
+			else if (DRXJ_ISQAMSTD(agc_settings->standard))
+				p_agc_settings = &(ext_attr->qam_rf_agc_cfg);
+			else if (DRXJ_ISATVSTD(agc_settings->standard))
+				p_agc_settings = &(ext_attr->atv_rf_agc_cfg);
+			else
+				return -EINVAL;
+
+			/* Restore TOP */
+			if (p_agc_settings->ctrl_mode == DRX_AGC_CTRL_AUTO) {
+				rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, p_agc_settings->top, 0);
+				if (rc != 0) {
+					pr_err("error %d\n", rc);
+					goto rw_error;
+				}
+				rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, p_agc_settings->top, 0);
+				if (rc != 0) {
+					pr_err("error %d\n", rc);
+					goto rw_error;
+				}
+			} else {
+				rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, 0, 0);
+				if (rc != 0) {
+					pr_err("error %d\n", rc);
+					goto rw_error;
+				}
+				rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, 0, 0);
+				if (rc != 0) {
+					pr_err("error %d\n", rc);
+					goto rw_error;
+				}
+			}
+			break;
+
+		case DRX_AGC_CTRL_USER:
+
+			/* Enable IF AGC DAC */
+			rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			data |= IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE;
+			rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+
+			/* Disable SCU IF AGC loop */
+			rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
+			data |= SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
+			if (common_attr->tuner_if_agc_pol)
+				data |= SCU_RAM_AGC_KI_INV_IF_POL__M;
+			else
+				data &= ~SCU_RAM_AGC_KI_INV_IF_POL__M;
+			rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+
+			/* Write value to output pin */
+			rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, agc_settings->output_level, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			break;
+
+		case DRX_AGC_CTRL_OFF:
+
+			/* Disable If AGC DAC */
+			rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			data &= (~IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE);
+			rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+
+			/* Disable SCU IF AGC loop */
+			rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
+			data |= SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
+			rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
+			if (rc != 0) {
+				pr_err("error %d\n", rc);
+				goto rw_error;
+			}
+			break;
+		default:
+			return -EINVAL;
+		}		/* switch ( agcsettings->ctrl_mode ) */
+
+		/* always set the top to support configurations without if-loop */
+		rc = (*scu_wr16) (dev_addr, SCU_RAM_AGC_INGAIN_TGT_MIN__A, agc_settings->top, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+	}
+
+	/* Store if agc settings */
+	switch (agc_settings->standard) {
+	case DRX_STANDARD_8VSB:
+		ext_attr->vsb_if_agc_cfg = *agc_settings;
+		break;
+#ifndef DRXJ_VSB_ONLY
+	case DRX_STANDARD_ITU_A:
+	case DRX_STANDARD_ITU_B:
+	case DRX_STANDARD_ITU_C:
+		ext_attr->qam_if_agc_cfg = *agc_settings;
+		break;
+#endif
+	default:
+		return -EIO;
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/**
+* \fn int set_iqm_af ()
+* \brief Configure IQM AF registers
+* \param demod instance of demodulator.
+* \param active
+* \return int.
+*/
+static int set_iqm_af(struct drx_demod_instance *demod, bool active)
+{
+	u16 data = 0;
+	struct i2c_device_addr *dev_addr = NULL;
+	int rc;
+
+	dev_addr = demod->my_i2c_dev_addr;
+
+	/* Configure IQM */
+	rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	if (!active)
+		data &= ((~IQM_AF_STDBY_STDBY_ADC_A2_ACTIVE) & (~IQM_AF_STDBY_STDBY_AMP_A2_ACTIVE) & (~IQM_AF_STDBY_STDBY_PD_A2_ACTIVE) & (~IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE) & (~IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE));
+	else
+		data |= (IQM_AF_STDBY_STDBY_ADC_A2_ACTIVE | IQM_AF_STDBY_STDBY_AMP_A2_ACTIVE | IQM_AF_STDBY_STDBY_PD_A2_ACTIVE | IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE | IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE);
+	rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/*============================================================================*/
+/*==              END 8VSB & QAM COMMON DATAPATH FUNCTIONS                  ==*/
+/*============================================================================*/
+
+/*============================================================================*/
+/*============================================================================*/
+/*==                       8VSB DATAPATH FUNCTIONS                          ==*/
+/*============================================================================*/
+/*============================================================================*/
+
+/**
+* \fn int power_down_vsb ()
+* \brief Powr down QAM related blocks.
+* \param demod instance of demodulator.
+* \param channel pointer to channel data.
+* \return int.
+*/
+static int power_down_vsb(struct drx_demod_instance *demod, bool primary)
+{
+	struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
+	struct drxjscu_cmd cmd_scu = { /* command     */ 0,
+		/* parameter_len */ 0,
+		/* result_len    */ 0,
+		/* *parameter   */ NULL,
+		/* *result      */ NULL
+	};
+	struct drx_cfg_mpeg_output cfg_mpeg_output;
+	int rc;
+	u16 cmd_result = 0;
+
+	/*
+	   STOP demodulator
+	   reset of FEC and VSB HW
+	 */
+	cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB |
+	    SCU_RAM_COMMAND_CMD_DEMOD_STOP;
+	cmd_scu.parameter_len = 0;
+	cmd_scu.result_len = 1;
+	cmd_scu.parameter = NULL;
+	cmd_scu.result = &cmd_result;
+	rc = scu_command(dev_addr, &cmd_scu);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	/* stop all comm_exec */
+	rc = drxj_dap_write_reg16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_STOP, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	if (primary) {
+		rc = drxj_dap_write_reg16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = set_iqm_af(demod, false);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+	} else {
+		rc = drxj_dap_write_reg16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+	}
+
+	cfg_mpeg_output.enable_mpeg_output = false;
+	rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/**
+* \fn int set_vsb_leak_n_gain ()
+* \brief Set ATSC demod.
+* \param demod instance of demodulator.
+* \return int.
+*/
+static int set_vsb_leak_n_gain(struct drx_demod_instance *demod)
+{
+	struct i2c_device_addr *dev_addr = NULL;
+	int rc;
+
+	const u8 vsb_ffe_leak_gain_ram0[] = {
+		DRXJ_16TO8(0x8),	/* FFETRAINLKRATIO1  */
+		DRXJ_16TO8(0x8),	/* FFETRAINLKRATIO2  */
+		DRXJ_16TO8(0x8),	/* FFETRAINLKRATIO3  */
+		DRXJ_16TO8(0xf),	/* FFETRAINLKRATIO4  */
+		DRXJ_16TO8(0xf),	/* FFETRAINLKRATIO5  */
+		DRXJ_16TO8(0xf),	/* FFETRAINLKRATIO6  */
+		DRXJ_16TO8(0xf),	/* FFETRAINLKRATIO7  */
+		DRXJ_16TO8(0xf),	/* FFETRAINLKRATIO8  */
+		DRXJ_16TO8(0xf),	/* FFETRAINLKRATIO9  */
+		DRXJ_16TO8(0x8),	/* FFETRAINLKRATIO10  */
+		DRXJ_16TO8(0x8),	/* FFETRAINLKRATIO11 */
+		DRXJ_16TO8(0x8),	/* FFETRAINLKRATIO12 */
+		DRXJ_16TO8(0x10),	/* FFERCA1TRAINLKRATIO1 */
+		DRXJ_16TO8(0x10),	/* FFERCA1TRAINLKRATIO2 */
+		DRXJ_16TO8(0x10),	/* FFERCA1TRAINLKRATIO3 */
+		DRXJ_16TO8(0x20),	/* FFERCA1TRAINLKRATIO4 */
+		DRXJ_16TO8(0x20),	/* FFERCA1TRAINLKRATIO5 */
+		DRXJ_16TO8(0x20),	/* FFERCA1TRAINLKRATIO6 */
+		DRXJ_16TO8(0x20),	/* FFERCA1TRAINLKRATIO7 */
+		DRXJ_16TO8(0x20),	/* FFERCA1TRAINLKRATIO8 */
+		DRXJ_16TO8(0x20),	/* FFERCA1TRAINLKRATIO9 */
+		DRXJ_16TO8(0x10),	/* FFERCA1TRAINLKRATIO10 */
+		DRXJ_16TO8(0x10),	/* FFERCA1TRAINLKRATIO11 */
+		DRXJ_16TO8(0x10),	/* FFERCA1TRAINLKRATIO12 */
+		DRXJ_16TO8(0x10),	/* FFERCA1DATALKRATIO1 */
+		DRXJ_16TO8(0x10),	/* FFERCA1DATALKRATIO2 */
+		DRXJ_16TO8(0x10),	/* FFERCA1DATALKRATIO3 */
+		DRXJ_16TO8(0x20),	/* FFERCA1DATALKRATIO4 */
+		DRXJ_16TO8(0x20),	/* FFERCA1DATALKRATIO5 */
+		DRXJ_16TO8(0x20),	/* FFERCA1DATALKRATIO6 */
+		DRXJ_16TO8(0x20),	/* FFERCA1DATALKRATIO7 */
+		DRXJ_16TO8(0x20),	/* FFERCA1DATALKRATIO8 */
+		DRXJ_16TO8(0x20),	/* FFERCA1DATALKRATIO9 */
+		DRXJ_16TO8(0x10),	/* FFERCA1DATALKRATIO10 */
+		DRXJ_16TO8(0x10),	/* FFERCA1DATALKRATIO11 */
+		DRXJ_16TO8(0x10),	/* FFERCA1DATALKRATIO12 */
+		DRXJ_16TO8(0x10),	/* FFERCA2TRAINLKRATIO1 */
+		DRXJ_16TO8(0x10),	/* FFERCA2TRAINLKRATIO2 */
+		DRXJ_16TO8(0x10),	/* FFERCA2TRAINLKRATIO3 */
+		DRXJ_16TO8(0x20),	/* FFERCA2TRAINLKRATIO4 */
+		DRXJ_16TO8(0x20),	/* FFERCA2TRAINLKRATIO5 */
+		DRXJ_16TO8(0x20),	/* FFERCA2TRAINLKRATIO6 */
+		DRXJ_16TO8(0x20),	/* FFERCA2TRAINLKRATIO7 */
+		DRXJ_16TO8(0x20),	/* FFERCA2TRAINLKRATIO8 */
+		DRXJ_16TO8(0x20),	/* FFERCA2TRAINLKRATIO9 */
+		DRXJ_16TO8(0x10),	/* FFERCA2TRAINLKRATIO10 */
+		DRXJ_16TO8(0x10),	/* FFERCA2TRAINLKRATIO11 */
+		DRXJ_16TO8(0x10),	/* FFERCA2TRAINLKRATIO12 */
+		DRXJ_16TO8(0x10),	/* FFERCA2DATALKRATIO1 */
+		DRXJ_16TO8(0x10),	/* FFERCA2DATALKRATIO2 */
+		DRXJ_16TO8(0x10),	/* FFERCA2DATALKRATIO3 */
+		DRXJ_16TO8(0x20),	/* FFERCA2DATALKRATIO4 */
+		DRXJ_16TO8(0x20),	/* FFERCA2DATALKRATIO5 */
+		DRXJ_16TO8(0x20),	/* FFERCA2DATALKRATIO6 */
+		DRXJ_16TO8(0x20),	/* FFERCA2DATALKRATIO7 */
+		DRXJ_16TO8(0x20),	/* FFERCA2DATALKRATIO8 */
+		DRXJ_16TO8(0x20),	/* FFERCA2DATALKRATIO9 */
+		DRXJ_16TO8(0x10),	/* FFERCA2DATALKRATIO10 */
+		DRXJ_16TO8(0x10),	/* FFERCA2DATALKRATIO11 */
+		DRXJ_16TO8(0x10),	/* FFERCA2DATALKRATIO12 */
+		DRXJ_16TO8(0x07),	/* FFEDDM1TRAINLKRATIO1 */
+		DRXJ_16TO8(0x07),	/* FFEDDM1TRAINLKRATIO2 */
+		DRXJ_16TO8(0x07),	/* FFEDDM1TRAINLKRATIO3 */
+		DRXJ_16TO8(0x0e),	/* FFEDDM1TRAINLKRATIO4 */
+		DRXJ_16TO8(0x0e),	/* FFEDDM1TRAINLKRATIO5 */
+		DRXJ_16TO8(0x0e),	/* FFEDDM1TRAINLKRATIO6 */
+		DRXJ_16TO8(0x0e),	/* FFEDDM1TRAINLKRATIO7 */
+		DRXJ_16TO8(0x0e),	/* FFEDDM1TRAINLKRATIO8 */
+		DRXJ_16TO8(0x0e),	/* FFEDDM1TRAINLKRATIO9 */
+		DRXJ_16TO8(0x07),	/* FFEDDM1TRAINLKRATIO10 */
+		DRXJ_16TO8(0x07),	/* FFEDDM1TRAINLKRATIO11 */
+		DRXJ_16TO8(0x07),	/* FFEDDM1TRAINLKRATIO12 */
+		DRXJ_16TO8(0x07),	/* FFEDDM1DATALKRATIO1 */
+		DRXJ_16TO8(0x07),	/* FFEDDM1DATALKRATIO2 */
+		DRXJ_16TO8(0x07),	/* FFEDDM1DATALKRATIO3 */
+		DRXJ_16TO8(0x0e),	/* FFEDDM1DATALKRATIO4 */
+		DRXJ_16TO8(0x0e),	/* FFEDDM1DATALKRATIO5 */
+		DRXJ_16TO8(0x0e),	/* FFEDDM1DATALKRATIO6 */
+		DRXJ_16TO8(0x0e),	/* FFEDDM1DATALKRATIO7 */
+		DRXJ_16TO8(0x0e),	/* FFEDDM1DATALKRATIO8 */
+		DRXJ_16TO8(0x0e),	/* FFEDDM1DATALKRATIO9 */
+		DRXJ_16TO8(0x07),	/* FFEDDM1DATALKRATIO10 */
+		DRXJ_16TO8(0x07),	/* FFEDDM1DATALKRATIO11 */
+		DRXJ_16TO8(0x07),	/* FFEDDM1DATALKRATIO12 */
+		DRXJ_16TO8(0x06),	/* FFEDDM2TRAINLKRATIO1 */
+		DRXJ_16TO8(0x06),	/* FFEDDM2TRAINLKRATIO2 */
+		DRXJ_16TO8(0x06),	/* FFEDDM2TRAINLKRATIO3 */
+		DRXJ_16TO8(0x0c),	/* FFEDDM2TRAINLKRATIO4 */
+		DRXJ_16TO8(0x0c),	/* FFEDDM2TRAINLKRATIO5 */
+		DRXJ_16TO8(0x0c),	/* FFEDDM2TRAINLKRATIO6 */
+		DRXJ_16TO8(0x0c),	/* FFEDDM2TRAINLKRATIO7 */
+		DRXJ_16TO8(0x0c),	/* FFEDDM2TRAINLKRATIO8 */
+		DRXJ_16TO8(0x0c),	/* FFEDDM2TRAINLKRATIO9 */
+		DRXJ_16TO8(0x06),	/* FFEDDM2TRAINLKRATIO10 */
+		DRXJ_16TO8(0x06),	/* FFEDDM2TRAINLKRATIO11 */
+		DRXJ_16TO8(0x06),	/* FFEDDM2TRAINLKRATIO12 */
+		DRXJ_16TO8(0x06),	/* FFEDDM2DATALKRATIO1 */
+		DRXJ_16TO8(0x06),	/* FFEDDM2DATALKRATIO2 */
+		DRXJ_16TO8(0x06),	/* FFEDDM2DATALKRATIO3 */
+		DRXJ_16TO8(0x0c),	/* FFEDDM2DATALKRATIO4 */
+		DRXJ_16TO8(0x0c),	/* FFEDDM2DATALKRATIO5 */
+		DRXJ_16TO8(0x0c),	/* FFEDDM2DATALKRATIO6 */
+		DRXJ_16TO8(0x0c),	/* FFEDDM2DATALKRATIO7 */
+		DRXJ_16TO8(0x0c),	/* FFEDDM2DATALKRATIO8 */
+		DRXJ_16TO8(0x0c),	/* FFEDDM2DATALKRATIO9 */
+		DRXJ_16TO8(0x06),	/* FFEDDM2DATALKRATIO10 */
+		DRXJ_16TO8(0x06),	/* FFEDDM2DATALKRATIO11 */
+		DRXJ_16TO8(0x06),	/* FFEDDM2DATALKRATIO12 */
+		DRXJ_16TO8(0x2020),	/* FIRTRAINGAIN1 */
+		DRXJ_16TO8(0x2020),	/* FIRTRAINGAIN2 */
+		DRXJ_16TO8(0x2020),	/* FIRTRAINGAIN3 */
+		DRXJ_16TO8(0x4040),	/* FIRTRAINGAIN4 */
+		DRXJ_16TO8(0x4040),	/* FIRTRAINGAIN5 */
+		DRXJ_16TO8(0x4040),	/* FIRTRAINGAIN6 */
+		DRXJ_16TO8(0x4040),	/* FIRTRAINGAIN7 */
+		DRXJ_16TO8(0x4040),	/* FIRTRAINGAIN8 */
+		DRXJ_16TO8(0x4040),	/* FIRTRAINGAIN9 */
+		DRXJ_16TO8(0x2020),	/* FIRTRAINGAIN10 */
+		DRXJ_16TO8(0x2020),	/* FIRTRAINGAIN11 */
+		DRXJ_16TO8(0x2020),	/* FIRTRAINGAIN12 */
+		DRXJ_16TO8(0x0808),	/* FIRRCA1GAIN1 */
+		DRXJ_16TO8(0x0808),	/* FIRRCA1GAIN2 */
+		DRXJ_16TO8(0x0808),	/* FIRRCA1GAIN3 */
+		DRXJ_16TO8(0x1010),	/* FIRRCA1GAIN4 */
+		DRXJ_16TO8(0x1010),	/* FIRRCA1GAIN5 */
+		DRXJ_16TO8(0x1010),	/* FIRRCA1GAIN6 */
+		DRXJ_16TO8(0x1010),	/* FIRRCA1GAIN7 */
+		DRXJ_16TO8(0x1010)	/* FIRRCA1GAIN8 */
+	};
+
+	const u8 vsb_ffe_leak_gain_ram1[] = {
+		DRXJ_16TO8(0x1010),	/* FIRRCA1GAIN9 */
+		DRXJ_16TO8(0x0808),	/* FIRRCA1GAIN10 */
+		DRXJ_16TO8(0x0808),	/* FIRRCA1GAIN11 */
+		DRXJ_16TO8(0x0808),	/* FIRRCA1GAIN12 */
+		DRXJ_16TO8(0x0808),	/* FIRRCA2GAIN1 */
+		DRXJ_16TO8(0x0808),	/* FIRRCA2GAIN2 */
+		DRXJ_16TO8(0x0808),	/* FIRRCA2GAIN3 */
+		DRXJ_16TO8(0x1010),	/* FIRRCA2GAIN4 */
+		DRXJ_16TO8(0x1010),	/* FIRRCA2GAIN5 */
+		DRXJ_16TO8(0x1010),	/* FIRRCA2GAIN6 */
+		DRXJ_16TO8(0x1010),	/* FIRRCA2GAIN7 */
+		DRXJ_16TO8(0x1010),	/* FIRRCA2GAIN8 */
+		DRXJ_16TO8(0x1010),	/* FIRRCA2GAIN9 */
+		DRXJ_16TO8(0x0808),	/* FIRRCA2GAIN10 */
+		DRXJ_16TO8(0x0808),	/* FIRRCA2GAIN11 */
+		DRXJ_16TO8(0x0808),	/* FIRRCA2GAIN12 */
+		DRXJ_16TO8(0x0303),	/* FIRDDM1GAIN1 */
+		DRXJ_16TO8(0x0303),	/* FIRDDM1GAIN2 */
+		DRXJ_16TO8(0x0303),	/* FIRDDM1GAIN3 */
+		DRXJ_16TO8(0x0606),	/* FIRDDM1GAIN4 */
+		DRXJ_16TO8(0x0606),	/* FIRDDM1GAIN5 */
+		DRXJ_16TO8(0x0606),	/* FIRDDM1GAIN6 */
+		DRXJ_16TO8(0x0606),	/* FIRDDM1GAIN7 */
+		DRXJ_16TO8(0x0606),	/* FIRDDM1GAIN8 */
+		DRXJ_16TO8(0x0606),	/* FIRDDM1GAIN9 */
+		DRXJ_16TO8(0x0303),	/* FIRDDM1GAIN10 */
+		DRXJ_16TO8(0x0303),	/* FIRDDM1GAIN11 */
+		DRXJ_16TO8(0x0303),	/* FIRDDM1GAIN12 */
+		DRXJ_16TO8(0x0303),	/* FIRDDM2GAIN1 */
+		DRXJ_16TO8(0x0303),	/* FIRDDM2GAIN2 */
+		DRXJ_16TO8(0x0303),	/* FIRDDM2GAIN3 */
+		DRXJ_16TO8(0x0505),	/* FIRDDM2GAIN4 */
+		DRXJ_16TO8(0x0505),	/* FIRDDM2GAIN5 */
+		DRXJ_16TO8(0x0505),	/* FIRDDM2GAIN6 */
+		DRXJ_16TO8(0x0505),	/* FIRDDM2GAIN7 */
+		DRXJ_16TO8(0x0505),	/* FIRDDM2GAIN8 */
+		DRXJ_16TO8(0x0505),	/* FIRDDM2GAIN9 */
+		DRXJ_16TO8(0x0303),	/* FIRDDM2GAIN10 */
+		DRXJ_16TO8(0x0303),	/* FIRDDM2GAIN11 */
+		DRXJ_16TO8(0x0303),	/* FIRDDM2GAIN12 */
+		DRXJ_16TO8(0x001f),	/* DFETRAINLKRATIO */
+		DRXJ_16TO8(0x01ff),	/* DFERCA1TRAINLKRATIO */
+		DRXJ_16TO8(0x01ff),	/* DFERCA1DATALKRATIO */
+		DRXJ_16TO8(0x004f),	/* DFERCA2TRAINLKRATIO */
+		DRXJ_16TO8(0x004f),	/* DFERCA2DATALKRATIO */
+		DRXJ_16TO8(0x01ff),	/* DFEDDM1TRAINLKRATIO */
+		DRXJ_16TO8(0x01ff),	/* DFEDDM1DATALKRATIO */
+		DRXJ_16TO8(0x0352),	/* DFEDDM2TRAINLKRATIO */
+		DRXJ_16TO8(0x0352),	/* DFEDDM2DATALKRATIO */
+		DRXJ_16TO8(0x0000),	/* DFETRAINGAIN */
+		DRXJ_16TO8(0x2020),	/* DFERCA1GAIN */
+		DRXJ_16TO8(0x1010),	/* DFERCA2GAIN */
+		DRXJ_16TO8(0x1818),	/* DFEDDM1GAIN */
+		DRXJ_16TO8(0x1212)	/* DFEDDM2GAIN */
+	};
+
+	dev_addr = demod->my_i2c_dev_addr;
+	rc = drxdap_fasi_write_block(dev_addr, VSB_SYSCTRL_RAM0_FFETRAINLKRATIO1__A, sizeof(vsb_ffe_leak_gain_ram0), ((u8 *)vsb_ffe_leak_gain_ram0), 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxdap_fasi_write_block(dev_addr, VSB_SYSCTRL_RAM1_FIRRCA1GAIN9__A, sizeof(vsb_ffe_leak_gain_ram1), ((u8 *)vsb_ffe_leak_gain_ram1), 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/**
+* \fn int set_vsb()
+* \brief Set 8VSB demod.
+* \param demod instance of demodulator.
+* \return int.
+*
+*/
+static int set_vsb(struct drx_demod_instance *demod)
+{
+	struct i2c_device_addr *dev_addr = NULL;
+	int rc;
+	struct drx_common_attr *common_attr = NULL;
+	struct drxjscu_cmd cmd_scu;
+	struct drxj_data *ext_attr = NULL;
+	u16 cmd_result = 0;
+	u16 cmd_param = 0;
+	const u8 vsb_taps_re[] = {
+		DRXJ_16TO8(-2),	/* re0  */
+		DRXJ_16TO8(4),	/* re1  */
+		DRXJ_16TO8(1),	/* re2  */
+		DRXJ_16TO8(-4),	/* re3  */
+		DRXJ_16TO8(1),	/* re4  */
+		DRXJ_16TO8(4),	/* re5  */
+		DRXJ_16TO8(-3),	/* re6  */
+		DRXJ_16TO8(-3),	/* re7  */
+		DRXJ_16TO8(6),	/* re8  */
+		DRXJ_16TO8(1),	/* re9  */
+		DRXJ_16TO8(-9),	/* re10 */
+		DRXJ_16TO8(3),	/* re11 */
+		DRXJ_16TO8(12),	/* re12 */
+		DRXJ_16TO8(-9),	/* re13 */
+		DRXJ_16TO8(-15),	/* re14 */
+		DRXJ_16TO8(17),	/* re15 */
+		DRXJ_16TO8(19),	/* re16 */
+		DRXJ_16TO8(-29),	/* re17 */
+		DRXJ_16TO8(-22),	/* re18 */
+		DRXJ_16TO8(45),	/* re19 */
+		DRXJ_16TO8(25),	/* re20 */
+		DRXJ_16TO8(-70),	/* re21 */
+		DRXJ_16TO8(-28),	/* re22 */
+		DRXJ_16TO8(111),	/* re23 */
+		DRXJ_16TO8(30),	/* re24 */
+		DRXJ_16TO8(-201),	/* re25 */
+		DRXJ_16TO8(-31),	/* re26 */
+		DRXJ_16TO8(629)	/* re27 */
+	};
+
+	dev_addr = demod->my_i2c_dev_addr;
+	common_attr = (struct drx_common_attr *) demod->my_common_attr;
+	ext_attr = (struct drxj_data *) demod->my_ext_attr;
+
+	/* stop all comm_exec */
+	rc = drxj_dap_write_reg16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_STOP, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	/* reset demodulator */
+	cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB
+	    | SCU_RAM_COMMAND_CMD_DEMOD_RESET;
+	cmd_scu.parameter_len = 0;
+	cmd_scu.result_len = 1;
+	cmd_scu.parameter = NULL;
+	cmd_scu.result = &cmd_result;
+	rc = scu_command(dev_addr, &cmd_scu);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	rc = drxj_dap_write_reg16(dev_addr, IQM_AF_DCF_BYPASS__A, 1, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_FS_ADJ_SEL__A, IQM_FS_ADJ_SEL_B_VSB, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_RC_ADJ_SEL__A, IQM_RC_ADJ_SEL_B_VSB, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	ext_attr->iqm_rc_rate_ofs = 0x00AD0D79;
+	rc = drxdap_fasi_write_reg32(dev_addr, IQM_RC_RATE_OFS_LO__A, ext_attr->iqm_rc_rate_ofs, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CFAGC_GAINSHIFT__A, 4, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CYGN1TRK__A, 1, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	rc = drxj_dap_write_reg16(dev_addr, IQM_RC_CROUT_ENA__A, 1, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_RC_STRETCH__A, 28, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_RT_ACTIVE__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_CF_SYMMETRIC__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_CF_MIDTAP__A, 3, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_CF_OUT_ENA__A, IQM_CF_OUT_ENA_VSB__M, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_CF_SCALE__A, 1393, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_CF_SCALE_SH__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_CF_POW_MEAS_LEN__A, 1, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_RE0__A, sizeof(vsb_taps_re), ((u8 *)vsb_taps_re), 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_IM0__A, sizeof(vsb_taps_re), ((u8 *)vsb_taps_re), 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_BNTHRESH__A, 330, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}	/* set higher threshold */
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CLPLASTNUM__A, 90, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}	/* burst detection on   */
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_SNRTH_RCA1__A, 0x0042, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}	/* drop thresholds by 1 dB */
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_SNRTH_RCA2__A, 0x0053, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}	/* drop thresholds by 2 dB */
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_EQCTRL__A, 0x1, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}	/* cma on               */
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_GPIO__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}	/* GPIO               */
+
+	/* Initialize the FEC Subsystem */
+	rc = drxj_dap_write_reg16(dev_addr, FEC_TOP_ANNEX__A, FEC_TOP_ANNEX_D, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	{
+		u16 fec_oc_snc_mode = 0;
+		rc = drxj_dap_read_reg16(dev_addr, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		/* output data even when not locked */
+		rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_MODE__A, fec_oc_snc_mode | FEC_OC_SNC_MODE_UNLOCK_ENABLE__M, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+	}
+
+	/* set clip */
+	rc = drxj_dap_write_reg16(dev_addr, IQM_AF_CLP_LEN__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_AF_CLP_TH__A, 470, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, IQM_AF_SNS_LEN__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_SNRTH_PT__A, 0xD4, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	/* no transparent, no A&C framing; parity is set in mpegoutput */
+	{
+		u16 fec_oc_reg_mode = 0;
+		rc = drxj_dap_read_reg16(dev_addr, FEC_OC_MODE__A, &fec_oc_reg_mode, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, FEC_OC_MODE__A, fec_oc_reg_mode & (~(FEC_OC_MODE_TRANSPARENT__M | FEC_OC_MODE_CLEAR__M | FEC_OC_MODE_RETAIN_FRAMING__M)), 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+	}
+
+	rc = drxj_dap_write_reg16(dev_addr, FEC_DI_TIMEOUT_LO__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}	/* timeout counter for restarting */
+	rc = drxj_dap_write_reg16(dev_addr, FEC_DI_TIMEOUT_HI__A, 3, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, FEC_RS_MODE__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}	/* bypass disabled */
+	/* initialize RS packet error measurement parameters */
+	rc = drxj_dap_write_reg16(dev_addr, FEC_RS_MEASUREMENT_PERIOD__A, FEC_RS_MEASUREMENT_PERIOD, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, FEC_RS_MEASUREMENT_PRESCALE__A, FEC_RS_MEASUREMENT_PRESCALE, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	/* init measurement period of MER/SER */
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_MEASUREMENT_PERIOD__A, VSB_TOP_MEASUREMENT_PERIOD, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxdap_fasi_write_reg32(dev_addr, SCU_RAM_FEC_ACCUM_CW_CORRECTED_LO__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_FEC_MEAS_COUNT__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CKGN1TRK__A, 128, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	/* B-Input to ADC, PGA+filter in standby */
+	if (!ext_attr->has_lna) {
+		rc = drxj_dap_write_reg16(dev_addr, IQM_AF_AMUX__A, 0x02, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+	}
+
+	/* turn on IQMAF. It has to be in front of setAgc**() */
+	rc = set_iqm_af(demod, true);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = adc_synchronization(demod);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	rc = init_agc(demod);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = set_agc_if(demod, &(ext_attr->vsb_if_agc_cfg), false);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = set_agc_rf(demod, &(ext_attr->vsb_rf_agc_cfg), false);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	{
+		/* TODO fix this, store a struct drxj_cfg_afe_gain structure in struct drxj_data instead
+		   of only the gain */
+		struct drxj_cfg_afe_gain vsb_pga_cfg = { DRX_STANDARD_8VSB, 0 };
+
+		vsb_pga_cfg.gain = ext_attr->vsb_pga_cfg;
+		rc = ctrl_set_cfg_afe_gain(demod, &vsb_pga_cfg);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+	}
+	rc = ctrl_set_cfg_pre_saw(demod, &(ext_attr->vsb_pre_saw_cfg));
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	/* Mpeg output has to be in front of FEC active */
+	rc = set_mpegtei_handling(demod);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = bit_reverse_mpeg_output(demod);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = set_mpeg_start_width(demod);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	{
+		/* TODO: move to set_standard after hardware reset value problem is solved */
+		/* Configure initial MPEG output */
+		struct drx_cfg_mpeg_output cfg_mpeg_output;
+
+		memcpy(&cfg_mpeg_output, &common_attr->mpeg_cfg, sizeof(cfg_mpeg_output));
+		cfg_mpeg_output.enable_mpeg_output = true;
+
+		rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+	}
+
+	/* TBD: what parameters should be set */
+	cmd_param = 0x00;	/* Default mode AGC on, etc */
+	cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB
+	    | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM;
+	cmd_scu.parameter_len = 1;
+	cmd_scu.result_len = 1;
+	cmd_scu.parameter = &cmd_param;
+	cmd_scu.result = &cmd_result;
+	rc = scu_command(dev_addr, &cmd_scu);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_BEAGC_GAINSHIFT__A, 0x0004, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_SNRTH_PT__A, 0x00D2, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_SYSSMTRNCTRL__A, VSB_TOP_SYSSMTRNCTRL__PRE | VSB_TOP_SYSSMTRNCTRL_NCOTIMEOUTCNTEN__M, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_BEDETCTRL__A, 0x142, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_LBAGCREFLVL__A, 640, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CYGN1ACQ__A, 4, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CYGN1TRK__A, 2, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CYGN2TRK__A, 3, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	/* start demodulator */
+	cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB
+	    | SCU_RAM_COMMAND_CMD_DEMOD_START;
+	cmd_scu.parameter_len = 0;
+	cmd_scu.result_len = 1;
+	cmd_scu.parameter = NULL;
+	cmd_scu.result = &cmd_result;
+	rc = scu_command(dev_addr, &cmd_scu);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	rc = drxj_dap_write_reg16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_ACTIVE, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_ACTIVE, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/**
+* \fn static short get_vsb_post_rs_pck_err(struct i2c_device_addr *dev_addr, u16 *PckErrs)
+* \brief Get the values of packet error in 8VSB mode
+* \return Error code
+*/
+static int get_vsb_post_rs_pck_err(struct i2c_device_addr *dev_addr,
+				   u32 *pck_errs, u32 *pck_count)
+{
+	int rc;
+	u16 data = 0;
+	u16 period = 0;
+	u16 prescale = 0;
+	u16 packet_errors_mant = 0;
+	u16 packet_errors_exp = 0;
+
+	rc = drxj_dap_read_reg16(dev_addr, FEC_RS_NR_FAILURES__A, &data, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	packet_errors_mant = data & FEC_RS_NR_FAILURES_FIXED_MANT__M;
+	packet_errors_exp = (data & FEC_RS_NR_FAILURES_EXP__M)
+	    >> FEC_RS_NR_FAILURES_EXP__B;
+	period = FEC_RS_MEASUREMENT_PERIOD;
+	prescale = FEC_RS_MEASUREMENT_PRESCALE;
+	/* packet error rate = (error packet number) per second */
+	/* 77.3 us is time for per packet */
+	if (period * prescale == 0) {
+		pr_err("error: period and/or prescale is zero!\n");
+		return -EIO;
+	}
+	*pck_errs = packet_errors_mant * (1 << packet_errors_exp);
+	*pck_count = period * prescale * 77;
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/**
+* \fn static short GetVSBBer(struct i2c_device_addr *dev_addr, u32 *ber)
+* \brief Get the values of ber in VSB mode
+* \return Error code
+*/
+static int get_vs_bpost_viterbi_ber(struct i2c_device_addr *dev_addr,
+				    u32 *ber, u32 *cnt)
+{
+	int rc;
+	u16 data = 0;
+	u16 period = 0;
+	u16 prescale = 0;
+	u16 bit_errors_mant = 0;
+	u16 bit_errors_exp = 0;
+
+	rc = drxj_dap_read_reg16(dev_addr, FEC_RS_NR_BIT_ERRORS__A, &data, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	period = FEC_RS_MEASUREMENT_PERIOD;
+	prescale = FEC_RS_MEASUREMENT_PRESCALE;
+
+	bit_errors_mant = data & FEC_RS_NR_BIT_ERRORS_FIXED_MANT__M;
+	bit_errors_exp = (data & FEC_RS_NR_BIT_ERRORS_EXP__M)
+	    >> FEC_RS_NR_BIT_ERRORS_EXP__B;
+
+	*cnt = period * prescale * 207 * ((bit_errors_exp > 2) ? 1 : 8);
+
+	if (((bit_errors_mant << bit_errors_exp) >> 3) > 68700)
+		*ber = (*cnt) * 26570;
+	else {
+		if (period * prescale == 0) {
+			pr_err("error: period and/or prescale is zero!\n");
+			return -EIO;
+		}
+		*ber = bit_errors_mant << ((bit_errors_exp > 2) ?
+			(bit_errors_exp - 3) : bit_errors_exp);
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/**
+* \fn static short get_vs_bpre_viterbi_ber(struct i2c_device_addr *dev_addr, u32 *ber)
+* \brief Get the values of ber in VSB mode
+* \return Error code
+*/
+static int get_vs_bpre_viterbi_ber(struct i2c_device_addr *dev_addr,
+				   u32 *ber, u32 *cnt)
+{
+	u16 data = 0;
+	int rc;
+
+	rc = drxj_dap_read_reg16(dev_addr, VSB_TOP_NR_SYM_ERRS__A, &data, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		return -EIO;
+	}
+	*ber = data;
+	*cnt = VSB_TOP_MEASUREMENT_PERIOD * SYMBOLS_PER_SEGMENT;
+
+	return 0;
+}
+
+/**
+* \fn static int get_vsbmer(struct i2c_device_addr *dev_addr, u16 *mer)
+* \brief Get the values of MER
+* \return Error code
+*/
+static int get_vsbmer(struct i2c_device_addr *dev_addr, u16 *mer)
+{
+	int rc;
+	u16 data_hi = 0;
+
+	rc = drxj_dap_read_reg16(dev_addr, VSB_TOP_ERR_ENERGY_H__A, &data_hi, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	*mer =
+	    (u16) (log1_times100(21504) - log1_times100((data_hi << 6) / 52));
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+
+/*============================================================================*/
+/*==                     END 8VSB DATAPATH FUNCTIONS                        ==*/
+/*============================================================================*/
+
+/*============================================================================*/
+/*============================================================================*/
+/*==                       QAM DATAPATH FUNCTIONS                           ==*/
+/*============================================================================*/
+/*============================================================================*/
+
+/**
+* \fn int power_down_qam ()
+* \brief Powr down QAM related blocks.
+* \param demod instance of demodulator.
+* \param channel pointer to channel data.
+* \return int.
+*/
+static int power_down_qam(struct drx_demod_instance *demod, bool primary)
+{
+	struct drxjscu_cmd cmd_scu = { /* command      */ 0,
+		/* parameter_len */ 0,
+		/* result_len    */ 0,
+		/* *parameter   */ NULL,
+		/* *result      */ NULL
+	};
+	int rc;
+	struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
+	struct drx_cfg_mpeg_output cfg_mpeg_output;
+	struct drx_common_attr *common_attr = demod->my_common_attr;
+	u16 cmd_result = 0;
+
+	/*
+	   STOP demodulator
+	   resets IQM, QAM and FEC HW blocks
+	 */
+	/* stop all comm_exec */
+	rc = drxj_dap_write_reg16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
+	    SCU_RAM_COMMAND_CMD_DEMOD_STOP;
+	cmd_scu.parameter_len = 0;
+	cmd_scu.result_len = 1;
+	cmd_scu.parameter = NULL;
+	cmd_scu.result = &cmd_result;
+	rc = scu_command(dev_addr, &cmd_scu);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	if (primary) {
+		rc = drxj_dap_write_reg16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = set_iqm_af(demod, false);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+	} else {
+		rc = drxj_dap_write_reg16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+	}
+
+	memcpy(&cfg_mpeg_output, &common_attr->mpeg_cfg, sizeof(cfg_mpeg_output));
+	cfg_mpeg_output.enable_mpeg_output = false;
+
+	rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/*============================================================================*/
+
+/**
+* \fn int set_qam_measurement ()
+* \brief Setup of the QAM Measuremnt intervals for signal quality
+* \param demod instance of demod.
+* \param constellation current constellation.
+* \return int.
+*
+*  NOTE:
+*  Take into account that for certain settings the errorcounters can overflow.
+*  The implementation does not check this.
+*
+*  TODO: overriding the ext_attr->fec_bits_desired by constellation dependent
+*  constants to get a measurement period of approx. 1 sec. Remove fec_bits_desired
+*  field ?
+*
+*/
+#ifndef DRXJ_VSB_ONLY
+static int
+set_qam_measurement(struct drx_demod_instance *demod,
+		    enum drx_modulation constellation, u32 symbol_rate)
+{
+	struct i2c_device_addr *dev_addr = NULL;	/* device address for I2C writes */
+	struct drxj_data *ext_attr = NULL;	/* Global data container for DRXJ specif data */
+	int rc;
+	u32 fec_bits_desired = 0;	/* BER accounting period */
+	u16 fec_rs_plen = 0;	/* defines RS BER measurement period */
+	u16 fec_rs_prescale = 0;	/* ReedSolomon Measurement Prescale */
+	u32 fec_rs_period = 0;	/* Value for corresponding I2C register */
+	u32 fec_rs_bit_cnt = 0;	/* Actual precise amount of bits */
+	u32 fec_oc_snc_fail_period = 0;	/* Value for corresponding I2C register */
+	u32 qam_vd_period = 0;	/* Value for corresponding I2C register */
+	u32 qam_vd_bit_cnt = 0;	/* Actual precise amount of bits */
+	u16 fec_vd_plen = 0;	/* no of trellis symbols: VD SER measur period */
+	u16 qam_vd_prescale = 0;	/* Viterbi Measurement Prescale */
+
+	dev_addr = demod->my_i2c_dev_addr;
+	ext_attr = (struct drxj_data *) demod->my_ext_attr;
+
+	fec_bits_desired = ext_attr->fec_bits_desired;
+	fec_rs_prescale = ext_attr->fec_rs_prescale;
+
+	switch (constellation) {
+	case DRX_CONSTELLATION_QAM16:
+		fec_bits_desired = 4 * symbol_rate;
+		break;
+	case DRX_CONSTELLATION_QAM32:
+		fec_bits_desired = 5 * symbol_rate;
+		break;
+	case DRX_CONSTELLATION_QAM64:
+		fec_bits_desired = 6 * symbol_rate;
+		break;
+	case DRX_CONSTELLATION_QAM128:
+		fec_bits_desired = 7 * symbol_rate;
+		break;
+	case DRX_CONSTELLATION_QAM256:
+		fec_bits_desired = 8 * symbol_rate;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Parameters for Reed-Solomon Decoder */
+	/* fecrs_period = (int)ceil(FEC_BITS_DESIRED/(fecrs_prescale*plen)) */
+	/* rs_bit_cnt   = fecrs_period*fecrs_prescale*plen                  */
+	/*     result is within 32 bit arithmetic ->                        */
+	/*     no need for mult or frac functions                           */
+
+	/* TODO: use constant instead of calculation and remove the fec_rs_plen in ext_attr */
+	switch (ext_attr->standard) {
+	case DRX_STANDARD_ITU_A:
+	case DRX_STANDARD_ITU_C:
+		fec_rs_plen = 204 * 8;
+		break;
+	case DRX_STANDARD_ITU_B:
+		fec_rs_plen = 128 * 7;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ext_attr->fec_rs_plen = fec_rs_plen;	/* for getSigQual */
+	fec_rs_bit_cnt = fec_rs_prescale * fec_rs_plen;	/* temp storage   */
+	if (fec_rs_bit_cnt == 0) {
+		pr_err("error: fec_rs_bit_cnt is zero!\n");
+		return -EIO;
+	}
+	fec_rs_period = fec_bits_desired / fec_rs_bit_cnt + 1;	/* ceil */
+	if (ext_attr->standard != DRX_STANDARD_ITU_B)
+		fec_oc_snc_fail_period = fec_rs_period;
+
+	/* limit to max 16 bit value (I2C register width) if needed */
+	if (fec_rs_period > 0xFFFF)
+		fec_rs_period = 0xFFFF;
+
+	/* write corresponding registers */
+	switch (ext_attr->standard) {
+	case DRX_STANDARD_ITU_A:
+	case DRX_STANDARD_ITU_C:
+		break;
+	case DRX_STANDARD_ITU_B:
+		switch (constellation) {
+		case DRX_CONSTELLATION_QAM64:
+			fec_rs_period = 31581;
+			fec_oc_snc_fail_period = 17932;
+			break;
+		case DRX_CONSTELLATION_QAM256:
+			fec_rs_period = 45446;
+			fec_oc_snc_fail_period = 25805;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_FAIL_PERIOD__A, (u16)fec_oc_snc_fail_period, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, FEC_RS_MEASUREMENT_PERIOD__A, (u16)fec_rs_period, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, FEC_RS_MEASUREMENT_PRESCALE__A, fec_rs_prescale, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	ext_attr->fec_rs_period = (u16) fec_rs_period;
+	ext_attr->fec_rs_prescale = fec_rs_prescale;
+	rc = drxdap_fasi_write_reg32(dev_addr, SCU_RAM_FEC_ACCUM_CW_CORRECTED_LO__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_FEC_MEAS_COUNT__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	if (ext_attr->standard == DRX_STANDARD_ITU_B) {
+		/* Parameters for Viterbi Decoder */
+		/* qamvd_period = (int)ceil(FEC_BITS_DESIRED/                      */
+		/*                    (qamvd_prescale*plen*(qam_constellation+1))) */
+		/* vd_bit_cnt   = qamvd_period*qamvd_prescale*plen                 */
+		/*     result is within 32 bit arithmetic ->                       */
+		/*     no need for mult or frac functions                          */
+
+		/* a(8 bit) * b(8 bit) = 16 bit result => mult32 not needed */
+		fec_vd_plen = ext_attr->fec_vd_plen;
+		qam_vd_prescale = ext_attr->qam_vd_prescale;
+		qam_vd_bit_cnt = qam_vd_prescale * fec_vd_plen;	/* temp storage */
+
+		switch (constellation) {
+		case DRX_CONSTELLATION_QAM64:
+			/* a(16 bit) * b(4 bit) = 20 bit result => mult32 not needed */
+			qam_vd_period =
+			    qam_vd_bit_cnt * (QAM_TOP_CONSTELLATION_QAM64 + 1)
+			    * (QAM_TOP_CONSTELLATION_QAM64 + 1);
+			break;
+		case DRX_CONSTELLATION_QAM256:
+			/* a(16 bit) * b(5 bit) = 21 bit result => mult32 not needed */
+			qam_vd_period =
+			    qam_vd_bit_cnt * (QAM_TOP_CONSTELLATION_QAM256 + 1)
+			    * (QAM_TOP_CONSTELLATION_QAM256 + 1);
+			break;
+		default:
+			return -EINVAL;
+		}
+		if (qam_vd_period == 0) {
+			pr_err("error: qam_vd_period is zero!\n");
+			return -EIO;
+		}
+		qam_vd_period = fec_bits_desired / qam_vd_period;
+		/* limit to max 16 bit value (I2C register width) if needed */
+		if (qam_vd_period > 0xFFFF)
+			qam_vd_period = 0xFFFF;
+
+		/* a(16 bit) * b(16 bit) = 32 bit result => mult32 not needed */
+		qam_vd_bit_cnt *= qam_vd_period;
+
+		rc = drxj_dap_write_reg16(dev_addr, QAM_VD_MEASUREMENT_PERIOD__A, (u16)qam_vd_period, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		rc = drxj_dap_write_reg16(dev_addr, QAM_VD_MEASUREMENT_PRESCALE__A, qam_vd_prescale, 0);
+		if (rc != 0) {
+			pr_err("error %d\n", rc);
+			goto rw_error;
+		}
+		ext_attr->qam_vd_period = (u16) qam_vd_period;
+		ext_attr->qam_vd_prescale = qam_vd_prescale;
+	}
+
+	return 0;
+rw_error:
+	return -EIO;
+}
+
+/*============================================================================*/
+
+/**
+* \fn int set_qam16 ()
+* \brief QAM16 specific setup
+* \param demod instance of demod.
+* \return int.
+*/
+static int set_qam16(struct drx_demod_instance *demod)
+{
+	struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
+	int rc;
+	const u8 qam_dq_qual_fun[] = {
+		DRXJ_16TO8(2),	/* fun0  */
+		DRXJ_16TO8(2),	/* fun1  */
+		DRXJ_16TO8(2),	/* fun2  */
+		DRXJ_16TO8(2),	/* fun3  */
+		DRXJ_16TO8(3),	/* fun4  */
+		DRXJ_16TO8(3),	/* fun5  */
+	};
+	const u8 qam_eq_cma_rad[] = {
+		DRXJ_16TO8(13517),	/* RAD0  */
+		DRXJ_16TO8(13517),	/* RAD1  */
+		DRXJ_16TO8(13517),	/* RAD2  */
+		DRXJ_16TO8(13517),	/* RAD3  */
+		DRXJ_16TO8(13517),	/* RAD4  */
+		DRXJ_16TO8(13517),	/* RAD5  */
+	};
+
+	rc = drxdap_fasi_write_block(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun), ((u8 *)qam_dq_qual_fun), 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxdap_fasi_write_block(dev_addr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qam_eq_cma_rad), ((u8 *)qam_eq_cma_rad), 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 140, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 50, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 120, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 230, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 95, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 105, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 56, 0);
+	if (rc != 0) {
+		pr_err("error %d\n", rc);
+		goto rw_error;
+	}
+	rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3, 0);
+	if (rc != 0) {
+		pr