Explorar o código

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

Pull media update from Mauro Carvalho Chehab:

 - OF documentation and patches at core and drivers, to be used by for
   embedded media systems

 - some I2C drivers used on go7007 were rewritten/promoted from staging:
   sony-btf-mpx, tw2804, tw9903, tw9906, wis-ov7640, wis-uda1342

 - add fimc-is driver (Exynos)

 - add a new radio driver: radio-si476x

 - add a two new tuners: r820t and tuner_it913x

 - split camera code on em28xx driver and add more models

 - the cypress firmware load is used outside dvb usb drivers.  So, move
   it to a common directory to make easier to re-use it

 - siano media driver updated to work with sms2270 devices

 - several work done in order to promote go7007 and solo6x1x out of
   staging (still, there are some pending issues)

 - several API compliance fixes at v4l2 drivers that don't behave as
   expected

 - as usual, lots of driver fixes, improvements, cleanups and new device
   addition at the existing drivers.

* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (831 commits)
  [media] cx88: make core less verbose
  [media] em28xx: fix oops at em28xx_dvb_bus_ctrl()
  [media] s5c73m3: fix indentation of the help section in Kconfig
  [media] cx25821-alsa: get rid of a __must_check warning
  [media] cx25821-video: declare cx25821_vidioc_s_std as static
  [media] cx25821-video: remove maxw from cx25821_vidioc_try_fmt_vid_cap
  [media] r820t: Remove a warning for an unused value
  [media] dib0090: Fix a warning at dib0090_set_EFUSE
  [media] dib8000: fix a warning
  [media] dib8000: Fix sub-channel range
  [media] dib8000: store dtv_property_cache in a temp var
  [media] dib8000: warning fix: declare internal functions as static
  [media] r820t: quiet gcc warning on n_ring
  [media] r820t: memory leak in release()
  [media] r820t: precendence bug in r820t_xtal_check()
  [media] videodev2.h: Remove the unused old V4L1 buffer types
  [media] anysee: Grammar s/report the/report to/
  [media] anysee: Initialize ret = 0 in anysee_frontend_attach()
  [media] media: videobuf2: fix the length check for mmap
  [media] em28xx: save isoc endpoint number for DVB only if endpoint has alt settings with xMaxPacketSize != 0
  ...
Linus Torvalds %!s(int64=12) %!d(string=hai) anos
pai
achega
240c3c3424
Modificáronse 100 ficheiros con 9616 adicións e 4030 borrados
  1. 22 24
      Documentation/DocBook/media/dvb/dvbproperty.xml
  2. 0 14
      Documentation/DocBook/media/v4l/common.xml
  3. 22 2
      Documentation/DocBook/media/v4l/compat.xml
  4. 86 1
      Documentation/DocBook/media/v4l/controls.xml
  5. 6 0
      Documentation/DocBook/media/v4l/io.xml
  6. 10 0
      Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml
  7. 196 10
      Documentation/DocBook/media/v4l/subdev-formats.xml
  8. 14 5
      Documentation/DocBook/media/v4l/v4l2.xml
  9. 7 2
      Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-ident.xml
  10. 223 0
      Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml
  11. 19 10
      Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml
  12. 0 240
      Documentation/DocBook/media/v4l/vidioc-enum-dv-presets.xml
  13. 0 5
      Documentation/DocBook/media/v4l/vidioc-enuminput.xml
  14. 0 5
      Documentation/DocBook/media/v4l/vidioc-enumoutput.xml
  15. 0 113
      Documentation/DocBook/media/v4l/vidioc-g-dv-preset.xml
  16. 9 0
      Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
  17. 0 78
      Documentation/DocBook/media/v4l/vidioc-query-dv-preset.xml
  18. 1 0
      Documentation/DocBook/media_api.tmpl
  19. 14 0
      Documentation/devicetree/bindings/media/exynos-fimc-lite.txt
  20. 49 0
      Documentation/devicetree/bindings/media/exynos4-fimc-is.txt
  21. 197 0
      Documentation/devicetree/bindings/media/samsung-fimc.txt
  22. 81 0
      Documentation/devicetree/bindings/media/samsung-mipi-csis.txt
  23. 228 0
      Documentation/devicetree/bindings/media/video-interfaces.txt
  24. 2 1
      Documentation/video4linux/CARDLIST.em28xx
  25. 3 0
      Documentation/video4linux/CARDLIST.tuner
  26. 187 0
      Documentation/video4linux/si476x.txt
  27. 83 17
      MAINTAINERS
  28. 69 2
      arch/arm/mach-davinci/board-dm355-evm.c
  29. 164 2
      arch/arm/mach-davinci/board-dm365-evm.c
  30. 4 4
      arch/arm/mach-davinci/board-dm644x-evm.c
  31. 1 1
      arch/arm/mach-davinci/board-dm646x-evm.c
  32. 9 2
      arch/arm/mach-davinci/davinci.h
  33. 164 10
      arch/arm/mach-davinci/dm355.c
  34. 178 17
      arch/arm/mach-davinci/dm365.c
  35. 3 8
      arch/arm/mach-davinci/dm644x.c
  36. 1 1
      arch/arm/mach-davinci/pm_domain.c
  37. 4 4
      arch/blackfin/mach-bf609/boards/ezkit.c
  38. 4 0
      drivers/media/common/Kconfig
  39. 1 0
      drivers/media/common/Makefile
  40. 2 2
      drivers/media/common/b2c2/flexcop-fe-tuner.c
  41. 40 42
      drivers/media/common/cypress_firmware.c
  42. 3 6
      drivers/media/common/cypress_firmware.h
  43. 2 2
      drivers/media/common/saa7146/saa7146_video.c
  44. 12 0
      drivers/media/common/siano/Kconfig
  45. 5 0
      drivers/media/common/siano/Makefile
  46. 81 34
      drivers/media/common/siano/sms-cards.c
  47. 14 0
      drivers/media/common/siano/sms-cards.h
  48. 930 368
      drivers/media/common/siano/smscoreapi.c
  49. 712 295
      drivers/media/common/siano/smscoreapi.h
  50. 551 0
      drivers/media/common/siano/smsdvb-debugfs.c
  51. 1230 0
      drivers/media/common/siano/smsdvb-main.c
  52. 0 1078
      drivers/media/common/siano/smsdvb.c
  53. 130 0
      drivers/media/common/siano/smsdvb.h
  54. 22 22
      drivers/media/common/siano/smsendian.c
  55. 0 1
      drivers/media/common/siano/smsir.h
  56. 0 39
      drivers/media/dvb-core/demux.h
  57. 3 2
      drivers/media/dvb-core/dmxdev.c
  58. 1 2
      drivers/media/dvb-core/dvb-usb-ids.h
  59. 16 14
      drivers/media/dvb-core/dvb_demux.c
  60. 2 2
      drivers/media/dvb-core/dvb_demux.h
  61. 184 149
      drivers/media/dvb-core/dvb_frontend.c
  62. 2 2
      drivers/media/dvb-core/dvb_frontend.h
  63. 1 1
      drivers/media/dvb-core/dvb_net.c
  64. 1 1
      drivers/media/dvb-frontends/Kconfig
  65. 3 2
      drivers/media/dvb-frontends/a8293.h
  66. 2 2
      drivers/media/dvb-frontends/af9013.h
  67. 114 24
      drivers/media/dvb-frontends/af9033.c
  68. 18 2
      drivers/media/dvb-frontends/af9033.h
  69. 1505 1
      drivers/media/dvb-frontends/af9033_priv.h
  70. 2 2
      drivers/media/dvb-frontends/atbm8830.h
  71. 2 2
      drivers/media/dvb-frontends/au8522.h
  72. 38 87
      drivers/media/dvb-frontends/au8522_decoder.c
  73. 2 4
      drivers/media/dvb-frontends/au8522_priv.h
  74. 2 2
      drivers/media/dvb-frontends/cx22702.h
  75. 3 2
      drivers/media/dvb-frontends/cx24113.h
  76. 2 2
      drivers/media/dvb-frontends/cx24116.h
  77. 7 21
      drivers/media/dvb-frontends/cx24123.c
  78. 2 2
      drivers/media/dvb-frontends/cx24123.h
  79. 2 2
      drivers/media/dvb-frontends/cxd2820r.h
  80. 2 1
      drivers/media/dvb-frontends/cxd2820r_core.c
  81. 17 0
      drivers/media/dvb-frontends/cxd2820r_t2.c
  82. 208 226
      drivers/media/dvb-frontends/dib0090.c
  83. 3 2
      drivers/media/dvb-frontends/dib3000mc.h
  84. 3 2
      drivers/media/dvb-frontends/dib7000m.h
  85. 16 1
      drivers/media/dvb-frontends/dib7000p.c
  86. 10 2
      drivers/media/dvb-frontends/dib7000p.h
  87. 1340 928
      drivers/media/dvb-frontends/dib8000.c
  88. 4 2
      drivers/media/dvb-frontends/dib8000.h
  89. 2 1
      drivers/media/dvb-frontends/dibx000_common.h
  90. 2 2
      drivers/media/dvb-frontends/drxd.h
  91. 2 2
      drivers/media/dvb-frontends/drxk.h
  92. 256 53
      drivers/media/dvb-frontends/drxk_hard.c
  93. 2 0
      drivers/media/dvb-frontends/drxk_hard.h
  94. 3 0
      drivers/media/dvb-frontends/drxk_map.h
  95. 2 2
      drivers/media/dvb-frontends/ds3000.h
  96. 2 2
      drivers/media/dvb-frontends/dvb_dummy_fe.h
  97. 2 2
      drivers/media/dvb-frontends/ec100.h
  98. 2 2
      drivers/media/dvb-frontends/hd29l2.h
  99. 27 1
      drivers/media/dvb-frontends/isl6421.c
  100. 2 2
      drivers/media/dvb-frontends/isl6421.h

+ 22 - 24
Documentation/DocBook/media/dvb/dvbproperty.xml

@@ -903,14 +903,12 @@ enum fe_interleaving {
 			<constant>svalue</constant> is for signed values of the measure (dB measures)
 			and <constant>uvalue</constant> is for unsigned values (counters, relative scale)</para></listitem>
 		<listitem><para><constant>scale</constant> - Scale for the value. It can be:</para>
-			<section id = "fecap-scale-params">
-			<itemizedlist mark='bullet'>
+			<itemizedlist mark='bullet' id="fecap-scale-params">
 				<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - The parameter is supported by the frontend, but it was not possible to collect it (could be a transitory or permanent condition)</para></listitem>
 				<listitem><para><constant>FE_SCALE_DECIBEL</constant> - parameter is a signed value, measured in 1/1000 dB</para></listitem>
 				<listitem><para><constant>FE_SCALE_RELATIVE</constant> - parameter is a unsigned value, where 0 means 0% and 65535 means 100%.</para></listitem>
 				<listitem><para><constant>FE_SCALE_COUNTER</constant> - parameter is a unsigned value that counts the occurrence of an event, like bit error, block error, or lapsed time.</para></listitem>
 			</itemizedlist>
-			</section>
 		</listitem>
 	</itemizedlist>
 	<section id="DTV-STAT-SIGNAL-STRENGTH">
@@ -918,9 +916,9 @@ enum fe_interleaving {
 		<para>Indicates the signal strength level at the analog part of the tuner or of the demod.</para>
 		<para>Possible scales for this metric are:</para>
 		<itemizedlist mark='bullet'>
-			<listitem><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</listitem>
-			<listitem><constant>FE_SCALE_DECIBEL</constant> - signal strength is in 0.0001 dBm units, power measured in miliwatts. This value is generally negative.</listitem>
-			<listitem><constant>FE_SCALE_RELATIVE</constant> - The frontend provides a 0% to 100% measurement for power (actually, 0 to 65535).</listitem>
+			<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
+			<listitem><para><constant>FE_SCALE_DECIBEL</constant> - signal strength is in 0.0001 dBm units, power measured in miliwatts. This value is generally negative.</para></listitem>
+			<listitem><para><constant>FE_SCALE_RELATIVE</constant> - The frontend provides a 0% to 100% measurement for power (actually, 0 to 65535).</para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="DTV-STAT-CNR">
@@ -928,9 +926,9 @@ enum fe_interleaving {
 		<para>Indicates the Signal to Noise ratio for the main carrier.</para>
 		<para>Possible scales for this metric are:</para>
 		<itemizedlist mark='bullet'>
-			<listitem><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</listitem>
-			<listitem><constant>FE_SCALE_DECIBEL</constant> - Signal/Noise ratio is in 0.0001 dB units.</listitem>
-			<listitem><constant>FE_SCALE_RELATIVE</constant> - The frontend provides a 0% to 100% measurement for Signal/Noise (actually, 0 to 65535).</listitem>
+			<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
+			<listitem><para><constant>FE_SCALE_DECIBEL</constant> - Signal/Noise ratio is in 0.0001 dB units.</para></listitem>
+			<listitem><para><constant>FE_SCALE_RELATIVE</constant> - The frontend provides a 0% to 100% measurement for Signal/Noise (actually, 0 to 65535).</para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="DTV-STAT-PRE-ERROR-BIT-COUNT">
@@ -943,8 +941,8 @@ enum fe_interleaving {
 		      The frontend may reset it when a channel/transponder is tuned.</para>
 		<para>Possible scales for this metric are:</para>
 		<itemizedlist mark='bullet'>
-			<listitem><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</listitem>
-			<listitem><constant>FE_SCALE_COUNTER</constant> - Number of error bits counted before the inner coding.</listitem>
+			<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
+			<listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of error bits counted before the inner coding.</para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="DTV-STAT-PRE-TOTAL-BIT-COUNT">
@@ -957,9 +955,9 @@ enum fe_interleaving {
 		      The frontend may reset it when a channel/transponder is tuned.</para>
 		<para>Possible scales for this metric are:</para>
 		<itemizedlist mark='bullet'>
-			<listitem><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</listitem>
-			<listitem><constant>FE_SCALE_COUNTER</constant> - Number of bits counted while measuring
-				 <link linkend="DTV-STAT-PRE-ERROR-BIT-COUNT"><constant>DTV_STAT_PRE_ERROR_BIT_COUNT</constant></link>.</listitem>
+			<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
+			<listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of bits counted while measuring
+				 <link linkend="DTV-STAT-PRE-ERROR-BIT-COUNT"><constant>DTV_STAT_PRE_ERROR_BIT_COUNT</constant></link>.</para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="DTV-STAT-POST-ERROR-BIT-COUNT">
@@ -972,8 +970,8 @@ enum fe_interleaving {
 		      The frontend may reset it when a channel/transponder is tuned.</para>
 		<para>Possible scales for this metric are:</para>
 		<itemizedlist mark='bullet'>
-			<listitem><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</listitem>
-			<listitem><constant>FE_SCALE_COUNTER</constant> - Number of error bits counted after the inner coding.</listitem>
+			<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
+			<listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of error bits counted after the inner coding.</para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="DTV-STAT-POST-TOTAL-BIT-COUNT">
@@ -986,9 +984,9 @@ enum fe_interleaving {
 		      The frontend may reset it when a channel/transponder is tuned.</para>
 		<para>Possible scales for this metric are:</para>
 		<itemizedlist mark='bullet'>
-			<listitem><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</listitem>
-			<listitem><constant>FE_SCALE_COUNTER</constant> - Number of bits counted while measuring
-				 <link linkend="DTV-STAT-POST-ERROR-BIT-COUNT"><constant>DTV_STAT_POST_ERROR_BIT_COUNT</constant></link>.</listitem>
+			<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
+			<listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of bits counted while measuring
+				 <link linkend="DTV-STAT-POST-ERROR-BIT-COUNT"><constant>DTV_STAT_POST_ERROR_BIT_COUNT</constant></link>.</para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="DTV-STAT-ERROR-BLOCK-COUNT">
@@ -998,8 +996,8 @@ enum fe_interleaving {
 		      The frontend may reset it when a channel/transponder is tuned.</para>
 		<para>Possible scales for this metric are:</para>
 		<itemizedlist mark='bullet'>
-			<listitem><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</listitem>
-			<listitem><constant>FE_SCALE_COUNTER</constant> - Number of error blocks counted after the outer coding.</listitem>
+			<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
+			<listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of error blocks counted after the outer coding.</para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="DTV-STAT-TOTAL-BLOCK-COUNT">
@@ -1011,9 +1009,9 @@ enum fe_interleaving {
 		by <link linkend="DTV-STAT-TOTAL-BLOCK-COUNT"><constant>DTV-STAT-TOTAL-BLOCK-COUNT</constant></link>.</para>
 		<para>Possible scales for this metric are:</para>
 		<itemizedlist mark='bullet'>
-			<listitem><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</listitem>
-			<listitem><constant>FE_SCALE_COUNTER</constant> - Number of blocks counted while measuring
-			<link linkend="DTV-STAT-ERROR-BLOCK-COUNT"><constant>DTV_STAT_ERROR_BLOCK_COUNT</constant></link>.</listitem>
+			<listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
+			<listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of blocks counted while measuring
+			<link linkend="DTV-STAT-ERROR-BLOCK-COUNT"><constant>DTV_STAT_ERROR_BLOCK_COUNT</constant></link>.</para></listitem>
 		</itemizedlist>
 	</section>
 	</section>

+ 0 - 14
Documentation/DocBook/media/v4l/common.xml

@@ -749,15 +749,6 @@ polarities, frontporch, backporch etc. The <filename>linux/v4l2-dv-timings.h</fi
 header can be used to get the timings of the formats in the <xref linkend="cea861" /> and
 <xref linkend="vesadmt" /> standards.
 	</para>
-	</listitem>
-	<listitem>
-	<para>DV Presets: Digital Video (DV) presets (<emphasis role="bold">deprecated</emphasis>).
-	These are IDs representing a
-video timing at the input/output. Presets are pre-defined timings implemented
-by the hardware according to video standards. A __u32 data type is used to represent
-a preset unlike the bit mask that is used in &v4l2-std-id; allowing future extensions
-to support as many different presets as needed. This API is deprecated in favor of the DV Timings
-API.</para>
 	</listitem>
 	</itemizedlist>
 	<para>To enumerate and query the attributes of the DV timings supported by a device,
@@ -766,11 +757,6 @@ API.</para>
 &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>To enumerate and query the attributes of DV presets supported by a device,
-applications use the &VIDIOC-ENUM-DV-PRESETS; ioctl. To get the current DV preset,
-applications use the &VIDIOC-G-DV-PRESET; ioctl and to set a preset they use the
-&VIDIOC-S-DV-PRESET; ioctl. To detect the preset as seen by the video receiver applications
-use the &VIDIOC-QUERY-DV-PRESET; 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>

+ 22 - 2
Documentation/DocBook/media/v4l/compat.xml

@@ -2310,6 +2310,9 @@ more information.</para>
 	<listitem>
 	  <para>Added FM Modulator (FM TX) Extended Control Class: <constant>V4L2_CTRL_CLASS_FM_TX</constant> and their Control IDs.</para>
 	</listitem>
+<listitem>
+	  <para>Added FM Receiver (FM RX) Extended Control Class: <constant>V4L2_CTRL_CLASS_FM_RX</constant> and their Control IDs.</para>
+	</listitem>
 	<listitem>
 	  <para>Added Remote Controller chapter, describing the default Remote Controller mapping for media devices.</para>
 	</listitem>
@@ -2493,6 +2496,23 @@ that used it. It was originally scheduled for removal in 2.6.35.
       </orderedlist>
     </section>
 
+    <section>
+      <title>V4L2 in Linux 3.10</title>
+      <orderedlist>
+        <listitem>
+	  <para>Removed obsolete and unused DV_PRESET ioctls
+	  VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET, VIDIOC_QUERY_DV_PRESET and
+	  VIDIOC_ENUM_DV_PRESET. Remove the related v4l2_input/output capability
+	  flags V4L2_IN_CAP_PRESETS and V4L2_OUT_CAP_PRESETS.
+	  </para>
+        </listitem>
+        <listitem>
+	  <para>Added new debugging ioctl &VIDIOC-DBG-G-CHIP-INFO;.
+	  </para>
+        </listitem>
+      </orderedlist>
+    </section>
+
     <section id="other">
       <title>Relation of V4L2 to other Linux multimedia APIs</title>
 
@@ -2625,8 +2645,8 @@ interfaces and should not be implemented in new drivers.</para>
 <xref linkend="extended-controls" />.</para>
         </listitem>
         <listitem>
-	  <para>&VIDIOC-G-DV-PRESET;, &VIDIOC-S-DV-PRESET;, &VIDIOC-ENUM-DV-PRESETS; and
-	  &VIDIOC-QUERY-DV-PRESET; ioctls. Use the DV Timings API (<xref linkend="dv-timings" />).</para>
+	  <para>VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET, VIDIOC_ENUM_DV_PRESETS and
+	  VIDIOC_QUERY_DV_PRESET ioctls. Use the DV Timings API (<xref linkend="dv-timings" />).</para>
         </listitem>
         <listitem>
 	  <para><constant>VIDIOC_SUBDEV_G_CROP</constant> and

+ 86 - 1
Documentation/DocBook/media/v4l/controls.xml

@@ -2299,6 +2299,12 @@ Possible values are:</entry>
 		</entrytbl>
 	      </row>
 	      <row><entry></entry></row>
+	      <row>
+		<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER</constant>&nbsp;</entry>
+		<entry>boolean</entry>
+	      </row><row><entry spanname="descr">Repeat the video sequence headers. Repeating these
+headers makes random access to the video stream easier. Applicable to the MPEG1, 2 and 4 encoder.</entry>
+	      </row>
 	      <row>
 		<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER</constant>&nbsp;</entry>
 		<entry>boolean</entry>
@@ -3136,6 +3142,13 @@ giving priority to the center of the metered area.</entry>
 		  <entry><constant>V4L2_EXPOSURE_METERING_SPOT</constant>&nbsp;</entry>
 		  <entry>Measure only very small area at the center of the frame.</entry>
 		</row>
+		<row>
+		  <entry><constant>V4L2_EXPOSURE_METERING_MATRIX</constant>&nbsp;</entry>
+		  <entry>A multi-zone metering. The light intensity is measured
+in several points of the frame and the the results are combined. The
+algorithm of the zones selection and their significance in calculating the
+final value is device dependant.</entry>
+		</row>
 	      </tbody>
 	    </entrytbl>
 	  </row>
@@ -3848,7 +3861,7 @@ in Hz. The range and step are driver-specific.</entry>
 	  </row>
 	  <row>
 	    <entry spanname="id"><constant>V4L2_CID_TUNE_PREEMPHASIS</constant>&nbsp;</entry>
-	    <entry>integer</entry>
+	    <entry>enum v4l2_preemphasis</entry>
 	  </row>
 	  <row id="v4l2-preemphasis"><entry spanname="descr">Configures the pre-emphasis value for broadcasting.
 A pre-emphasis filter is applied to the broadcast to accentuate the high audio frequencies.
@@ -4687,4 +4700,76 @@ interface and may change in the future.</para>
       </table>
 
     </section>
+
+    <section id="fm-rx-controls">
+      <title>FM Receiver Control Reference</title>
+
+      <para>The FM Receiver (FM_RX) class includes controls for common features of
+      FM Reception capable devices.</para>
+
+      <table pgwide="1" frame="none" id="fm-rx-control-id">
+      <title>FM_RX 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_FM_RX_CLASS</constant>&nbsp;</entry>
+            <entry>class</entry>
+          </row><row><entry spanname="descr">The FM_RX 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_RDS_RECEPTION</constant>&nbsp;</entry>
+            <entry>boolean</entry>
+          </row><row><entry spanname="descr">Enables/disables RDS
+	  reception by the radio tuner</entry>
+          </row>
+          <row>
+	    <entry spanname="id"><constant>V4L2_CID_TUNE_DEEMPHASIS</constant>&nbsp;</entry>
+	    <entry>enum v4l2_deemphasis</entry>
+	  </row>
+	  <row id="v4l2-deemphasis"><entry spanname="descr">Configures the de-emphasis value for reception.
+A de-emphasis filter is applied to the broadcast to accentuate the high audio frequencies.
+Depending on the region, a time constant of either 50 or 75 useconds is used. The enum&nbsp;v4l2_deemphasis
+defines possible values for de-emphasis. Here they are:</entry>
+	</row><row>
+	<entrytbl spanname="descr" cols="2">
+		  <tbody valign="top">
+		    <row>
+		      <entry><constant>V4L2_DEEMPHASIS_DISABLED</constant>&nbsp;</entry>
+		      <entry>No de-emphasis is applied.</entry>
+		    </row>
+		    <row>
+		      <entry><constant>V4L2_DEEMPHASIS_50_uS</constant>&nbsp;</entry>
+		      <entry>A de-emphasis of 50 uS is used.</entry>
+		    </row>
+		    <row>
+		      <entry><constant>V4L2_DEEMPHASIS_75_uS</constant>&nbsp;</entry>
+		      <entry>A de-emphasis of 75 uS is used.</entry>
+		    </row>
+		  </tbody>
+		</entrytbl>
+
+	  </row>
+          <row><entry></entry></row>
+        </tbody>
+      </tgroup>
+      </table>
+
+      </section>
 </section>

+ 6 - 0
Documentation/DocBook/media/v4l/io.xml

@@ -1145,6 +1145,12 @@ in which case caches have not been used.</entry>
 	    same clock outside V4L2, use
 	    <function>clock_gettime(2)</function> .</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_FLAG_TIMESTAMP_COPY</constant></entry>
+	    <entry>0x4000</entry>
+	    <entry>The CAPTURE buffer timestamp has been taken from the
+	    corresponding OUTPUT buffer. This flag applies only to mem2mem devices.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>

+ 10 - 0
Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml

@@ -272,6 +272,16 @@
 	    <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_LENS</constant></entry>
 	    <entry>Lens controller</entry>
 	  </row>
+	  <row>
+	    <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_DECODER</constant></entry>
+	    <entry>Video decoder, the basic function of the video decoder is to
+	    accept analogue video from a wide variety of sources such as
+	    broadcast, DVD players, cameras and video cassette recorders, in
+	    either NTSC, PAL or HD format and still occasionally SECAM, separate
+	    it into its component parts, luminance and chrominance, and output
+	    it in some digital video standard, with appropriate embedded timing
+	    signals.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>

+ 196 - 10
Documentation/DocBook/media/v4l/subdev-formats.xml

@@ -93,19 +93,35 @@
 
       <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-rgb">
 	<title>RGB formats</title>
-	<tgroup cols="11">
+	<tgroup cols="27">
 	  <colspec colname="id" align="left" />
 	  <colspec colname="code" align="center"/>
 	  <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" />
-	  <spanspec namest="b07" nameend="b00" spanname="b0" />
+	  <colspec colnum="4" colname="b23" align="center" />
+	  <colspec colnum="5" colname="b22" align="center" />
+	  <colspec colnum="6" colname="b21" align="center" />
+	  <colspec colnum="7" colname="b20" align="center" />
+	  <colspec colnum="8" colname="b19" align="center" />
+	  <colspec colnum="9" colname="b18" align="center" />
+	  <colspec colnum="10" colname="b17" align="center" />
+	  <colspec colnum="11" colname="b16" align="center" />
+	  <colspec colnum="12" colname="b15" align="center" />
+	  <colspec colnum="13" colname="b14" align="center" />
+	  <colspec colnum="14" colname="b13" align="center" />
+	  <colspec colnum="15" colname="b12" align="center" />
+	  <colspec colnum="16" colname="b11" align="center" />
+	  <colspec colnum="17" colname="b10" align="center" />
+	  <colspec colnum="18" colname="b09" align="center" />
+	  <colspec colnum="19" colname="b08" align="center" />
+	  <colspec colnum="20" colname="b07" align="center" />
+	  <colspec colnum="21" colname="b06" align="center" />
+	  <colspec colnum="22" colname="b05" align="center" />
+	  <colspec colnum="23" colname="b04" align="center" />
+	  <colspec colnum="24" colname="b03" align="center" />
+	  <colspec colnum="25" colname="b02" align="center" />
+	  <colspec colnum="26" colname="b01" align="center" />
+	  <colspec colnum="27" colname="b00" align="center" />
+	  <spanspec namest="b23" nameend="b00" spanname="b0" />
 	  <thead>
 	    <row>
 	      <entry>Identifier</entry>
@@ -117,6 +133,22 @@
 	      <entry></entry>
 	      <entry></entry>
 	      <entry>Bit</entry>
+	      <entry>23</entry>
+	      <entry>22</entry>
+	      <entry>21</entry>
+	      <entry>20</entry>
+	      <entry>19</entry>
+	      <entry>18</entry>
+	      <entry>17</entry>
+	      <entry>16</entry>
+	      <entry>15</entry>
+	      <entry>14</entry>
+	      <entry>13</entry>
+	      <entry>12</entry>
+	      <entry>11</entry>
+	      <entry>10</entry>
+	      <entry>9</entry>
+	      <entry>8</entry>
 	      <entry>7</entry>
 	      <entry>6</entry>
 	      <entry>5</entry>
@@ -132,6 +164,7 @@
 	      <entry>V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE</entry>
 	      <entry>0x1001</entry>
 	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>0</entry>
 	      <entry>0</entry>
 	      <entry>0</entry>
@@ -145,6 +178,7 @@
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>g<subscript>3</subscript></entry>
 	      <entry>g<subscript>2</subscript></entry>
 	      <entry>g<subscript>1</subscript></entry>
@@ -158,6 +192,7 @@
 	      <entry>V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE</entry>
 	      <entry>0x1002</entry>
 	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>g<subscript>3</subscript></entry>
 	      <entry>g<subscript>2</subscript></entry>
 	      <entry>g<subscript>1</subscript></entry>
@@ -171,6 +206,7 @@
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>0</entry>
 	      <entry>0</entry>
 	      <entry>0</entry>
@@ -184,6 +220,7 @@
 	      <entry>V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE</entry>
 	      <entry>0x1003</entry>
 	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>0</entry>
 	      <entry>r<subscript>4</subscript></entry>
 	      <entry>r<subscript>3</subscript></entry>
@@ -197,6 +234,7 @@
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>g<subscript>2</subscript></entry>
 	      <entry>g<subscript>1</subscript></entry>
 	      <entry>g<subscript>0</subscript></entry>
@@ -210,6 +248,7 @@
 	      <entry>V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE</entry>
 	      <entry>0x1004</entry>
 	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>g<subscript>2</subscript></entry>
 	      <entry>g<subscript>1</subscript></entry>
 	      <entry>g<subscript>0</subscript></entry>
@@ -223,6 +262,7 @@
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>0</entry>
 	      <entry>r<subscript>4</subscript></entry>
 	      <entry>r<subscript>3</subscript></entry>
@@ -236,6 +276,7 @@
 	      <entry>V4L2_MBUS_FMT_BGR565_2X8_BE</entry>
 	      <entry>0x1005</entry>
 	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>b<subscript>4</subscript></entry>
 	      <entry>b<subscript>3</subscript></entry>
 	      <entry>b<subscript>2</subscript></entry>
@@ -249,6 +290,7 @@
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>g<subscript>2</subscript></entry>
 	      <entry>g<subscript>1</subscript></entry>
 	      <entry>g<subscript>0</subscript></entry>
@@ -262,6 +304,7 @@
 	      <entry>V4L2_MBUS_FMT_BGR565_2X8_LE</entry>
 	      <entry>0x1006</entry>
 	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>g<subscript>2</subscript></entry>
 	      <entry>g<subscript>1</subscript></entry>
 	      <entry>g<subscript>0</subscript></entry>
@@ -275,6 +318,7 @@
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>b<subscript>4</subscript></entry>
 	      <entry>b<subscript>3</subscript></entry>
 	      <entry>b<subscript>2</subscript></entry>
@@ -288,6 +332,7 @@
 	      <entry>V4L2_MBUS_FMT_RGB565_2X8_BE</entry>
 	      <entry>0x1007</entry>
 	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>r<subscript>4</subscript></entry>
 	      <entry>r<subscript>3</subscript></entry>
 	      <entry>r<subscript>2</subscript></entry>
@@ -301,6 +346,7 @@
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>g<subscript>2</subscript></entry>
 	      <entry>g<subscript>1</subscript></entry>
 	      <entry>g<subscript>0</subscript></entry>
@@ -314,6 +360,7 @@
 	      <entry>V4L2_MBUS_FMT_RGB565_2X8_LE</entry>
 	      <entry>0x1008</entry>
 	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>g<subscript>2</subscript></entry>
 	      <entry>g<subscript>1</subscript></entry>
 	      <entry>g<subscript>0</subscript></entry>
@@ -327,6 +374,27 @@
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
+	      &dash-ent-16;
+	      <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-MBUS-FMT-RGB666-1X18">
+	      <entry>V4L2_MBUS_FMT_RGB666_1X18</entry>
+	      <entry>0x1009</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</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>
@@ -335,6 +403,124 @@
 	      <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>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-MBUS-FMT-RGB888-1X24">
+	      <entry>V4L2_MBUS_FMT_RGB888_1X24</entry>
+	      <entry>0x100a</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>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>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-MBUS-FMT-RGB888-2X12-BE">
+	      <entry>V4L2_MBUS_FMT_RGB888_2X12_BE</entry>
+	      <entry>0x100b</entry>
+	      <entry></entry>
+	      &dash-ent-10;
+	      <entry>-</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>g<subscript>7</subscript></entry>
+	      <entry>g<subscript>6</subscript></entry>
+	      <entry>g<subscript>5</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-10;
+	      <entry>-</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>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-MBUS-FMT-RGB888-2X12-LE">
+	      <entry>V4L2_MBUS_FMT_RGB888_2X12_LE</entry>
+	      <entry>0x100c</entry>
+	      <entry></entry>
+	      &dash-ent-10;
+	      <entry>-</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>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>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-10;
+	      <entry>-</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>g<subscript>7</subscript></entry>
+	      <entry>g<subscript>6</subscript></entry>
+	      <entry>g<subscript>5</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
 	    </row>
 	  </tbody>
 	</tgroup>

+ 14 - 5
Documentation/DocBook/media/v4l/v4l2.xml

@@ -124,6 +124,7 @@ Remote Controller chapter.</contrib>
       <year>2010</year>
       <year>2011</year>
       <year>2012</year>
+      <year>2013</year>
       <holder>Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin
 Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab,
 	Pawel Osciak</holder>
@@ -139,13 +140,23 @@ structs, ioctls) must be noted in more detail in the history chapter
 (compat.xml), along with the possible impact on existing drivers and
 applications. -->
 
+      <revision>
+	<revnumber>3.10</revnumber>
+	<date>2013-03-25</date>
+	<authorinitials>hv</authorinitials>
+	<revremark>Remove obsolete and unused DV_PRESET ioctls:
+	VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET, VIDIOC_QUERY_DV_PRESET and
+	VIDIOC_ENUM_DV_PRESET. Remove the related v4l2_input/output capability
+	flags V4L2_IN_CAP_PRESETS and V4L2_OUT_CAP_PRESETS. Added VIDIOC_DBG_G_CHIP_INFO.
+	</revremark>
+      </revision>
+
       <revision>
 	<revnumber>3.9</revnumber>
 	<date>2012-12-03</date>
 	<authorinitials>sa, sn</authorinitials>
 	<revremark>Added timestamp types to v4l2_buffer.
-	Added <constant>V4L2_EVENT_CTRL_CH_RANGE</constant> control
-	event changes flag, see <xref linkend="changes-flags"/>.
+	Added V4L2_EVENT_CTRL_CH_RANGE control event changes flag.
 	</revremark>
       </revision>
 
@@ -537,6 +548,7 @@ and discussions on the V4L mailing list.</revremark>
     &sub-create-bufs;
     &sub-cropcap;
     &sub-dbg-g-chip-ident;
+    &sub-dbg-g-chip-info;
     &sub-dbg-g-register;
     &sub-decoder-cmd;
     &sub-dqevent;
@@ -544,7 +556,6 @@ and discussions on the V4L mailing list.</revremark>
     &sub-encoder-cmd;
     &sub-enumaudio;
     &sub-enumaudioout;
-    &sub-enum-dv-presets;
     &sub-enum-dv-timings;
     &sub-enum-fmt;
     &sub-enum-framesizes;
@@ -558,7 +569,6 @@ and discussions on the V4L mailing list.</revremark>
     &sub-g-audioout;
     &sub-g-crop;
     &sub-g-ctrl;
-    &sub-g-dv-preset;
     &sub-g-dv-timings;
     &sub-g-enc-index;
     &sub-g-ext-ctrls;
@@ -582,7 +592,6 @@ and discussions on the V4L mailing list.</revremark>
     &sub-querybuf;
     &sub-querycap;
     &sub-queryctrl;
-    &sub-query-dv-preset;
     &sub-query-dv-timings;
     &sub-querystd;
     &sub-reqbufs;

+ 7 - 2
Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-ident.xml

@@ -200,10 +200,10 @@ the values from <xref linkend="chip-ids" />.</entry>
 	&cs-def;
 	<tbody valign="top">
 	  <row>
-	    <entry><constant>V4L2_CHIP_MATCH_HOST</constant></entry>
+	    <entry><constant>V4L2_CHIP_MATCH_BRIDGE</constant></entry>
 	    <entry>0</entry>
 	    <entry>Match the nth chip on the card, zero for the
-	    host chip. Does not match &i2c; chips.</entry>
+	    bridge chip. Does not match sub-devices.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_CHIP_MATCH_I2C_DRIVER</constant></entry>
@@ -220,6 +220,11 @@ the values from <xref linkend="chip-ids" />.</entry>
 	    <entry>3</entry>
 	    <entry>Match the nth anciliary AC97 chip.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_SUBDEV</constant></entry>
+	    <entry>4</entry>
+	    <entry>Match the nth sub-device. Can't be used with this ioctl.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>

+ 223 - 0
Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml

@@ -0,0 +1,223 @@
+<refentry id="vidioc-dbg-g-chip-info">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_DBG_G_CHIP_INFO</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_DBG_G_CHIP_INFO</refname>
+    <refpurpose>Identify the chips on a TV card</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_dbg_chip_info
+*<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_DBG_G_CHIP_INFO</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <note>
+      <title>Experimental</title>
+
+      <para>This is an <link
+linkend="experimental">experimental</link> interface and may change in
+the future.</para>
+    </note>
+
+    <para>For driver debugging purposes this ioctl allows test
+applications to query the driver about the chips present on the TV
+card. Regular applications must not use it. When you found a chip
+specific bug, please contact the linux-media mailing list (&v4l-ml;)
+so it can be fixed.</para>
+
+    <para>Additionally the Linux kernel must be compiled with the
+<constant>CONFIG_VIDEO_ADV_DEBUG</constant> option to enable this ioctl.</para>
+
+    <para>To query the driver applications must initialize the
+<structfield>match.type</structfield> and
+<structfield>match.addr</structfield> or <structfield>match.name</structfield>
+fields of a &v4l2-dbg-chip-info;
+and call <constant>VIDIOC_DBG_G_CHIP_INFO</constant> with a pointer to
+this structure. On success the driver stores information about the
+selected chip in the <structfield>name</structfield> and
+<structfield>flags</structfield> fields. On failure the structure
+remains unchanged.</para>
+
+    <para>When <structfield>match.type</structfield> is
+<constant>V4L2_CHIP_MATCH_BRIDGE</constant>,
+<structfield>match.addr</structfield> selects the nth bridge 'chip'
+on the TV card. You can enumerate all chips by starting at zero and
+incrementing <structfield>match.addr</structfield> by one until
+<constant>VIDIOC_DBG_G_CHIP_INFO</constant> fails with an &EINVAL;.
+The number zero always selects the bridge chip itself, &eg; the chip
+connected to the PCI or USB bus. Non-zero numbers identify specific
+parts of the bridge chip such as an AC97 register block.</para>
+
+    <para>When <structfield>match.type</structfield> is
+<constant>V4L2_CHIP_MATCH_SUBDEV</constant>,
+<structfield>match.addr</structfield> selects the nth sub-device. This
+allows you to enumerate over all sub-devices.</para>
+
+    <para>On success, the <structfield>name</structfield> field will
+contain a chip name and the <structfield>flags</structfield> field will
+contain <constant>V4L2_CHIP_FL_READABLE</constant> if the driver supports
+reading registers from the device or <constant>V4L2_CHIP_FL_WRITABLE</constant>
+if the driver supports writing registers to the device.</para>
+
+    <para>We recommended the <application>v4l2-dbg</application>
+utility over calling this ioctl directly. It is available from the
+LinuxTV v4l-dvb repository; see <ulink
+url="http://linuxtv.org/repo/">http://linuxtv.org/repo/</ulink> for
+access instructions.</para>
+
+    <!-- Note for convenience vidioc-dbg-g-register.sgml
+	 contains a duplicate of this table. -->
+    <table pgwide="1" frame="none" id="name-v4l2-dbg-match">
+      <title>struct <structname>v4l2_dbg_match</structname></title>
+      <tgroup cols="4">
+	&cs-ustr;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>type</structfield></entry>
+	    <entry>See <xref linkend="name-chip-match-types" /> for a list of
+possible types.</entry>
+	  </row>
+	  <row>
+	    <entry>union</entry>
+	    <entry>(anonymous)</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>__u32</entry>
+	    <entry><structfield>addr</structfield></entry>
+	    <entry>Match a chip by this number, interpreted according
+to the <structfield>type</structfield> field.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>char</entry>
+	    <entry><structfield>name[32]</structfield></entry>
+	    <entry>Match a chip by this name, interpreted according
+to the <structfield>type</structfield> field.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table pgwide="1" frame="none" id="v4l2-dbg-chip-info">
+      <title>struct <structname>v4l2_dbg_chip_info</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>struct v4l2_dbg_match</entry>
+	    <entry><structfield>match</structfield></entry>
+	    <entry>How to match the chip, see <xref linkend="name-v4l2-dbg-match" />.</entry>
+	  </row>
+	  <row>
+	    <entry>char</entry>
+	    <entry><structfield>name[32]</structfield></entry>
+	    <entry>The name of the chip.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>flags</structfield></entry>
+	    <entry>Set by the driver. If <constant>V4L2_CHIP_FL_READABLE</constant>
+is set, then the driver supports reading registers from the device. If
+<constant>V4L2_CHIP_FL_WRITABLE</constant> is set, then it supports writing registers.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved[8]</structfield></entry>
+	    <entry>Reserved fields, both application and driver must set these to 0.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <!-- Note for convenience vidioc-dbg-g-register.sgml
+	 contains a duplicate of this table. -->
+    <table pgwide="1" frame="none" id="name-chip-match-types">
+      <title>Chip Match Types</title>
+      <tgroup cols="3">
+	&cs-def;
+	<tbody valign="top">
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_BRIDGE</constant></entry>
+	    <entry>0</entry>
+	    <entry>Match the nth chip on the card, zero for the
+	    bridge chip. Does not match sub-devices.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_I2C_DRIVER</constant></entry>
+	    <entry>1</entry>
+	    <entry>Match an &i2c; chip by its driver name. Can't be used with this ioctl.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_I2C_ADDR</constant></entry>
+	    <entry>2</entry>
+	    <entry>Match a chip by its 7 bit &i2c; bus address. Can't be used with this ioctl.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_AC97</constant></entry>
+	    <entry>3</entry>
+	    <entry>Match the nth anciliary AC97 chip. Can't be used with this ioctl.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_SUBDEV</constant></entry>
+	    <entry>4</entry>
+	    <entry>Match the nth sub-device.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The <structfield>match_type</structfield> is invalid or
+no device could be matched.</para>
+	</listitem>
+      </varlistentry>
+     </variablelist>
+  </refsect1>
+</refentry>

+ 19 - 10
Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml

@@ -87,7 +87,7 @@ written into the register.</para>
 
     <para>To read a register applications must initialize the
 <structfield>match.type</structfield>,
-<structfield>match.chip</structfield> or <structfield>match.name</structfield> and
+<structfield>match.addr</structfield> or <structfield>match.name</structfield> and
 <structfield>reg</structfield> fields, and call
 <constant>VIDIOC_DBG_G_REGISTER</constant> with a pointer to this
 structure. On success the driver stores the register value in the
@@ -95,11 +95,11 @@ structure. On success the driver stores the register value in the
 unchanged.</para>
 
     <para>When <structfield>match.type</structfield> is
-<constant>V4L2_CHIP_MATCH_HOST</constant>,
-<structfield>match.addr</structfield> selects the nth non-&i2c; chip
+<constant>V4L2_CHIP_MATCH_BRIDGE</constant>,
+<structfield>match.addr</structfield> selects the nth non-sub-device chip
 on the TV card.  The number zero always selects the host chip, &eg; the
 chip connected to the PCI or USB bus. You can find out which chips are
-present with the &VIDIOC-DBG-G-CHIP-IDENT; ioctl.</para>
+present with the &VIDIOC-DBG-G-CHIP-INFO; ioctl.</para>
 
     <para>When <structfield>match.type</structfield> is
 <constant>V4L2_CHIP_MATCH_I2C_DRIVER</constant>,
@@ -109,7 +109,7 @@ For instance
 supported by the saa7127 driver, regardless of its &i2c; bus address.
 When multiple chips supported by the same driver are present, the
 effect of these ioctls is undefined. Again with the
-&VIDIOC-DBG-G-CHIP-IDENT; ioctl you can find out which &i2c; chips are
+&VIDIOC-DBG-G-CHIP-INFO; ioctl you can find out which &i2c; chips are
 present.</para>
 
     <para>When <structfield>match.type</structfield> is
@@ -122,19 +122,23 @@ bus address.</para>
 <structfield>match.addr</structfield> selects the nth AC97 chip
 on the TV card.</para>
 
+    <para>When <structfield>match.type</structfield> is
+<constant>V4L2_CHIP_MATCH_SUBDEV</constant>,
+<structfield>match.addr</structfield> selects the nth sub-device.</para>
+
     <note>
       <title>Success not guaranteed</title>
 
       <para>Due to a flaw in the Linux &i2c; bus driver these ioctls may
 return successfully without actually reading or writing a register. To
-catch the most likely failure we recommend a &VIDIOC-DBG-G-CHIP-IDENT;
+catch the most likely failure we recommend a &VIDIOC-DBG-G-CHIP-INFO;
 call confirming the presence of the selected &i2c; chip.</para>
     </note>
 
     <para>These ioctls are optional, not all drivers may support them.
 However when a driver supports these ioctls it must also support
-&VIDIOC-DBG-G-CHIP-IDENT;. Conversely it may support
-<constant>VIDIOC_DBG_G_CHIP_IDENT</constant> but not these ioctls.</para>
+&VIDIOC-DBG-G-CHIP-INFO;. Conversely it may support
+<constant>VIDIOC_DBG_G_CHIP_INFO</constant> but not these ioctls.</para>
 
     <para><constant>VIDIOC_DBG_G_REGISTER</constant> and
 <constant>VIDIOC_DBG_S_REGISTER</constant> were introduced in Linux
@@ -217,10 +221,10 @@ register.</entry>
 	&cs-def;
 	<tbody valign="top">
 	  <row>
-	    <entry><constant>V4L2_CHIP_MATCH_HOST</constant></entry>
+	    <entry><constant>V4L2_CHIP_MATCH_BRIDGE</constant></entry>
 	    <entry>0</entry>
 	    <entry>Match the nth chip on the card, zero for the
-	    host chip. Does not match &i2c; chips.</entry>
+	    bridge chip. Does not match sub-devices.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_CHIP_MATCH_I2C_DRIVER</constant></entry>
@@ -237,6 +241,11 @@ register.</entry>
 	    <entry>3</entry>
 	    <entry>Match the nth anciliary AC97 chip.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_CHIP_MATCH_SUBDEV</constant></entry>
+	    <entry>4</entry>
+	    <entry>Match the nth sub-device.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>

+ 0 - 240
Documentation/DocBook/media/v4l/vidioc-enum-dv-presets.xml

@@ -1,240 +0,0 @@
-<refentry id="vidioc-enum-dv-presets">
-  <refmeta>
-    <refentrytitle>ioctl VIDIOC_ENUM_DV_PRESETS</refentrytitle>
-    &manvol;
-  </refmeta>
-
-  <refnamediv>
-    <refname>VIDIOC_ENUM_DV_PRESETS</refname>
-    <refpurpose>Enumerate supported Digital Video presets</refpurpose>
-  </refnamediv>
-
-  <refsynopsisdiv>
-    <funcsynopsis>
-      <funcprototype>
-	<funcdef>int <function>ioctl</function></funcdef>
-	<paramdef>int <parameter>fd</parameter></paramdef>
-	<paramdef>int <parameter>request</parameter></paramdef>
-	<paramdef>struct v4l2_dv_enum_preset *<parameter>argp</parameter></paramdef>
-      </funcprototype>
-    </funcsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>Arguments</title>
-
-    <variablelist>
-      <varlistentry>
-	<term><parameter>fd</parameter></term>
-	<listitem>
-	  <para>&fd;</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><parameter>request</parameter></term>
-	<listitem>
-	  <para>VIDIOC_ENUM_DV_PRESETS</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><parameter>argp</parameter></term>
-	<listitem>
-	  <para></para>
-	</listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-
-  <refsect1>
-    <title>Description</title>
-
-    <para>This ioctl is <emphasis role="bold">deprecated</emphasis>.
-    New drivers and applications should use &VIDIOC-ENUM-DV-TIMINGS; instead.
-    </para>
-
-    <para>To query the attributes of a DV preset, applications initialize the
-<structfield>index</structfield> field and zero the reserved array of &v4l2-dv-enum-preset;
-and call the <constant>VIDIOC_ENUM_DV_PRESETS</constant> ioctl with a pointer to this
-structure. Drivers fill the rest of the structure or return an
-&EINVAL; when the index is out of bounds. To enumerate all DV Presets supported,
-applications shall begin at index zero, incrementing by one until the
-driver returns <errorcode>EINVAL</errorcode>. Drivers may enumerate a
-different set of DV presets after switching the video input or
-output.</para>
-
-    <table pgwide="1" frame="none" id="v4l2-dv-enum-preset">
-      <title>struct <structname>v4l2_dv_enum_presets</structname></title>
-      <tgroup cols="3">
-	&cs-str;
-	<tbody valign="top">
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>index</structfield></entry>
-	    <entry>Number of the DV preset, set by the
-application.</entry>
-	  </row>
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>preset</structfield></entry>
-	    <entry>This field identifies one of the DV preset values listed in <xref linkend="v4l2-dv-presets-vals"/>.</entry>
-	  </row>
-	  <row>
-	    <entry>__u8</entry>
-	    <entry><structfield>name</structfield>[24]</entry>
-	    <entry>Name of the preset, a NUL-terminated ASCII string, for example: "720P-60", "1080I-60". This information is
-intended for the user.</entry>
-	  </row>
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>width</structfield></entry>
-	    <entry>Width of the active video in pixels for the DV preset.</entry>
-	  </row>
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>height</structfield></entry>
-	    <entry>Height of the active video in lines for the DV preset.</entry>
-	  </row>
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>reserved</structfield>[4]</entry>
-	    <entry>Reserved for future extensions. Drivers must set the array to zero.</entry>
-	  </row>
-	</tbody>
-      </tgroup>
-    </table>
-
-    <table pgwide="1" frame="none" id="v4l2-dv-presets-vals">
-      <title>struct <structname>DV Presets</structname></title>
-      <tgroup cols="3">
-	&cs-str;
-	<tbody valign="top">
-	  <row>
-	    <entry>Preset</entry>
-	    <entry>Preset value</entry>
-	    <entry>Description</entry>
-	  </row>
-	  <row>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_INVALID</entry>
-	    <entry>0</entry>
-	    <entry>Invalid preset value.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_480P59_94</entry>
-	    <entry>1</entry>
-	    <entry>720x480 progressive video at 59.94 fps as per BT.1362.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_576P50</entry>
-	    <entry>2</entry>
-	    <entry>720x576 progressive video at 50 fps as per BT.1362.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_720P24</entry>
-	    <entry>3</entry>
-	    <entry>1280x720 progressive video at 24 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_720P25</entry>
-	    <entry>4</entry>
-	    <entry>1280x720 progressive video at 25 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_720P30</entry>
-	    <entry>5</entry>
-	    <entry>1280x720 progressive video at 30 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_720P50</entry>
-	    <entry>6</entry>
-	    <entry>1280x720 progressive video at 50 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_720P59_94</entry>
-	    <entry>7</entry>
-	    <entry>1280x720 progressive video at 59.94 fps as per SMPTE 274M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_720P60</entry>
-	    <entry>8</entry>
-	    <entry>1280x720 progressive video at 60 fps as per SMPTE 274M/296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080I29_97</entry>
-	    <entry>9</entry>
-	    <entry>1920x1080 interlaced video at 29.97 fps as per BT.1120/SMPTE 274M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080I30</entry>
-	    <entry>10</entry>
-	    <entry>1920x1080 interlaced video at 30 fps as per BT.1120/SMPTE 274M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080I25</entry>
-	    <entry>11</entry>
-	    <entry>1920x1080 interlaced video at 25 fps as per BT.1120.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080I50</entry>
-	    <entry>12</entry>
-	    <entry>1920x1080 interlaced video at 50 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080I60</entry>
-	    <entry>13</entry>
-	    <entry>1920x1080 interlaced video at 60 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080P24</entry>
-	    <entry>14</entry>
-	    <entry>1920x1080 progressive video at 24 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080P25</entry>
-	    <entry>15</entry>
-	    <entry>1920x1080 progressive video at 25 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080P30</entry>
-	    <entry>16</entry>
-	    <entry>1920x1080 progressive video at 30 fps as per SMPTE 296M.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080P50</entry>
-	    <entry>17</entry>
-	    <entry>1920x1080 progressive video at 50 fps as per BT.1120.</entry>
-	  </row>
-	  <row>
-	    <entry>V4L2_DV_1080P60</entry>
-	    <entry>18</entry>
-	    <entry>1920x1080 progressive video at 60 fps as per BT.1120.</entry>
-	  </row>
-	</tbody>
-      </tgroup>
-    </table>
-  </refsect1>
-
-  <refsect1>
-    &return-value;
-
-    <variablelist>
-      <varlistentry>
-	<term><errorcode>EINVAL</errorcode></term>
-	<listitem>
-	  <para>The &v4l2-dv-enum-preset; <structfield>index</structfield>
-is out of bounds.</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><errorcode>ENODATA</errorcode></term>
-	<listitem>
-	  <para>Digital video presets are not supported for this input or output.</para>
-	</listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-</refentry>

+ 0 - 5
Documentation/DocBook/media/v4l/vidioc-enuminput.xml

@@ -277,11 +277,6 @@ input/output interface to linux-media@vger.kernel.org on 19 Oct 2009.
       <tgroup cols="3">
 	&cs-def;
 	<tbody valign="top">
-	  <row>
-	    <entry><constant>V4L2_IN_CAP_PRESETS</constant></entry>
-	    <entry>0x00000001</entry>
-	    <entry>This input supports setting DV presets by using VIDIOC_S_DV_PRESET.</entry>
-	  </row>
 	  <row>
 	    <entry><constant>V4L2_IN_CAP_DV_TIMINGS</constant></entry>
 	    <entry>0x00000002</entry>

+ 0 - 5
Documentation/DocBook/media/v4l/vidioc-enumoutput.xml

@@ -162,11 +162,6 @@ input/output interface to linux-media@vger.kernel.org on 19 Oct 2009.
       <tgroup cols="3">
 	&cs-def;
 	<tbody valign="top">
-	  <row>
-	    <entry><constant>V4L2_OUT_CAP_PRESETS</constant></entry>
-	    <entry>0x00000001</entry>
-	    <entry>This output supports setting DV presets by using VIDIOC_S_DV_PRESET.</entry>
-	  </row>
 	  <row>
 	    <entry><constant>V4L2_OUT_CAP_DV_TIMINGS</constant></entry>
 	    <entry>0x00000002</entry>

+ 0 - 113
Documentation/DocBook/media/v4l/vidioc-g-dv-preset.xml

@@ -1,113 +0,0 @@
-<refentry id="vidioc-g-dv-preset">
-  <refmeta>
-    <refentrytitle>ioctl VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET</refentrytitle>
-    &manvol;
-  </refmeta>
-
-  <refnamediv>
-    <refname>VIDIOC_G_DV_PRESET</refname>
-    <refname>VIDIOC_S_DV_PRESET</refname>
-    <refpurpose>Query or select the DV preset of the current input or output</refpurpose>
-  </refnamediv>
-
-  <refsynopsisdiv>
-    <funcsynopsis>
-      <funcprototype>
-	<funcdef>int <function>ioctl</function></funcdef>
-	<paramdef>int <parameter>fd</parameter></paramdef>
-	<paramdef>int <parameter>request</parameter></paramdef>
-	<paramdef>struct v4l2_dv_preset *<parameter>argp</parameter></paramdef>
-      </funcprototype>
-    </funcsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>Arguments</title>
-
-    <variablelist>
-      <varlistentry>
-	<term><parameter>fd</parameter></term>
-	<listitem>
-	  <para>&fd;</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><parameter>request</parameter></term>
-	<listitem>
-	  <para>VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><parameter>argp</parameter></term>
-	<listitem>
-	  <para></para>
-	</listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-
-  <refsect1>
-    <title>Description</title>
-
-    <para>These ioctls are <emphasis role="bold">deprecated</emphasis>.
-    New drivers and applications should use &VIDIOC-G-DV-TIMINGS; and &VIDIOC-S-DV-TIMINGS;
-    instead.
-    </para>
-
-    <para>To query and select the current DV preset, applications
-use the <constant>VIDIOC_G_DV_PRESET</constant> and <constant>VIDIOC_S_DV_PRESET</constant>
-ioctls which take a pointer to a &v4l2-dv-preset; type as argument.
-Applications must zero the reserved array in &v4l2-dv-preset;.
-<constant>VIDIOC_G_DV_PRESET</constant> returns a dv preset in the field
-<structfield>preset</structfield> of &v4l2-dv-preset;.</para>
-
-    <para><constant>VIDIOC_S_DV_PRESET</constant> accepts a pointer to a &v4l2-dv-preset;
-that has the preset value to be set. Applications must zero the reserved array in &v4l2-dv-preset;.
-If the preset is not supported, it returns an &EINVAL; </para>
-  </refsect1>
-
-  <refsect1>
-    &return-value;
-
-    <variablelist>
-      <varlistentry>
-	<term><errorcode>EINVAL</errorcode></term>
-	<listitem>
-	  <para>This ioctl is not supported, or the
-<constant>VIDIOC_S_DV_PRESET</constant>,<constant>VIDIOC_S_DV_PRESET</constant> parameter was unsuitable.</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><errorcode>ENODATA</errorcode></term>
-	<listitem>
-	  <para>Digital video presets are not supported for this input or output.</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><errorcode>EBUSY</errorcode></term>
-	<listitem>
-	  <para>The device is busy and therefore can not change the preset.</para>
-	</listitem>
-      </varlistentry>
-    </variablelist>
-
-    <table pgwide="1" frame="none" id="v4l2-dv-preset">
-      <title>struct <structname>v4l2_dv_preset</structname></title>
-      <tgroup cols="3">
-	&cs-str;
-	<tbody valign="top">
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>preset</structfield></entry>
-	    <entry>Preset value to represent the digital video timings</entry>
-	  </row>
-	  <row>
-	    <entry>__u32</entry>
-	    <entry><structfield>reserved[4]</structfield></entry>
-	    <entry>Reserved fields for future use</entry>
-	  </row>
-	</tbody>
-      </tgroup>
-    </table>
-  </refsect1>
-</refentry>

+ 9 - 0
Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml

@@ -319,6 +319,15 @@ These controls are described in <xref
 	    processing controls. These controls are described in <xref
 	    linkend="image-process-controls" />.</entry>
 	  </row>
+
+	  <row>
+	    <entry><constant>V4L2_CTRL_CLASS_FM_RX</constant></entry>
+	    <entry>0xa10000</entry>
+	    <entry>The class containing FM Receiver (FM RX) controls.
+These controls are described in <xref
+		linkend="fm-rx-controls" />.</entry>
+	  </row>
+
 	</tbody>
       </tgroup>
     </table>

+ 0 - 78
Documentation/DocBook/media/v4l/vidioc-query-dv-preset.xml

@@ -1,78 +0,0 @@
-<refentry id="vidioc-query-dv-preset">
-  <refmeta>
-    <refentrytitle>ioctl VIDIOC_QUERY_DV_PRESET</refentrytitle>
-    &manvol;
-  </refmeta>
-
-  <refnamediv>
-    <refname>VIDIOC_QUERY_DV_PRESET</refname>
-    <refpurpose>Sense the DV preset received by the current
-input</refpurpose>
-  </refnamediv>
-
-  <refsynopsisdiv>
-    <funcsynopsis>
-      <funcprototype>
-	<funcdef>int <function>ioctl</function></funcdef>
-	<paramdef>int <parameter>fd</parameter></paramdef>
-	<paramdef>int <parameter>request</parameter></paramdef>
-	<paramdef>struct v4l2_dv_preset *<parameter>argp</parameter></paramdef>
-      </funcprototype>
-    </funcsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>Arguments</title>
-
-    <variablelist>
-	<varlistentry>
-	<term><parameter>fd</parameter></term>
-	<listitem>
-	  <para>&fd;</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><parameter>request</parameter></term>
-	<listitem>
-	  <para>VIDIOC_QUERY_DV_PRESET</para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term><parameter>argp</parameter></term>
-	<listitem>
-	  <para></para>
-	</listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-
-  <refsect1>
-    <title>Description</title>
-
-    <para>This ioctl is <emphasis role="bold">deprecated</emphasis>.
-    New drivers and applications should use &VIDIOC-QUERY-DV-TIMINGS; instead.
-    </para>
-
-    <para>The hardware may be able to detect the current DV preset
-automatically, similar to sensing the video standard. To do so, applications
-call <constant> VIDIOC_QUERY_DV_PRESET</constant> with a pointer to a
-&v4l2-dv-preset; type. Once the hardware detects a preset, that preset is
-returned in the preset field of &v4l2-dv-preset;. If the preset could not be
-detected because there was no signal, or the signal was unreliable, or the
-signal did not map to a supported preset, then the value V4L2_DV_INVALID is
-returned.</para>
-  </refsect1>
-
-  <refsect1>
-    &return-value;
-
-    <variablelist>
-      <varlistentry>
-	<term><errorcode>ENODATA</errorcode></term>
-	<listitem>
-	  <para>Digital video presets are not supported for this input or output.</para>
-	</listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-</refentry>

+ 1 - 0
Documentation/DocBook/media_api.tmpl

@@ -23,6 +23,7 @@
 <!-- LinuxTV v4l-dvb repository. -->
 <!ENTITY v4l-dvb		"<ulink url='http://linuxtv.org/repo/'>http://linuxtv.org/repo/</ulink>">
 <!ENTITY dash-ent-10            "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
+<!ENTITY dash-ent-16            "<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>-</entry><entry>-</entry>">
 ]>
 
 <book id="media_api">

+ 14 - 0
Documentation/devicetree/bindings/media/exynos-fimc-lite.txt

@@ -0,0 +1,14 @@
+Exynos4x12/Exynos5 SoC series camera host interface (FIMC-LITE)
+
+Required properties:
+
+- compatible	: should be "samsung,exynos4212-fimc" for Exynos4212 and
+		  Exynos4412 SoCs;
+- reg		: physical base address and size of the device memory mapped
+		  registers;
+- interrupts	: should contain FIMC-LITE interrupt;
+- clocks	: FIMC LITE gate clock should be specified in this property.
+- clock-names	: should contain "flite" entry.
+
+Each FIMC device should have an alias in the aliases node, in the form of
+fimc-lite<n>, where <n> is an integer specifying the IP block instance.

+ 49 - 0
Documentation/devicetree/bindings/media/exynos4-fimc-is.txt

@@ -0,0 +1,49 @@
+Exynos4x12 SoC series Imaging Subsystem (FIMC-IS)
+
+The FIMC-IS is a subsystem for processing image signal from an image sensor.
+The Exynos4x12 SoC series FIMC-IS V1.5 comprises of a dedicated ARM Cortex-A5
+processor, ISP, DRC and FD IP blocks and peripheral devices such as UART, I2C
+and SPI bus controllers, PWM and ADC.
+
+fimc-is node
+------------
+
+Required properties:
+- compatible	: should be "samsung,exynos4212-fimc-is" for Exynos4212 and
+		  Exynos4412 SoCs;
+- reg		: physical base address and length of the registers set;
+- interrupts	: must contain two FIMC-IS interrupts, in order: ISP0, ISP1;
+- clocks	: list of clock specifiers, corresponding to entries in
+		  clock-names property;
+- clock-names	: must contain "ppmuispx", "ppmuispx", "lite0", "lite1"
+		  "mpll", "sysreg", "isp", "drc", "fd", "mcuisp", "uart",
+		  "ispdiv0", "ispdiv1", "mcuispdiv0", "mcuispdiv1", "aclk200",
+		  "div_aclk200", "aclk400mcuisp", "div_aclk400mcuisp" entries,
+		  matching entries in the clocks property.
+pmu subnode
+-----------
+
+Required properties:
+ - reg : must contain PMU physical base address and size of the register set.
+
+The following are the FIMC-IS peripheral device nodes and can be specified
+either standalone or as the fimc-is node child nodes.
+
+i2c-isp (ISP I2C bus controller) nodes
+------------------------------------------
+
+Required properties:
+
+- compatible	: should be "samsung,exynos4212-i2c-isp" for Exynos4212 and
+		  Exynos4412 SoCs;
+- reg		: physical base address and length of the registers set;
+- clocks	: must contain gate clock specifier for this controller;
+- clock-names	: must contain "i2c_isp" entry.
+
+For the above nodes it is required to specify a pinctrl state named "default",
+according to the pinctrl bindings defined in ../pinctrl/pinctrl-bindings.txt.
+
+Device tree nodes of the image sensors' controlled directly by the FIMC-IS
+firmware must be child nodes of their corresponding ISP I2C bus controller node.
+The data link of these image sensors must be specified using the common video
+interfaces bindings, defined in video-interfaces.txt.

+ 197 - 0
Documentation/devicetree/bindings/media/samsung-fimc.txt

@@ -0,0 +1,197 @@
+Samsung S5P/EXYNOS SoC Camera Subsystem (FIMC)
+----------------------------------------------
+
+The S5P/Exynos SoC Camera subsystem comprises of multiple sub-devices
+represented by separate device tree nodes. Currently this includes: FIMC (in
+the S5P SoCs series known as CAMIF), MIPI CSIS, FIMC-LITE and FIMC-IS (ISP).
+
+The sub-subdevices are defined as child nodes of the common 'camera' node which
+also includes common properties of the whole subsystem not really specific to
+any single sub-device, like common camera port pins or the CAMCLK clock outputs
+for external image sensors attached to an SoC.
+
+Common 'camera' node
+--------------------
+
+Required properties:
+
+- compatible	: must be "samsung,fimc", "simple-bus"
+- clocks	: list of clock specifiers, corresponding to entries in
+		  the clock-names property;
+- clock-names	: must contain "sclk_cam0", "sclk_cam1", "pxl_async0",
+		  "pxl_async1" entries, matching entries in the clocks property.
+
+The pinctrl bindings defined in ../pinctrl/pinctrl-bindings.txt must be used
+to define a required pinctrl state named "default" and optional pinctrl states:
+"idle", "active-a", active-b". These optional states can be used to switch the
+camera port pinmux at runtime. The "idle" state should configure both the camera
+ports A and B into high impedance state, especially the CAMCLK clock output
+should be inactive. For the "active-a" state the camera port A must be activated
+and the port B deactivated and for the state "active-b" it should be the other
+way around.
+
+The 'camera' node must include at least one 'fimc' child node.
+
+'fimc' device nodes
+-------------------
+
+Required properties:
+
+- compatible: "samsung,s5pv210-fimc" for S5PV210, "samsung,exynos4210-fimc"
+  for Exynos4210 and "samsung,exynos4212-fimc" for Exynos4x12 SoCs;
+- reg: physical base address and length of the registers set for the device;
+- interrupts: should contain FIMC interrupt;
+- clocks: list of clock specifiers, must contain an entry for each required
+  entry in clock-names;
+- clock-names: must contain "fimc", "sclk_fimc" entries.
+- samsung,pix-limits: an array of maximum supported image sizes in pixels, for
+  details refer to Table 2-1 in the S5PV210 SoC User Manual; The meaning of
+  each cell is as follows:
+  0 - scaler input horizontal size,
+  1 - input horizontal size for the scaler bypassed,
+  2 - REAL_WIDTH without input rotation,
+  3 - REAL_HEIGHT with input rotation,
+- samsung,sysreg: a phandle to the SYSREG node.
+
+Each FIMC device should have an alias in the aliases node, in the form of
+fimc<n>, where <n> is an integer specifying the IP block instance.
+
+Optional properties:
+
+- clock-frequency: maximum FIMC local clock (LCLK) frequency;
+- samsung,min-pix-sizes: an array specyfing minimum image size in pixels at
+  the FIMC input and output DMA, in the first and second cell respectively.
+  Default value when this property is not present is <16 16>;
+- samsung,min-pix-alignment: minimum supported image height alignment (first
+  cell) and the horizontal image offset (second cell). The values are in pixels
+  and default to <2 1> when this property is not present;
+- samsung,mainscaler-ext: a boolean property indicating whether the FIMC IP
+  supports extended image size and has CIEXTEN register;
+- samsung,rotators: a bitmask specifying whether this IP has the input and
+  the output rotator. Bits 4 and 0 correspond to input and output rotator
+  respectively. If a rotator is present its corresponding bit should be set.
+  Default value when this property is not specified is 0x11.
+- samsung,cam-if: a bolean property indicating whether the IP block includes
+  the camera input interface.
+- samsung,isp-wb: this property must be present if the IP block has the ISP
+  writeback input.
+- samsung,lcd-wb: this property must be present if the IP block has the LCD
+  writeback input.
+
+
+'parallel-ports' node
+---------------------
+
+This node should contain child 'port' nodes specifying active parallel video
+input ports. It includes camera A and camera B inputs. 'reg' property in the
+port nodes specifies data input - 0, 1 indicates input A, B respectively.
+
+Optional properties
+
+- samsung,camclk-out : specifies clock output for remote sensor,
+		       0 - CAM_A_CLKOUT, 1 - CAM_B_CLKOUT;
+
+Image sensor nodes
+------------------
+
+The sensor device nodes should be added to their control bus controller (e.g.
+I2C0) nodes and linked to a port node in the csis or the parallel-ports node,
+using the common video interfaces bindings, defined in video-interfaces.txt.
+The implementation of this bindings requires clock-frequency property to be
+present in the sensor device nodes.
+
+Example:
+
+	aliases {
+		fimc0 = &fimc_0;
+	};
+
+	/* Parallel bus IF sensor */
+	i2c_0: i2c@13860000 {
+		s5k6aa: sensor@3c {
+			compatible = "samsung,s5k6aafx";
+			reg = <0x3c>;
+			vddio-supply = <...>;
+
+			clock-frequency = <24000000>;
+			clocks = <...>;
+			clock-names = "mclk";
+
+			port {
+				s5k6aa_ep: endpoint {
+					remote-endpoint = <&fimc0_ep>;
+					bus-width = <8>;
+					hsync-active = <0>;
+					vsync-active = <1>;
+					pclk-sample = <1>;
+				};
+			};
+		};
+	};
+
+	/* MIPI CSI-2 bus IF sensor */
+	s5c73m3: sensor@0x1a {
+		compatible = "samsung,s5c73m3";
+		reg = <0x1a>;
+		vddio-supply = <...>;
+
+		clock-frequency = <24000000>;
+		clocks = <...>;
+		clock-names = "mclk";
+
+		port {
+			s5c73m3_1: endpoint {
+				data-lanes = <1 2 3 4>;
+				remote-endpoint = <&csis0_ep>;
+			};
+		};
+	};
+
+	camera {
+		compatible = "samsung,fimc", "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		status = "okay";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&cam_port_a_clk_active>;
+
+		/* parallel camera ports */
+		parallel-ports {
+			/* camera A input */
+			port@0 {
+				reg = <0>;
+				fimc0_ep: endpoint {
+					remote-endpoint = <&s5k6aa_ep>;
+					bus-width = <8>;
+					hsync-active = <0>;
+					vsync-active = <1>;
+					pclk-sample = <1>;
+				};
+			};
+		};
+
+		fimc_0: fimc@11800000 {
+			compatible = "samsung,exynos4210-fimc";
+			reg = <0x11800000 0x1000>;
+			interrupts = <0 85 0>;
+			status = "okay";
+		};
+
+		csis_0: csis@11880000 {
+			compatible = "samsung,exynos4210-csis";
+			reg = <0x11880000 0x1000>;
+			interrupts = <0 78 0>;
+			/* camera C input */
+			port@3 {
+				reg = <3>;
+				csis0_ep: endpoint {
+					remote-endpoint = <&s5c73m3_ep>;
+					data-lanes = <1 2 3 4>;
+					samsung,csis-hs-settle = <12>;
+				};
+			};
+		};
+	};
+
+The MIPI-CSIS device binding is defined in samsung-mipi-csis.txt.

+ 81 - 0
Documentation/devicetree/bindings/media/samsung-mipi-csis.txt

@@ -0,0 +1,81 @@
+Samsung S5P/EXYNOS SoC series MIPI CSI-2 receiver (MIPI CSIS)
+-------------------------------------------------------------
+
+Required properties:
+
+- compatible	  : "samsung,s5pv210-csis" for S5PV210 (S5PC110),
+		    "samsung,exynos4210-csis" for Exynos4210 (S5PC210),
+		    "samsung,exynos4212-csis" for Exynos4212/Exynos4412
+		    SoC series;
+- reg		  : offset and length of the register set for the device;
+- interrupts      : should contain MIPI CSIS interrupt; the format of the
+		    interrupt specifier depends on the interrupt controller;
+- bus-width	  : maximum number of data lanes supported (SoC specific);
+- vddio-supply    : MIPI CSIS I/O and PLL voltage supply (e.g. 1.8V);
+- vddcore-supply  : MIPI CSIS Core voltage supply (e.g. 1.1V);
+- clocks	  : list of clock specifiers, corresponding to entries in
+		    clock-names property;
+- clock-names	  : must contain "csis", "sclk_csis" entries, matching entries
+		    in the clocks property.
+
+Optional properties:
+
+- clock-frequency : The IP's main (system bus) clock frequency in Hz, default
+		    value when this property is not specified is 166 MHz;
+- samsung,csis-wclk : CSI-2 wrapper clock selection. If this property is present
+		    external clock from CMU will be used, or the bus clock if
+		    if it's not specified.
+
+The device node should contain one 'port' child node with one child 'endpoint'
+node, according to the bindings defined in Documentation/devicetree/bindings/
+media/video-interfaces.txt. The following are properties specific to those nodes.
+
+port node
+---------
+
+- reg		  : (required) must be 3 for camera C input (CSIS0) or 4 for
+		    camera D input (CSIS1);
+
+endpoint node
+-------------
+
+- data-lanes	  : (required) an array specifying active physical MIPI-CSI2
+		    data input lanes and their mapping to logical lanes; the
+		    array's content is unused, only its length is meaningful;
+
+- samsung,csis-hs-settle : (optional) differential receiver (HS-RX) settle time;
+
+
+Example:
+
+	reg0: regulator@0 {
+	};
+
+	reg1: regulator@1 {
+	};
+
+/* SoC properties */
+
+	csis_0: csis@11880000 {
+		compatible = "samsung,exynos4210-csis";
+		reg = <0x11880000 0x1000>;
+		interrupts = <0 78 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+/* Board properties */
+
+	csis_0: csis@11880000 {
+		clock-frequency = <166000000>;
+		vddio-supply = <&reg0>;
+		vddcore-supply = <&reg1>;
+		port {
+			reg = <3>; /* 3 - CSIS0, 4 - CSIS1 */
+			csis0_ep: endpoint {
+				remote-endpoint = <...>;
+				data-lanes = <1>, <2>;
+				samsung,csis-hs-settle = <12>;
+			};
+		};
+	};

+ 228 - 0
Documentation/devicetree/bindings/media/video-interfaces.txt

@@ -0,0 +1,228 @@
+Common bindings for video receiver and transmitter interfaces
+
+General concept
+---------------
+
+Video data pipelines usually consist of external devices, e.g. camera sensors,
+controlled over an I2C, SPI or UART bus, and SoC internal IP blocks, including
+video DMA engines and video data processors.
+
+SoC internal blocks are described by DT nodes, placed similarly to other SoC
+blocks.  External devices are represented as child nodes of their respective
+bus controller nodes, e.g. I2C.
+
+Data interfaces on all video devices are described by their child 'port' nodes.
+Configuration of a port depends on other devices participating in the data
+transfer and is described by 'endpoint' subnodes.
+
+device {
+	...
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			...
+			endpoint@0 { ... };
+			endpoint@1 { ... };
+		};
+		port@1 { ... };
+	};
+};
+
+If a port can be configured to work with more than one remote device on the same
+bus, an 'endpoint' child node must be provided for each of them.  If more than
+one port is present in a device node or there is more than one endpoint at a
+port, or port node needs to be associated with a selected hardware interface,
+a common scheme using '#address-cells', '#size-cells' and 'reg' properties is
+used.
+
+All 'port' nodes can be grouped under optional 'ports' node, which allows to
+specify #address-cells, #size-cells properties independently for the 'port'
+and 'endpoint' nodes and any child device nodes a device might have.
+
+Two 'endpoint' nodes are linked with each other through their 'remote-endpoint'
+phandles.  An endpoint subnode of a device contains all properties needed for
+configuration of this device for data exchange with other device.  In most
+cases properties at the peer 'endpoint' nodes will be identical, however they
+might need to be different when there is any signal modifications on the bus
+between two devices, e.g. there are logic signal inverters on the lines.
+
+It is allowed for multiple endpoints at a port to be active simultaneously,
+where supported by a device.  For example, in case where a data interface of
+a device is partitioned into multiple data busses, e.g. 16-bit input port
+divided into two separate ITU-R BT.656 8-bit busses.  In such case bus-width
+and data-shift properties can be used to assign physical data lines to each
+endpoint node (logical bus).
+
+
+Required properties
+-------------------
+
+If there is more than one 'port' or more than one 'endpoint' node or 'reg'
+property is present in port and/or endpoint nodes the following properties
+are required in a relevant parent node:
+
+ - #address-cells : number of cells required to define port/endpoint
+		    identifier, should be 1.
+ - #size-cells    : should be zero.
+
+Optional endpoint properties
+----------------------------
+
+- remote-endpoint: phandle to an 'endpoint' subnode of a remote device node.
+- slave-mode: a boolean property indicating that the link is run in slave mode.
+  The default when this property is not specified is master mode. In the slave
+  mode horizontal and vertical synchronization signals are provided to the
+  slave device (data source) by the master device (data sink). In the master
+  mode the data source device is also the source of the synchronization signals.
+- bus-width: number of data lines actively used, valid for the parallel busses.
+- data-shift: on the parallel data busses, if bus-width is used to specify the
+  number of data lines, data-shift can be used to specify which data lines are
+  used, e.g. "bus-width=<8>; data-shift=<2>;" means, that lines 9:2 are used.
+- hsync-active: active state of the HSYNC signal, 0/1 for LOW/HIGH respectively.
+- vsync-active: active state of the VSYNC signal, 0/1 for LOW/HIGH respectively.
+  Note, that if HSYNC and VSYNC polarities are not specified, embedded
+  synchronization may be required, where supported.
+- data-active: similar to HSYNC and VSYNC, specifies data line polarity.
+- field-even-active: field signal level during the even field data transmission.
+- pclk-sample: sample data on rising (1) or falling (0) edge of the pixel clock
+  signal.
+- data-lanes: an array of physical data lane indexes. Position of an entry
+  determines the logical lane number, while the value of an entry indicates
+  physical lane, e.g. for 2-lane MIPI CSI-2 bus we could have
+  "data-lanes = <1 2>;", assuming the clock lane is on hardware lane 0.
+  This property is valid for serial busses only (e.g. MIPI CSI-2).
+- clock-lanes: an array of physical clock lane indexes. Position of an entry
+  determines the logical lane number, while the value of an entry indicates
+  physical lane, e.g. for a MIPI CSI-2 bus we could have "clock-lanes = <0>;",
+  which places the clock lane on hardware lane 0. This property is valid for
+  serial busses only (e.g. MIPI CSI-2). Note that for the MIPI CSI-2 bus this
+  array contains only one entry.
+- clock-noncontinuous: a boolean property to allow MIPI CSI-2 non-continuous
+  clock mode.
+
+
+Example
+-------
+
+The example snippet below describes two data pipelines.  ov772x and imx074 are
+camera sensors with a parallel and serial (MIPI CSI-2) video bus respectively.
+Both sensors are on the I2C control bus corresponding to the i2c0 controller
+node.  ov772x sensor is linked directly to the ceu0 video host interface.
+imx074 is linked to ceu0 through the MIPI CSI-2 receiver (csi2). ceu0 has a
+(single) DMA engine writing captured data to memory.  ceu0 node has a single
+'port' node which may indicate that at any time only one of the following data
+pipelines can be active: ov772x -> ceu0 or imx074 -> csi2 -> ceu0.
+
+	ceu0: ceu@0xfe910000 {
+		compatible = "renesas,sh-mobile-ceu";
+		reg = <0xfe910000 0xa0>;
+		interrupts = <0x880>;
+
+		mclk: master_clock {
+			compatible = "renesas,ceu-clock";
+			#clock-cells = <1>;
+			clock-frequency = <50000000>;	/* Max clock frequency */
+			clock-output-names = "mclk";
+		};
+
+		port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* Parallel bus endpoint */
+			ceu0_1: endpoint@1 {
+				reg = <1>;		/* Local endpoint # */
+				remote = <&ov772x_1_1>;	/* Remote phandle */
+				bus-width = <8>;	/* Used data lines */
+				data-shift = <2>;	/* Lines 9:2 are used */
+
+				/* If hsync-active/vsync-active are missing,
+				   embedded BT.656 sync is used */
+				hsync-active = <0>;	/* Active low */
+				vsync-active = <0>;	/* Active low */
+				data-active = <1>;	/* Active high */
+				pclk-sample = <1>;	/* Rising */
+			};
+
+			/* MIPI CSI-2 bus endpoint */
+			ceu0_0: endpoint@0 {
+				reg = <0>;
+				remote = <&csi2_2>;
+			};
+		};
+	};
+
+	i2c0: i2c@0xfff20000 {
+		...
+		ov772x_1: camera@0x21 {
+			compatible = "omnivision,ov772x";
+			reg = <0x21>;
+			vddio-supply = <&regulator1>;
+			vddcore-supply = <&regulator2>;
+
+			clock-frequency = <20000000>;
+			clocks = <&mclk 0>;
+			clock-names = "xclk";
+
+			port {
+				/* With 1 endpoint per port no need for addresses. */
+				ov772x_1_1: endpoint {
+					bus-width = <8>;
+					remote-endpoint = <&ceu0_1>;
+					hsync-active = <1>;
+					vsync-active = <0>; /* Who came up with an
+							       inverter here ?... */
+					data-active = <1>;
+					pclk-sample = <1>;
+				};
+			};
+		};
+
+		imx074: camera@0x1a {
+			compatible = "sony,imx074";
+			reg = <0x1a>;
+			vddio-supply = <&regulator1>;
+			vddcore-supply = <&regulator2>;
+
+			clock-frequency = <30000000>;	/* Shared clock with ov772x_1 */
+			clocks = <&mclk 0>;
+			clock-names = "sysclk";		/* Assuming this is the
+							   name in the datasheet */
+			port {
+				imx074_1: endpoint {
+					clock-lanes = <0>;
+					data-lanes = <1 2>;
+					remote-endpoint = <&csi2_1>;
+				};
+			};
+		};
+	};
+
+	csi2: csi2@0xffc90000 {
+		compatible = "renesas,sh-mobile-csi2";
+		reg = <0xffc90000 0x1000>;
+		interrupts = <0x17a0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@1 {
+			compatible = "renesas,csi2c";	/* One of CSI2I and CSI2C. */
+			reg = <1>;			/* CSI-2 PHY #1 of 2: PHY_S,
+							   PHY_M has port address 0,
+							   is unused. */
+			csi2_1: endpoint {
+				clock-lanes = <0>;
+				data-lanes = <2 1>;
+				remote-endpoint = <&imx074_1>;
+			};
+		};
+		port@2 {
+			reg = <2>;			/* port 2: link to the CEU */
+
+			csi2_2: endpoint {
+				remote-endpoint = <&ceu0_0>;
+			};
+		};
+	};

+ 2 - 1
Documentation/video4linux/CARDLIST.em28xx

@@ -76,7 +76,7 @@
  76 -> KWorld PlusTV 340U or UB435-Q (ATSC)     (em2870)        [1b80:a340]
  77 -> EM2874 Leadership ISDBT                  (em2874)
  78 -> PCTV nanoStick T2 290e                   (em28174)
- 79 -> Terratec Cinergy H5                      (em2884)        [0ccd:10a2,0ccd:10ad]
+ 79 -> Terratec Cinergy H5                      (em2884)        [0ccd:10a2,0ccd:10ad,0ccd:10b6]
  80 -> PCTV DVB-S2 Stick (460e)                 (em28174)
  81 -> Hauppauge WinTV HVR 930C                 (em2884)        [2040:1605]
  82 -> Terratec Cinergy HTC Stick               (em2884)        [0ccd:00b2]
@@ -85,3 +85,4 @@
  85 -> PCTV QuatroStick (510e)                  (em2884)        [2304:0242]
  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]

+ 3 - 0
Documentation/video4linux/CARDLIST.tuner

@@ -86,3 +86,6 @@ tuner=85 - Philips FQ1236 MK5
 tuner=86 - Tena TNF5337 MFD
 tuner=87 - Xceive 4000 tuner
 tuner=88 - Xceive 5000C tuner
+tuner=89 - Sony PAL+SECAM (BTF-PG472Z)
+tuner=90 - Sony NTSC-M-JP (BTF-PK467Z)
+tuner=91 - Sony NTSC-M (BTF-PB463Z)

+ 187 - 0
Documentation/video4linux/si476x.txt

@@ -0,0 +1,187 @@
+SI476x Driver Readme
+------------------------------------------------
+	Copyright (C) 2013 Andrey Smirnov <andrew.smirnov@gmail.com>
+
+TODO for the driver
+------------------------------
+
+- According to the SiLabs' datasheet it is possible to update the
+  firmware of the radio chip in the run-time, thus bringing it to the
+  most recent version. Unfortunately I couldn't find any mentioning of
+  the said firmware update for the old chips that I tested the driver
+  against, so for chips like that the driver only exposes the old
+  functionality.
+
+
+Parameters exposed over debugfs
+-------------------------------
+SI476x allow user to get multiple characteristics that can be very
+useful for EoL testing/RF performance estimation, parameters that have
+very little to do with V4L2 subsystem. Such parameters are exposed via
+debugfs and can be accessed via regular file I/O operations.
+
+The drivers exposes following files:
+
+* /sys/kernel/debug/<device-name>/acf
+  This file contains ACF(Automatically Controlled Features) status
+  information. The contents of the file is binary data of the
+  following layout:
+
+  Offset	| Name		| Description
+  ====================================================================
+  0x00		| blend_int	| Flag, set when stereo separation has
+  		|  		| crossed below the blend threshold
+  --------------------------------------------------------------------
+  0x01		| hblend_int	| Flag, set when HiBlend cutoff
+  		| 		| frequency is lower than threshold
+  --------------------------------------------------------------------
+  0x02		| hicut_int	| Flag, set when HiCut cutoff
+  		| 		| frequency is lower than threshold
+  --------------------------------------------------------------------
+  0x03		| chbw_int	| Flag, set when channel filter
+  		| 		| bandwidth is less than threshold
+  --------------------------------------------------------------------
+  0x04		| softmute_int	| Flag indicating that softmute
+  		| 		| attenuation has increased above
+		|		| softmute threshold
+  --------------------------------------------------------------------
+  0x05		| smute		| 0 - Audio is not soft muted
+  		| 		| 1 - Audio is soft muted
+  --------------------------------------------------------------------
+  0x06		| smattn	| Soft mute attenuation level in dB
+  --------------------------------------------------------------------
+  0x07		| chbw		| Channel filter bandwidth in kHz
+  --------------------------------------------------------------------
+  0x08		| hicut		| HiCut cutoff frequency in units of
+  		| 		| 100Hz
+  --------------------------------------------------------------------
+  0x09		| hiblend	| HiBlend cutoff frequency in units
+  		| 		| of 100 Hz
+  --------------------------------------------------------------------
+  0x10		| pilot		| 0 - Stereo pilot is not present
+  		| 		| 1 - Stereo pilot is present
+  --------------------------------------------------------------------
+  0x11		| stblend	| Stereo blend in %
+  --------------------------------------------------------------------
+
+
+* /sys/kernel/debug/<device-name>/rds_blckcnt
+  This file contains statistics about RDS receptions. It's binary data
+  has the following layout:
+
+  Offset	| Name		| Description
+  ====================================================================
+  0x00		| expected	| Number of expected RDS blocks
+  --------------------------------------------------------------------
+  0x02		| received	| Number of received RDS blocks
+  --------------------------------------------------------------------
+  0x04		| uncorrectable	| Number of uncorrectable RDS blocks
+  --------------------------------------------------------------------
+
+* /sys/kernel/debug/<device-name>/agc
+  This file contains information about parameters pertaining to
+  AGC(Automatic Gain Control)
+
+  The layout is:
+  Offset	| Name		| Description
+  ====================================================================
+  0x00		| mxhi		| 0 - FM Mixer PD high threshold is
+  		| 		| not tripped
+		|		| 1 - FM Mixer PD high threshold is
+		|		| tripped
+  --------------------------------------------------------------------
+  0x01		| mxlo		| ditto for FM Mixer PD low
+  --------------------------------------------------------------------
+  0x02		| lnahi		| ditto for FM LNA PD high
+  --------------------------------------------------------------------
+  0x03		| lnalo		| ditto for FM LNA PD low
+  --------------------------------------------------------------------
+  0x04		| fmagc1	| FMAGC1 attenuator resistance
+  		| 		| (see datasheet for more detail)
+  --------------------------------------------------------------------
+  0x05		| fmagc2	| ditto for FMAGC2
+  --------------------------------------------------------------------
+  0x06		| pgagain	| PGA gain in dB
+  --------------------------------------------------------------------
+  0x07		| fmwblang	| FM/WB LNA Gain in dB
+  --------------------------------------------------------------------
+
+* /sys/kernel/debug/<device-name>/rsq
+  This file contains information about parameters pertaining to
+  RSQ(Received Signal Quality)
+
+  The layout is:
+  Offset	| Name		| Description
+  ====================================================================
+  0x00		| multhint	| 0 - multipath value has not crossed
+  		| 		| the Multipath high threshold
+		|		| 1 - multipath value has crossed
+  		| 		| the Multipath high threshold
+  --------------------------------------------------------------------
+  0x01		| multlint	| ditto for Multipath low threshold
+  --------------------------------------------------------------------
+  0x02		| snrhint	| 0 - received signal's SNR has not
+  		| 		| crossed high threshold
+		|		| 1 - received signal's SNR has
+  		| 		| crossed high threshold
+  --------------------------------------------------------------------
+  0x03		| snrlint	| ditto for low threshold
+  --------------------------------------------------------------------
+  0x04		| rssihint	| ditto for RSSI high threshold
+  --------------------------------------------------------------------
+  0x05		| rssilint	| ditto for RSSI low threshold
+  --------------------------------------------------------------------
+  0x06		| bltf		| Flag indicating if seek command
+  		| 		| reached/wrapped seek band limit
+  --------------------------------------------------------------------
+  0x07		| snr_ready	| Indicates that SNR metrics is ready
+  --------------------------------------------------------------------
+  0x08		| rssiready	| ditto for RSSI metrics
+  --------------------------------------------------------------------
+  0x09		| injside	| 0 - Low-side injection is being used
+  		| 		| 1 - High-side injection is used
+  --------------------------------------------------------------------
+  0x10		| afcrl		| Flag indicating if AFC rails
+  --------------------------------------------------------------------
+  0x11		| valid		| Flag indicating if channel is valid
+  --------------------------------------------------------------------
+  0x12		| readfreq	| Current tuned frequency
+  --------------------------------------------------------------------
+  0x14		| freqoff	| Singed frequency offset in units of
+  		| 		| 2ppm
+  --------------------------------------------------------------------
+  0x15		| rssi		| Signed value of RSSI in dBuV
+  --------------------------------------------------------------------
+  0x16		| snr		| Signed RF SNR in dB
+  --------------------------------------------------------------------
+  0x17		| issi		| Signed Image Strength Signal
+  		| 		| indicator
+  --------------------------------------------------------------------
+  0x18		| lassi		| Signed Low side adjacent Channel
+  		| 		| Strength indicator
+  --------------------------------------------------------------------
+  0x19		| hassi		| ditto fpr High side
+  --------------------------------------------------------------------
+  0x20		| mult		| Multipath indicator
+  --------------------------------------------------------------------
+  0x21		| dev		| Frequency deviation
+  --------------------------------------------------------------------
+  0x24		| assi		| Adjascent channel SSI
+  --------------------------------------------------------------------
+  0x25		| usn		| Ultrasonic noise indicator
+  --------------------------------------------------------------------
+  0x26		| pilotdev	| Pilot deviation in units of 100 Hz
+  --------------------------------------------------------------------
+  0x27		| rdsdev	| ditto for RDS
+  --------------------------------------------------------------------
+  0x28		| assidev	| ditto for ASSI
+  --------------------------------------------------------------------
+  0x29		| strongdev	| Frequency deviation
+  --------------------------------------------------------------------
+  0x30		| rdspi		| RDS PI code
+  --------------------------------------------------------------------
+
+* /sys/kernel/debug/<device-name>/rsq_primary
+  This file contains information about parameters pertaining to
+  RSQ(Received Signal Quality) for primary tuner only. Layout is as
+  the one above.

+ 83 - 17
MAINTAINERS

@@ -2287,7 +2287,7 @@ L:	linux-media@vger.kernel.org
 T:	git git://linuxtv.org/media_tree.git
 W:	http://linuxtv.org
 S:	Maintained
-F:	drivers/media/i2c/cx2341x*
+F:	drivers/media/common/cx2341x*
 F:	include/media/cx2341x*
 
 CX88 VIDEO4LINUX DRIVER
@@ -2370,6 +2370,16 @@ W:	http://www.cyclades.com/
 S:	Orphan
 F:	drivers/net/wan/pc300*
 
+CYPRESS_FIRMWARE 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/media/common/cypress_firmware*
+
 CYTTSP TOUCHSCREEN DRIVER
 M:	Javier Martinez Canillas <javier@dowhile0.org>
 L:	linux-input@vger.kernel.org
@@ -2738,7 +2748,7 @@ T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
 F:	drivers/media/usb/dvb-usb/cxusb*
 
-DVB_USB_CYPRESS_FIRMWARE MEDIA DRIVER
+DVB_USB_EC168 MEDIA DRIVER
 M:	Antti Palosaari <crope@iki.fi>
 L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org/
@@ -2746,17 +2756,16 @@ 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/media/usb/dvb-usb-v2/cypress_firmware*
+F:	drivers/media/usb/dvb-usb-v2/ec168*
 
-DVB_USB_EC168 MEDIA DRIVER
+DVB_USB_GL861 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/media/usb/dvb-usb-v2/ec168*
+F:	drivers/media/usb/dvb-usb-v2/gl861*
 
 DVB_USB_MXL111SF MEDIA DRIVER
 M:	Michael Krufky <mkrufky@linuxtv.org>
@@ -3600,6 +3609,14 @@ W:	http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/
 S:	Maintained
 F:	drivers/platform/x86/hdaps.c
 
+HDPVR USB VIDEO ENCODER DRIVER
+M:	Hans Verkuil <hverkuil@xs4all.nl>
+L:	linux-media@vger.kernel.org
+T:	git git://linuxtv.org/media_tree.git
+W:	http://linuxtv.org
+S:	Odd Fixes
+F:	drivers/media/usb/hdpvr
+
 HWPOISON MEMORY FAILURE HANDLING
 M:	Andi Kleen <andi@firstfloor.org>
 L:	linux-mm@kvack.org
@@ -4429,6 +4446,16 @@ 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/
+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/media/tuners/it913x*
+
 IVTV VIDEO4LINUX DRIVER
 M:	Andy Walls <awalls@md.metrocast.net>
 L:	ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
@@ -6703,6 +6730,16 @@ T:	git git://linuxtv.org/anttip/media_tree.git
 S:	Maintained
 F:	drivers/media/dvb-frontends/rtl2830*
 
+RTL2832 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/media/dvb-frontends/rtl2832*
+
 RTL8180 WIRELESS DRIVER
 M:	"John W. Linville" <linville@tuxdriver.com>
 L:	linux-wireless@vger.kernel.org
@@ -6805,7 +6842,7 @@ L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org
 T:	git git://linuxtv.org/media_tree.git
 S:	Odd fixes
-F:	Documentation/video4linux/saa7134/
+F:	Documentation/video4linux/*.saa7134
 F:	drivers/media/pci/saa7134/
 
 SAA7146 VIDEO4LINUX-2 DRIVER
@@ -6898,9 +6935,8 @@ F:	drivers/clocksource
 
 TLG2300 VIDEO4LINUX-2 DRIVER
 M:	Huang Shijie <shijie8@gmail.com>
-M:	Kang Yong <kangyong@telegent.com>
-M:	Zhang Xiaobing <xbzhang@telegent.com>
-S:	Supported
+M:	Hans Verkuil <hverkuil@xs4all.nl>
+S:	Odd Fixes
 F:	drivers/media/usb/tlg2300
 
 SC1200 WDT DRIVER
@@ -7146,17 +7182,43 @@ F:	drivers/media/radio/si470x/radio-si470x-common.c
 F:	drivers/media/radio/si470x/radio-si470x.h
 F:	drivers/media/radio/si470x/radio-si470x-usb.c
 
+SI4713 FM RADIO TRANSMITTER I2C DRIVER
+M:	Eduardo Valentin <edubezval@gmail.com>
+L:	linux-media@vger.kernel.org
+T:	git git://linuxtv.org/media_tree.git
+W:	http://linuxtv.org
+S:	Odd Fixes
+F:	drivers/media/radio/si4713-i2c.?
+
+SI4713 FM RADIO TRANSMITTER PLATFORM DRIVER
+M:	Eduardo Valentin <edubezval@gmail.com>
+L:	linux-media@vger.kernel.org
+T:	git git://linuxtv.org/media_tree.git
+W:	http://linuxtv.org
+S:	Odd Fixes
+F:	drivers/media/radio/radio-si4713.h
+
+SIANO DVB DRIVER
+M:	Mauro Carvalho Chehab <mchehab@redhat.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Odd fixes
+F:	drivers/media/common/siano/
+F:	drivers/media/dvb/siano/
+F:	drivers/media/usb/siano/
+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
 F:	drivers/media/platform/sh_veu.c
-F:	include/media/sh_veu.h
 
 SH_VOU V4L2 OUTPUT DRIVER
 M:	Guennadi Liakhovetski <g.liakhovetski@gmx.de>
 L:	linux-media@vger.kernel.org
-S:	Maintained
+S:	Odd Fixes
 F:	drivers/media/platform/sh_vou.c
 F:	include/media/sh_vou.h
 
@@ -7198,14 +7260,13 @@ F:	arch/arm/mach-davinci
 F:	drivers/i2c/busses/i2c-davinci.c
 
 TI DAVINCI SERIES MEDIA DRIVER
-M:	Manjunath Hadli <manjunath.hadli@ti.com>
-M:	Prabhakar Lad <prabhakar.lad@ti.com>
+M:	Lad, Prabhakar <prabhakar.csengg@gmail.com>
 L:	linux-media@vger.kernel.org
 L:	davinci-linux-open-source@linux.davincidsp.com (moderated for non-subscribers)
 W:	http://linuxtv.org/
 Q:	http://patchwork.linuxtv.org/project/linux-media/list/
 T:	git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
-S:	Supported
+S:	Maintained
 F:	drivers/media/platform/davinci/
 F:	include/media/davinci/
 
@@ -7577,6 +7638,11 @@ M:	David Täht <d@teklibre.com>
 S:	Odd Fixes
 F:	drivers/staging/frontier/
 
+STAGING - GO7007 MPEG CODEC
+M:	Hans Verkuil <hans.verkuil@cisco.com>
+S:	Maintained
+F:	drivers/staging/media/go7007/
+
 STAGING - INDUSTRIAL IO
 M:	Jonathan Cameron <jic23@cam.ac.uk>
 L:	linux-iio@vger.kernel.org
@@ -7627,8 +7693,8 @@ S:	Odd Fixes
 F:	drivers/staging/sm7xxfb/
 
 STAGING - SOFTLOGIC 6x10 MPEG CODEC
-M:	Ben Collins <bcollins@bluecherry.net>
-S:	Odd Fixes
+M:	Ismael Luceno <ismael.luceno@corp.bluecherry.net>
+S:	Supported
 F:	drivers/staging/media/solo6x10/
 
 STAGING - SPEAKUP CONSOLE SPEECH DRIVER

+ 69 - 2
arch/arm/mach-davinci/board-dm355-evm.c

@@ -242,6 +242,73 @@ static struct vpfe_config vpfe_cfg = {
 	.ccdc = "DM355 CCDC",
 };
 
+/* venc standards timings */
+static struct vpbe_enc_mode_info dm355evm_enc_preset_timing[] = {
+	{
+		.name		= "ntsc",
+		.timings_type	= VPBE_ENC_STD,
+		.std_id		= V4L2_STD_NTSC,
+		.interlaced	= 1,
+		.xres		= 720,
+		.yres		= 480,
+		.aspect		= {11, 10},
+		.fps		= {30000, 1001},
+		.left_margin	= 0x79,
+		.upper_margin	= 0x10,
+	},
+	{
+		.name		= "pal",
+		.timings_type	= VPBE_ENC_STD,
+		.std_id		= V4L2_STD_PAL,
+		.interlaced	= 1,
+		.xres		= 720,
+		.yres		= 576,
+		.aspect		= {54, 59},
+		.fps		= {25, 1},
+		.left_margin	= 0x7E,
+		.upper_margin	= 0x16
+	},
+};
+
+#define VENC_STD_ALL	(V4L2_STD_NTSC | V4L2_STD_PAL)
+
+/*
+ * The outputs available from VPBE + ecnoders. Keep the
+ * the order same as that of encoders. First those from venc followed by that
+ * from encoders. Index in the output refers to index on a particular encoder.
+ * Driver uses this index to pass it to encoder when it supports more than
+ * one output. Application uses index of the array to set an output.
+ */
+static struct vpbe_output dm355evm_vpbe_outputs[] = {
+	{
+		.output		= {
+			.index		= 0,
+			.name		= "Composite",
+			.type		= V4L2_OUTPUT_TYPE_ANALOG,
+			.std		= VENC_STD_ALL,
+			.capabilities	= V4L2_OUT_CAP_STD,
+		},
+		.subdev_name	= DM355_VPBE_VENC_SUBDEV_NAME,
+		.default_mode	= "ntsc",
+		.num_modes	= ARRAY_SIZE(dm355evm_enc_preset_timing),
+		.modes		= dm355evm_enc_preset_timing,
+		.if_params	= V4L2_MBUS_FMT_FIXED,
+	},
+};
+
+static struct vpbe_config dm355evm_display_cfg = {
+	.module_name	= "dm355-vpbe-display",
+	.i2c_adapter_id	= 1,
+	.osd		= {
+		.module_name	= DM355_VPBE_OSD_SUBDEV_NAME,
+	},
+	.venc		= {
+		.module_name	= DM355_VPBE_VENC_SUBDEV_NAME,
+	},
+	.num_outputs	= ARRAY_SIZE(dm355evm_vpbe_outputs),
+	.outputs	= dm355evm_vpbe_outputs,
+};
+
 static struct platform_device *davinci_evm_devices[] __initdata = {
 	&dm355evm_dm9000,
 	&davinci_nand_device,
@@ -253,8 +320,6 @@ static struct davinci_uart_config uart_config __initdata = {
 
 static void __init dm355_evm_map_io(void)
 {
-	/* setup input configuration for VPFE input devices */
-	dm355_set_vpfe_config(&vpfe_cfg);
 	dm355_init();
 }
 
@@ -344,6 +409,8 @@ static __init void dm355_evm_init(void)
 	davinci_setup_mmc(0, &dm355evm_mmc_config);
 	davinci_setup_mmc(1, &dm355evm_mmc_config);
 
+	dm355_init_video(&vpfe_cfg, &dm355evm_display_cfg);
+
 	dm355_init_spi0(BIT(0), dm355_evm_spi_info,
 			ARRAY_SIZE(dm355_evm_spi_info));
 

+ 164 - 2
arch/arm/mach-davinci/board-dm365-evm.c

@@ -27,6 +27,7 @@
 #include <linux/input.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/eeprom.h>
+#include <linux/v4l2-dv-timings.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -39,6 +40,7 @@
 #include <linux/platform_data/mtd-davinci.h>
 #include <linux/platform_data/keyscan-davinci.h>
 
+#include <media/ths7303.h>
 #include <media/tvp514x.h>
 
 #include "davinci.h"
@@ -374,6 +376,166 @@ static struct vpfe_config vpfe_cfg = {
 	.ccdc = "ISIF",
 };
 
+/* venc standards timings */
+static struct vpbe_enc_mode_info dm365evm_enc_std_timing[] = {
+	{
+		.name		= "ntsc",
+		.timings_type	= VPBE_ENC_STD,
+		.std_id		= V4L2_STD_NTSC,
+		.interlaced	= 1,
+		.xres		= 720,
+		.yres		= 480,
+		.aspect		= {11, 10},
+		.fps		= {30000, 1001},
+		.left_margin	= 0x79,
+		.upper_margin	= 0x10,
+	},
+	{
+		.name		= "pal",
+		.timings_type	= VPBE_ENC_STD,
+		.std_id		= V4L2_STD_PAL,
+		.interlaced	= 1,
+		.xres		= 720,
+		.yres		= 576,
+		.aspect		= {54, 59},
+		.fps		= {25, 1},
+		.left_margin	= 0x7E,
+		.upper_margin	= 0x16,
+	},
+};
+
+/* venc dv timings */
+static struct vpbe_enc_mode_info dm365evm_enc_preset_timing[] = {
+	{
+		.name		= "480p59_94",
+		.timings_type	= VPBE_ENC_DV_TIMINGS,
+		.dv_timings	= V4L2_DV_BT_CEA_720X480P59_94,
+		.interlaced	= 0,
+		.xres		= 720,
+		.yres		= 480,
+		.aspect		= {1, 1},
+		.fps		= {5994, 100},
+		.left_margin	= 0x8F,
+		.upper_margin	= 0x2D,
+	},
+	{
+		.name		= "576p50",
+		.timings_type	= VPBE_ENC_DV_TIMINGS,
+		.dv_timings	= V4L2_DV_BT_CEA_720X576P50,
+		.interlaced	= 0,
+		.xres		= 720,
+		.yres		= 576,
+		.aspect		= {1, 1},
+		.fps		= {50, 1},
+		.left_margin	= 0x8C,
+		.upper_margin   = 0x36,
+	},
+	{
+		.name		= "720p60",
+		.timings_type	= VPBE_ENC_DV_TIMINGS,
+		.dv_timings	= V4L2_DV_BT_CEA_1280X720P60,
+		.interlaced	= 0,
+		.xres		= 1280,
+		.yres		= 720,
+		.aspect		= {1, 1},
+		.fps		= {60, 1},
+		.left_margin	= 0x117,
+		.right_margin	= 70,
+		.upper_margin	= 38,
+		.lower_margin	= 3,
+		.hsync_len	= 80,
+		.vsync_len	= 5,
+	},
+	{
+		.name		= "1080i60",
+		.timings_type	= VPBE_ENC_DV_TIMINGS,
+		.dv_timings	= V4L2_DV_BT_CEA_1920X1080I60,
+		.interlaced	= 1,
+		.xres		= 1920,
+		.yres		= 1080,
+		.aspect		= {1, 1},
+		.fps		= {30, 1},
+		.left_margin	= 0xc9,
+		.right_margin	= 80,
+		.upper_margin	= 30,
+		.lower_margin	= 3,
+		.hsync_len	= 88,
+		.vsync_len	= 5,
+	},
+};
+
+#define VENC_STD_ALL	(V4L2_STD_NTSC | V4L2_STD_PAL)
+
+/*
+ * The outputs available from VPBE + ecnoders. Keep the
+ * the order same as that of encoders. First those from venc followed by that
+ * from encoders. Index in the output refers to index on a particular
+ * encoder.Driver uses this index to pass it to encoder when it supports more
+ * than one output. Application uses index of the array to set an output.
+ */
+static struct vpbe_output dm365evm_vpbe_outputs[] = {
+	{
+		.output		= {
+			.index		= 0,
+			.name		= "Composite",
+			.type		= V4L2_OUTPUT_TYPE_ANALOG,
+			.std		= VENC_STD_ALL,
+			.capabilities	= V4L2_OUT_CAP_STD,
+		},
+		.subdev_name	= DM365_VPBE_VENC_SUBDEV_NAME,
+		.default_mode	= "ntsc",
+		.num_modes	= ARRAY_SIZE(dm365evm_enc_std_timing),
+		.modes		= dm365evm_enc_std_timing,
+		.if_params	= V4L2_MBUS_FMT_FIXED,
+	},
+	{
+		.output		= {
+			.index		= 1,
+			.name		= "Component",
+			.type		= V4L2_OUTPUT_TYPE_ANALOG,
+			.capabilities	= V4L2_OUT_CAP_DV_TIMINGS,
+		},
+		.subdev_name	= DM365_VPBE_VENC_SUBDEV_NAME,
+		.default_mode	= "480p59_94",
+		.num_modes	= ARRAY_SIZE(dm365evm_enc_preset_timing),
+		.modes		= dm365evm_enc_preset_timing,
+		.if_params	= V4L2_MBUS_FMT_FIXED,
+	},
+};
+
+/*
+ * Amplifiers on the board
+ */
+struct ths7303_platform_data ths7303_pdata = {
+	.ch_1 = 3,
+	.ch_2 = 3,
+	.ch_3 = 3,
+	.init_enable = 1,
+};
+
+static struct amp_config_info vpbe_amp = {
+	.module_name	= "ths7303",
+	.is_i2c		= 1,
+	.board_info	= {
+		I2C_BOARD_INFO("ths7303", 0x2c),
+		.platform_data = &ths7303_pdata,
+	}
+};
+
+static struct vpbe_config dm365evm_display_cfg = {
+	.module_name	= "dm365-vpbe-display",
+	.i2c_adapter_id	= 1,
+	.amp		= &vpbe_amp,
+	.osd		= {
+		.module_name	= DM365_VPBE_OSD_SUBDEV_NAME,
+	},
+	.venc		= {
+		.module_name	= DM365_VPBE_VENC_SUBDEV_NAME,
+	},
+	.num_outputs	= ARRAY_SIZE(dm365evm_vpbe_outputs),
+	.outputs	= dm365evm_vpbe_outputs,
+};
+
 static void __init evm_init_i2c(void)
 {
 	davinci_init_i2c(&i2c_pdata);
@@ -564,8 +726,6 @@ static struct davinci_uart_config uart_config __initdata = {
 
 static void __init dm365_evm_map_io(void)
 {
-	/* setup input configuration for VPFE input devices */
-	dm365_set_vpfe_config(&vpfe_cfg);
 	dm365_init();
 }
 
@@ -597,6 +757,8 @@ static __init void dm365_evm_init(void)
 
 	davinci_setup_mmc(0, &dm365evm_mmc_config);
 
+	dm365_init_video(&vpfe_cfg, &dm365evm_display_cfg);
+
 	/* maybe setup mmc1/etc ... _after_ mmc0 */
 	evm_init_cpld();
 

+ 4 - 4
arch/arm/mach-davinci/board-dm644x-evm.c

@@ -622,7 +622,7 @@ static struct vpbe_enc_mode_info dm644xevm_enc_std_timing[] = {
 	{
 		.name		= "ntsc",
 		.timings_type	= VPBE_ENC_STD,
-		.std_id		= V4L2_STD_525_60,
+		.std_id		= V4L2_STD_NTSC,
 		.interlaced	= 1,
 		.xres		= 720,
 		.yres		= 480,
@@ -634,7 +634,7 @@ static struct vpbe_enc_mode_info dm644xevm_enc_std_timing[] = {
 	{
 		.name		= "pal",
 		.timings_type	= VPBE_ENC_STD,
-		.std_id		= V4L2_STD_625_50,
+		.std_id		= V4L2_STD_PAL,
 		.interlaced	= 1,
 		.xres		= 720,
 		.yres		= 576,
@@ -649,7 +649,7 @@ static struct vpbe_enc_mode_info dm644xevm_enc_std_timing[] = {
 static struct vpbe_enc_mode_info dm644xevm_enc_preset_timing[] = {
 	{
 		.name		= "480p59_94",
-		.timings_type	= VPBE_ENC_CUSTOM_TIMINGS,
+		.timings_type	= VPBE_ENC_DV_TIMINGS,
 		.dv_timings	= V4L2_DV_BT_CEA_720X480P59_94,
 		.interlaced	= 0,
 		.xres		= 720,
@@ -661,7 +661,7 @@ static struct vpbe_enc_mode_info dm644xevm_enc_preset_timing[] = {
 	},
 	{
 		.name		= "576p50",
-		.timings_type	= VPBE_ENC_CUSTOM_TIMINGS,
+		.timings_type	= VPBE_ENC_DV_TIMINGS,
 		.dv_timings	= V4L2_DV_BT_CEA_720X576P50,
 		.interlaced	= 0,
 		.xres		= 720,

+ 1 - 1
arch/arm/mach-davinci/board-dm646x-evm.c

@@ -514,7 +514,7 @@ static const struct vpif_output dm6467_ch0_outputs[] = {
 			.index = 1,
 			.name = "Component",
 			.type = V4L2_OUTPUT_TYPE_ANALOG,
-			.capabilities = V4L2_OUT_CAP_CUSTOM_TIMINGS,
+			.capabilities = V4L2_OUT_CAP_DV_TIMINGS,
 		},
 		.subdev_name = "adv7343",
 		.output_route = ADV7343_COMPONENT_ID,

+ 9 - 2
arch/arm/mach-davinci/davinci.h

@@ -36,12 +36,19 @@
 #include <media/davinci/vpbe_osd.h>
 
 #define DAVINCI_SYSTEM_MODULE_BASE	0x01c40000
+#define SYSMOD_VDAC_CONFIG		0x2c
 #define SYSMOD_VIDCLKCTL		0x38
 #define SYSMOD_VPSS_CLKCTL		0x44
 #define SYSMOD_VDD3P3VPWDN		0x48
 #define SYSMOD_VSCLKDIS			0x6c
 #define SYSMOD_PUPDCTL1			0x7c
 
+/* VPSS CLKCTL bit definitions */
+#define VPSS_MUXSEL_EXTCLK_ENABLE	BIT(1)
+#define VPSS_VENCCLKEN_ENABLE		BIT(3)
+#define VPSS_DACCLKEN_ENABLE		BIT(4)
+#define VPSS_PLLC2SYSCLK5_ENABLE	BIT(5)
+
 extern void __iomem *davinci_sysmod_base;
 #define DAVINCI_SYSMOD_VIRT(x)	(davinci_sysmod_base + (x))
 void davinci_map_sysmod(void);
@@ -74,7 +81,7 @@ void __init dm355_init(void);
 void dm355_init_spi0(unsigned chipselect_mask,
 		const struct spi_board_info *info, unsigned len);
 void __init dm355_init_asp1(u32 evt_enable, struct snd_platform_data *pdata);
-void dm355_set_vpfe_config(struct vpfe_config *cfg);
+int dm355_init_video(struct vpfe_config *, struct vpbe_config *);
 
 /* DM365 function declarations */
 void __init dm365_init(void);
@@ -84,7 +91,7 @@ void __init dm365_init_ks(struct davinci_ks_platform_data *pdata);
 void __init dm365_init_rtc(void);
 void dm365_init_spi0(unsigned chipselect_mask,
 			const struct spi_board_info *info, unsigned len);
-void dm365_set_vpfe_config(struct vpfe_config *cfg);
+int dm365_init_video(struct vpfe_config *, struct vpbe_config *);
 
 /* DM644x function declarations */
 void __init dm644x_init(void);

+ 164 - 10
arch/arm/mach-davinci/dm355.c

@@ -35,6 +35,8 @@
 #include "asp.h"
 
 #define DM355_UART2_BASE	(IO_PHYS + 0x206000)
+#define DM355_OSD_BASE		(IO_PHYS + 0x70200)
+#define DM355_VENC_BASE		(IO_PHYS + 0x70400)
 
 /*
  * Device specific clocks
@@ -345,8 +347,8 @@ static struct clk_lookup dm355_clks[] = {
 	CLK(NULL, "pll1_aux", &pll1_aux_clk),
 	CLK(NULL, "pll1_sysclkbp", &pll1_sysclkbp),
 	CLK(NULL, "vpss_dac", &vpss_dac_clk),
-	CLK(NULL, "vpss_master", &vpss_master_clk),
-	CLK(NULL, "vpss_slave", &vpss_slave_clk),
+	CLK("vpss", "master", &vpss_master_clk),
+	CLK("vpss", "slave", &vpss_slave_clk),
 	CLK(NULL, "clkout1", &clkout1_clk),
 	CLK(NULL, "clkout2", &clkout2_clk),
 	CLK(NULL, "pll2", &pll2_clk),
@@ -744,11 +746,146 @@ static struct platform_device vpfe_capture_dev = {
 	},
 };
 
-void dm355_set_vpfe_config(struct vpfe_config *cfg)
+static struct resource dm355_osd_resources[] = {
+	{
+		.start	= DM355_OSD_BASE,
+		.end	= DM355_OSD_BASE + 0x17f,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device dm355_osd_dev = {
+	.name		= DM355_VPBE_OSD_SUBDEV_NAME,
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(dm355_osd_resources),
+	.resource	= dm355_osd_resources,
+	.dev		= {
+		.dma_mask		= &vpfe_capture_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+static struct resource dm355_venc_resources[] = {
+	{
+		.start	= IRQ_VENCINT,
+		.end	= IRQ_VENCINT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	/* venc registers io space */
+	{
+		.start	= DM355_VENC_BASE,
+		.end	= DM355_VENC_BASE + 0x17f,
+		.flags	= IORESOURCE_MEM,
+	},
+	/* VDAC config register io space */
+	{
+		.start	= DAVINCI_SYSTEM_MODULE_BASE + SYSMOD_VDAC_CONFIG,
+		.end	= DAVINCI_SYSTEM_MODULE_BASE + SYSMOD_VDAC_CONFIG + 3,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource dm355_v4l2_disp_resources[] = {
+	{
+		.start	= IRQ_VENCINT,
+		.end	= IRQ_VENCINT,
+		.flags	= IORESOURCE_IRQ,
+	},
+	/* venc registers io space */
+	{
+		.start	= DM355_VENC_BASE,
+		.end	= DM355_VENC_BASE + 0x17f,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static int dm355_vpbe_setup_pinmux(enum v4l2_mbus_pixelcode if_type,
+			    int field)
+{
+	switch (if_type) {
+	case V4L2_MBUS_FMT_SGRBG8_1X8:
+		davinci_cfg_reg(DM355_VOUT_FIELD_G70);
+		break;
+	case V4L2_MBUS_FMT_YUYV10_1X20:
+		if (field)
+			davinci_cfg_reg(DM355_VOUT_FIELD);
+		else
+			davinci_cfg_reg(DM355_VOUT_FIELD_G70);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	davinci_cfg_reg(DM355_VOUT_COUTL_EN);
+	davinci_cfg_reg(DM355_VOUT_COUTH_EN);
+
+	return 0;
+}
+
+static int dm355_venc_setup_clock(enum vpbe_enc_timings_type type,
+				   unsigned int pclock)
 {
-	vpfe_capture_dev.dev.platform_data = cfg;
+	void __iomem *vpss_clk_ctrl_reg;
+
+	vpss_clk_ctrl_reg = DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL);
+
+	switch (type) {
+	case VPBE_ENC_STD:
+		writel(VPSS_DACCLKEN_ENABLE | VPSS_VENCCLKEN_ENABLE,
+		       vpss_clk_ctrl_reg);
+		break;
+	case VPBE_ENC_DV_TIMINGS:
+		if (pclock > 27000000)
+			/*
+			 * For HD, use external clock source since we cannot
+			 * support HD mode with internal clocks.
+			 */
+			writel(VPSS_MUXSEL_EXTCLK_ENABLE, vpss_clk_ctrl_reg);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
+static struct platform_device dm355_vpbe_display = {
+	.name		= "vpbe-v4l2",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(dm355_v4l2_disp_resources),
+	.resource	= dm355_v4l2_disp_resources,
+	.dev		= {
+		.dma_mask		= &vpfe_capture_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+struct venc_platform_data dm355_venc_pdata = {
+	.setup_pinmux	= dm355_vpbe_setup_pinmux,
+	.setup_clock	= dm355_venc_setup_clock,
+};
+
+static struct platform_device dm355_venc_dev = {
+	.name		= DM355_VPBE_VENC_SUBDEV_NAME,
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(dm355_venc_resources),
+	.resource	= dm355_venc_resources,
+	.dev		= {
+		.dma_mask		= &vpfe_capture_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= (void *)&dm355_venc_pdata,
+	},
+};
+
+static struct platform_device dm355_vpbe_dev = {
+	.name		= "vpbe_controller",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= &vpfe_capture_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
 /*----------------------------------------------------------------------*/
 
 static struct map_desc dm355_io_desc[] = {
@@ -868,19 +1005,36 @@ void __init dm355_init(void)
 	davinci_map_sysmod();
 }
 
+int __init dm355_init_video(struct vpfe_config *vpfe_cfg,
+				struct vpbe_config *vpbe_cfg)
+{
+	if (vpfe_cfg || vpbe_cfg)
+		platform_device_register(&dm355_vpss_device);
+
+	if (vpfe_cfg) {
+		vpfe_capture_dev.dev.platform_data = vpfe_cfg;
+		platform_device_register(&dm355_ccdc_dev);
+		platform_device_register(&vpfe_capture_dev);
+	}
+
+	if (vpbe_cfg) {
+		dm355_vpbe_dev.dev.platform_data = vpbe_cfg;
+		platform_device_register(&dm355_osd_dev);
+		platform_device_register(&dm355_venc_dev);
+		platform_device_register(&dm355_vpbe_dev);
+		platform_device_register(&dm355_vpbe_display);
+	}
+
+	return 0;
+}
+
 static int __init dm355_init_devices(void)
 {
 	if (!cpu_is_davinci_dm355())
 		return 0;
 
-	/* Add ccdc clock aliases */
-	clk_add_alias("master", dm355_ccdc_dev.name, "vpss_master", NULL);
-	clk_add_alias("slave", dm355_ccdc_dev.name, "vpss_master", NULL);
 	davinci_cfg_reg(DM355_INT_EDMA_CC);
 	platform_device_register(&dm355_edma_device);
-	platform_device_register(&dm355_vpss_device);
-	platform_device_register(&dm355_ccdc_dev);
-	platform_device_register(&vpfe_capture_dev);
 
 	return 0;
 }

+ 178 - 17
arch/arm/mach-davinci/dm365.c

@@ -39,16 +39,13 @@
 #include "asp.h"
 
 #define DM365_REF_FREQ		24000000	/* 24 MHz on the DM365 EVM */
-
-/* Base of key scan register bank */
-#define DM365_KEYSCAN_BASE		0x01c69400
-
 #define DM365_RTC_BASE			0x01c69000
-
+#define DM365_KEYSCAN_BASE		0x01c69400
+#define DM365_OSD_BASE			0x01c71c00
+#define DM365_VENC_BASE			0x01c71e00
 #define DAVINCI_DM365_VC_BASE		0x01d0c000
 #define DAVINCI_DMA_VC_TX		2
 #define DAVINCI_DMA_VC_RX		3
-
 #define DM365_EMAC_BASE			0x01d07000
 #define DM365_EMAC_MDIO_BASE		(DM365_EMAC_BASE + 0x4000)
 #define DM365_EMAC_CNTRL_OFFSET		0x0000
@@ -257,6 +254,12 @@ static struct clk vpss_master_clk = {
 	.flags		= CLK_PSC,
 };
 
+static struct clk vpss_slave_clk = {
+	.name		= "vpss_slave",
+	.parent		= &pll1_sysclk5,
+	.lpsc		= DAVINCI_LPSC_VPSSSLV,
+};
+
 static struct clk arm_clk = {
 	.name		= "arm_clk",
 	.parent		= &pll2_sysclk2,
@@ -449,7 +452,8 @@ static struct clk_lookup dm365_clks[] = {
 	CLK(NULL, "pll2_sysclk8", &pll2_sysclk8),
 	CLK(NULL, "pll2_sysclk9", &pll2_sysclk9),
 	CLK(NULL, "vpss_dac", &vpss_dac_clk),
-	CLK(NULL, "vpss_master", &vpss_master_clk),
+	CLK("vpss", "master", &vpss_master_clk),
+	CLK("vpss", "slave", &vpss_slave_clk),
 	CLK(NULL, "arm", &arm_clk),
 	CLK(NULL, "uart0", &uart0_clk),
 	CLK(NULL, "uart1", &uart1_clk),
@@ -1226,6 +1230,173 @@ static struct platform_device dm365_isif_dev = {
 	},
 };
 
+static struct resource dm365_osd_resources[] = {
+	{
+		.start = DM365_OSD_BASE,
+		.end   = DM365_OSD_BASE + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static u64 dm365_video_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device dm365_osd_dev = {
+	.name		= DM365_VPBE_OSD_SUBDEV_NAME,
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(dm365_osd_resources),
+	.resource	= dm365_osd_resources,
+	.dev		= {
+		.dma_mask		= &dm365_video_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+static struct resource dm365_venc_resources[] = {
+	{
+		.start = IRQ_VENCINT,
+		.end   = IRQ_VENCINT,
+		.flags = IORESOURCE_IRQ,
+	},
+	/* venc registers io space */
+	{
+		.start = DM365_VENC_BASE,
+		.end   = DM365_VENC_BASE + 0x177,
+		.flags = IORESOURCE_MEM,
+	},
+	/* vdaccfg registers io space */
+	{
+		.start = DAVINCI_SYSTEM_MODULE_BASE + SYSMOD_VDAC_CONFIG,
+		.end   = DAVINCI_SYSTEM_MODULE_BASE + SYSMOD_VDAC_CONFIG + 3,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static struct resource dm365_v4l2_disp_resources[] = {
+	{
+		.start = IRQ_VENCINT,
+		.end   = IRQ_VENCINT,
+		.flags = IORESOURCE_IRQ,
+	},
+	/* venc registers io space */
+	{
+		.start = DM365_VENC_BASE,
+		.end   = DM365_VENC_BASE + 0x177,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static int dm365_vpbe_setup_pinmux(enum v4l2_mbus_pixelcode if_type,
+			    int field)
+{
+	switch (if_type) {
+	case V4L2_MBUS_FMT_SGRBG8_1X8:
+		davinci_cfg_reg(DM365_VOUT_FIELD_G81);
+		davinci_cfg_reg(DM365_VOUT_COUTL_EN);
+		davinci_cfg_reg(DM365_VOUT_COUTH_EN);
+		break;
+	case V4L2_MBUS_FMT_YUYV10_1X20:
+		if (field)
+			davinci_cfg_reg(DM365_VOUT_FIELD);
+		else
+			davinci_cfg_reg(DM365_VOUT_FIELD_G81);
+		davinci_cfg_reg(DM365_VOUT_COUTL_EN);
+		davinci_cfg_reg(DM365_VOUT_COUTH_EN);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int dm365_venc_setup_clock(enum vpbe_enc_timings_type type,
+				  unsigned int pclock)
+{
+	void __iomem *vpss_clkctl_reg;
+	u32 val;
+
+	vpss_clkctl_reg = DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL);
+
+	switch (type) {
+	case VPBE_ENC_STD:
+		val = VPSS_VENCCLKEN_ENABLE | VPSS_DACCLKEN_ENABLE;
+		break;
+	case VPBE_ENC_DV_TIMINGS:
+		if (pclock <= 27000000) {
+			val = VPSS_VENCCLKEN_ENABLE | VPSS_DACCLKEN_ENABLE;
+		} else {
+			/* set sysclk4 to output 74.25 MHz from pll1 */
+			val = VPSS_PLLC2SYSCLK5_ENABLE | VPSS_DACCLKEN_ENABLE |
+			      VPSS_VENCCLKEN_ENABLE;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+	writel(val, vpss_clkctl_reg);
+
+	return 0;
+}
+
+static struct platform_device dm365_vpbe_display = {
+	.name		= "vpbe-v4l2",
+	.id		= -1,
+	.num_resources  = ARRAY_SIZE(dm365_v4l2_disp_resources),
+	.resource	= dm365_v4l2_disp_resources,
+	.dev		= {
+		.dma_mask		= &dm365_video_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+struct venc_platform_data dm365_venc_pdata = {
+	.setup_pinmux	= dm365_vpbe_setup_pinmux,
+	.setup_clock	= dm365_venc_setup_clock,
+};
+
+static struct platform_device dm365_venc_dev = {
+	.name		= DM365_VPBE_VENC_SUBDEV_NAME,
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(dm365_venc_resources),
+	.resource	= dm365_venc_resources,
+	.dev		= {
+		.dma_mask		= &dm365_video_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= (void *)&dm365_venc_pdata,
+	},
+};
+
+static struct platform_device dm365_vpbe_dev = {
+	.name		= "vpbe_controller",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= &dm365_video_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+int __init dm365_init_video(struct vpfe_config *vpfe_cfg,
+				struct vpbe_config *vpbe_cfg)
+{
+	if (vpfe_cfg || vpbe_cfg)
+		platform_device_register(&dm365_vpss_device);
+
+	if (vpfe_cfg) {
+		vpfe_capture_dev.dev.platform_data = vpfe_cfg;
+		platform_device_register(&dm365_isif_dev);
+		platform_device_register(&vpfe_capture_dev);
+	}
+	if (vpbe_cfg) {
+		dm365_vpbe_dev.dev.platform_data = vpbe_cfg;
+		platform_device_register(&dm365_osd_dev);
+		platform_device_register(&dm365_venc_dev);
+		platform_device_register(&dm365_vpbe_dev);
+		platform_device_register(&dm365_vpbe_display);
+	}
+
+	return 0;
+}
+
 static int __init dm365_init_devices(void)
 {
 	if (!cpu_is_davinci_dm365())
@@ -1239,16 +1410,6 @@ static int __init dm365_init_devices(void)
 	clk_add_alias(NULL, dev_name(&dm365_mdio_device.dev),
 		      NULL, &dm365_emac_device.dev);
 
-	/* Add isif clock alias */
-	clk_add_alias("master", dm365_isif_dev.name, "vpss_master", NULL);
-	platform_device_register(&dm365_vpss_device);
-	platform_device_register(&dm365_isif_dev);
-	platform_device_register(&vpfe_capture_dev);
 	return 0;
 }
 postcore_initcall(dm365_init_devices);
-
-void dm365_set_vpfe_config(struct vpfe_config *cfg)
-{
-       vpfe_capture_dev.dev.platform_data = cfg;
-}

+ 3 - 8
arch/arm/mach-davinci/dm644x.c

@@ -300,8 +300,8 @@ static struct clk_lookup dm644x_clks[] = {
 	CLK(NULL, "dsp", &dsp_clk),
 	CLK(NULL, "arm", &arm_clk),
 	CLK(NULL, "vicp", &vicp_clk),
-	CLK(NULL, "vpss_master", &vpss_master_clk),
-	CLK(NULL, "vpss_slave", &vpss_slave_clk),
+	CLK("vpss", "master", &vpss_master_clk),
+	CLK("vpss", "slave", &vpss_slave_clk),
 	CLK(NULL, "arm", &arm_clk),
 	CLK(NULL, "uart0", &uart0_clk),
 	CLK(NULL, "uart1", &uart1_clk),
@@ -706,7 +706,7 @@ static int dm644x_venc_setup_clock(enum vpbe_enc_timings_type type,
 		v |= DM644X_VPSS_DACCLKEN;
 		writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
 		break;
-	case VPBE_ENC_CUSTOM_TIMINGS:
+	case VPBE_ENC_DV_TIMINGS:
 		if (pclock <= 27000000) {
 			v |= DM644X_VPSS_DACCLKEN;
 			writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
@@ -901,11 +901,6 @@ int __init dm644x_init_video(struct vpfe_config *vpfe_cfg,
 		dm644x_vpfe_dev.dev.platform_data = vpfe_cfg;
 		platform_device_register(&dm644x_ccdc_dev);
 		platform_device_register(&dm644x_vpfe_dev);
-		/* Add ccdc clock aliases */
-		clk_add_alias("master", dm644x_ccdc_dev.name,
-			      "vpss_master", NULL);
-		clk_add_alias("slave", dm644x_ccdc_dev.name,
-			      "vpss_slave", NULL);
 	}
 
 	if (vpbe_cfg) {

+ 1 - 1
arch/arm/mach-davinci/pm_domain.c

@@ -53,7 +53,7 @@ static struct dev_pm_domain davinci_pm_domain = {
 
 static struct pm_clk_notifier_block platform_bus_notifier = {
 	.pm_domain = &davinci_pm_domain,
-	.con_ids = { "fck", NULL, },
+	.con_ids = { "fck", "master", "slave", NULL },
 };
 
 static int __init davinci_pm_runtime_init(void)

+ 4 - 4
arch/blackfin/mach-bf609/boards/ezkit.c

@@ -936,19 +936,19 @@ static struct v4l2_input adv7842_inputs[] = {
 		.index = 2,
 		.name = "Component",
 		.type = V4L2_INPUT_TYPE_CAMERA,
-		.capabilities = V4L2_IN_CAP_CUSTOM_TIMINGS,
+		.capabilities = V4L2_IN_CAP_DV_TIMINGS,
 	},
 	{
 		.index = 3,
 		.name = "VGA",
 		.type = V4L2_INPUT_TYPE_CAMERA,
-		.capabilities = V4L2_IN_CAP_CUSTOM_TIMINGS,
+		.capabilities = V4L2_IN_CAP_DV_TIMINGS,
 	},
 	{
 		.index = 4,
 		.name = "HDMI",
 		.type = V4L2_INPUT_TYPE_CAMERA,
-		.capabilities = V4L2_IN_CAP_CUSTOM_TIMINGS,
+		.capabilities = V4L2_IN_CAP_DV_TIMINGS,
 	},
 };
 
@@ -1074,7 +1074,7 @@ static struct v4l2_output adv7511_outputs[] = {
 		.index = 0,
 		.name = "HDMI",
 		.type = V4L2_INPUT_TYPE_CAMERA,
-		.capabilities = V4L2_OUT_CAP_CUSTOM_TIMINGS,
+		.capabilities = V4L2_OUT_CAP_DV_TIMINGS,
 	},
 };
 

+ 4 - 0
drivers/media/common/Kconfig

@@ -16,6 +16,10 @@ config VIDEO_TVEEPROM
 	tristate
 	depends on I2C
 
+config CYPRESS_FIRMWARE
+	tristate "Cypress firmware helper routines"
+	depends on USB
+
 source "drivers/media/common/b2c2/Kconfig"
 source "drivers/media/common/saa7146/Kconfig"
 source "drivers/media/common/siano/Kconfig"

+ 1 - 0
drivers/media/common/Makefile

@@ -2,3 +2,4 @@ obj-y += b2c2/ saa7146/ siano/
 obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
 obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
 obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
+obj-$(CONFIG_CYPRESS_FIRMWARE) += cypress_firmware.o

+ 2 - 2
drivers/media/common/b2c2/flexcop-fe-tuner.c

@@ -325,7 +325,7 @@ static int skystar2_rev27_attach(struct flexcop_device *fc,
 	/* enable no_base_addr - no repeated start when reading */
 	fc->fc_i2c_adap[2].no_base_addr = 1;
 	if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
-			0x08, 1, 1)) {
+			0x08, 1, 1, false)) {
 		err("ISL6421 could NOT be attached");
 		goto fail_isl;
 	}
@@ -391,7 +391,7 @@ static int skystar2_rev28_attach(struct flexcop_device *fc,
 
 	fc->fc_i2c_adap[2].no_base_addr = 1;
 	if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
-			0x08, 0, 0)) {
+			0x08, 0, 0, false)) {
 		err("ISL6421 could NOT be attached");
 		fc->fc_i2c_adap[2].no_base_addr = 0;
 		return 0;

+ 40 - 42
drivers/media/usb/dvb-usb-v2/cypress_firmware.c → drivers/media/common/cypress_firmware.c

@@ -8,7 +8,10 @@
  *
  */
 
-#include "dvb_usb.h"
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/firmware.h>
 #include "cypress_firmware.h"
 
 struct usb_cypress_controller {
@@ -30,14 +33,42 @@ static const struct usb_cypress_controller cypress[] = {
 static int usb_cypress_writemem(struct usb_device *udev, u16 addr, u8 *data,
 		u8 len)
 {
-	dvb_usb_dbg_usb_control_msg(udev,
-			0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len);
-
 	return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 			0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000);
 }
 
-int usbv2_cypress_load_firmware(struct usb_device *udev,
+static int cypress_get_hexline(const struct firmware *fw,
+				struct hexline *hx, int *pos)
+{
+	u8 *b = (u8 *) &fw->data[*pos];
+	int data_offs = 4;
+
+	if (*pos >= fw->size)
+		return 0;
+
+	memset(hx, 0, sizeof(struct hexline));
+	hx->len = b[0];
+
+	if ((*pos + hx->len + 4) >= fw->size)
+		return -EINVAL;
+
+	hx->addr = b[1] | (b[2] << 8);
+	hx->type = b[3];
+
+	if (hx->type == 0x04) {
+		/* b[4] and b[5] are the Extended linear address record data
+		 * field */
+		hx->addr |= (b[4] << 24) | (b[5] << 16);
+	}
+
+	memcpy(hx->data, &b[data_offs], hx->len);
+	hx->chk = b[hx->len + data_offs];
+	*pos += hx->len + 5;
+
+	return *pos;
+}
+
+int cypress_load_firmware(struct usb_device *udev,
 		const struct firmware *fw, int type)
 {
 	struct hexline *hx;
@@ -61,7 +92,7 @@ int usbv2_cypress_load_firmware(struct usb_device *udev,
 
 	/* write firmware to memory */
 	for (;;) {
-		ret = dvb_usbv2_get_hexline(fw, hx, &pos);
+		ret = cypress_get_hexline(fw, hx, &pos);
 		if (ret < 0)
 			goto err_kfree;
 		else if (ret == 0)
@@ -71,9 +102,8 @@ int usbv2_cypress_load_firmware(struct usb_device *udev,
 		if (ret < 0) {
 			goto err_kfree;
 		} else if (ret != hx->len) {
-			dev_err(&udev->dev, "%s: error while transferring " \
-					"firmware (transferred size=%d, " \
-					"block size=%d)\n",
+			dev_err(&udev->dev,
+					"%s: error while transferring firmware (transferred size=%d, block size=%d)\n",
 					KBUILD_MODNAME, ret, hx->len);
 			ret = -EIO;
 			goto err_kfree;
@@ -95,39 +125,7 @@ err_kfree:
 	kfree(hx);
 	return ret;
 }
-EXPORT_SYMBOL(usbv2_cypress_load_firmware);
-
-int dvb_usbv2_get_hexline(const struct firmware *fw, struct hexline *hx,
-		int *pos)
-{
-	u8 *b = (u8 *) &fw->data[*pos];
-	int data_offs = 4;
-
-	if (*pos >= fw->size)
-		return 0;
-
-	memset(hx, 0, sizeof(struct hexline));
-	hx->len = b[0];
-
-	if ((*pos + hx->len + 4) >= fw->size)
-		return -EINVAL;
-
-	hx->addr = b[1] | (b[2] << 8);
-	hx->type = b[3];
-
-	if (hx->type == 0x04) {
-		/* b[4] and b[5] are the Extended linear address record data
-		 * field */
-		hx->addr |= (b[4] << 24) | (b[5] << 16);
-	}
-
-	memcpy(hx->data, &b[data_offs], hx->len);
-	hx->chk = b[hx->len + data_offs];
-	*pos += hx->len + 5;
-
-	return *pos;
-}
-EXPORT_SYMBOL(dvb_usbv2_get_hexline);
+EXPORT_SYMBOL(cypress_load_firmware);
 
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 MODULE_DESCRIPTION("Cypress firmware download");

+ 3 - 6
drivers/media/usb/dvb-usb-v2/cypress_firmware.h → drivers/media/common/cypress_firmware.h

@@ -1,5 +1,4 @@
-/* cypress_firmware.h is part of the DVB USB library.
- *
+/*
  * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
  * see dvb-usb-init.c for copyright information.
  *
@@ -23,9 +22,7 @@ struct hexline {
 	u8 data[255];
 	u8 chk;
 };
-extern int usbv2_cypress_load_firmware(struct usb_device *,
-		const struct firmware *, int);
-extern int dvb_usbv2_get_hexline(const struct firmware *,
-		struct hexline *, int *);
+
+int cypress_load_firmware(struct usb_device *, const struct firmware *, int);
 
 #endif

+ 2 - 2
drivers/media/common/saa7146/saa7146_video.c

@@ -832,7 +832,7 @@ static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
 	}
 	*/
 
-static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
+static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id)
 {
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct saa7146_vv *vv = dev->vv_data;
@@ -856,7 +856,7 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
 	}
 
 	for (i = 0; i < dev->ext_vv_data->num_stds; i++)
-		if (*id & dev->ext_vv_data->stds[i].id)
+		if (id & dev->ext_vv_data->stds[i].id)
 			break;
 	if (i != dev->ext_vv_data->num_stds) {
 		vv->standard = &dev->ext_vv_data->stds[i];

+ 12 - 0
drivers/media/common/siano/Kconfig

@@ -17,3 +17,15 @@ config SMS_SIANO_RC
 	default y
 	---help---
 	  Choose Y to select Remote Controller support for Siano driver.
+
+config SMS_SIANO_DEBUGFS
+	bool "Enable debugfs for smsdvb"
+	depends on SMS_SIANO_MDTV
+	depends on DEBUG_FS
+	depends on SMS_USB_DRV
+	---help---
+	  Choose Y to enable visualizing a dump of the frontend
+	  statistics response packets via debugfs. Currently, works
+	  only with Siano USB devices.
+
+	  Useful only for developers. In doubt, say N.

+ 5 - 0
drivers/media/common/siano/Makefile

@@ -1,4 +1,5 @@
 smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o
+smsdvb-objs := smsdvb-main.o
 
 obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o
 
@@ -6,6 +7,10 @@ ifeq ($(CONFIG_SMS_SIANO_RC),y)
   smsmdtv-objs += smsir.o
 endif
 
+ifeq ($(CONFIG_SMS_SIANO_DEBUGFS),y)
+  smsdvb-objs += smsdvb-debugfs.o
+endif
+
 ccflags-y += -Idrivers/media/dvb-core
 ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
 

+ 81 - 34
drivers/media/common/siano/sms-cards.c

@@ -28,43 +28,53 @@ MODULE_PARM_DESC(cards_dbg, "set debug level (info=1, adv=2 (or-able))");
 static struct sms_board sms_boards[] = {
 	[SMS_BOARD_UNKNOWN] = {
 		.name	= "Unknown board",
+		.type = SMS_UNKNOWN_TYPE,
+		.default_mode = DEVICE_MODE_NONE,
 	},
 	[SMS1XXX_BOARD_SIANO_STELLAR] = {
 		.name	= "Siano Stellar Digital Receiver",
 		.type	= SMS_STELLAR,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 	},
 	[SMS1XXX_BOARD_SIANO_NOVA_A] = {
 		.name	= "Siano Nova A Digital Receiver",
 		.type	= SMS_NOVA_A0,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 	},
 	[SMS1XXX_BOARD_SIANO_NOVA_B] = {
 		.name	= "Siano Nova B Digital Receiver",
 		.type	= SMS_NOVA_B0,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 	},
 	[SMS1XXX_BOARD_SIANO_VEGA] = {
 		.name	= "Siano Vega Digital Receiver",
 		.type	= SMS_VEGA,
+		.default_mode = DEVICE_MODE_CMMB,
 	},
 	[SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT] = {
 		.name	= "Hauppauge Catamount",
 		.type	= SMS_STELLAR,
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw",
+		.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_STELLAR,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 	},
 	[SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A] = {
 		.name	= "Hauppauge Okemo-A",
 		.type	= SMS_NOVA_A0,
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw",
+		.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_NOVA_A,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 	},
 	[SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B] = {
 		.name	= "Hauppauge Okemo-B",
 		.type	= SMS_NOVA_B0,
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
+		.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_NOVA_B,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 	},
 	[SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
 		.name	= "Hauppauge WinTV MiniStick",
 		.type	= SMS_NOVA_B0,
-		.fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw",
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
+		.fw[DEVICE_MODE_ISDBT_BDA] = SMS_FW_ISDBT_HCW_55XXX,
+		.fw[DEVICE_MODE_DVBT_BDA]  = SMS_FW_DVBT_HCW_55XXX,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 		.rc_codes = RC_MAP_HAUPPAUGE,
 		.board_cfg.leds_power = 26,
 		.board_cfg.led0 = 27,
@@ -77,7 +87,8 @@ static struct sms_board sms_boards[] = {
 	[SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD] = {
 		.name	= "Hauppauge WinTV MiniCard",
 		.type	= SMS_NOVA_B0,
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
+		.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_HCW_55XXX,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 		.lna_ctrl  = 29,
 		.board_cfg.foreign_lna0_ctrl = 29,
 		.rf_switch = 17,
@@ -86,18 +97,65 @@ static struct sms_board sms_boards[] = {
 	[SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = {
 		.name	= "Hauppauge WinTV MiniCard",
 		.type	= SMS_NOVA_B0,
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
+		.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_HCW_55XXX,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 		.lna_ctrl  = -1,
 	},
 	[SMS1XXX_BOARD_SIANO_NICE] = {
-	/* 11 */
 		.name = "Siano Nice Digital Receiver",
 		.type = SMS_NOVA_B0,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
 	},
 	[SMS1XXX_BOARD_SIANO_VENICE] = {
-	/* 12 */
 		.name = "Siano Venice Digital Receiver",
 		.type = SMS_VEGA,
+		.default_mode = DEVICE_MODE_CMMB,
+	},
+	[SMS1XXX_BOARD_SIANO_STELLAR_ROM] = {
+		.name = "Siano Stellar Digital Receiver ROM",
+		.type = SMS_STELLAR,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
+		.intf_num = 1,
+	},
+	[SMS1XXX_BOARD_ZTE_DVB_DATA_CARD] = {
+		.name = "ZTE Data Card Digital Receiver",
+		.type = SMS_NOVA_B0,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
+		.intf_num = 5,
+		.mtu = 15792,
+	},
+	[SMS1XXX_BOARD_ONDA_MDTV_DATA_CARD] = {
+		.name = "ONDA Data Card Digital Receiver",
+		.type = SMS_NOVA_B0,
+		.default_mode = DEVICE_MODE_DVBT_BDA,
+		.intf_num = 6,
+		.mtu = 15792,
+	},
+	[SMS1XXX_BOARD_SIANO_MING] = {
+		.name = "Siano Ming Digital Receiver",
+		.type = SMS_MING,
+		.default_mode = DEVICE_MODE_CMMB,
+	},
+	[SMS1XXX_BOARD_SIANO_PELE] = {
+		.name = "Siano Pele Digital Receiver",
+		.type = SMS_PELE,
+		.default_mode = DEVICE_MODE_ISDBT_BDA,
+	},
+	[SMS1XXX_BOARD_SIANO_RIO] = {
+		.name = "Siano Rio Digital Receiver",
+		.type = SMS_RIO,
+		.default_mode = DEVICE_MODE_ISDBT_BDA,
+	},
+	[SMS1XXX_BOARD_SIANO_DENVER_1530] = {
+		.name = "Siano Denver (ATSC-M/H) Digital Receiver",
+		.type = SMS_DENVER_1530,
+		.default_mode = DEVICE_MODE_ATSC,
+		.crystal = 2400,
+	},
+	[SMS1XXX_BOARD_SIANO_DENVER_2160] = {
+		.name = "Siano Denver (TDMB) Digital Receiver",
+		.type = SMS_DENVER_2160,
+		.default_mode = DEVICE_MODE_DAB_TDMB,
 	},
 };
 
@@ -109,20 +167,21 @@ struct sms_board *sms_get_board(unsigned id)
 }
 EXPORT_SYMBOL_GPL(sms_get_board);
 static inline void sms_gpio_assign_11xx_default_led_config(
-		struct smscore_gpio_config *pGpioConfig) {
-	pGpioConfig->Direction = SMS_GPIO_DIRECTION_OUTPUT;
-	pGpioConfig->InputCharacteristics =
-		SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL;
-	pGpioConfig->OutputDriving = SMS_GPIO_OUTPUT_DRIVING_4mA;
-	pGpioConfig->OutputSlewRate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS;
-	pGpioConfig->PullUpDown = SMS_GPIO_PULL_UP_DOWN_NONE;
+		struct smscore_config_gpio *p_gpio_config) {
+	p_gpio_config->direction = SMS_GPIO_DIRECTION_OUTPUT;
+	p_gpio_config->inputcharacteristics =
+		SMS_GPIO_INPUTCHARACTERISTICS_NORMAL;
+	p_gpio_config->outputdriving = SMS_GPIO_OUTPUTDRIVING_4mA;
+	p_gpio_config->outputslewrate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS;
+	p_gpio_config->pullupdown = SMS_GPIO_PULLUPDOWN_NONE;
 }
 
 int sms_board_event(struct smscore_device_t *coredev,
-		enum SMS_BOARD_EVENTS gevent) {
-	struct smscore_gpio_config MyGpioConfig;
+		    enum SMS_BOARD_EVENTS gevent)
+{
+	struct smscore_config_gpio my_gpio_config;
 
-	sms_gpio_assign_11xx_default_led_config(&MyGpioConfig);
+	sms_gpio_assign_11xx_default_led_config(&my_gpio_config);
 
 	switch (gevent) {
 	case BOARD_EVENT_POWER_INIT: /* including hotplug */
@@ -182,8 +241,8 @@ static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable)
 		.direction            = SMS_GPIO_DIRECTION_OUTPUT,
 		.pullupdown           = SMS_GPIO_PULLUPDOWN_NONE,
 		.inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL,
-		.outputslewrate       = SMS_GPIO_OUTPUTSLEWRATE_FAST,
-		.outputdriving        = SMS_GPIO_OUTPUTDRIVING_4mA,
+		.outputslewrate       = SMS_GPIO_OUTPUT_SLEW_RATE_FAST,
+		.outputdriving        = SMS_GPIO_OUTPUTDRIVING_S_4mA,
 	};
 
 	if (pin == 0)
@@ -293,19 +352,7 @@ EXPORT_SYMBOL_GPL(sms_board_lna_control);
 
 int sms_board_load_modules(int id)
 {
-	switch (id) {
-	case SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT:
-	case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A:
-	case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B:
-	case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
-	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
-	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
-		request_module("smsdvb");
-		break;
-	default:
-		/* do nothing */
-		break;
-	}
+	request_module("smsdvb");
 	return 0;
 }
 EXPORT_SYMBOL_GPL(sms_board_load_modules);

+ 14 - 0
drivers/media/common/siano/sms-cards.h

@@ -37,6 +37,14 @@
 #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 10
 #define SMS1XXX_BOARD_SIANO_NICE	11
 #define SMS1XXX_BOARD_SIANO_VENICE	12
+#define SMS1XXX_BOARD_SIANO_STELLAR_ROM 13
+#define SMS1XXX_BOARD_ZTE_DVB_DATA_CARD	14
+#define SMS1XXX_BOARD_ONDA_MDTV_DATA_CARD 15
+#define SMS1XXX_BOARD_SIANO_MING	16
+#define SMS1XXX_BOARD_SIANO_PELE	17
+#define SMS1XXX_BOARD_SIANO_RIO		18
+#define SMS1XXX_BOARD_SIANO_DENVER_1530	19
+#define SMS1XXX_BOARD_SIANO_DENVER_2160 20
 
 struct sms_board_gpio_cfg {
 	int lna_vhf_exist;
@@ -79,6 +87,12 @@ struct sms_board {
 
 	/* gpios */
 	int led_power, led_hi, led_lo, lna_ctrl, rf_switch;
+
+	char intf_num;
+	int default_mode;
+	unsigned int mtu;
+	unsigned int crystal;
+	struct sms_antenna_config_ST *antenna_config;
 };
 
 struct sms_board *sms_get_board(unsigned id);

+ 930 - 368
drivers/media/common/siano/smscoreapi.c

@@ -37,7 +37,6 @@
 #include "smscoreapi.h"
 #include "sms-cards.h"
 #include "smsir.h"
-#include "smsendian.h"
 
 static int sms_dbg;
 module_param_named(debug, sms_dbg, int, 0644);
@@ -58,11 +57,350 @@ struct smscore_client_t {
 	struct list_head entry;
 	struct smscore_device_t *coredev;
 	void			*context;
-	struct list_head 	idlist;
-	onresponse_t	onresponse_handler;
+	struct list_head	idlist;
+	onresponse_t		onresponse_handler;
 	onremove_t		onremove_handler;
 };
 
+static char *siano_msgs[] = {
+	[MSG_TYPE_BASE_VAL                           - MSG_TYPE_BASE_VAL] = "MSG_TYPE_BASE_VAL",
+	[MSG_SMS_GET_VERSION_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_VERSION_REQ",
+	[MSG_SMS_GET_VERSION_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_VERSION_RES",
+	[MSG_SMS_MULTI_BRIDGE_CFG                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_MULTI_BRIDGE_CFG",
+	[MSG_SMS_GPIO_CONFIG_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_CONFIG_REQ",
+	[MSG_SMS_GPIO_CONFIG_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_CONFIG_RES",
+	[MSG_SMS_GPIO_SET_LEVEL_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_SET_LEVEL_REQ",
+	[MSG_SMS_GPIO_SET_LEVEL_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_SET_LEVEL_RES",
+	[MSG_SMS_GPIO_GET_LEVEL_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_GET_LEVEL_REQ",
+	[MSG_SMS_GPIO_GET_LEVEL_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_GET_LEVEL_RES",
+	[MSG_SMS_EEPROM_BURN_IND                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_EEPROM_BURN_IND",
+	[MSG_SMS_LOG_ENABLE_CHANGE_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOG_ENABLE_CHANGE_REQ",
+	[MSG_SMS_LOG_ENABLE_CHANGE_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOG_ENABLE_CHANGE_RES",
+	[MSG_SMS_SET_MAX_TX_MSG_LEN_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_MAX_TX_MSG_LEN_REQ",
+	[MSG_SMS_SET_MAX_TX_MSG_LEN_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_MAX_TX_MSG_LEN_RES",
+	[MSG_SMS_SPI_HALFDUPLEX_TOKEN_HOST_TO_DEVICE - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_HALFDUPLEX_TOKEN_HOST_TO_DEVICE",
+	[MSG_SMS_SPI_HALFDUPLEX_TOKEN_DEVICE_TO_HOST - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_HALFDUPLEX_TOKEN_DEVICE_TO_HOST",
+	[MSG_SMS_BACKGROUND_SCAN_FLAG_CHANGE_REQ     - MSG_TYPE_BASE_VAL] = "MSG_SMS_BACKGROUND_SCAN_FLAG_CHANGE_REQ",
+	[MSG_SMS_BACKGROUND_SCAN_FLAG_CHANGE_RES     - MSG_TYPE_BASE_VAL] = "MSG_SMS_BACKGROUND_SCAN_FLAG_CHANGE_RES",
+	[MSG_SMS_BACKGROUND_SCAN_SIGNAL_DETECTED_IND - MSG_TYPE_BASE_VAL] = "MSG_SMS_BACKGROUND_SCAN_SIGNAL_DETECTED_IND",
+	[MSG_SMS_BACKGROUND_SCAN_NO_SIGNAL_IND       - MSG_TYPE_BASE_VAL] = "MSG_SMS_BACKGROUND_SCAN_NO_SIGNAL_IND",
+	[MSG_SMS_CONFIGURE_RF_SWITCH_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_CONFIGURE_RF_SWITCH_REQ",
+	[MSG_SMS_CONFIGURE_RF_SWITCH_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_CONFIGURE_RF_SWITCH_RES",
+	[MSG_SMS_MRC_PATH_DISCONNECT_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_PATH_DISCONNECT_REQ",
+	[MSG_SMS_MRC_PATH_DISCONNECT_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_PATH_DISCONNECT_RES",
+	[MSG_SMS_RECEIVE_1SEG_THROUGH_FULLSEG_REQ    - MSG_TYPE_BASE_VAL] = "MSG_SMS_RECEIVE_1SEG_THROUGH_FULLSEG_REQ",
+	[MSG_SMS_RECEIVE_1SEG_THROUGH_FULLSEG_RES    - MSG_TYPE_BASE_VAL] = "MSG_SMS_RECEIVE_1SEG_THROUGH_FULLSEG_RES",
+	[MSG_SMS_RECEIVE_VHF_VIA_VHF_INPUT_REQ       - MSG_TYPE_BASE_VAL] = "MSG_SMS_RECEIVE_VHF_VIA_VHF_INPUT_REQ",
+	[MSG_SMS_RECEIVE_VHF_VIA_VHF_INPUT_RES       - MSG_TYPE_BASE_VAL] = "MSG_SMS_RECEIVE_VHF_VIA_VHF_INPUT_RES",
+	[MSG_WR_REG_RFT_REQ                          - MSG_TYPE_BASE_VAL] = "MSG_WR_REG_RFT_REQ",
+	[MSG_WR_REG_RFT_RES                          - MSG_TYPE_BASE_VAL] = "MSG_WR_REG_RFT_RES",
+	[MSG_RD_REG_RFT_REQ                          - MSG_TYPE_BASE_VAL] = "MSG_RD_REG_RFT_REQ",
+	[MSG_RD_REG_RFT_RES                          - MSG_TYPE_BASE_VAL] = "MSG_RD_REG_RFT_RES",
+	[MSG_RD_REG_ALL_RFT_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_RD_REG_ALL_RFT_REQ",
+	[MSG_RD_REG_ALL_RFT_RES                      - MSG_TYPE_BASE_VAL] = "MSG_RD_REG_ALL_RFT_RES",
+	[MSG_HELP_INT                                - MSG_TYPE_BASE_VAL] = "MSG_HELP_INT",
+	[MSG_RUN_SCRIPT_INT                          - MSG_TYPE_BASE_VAL] = "MSG_RUN_SCRIPT_INT",
+	[MSG_SMS_EWS_INBAND_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_EWS_INBAND_REQ",
+	[MSG_SMS_EWS_INBAND_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_EWS_INBAND_RES",
+	[MSG_SMS_RFS_SELECT_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_RFS_SELECT_REQ",
+	[MSG_SMS_RFS_SELECT_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_RFS_SELECT_RES",
+	[MSG_SMS_MB_GET_VER_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_GET_VER_REQ",
+	[MSG_SMS_MB_GET_VER_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_GET_VER_RES",
+	[MSG_SMS_MB_WRITE_CFGFILE_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_WRITE_CFGFILE_REQ",
+	[MSG_SMS_MB_WRITE_CFGFILE_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_WRITE_CFGFILE_RES",
+	[MSG_SMS_MB_READ_CFGFILE_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_READ_CFGFILE_REQ",
+	[MSG_SMS_MB_READ_CFGFILE_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_READ_CFGFILE_RES",
+	[MSG_SMS_RD_MEM_REQ                          - MSG_TYPE_BASE_VAL] = "MSG_SMS_RD_MEM_REQ",
+	[MSG_SMS_RD_MEM_RES                          - MSG_TYPE_BASE_VAL] = "MSG_SMS_RD_MEM_RES",
+	[MSG_SMS_WR_MEM_REQ                          - MSG_TYPE_BASE_VAL] = "MSG_SMS_WR_MEM_REQ",
+	[MSG_SMS_WR_MEM_RES                          - MSG_TYPE_BASE_VAL] = "MSG_SMS_WR_MEM_RES",
+	[MSG_SMS_UPDATE_MEM_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_UPDATE_MEM_REQ",
+	[MSG_SMS_UPDATE_MEM_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_UPDATE_MEM_RES",
+	[MSG_SMS_ISDBT_ENABLE_FULL_PARAMS_SET_REQ    - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_ENABLE_FULL_PARAMS_SET_REQ",
+	[MSG_SMS_ISDBT_ENABLE_FULL_PARAMS_SET_RES    - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_ENABLE_FULL_PARAMS_SET_RES",
+	[MSG_SMS_RF_TUNE_REQ                         - MSG_TYPE_BASE_VAL] = "MSG_SMS_RF_TUNE_REQ",
+	[MSG_SMS_RF_TUNE_RES                         - MSG_TYPE_BASE_VAL] = "MSG_SMS_RF_TUNE_RES",
+	[MSG_SMS_ISDBT_ENABLE_HIGH_MOBILITY_REQ      - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_ENABLE_HIGH_MOBILITY_REQ",
+	[MSG_SMS_ISDBT_ENABLE_HIGH_MOBILITY_RES      - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_ENABLE_HIGH_MOBILITY_RES",
+	[MSG_SMS_ISDBT_SB_RECEPTION_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_SB_RECEPTION_REQ",
+	[MSG_SMS_ISDBT_SB_RECEPTION_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_SB_RECEPTION_RES",
+	[MSG_SMS_GENERIC_EPROM_WRITE_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_EPROM_WRITE_REQ",
+	[MSG_SMS_GENERIC_EPROM_WRITE_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_EPROM_WRITE_RES",
+	[MSG_SMS_GENERIC_EPROM_READ_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_EPROM_READ_REQ",
+	[MSG_SMS_GENERIC_EPROM_READ_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_EPROM_READ_RES",
+	[MSG_SMS_EEPROM_WRITE_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_EEPROM_WRITE_REQ",
+	[MSG_SMS_EEPROM_WRITE_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_EEPROM_WRITE_RES",
+	[MSG_SMS_CUSTOM_READ_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_CUSTOM_READ_REQ",
+	[MSG_SMS_CUSTOM_READ_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_CUSTOM_READ_RES",
+	[MSG_SMS_CUSTOM_WRITE_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_CUSTOM_WRITE_REQ",
+	[MSG_SMS_CUSTOM_WRITE_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_CUSTOM_WRITE_RES",
+	[MSG_SMS_INIT_DEVICE_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_INIT_DEVICE_REQ",
+	[MSG_SMS_INIT_DEVICE_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_INIT_DEVICE_RES",
+	[MSG_SMS_ATSC_SET_ALL_IP_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_SET_ALL_IP_REQ",
+	[MSG_SMS_ATSC_SET_ALL_IP_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_SET_ALL_IP_RES",
+	[MSG_SMS_ATSC_START_ENSEMBLE_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_START_ENSEMBLE_REQ",
+	[MSG_SMS_ATSC_START_ENSEMBLE_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_START_ENSEMBLE_RES",
+	[MSG_SMS_SET_OUTPUT_MODE_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_OUTPUT_MODE_REQ",
+	[MSG_SMS_SET_OUTPUT_MODE_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_OUTPUT_MODE_RES",
+	[MSG_SMS_ATSC_IP_FILTER_GET_LIST_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_GET_LIST_REQ",
+	[MSG_SMS_ATSC_IP_FILTER_GET_LIST_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_GET_LIST_RES",
+	[MSG_SMS_SUB_CHANNEL_START_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SUB_CHANNEL_START_REQ",
+	[MSG_SMS_SUB_CHANNEL_START_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SUB_CHANNEL_START_RES",
+	[MSG_SMS_SUB_CHANNEL_STOP_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SUB_CHANNEL_STOP_REQ",
+	[MSG_SMS_SUB_CHANNEL_STOP_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SUB_CHANNEL_STOP_RES",
+	[MSG_SMS_ATSC_IP_FILTER_ADD_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_ADD_REQ",
+	[MSG_SMS_ATSC_IP_FILTER_ADD_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_ADD_RES",
+	[MSG_SMS_ATSC_IP_FILTER_REMOVE_REQ           - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_REMOVE_REQ",
+	[MSG_SMS_ATSC_IP_FILTER_REMOVE_RES           - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_REMOVE_RES",
+	[MSG_SMS_ATSC_IP_FILTER_REMOVE_ALL_REQ       - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_REMOVE_ALL_REQ",
+	[MSG_SMS_ATSC_IP_FILTER_REMOVE_ALL_RES       - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_REMOVE_ALL_RES",
+	[MSG_SMS_WAIT_CMD                            - MSG_TYPE_BASE_VAL] = "MSG_SMS_WAIT_CMD",
+	[MSG_SMS_ADD_PID_FILTER_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_ADD_PID_FILTER_REQ",
+	[MSG_SMS_ADD_PID_FILTER_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_ADD_PID_FILTER_RES",
+	[MSG_SMS_REMOVE_PID_FILTER_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_REMOVE_PID_FILTER_REQ",
+	[MSG_SMS_REMOVE_PID_FILTER_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_REMOVE_PID_FILTER_RES",
+	[MSG_SMS_FAST_INFORMATION_CHANNEL_REQ        - MSG_TYPE_BASE_VAL] = "MSG_SMS_FAST_INFORMATION_CHANNEL_REQ",
+	[MSG_SMS_FAST_INFORMATION_CHANNEL_RES        - MSG_TYPE_BASE_VAL] = "MSG_SMS_FAST_INFORMATION_CHANNEL_RES",
+	[MSG_SMS_DAB_CHANNEL                         - MSG_TYPE_BASE_VAL] = "MSG_SMS_DAB_CHANNEL",
+	[MSG_SMS_GET_PID_FILTER_LIST_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_PID_FILTER_LIST_REQ",
+	[MSG_SMS_GET_PID_FILTER_LIST_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_PID_FILTER_LIST_RES",
+	[MSG_SMS_POWER_DOWN_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_DOWN_REQ",
+	[MSG_SMS_POWER_DOWN_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_DOWN_RES",
+	[MSG_SMS_ATSC_SLT_EXIST_IND                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_SLT_EXIST_IND",
+	[MSG_SMS_ATSC_NO_SLT_IND                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_NO_SLT_IND",
+	[MSG_SMS_GET_STATISTICS_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_STATISTICS_REQ",
+	[MSG_SMS_GET_STATISTICS_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_STATISTICS_RES",
+	[MSG_SMS_SEND_DUMP                           - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_DUMP",
+	[MSG_SMS_SCAN_START_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_START_REQ",
+	[MSG_SMS_SCAN_START_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_START_RES",
+	[MSG_SMS_SCAN_STOP_REQ                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_STOP_REQ",
+	[MSG_SMS_SCAN_STOP_RES                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_STOP_RES",
+	[MSG_SMS_SCAN_PROGRESS_IND                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_PROGRESS_IND",
+	[MSG_SMS_SCAN_COMPLETE_IND                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_COMPLETE_IND",
+	[MSG_SMS_LOG_ITEM                            - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOG_ITEM",
+	[MSG_SMS_DAB_SUBCHANNEL_RECONFIG_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_DAB_SUBCHANNEL_RECONFIG_REQ",
+	[MSG_SMS_DAB_SUBCHANNEL_RECONFIG_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_DAB_SUBCHANNEL_RECONFIG_RES",
+	[MSG_SMS_HO_PER_SLICES_IND                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_PER_SLICES_IND",
+	[MSG_SMS_HO_INBAND_POWER_IND                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_INBAND_POWER_IND",
+	[MSG_SMS_MANUAL_DEMOD_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_MANUAL_DEMOD_REQ",
+	[MSG_SMS_HO_TUNE_ON_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_TUNE_ON_REQ",
+	[MSG_SMS_HO_TUNE_ON_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_TUNE_ON_RES",
+	[MSG_SMS_HO_TUNE_OFF_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_TUNE_OFF_REQ",
+	[MSG_SMS_HO_TUNE_OFF_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_TUNE_OFF_RES",
+	[MSG_SMS_HO_PEEK_FREQ_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_PEEK_FREQ_REQ",
+	[MSG_SMS_HO_PEEK_FREQ_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_PEEK_FREQ_RES",
+	[MSG_SMS_HO_PEEK_FREQ_IND                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_PEEK_FREQ_IND",
+	[MSG_SMS_MB_ATTEN_SET_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_ATTEN_SET_REQ",
+	[MSG_SMS_MB_ATTEN_SET_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_ATTEN_SET_RES",
+	[MSG_SMS_ENABLE_STAT_IN_I2C_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ENABLE_STAT_IN_I2C_REQ",
+	[MSG_SMS_ENABLE_STAT_IN_I2C_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ENABLE_STAT_IN_I2C_RES",
+	[MSG_SMS_SET_ANTENNA_CONFIG_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_ANTENNA_CONFIG_REQ",
+	[MSG_SMS_SET_ANTENNA_CONFIG_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_ANTENNA_CONFIG_RES",
+	[MSG_SMS_GET_STATISTICS_EX_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_STATISTICS_EX_REQ",
+	[MSG_SMS_GET_STATISTICS_EX_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_STATISTICS_EX_RES",
+	[MSG_SMS_SLEEP_RESUME_COMP_IND               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SLEEP_RESUME_COMP_IND",
+	[MSG_SMS_SWITCH_HOST_INTERFACE_REQ           - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWITCH_HOST_INTERFACE_REQ",
+	[MSG_SMS_SWITCH_HOST_INTERFACE_RES           - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWITCH_HOST_INTERFACE_RES",
+	[MSG_SMS_DATA_DOWNLOAD_REQ                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_DOWNLOAD_REQ",
+	[MSG_SMS_DATA_DOWNLOAD_RES                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_DOWNLOAD_RES",
+	[MSG_SMS_DATA_VALIDITY_REQ                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_VALIDITY_REQ",
+	[MSG_SMS_DATA_VALIDITY_RES                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_VALIDITY_RES",
+	[MSG_SMS_SWDOWNLOAD_TRIGGER_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWDOWNLOAD_TRIGGER_REQ",
+	[MSG_SMS_SWDOWNLOAD_TRIGGER_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWDOWNLOAD_TRIGGER_RES",
+	[MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ",
+	[MSG_SMS_SWDOWNLOAD_BACKDOOR_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWDOWNLOAD_BACKDOOR_RES",
+	[MSG_SMS_GET_VERSION_EX_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_VERSION_EX_REQ",
+	[MSG_SMS_GET_VERSION_EX_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_VERSION_EX_RES",
+	[MSG_SMS_CLOCK_OUTPUT_CONFIG_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_CLOCK_OUTPUT_CONFIG_REQ",
+	[MSG_SMS_CLOCK_OUTPUT_CONFIG_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_CLOCK_OUTPUT_CONFIG_RES",
+	[MSG_SMS_I2C_SET_FREQ_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_I2C_SET_FREQ_REQ",
+	[MSG_SMS_I2C_SET_FREQ_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_I2C_SET_FREQ_RES",
+	[MSG_SMS_GENERIC_I2C_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_I2C_REQ",
+	[MSG_SMS_GENERIC_I2C_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_I2C_RES",
+	[MSG_SMS_DVBT_BDA_DATA                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_DVBT_BDA_DATA",
+	[MSG_SW_RELOAD_REQ                           - MSG_TYPE_BASE_VAL] = "MSG_SW_RELOAD_REQ",
+	[MSG_SMS_DATA_MSG                            - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_MSG",
+	[MSG_TABLE_UPLOAD_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_TABLE_UPLOAD_REQ",
+	[MSG_TABLE_UPLOAD_RES                        - MSG_TYPE_BASE_VAL] = "MSG_TABLE_UPLOAD_RES",
+	[MSG_SW_RELOAD_START_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SW_RELOAD_START_REQ",
+	[MSG_SW_RELOAD_START_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SW_RELOAD_START_RES",
+	[MSG_SW_RELOAD_EXEC_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SW_RELOAD_EXEC_REQ",
+	[MSG_SW_RELOAD_EXEC_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SW_RELOAD_EXEC_RES",
+	[MSG_SMS_SPI_INT_LINE_SET_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_INT_LINE_SET_REQ",
+	[MSG_SMS_SPI_INT_LINE_SET_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_INT_LINE_SET_RES",
+	[MSG_SMS_GPIO_CONFIG_EX_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_CONFIG_EX_REQ",
+	[MSG_SMS_GPIO_CONFIG_EX_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_CONFIG_EX_RES",
+	[MSG_SMS_WATCHDOG_ACT_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_WATCHDOG_ACT_REQ",
+	[MSG_SMS_WATCHDOG_ACT_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_WATCHDOG_ACT_RES",
+	[MSG_SMS_LOOPBACK_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOOPBACK_REQ",
+	[MSG_SMS_LOOPBACK_RES                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOOPBACK_RES",
+	[MSG_SMS_RAW_CAPTURE_START_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_RAW_CAPTURE_START_REQ",
+	[MSG_SMS_RAW_CAPTURE_START_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_RAW_CAPTURE_START_RES",
+	[MSG_SMS_RAW_CAPTURE_ABORT_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_RAW_CAPTURE_ABORT_REQ",
+	[MSG_SMS_RAW_CAPTURE_ABORT_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_RAW_CAPTURE_ABORT_RES",
+	[MSG_SMS_RAW_CAPTURE_COMPLETE_IND            - MSG_TYPE_BASE_VAL] = "MSG_SMS_RAW_CAPTURE_COMPLETE_IND",
+	[MSG_SMS_DATA_PUMP_IND                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_PUMP_IND",
+	[MSG_SMS_DATA_PUMP_REQ                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_PUMP_REQ",
+	[MSG_SMS_DATA_PUMP_RES                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_PUMP_RES",
+	[MSG_SMS_FLASH_DL_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_FLASH_DL_REQ",
+	[MSG_SMS_EXEC_TEST_1_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXEC_TEST_1_REQ",
+	[MSG_SMS_EXEC_TEST_1_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXEC_TEST_1_RES",
+	[MSG_SMS_ENBALE_TS_INTERFACE_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_ENBALE_TS_INTERFACE_REQ",
+	[MSG_SMS_ENBALE_TS_INTERFACE_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_ENBALE_TS_INTERFACE_RES",
+	[MSG_SMS_SPI_SET_BUS_WIDTH_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_SET_BUS_WIDTH_REQ",
+	[MSG_SMS_SPI_SET_BUS_WIDTH_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_SET_BUS_WIDTH_RES",
+	[MSG_SMS_SEND_EMM_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_EMM_REQ",
+	[MSG_SMS_SEND_EMM_RES                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_EMM_RES",
+	[MSG_SMS_DISABLE_TS_INTERFACE_REQ            - MSG_TYPE_BASE_VAL] = "MSG_SMS_DISABLE_TS_INTERFACE_REQ",
+	[MSG_SMS_DISABLE_TS_INTERFACE_RES            - MSG_TYPE_BASE_VAL] = "MSG_SMS_DISABLE_TS_INTERFACE_RES",
+	[MSG_SMS_IS_BUF_FREE_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_IS_BUF_FREE_REQ",
+	[MSG_SMS_IS_BUF_FREE_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_IS_BUF_FREE_RES",
+	[MSG_SMS_EXT_ANTENNA_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXT_ANTENNA_REQ",
+	[MSG_SMS_EXT_ANTENNA_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXT_ANTENNA_RES",
+	[MSG_SMS_CMMB_GET_NET_OF_FREQ_REQ_OBSOLETE   - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_NET_OF_FREQ_REQ_OBSOLETE",
+	[MSG_SMS_CMMB_GET_NET_OF_FREQ_RES_OBSOLETE   - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_NET_OF_FREQ_RES_OBSOLETE",
+	[MSG_SMS_BATTERY_LEVEL_REQ                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_BATTERY_LEVEL_REQ",
+	[MSG_SMS_BATTERY_LEVEL_RES                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_BATTERY_LEVEL_RES",
+	[MSG_SMS_CMMB_INJECT_TABLE_REQ_OBSOLETE      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_INJECT_TABLE_REQ_OBSOLETE",
+	[MSG_SMS_CMMB_INJECT_TABLE_RES_OBSOLETE      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_INJECT_TABLE_RES_OBSOLETE",
+	[MSG_SMS_FM_RADIO_BLOCK_IND                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_FM_RADIO_BLOCK_IND",
+	[MSG_SMS_HOST_NOTIFICATION_IND               - MSG_TYPE_BASE_VAL] = "MSG_SMS_HOST_NOTIFICATION_IND",
+	[MSG_SMS_CMMB_GET_CONTROL_TABLE_REQ_OBSOLETE - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_CONTROL_TABLE_REQ_OBSOLETE",
+	[MSG_SMS_CMMB_GET_CONTROL_TABLE_RES_OBSOLETE - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_CONTROL_TABLE_RES_OBSOLETE",
+	[MSG_SMS_CMMB_GET_NETWORKS_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_NETWORKS_REQ",
+	[MSG_SMS_CMMB_GET_NETWORKS_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_NETWORKS_RES",
+	[MSG_SMS_CMMB_START_SERVICE_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_START_SERVICE_REQ",
+	[MSG_SMS_CMMB_START_SERVICE_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_START_SERVICE_RES",
+	[MSG_SMS_CMMB_STOP_SERVICE_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_STOP_SERVICE_REQ",
+	[MSG_SMS_CMMB_STOP_SERVICE_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_STOP_SERVICE_RES",
+	[MSG_SMS_CMMB_ADD_CHANNEL_FILTER_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_ADD_CHANNEL_FILTER_REQ",
+	[MSG_SMS_CMMB_ADD_CHANNEL_FILTER_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_ADD_CHANNEL_FILTER_RES",
+	[MSG_SMS_CMMB_REMOVE_CHANNEL_FILTER_REQ      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_REMOVE_CHANNEL_FILTER_REQ",
+	[MSG_SMS_CMMB_REMOVE_CHANNEL_FILTER_RES      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_REMOVE_CHANNEL_FILTER_RES",
+	[MSG_SMS_CMMB_START_CONTROL_INFO_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_START_CONTROL_INFO_REQ",
+	[MSG_SMS_CMMB_START_CONTROL_INFO_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_START_CONTROL_INFO_RES",
+	[MSG_SMS_CMMB_STOP_CONTROL_INFO_REQ          - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_STOP_CONTROL_INFO_REQ",
+	[MSG_SMS_CMMB_STOP_CONTROL_INFO_RES          - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_STOP_CONTROL_INFO_RES",
+	[MSG_SMS_ISDBT_TUNE_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_TUNE_REQ",
+	[MSG_SMS_ISDBT_TUNE_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_TUNE_RES",
+	[MSG_SMS_TRANSMISSION_IND                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_TRANSMISSION_IND",
+	[MSG_SMS_PID_STATISTICS_IND                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_PID_STATISTICS_IND",
+	[MSG_SMS_POWER_DOWN_IND                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_DOWN_IND",
+	[MSG_SMS_POWER_DOWN_CONF                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_DOWN_CONF",
+	[MSG_SMS_POWER_UP_IND                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_UP_IND",
+	[MSG_SMS_POWER_UP_CONF                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_UP_CONF",
+	[MSG_SMS_POWER_MODE_SET_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_MODE_SET_REQ",
+	[MSG_SMS_POWER_MODE_SET_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_MODE_SET_RES",
+	[MSG_SMS_DEBUG_HOST_EVENT_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_DEBUG_HOST_EVENT_REQ",
+	[MSG_SMS_DEBUG_HOST_EVENT_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_DEBUG_HOST_EVENT_RES",
+	[MSG_SMS_NEW_CRYSTAL_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_NEW_CRYSTAL_REQ",
+	[MSG_SMS_NEW_CRYSTAL_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_NEW_CRYSTAL_RES",
+	[MSG_SMS_CONFIG_SPI_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CONFIG_SPI_REQ",
+	[MSG_SMS_CONFIG_SPI_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CONFIG_SPI_RES",
+	[MSG_SMS_I2C_SHORT_STAT_IND                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_I2C_SHORT_STAT_IND",
+	[MSG_SMS_START_IR_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_START_IR_REQ",
+	[MSG_SMS_START_IR_RES                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_START_IR_RES",
+	[MSG_SMS_IR_SAMPLES_IND                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_IR_SAMPLES_IND",
+	[MSG_SMS_CMMB_CA_SERVICE_IND                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_CA_SERVICE_IND",
+	[MSG_SMS_SLAVE_DEVICE_DETECTED               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SLAVE_DEVICE_DETECTED",
+	[MSG_SMS_INTERFACE_LOCK_IND                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_INTERFACE_LOCK_IND",
+	[MSG_SMS_INTERFACE_UNLOCK_IND                - MSG_TYPE_BASE_VAL] = "MSG_SMS_INTERFACE_UNLOCK_IND",
+	[MSG_SMS_SEND_ROSUM_BUFF_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_ROSUM_BUFF_REQ",
+	[MSG_SMS_SEND_ROSUM_BUFF_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_ROSUM_BUFF_RES",
+	[MSG_SMS_ROSUM_BUFF                          - MSG_TYPE_BASE_VAL] = "MSG_SMS_ROSUM_BUFF",
+	[MSG_SMS_SET_AES128_KEY_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_AES128_KEY_REQ",
+	[MSG_SMS_SET_AES128_KEY_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_AES128_KEY_RES",
+	[MSG_SMS_MBBMS_WRITE_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_MBBMS_WRITE_REQ",
+	[MSG_SMS_MBBMS_WRITE_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_MBBMS_WRITE_RES",
+	[MSG_SMS_MBBMS_READ_IND                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_MBBMS_READ_IND",
+	[MSG_SMS_IQ_STREAM_START_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_IQ_STREAM_START_REQ",
+	[MSG_SMS_IQ_STREAM_START_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_IQ_STREAM_START_RES",
+	[MSG_SMS_IQ_STREAM_STOP_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_IQ_STREAM_STOP_REQ",
+	[MSG_SMS_IQ_STREAM_STOP_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_IQ_STREAM_STOP_RES",
+	[MSG_SMS_IQ_STREAM_DATA_BLOCK                - MSG_TYPE_BASE_VAL] = "MSG_SMS_IQ_STREAM_DATA_BLOCK",
+	[MSG_SMS_GET_EEPROM_VERSION_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_EEPROM_VERSION_REQ",
+	[MSG_SMS_GET_EEPROM_VERSION_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_EEPROM_VERSION_RES",
+	[MSG_SMS_SIGNAL_DETECTED_IND                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SIGNAL_DETECTED_IND",
+	[MSG_SMS_NO_SIGNAL_IND                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_NO_SIGNAL_IND",
+	[MSG_SMS_MRC_SHUTDOWN_SLAVE_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_SHUTDOWN_SLAVE_REQ",
+	[MSG_SMS_MRC_SHUTDOWN_SLAVE_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_SHUTDOWN_SLAVE_RES",
+	[MSG_SMS_MRC_BRINGUP_SLAVE_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_BRINGUP_SLAVE_REQ",
+	[MSG_SMS_MRC_BRINGUP_SLAVE_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_BRINGUP_SLAVE_RES",
+	[MSG_SMS_EXTERNAL_LNA_CTRL_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXTERNAL_LNA_CTRL_REQ",
+	[MSG_SMS_EXTERNAL_LNA_CTRL_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXTERNAL_LNA_CTRL_RES",
+	[MSG_SMS_SET_PERIODIC_STATISTICS_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_PERIODIC_STATISTICS_REQ",
+	[MSG_SMS_SET_PERIODIC_STATISTICS_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_PERIODIC_STATISTICS_RES",
+	[MSG_SMS_CMMB_SET_AUTO_OUTPUT_TS0_REQ        - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_AUTO_OUTPUT_TS0_REQ",
+	[MSG_SMS_CMMB_SET_AUTO_OUTPUT_TS0_RES        - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_AUTO_OUTPUT_TS0_RES",
+	[LOCAL_TUNE                                  - MSG_TYPE_BASE_VAL] = "LOCAL_TUNE",
+	[LOCAL_IFFT_H_ICI                            - MSG_TYPE_BASE_VAL] = "LOCAL_IFFT_H_ICI",
+	[MSG_RESYNC_REQ                              - MSG_TYPE_BASE_VAL] = "MSG_RESYNC_REQ",
+	[MSG_SMS_CMMB_GET_MRC_STATISTICS_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_MRC_STATISTICS_REQ",
+	[MSG_SMS_CMMB_GET_MRC_STATISTICS_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_MRC_STATISTICS_RES",
+	[MSG_SMS_LOG_EX_ITEM                         - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOG_EX_ITEM",
+	[MSG_SMS_DEVICE_DATA_LOSS_IND                - MSG_TYPE_BASE_VAL] = "MSG_SMS_DEVICE_DATA_LOSS_IND",
+	[MSG_SMS_MRC_WATCHDOG_TRIGGERED_IND          - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_WATCHDOG_TRIGGERED_IND",
+	[MSG_SMS_USER_MSG_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_USER_MSG_REQ",
+	[MSG_SMS_USER_MSG_RES                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_USER_MSG_RES",
+	[MSG_SMS_SMART_CARD_INIT_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SMART_CARD_INIT_REQ",
+	[MSG_SMS_SMART_CARD_INIT_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SMART_CARD_INIT_RES",
+	[MSG_SMS_SMART_CARD_WRITE_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SMART_CARD_WRITE_REQ",
+	[MSG_SMS_SMART_CARD_WRITE_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SMART_CARD_WRITE_RES",
+	[MSG_SMS_SMART_CARD_READ_IND                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SMART_CARD_READ_IND",
+	[MSG_SMS_TSE_ENABLE_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_TSE_ENABLE_REQ",
+	[MSG_SMS_TSE_ENABLE_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_TSE_ENABLE_RES",
+	[MSG_SMS_CMMB_GET_SHORT_STATISTICS_REQ       - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_SHORT_STATISTICS_REQ",
+	[MSG_SMS_CMMB_GET_SHORT_STATISTICS_RES       - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_SHORT_STATISTICS_RES",
+	[MSG_SMS_LED_CONFIG_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_LED_CONFIG_REQ",
+	[MSG_SMS_LED_CONFIG_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_LED_CONFIG_RES",
+	[MSG_PWM_ANTENNA_REQ                         - MSG_TYPE_BASE_VAL] = "MSG_PWM_ANTENNA_REQ",
+	[MSG_PWM_ANTENNA_RES                         - MSG_TYPE_BASE_VAL] = "MSG_PWM_ANTENNA_RES",
+	[MSG_SMS_CMMB_SMD_SN_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SMD_SN_REQ",
+	[MSG_SMS_CMMB_SMD_SN_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SMD_SN_RES",
+	[MSG_SMS_CMMB_SET_CA_CW_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_CA_CW_REQ",
+	[MSG_SMS_CMMB_SET_CA_CW_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_CA_CW_RES",
+	[MSG_SMS_CMMB_SET_CA_SALT_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_CA_SALT_REQ",
+	[MSG_SMS_CMMB_SET_CA_SALT_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_CA_SALT_RES",
+	[MSG_SMS_NSCD_INIT_REQ                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_INIT_REQ",
+	[MSG_SMS_NSCD_INIT_RES                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_INIT_RES",
+	[MSG_SMS_NSCD_PROCESS_SECTION_REQ            - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_PROCESS_SECTION_REQ",
+	[MSG_SMS_NSCD_PROCESS_SECTION_RES            - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_PROCESS_SECTION_RES",
+	[MSG_SMS_DBD_CREATE_OBJECT_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_CREATE_OBJECT_REQ",
+	[MSG_SMS_DBD_CREATE_OBJECT_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_CREATE_OBJECT_RES",
+	[MSG_SMS_DBD_CONFIGURE_REQ                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_CONFIGURE_REQ",
+	[MSG_SMS_DBD_CONFIGURE_RES                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_CONFIGURE_RES",
+	[MSG_SMS_DBD_SET_KEYS_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_SET_KEYS_REQ",
+	[MSG_SMS_DBD_SET_KEYS_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_SET_KEYS_RES",
+	[MSG_SMS_DBD_PROCESS_HEADER_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_HEADER_REQ",
+	[MSG_SMS_DBD_PROCESS_HEADER_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_HEADER_RES",
+	[MSG_SMS_DBD_PROCESS_DATA_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_DATA_REQ",
+	[MSG_SMS_DBD_PROCESS_DATA_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_DATA_RES",
+	[MSG_SMS_DBD_PROCESS_GET_DATA_REQ            - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_GET_DATA_REQ",
+	[MSG_SMS_DBD_PROCESS_GET_DATA_RES            - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_GET_DATA_RES",
+	[MSG_SMS_NSCD_OPEN_SESSION_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_OPEN_SESSION_REQ",
+	[MSG_SMS_NSCD_OPEN_SESSION_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_OPEN_SESSION_RES",
+	[MSG_SMS_SEND_HOST_DATA_TO_DEMUX_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_HOST_DATA_TO_DEMUX_REQ",
+	[MSG_SMS_SEND_HOST_DATA_TO_DEMUX_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_HOST_DATA_TO_DEMUX_RES",
+	[MSG_LAST_MSG_TYPE                           - MSG_TYPE_BASE_VAL] = "MSG_LAST_MSG_TYPE",
+};
+
+char *smscore_translate_msg(enum msg_types msgtype)
+{
+	int i = msgtype - MSG_TYPE_BASE_VAL;
+	char *msg;
+
+	if (i < 0 || i >= ARRAY_SIZE(siano_msgs))
+		return "Unknown msg type";
+
+	msg = siano_msgs[i];
+
+	if (!*msg)
+		return "Unknown msg type";
+
+	return msg;
+}
+EXPORT_SYMBOL_GPL(smscore_translate_msg);
+
 void smscore_set_board_id(struct smscore_device_t *core, int id)
 {
 	core->board_id = id;
@@ -96,7 +434,7 @@ static struct mutex g_smscore_deviceslock;
 static struct list_head g_smscore_registry;
 static struct mutex g_smscore_registrylock;
 
-static int default_mode = 4;
+static int default_mode = DEVICE_MODE_NONE;
 
 module_param(default_mode, int, 0644);
 MODULE_PARM_DESC(default_mode, "default firmware id (device mode)");
@@ -151,10 +489,10 @@ static enum sms_device_type_st smscore_registry_gettype(char *devpath)
 	else
 		sms_err("No registry found.");
 
-	return -1;
+	return -EINVAL;
 }
 
-void smscore_registry_setmode(char *devpath, int mode)
+static void smscore_registry_setmode(char *devpath, int mode)
 {
 	struct smscore_registry_entry_t *entry;
 
@@ -294,10 +632,11 @@ static struct
 smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
 				       dma_addr_t common_buffer_phys)
 {
-	struct smscore_buffer_t *cb =
-		kmalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
+	struct smscore_buffer_t *cb;
+
+	cb = kzalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
 	if (!cb) {
-		sms_info("kmalloc(...) failed");
+		sms_info("kzalloc(...) failed");
 		return NULL;
 	}
 
@@ -344,6 +683,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
 	/* init completion events */
 	init_completion(&dev->version_ex_done);
 	init_completion(&dev->data_download_done);
+	init_completion(&dev->data_validity_done);
 	init_completion(&dev->trigger_done);
 	init_completion(&dev->init_device_done);
 	init_completion(&dev->reload_start_done);
@@ -370,9 +710,10 @@ int smscore_register_device(struct smsdevice_params_t *params,
 	for (buffer = dev->common_buffer;
 	     dev->num_buffers < params->num_buffers;
 	     dev->num_buffers++, buffer += params->buffer_size) {
-		struct smscore_buffer_t *cb =
-			smscore_createbuffer(buffer, dev->common_buffer,
-					     dev->common_buffer_phys);
+		struct smscore_buffer_t *cb;
+
+		cb = smscore_createbuffer(buffer, dev->common_buffer,
+					  dev->common_buffer_phys);
 		if (!cb) {
 			smscore_unregister_device(dev);
 			return -ENOMEM;
@@ -384,6 +725,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
 	sms_info("allocated %d buffers", dev->num_buffers);
 
 	dev->mode = DEVICE_MODE_NONE;
+	dev->board_id = SMS_BOARD_UNKNOWN;
 	dev->context = params->context;
 	dev->device = params->device;
 	dev->setmode_handler = params->setmode_handler;
@@ -413,7 +755,13 @@ EXPORT_SYMBOL_GPL(smscore_register_device);
 
 static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
 		void *buffer, size_t size, struct completion *completion) {
-	int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
+	int rc;
+
+	if (completion == NULL)
+		return -EINVAL;
+	init_completion(completion);
+
+	rc = coredev->sendrequest_handler(coredev->context, buffer, size);
 	if (rc < 0) {
 		sms_info("sendrequest returned error %d", rc);
 		return rc;
@@ -444,24 +792,22 @@ static int smscore_init_ir(struct smscore_device_t *coredev)
 		if	(rc != 0)
 			sms_err("Error initialization DTV IR sub-module");
 		else {
-			buffer = kmalloc(sizeof(struct SmsMsgData_ST2) +
+			buffer = kmalloc(sizeof(struct sms_msg_data2) +
 						SMS_DMA_ALIGNMENT,
 						GFP_KERNEL | GFP_DMA);
 			if (buffer) {
-				struct SmsMsgData_ST2 *msg =
-				(struct SmsMsgData_ST2 *)
+				struct sms_msg_data2 *msg =
+				(struct sms_msg_data2 *)
 				SMS_ALIGN_ADDRESS(buffer);
 
-				SMS_INIT_MSG(&msg->xMsgHeader,
+				SMS_INIT_MSG(&msg->x_msg_header,
 						MSG_SMS_START_IR_REQ,
-						sizeof(struct SmsMsgData_ST2));
-				msg->msgData[0] = coredev->ir.controller;
-				msg->msgData[1] = coredev->ir.timeout;
+						sizeof(struct sms_msg_data2));
+				msg->msg_data[0] = coredev->ir.controller;
+				msg->msg_data[1] = coredev->ir.timeout;
 
-				smsendian_handle_tx_message(
-					(struct SmsMsgHdr_ST2 *)msg);
 				rc = smscore_sendrequest_and_wait(coredev, msg,
-						msg->xMsgHeader. msgLength,
+						msg->x_msg_header. msg_length,
 						&coredev->ir_init_done);
 
 				kfree(buffer);
@@ -475,22 +821,83 @@ static int smscore_init_ir(struct smscore_device_t *coredev)
 	return 0;
 }
 
+/**
+ * configures device features according to board configuration structure.
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ *
+ * @return 0 on success, <0 on error.
+ */
+static int smscore_configure_board(struct smscore_device_t *coredev)
+{
+	struct sms_board *board;
+
+	board = sms_get_board(coredev->board_id);
+	if (!board) {
+		sms_err("no board configuration exist.");
+		return -EINVAL;
+	}
+
+	if (board->mtu) {
+		struct sms_msg_data mtu_msg;
+		sms_debug("set max transmit unit %d", board->mtu);
+
+		mtu_msg.x_msg_header.msg_src_id = 0;
+		mtu_msg.x_msg_header.msg_dst_id = HIF_TASK;
+		mtu_msg.x_msg_header.msg_flags = 0;
+		mtu_msg.x_msg_header.msg_type = MSG_SMS_SET_MAX_TX_MSG_LEN_REQ;
+		mtu_msg.x_msg_header.msg_length = sizeof(mtu_msg);
+		mtu_msg.msg_data[0] = board->mtu;
+
+		coredev->sendrequest_handler(coredev->context, &mtu_msg,
+					     sizeof(mtu_msg));
+	}
+
+	if (board->crystal) {
+		struct sms_msg_data crys_msg;
+		sms_debug("set crystal value %d", board->crystal);
+
+		SMS_INIT_MSG(&crys_msg.x_msg_header,
+				MSG_SMS_NEW_CRYSTAL_REQ,
+				sizeof(crys_msg));
+		crys_msg.msg_data[0] = board->crystal;
+
+		coredev->sendrequest_handler(coredev->context, &crys_msg,
+					     sizeof(crys_msg));
+	}
+
+	return 0;
+}
+
 /**
  * sets initial device mode and notifies client hotplugs that device is ready
  *
  * @param coredev pointer to a coredev object returned by
- * 		  smscore_register_device
+ *		  smscore_register_device
  *
  * @return 0 on success, <0 on error.
  */
 int smscore_start_device(struct smscore_device_t *coredev)
 {
-	int rc = smscore_set_device_mode(
-			coredev, smscore_registry_getmode(coredev->devpath));
+	int rc;
+	int board_id = smscore_get_board_id(coredev);
+	int mode = smscore_registry_getmode(coredev->devpath);
+
+	/* Device is initialized as DEVICE_MODE_NONE */
+	if (board_id != SMS_BOARD_UNKNOWN && mode == DEVICE_MODE_NONE)
+		mode = sms_get_board(board_id)->default_mode;
+
+	rc = smscore_set_device_mode(coredev, mode);
 	if (rc < 0) {
 		sms_info("set device mode faile , rc %d", rc);
 		return rc;
 	}
+	rc = smscore_configure_board(coredev);
+	if (rc < 0) {
+		sms_info("configure board failed , rc %d", rc);
+		return rc;
+	}
 
 	kmutex_lock(&g_smscore_deviceslock);
 
@@ -509,18 +916,19 @@ EXPORT_SYMBOL_GPL(smscore_start_device);
 static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
 					 void *buffer, size_t size)
 {
-	struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;
-	struct SmsMsgHdr_ST *msg;
-	u32 mem_address;
-	u8 *payload = firmware->Payload;
+	struct sms_firmware *firmware = (struct sms_firmware *) buffer;
+	struct sms_msg_data4 *msg;
+	u32 mem_address,  calc_checksum = 0;
+	u32 i, *ptr;
+	u8 *payload = firmware->payload;
 	int rc = 0;
-	firmware->StartAddress = le32_to_cpu(firmware->StartAddress);
-	firmware->Length = le32_to_cpu(firmware->Length);
+	firmware->start_address = le32_to_cpu(firmware->start_address);
+	firmware->length = le32_to_cpu(firmware->length);
 
-	mem_address = firmware->StartAddress;
+	mem_address = firmware->start_address;
 
 	sms_info("loading FW to addr 0x%x size %d",
-		 mem_address, firmware->Length);
+		 mem_address, firmware->length);
 	if (coredev->preload_handler) {
 		rc = coredev->preload_handler(coredev->context);
 		if (rc < 0)
@@ -534,35 +942,36 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
 
 	if (coredev->mode != DEVICE_MODE_NONE) {
 		sms_debug("sending reload command.");
-		SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ,
-			     sizeof(struct SmsMsgHdr_ST));
+		SMS_INIT_MSG(&msg->x_msg_header, MSG_SW_RELOAD_START_REQ,
+			     sizeof(struct sms_msg_hdr));
 		rc = smscore_sendrequest_and_wait(coredev, msg,
-						  msg->msgLength,
+						  msg->x_msg_header.msg_length,
 						  &coredev->reload_start_done);
+		if (rc < 0) {
+			sms_err("device reload failed, rc %d", rc);
+			goto exit_fw_download;
+		}
 		mem_address = *(u32 *) &payload[20];
 	}
 
+	for (i = 0, ptr = (u32 *)firmware->payload; i < firmware->length/4 ;
+	     i++, ptr++)
+		calc_checksum += *ptr;
+
 	while (size && rc >= 0) {
-		struct SmsDataDownload_ST *DataMsg =
-			(struct SmsDataDownload_ST *) msg;
-		int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE);
+		struct sms_data_download *data_msg =
+			(struct sms_data_download *) msg;
+		int payload_size = min_t(int, size, SMS_MAX_PAYLOAD_SIZE);
 
-		SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ,
-			     (u16)(sizeof(struct SmsMsgHdr_ST) +
+		SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_DATA_DOWNLOAD_REQ,
+			     (u16)(sizeof(struct sms_msg_hdr) +
 				      sizeof(u32) + payload_size));
 
-		DataMsg->MemAddr = mem_address;
-		memcpy(DataMsg->Payload, payload, payload_size);
+		data_msg->mem_addr = mem_address;
+		memcpy(data_msg->payload, payload, payload_size);
 
-		if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) &&
-		    (coredev->mode == DEVICE_MODE_NONE))
-			rc = coredev->sendrequest_handler(
-				coredev->context, DataMsg,
-				DataMsg->xMsgHeader.msgLength);
-		else
-			rc = smscore_sendrequest_and_wait(
-				coredev, DataMsg,
-				DataMsg->xMsgHeader.msgLength,
+		rc = smscore_sendrequest_and_wait(coredev, data_msg,
+				data_msg->x_msg_header.msg_length,
 				&coredev->data_download_done);
 
 		payload += payload_size;
@@ -570,50 +979,158 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
 		mem_address += payload_size;
 	}
 
-	if (rc >= 0) {
-		if (coredev->mode == DEVICE_MODE_NONE) {
-			struct SmsMsgData_ST *TriggerMsg =
-				(struct SmsMsgData_ST *) msg;
-
-			SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
-				     sizeof(struct SmsMsgHdr_ST) +
-				     sizeof(u32) * 5);
-
-			TriggerMsg->msgData[0] = firmware->StartAddress;
-						/* Entry point */
-			TriggerMsg->msgData[1] = 5; /* Priority */
-			TriggerMsg->msgData[2] = 0x200; /* Stack size */
-			TriggerMsg->msgData[3] = 0; /* Parameter */
-			TriggerMsg->msgData[4] = 4; /* Task ID */
-
-			if (coredev->device_flags & SMS_ROM_NO_RESPONSE) {
-				rc = coredev->sendrequest_handler(
-					coredev->context, TriggerMsg,
-					TriggerMsg->xMsgHeader.msgLength);
-				msleep(100);
-			} else
-				rc = smscore_sendrequest_and_wait(
-					coredev, TriggerMsg,
-					TriggerMsg->xMsgHeader.msgLength,
+	if (rc < 0)
+		goto exit_fw_download;
+
+	sms_err("sending MSG_SMS_DATA_VALIDITY_REQ expecting 0x%x",
+		calc_checksum);
+	SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_DATA_VALIDITY_REQ,
+			sizeof(msg->x_msg_header) +
+			sizeof(u32) * 3);
+	msg->msg_data[0] = firmware->start_address;
+		/* Entry point */
+	msg->msg_data[1] = firmware->length;
+	msg->msg_data[2] = 0; /* Regular checksum*/
+	rc = smscore_sendrequest_and_wait(coredev, msg,
+					  msg->x_msg_header.msg_length,
+					  &coredev->data_validity_done);
+	if (rc < 0)
+		goto exit_fw_download;
+
+	if (coredev->mode == DEVICE_MODE_NONE) {
+		struct sms_msg_data *trigger_msg =
+			(struct sms_msg_data *) msg;
+
+		sms_debug("sending MSG_SMS_SWDOWNLOAD_TRIGGER_REQ");
+		SMS_INIT_MSG(&msg->x_msg_header,
+				MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
+				sizeof(struct sms_msg_hdr) +
+				sizeof(u32) * 5);
+
+		trigger_msg->msg_data[0] = firmware->start_address;
+					/* Entry point */
+		trigger_msg->msg_data[1] = 6; /* Priority */
+		trigger_msg->msg_data[2] = 0x200; /* Stack size */
+		trigger_msg->msg_data[3] = 0; /* Parameter */
+		trigger_msg->msg_data[4] = 4; /* Task ID */
+
+		rc = smscore_sendrequest_and_wait(coredev, trigger_msg,
+					trigger_msg->x_msg_header.msg_length,
 					&coredev->trigger_done);
-		} else {
-			SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,
-				     sizeof(struct SmsMsgHdr_ST));
-
-			rc = coredev->sendrequest_handler(coredev->context,
-							  msg, msg->msgLength);
-		}
-		msleep(500);
+	} else {
+		SMS_INIT_MSG(&msg->x_msg_header, MSG_SW_RELOAD_EXEC_REQ,
+				sizeof(struct sms_msg_hdr));
+		rc = coredev->sendrequest_handler(coredev->context, msg,
+				msg->x_msg_header.msg_length);
 	}
 
-	sms_debug("rc=%d, postload=%p ", rc,
-		  coredev->postload_handler);
+	if (rc < 0)
+		goto exit_fw_download;
+
+	/*
+	 * backward compatibility - wait to device_ready_done for
+	 * not more than 400 ms
+	 */
+	msleep(400);
 
+exit_fw_download:
 	kfree(msg);
 
-	return ((rc >= 0) && coredev->postload_handler) ?
-		coredev->postload_handler(coredev->context) :
-		rc;
+	if (coredev->postload_handler) {
+		sms_debug("rc=%d, postload=0x%p", rc, coredev->postload_handler);
+		if (rc >= 0)
+			return coredev->postload_handler(coredev->context);
+	}
+
+	sms_debug("rc=%d", rc);
+	return rc;
+}
+
+static char *smscore_fw_lkup[][DEVICE_MODE_MAX] = {
+	[SMS_NOVA_A0] = {
+		[DEVICE_MODE_DVBT]		= SMS_FW_DVB_NOVA_12MHZ,
+		[DEVICE_MODE_DVBH]		= SMS_FW_DVB_NOVA_12MHZ,
+		[DEVICE_MODE_DAB_TDMB]		= SMS_FW_TDMB_NOVA_12MHZ,
+		[DEVICE_MODE_DVBT_BDA]		= SMS_FW_DVB_NOVA_12MHZ,
+		[DEVICE_MODE_ISDBT]		= SMS_FW_ISDBT_NOVA_12MHZ,
+		[DEVICE_MODE_ISDBT_BDA]		= SMS_FW_ISDBT_NOVA_12MHZ,
+	},
+	[SMS_NOVA_B0] = {
+		[DEVICE_MODE_DVBT]		= SMS_FW_DVB_NOVA_12MHZ_B0,
+		[DEVICE_MODE_DVBH]		= SMS_FW_DVB_NOVA_12MHZ_B0,
+		[DEVICE_MODE_DAB_TDMB]		= SMS_FW_TDMB_NOVA_12MHZ_B0,
+		[DEVICE_MODE_DVBT_BDA]		= SMS_FW_DVB_NOVA_12MHZ_B0,
+		[DEVICE_MODE_ISDBT]		= SMS_FW_ISDBT_NOVA_12MHZ_B0,
+		[DEVICE_MODE_ISDBT_BDA]		= SMS_FW_ISDBT_NOVA_12MHZ_B0,
+		[DEVICE_MODE_FM_RADIO]		= SMS_FW_FM_RADIO,
+		[DEVICE_MODE_FM_RADIO_BDA]	= SMS_FW_FM_RADIO,
+	},
+	[SMS_VEGA] = {
+		[DEVICE_MODE_CMMB]		= SMS_FW_CMMB_VEGA_12MHZ,
+	},
+	[SMS_VENICE] = {
+		[DEVICE_MODE_CMMB]		= SMS_FW_CMMB_VENICE_12MHZ,
+	},
+	[SMS_MING] = {
+		[DEVICE_MODE_CMMB]		= SMS_FW_CMMB_MING_APP,
+	},
+	[SMS_PELE] = {
+		[DEVICE_MODE_ISDBT]		= SMS_FW_ISDBT_PELE,
+		[DEVICE_MODE_ISDBT_BDA]		= SMS_FW_ISDBT_PELE,
+	},
+	[SMS_RIO] = {
+		[DEVICE_MODE_DVBT]		= SMS_FW_DVB_RIO,
+		[DEVICE_MODE_DVBH]		= SMS_FW_DVBH_RIO,
+		[DEVICE_MODE_DVBT_BDA]		= SMS_FW_DVB_RIO,
+		[DEVICE_MODE_ISDBT]		= SMS_FW_ISDBT_RIO,
+		[DEVICE_MODE_ISDBT_BDA]		= SMS_FW_ISDBT_RIO,
+		[DEVICE_MODE_FM_RADIO]		= SMS_FW_FM_RADIO_RIO,
+		[DEVICE_MODE_FM_RADIO_BDA]	= SMS_FW_FM_RADIO_RIO,
+	},
+	[SMS_DENVER_1530] = {
+		[DEVICE_MODE_ATSC]		= SMS_FW_ATSC_DENVER,
+	},
+	[SMS_DENVER_2160] = {
+		[DEVICE_MODE_DAB_TDMB]		= SMS_FW_TDMB_DENVER,
+	},
+};
+
+/**
+ * get firmware file name from one of the two mechanisms : sms_boards or
+ * smscore_fw_lkup.
+ * @param coredev pointer to a coredev object returned by
+ *		  smscore_register_device
+ * @param mode requested mode of operation
+ * @param lookup if 1, always get the fw filename from smscore_fw_lkup
+ *	 table. if 0, try first to get from sms_boards
+ *
+ * @return 0 on success, <0 on error.
+ */
+static char *smscore_get_fw_filename(struct smscore_device_t *coredev,
+			      int mode)
+{
+	char **fw;
+	int board_id = smscore_get_board_id(coredev);
+	enum sms_device_type_st type;
+
+	type = smscore_registry_gettype(coredev->devpath);
+
+	/* Prevent looking outside the smscore_fw_lkup table */
+	if (type <= SMS_UNKNOWN_TYPE || type >= SMS_NUM_OF_DEVICE_TYPES)
+		return NULL;
+	if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX)
+		return NULL;
+
+	sms_debug("trying to get fw name from sms_boards board_id %d mode %d",
+		  board_id, mode);
+	fw = sms_get_board(board_id)->fw;
+	if (!fw || !fw[mode]) {
+		sms_debug("cannot find fw name in sms_boards, getting from lookup table mode %d type %d",
+			  mode, type);
+		return smscore_fw_lkup[type][mode];
+	}
+
+	return fw[mode];
 }
 
 /**
@@ -627,41 +1144,46 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
  * @return 0 on success, <0 on error.
  */
 static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
-					   char *filename,
+					   int mode,
 					   loadfirmware_t loadfirmware_handler)
 {
 	int rc = -ENOENT;
+	u8 *fw_buf;
+	u32 fw_buf_size;
 	const struct firmware *fw;
-	u8 *fw_buffer;
 
-	if (loadfirmware_handler == NULL && !(coredev->device_flags &
-					      SMS_DEVICE_FAMILY2))
+	char *fw_filename = smscore_get_fw_filename(coredev, mode);
+	if (!fw_filename) {
+		sms_info("mode %d not supported on this device", mode);
+		return -ENOENT;
+	}
+	sms_debug("Firmware name: %s", fw_filename);
+
+	if (loadfirmware_handler == NULL && !(coredev->device_flags
+			& SMS_DEVICE_FAMILY2))
 		return -EINVAL;
 
-	rc = request_firmware(&fw, filename, coredev->device);
+	rc = request_firmware(&fw, fw_filename, coredev->device);
 	if (rc < 0) {
-		sms_info("failed to open \"%s\"", filename);
+		sms_info("failed to open \"%s\"", fw_filename);
 		return rc;
 	}
-	sms_info("read FW %s, size=%zd", filename, fw->size);
-	fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
-			    GFP_KERNEL | GFP_DMA);
-	if (fw_buffer) {
-		memcpy(fw_buffer, fw->data, fw->size);
-
-		rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
-		      smscore_load_firmware_family2(coredev,
-						    fw_buffer,
-						    fw->size) :
-		      loadfirmware_handler(coredev->context,
-					   fw_buffer, fw->size);
-
-		kfree(fw_buffer);
-	} else {
+	sms_info("read fw %s, buffer size=0x%zx", fw_filename, fw->size);
+	fw_buf = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
+			 GFP_KERNEL | GFP_DMA);
+	if (!fw_buf) {
 		sms_info("failed to allocate firmware buffer");
-		rc = -ENOMEM;
+		return -ENOMEM;
 	}
+	memcpy(fw_buf, fw->data, fw->size);
+	fw_buf_size = fw->size;
+
+	rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
+		smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size)
+		: loadfirmware_handler(coredev->context, fw_buf,
+		fw_buf_size);
 
+	kfree(fw_buf);
 	release_firmware(fw);
 
 	return rc;
@@ -703,14 +1225,15 @@ void smscore_unregister_device(struct smscore_device_t *coredev)
 		if (num_buffers == coredev->num_buffers)
 			break;
 		if (++retry > 10) {
-			sms_info("exiting although "
-				 "not all buffers released.");
+			sms_info("exiting although not all buffers released.");
 			break;
 		}
 
 		sms_info("waiting for %d buffer(s)",
 			 coredev->num_buffers - num_buffers);
+		kmutex_unlock(&g_smscore_deviceslock);
 		msleep(100);
+		kmutex_lock(&g_smscore_deviceslock);
 	}
 
 	sms_info("freed %d buffers", num_buffers);
@@ -719,8 +1242,7 @@ void smscore_unregister_device(struct smscore_device_t *coredev)
 		dma_free_coherent(NULL, coredev->common_buffer_size,
 			coredev->common_buffer, coredev->common_buffer_phys);
 
-	if (coredev->fw_buf != NULL)
-		kfree(coredev->fw_buf);
+	kfree(coredev->fw_buf);
 
 	list_del(&coredev->entry);
 	kfree(coredev);
@@ -733,19 +1255,19 @@ EXPORT_SYMBOL_GPL(smscore_unregister_device);
 
 static int smscore_detect_mode(struct smscore_device_t *coredev)
 {
-	void *buffer = kmalloc(sizeof(struct SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT,
+	void *buffer = kmalloc(sizeof(struct sms_msg_hdr) + SMS_DMA_ALIGNMENT,
 			       GFP_KERNEL | GFP_DMA);
-	struct SmsMsgHdr_ST *msg =
-		(struct SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer);
+	struct sms_msg_hdr *msg =
+		(struct sms_msg_hdr *) SMS_ALIGN_ADDRESS(buffer);
 	int rc;
 
 	if (!buffer)
 		return -ENOMEM;
 
 	SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ,
-		     sizeof(struct SmsMsgHdr_ST));
+		     sizeof(struct sms_msg_hdr));
 
-	rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength,
+	rc = smscore_sendrequest_and_wait(coredev, msg, msg->msg_length,
 					  &coredev->version_ex_done);
 	if (rc == -ETIME) {
 		sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");
@@ -753,11 +1275,11 @@ static int smscore_detect_mode(struct smscore_device_t *coredev)
 		if (wait_for_completion_timeout(&coredev->resume_done,
 						msecs_to_jiffies(5000))) {
 			rc = smscore_sendrequest_and_wait(
-				coredev, msg, msg->msgLength,
+				coredev, msg, msg->msg_length,
 				&coredev->version_ex_done);
 			if (rc < 0)
-				sms_err("MSG_SMS_GET_VERSION_EX_REQ failed "
-					"second try, rc %d", rc);
+				sms_err("MSG_SMS_GET_VERSION_EX_REQ failed second try, rc %d",
+					rc);
 		} else
 			rc = -ETIME;
 	}
@@ -767,31 +1289,39 @@ static int smscore_detect_mode(struct smscore_device_t *coredev)
 	return rc;
 }
 
-static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = {
-	/*Stellar		NOVA A0		Nova B0		VEGA*/
-	/*DVBT*/
-	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
-	/*DVBH*/
-	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
-	/*TDMB*/
-	{"none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none"},
-	/*DABIP*/
-	{"none", "none", "none", "none"},
-	/*BDA*/
-	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
-	/*ISDBT*/
-	{"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
-	/*ISDBTBDA*/
-	{"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
-	/*CMMB*/
-	{"none", "none", "none", "cmmb_vega_12mhz.inp"}
-};
-
-static inline char *sms_get_fw_name(struct smscore_device_t *coredev,
-				    int mode, enum sms_device_type_st type)
+/**
+ * send init device request and wait for response
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ * @param mode requested mode of operation
+ *
+ * @return 0 on success, <0 on error.
+ */
+static int smscore_init_device(struct smscore_device_t *coredev, int mode)
 {
-	char **fw = sms_get_board(smscore_get_board_id(coredev))->fw;
-	return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type];
+	void *buffer;
+	struct sms_msg_data *msg;
+	int rc = 0;
+
+	buffer = kmalloc(sizeof(struct sms_msg_data) +
+			SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
+	if (!buffer) {
+		sms_err("Could not allocate buffer for init device message.");
+		return -ENOMEM;
+	}
+
+	msg = (struct sms_msg_data *)SMS_ALIGN_ADDRESS(buffer);
+	SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ,
+			sizeof(struct sms_msg_data));
+	msg->msg_data[0] = mode;
+
+	rc = smscore_sendrequest_and_wait(coredev, msg,
+			msg->x_msg_header. msg_length,
+			&coredev->init_device_done);
+
+	kfree(buffer);
+	return rc;
 }
 
 /**
@@ -806,13 +1336,11 @@ static inline char *sms_get_fw_name(struct smscore_device_t *coredev,
  */
 int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
 {
-	void *buffer;
 	int rc = 0;
-	enum sms_device_type_st type;
 
 	sms_debug("set device mode to %d", mode);
 	if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
-		if (mode < DEVICE_MODE_DVBT || mode >= DEVICE_MODE_RAW_TUNER) {
+		if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX) {
 			sms_err("invalid mode specified %d", mode);
 			return -EINVAL;
 		}
@@ -833,58 +1361,21 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
 		}
 
 		if (!(coredev->modes_supported & (1 << mode))) {
-			char *fw_filename;
-
-			type = smscore_registry_gettype(coredev->devpath);
-			fw_filename = sms_get_fw_name(coredev, mode, type);
-
 			rc = smscore_load_firmware_from_file(coredev,
-							     fw_filename, NULL);
-			if (rc < 0) {
-				sms_warn("error %d loading firmware: %s, "
-					 "trying again with default firmware",
-					 rc, fw_filename);
-
-				/* try again with the default firmware */
-				fw_filename = smscore_fw_lkup[mode][type];
-				rc = smscore_load_firmware_from_file(coredev,
-							     fw_filename, NULL);
-
-				if (rc < 0) {
-					sms_warn("error %d loading "
-						 "firmware: %s", rc,
-						 fw_filename);
-					return rc;
-				}
-			}
-			sms_log("firmware download success: %s", fw_filename);
-		} else
-			sms_info("mode %d supported by running "
-				 "firmware", mode);
-
-		buffer = kmalloc(sizeof(struct SmsMsgData_ST) +
-				 SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
-		if (buffer) {
-			struct SmsMsgData_ST *msg =
-				(struct SmsMsgData_ST *)
-					SMS_ALIGN_ADDRESS(buffer);
-
-			SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,
-				     sizeof(struct SmsMsgData_ST));
-			msg->msgData[0] = mode;
-
-			rc = smscore_sendrequest_and_wait(
-				coredev, msg, msg->xMsgHeader.msgLength,
-				&coredev->init_device_done);
-
-			kfree(buffer);
+							     mode, NULL);
+			if (rc >= 0)
+				sms_info("firmware download success");
 		} else {
-			sms_err("Could not allocate buffer for "
-				"init device message.");
-			rc = -ENOMEM;
+			sms_info("mode %d is already supported by running firmware",
+				 mode);
+		}
+		if (coredev->fw_version >= 0x800) {
+			rc = smscore_init_device(coredev, mode);
+			if (rc < 0)
+				sms_err("device init failed, rc %d.", rc);
 		}
 	} else {
-		if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
+		if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX) {
 			sms_err("invalid mode specified %d", mode);
 			return -EINVAL;
 		}
@@ -900,12 +1391,32 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
 	}
 
 	if (rc >= 0) {
+		char *buffer;
 		coredev->mode = mode;
 		coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
+
+		buffer = kmalloc(sizeof(struct sms_msg_data) +
+				 SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
+		if (buffer) {
+			struct sms_msg_data *msg = (struct sms_msg_data *) SMS_ALIGN_ADDRESS(buffer);
+
+			SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ,
+				     sizeof(struct sms_msg_data));
+			msg->msg_data[0] = mode;
+
+			rc = smscore_sendrequest_and_wait(
+				coredev, msg, msg->x_msg_header.msg_length,
+				&coredev->init_device_done);
+
+			kfree(buffer);
+		}
 	}
 
 	if (rc < 0)
 		sms_err("return error code %d.", rc);
+	else
+		sms_debug("Success setting device mode.");
+
 	return rc;
 }
 
@@ -971,7 +1482,7 @@ found:
  */
 void smscore_onresponse(struct smscore_device_t *coredev,
 		struct smscore_buffer_t *cb) {
-	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) ((u8 *) cb->p
+	struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) ((u8 *) cb->p
 			+ cb->offset);
 	struct smscore_client_t *client;
 	int rc = -EBUSY;
@@ -983,7 +1494,7 @@ void smscore_onresponse(struct smscore_device_t *coredev,
 		last_sample_time = time_now;
 
 	if (time_now - last_sample_time > 10000) {
-		sms_debug("\ndata rate %d bytes/secs",
+		sms_debug("data rate %d bytes/secs",
 			  (int)((data_total * 1000) /
 				(time_now - last_sample_time)));
 
@@ -993,14 +1504,14 @@ void smscore_onresponse(struct smscore_device_t *coredev,
 
 	data_total += cb->size;
 	/* Do we need to re-route? */
-	if ((phdr->msgType == MSG_SMS_HO_PER_SLICES_IND) ||
-			(phdr->msgType == MSG_SMS_TRANSMISSION_IND)) {
+	if ((phdr->msg_type == MSG_SMS_HO_PER_SLICES_IND) ||
+			(phdr->msg_type == MSG_SMS_TRANSMISSION_IND)) {
 		if (coredev->mode == DEVICE_MODE_DVBT_BDA)
-			phdr->msgDstId = DVBT_BDA_CONTROL_MSG_ID;
+			phdr->msg_dst_id = DVBT_BDA_CONTROL_MSG_ID;
 	}
 
 
-	client = smscore_find_client(coredev, phdr->msgType, phdr->msgDstId);
+	client = smscore_find_client(coredev, phdr->msg_type, phdr->msg_dst_id);
 
 	/* If no client registered for type & id,
 	 * check for control client where type is not registered */
@@ -1008,57 +1519,75 @@ void smscore_onresponse(struct smscore_device_t *coredev,
 		rc = client->onresponse_handler(client->context, cb);
 
 	if (rc < 0) {
-		switch (phdr->msgType) {
+		switch (phdr->msg_type) {
+		case MSG_SMS_ISDBT_TUNE_RES:
+			break;
+		case MSG_SMS_RF_TUNE_RES:
+			break;
+		case MSG_SMS_SIGNAL_DETECTED_IND:
+			break;
+		case MSG_SMS_NO_SIGNAL_IND:
+			break;
+		case MSG_SMS_SPI_INT_LINE_SET_RES:
+			break;
+		case MSG_SMS_INTERFACE_LOCK_IND:
+			break;
+		case MSG_SMS_INTERFACE_UNLOCK_IND:
+			break;
 		case MSG_SMS_GET_VERSION_EX_RES:
 		{
-			struct SmsVersionRes_ST *ver =
-				(struct SmsVersionRes_ST *) phdr;
-			sms_debug("MSG_SMS_GET_VERSION_EX_RES "
-				  "id %d prots 0x%x ver %d.%d",
-				  ver->FirmwareId, ver->SupportedProtocols,
-				  ver->RomVersionMajor, ver->RomVersionMinor);
-
-			coredev->mode = ver->FirmwareId == 255 ?
-				DEVICE_MODE_NONE : ver->FirmwareId;
-			coredev->modes_supported = ver->SupportedProtocols;
+			struct sms_version_res *ver =
+				(struct sms_version_res *) phdr;
+			sms_debug("Firmware id %d prots 0x%x ver %d.%d",
+				  ver->firmware_id, ver->supported_protocols,
+				  ver->rom_ver_major, ver->rom_ver_minor);
+
+			coredev->mode = ver->firmware_id == 255 ?
+				DEVICE_MODE_NONE : ver->firmware_id;
+			coredev->modes_supported = ver->supported_protocols;
+			coredev->fw_version = ver->rom_ver_major << 8 |
+					      ver->rom_ver_minor;
 
 			complete(&coredev->version_ex_done);
 			break;
 		}
 		case MSG_SMS_INIT_DEVICE_RES:
-			sms_debug("MSG_SMS_INIT_DEVICE_RES");
 			complete(&coredev->init_device_done);
 			break;
 		case MSG_SW_RELOAD_START_RES:
-			sms_debug("MSG_SW_RELOAD_START_RES");
 			complete(&coredev->reload_start_done);
 			break;
+		case MSG_SMS_DATA_VALIDITY_RES:
+		{
+			struct sms_msg_data *validity = (struct sms_msg_data *) phdr;
+
+			sms_err("MSG_SMS_DATA_VALIDITY_RES, checksum = 0x%x",
+				validity->msg_data[0]);
+			complete(&coredev->data_validity_done);
+			break;
+		}
 		case MSG_SMS_DATA_DOWNLOAD_RES:
 			complete(&coredev->data_download_done);
 			break;
 		case MSG_SW_RELOAD_EXEC_RES:
-			sms_debug("MSG_SW_RELOAD_EXEC_RES");
 			break;
 		case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
-			sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");
 			complete(&coredev->trigger_done);
 			break;
 		case MSG_SMS_SLEEP_RESUME_COMP_IND:
 			complete(&coredev->resume_done);
 			break;
 		case MSG_SMS_GPIO_CONFIG_EX_RES:
-			sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES");
 			complete(&coredev->gpio_configuration_done);
 			break;
 		case MSG_SMS_GPIO_SET_LEVEL_RES:
-			sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES");
 			complete(&coredev->gpio_set_level_done);
 			break;
 		case MSG_SMS_GPIO_GET_LEVEL_RES:
 		{
 			u32 *msgdata = (u32 *) phdr;
 			coredev->gpio_get_res = msgdata[1];
-			sms_debug("MSG_SMS_GPIO_GET_LEVEL_RES gpio level %d",
+			sms_debug("gpio level %d",
 					coredev->gpio_get_res);
 			complete(&coredev->gpio_get_level_done);
 			break;
@@ -1070,12 +1599,24 @@ void smscore_onresponse(struct smscore_device_t *coredev,
 			sms_ir_event(coredev,
 				(const char *)
 				((char *)phdr
-				+ sizeof(struct SmsMsgHdr_ST)),
-				(int)phdr->msgLength
-				- sizeof(struct SmsMsgHdr_ST));
+				+ sizeof(struct sms_msg_hdr)),
+				(int)phdr->msg_length
+				- sizeof(struct sms_msg_hdr));
+			break;
+
+		case MSG_SMS_DVBT_BDA_DATA:
+			/*
+			 * It can be received here, if the frontend is
+			 * tuned into a valid channel and the proper firmware
+			 * is loaded. That happens when the module got removed
+			 * and re-inserted, without powering the device off
+			 */
 			break;
 
 		default:
+			sms_debug("message %s(%d) not handled.",
+				  smscore_translate_msg(phdr->msg_type),
+				  phdr->msg_type);
 			break;
 		}
 		smscore_putbuffer(coredev, cb);
@@ -1257,7 +1798,7 @@ int smsclient_sendrequest(struct smscore_client_t *client,
 			  void *buffer, size_t size)
 {
 	struct smscore_device_t *coredev;
-	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) buffer;
+	struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) buffer;
 	int rc;
 
 	if (client == NULL) {
@@ -1274,7 +1815,7 @@ int smsclient_sendrequest(struct smscore_client_t *client,
 	}
 
 	rc = smscore_validate_client(client->coredev, client, 0,
-				     phdr->msgSrcId);
+				     phdr->msg_src_id);
 	if (rc < 0)
 		return rc;
 
@@ -1288,16 +1829,16 @@ int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
 			   struct smscore_config_gpio *pinconfig)
 {
 	struct {
-		struct SmsMsgHdr_ST hdr;
+		struct sms_msg_hdr hdr;
 		u32 data[6];
 	} msg;
 
 	if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
-		msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-		msg.hdr.msgDstId = HIF_TASK;
-		msg.hdr.msgFlags = 0;
-		msg.hdr.msgType  = MSG_SMS_GPIO_CONFIG_EX_REQ;
-		msg.hdr.msgLength = sizeof(msg);
+		msg.hdr.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+		msg.hdr.msg_dst_id = HIF_TASK;
+		msg.hdr.msg_flags = 0;
+		msg.hdr.msg_type  = MSG_SMS_GPIO_CONFIG_EX_REQ;
+		msg.hdr.msg_length = sizeof(msg);
 
 		msg.data[0] = pin;
 		msg.data[1] = pinconfig->pullupdown;
@@ -1306,16 +1847,16 @@ int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
 		msg.data[2] = pinconfig->outputslewrate == 0 ? 3 : 0;
 
 		switch (pinconfig->outputdriving) {
-		case SMS_GPIO_OUTPUTDRIVING_16mA:
+		case SMS_GPIO_OUTPUTDRIVING_S_16mA:
 			msg.data[3] = 7; /* Nova - 16mA */
 			break;
-		case SMS_GPIO_OUTPUTDRIVING_12mA:
+		case SMS_GPIO_OUTPUTDRIVING_S_12mA:
 			msg.data[3] = 5; /* Nova - 11mA */
 			break;
-		case SMS_GPIO_OUTPUTDRIVING_8mA:
+		case SMS_GPIO_OUTPUTDRIVING_S_8mA:
 			msg.data[3] = 3; /* Nova - 7mA */
 			break;
-		case SMS_GPIO_OUTPUTDRIVING_4mA:
+		case SMS_GPIO_OUTPUTDRIVING_S_4mA:
 		default:
 			msg.data[3] = 2; /* Nova - 4mA */
 			break;
@@ -1333,18 +1874,18 @@ int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
 int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level)
 {
 	struct {
-		struct SmsMsgHdr_ST hdr;
+		struct sms_msg_hdr hdr;
 		u32 data[3];
 	} msg;
 
 	if (pin > MAX_GPIO_PIN_NUMBER)
 		return -EINVAL;
 
-	msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	msg.hdr.msgDstId = HIF_TASK;
-	msg.hdr.msgFlags = 0;
-	msg.hdr.msgType  = MSG_SMS_GPIO_SET_LEVEL_REQ;
-	msg.hdr.msgLength = sizeof(msg);
+	msg.hdr.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+	msg.hdr.msg_dst_id = HIF_TASK;
+	msg.hdr.msg_flags = 0;
+	msg.hdr.msg_type  = MSG_SMS_GPIO_SET_LEVEL_REQ;
+	msg.hdr.msg_length = sizeof(msg);
 
 	msg.data[0] = pin;
 	msg.data[1] = level ? 1 : 0;
@@ -1355,122 +1896,121 @@ int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level)
 }
 
 /* new GPIO management implementation */
-static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum,
-		u32 *pGroupNum, u32 *pGroupCfg) {
-
-	*pGroupCfg = 1;
-
-	if (PinNum <= 1)	{
-		*pTranslatedPinNum = 0;
-		*pGroupNum = 9;
-		*pGroupCfg = 2;
-	} else if (PinNum >= 2 && PinNum <= 6) {
-		*pTranslatedPinNum = 2;
-		*pGroupNum = 0;
-		*pGroupCfg = 2;
-	} else if (PinNum >= 7 && PinNum <= 11) {
-		*pTranslatedPinNum = 7;
-		*pGroupNum = 1;
-	} else if (PinNum >= 12 && PinNum <= 15) {
-		*pTranslatedPinNum = 12;
-		*pGroupNum = 2;
-		*pGroupCfg = 3;
-	} else if (PinNum == 16) {
-		*pTranslatedPinNum = 16;
-		*pGroupNum = 23;
-	} else if (PinNum >= 17 && PinNum <= 24) {
-		*pTranslatedPinNum = 17;
-		*pGroupNum = 3;
-	} else if (PinNum == 25) {
-		*pTranslatedPinNum = 25;
-		*pGroupNum = 6;
-	} else if (PinNum >= 26 && PinNum <= 28) {
-		*pTranslatedPinNum = 26;
-		*pGroupNum = 4;
-	} else if (PinNum == 29) {
-		*pTranslatedPinNum = 29;
-		*pGroupNum = 5;
-		*pGroupCfg = 2;
-	} else if (PinNum == 30) {
-		*pTranslatedPinNum = 30;
-		*pGroupNum = 8;
-	} else if (PinNum == 31) {
-		*pTranslatedPinNum = 31;
-		*pGroupNum = 17;
+static int get_gpio_pin_params(u32 pin_num, u32 *p_translatedpin_num,
+		u32 *p_group_num, u32 *p_group_cfg) {
+
+	*p_group_cfg = 1;
+
+	if (pin_num <= 1)	{
+		*p_translatedpin_num = 0;
+		*p_group_num = 9;
+		*p_group_cfg = 2;
+	} else if (pin_num >= 2 && pin_num <= 6) {
+		*p_translatedpin_num = 2;
+		*p_group_num = 0;
+		*p_group_cfg = 2;
+	} else if (pin_num >= 7 && pin_num <= 11) {
+		*p_translatedpin_num = 7;
+		*p_group_num = 1;
+	} else if (pin_num >= 12 && pin_num <= 15) {
+		*p_translatedpin_num = 12;
+		*p_group_num = 2;
+		*p_group_cfg = 3;
+	} else if (pin_num == 16) {
+		*p_translatedpin_num = 16;
+		*p_group_num = 23;
+	} else if (pin_num >= 17 && pin_num <= 24) {
+		*p_translatedpin_num = 17;
+		*p_group_num = 3;
+	} else if (pin_num == 25) {
+		*p_translatedpin_num = 25;
+		*p_group_num = 6;
+	} else if (pin_num >= 26 && pin_num <= 28) {
+		*p_translatedpin_num = 26;
+		*p_group_num = 4;
+	} else if (pin_num == 29) {
+		*p_translatedpin_num = 29;
+		*p_group_num = 5;
+		*p_group_cfg = 2;
+	} else if (pin_num == 30) {
+		*p_translatedpin_num = 30;
+		*p_group_num = 8;
+	} else if (pin_num == 31) {
+		*p_translatedpin_num = 31;
+		*p_group_num = 17;
 	} else
 		return -1;
 
-	*pGroupCfg <<= 24;
+	*p_group_cfg <<= 24;
 
 	return 0;
 }
 
-int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
-		struct smscore_gpio_config *pGpioConfig) {
+int smscore_gpio_configure(struct smscore_device_t *coredev, u8 pin_num,
+		struct smscore_config_gpio *p_gpio_config) {
 
-	u32 totalLen;
-	u32 TranslatedPinNum = 0;
-	u32 GroupNum = 0;
-	u32 ElectricChar;
-	u32 groupCfg;
+	u32 total_len;
+	u32 translatedpin_num = 0;
+	u32 group_num = 0;
+	u32 electric_char;
+	u32 group_cfg;
 	void *buffer;
 	int rc;
 
-	struct SetGpioMsg {
-		struct SmsMsgHdr_ST xMsgHeader;
-		u32 msgData[6];
-	} *pMsg;
+	struct set_gpio_msg {
+		struct sms_msg_hdr x_msg_header;
+		u32 msg_data[6];
+	} *p_msg;
 
 
-	if (PinNum > MAX_GPIO_PIN_NUMBER)
+	if (pin_num > MAX_GPIO_PIN_NUMBER)
 		return -EINVAL;
 
-	if (pGpioConfig == NULL)
+	if (p_gpio_config == NULL)
 		return -EINVAL;
 
-	totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6);
+	total_len = sizeof(struct sms_msg_hdr) + (sizeof(u32) * 6);
 
-	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+	buffer = kmalloc(total_len + SMS_DMA_ALIGNMENT,
 			GFP_KERNEL | GFP_DMA);
 	if (!buffer)
 		return -ENOMEM;
 
-	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+	p_msg = (struct set_gpio_msg *) SMS_ALIGN_ADDRESS(buffer);
 
-	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	pMsg->xMsgHeader.msgDstId = HIF_TASK;
-	pMsg->xMsgHeader.msgFlags = 0;
-	pMsg->xMsgHeader.msgLength = (u16) totalLen;
-	pMsg->msgData[0] = PinNum;
+	p_msg->x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+	p_msg->x_msg_header.msg_dst_id = HIF_TASK;
+	p_msg->x_msg_header.msg_flags = 0;
+	p_msg->x_msg_header.msg_length = (u16) total_len;
+	p_msg->msg_data[0] = pin_num;
 
 	if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) {
-		pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ;
-		if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum,
-				&groupCfg) != 0) {
+		p_msg->x_msg_header.msg_type = MSG_SMS_GPIO_CONFIG_REQ;
+		if (get_gpio_pin_params(pin_num, &translatedpin_num, &group_num,
+				&group_cfg) != 0) {
 			rc = -EINVAL;
 			goto free;
 		}
 
-		pMsg->msgData[1] = TranslatedPinNum;
-		pMsg->msgData[2] = GroupNum;
-		ElectricChar = (pGpioConfig->PullUpDown)
-				| (pGpioConfig->InputCharacteristics << 2)
-				| (pGpioConfig->OutputSlewRate << 3)
-				| (pGpioConfig->OutputDriving << 4);
-		pMsg->msgData[3] = ElectricChar;
-		pMsg->msgData[4] = pGpioConfig->Direction;
-		pMsg->msgData[5] = groupCfg;
+		p_msg->msg_data[1] = translatedpin_num;
+		p_msg->msg_data[2] = group_num;
+		electric_char = (p_gpio_config->pullupdown)
+				| (p_gpio_config->inputcharacteristics << 2)
+				| (p_gpio_config->outputslewrate << 3)
+				| (p_gpio_config->outputdriving << 4);
+		p_msg->msg_data[3] = electric_char;
+		p_msg->msg_data[4] = p_gpio_config->direction;
+		p_msg->msg_data[5] = group_cfg;
 	} else {
-		pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ;
-		pMsg->msgData[1] = pGpioConfig->PullUpDown;
-		pMsg->msgData[2] = pGpioConfig->OutputSlewRate;
-		pMsg->msgData[3] = pGpioConfig->OutputDriving;
-		pMsg->msgData[4] = pGpioConfig->Direction;
-		pMsg->msgData[5] = 0;
+		p_msg->x_msg_header.msg_type = MSG_SMS_GPIO_CONFIG_EX_REQ;
+		p_msg->msg_data[1] = p_gpio_config->pullupdown;
+		p_msg->msg_data[2] = p_gpio_config->outputslewrate;
+		p_msg->msg_data[3] = p_gpio_config->outputdriving;
+		p_msg->msg_data[4] = p_gpio_config->direction;
+		p_msg->msg_data[5] = 0;
 	}
 
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
-	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+	rc = smscore_sendrequest_and_wait(coredev, p_msg, total_len,
 			&coredev->gpio_configuration_done);
 
 	if (rc != 0) {
@@ -1485,42 +2025,41 @@ free:
 	return rc;
 }
 
-int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
-		u8 NewLevel) {
+int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 pin_num,
+		u8 new_level) {
 
-	u32 totalLen;
+	u32 total_len;
 	int rc;
 	void *buffer;
 
-	struct SetGpioMsg {
-		struct SmsMsgHdr_ST xMsgHeader;
-		u32 msgData[3]; /* keep it 3 ! */
-	} *pMsg;
+	struct set_gpio_msg {
+		struct sms_msg_hdr x_msg_header;
+		u32 msg_data[3]; /* keep it 3 ! */
+	} *p_msg;
 
-	if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER))
+	if ((new_level > 1) || (pin_num > MAX_GPIO_PIN_NUMBER))
 		return -EINVAL;
 
-	totalLen = sizeof(struct SmsMsgHdr_ST) +
+	total_len = sizeof(struct sms_msg_hdr) +
 			(3 * sizeof(u32)); /* keep it 3 ! */
 
-	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+	buffer = kmalloc(total_len + SMS_DMA_ALIGNMENT,
 			GFP_KERNEL | GFP_DMA);
 	if (!buffer)
 		return -ENOMEM;
 
-	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+	p_msg = (struct set_gpio_msg *) SMS_ALIGN_ADDRESS(buffer);
 
-	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	pMsg->xMsgHeader.msgDstId = HIF_TASK;
-	pMsg->xMsgHeader.msgFlags = 0;
-	pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ;
-	pMsg->xMsgHeader.msgLength = (u16) totalLen;
-	pMsg->msgData[0] = PinNum;
-	pMsg->msgData[1] = NewLevel;
+	p_msg->x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+	p_msg->x_msg_header.msg_dst_id = HIF_TASK;
+	p_msg->x_msg_header.msg_flags = 0;
+	p_msg->x_msg_header.msg_type = MSG_SMS_GPIO_SET_LEVEL_REQ;
+	p_msg->x_msg_header.msg_length = (u16) total_len;
+	p_msg->msg_data[0] = pin_num;
+	p_msg->msg_data[1] = new_level;
 
 	/* Send message to SMS */
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
-	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+	rc = smscore_sendrequest_and_wait(coredev, p_msg, total_len,
 			&coredev->gpio_set_level_done);
 
 	if (rc != 0) {
@@ -1534,42 +2073,41 @@ int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
 	return rc;
 }
 
-int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
+int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 pin_num,
 		u8 *level) {
 
-	u32 totalLen;
+	u32 total_len;
 	int rc;
 	void *buffer;
 
-	struct SetGpioMsg {
-		struct SmsMsgHdr_ST xMsgHeader;
-		u32 msgData[2];
-	} *pMsg;
+	struct set_gpio_msg {
+		struct sms_msg_hdr x_msg_header;
+		u32 msg_data[2];
+	} *p_msg;
 
 
-	if (PinNum > MAX_GPIO_PIN_NUMBER)
+	if (pin_num > MAX_GPIO_PIN_NUMBER)
 		return -EINVAL;
 
-	totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32));
+	total_len = sizeof(struct sms_msg_hdr) + (2 * sizeof(u32));
 
-	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+	buffer = kmalloc(total_len + SMS_DMA_ALIGNMENT,
 			GFP_KERNEL | GFP_DMA);
 	if (!buffer)
 		return -ENOMEM;
 
-	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+	p_msg = (struct set_gpio_msg *) SMS_ALIGN_ADDRESS(buffer);
 
-	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	pMsg->xMsgHeader.msgDstId = HIF_TASK;
-	pMsg->xMsgHeader.msgFlags = 0;
-	pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ;
-	pMsg->xMsgHeader.msgLength = (u16) totalLen;
-	pMsg->msgData[0] = PinNum;
-	pMsg->msgData[1] = 0;
+	p_msg->x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+	p_msg->x_msg_header.msg_dst_id = HIF_TASK;
+	p_msg->x_msg_header.msg_flags = 0;
+	p_msg->x_msg_header.msg_type = MSG_SMS_GPIO_GET_LEVEL_REQ;
+	p_msg->x_msg_header.msg_length = (u16) total_len;
+	p_msg->msg_data[0] = pin_num;
+	p_msg->msg_data[1] = 0;
 
 	/* Send message to SMS */
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
-	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+	rc = smscore_sendrequest_and_wait(coredev, p_msg, total_len,
 			&coredev->gpio_get_level_done);
 
 	if (rc != 0) {
@@ -1635,3 +2173,27 @@ module_exit(smscore_module_exit);
 MODULE_DESCRIPTION("Siano MDTV Core module");
 MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
 MODULE_LICENSE("GPL");
+
+/* This should match what's defined at smscoreapi.h */
+MODULE_FIRMWARE(SMS_FW_ATSC_DENVER);
+MODULE_FIRMWARE(SMS_FW_CMMB_MING_APP);
+MODULE_FIRMWARE(SMS_FW_CMMB_VEGA_12MHZ);
+MODULE_FIRMWARE(SMS_FW_CMMB_VENICE_12MHZ);
+MODULE_FIRMWARE(SMS_FW_DVBH_RIO);
+MODULE_FIRMWARE(SMS_FW_DVB_NOVA_12MHZ_B0);
+MODULE_FIRMWARE(SMS_FW_DVB_NOVA_12MHZ);
+MODULE_FIRMWARE(SMS_FW_DVB_RIO);
+MODULE_FIRMWARE(SMS_FW_FM_RADIO);
+MODULE_FIRMWARE(SMS_FW_FM_RADIO_RIO);
+MODULE_FIRMWARE(SMS_FW_DVBT_HCW_55XXX);
+MODULE_FIRMWARE(SMS_FW_ISDBT_HCW_55XXX);
+MODULE_FIRMWARE(SMS_FW_ISDBT_NOVA_12MHZ_B0);
+MODULE_FIRMWARE(SMS_FW_ISDBT_NOVA_12MHZ);
+MODULE_FIRMWARE(SMS_FW_ISDBT_PELE);
+MODULE_FIRMWARE(SMS_FW_ISDBT_RIO);
+MODULE_FIRMWARE(SMS_FW_DVBT_NOVA_A);
+MODULE_FIRMWARE(SMS_FW_DVBT_NOVA_B);
+MODULE_FIRMWARE(SMS_FW_DVBT_STELLAR);
+MODULE_FIRMWARE(SMS_FW_TDMB_DENVER);
+MODULE_FIRMWARE(SMS_FW_TDMB_NOVA_12MHZ_B0);
+MODULE_FIRMWARE(SMS_FW_TDMB_NOVA_12MHZ);

+ 712 - 295
drivers/media/common/siano/smscoreapi.h

@@ -40,9 +40,33 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define kmutex_trylock(_p_) mutex_trylock(_p_)
 #define kmutex_unlock(_p_) mutex_unlock(_p_)
 
-#ifndef min
-#define min(a, b) (((a) < (b)) ? (a) : (b))
-#endif
+/*
+ * Define the firmware names used by the driver.
+ * Those should match what's used at smscoreapi.c and sms-cards.c
+ * including the MODULE_FIRMWARE() macros at the end of smscoreapi.c
+ */
+#define SMS_FW_ATSC_DENVER         "atsc_denver.inp"
+#define SMS_FW_CMMB_MING_APP       "cmmb_ming_app.inp"
+#define SMS_FW_CMMB_VEGA_12MHZ     "cmmb_vega_12mhz.inp"
+#define SMS_FW_CMMB_VENICE_12MHZ   "cmmb_venice_12mhz.inp"
+#define SMS_FW_DVBH_RIO            "dvbh_rio.inp"
+#define SMS_FW_DVB_NOVA_12MHZ_B0   "dvb_nova_12mhz_b0.inp"
+#define SMS_FW_DVB_NOVA_12MHZ      "dvb_nova_12mhz.inp"
+#define SMS_FW_DVB_RIO             "dvb_rio.inp"
+#define SMS_FW_FM_RADIO            "fm_radio.inp"
+#define SMS_FW_FM_RADIO_RIO        "fm_radio_rio.inp"
+#define SMS_FW_DVBT_HCW_55XXX      "sms1xxx-hcw-55xxx-dvbt-02.fw"
+#define SMS_FW_ISDBT_HCW_55XXX     "sms1xxx-hcw-55xxx-isdbt-02.fw"
+#define SMS_FW_ISDBT_NOVA_12MHZ_B0 "isdbt_nova_12mhz_b0.inp"
+#define SMS_FW_ISDBT_NOVA_12MHZ    "isdbt_nova_12mhz.inp"
+#define SMS_FW_ISDBT_PELE          "isdbt_pele.inp"
+#define SMS_FW_ISDBT_RIO           "isdbt_rio.inp"
+#define SMS_FW_DVBT_NOVA_A         "sms1xxx-nova-a-dvbt-01.fw"
+#define SMS_FW_DVBT_NOVA_B         "sms1xxx-nova-b-dvbt-01.fw"
+#define SMS_FW_DVBT_STELLAR        "sms1xxx-stellar-dvbt-01.fw"
+#define SMS_FW_TDMB_DENVER         "tdmb_denver.inp"
+#define SMS_FW_TDMB_NOVA_12MHZ_B0  "tdmb_nova_12mhz_b0.inp"
+#define SMS_FW_TDMB_NOVA_12MHZ     "tdmb_nova_12mhz.inp"
 
 #define SMS_PROTOCOL_MAX_RAOUNDTRIP_MS			(10000)
 #define SMS_ALLOC_ALIGNMENT				128
@@ -50,18 +74,31 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define SMS_ALIGN_ADDRESS(addr) \
 	((((uintptr_t)(addr)) + (SMS_DMA_ALIGNMENT-1)) & ~(SMS_DMA_ALIGNMENT-1))
 
+#define SMS_DEVICE_FAMILY1				0
 #define SMS_DEVICE_FAMILY2				1
 #define SMS_ROM_NO_RESPONSE				2
 #define SMS_DEVICE_NOT_READY				0x8000000
 
 enum sms_device_type_st {
+	SMS_UNKNOWN_TYPE = -1,
 	SMS_STELLAR = 0,
 	SMS_NOVA_A0,
 	SMS_NOVA_B0,
 	SMS_VEGA,
+	SMS_VENICE,
+	SMS_MING,
+	SMS_PELE,
+	SMS_RIO,
+	SMS_DENVER_1530,
+	SMS_DENVER_2160,
 	SMS_NUM_OF_DEVICE_TYPES
 };
 
+enum sms_power_mode_st {
+	SMS_POWER_MODE_ACTIVE,
+	SMS_POWER_MODE_SUSPENDED
+};
+
 struct smscore_device_t;
 struct smscore_client_t;
 struct smscore_buffer_t;
@@ -149,6 +186,7 @@ struct smscore_device_t {
 
 	/* host <--> device messages */
 	struct completion version_ex_done, data_download_done, trigger_done;
+	struct completion data_validity_done, device_ready_done;
 	struct completion init_device_done, reload_start_done, resume_done;
 	struct completion gpio_configuration_done, gpio_set_level_done;
 	struct completion gpio_get_level_done, ir_init_done;
@@ -165,10 +203,17 @@ struct smscore_device_t {
 	/* Firmware */
 	u8 *fw_buf;
 	u32 fw_buf_size;
+	u16 fw_version;
 
 	/* Infrared (IR) */
 	struct ir_t ir;
 
+	/*
+	 * Identify if device is USB or not.
+	 * Used by smsdvb-sysfs to know the root node for debugfs
+	 */
+	bool is_usb_device;
+
 	int led_state;
 };
 
@@ -176,81 +221,363 @@ struct smscore_device_t {
 #define SMS_ANTENNA_GPIO_0					1
 #define SMS_ANTENNA_GPIO_1					0
 
-#define BW_8_MHZ							0
-#define BW_7_MHZ							1
-#define BW_6_MHZ							2
-#define BW_5_MHZ							3
-#define BW_ISDBT_1SEG						4
-#define BW_ISDBT_3SEG						5
+enum sms_bandwidth_mode {
+	BW_8_MHZ = 0,
+	BW_7_MHZ = 1,
+	BW_6_MHZ = 2,
+	BW_5_MHZ = 3,
+	BW_ISDBT_1SEG = 4,
+	BW_ISDBT_3SEG = 5,
+	BW_2_MHZ = 6,
+	BW_FM_RADIO = 7,
+	BW_ISDBT_13SEG = 8,
+	BW_1_5_MHZ = 15,
+	BW_UNKNOWN = 0xffff
+};
+
 
 #define MSG_HDR_FLAG_SPLIT_MSG				4
 
 #define MAX_GPIO_PIN_NUMBER					31
 
 #define HIF_TASK							11
+#define HIF_TASK_SLAVE					22
+#define HIF_TASK_SLAVE2					33
+#define HIF_TASK_SLAVE3					44
 #define SMS_HOST_LIB						150
 #define DVBT_BDA_CONTROL_MSG_ID				201
 
 #define SMS_MAX_PAYLOAD_SIZE				240
 #define SMS_TUNE_TIMEOUT					500
 
-#define MSG_SMS_GPIO_CONFIG_REQ				507
-#define MSG_SMS_GPIO_CONFIG_RES				508
-#define MSG_SMS_GPIO_SET_LEVEL_REQ			509
-#define MSG_SMS_GPIO_SET_LEVEL_RES			510
-#define MSG_SMS_GPIO_GET_LEVEL_REQ			511
-#define MSG_SMS_GPIO_GET_LEVEL_RES			512
-#define MSG_SMS_RF_TUNE_REQ					561
-#define MSG_SMS_RF_TUNE_RES					562
-#define MSG_SMS_INIT_DEVICE_REQ				578
-#define MSG_SMS_INIT_DEVICE_RES				579
-#define MSG_SMS_ADD_PID_FILTER_REQ			601
-#define MSG_SMS_ADD_PID_FILTER_RES			602
-#define MSG_SMS_REMOVE_PID_FILTER_REQ			603
-#define MSG_SMS_REMOVE_PID_FILTER_RES			604
-#define MSG_SMS_DAB_CHANNEL				607
-#define MSG_SMS_GET_PID_FILTER_LIST_REQ			608
-#define MSG_SMS_GET_PID_FILTER_LIST_RES			609
-#define MSG_SMS_GET_STATISTICS_RES			616
-#define MSG_SMS_GET_STATISTICS_REQ			615
-#define MSG_SMS_HO_PER_SLICES_IND			630
-#define MSG_SMS_SET_ANTENNA_CONFIG_REQ			651
-#define MSG_SMS_SET_ANTENNA_CONFIG_RES			652
-#define MSG_SMS_SLEEP_RESUME_COMP_IND			655
-#define MSG_SMS_DATA_DOWNLOAD_REQ			660
-#define MSG_SMS_DATA_DOWNLOAD_RES			661
-#define MSG_SMS_SWDOWNLOAD_TRIGGER_REQ		664
-#define MSG_SMS_SWDOWNLOAD_TRIGGER_RES		665
-#define MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ		666
-#define MSG_SMS_SWDOWNLOAD_BACKDOOR_RES		667
-#define MSG_SMS_GET_VERSION_EX_REQ			668
-#define MSG_SMS_GET_VERSION_EX_RES			669
-#define MSG_SMS_SET_CLOCK_OUTPUT_REQ		670
-#define MSG_SMS_I2C_SET_FREQ_REQ			685
-#define MSG_SMS_GENERIC_I2C_REQ				687
-#define MSG_SMS_GENERIC_I2C_RES				688
-#define MSG_SMS_DVBT_BDA_DATA				693
-#define MSG_SW_RELOAD_REQ					697
-#define MSG_SMS_DATA_MSG					699
-#define MSG_SW_RELOAD_START_REQ				702
-#define MSG_SW_RELOAD_START_RES				703
-#define MSG_SW_RELOAD_EXEC_REQ				704
-#define MSG_SW_RELOAD_EXEC_RES				705
-#define MSG_SMS_SPI_INT_LINE_SET_REQ		710
-#define MSG_SMS_GPIO_CONFIG_EX_REQ			712
-#define MSG_SMS_GPIO_CONFIG_EX_RES			713
-#define MSG_SMS_ISDBT_TUNE_REQ				776
-#define MSG_SMS_ISDBT_TUNE_RES				777
-#define MSG_SMS_TRANSMISSION_IND			782
-#define MSG_SMS_START_IR_REQ				800
-#define MSG_SMS_START_IR_RES				801
-#define MSG_SMS_IR_SAMPLES_IND				802
-#define MSG_SMS_SIGNAL_DETECTED_IND			827
-#define MSG_SMS_NO_SIGNAL_IND				828
+enum msg_types {
+	MSG_TYPE_BASE_VAL = 500,
+	MSG_SMS_GET_VERSION_REQ = 503,
+	MSG_SMS_GET_VERSION_RES = 504,
+	MSG_SMS_MULTI_BRIDGE_CFG = 505,
+	MSG_SMS_GPIO_CONFIG_REQ = 507,
+	MSG_SMS_GPIO_CONFIG_RES = 508,
+	MSG_SMS_GPIO_SET_LEVEL_REQ = 509,
+	MSG_SMS_GPIO_SET_LEVEL_RES = 510,
+	MSG_SMS_GPIO_GET_LEVEL_REQ = 511,
+	MSG_SMS_GPIO_GET_LEVEL_RES = 512,
+	MSG_SMS_EEPROM_BURN_IND = 513,
+	MSG_SMS_LOG_ENABLE_CHANGE_REQ = 514,
+	MSG_SMS_LOG_ENABLE_CHANGE_RES = 515,
+	MSG_SMS_SET_MAX_TX_MSG_LEN_REQ = 516,
+	MSG_SMS_SET_MAX_TX_MSG_LEN_RES = 517,
+	MSG_SMS_SPI_HALFDUPLEX_TOKEN_HOST_TO_DEVICE = 518,
+	MSG_SMS_SPI_HALFDUPLEX_TOKEN_DEVICE_TO_HOST = 519,
+	MSG_SMS_BACKGROUND_SCAN_FLAG_CHANGE_REQ = 520,
+	MSG_SMS_BACKGROUND_SCAN_FLAG_CHANGE_RES = 521,
+	MSG_SMS_BACKGROUND_SCAN_SIGNAL_DETECTED_IND = 522,
+	MSG_SMS_BACKGROUND_SCAN_NO_SIGNAL_IND = 523,
+	MSG_SMS_CONFIGURE_RF_SWITCH_REQ = 524,
+	MSG_SMS_CONFIGURE_RF_SWITCH_RES = 525,
+	MSG_SMS_MRC_PATH_DISCONNECT_REQ = 526,
+	MSG_SMS_MRC_PATH_DISCONNECT_RES = 527,
+	MSG_SMS_RECEIVE_1SEG_THROUGH_FULLSEG_REQ = 528,
+	MSG_SMS_RECEIVE_1SEG_THROUGH_FULLSEG_RES = 529,
+	MSG_SMS_RECEIVE_VHF_VIA_VHF_INPUT_REQ = 530,
+	MSG_SMS_RECEIVE_VHF_VIA_VHF_INPUT_RES = 531,
+	MSG_WR_REG_RFT_REQ = 533,
+	MSG_WR_REG_RFT_RES = 534,
+	MSG_RD_REG_RFT_REQ = 535,
+	MSG_RD_REG_RFT_RES = 536,
+	MSG_RD_REG_ALL_RFT_REQ = 537,
+	MSG_RD_REG_ALL_RFT_RES = 538,
+	MSG_HELP_INT = 539,
+	MSG_RUN_SCRIPT_INT = 540,
+	MSG_SMS_EWS_INBAND_REQ = 541,
+	MSG_SMS_EWS_INBAND_RES = 542,
+	MSG_SMS_RFS_SELECT_REQ = 543,
+	MSG_SMS_RFS_SELECT_RES = 544,
+	MSG_SMS_MB_GET_VER_REQ = 545,
+	MSG_SMS_MB_GET_VER_RES = 546,
+	MSG_SMS_MB_WRITE_CFGFILE_REQ = 547,
+	MSG_SMS_MB_WRITE_CFGFILE_RES = 548,
+	MSG_SMS_MB_READ_CFGFILE_REQ = 549,
+	MSG_SMS_MB_READ_CFGFILE_RES = 550,
+	MSG_SMS_RD_MEM_REQ = 552,
+	MSG_SMS_RD_MEM_RES = 553,
+	MSG_SMS_WR_MEM_REQ = 554,
+	MSG_SMS_WR_MEM_RES = 555,
+	MSG_SMS_UPDATE_MEM_REQ = 556,
+	MSG_SMS_UPDATE_MEM_RES = 557,
+	MSG_SMS_ISDBT_ENABLE_FULL_PARAMS_SET_REQ = 558,
+	MSG_SMS_ISDBT_ENABLE_FULL_PARAMS_SET_RES = 559,
+	MSG_SMS_RF_TUNE_REQ = 561,
+	MSG_SMS_RF_TUNE_RES = 562,
+	MSG_SMS_ISDBT_ENABLE_HIGH_MOBILITY_REQ = 563,
+	MSG_SMS_ISDBT_ENABLE_HIGH_MOBILITY_RES = 564,
+	MSG_SMS_ISDBT_SB_RECEPTION_REQ = 565,
+	MSG_SMS_ISDBT_SB_RECEPTION_RES = 566,
+	MSG_SMS_GENERIC_EPROM_WRITE_REQ = 567,
+	MSG_SMS_GENERIC_EPROM_WRITE_RES = 568,
+	MSG_SMS_GENERIC_EPROM_READ_REQ = 569,
+	MSG_SMS_GENERIC_EPROM_READ_RES = 570,
+	MSG_SMS_EEPROM_WRITE_REQ = 571,
+	MSG_SMS_EEPROM_WRITE_RES = 572,
+	MSG_SMS_CUSTOM_READ_REQ = 574,
+	MSG_SMS_CUSTOM_READ_RES = 575,
+	MSG_SMS_CUSTOM_WRITE_REQ = 576,
+	MSG_SMS_CUSTOM_WRITE_RES = 577,
+	MSG_SMS_INIT_DEVICE_REQ = 578,
+	MSG_SMS_INIT_DEVICE_RES = 579,
+	MSG_SMS_ATSC_SET_ALL_IP_REQ = 580,
+	MSG_SMS_ATSC_SET_ALL_IP_RES = 581,
+	MSG_SMS_ATSC_START_ENSEMBLE_REQ = 582,
+	MSG_SMS_ATSC_START_ENSEMBLE_RES = 583,
+	MSG_SMS_SET_OUTPUT_MODE_REQ = 584,
+	MSG_SMS_SET_OUTPUT_MODE_RES = 585,
+	MSG_SMS_ATSC_IP_FILTER_GET_LIST_REQ = 586,
+	MSG_SMS_ATSC_IP_FILTER_GET_LIST_RES = 587,
+	MSG_SMS_SUB_CHANNEL_START_REQ = 589,
+	MSG_SMS_SUB_CHANNEL_START_RES = 590,
+	MSG_SMS_SUB_CHANNEL_STOP_REQ = 591,
+	MSG_SMS_SUB_CHANNEL_STOP_RES = 592,
+	MSG_SMS_ATSC_IP_FILTER_ADD_REQ = 593,
+	MSG_SMS_ATSC_IP_FILTER_ADD_RES = 594,
+	MSG_SMS_ATSC_IP_FILTER_REMOVE_REQ = 595,
+	MSG_SMS_ATSC_IP_FILTER_REMOVE_RES = 596,
+	MSG_SMS_ATSC_IP_FILTER_REMOVE_ALL_REQ = 597,
+	MSG_SMS_ATSC_IP_FILTER_REMOVE_ALL_RES = 598,
+	MSG_SMS_WAIT_CMD = 599,
+	MSG_SMS_ADD_PID_FILTER_REQ = 601,
+	MSG_SMS_ADD_PID_FILTER_RES = 602,
+	MSG_SMS_REMOVE_PID_FILTER_REQ = 603,
+	MSG_SMS_REMOVE_PID_FILTER_RES = 604,
+	MSG_SMS_FAST_INFORMATION_CHANNEL_REQ = 605,
+	MSG_SMS_FAST_INFORMATION_CHANNEL_RES = 606,
+	MSG_SMS_DAB_CHANNEL = 607,
+	MSG_SMS_GET_PID_FILTER_LIST_REQ = 608,
+	MSG_SMS_GET_PID_FILTER_LIST_RES = 609,
+	MSG_SMS_POWER_DOWN_REQ = 610,
+	MSG_SMS_POWER_DOWN_RES = 611,
+	MSG_SMS_ATSC_SLT_EXIST_IND = 612,
+	MSG_SMS_ATSC_NO_SLT_IND = 613,
+	MSG_SMS_GET_STATISTICS_REQ = 615,
+	MSG_SMS_GET_STATISTICS_RES = 616,
+	MSG_SMS_SEND_DUMP = 617,
+	MSG_SMS_SCAN_START_REQ = 618,
+	MSG_SMS_SCAN_START_RES = 619,
+	MSG_SMS_SCAN_STOP_REQ = 620,
+	MSG_SMS_SCAN_STOP_RES = 621,
+	MSG_SMS_SCAN_PROGRESS_IND = 622,
+	MSG_SMS_SCAN_COMPLETE_IND = 623,
+	MSG_SMS_LOG_ITEM = 624,
+	MSG_SMS_DAB_SUBCHANNEL_RECONFIG_REQ = 628,
+	MSG_SMS_DAB_SUBCHANNEL_RECONFIG_RES = 629,
+	MSG_SMS_HO_PER_SLICES_IND = 630,
+	MSG_SMS_HO_INBAND_POWER_IND = 631,
+	MSG_SMS_MANUAL_DEMOD_REQ = 632,
+	MSG_SMS_HO_TUNE_ON_REQ = 636,
+	MSG_SMS_HO_TUNE_ON_RES = 637,
+	MSG_SMS_HO_TUNE_OFF_REQ = 638,
+	MSG_SMS_HO_TUNE_OFF_RES = 639,
+	MSG_SMS_HO_PEEK_FREQ_REQ = 640,
+	MSG_SMS_HO_PEEK_FREQ_RES = 641,
+	MSG_SMS_HO_PEEK_FREQ_IND = 642,
+	MSG_SMS_MB_ATTEN_SET_REQ = 643,
+	MSG_SMS_MB_ATTEN_SET_RES = 644,
+	MSG_SMS_ENABLE_STAT_IN_I2C_REQ = 649,
+	MSG_SMS_ENABLE_STAT_IN_I2C_RES = 650,
+	MSG_SMS_SET_ANTENNA_CONFIG_REQ = 651,
+	MSG_SMS_SET_ANTENNA_CONFIG_RES = 652,
+	MSG_SMS_GET_STATISTICS_EX_REQ = 653,
+	MSG_SMS_GET_STATISTICS_EX_RES = 654,
+	MSG_SMS_SLEEP_RESUME_COMP_IND = 655,
+	MSG_SMS_SWITCH_HOST_INTERFACE_REQ = 656,
+	MSG_SMS_SWITCH_HOST_INTERFACE_RES = 657,
+	MSG_SMS_DATA_DOWNLOAD_REQ = 660,
+	MSG_SMS_DATA_DOWNLOAD_RES = 661,
+	MSG_SMS_DATA_VALIDITY_REQ = 662,
+	MSG_SMS_DATA_VALIDITY_RES = 663,
+	MSG_SMS_SWDOWNLOAD_TRIGGER_REQ = 664,
+	MSG_SMS_SWDOWNLOAD_TRIGGER_RES = 665,
+	MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ = 666,
+	MSG_SMS_SWDOWNLOAD_BACKDOOR_RES = 667,
+	MSG_SMS_GET_VERSION_EX_REQ = 668,
+	MSG_SMS_GET_VERSION_EX_RES = 669,
+	MSG_SMS_CLOCK_OUTPUT_CONFIG_REQ = 670,
+	MSG_SMS_CLOCK_OUTPUT_CONFIG_RES = 671,
+	MSG_SMS_I2C_SET_FREQ_REQ = 685,
+	MSG_SMS_I2C_SET_FREQ_RES = 686,
+	MSG_SMS_GENERIC_I2C_REQ = 687,
+	MSG_SMS_GENERIC_I2C_RES = 688,
+	MSG_SMS_DVBT_BDA_DATA = 693,
+	MSG_SW_RELOAD_REQ = 697,
+	MSG_SMS_DATA_MSG = 699,
+	MSG_TABLE_UPLOAD_REQ = 700,
+	MSG_TABLE_UPLOAD_RES = 701,
+	MSG_SW_RELOAD_START_REQ = 702,
+	MSG_SW_RELOAD_START_RES = 703,
+	MSG_SW_RELOAD_EXEC_REQ = 704,
+	MSG_SW_RELOAD_EXEC_RES = 705,
+	MSG_SMS_SPI_INT_LINE_SET_REQ = 710,
+	MSG_SMS_SPI_INT_LINE_SET_RES = 711,
+	MSG_SMS_GPIO_CONFIG_EX_REQ = 712,
+	MSG_SMS_GPIO_CONFIG_EX_RES = 713,
+	MSG_SMS_WATCHDOG_ACT_REQ = 716,
+	MSG_SMS_WATCHDOG_ACT_RES = 717,
+	MSG_SMS_LOOPBACK_REQ = 718,
+	MSG_SMS_LOOPBACK_RES = 719,
+	MSG_SMS_RAW_CAPTURE_START_REQ = 720,
+	MSG_SMS_RAW_CAPTURE_START_RES = 721,
+	MSG_SMS_RAW_CAPTURE_ABORT_REQ = 722,
+	MSG_SMS_RAW_CAPTURE_ABORT_RES = 723,
+	MSG_SMS_RAW_CAPTURE_COMPLETE_IND = 728,
+	MSG_SMS_DATA_PUMP_IND = 729,
+	MSG_SMS_DATA_PUMP_REQ = 730,
+	MSG_SMS_DATA_PUMP_RES = 731,
+	MSG_SMS_FLASH_DL_REQ = 732,
+	MSG_SMS_EXEC_TEST_1_REQ = 734,
+	MSG_SMS_EXEC_TEST_1_RES = 735,
+	MSG_SMS_ENBALE_TS_INTERFACE_REQ = 736,
+	MSG_SMS_ENBALE_TS_INTERFACE_RES = 737,
+	MSG_SMS_SPI_SET_BUS_WIDTH_REQ = 738,
+	MSG_SMS_SPI_SET_BUS_WIDTH_RES = 739,
+	MSG_SMS_SEND_EMM_REQ = 740,
+	MSG_SMS_SEND_EMM_RES = 741,
+	MSG_SMS_DISABLE_TS_INTERFACE_REQ = 742,
+	MSG_SMS_DISABLE_TS_INTERFACE_RES = 743,
+	MSG_SMS_IS_BUF_FREE_REQ = 744,
+	MSG_SMS_IS_BUF_FREE_RES = 745,
+	MSG_SMS_EXT_ANTENNA_REQ = 746,
+	MSG_SMS_EXT_ANTENNA_RES = 747,
+	MSG_SMS_CMMB_GET_NET_OF_FREQ_REQ_OBSOLETE = 748,
+	MSG_SMS_CMMB_GET_NET_OF_FREQ_RES_OBSOLETE = 749,
+	MSG_SMS_BATTERY_LEVEL_REQ = 750,
+	MSG_SMS_BATTERY_LEVEL_RES = 751,
+	MSG_SMS_CMMB_INJECT_TABLE_REQ_OBSOLETE = 752,
+	MSG_SMS_CMMB_INJECT_TABLE_RES_OBSOLETE = 753,
+	MSG_SMS_FM_RADIO_BLOCK_IND = 754,
+	MSG_SMS_HOST_NOTIFICATION_IND = 755,
+	MSG_SMS_CMMB_GET_CONTROL_TABLE_REQ_OBSOLETE = 756,
+	MSG_SMS_CMMB_GET_CONTROL_TABLE_RES_OBSOLETE = 757,
+	MSG_SMS_CMMB_GET_NETWORKS_REQ = 760,
+	MSG_SMS_CMMB_GET_NETWORKS_RES = 761,
+	MSG_SMS_CMMB_START_SERVICE_REQ = 762,
+	MSG_SMS_CMMB_START_SERVICE_RES = 763,
+	MSG_SMS_CMMB_STOP_SERVICE_REQ = 764,
+	MSG_SMS_CMMB_STOP_SERVICE_RES = 765,
+	MSG_SMS_CMMB_ADD_CHANNEL_FILTER_REQ = 768,
+	MSG_SMS_CMMB_ADD_CHANNEL_FILTER_RES = 769,
+	MSG_SMS_CMMB_REMOVE_CHANNEL_FILTER_REQ = 770,
+	MSG_SMS_CMMB_REMOVE_CHANNEL_FILTER_RES = 771,
+	MSG_SMS_CMMB_START_CONTROL_INFO_REQ = 772,
+	MSG_SMS_CMMB_START_CONTROL_INFO_RES = 773,
+	MSG_SMS_CMMB_STOP_CONTROL_INFO_REQ = 774,
+	MSG_SMS_CMMB_STOP_CONTROL_INFO_RES = 775,
+	MSG_SMS_ISDBT_TUNE_REQ = 776,
+	MSG_SMS_ISDBT_TUNE_RES = 777,
+	MSG_SMS_TRANSMISSION_IND = 782,
+	MSG_SMS_PID_STATISTICS_IND = 783,
+	MSG_SMS_POWER_DOWN_IND = 784,
+	MSG_SMS_POWER_DOWN_CONF = 785,
+	MSG_SMS_POWER_UP_IND = 786,
+	MSG_SMS_POWER_UP_CONF = 787,
+	MSG_SMS_POWER_MODE_SET_REQ = 790,
+	MSG_SMS_POWER_MODE_SET_RES = 791,
+	MSG_SMS_DEBUG_HOST_EVENT_REQ = 792,
+	MSG_SMS_DEBUG_HOST_EVENT_RES = 793,
+	MSG_SMS_NEW_CRYSTAL_REQ = 794,
+	MSG_SMS_NEW_CRYSTAL_RES = 795,
+	MSG_SMS_CONFIG_SPI_REQ = 796,
+	MSG_SMS_CONFIG_SPI_RES = 797,
+	MSG_SMS_I2C_SHORT_STAT_IND = 798,
+	MSG_SMS_START_IR_REQ = 800,
+	MSG_SMS_START_IR_RES = 801,
+	MSG_SMS_IR_SAMPLES_IND = 802,
+	MSG_SMS_CMMB_CA_SERVICE_IND = 803,
+	MSG_SMS_SLAVE_DEVICE_DETECTED = 804,
+	MSG_SMS_INTERFACE_LOCK_IND = 805,
+	MSG_SMS_INTERFACE_UNLOCK_IND = 806,
+	MSG_SMS_SEND_ROSUM_BUFF_REQ = 810,
+	MSG_SMS_SEND_ROSUM_BUFF_RES = 811,
+	MSG_SMS_ROSUM_BUFF = 812,
+	MSG_SMS_SET_AES128_KEY_REQ = 815,
+	MSG_SMS_SET_AES128_KEY_RES = 816,
+	MSG_SMS_MBBMS_WRITE_REQ = 817,
+	MSG_SMS_MBBMS_WRITE_RES = 818,
+	MSG_SMS_MBBMS_READ_IND = 819,
+	MSG_SMS_IQ_STREAM_START_REQ = 820,
+	MSG_SMS_IQ_STREAM_START_RES = 821,
+	MSG_SMS_IQ_STREAM_STOP_REQ = 822,
+	MSG_SMS_IQ_STREAM_STOP_RES = 823,
+	MSG_SMS_IQ_STREAM_DATA_BLOCK = 824,
+	MSG_SMS_GET_EEPROM_VERSION_REQ = 825,
+	MSG_SMS_GET_EEPROM_VERSION_RES = 826,
+	MSG_SMS_SIGNAL_DETECTED_IND = 827,
+	MSG_SMS_NO_SIGNAL_IND = 828,
+	MSG_SMS_MRC_SHUTDOWN_SLAVE_REQ = 830,
+	MSG_SMS_MRC_SHUTDOWN_SLAVE_RES = 831,
+	MSG_SMS_MRC_BRINGUP_SLAVE_REQ = 832,
+	MSG_SMS_MRC_BRINGUP_SLAVE_RES = 833,
+	MSG_SMS_EXTERNAL_LNA_CTRL_REQ = 834,
+	MSG_SMS_EXTERNAL_LNA_CTRL_RES = 835,
+	MSG_SMS_SET_PERIODIC_STATISTICS_REQ = 836,
+	MSG_SMS_SET_PERIODIC_STATISTICS_RES = 837,
+	MSG_SMS_CMMB_SET_AUTO_OUTPUT_TS0_REQ = 838,
+	MSG_SMS_CMMB_SET_AUTO_OUTPUT_TS0_RES = 839,
+	LOCAL_TUNE = 850,
+	LOCAL_IFFT_H_ICI = 851,
+	MSG_RESYNC_REQ = 852,
+	MSG_SMS_CMMB_GET_MRC_STATISTICS_REQ = 853,
+	MSG_SMS_CMMB_GET_MRC_STATISTICS_RES = 854,
+	MSG_SMS_LOG_EX_ITEM = 855,
+	MSG_SMS_DEVICE_DATA_LOSS_IND = 856,
+	MSG_SMS_MRC_WATCHDOG_TRIGGERED_IND = 857,
+	MSG_SMS_USER_MSG_REQ = 858,
+	MSG_SMS_USER_MSG_RES = 859,
+	MSG_SMS_SMART_CARD_INIT_REQ = 860,
+	MSG_SMS_SMART_CARD_INIT_RES = 861,
+	MSG_SMS_SMART_CARD_WRITE_REQ = 862,
+	MSG_SMS_SMART_CARD_WRITE_RES = 863,
+	MSG_SMS_SMART_CARD_READ_IND = 864,
+	MSG_SMS_TSE_ENABLE_REQ = 866,
+	MSG_SMS_TSE_ENABLE_RES = 867,
+	MSG_SMS_CMMB_GET_SHORT_STATISTICS_REQ = 868,
+	MSG_SMS_CMMB_GET_SHORT_STATISTICS_RES = 869,
+	MSG_SMS_LED_CONFIG_REQ = 870,
+	MSG_SMS_LED_CONFIG_RES = 871,
+	MSG_PWM_ANTENNA_REQ = 872,
+	MSG_PWM_ANTENNA_RES = 873,
+	MSG_SMS_CMMB_SMD_SN_REQ = 874,
+	MSG_SMS_CMMB_SMD_SN_RES = 875,
+	MSG_SMS_CMMB_SET_CA_CW_REQ = 876,
+	MSG_SMS_CMMB_SET_CA_CW_RES = 877,
+	MSG_SMS_CMMB_SET_CA_SALT_REQ = 878,
+	MSG_SMS_CMMB_SET_CA_SALT_RES = 879,
+	MSG_SMS_NSCD_INIT_REQ = 880,
+	MSG_SMS_NSCD_INIT_RES = 881,
+	MSG_SMS_NSCD_PROCESS_SECTION_REQ = 882,
+	MSG_SMS_NSCD_PROCESS_SECTION_RES = 883,
+	MSG_SMS_DBD_CREATE_OBJECT_REQ = 884,
+	MSG_SMS_DBD_CREATE_OBJECT_RES = 885,
+	MSG_SMS_DBD_CONFIGURE_REQ = 886,
+	MSG_SMS_DBD_CONFIGURE_RES = 887,
+	MSG_SMS_DBD_SET_KEYS_REQ = 888,
+	MSG_SMS_DBD_SET_KEYS_RES = 889,
+	MSG_SMS_DBD_PROCESS_HEADER_REQ = 890,
+	MSG_SMS_DBD_PROCESS_HEADER_RES = 891,
+	MSG_SMS_DBD_PROCESS_DATA_REQ = 892,
+	MSG_SMS_DBD_PROCESS_DATA_RES = 893,
+	MSG_SMS_DBD_PROCESS_GET_DATA_REQ = 894,
+	MSG_SMS_DBD_PROCESS_GET_DATA_RES = 895,
+	MSG_SMS_NSCD_OPEN_SESSION_REQ = 896,
+	MSG_SMS_NSCD_OPEN_SESSION_RES = 897,
+	MSG_SMS_SEND_HOST_DATA_TO_DEMUX_REQ = 898,
+	MSG_SMS_SEND_HOST_DATA_TO_DEMUX_RES = 899,
+	MSG_LAST_MSG_TYPE = 900,
+};
 
 #define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \
-	(ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \
-	(ptr)->msgLength = len; (ptr)->msgFlags = 0; \
+	(ptr)->msg_type = type; \
+	(ptr)->msg_src_id = src; \
+	(ptr)->msg_dst_id = dst; \
+	(ptr)->msg_length = len; \
+	(ptr)->msg_flags = 0; \
 } while (0)
 
 #define SMS_INIT_MSG(ptr, type, len) \
@@ -277,228 +604,296 @@ enum SMS_DEVICE_MODE {
 	DEVICE_MODE_ISDBT_BDA,
 	DEVICE_MODE_CMMB,
 	DEVICE_MODE_RAW_TUNER,
+	DEVICE_MODE_FM_RADIO,
+	DEVICE_MODE_FM_RADIO_BDA,
+	DEVICE_MODE_ATSC,
 	DEVICE_MODE_MAX,
 };
 
-struct SmsMsgHdr_ST {
-	u16	msgType;
-	u8	msgSrcId;
-	u8	msgDstId;
-	u16	msgLength; /* Length of entire message, including header */
-	u16	msgFlags;
+struct sms_msg_hdr {
+	u16	msg_type;
+	u8	msg_src_id;
+	u8	msg_dst_id;
+	u16	msg_length; /* length of entire message, including header */
+	u16	msg_flags;
+};
+
+struct sms_msg_data {
+	struct sms_msg_hdr x_msg_header;
+	u32 msg_data[1];
 };
 
-struct SmsMsgData_ST {
-	struct SmsMsgHdr_ST xMsgHeader;
-	u32 msgData[1];
+struct sms_msg_data2 {
+	struct sms_msg_hdr x_msg_header;
+	u32 msg_data[2];
 };
 
-struct SmsMsgData_ST2 {
-	struct SmsMsgHdr_ST xMsgHeader;
-	u32 msgData[2];
+struct sms_msg_data4 {
+	struct sms_msg_hdr x_msg_header;
+	u32 msg_data[4];
 };
 
-struct SmsDataDownload_ST {
-	struct SmsMsgHdr_ST	xMsgHeader;
-	u32			MemAddr;
-	u8			Payload[SMS_MAX_PAYLOAD_SIZE];
+struct sms_data_download {
+	struct sms_msg_hdr	x_msg_header;
+	u32			mem_addr;
+	u8			payload[SMS_MAX_PAYLOAD_SIZE];
 };
 
-struct SmsVersionRes_ST {
-	struct SmsMsgHdr_ST	xMsgHeader;
+struct sms_version_res {
+	struct sms_msg_hdr	x_msg_header;
 
-	u16		ChipModel; /* e.g. 0x1102 for SMS-1102 "Nova" */
-	u8		Step; /* 0 - Step A */
-	u8		MetalFix; /* 0 - Metal 0 */
+	u16		chip_model; /* e.g. 0x1102 for SMS-1102 "Nova" */
+	u8		step; /* 0 - step A */
+	u8		metal_fix; /* 0 - Metal 0 */
 
-	/* FirmwareId 0xFF if ROM, otherwise the
+	/* firmware_id 0xFF if ROM, otherwise the
 	 * value indicated by SMSHOSTLIB_DEVICE_MODES_E */
-	u8 FirmwareId;
-	/* SupportedProtocols Bitwise OR combination of
+	u8 firmware_id;
+	/* supported_protocols Bitwise OR combination of
 					     * supported protocols */
-	u8 SupportedProtocols;
+	u8 supported_protocols;
 
-	u8		VersionMajor;
-	u8		VersionMinor;
-	u8		VersionPatch;
-	u8		VersionFieldPatch;
+	u8		version_major;
+	u8		version_minor;
+	u8		version_patch;
+	u8		version_field_patch;
 
-	u8		RomVersionMajor;
-	u8		RomVersionMinor;
-	u8		RomVersionPatch;
-	u8		RomVersionFieldPatch;
+	u8		rom_ver_major;
+	u8		rom_ver_minor;
+	u8		rom_ver_patch;
+	u8		rom_ver_field_patch;
 
 	u8		TextLabel[34];
 };
 
-struct SmsFirmware_ST {
-	u32			CheckSum;
-	u32			Length;
-	u32			StartAddress;
-	u8			Payload[1];
+struct sms_firmware {
+	u32			check_sum;
+	u32			length;
+	u32			start_address;
+	u8			payload[1];
 };
 
-/* Statistics information returned as response for
- * SmsHostApiGetStatistics_Req */
-struct SMSHOSTLIB_STATISTICS_ST {
-	u32 Reserved;		/* Reserved */
+/* statistics information returned as response for
+ * SmsHostApiGetstatistics_Req */
+struct sms_stats {
+	u32 reserved;		/* reserved */
 
 	/* Common parameters */
-	u32 IsRfLocked;		/* 0 - not locked, 1 - locked */
-	u32 IsDemodLocked;	/* 0 - not locked, 1 - locked */
-	u32 IsExternalLNAOn;	/* 0 - external LNA off, 1 - external LNA on */
+	u32 is_rf_locked;		/* 0 - not locked, 1 - locked */
+	u32 is_demod_locked;	/* 0 - not locked, 1 - locked */
+	u32 is_external_lna_on;	/* 0 - external LNA off, 1 - external LNA on */
 
 	/* Reception quality */
 	s32 SNR;		/* dB */
-	u32 BER;		/* Post Viterbi BER [1E-5] */
+	u32 ber;		/* Post Viterbi ber [1E-5] */
 	u32 FIB_CRC;		/* CRC errors percentage, valid only for DAB */
-	u32 TS_PER;		/* Transport stream PER,
+	u32 ts_per;		/* Transport stream PER,
 	0xFFFFFFFF indicate N/A, valid only for DVB-T/H */
 	u32 MFER;		/* DVB-H frame error rate in percentage,
 	0xFFFFFFFF indicate N/A, valid only for DVB-H */
 	s32 RSSI;		/* dBm */
-	s32 InBandPwr;		/* In band power in dBM */
-	s32 CarrierOffset;	/* Carrier Offset in bin/1024 */
+	s32 in_band_pwr;		/* In band power in dBM */
+	s32 carrier_offset;	/* Carrier Offset in bin/1024 */
 
 	/* Transmission parameters */
-	u32 Frequency;		/* Frequency in Hz */
-	u32 Bandwidth;		/* Bandwidth in MHz, valid only for DVB-T/H */
-	u32 TransmissionMode;	/* Transmission Mode, for DAB modes 1-4,
+	u32 frequency;		/* frequency in Hz */
+	u32 bandwidth;		/* bandwidth in MHz, valid only for DVB-T/H */
+	u32 transmission_mode;	/* Transmission Mode, for DAB modes 1-4,
 	for DVB-T/H FFT mode carriers in Kilos */
-	u32 ModemState;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET,
+	u32 modem_state;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET,
 	valid only for DVB-T/H */
-	u32 GuardInterval;	/* Guard Interval from
-	SMSHOSTLIB_GUARD_INTERVALS_ET, 	valid only for DVB-T/H */
-	u32 CodeRate;		/* Code Rate from SMSHOSTLIB_CODE_RATE_ET,
+	u32 guard_interval;	/* Guard Interval from
+	SMSHOSTLIB_GUARD_INTERVALS_ET,	valid only for DVB-T/H */
+	u32 code_rate;		/* Code Rate from SMSHOSTLIB_CODE_RATE_ET,
 	valid only for DVB-T/H */
-	u32 LPCodeRate;		/* Low Priority Code Rate from
+	u32 lp_code_rate;		/* Low Priority Code Rate from
 	SMSHOSTLIB_CODE_RATE_ET, valid only for DVB-T/H */
-	u32 Hierarchy;		/* Hierarchy from SMSHOSTLIB_HIERARCHY_ET,
+	u32 hierarchy;		/* hierarchy from SMSHOSTLIB_HIERARCHY_ET,
 	valid only for DVB-T/H */
-	u32 Constellation;	/* Constellation from
+	u32 constellation;	/* constellation from
 	SMSHOSTLIB_CONSTELLATION_ET, valid only for DVB-T/H */
 
 	/* Burst parameters, valid only for DVB-H */
-	u32 BurstSize;		/* Current burst size in bytes,
+	u32 burst_size;		/* Current burst size in bytes,
 	valid only for DVB-H */
-	u32 BurstDuration;	/* Current burst duration in mSec,
+	u32 burst_duration;	/* Current burst duration in mSec,
 	valid only for DVB-H */
-	u32 BurstCycleTime;	/* Current burst cycle time in mSec,
+	u32 burst_cycle_time;	/* Current burst cycle time in mSec,
 	valid only for DVB-H */
-	u32 CalculatedBurstCycleTime;/* Current burst cycle time in mSec,
+	u32 calc_burst_cycle_time;/* Current burst cycle time in mSec,
 	as calculated by demodulator, valid only for DVB-H */
-	u32 NumOfRows;		/* Number of rows in MPE table,
+	u32 num_of_rows;		/* Number of rows in MPE table,
 	valid only for DVB-H */
-	u32 NumOfPaddCols;	/* Number of padding columns in MPE table,
+	u32 num_of_padd_cols;	/* Number of padding columns in MPE table,
 	valid only for DVB-H */
-	u32 NumOfPunctCols;	/* Number of puncturing columns in MPE table,
+	u32 num_of_punct_cols;	/* Number of puncturing columns in MPE table,
 	valid only for DVB-H */
-	u32 ErrorTSPackets;	/* Number of erroneous
+	u32 error_ts_packets;	/* Number of erroneous
 	transport-stream packets */
-	u32 TotalTSPackets;	/* Total number of transport-stream packets */
-	u32 NumOfValidMpeTlbs;	/* Number of MPE tables which do not include
+	u32 total_ts_packets;	/* Total number of transport-stream packets */
+	u32 num_of_valid_mpe_tlbs;	/* Number of MPE tables which do not include
 	errors after MPE RS decoding */
-	u32 NumOfInvalidMpeTlbs;/* Number of MPE tables which include errors
+	u32 num_of_invalid_mpe_tlbs;/* Number of MPE tables which include errors
 	after MPE RS decoding */
-	u32 NumOfCorrectedMpeTlbs;/* Number of MPE tables which were
+	u32 num_of_corrected_mpe_tlbs;/* Number of MPE tables which were
 	corrected by MPE RS decoding */
 	/* Common params */
-	u32 BERErrorCount;	/* Number of errornous SYNC bits. */
-	u32 BERBitCount;	/* Total number of SYNC bits. */
+	u32 ber_error_count;	/* Number of errornous SYNC bits. */
+	u32 ber_bit_count;	/* Total number of SYNC bits. */
 
 	/* Interface information */
-	u32 SmsToHostTxErrors;	/* Total number of transmission errors. */
+	u32 sms_to_host_tx_errors;	/* Total number of transmission errors. */
 
 	/* DAB/T-DMB */
-	u32 PreBER; 		/* DAB/T-DMB only: Pre Viterbi BER [1E-5] */
+	u32 pre_ber;		/* DAB/T-DMB only: Pre Viterbi ber [1E-5] */
 
 	/* DVB-H TPS parameters */
-	u32 CellId;		/* TPS Cell ID in bits 15..0, bits 31..16 zero;
+	u32 cell_id;		/* TPS Cell ID in bits 15..0, bits 31..16 zero;
 	 if set to 0xFFFFFFFF cell_id not yet recovered */
-	u32 DvbhSrvIndHP;	/* DVB-H service indication info, bit 1 -
+	u32 dvbh_srv_ind_hp;	/* DVB-H service indication info, bit 1 -
 	Time Slicing indicator, bit 0 - MPE-FEC indicator */
-	u32 DvbhSrvIndLP;	/* DVB-H service indication info, bit 1 -
+	u32 dvbh_srv_ind_lp;	/* DVB-H service indication info, bit 1 -
 	Time Slicing indicator, bit 0 - MPE-FEC indicator */
 
-	u32 NumMPEReceived;	/* DVB-H, Num MPE section received */
+	u32 num_mpe_received;	/* DVB-H, Num MPE section received */
 
-	u32 ReservedFields[10];	/* Reserved */
+	u32 reservedFields[10];	/* reserved */
 };
 
-struct SmsMsgStatisticsInfo_ST {
-	u32 RequestResult;
+struct sms_msg_statistics_info {
+	u32 request_result;
 
-	struct SMSHOSTLIB_STATISTICS_ST Stat;
+	struct sms_stats stat;
 
 	/* Split the calc of the SNR in DAB */
-	u32 Signal; /* dB */
-	u32 Noise; /* dB */
+	u32 signal; /* dB */
+	u32 noise; /* dB */
 
 };
 
-struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST {
+struct sms_isdbt_layer_stats {
 	/* Per-layer information */
-	u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET,
+	u32 code_rate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET,
 		       * 255 means layer does not exist */
-	u32 Constellation; /* Constellation from SMSHOSTLIB_CONSTELLATION_ET,
+	u32 constellation; /* constellation from SMSHOSTLIB_CONSTELLATION_ET,
 			    * 255 means layer does not exist */
-	u32 BER; /* Post Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */
-	u32 BERErrorCount; /* Post Viterbi Error Bits Count */
-	u32 BERBitCount; /* Post Viterbi Total Bits Count */
-	u32 PreBER; /* Pre Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */
-	u32 TS_PER; /* Transport stream PER [%], 0xFFFFFFFF indicate N/A */
-	u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */
-	u32 TotalTSPackets; /* Total number of transport-stream packets */
-	u32 TILdepthI; /* Time interleaver depth I parameter,
+	u32 ber; /* Post Viterbi ber [1E-5], 0xFFFFFFFF indicate N/A */
+	u32 ber_error_count; /* Post Viterbi Error Bits Count */
+	u32 ber_bit_count; /* Post Viterbi Total Bits Count */
+	u32 pre_ber; /* Pre Viterbi ber [1E-5], 0xFFFFFFFF indicate N/A */
+	u32 ts_per; /* Transport stream PER [%], 0xFFFFFFFF indicate N/A */
+	u32 error_ts_packets; /* Number of erroneous transport-stream packets */
+	u32 total_ts_packets; /* Total number of transport-stream packets */
+	u32 ti_ldepth_i; /* Time interleaver depth I parameter,
 			* 255 means layer does not exist */
-	u32 NumberOfSegments; /* Number of segments in layer A,
+	u32 number_of_segments; /* Number of segments in layer A,
 			       * 255 means layer does not exist */
-	u32 TMCCErrors; /* TMCC errors */
+	u32 tmcc_errors; /* TMCC errors */
 };
 
-struct SMSHOSTLIB_STATISTICS_ISDBT_ST {
-	u32 StatisticsType; /* Enumerator identifying the type of the
+struct sms_isdbt_stats {
+	u32 statistics_type; /* Enumerator identifying the type of the
 				* structure.  Values are the same as
 				* SMSHOSTLIB_DEVICE_MODES_E
 				*
 				* This field MUST always be first in any
 				* statistics structure */
 
-	u32 FullSize; /* Total size of the structure returned by the modem.
+	u32 full_size; /* Total size of the structure returned by the modem.
 		       * If the size requested by the host is smaller than
-		       * FullSize, the struct will be truncated */
+		       * full_size, the struct will be truncated */
 
 	/* Common parameters */
-	u32 IsRfLocked; /* 0 - not locked, 1 - locked */
-	u32 IsDemodLocked; /* 0 - not locked, 1 - locked */
-	u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */
+	u32 is_rf_locked; /* 0 - not locked, 1 - locked */
+	u32 is_demod_locked; /* 0 - not locked, 1 - locked */
+	u32 is_external_lna_on; /* 0 - external LNA off, 1 - external LNA on */
 
 	/* Reception quality */
 	s32  SNR; /* dB */
 	s32  RSSI; /* dBm */
-	s32  InBandPwr; /* In band power in dBM */
-	s32  CarrierOffset; /* Carrier Offset in Hz */
+	s32  in_band_pwr; /* In band power in dBM */
+	s32  carrier_offset; /* Carrier Offset in Hz */
 
 	/* Transmission parameters */
-	u32 Frequency; /* Frequency in Hz */
-	u32 Bandwidth; /* Bandwidth in MHz */
-	u32 TransmissionMode; /* ISDB-T transmission mode */
-	u32 ModemState; /* 0 - Acquisition, 1 - Locked */
-	u32 GuardInterval; /* Guard Interval, 1 divided by value */
-	u32 SystemType; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */
-	u32 PartialReception; /* TRUE - partial reception, FALSE otherwise */
-	u32 NumOfLayers; /* Number of ISDB-T layers in the network */
+	u32 frequency; /* frequency in Hz */
+	u32 bandwidth; /* bandwidth in MHz */
+	u32 transmission_mode; /* ISDB-T transmission mode */
+	u32 modem_state; /* 0 - Acquisition, 1 - Locked */
+	u32 guard_interval; /* Guard Interval, 1 divided by value */
+	u32 system_type; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */
+	u32 partial_reception; /* TRUE - partial reception, FALSE otherwise */
+	u32 num_of_layers; /* Number of ISDB-T layers in the network */
 
 	/* Per-layer information */
 	/* Layers A, B and C */
-	struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST	LayerInfo[3];
-	/* Per-layer statistics, see SMSHOSTLIB_ISDBT_LAYER_STAT_ST */
+	struct sms_isdbt_layer_stats	layer_info[3];
+	/* Per-layer statistics, see sms_isdbt_layer_stats */
 
 	/* Interface information */
-	u32 SmsToHostTxErrors; /* Total number of transmission errors. */
+	u32 sms_to_host_tx_errors; /* Total number of transmission errors. */
 };
 
-struct PID_STATISTICS_DATA_S {
+struct sms_isdbt_stats_ex {
+	u32 statistics_type; /* Enumerator identifying the type of the
+				* structure.  Values are the same as
+				* SMSHOSTLIB_DEVICE_MODES_E
+				*
+				* This field MUST always be first in any
+				* statistics structure */
+
+	u32 full_size; /* Total size of the structure returned by the modem.
+		       * If the size requested by the host is smaller than
+		       * full_size, the struct will be truncated */
+
+	/* Common parameters */
+	u32 is_rf_locked; /* 0 - not locked, 1 - locked */
+	u32 is_demod_locked; /* 0 - not locked, 1 - locked */
+	u32 is_external_lna_on; /* 0 - external LNA off, 1 - external LNA on */
+
+	/* Reception quality */
+	s32  SNR; /* dB */
+	s32  RSSI; /* dBm */
+	s32  in_band_pwr; /* In band power in dBM */
+	s32  carrier_offset; /* Carrier Offset in Hz */
+
+	/* Transmission parameters */
+	u32 frequency; /* frequency in Hz */
+	u32 bandwidth; /* bandwidth in MHz */
+	u32 transmission_mode; /* ISDB-T transmission mode */
+	u32 modem_state; /* 0 - Acquisition, 1 - Locked */
+	u32 guard_interval; /* Guard Interval, 1 divided by value */
+	u32 system_type; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */
+	u32 partial_reception; /* TRUE - partial reception, FALSE otherwise */
+	u32 num_of_layers; /* Number of ISDB-T layers in the network */
+
+	u32 segment_number; /* Segment number for ISDB-Tsb */
+	u32 tune_bw;	   /* Tuned bandwidth - BW_ISDBT_1SEG / BW_ISDBT_3SEG */
+
+	/* Per-layer information */
+	/* Layers A, B and C */
+	struct sms_isdbt_layer_stats	layer_info[3];
+	/* Per-layer statistics, see sms_isdbt_layer_stats */
+
+	/* Interface information */
+	u32 reserved1;    /* Was sms_to_host_tx_errors - obsolete . */
+ /* Proprietary information */
+	u32 ext_antenna;    /* Obsolete field. */
+	u32 reception_quality;
+	u32 ews_alert_active;   /* signals if EWS alert is currently on */
+	u32 lna_on_off;	/* Internal LNA state: 0: OFF, 1: ON */
+
+	u32 rf_agc_level;	 /* RF AGC Level [linear units], full gain = 65535 (20dB) */
+	u32 bb_agc_level;    /* Baseband AGC level [linear units], full gain = 65535 (71.5dB) */
+	u32 fw_errors_counter;   /* Application errors - should be always zero */
+	u8 FwErrorsHistoryArr[8]; /* Last FW errors IDs - first is most recent, last is oldest */
+
+	s32  MRC_SNR;     /* dB */
+	u32 snr_full_res;    /* dB x 65536 */
+	u32 reserved4[4];
+};
+
+
+struct sms_pid_stats_data {
 	struct PID_BURST_S {
 		u32 size;
 		u32 padding_cols;
@@ -513,112 +908,155 @@ struct PID_STATISTICS_DATA_S {
 	u32 tot_cor_tbl;
 };
 
-struct PID_DATA_S {
+struct sms_pid_data {
 	u32 pid;
 	u32 num_rows;
-	struct PID_STATISTICS_DATA_S pid_statistics;
+	struct sms_pid_stats_data pid_statistics;
 };
 
 #define CORRECT_STAT_RSSI(_stat) ((_stat).RSSI *= -1)
-#define CORRECT_STAT_BANDWIDTH(_stat) (_stat.Bandwidth = 8 - _stat.Bandwidth)
+#define CORRECT_STAT_BANDWIDTH(_stat) (_stat.bandwidth = 8 - _stat.bandwidth)
 #define CORRECT_STAT_TRANSMISSON_MODE(_stat) \
-	if (_stat.TransmissionMode == 0) \
-		_stat.TransmissionMode = 2; \
-	else if (_stat.TransmissionMode == 1) \
-		_stat.TransmissionMode = 8; \
+	if (_stat.transmission_mode == 0) \
+		_stat.transmission_mode = 2; \
+	else if (_stat.transmission_mode == 1) \
+		_stat.transmission_mode = 8; \
 		else \
-			_stat.TransmissionMode = 4;
+			_stat.transmission_mode = 4;
 
-struct TRANSMISSION_STATISTICS_S {
-	u32 Frequency;		/* Frequency in Hz */
-	u32 Bandwidth;		/* Bandwidth in MHz */
-	u32 TransmissionMode;	/* FFT mode carriers in Kilos */
-	u32 GuardInterval;	/* Guard Interval from
+struct sms_tx_stats {
+	u32 frequency;		/* frequency in Hz */
+	u32 bandwidth;		/* bandwidth in MHz */
+	u32 transmission_mode;	/* FFT mode carriers in Kilos */
+	u32 guard_interval;	/* Guard Interval from
 	SMSHOSTLIB_GUARD_INTERVALS_ET */
-	u32 CodeRate;		/* Code Rate from SMSHOSTLIB_CODE_RATE_ET */
-	u32 LPCodeRate;		/* Low Priority Code Rate from
+	u32 code_rate;		/* Code Rate from SMSHOSTLIB_CODE_RATE_ET */
+	u32 lp_code_rate;		/* Low Priority Code Rate from
 	SMSHOSTLIB_CODE_RATE_ET */
-	u32 Hierarchy;		/* Hierarchy from SMSHOSTLIB_HIERARCHY_ET */
-	u32 Constellation;	/* Constellation from
+	u32 hierarchy;		/* hierarchy from SMSHOSTLIB_HIERARCHY_ET */
+	u32 constellation;	/* constellation from
 	SMSHOSTLIB_CONSTELLATION_ET */
 
 	/* DVB-H TPS parameters */
-	u32 CellId;		/* TPS Cell ID in bits 15..0, bits 31..16 zero;
+	u32 cell_id;		/* TPS Cell ID in bits 15..0, bits 31..16 zero;
 	 if set to 0xFFFFFFFF cell_id not yet recovered */
-	u32 DvbhSrvIndHP;	/* DVB-H service indication info, bit 1 -
+	u32 dvbh_srv_ind_hp;	/* DVB-H service indication info, bit 1 -
 	 Time Slicing indicator, bit 0 - MPE-FEC indicator */
-	u32 DvbhSrvIndLP;	/* DVB-H service indication info, bit 1 -
+	u32 dvbh_srv_ind_lp;	/* DVB-H service indication info, bit 1 -
 	 Time Slicing indicator, bit 0 - MPE-FEC indicator */
-	u32 IsDemodLocked;	/* 0 - not locked, 1 - locked */
+	u32 is_demod_locked;	/* 0 - not locked, 1 - locked */
+};
+
+struct sms_rx_stats {
+	u32 is_rf_locked;		/* 0 - not locked, 1 - locked */
+	u32 is_demod_locked;	/* 0 - not locked, 1 - locked */
+	u32 is_external_lna_on;	/* 0 - external LNA off, 1 - external LNA on */
+
+	u32 modem_state;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
+	s32 SNR;		/* dB */
+	u32 ber;		/* Post Viterbi ber [1E-5] */
+	u32 ber_error_count;	/* Number of erronous SYNC bits. */
+	u32 ber_bit_count;	/* Total number of SYNC bits. */
+	u32 ts_per;		/* Transport stream PER,
+	0xFFFFFFFF indicate N/A */
+	u32 MFER;		/* DVB-H frame error rate in percentage,
+	0xFFFFFFFF indicate N/A, valid only for DVB-H */
+	s32 RSSI;		/* dBm */
+	s32 in_band_pwr;		/* In band power in dBM */
+	s32 carrier_offset;	/* Carrier Offset in bin/1024 */
+	u32 error_ts_packets;	/* Number of erroneous
+	transport-stream packets */
+	u32 total_ts_packets;	/* Total number of transport-stream packets */
+
+	s32 MRC_SNR;		/* dB */
+	s32 MRC_RSSI;		/* dBm */
+	s32 mrc_in_band_pwr;	/* In band power in dBM */
 };
 
-struct RECEPTION_STATISTICS_S {
-	u32 IsRfLocked;		/* 0 - not locked, 1 - locked */
-	u32 IsDemodLocked;	/* 0 - not locked, 1 - locked */
-	u32 IsExternalLNAOn;	/* 0 - external LNA off, 1 - external LNA on */
+struct sms_rx_stats_ex {
+	u32 is_rf_locked;		/* 0 - not locked, 1 - locked */
+	u32 is_demod_locked;	/* 0 - not locked, 1 - locked */
+	u32 is_external_lna_on;	/* 0 - external LNA off, 1 - external LNA on */
 
-	u32 ModemState;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
+	u32 modem_state;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
 	s32 SNR;		/* dB */
-	u32 BER;		/* Post Viterbi BER [1E-5] */
-	u32 BERErrorCount;	/* Number of erronous SYNC bits. */
-	u32 BERBitCount;	/* Total number of SYNC bits. */
-	u32 TS_PER;		/* Transport stream PER,
+	u32 ber;		/* Post Viterbi ber [1E-5] */
+	u32 ber_error_count;	/* Number of erronous SYNC bits. */
+	u32 ber_bit_count;	/* Total number of SYNC bits. */
+	u32 ts_per;		/* Transport stream PER,
 	0xFFFFFFFF indicate N/A */
 	u32 MFER;		/* DVB-H frame error rate in percentage,
 	0xFFFFFFFF indicate N/A, valid only for DVB-H */
 	s32 RSSI;		/* dBm */
-	s32 InBandPwr;		/* In band power in dBM */
-	s32 CarrierOffset;	/* Carrier Offset in bin/1024 */
-	u32 ErrorTSPackets;	/* Number of erroneous
+	s32 in_band_pwr;		/* In band power in dBM */
+	s32 carrier_offset;	/* Carrier Offset in bin/1024 */
+	u32 error_ts_packets;	/* Number of erroneous
 	transport-stream packets */
-	u32 TotalTSPackets;	/* Total number of transport-stream packets */
+	u32 total_ts_packets;	/* Total number of transport-stream packets */
+
+	s32  ref_dev_ppm;
+	s32  freq_dev_hz;
 
 	s32 MRC_SNR;		/* dB */
 	s32 MRC_RSSI;		/* dBm */
-	s32 MRC_InBandPwr;	/* In band power in dBM */
+	s32 mrc_in_band_pwr;	/* In band power in dBM */
 };
 
 
-/* Statistics information returned as response for
- * SmsHostApiGetStatisticsEx_Req for DVB applications, SMS1100 and up */
-struct SMSHOSTLIB_STATISTICS_DVB_S {
+/* statistics information returned as response for
+ * SmsHostApiGetstatisticsEx_Req for DVB applications, SMS1100 and up */
+struct sms_stats_dvb {
 	/* Reception */
-	struct RECEPTION_STATISTICS_S ReceptionData;
+	struct sms_rx_stats reception_data;
 
 	/* Transmission parameters */
-	struct TRANSMISSION_STATISTICS_S TransmissionData;
+	struct sms_tx_stats transmission_data;
 
 	/* Burst parameters, valid only for DVB-H */
 #define	SRVM_MAX_PID_FILTERS 8
-	struct PID_DATA_S PidData[SRVM_MAX_PID_FILTERS];
+	struct sms_pid_data pid_data[SRVM_MAX_PID_FILTERS];
 };
 
-struct SRVM_SIGNAL_STATUS_S {
+/* statistics information returned as response for
+ * SmsHostApiGetstatisticsEx_Req for DVB applications, SMS1100 and up */
+struct sms_stats_dvb_ex {
+	/* Reception */
+	struct sms_rx_stats_ex reception_data;
+
+	/* Transmission parameters */
+	struct sms_tx_stats transmission_data;
+
+	/* Burst parameters, valid only for DVB-H */
+#define	SRVM_MAX_PID_FILTERS 8
+	struct sms_pid_data pid_data[SRVM_MAX_PID_FILTERS];
+};
+
+struct sms_srvm_signal_status {
 	u32 result;
 	u32 snr;
-	u32 tsPackets;
-	u32 etsPackets;
+	u32 ts_packets;
+	u32 ets_packets;
 	u32 constellation;
-	u32 hpCode;
-	u32 tpsSrvIndLP;
-	u32 tpsSrvIndHP;
-	u32 cellId;
+	u32 hp_code;
+	u32 tps_srv_ind_lp;
+	u32 tps_srv_ind_hp;
+	u32 cell_id;
 	u32 reason;
 
-	s32 inBandPower;
-	u32 requestId;
+	s32 in_band_power;
+	u32 request_id;
 };
 
-struct SMSHOSTLIB_I2C_REQ_ST {
-	u32	DeviceAddress; /* I2c device address */
-	u32	WriteCount; /* number of bytes to write */
-	u32	ReadCount; /* number of bytes to read */
+struct sms_i2c_req {
+	u32	device_address; /* I2c device address */
+	u32	write_count; /* number of bytes to write */
+	u32	read_count; /* number of bytes to read */
 	u8	Data[1];
 };
 
-struct SMSHOSTLIB_I2C_RES_ST {
-	u32	Status; /* non-zero value in case of failure */
-	u32	ReadCount; /* number of bytes read */
+struct sms_i2c_res {
+	u32	status; /* non-zero value in case of failure */
+	u32	read_count; /* number of bytes read */
 	u8	Data[1];
 };
 
@@ -638,59 +1076,39 @@ struct smscore_config_gpio {
 #define SMS_GPIO_INPUTCHARACTERISTICS_SCHMITT 1
 	u8 inputcharacteristics;
 
-#define SMS_GPIO_OUTPUTSLEWRATE_FAST 0
-#define SMS_GPIO_OUTPUTSLEWRATE_SLOW 1
-	u8 outputslewrate;
-
-#define SMS_GPIO_OUTPUTDRIVING_4mA  0
-#define SMS_GPIO_OUTPUTDRIVING_8mA  1
-#define SMS_GPIO_OUTPUTDRIVING_12mA 2
-#define SMS_GPIO_OUTPUTDRIVING_16mA 3
-	u8 outputdriving;
-};
-
-struct smscore_gpio_config {
-#define SMS_GPIO_DIRECTION_INPUT  0
-#define SMS_GPIO_DIRECTION_OUTPUT 1
-	u8 Direction;
-
-#define SMS_GPIO_PULL_UP_DOWN_NONE     0
-#define SMS_GPIO_PULL_UP_DOWN_PULLDOWN 1
-#define SMS_GPIO_PULL_UP_DOWN_PULLUP   2
-#define SMS_GPIO_PULL_UP_DOWN_KEEPER   3
-	u8 PullUpDown;
-
-#define SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL  0
-#define SMS_GPIO_INPUT_CHARACTERISTICS_SCHMITT 1
-	u8 InputCharacteristics;
-
-#define SMS_GPIO_OUTPUT_SLEW_RATE_SLOW		1 /* 10xx */
-#define SMS_GPIO_OUTPUT_SLEW_RATE_FAST		0 /* 10xx */
+	/* 10xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_FAST 0
+#define SMS_GPIO_OUTPUT_SLEW_WRATE_SLOW 1
 
+	/* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS	0
+#define SMS_GPIO_OUTPUT_SLEW_RATE_0_9_V_NS	1
+#define SMS_GPIO_OUTPUT_SLEW_RATE_1_7_V_NS	2
+#define SMS_GPIO_OUTPUT_SLEW_RATE_3_3_V_NS	3
 
-#define SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS	0 /* 11xx */
-#define SMS_GPIO_OUTPUT_SLEW_RATE_0_9_V_NS	1 /* 11xx */
-#define SMS_GPIO_OUTPUT_SLEW_RATE_1_7_V_NS	2 /* 11xx */
-#define SMS_GPIO_OUTPUT_SLEW_RATE_3_3_V_NS	3 /* 11xx */
-	u8 OutputSlewRate;
+	u8 outputslewrate;
 
-#define SMS_GPIO_OUTPUT_DRIVING_S_4mA		0 /* 10xx */
-#define SMS_GPIO_OUTPUT_DRIVING_S_8mA		1 /* 10xx */
-#define SMS_GPIO_OUTPUT_DRIVING_S_12mA		2 /* 10xx */
-#define SMS_GPIO_OUTPUT_DRIVING_S_16mA		3 /* 10xx */
+	/* 10xx */
+#define SMS_GPIO_OUTPUTDRIVING_S_4mA  0
+#define SMS_GPIO_OUTPUTDRIVING_S_8mA  1
+#define SMS_GPIO_OUTPUTDRIVING_S_12mA 2
+#define SMS_GPIO_OUTPUTDRIVING_S_16mA 3
+
+	/* 11xx*/
+#define SMS_GPIO_OUTPUTDRIVING_1_5mA	0
+#define SMS_GPIO_OUTPUTDRIVING_2_8mA	1
+#define SMS_GPIO_OUTPUTDRIVING_4mA	2
+#define SMS_GPIO_OUTPUTDRIVING_7mA	3
+#define SMS_GPIO_OUTPUTDRIVING_10mA	4
+#define SMS_GPIO_OUTPUTDRIVING_11mA	5
+#define SMS_GPIO_OUTPUTDRIVING_14mA	6
+#define SMS_GPIO_OUTPUTDRIVING_16mA	7
 
-#define SMS_GPIO_OUTPUT_DRIVING_1_5mA		0 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_2_8mA		1 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_4mA		2 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_7mA		3 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_10mA		4 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_11mA		5 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_14mA		6 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_16mA		7 /* 11xx */
-	u8 OutputDriving;
+	u8 outputdriving;
 };
 
-extern void smscore_registry_setmode(char *devpath, int mode);
+char *smscore_translate_msg(enum msg_types msgtype);
+
 extern int smscore_registry_getmode(char *devpath);
 
 extern int smscore_register_hotplug(hotplug_t hotplug);
@@ -721,8 +1139,6 @@ extern void smscore_onresponse(struct smscore_device_t *coredev,
 extern int smscore_get_common_buffer_size(struct smscore_device_t *coredev);
 extern int smscore_map_common_buffer(struct smscore_device_t *coredev,
 				      struct vm_area_struct *vma);
-extern int smscore_get_fw_filename(struct smscore_device_t *coredev,
-				   int mode, char *filename);
 extern int smscore_send_fw_file(struct smscore_device_t *coredev,
 				u8 *ufwbuf, int size);
 
@@ -737,11 +1153,11 @@ int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
 int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level);
 
 /* new GPIO management */
-extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
-		struct smscore_gpio_config *pGpioConfig);
-extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
-		u8 NewLevel);
-extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
+extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 pin_num,
+		struct smscore_config_gpio *p_gpio_config);
+extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 pin_num,
+		u8 new_level);
+extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 pin_num,
 		u8 *level);
 
 void smscore_set_board_id(struct smscore_device_t *core, int id);
@@ -760,7 +1176,8 @@ int smscore_led_state(struct smscore_device_t *core, int led);
 
 #define dprintk(kern, lvl, fmt, arg...) do {\
 	if (sms_dbg & lvl) \
-		sms_printk(kern, fmt, ##arg); } while (0)
+		sms_printk(kern, fmt, ##arg); \
+} while (0)
 
 #define sms_log(fmt, arg...) sms_printk(KERN_INFO, fmt, ##arg)
 #define sms_err(fmt, arg...) \

+ 551 - 0
drivers/media/common/siano/smsdvb-debugfs.c

@@ -0,0 +1,551 @@
+/***********************************************************************
+ *
+ * Copyright(c) 2013 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+
+ *  This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ***********************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/debugfs.h>
+#include <linux/spinlock.h>
+#include <linux/usb.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+
+#include "smscoreapi.h"
+
+#include "smsdvb.h"
+
+static struct dentry *smsdvb_debugfs_usb_root;
+
+struct smsdvb_debugfs {
+	struct kref		refcount;
+	spinlock_t		lock;
+
+	char			stats_data[PAGE_SIZE];
+	unsigned		stats_count;
+	bool			stats_was_read;
+
+	wait_queue_head_t	stats_queue;
+};
+
+static void smsdvb_print_dvb_stats(struct smsdvb_debugfs *debug_data,
+			    struct sms_stats *p)
+{
+	int n = 0;
+	char *buf;
+
+	spin_lock(&debug_data->lock);
+	if (debug_data->stats_count) {
+		spin_unlock(&debug_data->lock);
+		return;
+	}
+
+	buf = debug_data->stats_data;
+
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_rf_locked = %d\n", p->is_rf_locked);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_demod_locked = %d\n", p->is_demod_locked);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_external_lna_on = %d\n", p->is_external_lna_on);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "SNR = %d\n", p->SNR);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "ber = %d\n", p->ber);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "FIB_CRC = %d\n", p->FIB_CRC);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "ts_per = %d\n", p->ts_per);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "MFER = %d\n", p->MFER);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "RSSI = %d\n", p->RSSI);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "in_band_pwr = %d\n", p->in_band_pwr);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "carrier_offset = %d\n", p->carrier_offset);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "modem_state = %d\n", p->modem_state);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "frequency = %d\n", p->frequency);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "bandwidth = %d\n", p->bandwidth);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "transmission_mode = %d\n", p->transmission_mode);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "modem_state = %d\n", p->modem_state);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "guard_interval = %d\n", p->guard_interval);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "code_rate = %d\n", p->code_rate);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "lp_code_rate = %d\n", p->lp_code_rate);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "hierarchy = %d\n", p->hierarchy);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "constellation = %d\n", p->constellation);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "burst_size = %d\n", p->burst_size);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "burst_duration = %d\n", p->burst_duration);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "burst_cycle_time = %d\n", p->burst_cycle_time);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "calc_burst_cycle_time = %d\n",
+		      p->calc_burst_cycle_time);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_of_rows = %d\n", p->num_of_rows);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_of_padd_cols = %d\n", p->num_of_padd_cols);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_of_punct_cols = %d\n", p->num_of_punct_cols);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "error_ts_packets = %d\n", p->error_ts_packets);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "total_ts_packets = %d\n", p->total_ts_packets);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_of_valid_mpe_tlbs = %d\n", p->num_of_valid_mpe_tlbs);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_of_invalid_mpe_tlbs = %d\n", p->num_of_invalid_mpe_tlbs);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_of_corrected_mpe_tlbs = %d\n", p->num_of_corrected_mpe_tlbs);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "ber_error_count = %d\n", p->ber_error_count);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "ber_bit_count = %d\n", p->ber_bit_count);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "sms_to_host_tx_errors = %d\n", p->sms_to_host_tx_errors);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "pre_ber = %d\n", p->pre_ber);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "cell_id = %d\n", p->cell_id);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "dvbh_srv_ind_hp = %d\n", p->dvbh_srv_ind_hp);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "dvbh_srv_ind_lp = %d\n", p->dvbh_srv_ind_lp);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_mpe_received = %d\n", p->num_mpe_received);
+
+	debug_data->stats_count = n;
+	spin_unlock(&debug_data->lock);
+	wake_up(&debug_data->stats_queue);
+}
+
+static void smsdvb_print_isdb_stats(struct smsdvb_debugfs *debug_data,
+			     struct sms_isdbt_stats *p)
+{
+	int i, n = 0;
+	char *buf;
+
+	spin_lock(&debug_data->lock);
+	if (debug_data->stats_count) {
+		spin_unlock(&debug_data->lock);
+		return;
+	}
+
+	buf = debug_data->stats_data;
+
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "statistics_type = %d\t", p->statistics_type);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "full_size = %d\n", p->full_size);
+
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_rf_locked = %d\t\t", p->is_rf_locked);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_demod_locked = %d\t", p->is_demod_locked);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_external_lna_on = %d\n", p->is_external_lna_on);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "SNR = %d dB\t\t", p->SNR);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "RSSI = %d dBm\t\t", p->RSSI);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "in_band_pwr = %d dBm\n", p->in_band_pwr);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "carrier_offset = %d\t", p->carrier_offset);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "bandwidth = %d\t\t", p->bandwidth);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "frequency = %d Hz\n", p->frequency);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "transmission_mode = %d\t", p->transmission_mode);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "modem_state = %d\t\t", p->modem_state);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "guard_interval = %d\n", p->guard_interval);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "system_type = %d\t\t", p->system_type);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "partial_reception = %d\t", p->partial_reception);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_of_layers = %d\n", p->num_of_layers);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "sms_to_host_tx_errors = %d\n", p->sms_to_host_tx_errors);
+
+	for (i = 0; i < 3; i++) {
+		if (p->layer_info[i].number_of_segments < 1 ||
+		    p->layer_info[i].number_of_segments > 13)
+			continue;
+
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\nLayer %d\n", i);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tcode_rate = %d\t",
+			      p->layer_info[i].code_rate);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "constellation = %d\n",
+			      p->layer_info[i].constellation);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tber = %-5d\t",
+			      p->layer_info[i].ber);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tber_error_count = %-5d\t",
+			      p->layer_info[i].ber_error_count);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "ber_bit_count = %-5d\n",
+			      p->layer_info[i].ber_bit_count);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tpre_ber = %-5d\t",
+			      p->layer_info[i].pre_ber);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tts_per = %-5d\n",
+			      p->layer_info[i].ts_per);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\terror_ts_packets = %-5d\t",
+			      p->layer_info[i].error_ts_packets);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "total_ts_packets = %-5d\t",
+			      p->layer_info[i].total_ts_packets);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "ti_ldepth_i = %d\n",
+			      p->layer_info[i].ti_ldepth_i);
+		n += snprintf(&buf[n], PAGE_SIZE - n,
+			      "\tnumber_of_segments = %d\t",
+			      p->layer_info[i].number_of_segments);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "tmcc_errors = %d\n",
+			      p->layer_info[i].tmcc_errors);
+	}
+
+	debug_data->stats_count = n;
+	spin_unlock(&debug_data->lock);
+	wake_up(&debug_data->stats_queue);
+}
+
+static void smsdvb_print_isdb_stats_ex(struct smsdvb_debugfs *debug_data,
+				struct sms_isdbt_stats_ex *p)
+{
+	int i, n = 0;
+	char *buf;
+
+	spin_lock(&debug_data->lock);
+	if (debug_data->stats_count) {
+		spin_unlock(&debug_data->lock);
+		return;
+	}
+
+	buf = debug_data->stats_data;
+
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "statistics_type = %d\t", p->statistics_type);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "full_size = %d\n", p->full_size);
+
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_rf_locked = %d\t\t", p->is_rf_locked);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_demod_locked = %d\t", p->is_demod_locked);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "is_external_lna_on = %d\n", p->is_external_lna_on);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "SNR = %d dB\t\t", p->SNR);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "RSSI = %d dBm\t\t", p->RSSI);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "in_band_pwr = %d dBm\n", p->in_band_pwr);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "carrier_offset = %d\t", p->carrier_offset);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "bandwidth = %d\t\t", p->bandwidth);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "frequency = %d Hz\n", p->frequency);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "transmission_mode = %d\t", p->transmission_mode);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "modem_state = %d\t\t", p->modem_state);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "guard_interval = %d\n", p->guard_interval);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "system_type = %d\t\t", p->system_type);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "partial_reception = %d\t", p->partial_reception);
+	n += snprintf(&buf[n], PAGE_SIZE - n,
+		      "num_of_layers = %d\n", p->num_of_layers);
+	n += snprintf(&buf[n], PAGE_SIZE - n, "segment_number = %d\t",
+		      p->segment_number);
+	n += snprintf(&buf[n], PAGE_SIZE - n, "tune_bw = %d\n",
+		      p->tune_bw);
+
+	for (i = 0; i < 3; i++) {
+		if (p->layer_info[i].number_of_segments < 1 ||
+		    p->layer_info[i].number_of_segments > 13)
+			continue;
+
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\nLayer %d\n", i);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tcode_rate = %d\t",
+			      p->layer_info[i].code_rate);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "constellation = %d\n",
+			      p->layer_info[i].constellation);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tber = %-5d\t",
+			      p->layer_info[i].ber);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tber_error_count = %-5d\t",
+			      p->layer_info[i].ber_error_count);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "ber_bit_count = %-5d\n",
+			      p->layer_info[i].ber_bit_count);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tpre_ber = %-5d\t",
+			      p->layer_info[i].pre_ber);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\tts_per = %-5d\n",
+			      p->layer_info[i].ts_per);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "\terror_ts_packets = %-5d\t",
+			      p->layer_info[i].error_ts_packets);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "total_ts_packets = %-5d\t",
+			      p->layer_info[i].total_ts_packets);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "ti_ldepth_i = %d\n",
+			      p->layer_info[i].ti_ldepth_i);
+		n += snprintf(&buf[n], PAGE_SIZE - n,
+			      "\tnumber_of_segments = %d\t",
+			      p->layer_info[i].number_of_segments);
+		n += snprintf(&buf[n], PAGE_SIZE - n, "tmcc_errors = %d\n",
+			      p->layer_info[i].tmcc_errors);
+	}
+
+
+	debug_data->stats_count = n;
+	spin_unlock(&debug_data->lock);
+
+	wake_up(&debug_data->stats_queue);
+}
+
+static int smsdvb_stats_open(struct inode *inode, struct file *file)
+{
+	struct smsdvb_client_t *client = inode->i_private;
+	struct smsdvb_debugfs *debug_data = client->debug_data;
+
+	kref_get(&debug_data->refcount);
+
+	spin_lock(&debug_data->lock);
+	debug_data->stats_count = 0;
+	debug_data->stats_was_read = false;
+	spin_unlock(&debug_data->lock);
+
+	file->private_data = debug_data;
+
+	return 0;
+}
+
+static void smsdvb_debugfs_data_release(struct kref *ref)
+{
+	struct smsdvb_debugfs *debug_data;
+
+	debug_data = container_of(ref, struct smsdvb_debugfs, refcount);
+	kfree(debug_data);
+}
+
+static int smsdvb_stats_wait_read(struct smsdvb_debugfs *debug_data)
+{
+	int rc = 1;
+
+	spin_lock(&debug_data->lock);
+
+	if (debug_data->stats_was_read)
+		goto exit;
+
+	rc = debug_data->stats_count;
+
+exit:
+	spin_unlock(&debug_data->lock);
+	return rc;
+}
+
+static unsigned int smsdvb_stats_poll(struct file *file, poll_table *wait)
+{
+	struct smsdvb_debugfs *debug_data = file->private_data;
+	int rc;
+
+	kref_get(&debug_data->refcount);
+
+	poll_wait(file, &debug_data->stats_queue, wait);
+
+	rc = smsdvb_stats_wait_read(debug_data);
+	if (rc > 0)
+		rc = POLLIN | POLLRDNORM;
+
+	kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
+
+	return rc;
+}
+
+static ssize_t smsdvb_stats_read(struct file *file, char __user *user_buf,
+				      size_t nbytes, loff_t *ppos)
+{
+	int rc = 0, len;
+	struct smsdvb_debugfs *debug_data = file->private_data;
+
+	kref_get(&debug_data->refcount);
+
+	if (file->f_flags & O_NONBLOCK) {
+		rc = smsdvb_stats_wait_read(debug_data);
+		if (!rc) {
+			rc = -EWOULDBLOCK;
+			goto ret;
+		}
+	} else {
+		rc = wait_event_interruptible(debug_data->stats_queue,
+				      smsdvb_stats_wait_read(debug_data));
+		if (rc < 0)
+			goto ret;
+	}
+
+	if (debug_data->stats_was_read) {
+		rc = 0;	/* EOF */
+		goto ret;
+	}
+
+	len = debug_data->stats_count - *ppos;
+	if (len >= 0)
+		rc = simple_read_from_buffer(user_buf, nbytes, ppos,
+					     debug_data->stats_data, len);
+	else
+		rc = 0;
+
+	if (*ppos >= debug_data->stats_count) {
+		spin_lock(&debug_data->lock);
+		debug_data->stats_was_read = true;
+		spin_unlock(&debug_data->lock);
+	}
+ret:
+	kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
+	return rc;
+}
+
+static int smsdvb_stats_release(struct inode *inode, struct file *file)
+{
+	struct smsdvb_debugfs *debug_data = file->private_data;
+
+	spin_lock(&debug_data->lock);
+	debug_data->stats_was_read = true;	/* return EOF to read() */
+	spin_unlock(&debug_data->lock);
+	wake_up_interruptible_sync(&debug_data->stats_queue);
+
+	kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
+	file->private_data = NULL;
+
+	return 0;
+}
+
+static const struct file_operations debugfs_stats_ops = {
+	.open = smsdvb_stats_open,
+	.poll = smsdvb_stats_poll,
+	.read = smsdvb_stats_read,
+	.release = smsdvb_stats_release,
+	.llseek = generic_file_llseek,
+};
+
+/*
+ * Functions used by smsdvb, in order to create the interfaces
+ */
+
+int smsdvb_debugfs_create(struct smsdvb_client_t *client)
+{
+	struct smscore_device_t *coredev = client->coredev;
+	struct dentry *d;
+	struct smsdvb_debugfs *debug_data;
+
+	if (!smsdvb_debugfs_usb_root || !coredev->is_usb_device)
+		return -ENODEV;
+
+	client->debugfs = debugfs_create_dir(coredev->devpath,
+					     smsdvb_debugfs_usb_root);
+	if (IS_ERR_OR_NULL(client->debugfs)) {
+		pr_info("Unable to create debugfs %s directory.\n",
+			coredev->devpath);
+		return -ENODEV;
+	}
+
+	d = debugfs_create_file("stats", S_IRUGO | S_IWUSR, client->debugfs,
+				client, &debugfs_stats_ops);
+	if (!d) {
+		debugfs_remove(client->debugfs);
+		return -ENOMEM;
+	}
+
+	debug_data = kzalloc(sizeof(*client->debug_data), GFP_KERNEL);
+	if (!debug_data)
+		return -ENOMEM;
+
+	client->debug_data        = debug_data;
+	client->prt_dvb_stats     = smsdvb_print_dvb_stats;
+	client->prt_isdb_stats    = smsdvb_print_isdb_stats;
+	client->prt_isdb_stats_ex = smsdvb_print_isdb_stats_ex;
+
+	init_waitqueue_head(&debug_data->stats_queue);
+	spin_lock_init(&debug_data->lock);
+	kref_init(&debug_data->refcount);
+
+	return 0;
+}
+
+void smsdvb_debugfs_release(struct smsdvb_client_t *client)
+{
+	if (!client->debugfs)
+		return;
+
+	client->prt_dvb_stats     = NULL;
+	client->prt_isdb_stats    = NULL;
+	client->prt_isdb_stats_ex = NULL;
+
+	debugfs_remove_recursive(client->debugfs);
+	kref_put(&client->debug_data->refcount, smsdvb_debugfs_data_release);
+
+	client->debug_data = NULL;
+	client->debugfs = NULL;
+}
+
+int smsdvb_debugfs_register(void)
+{
+	struct dentry *d;
+
+	/*
+	 * FIXME: This was written to debug Siano USB devices. So, it creates
+	 * the debugfs node under <debugfs>/usb.
+	 * A similar logic would be needed for Siano sdio devices, but, in that
+	 * case, usb_debug_root is not a good choice.
+	 *
+	 * Perhaps the right fix here would be to create another sysfs root
+	 * node for sdio-based boards, but this may need some logic at sdio
+	 * subsystem.
+	 */
+	d = debugfs_create_dir("smsdvb", usb_debug_root);
+	if (IS_ERR_OR_NULL(d)) {
+		sms_err("Couldn't create sysfs node for smsdvb");
+		return PTR_ERR(d);
+	} else {
+		smsdvb_debugfs_usb_root = d;
+	}
+	return 0;
+}
+
+void smsdvb_debugfs_unregister(void)
+{
+	debugfs_remove_recursive(smsdvb_debugfs_usb_root);
+	smsdvb_debugfs_usb_root = NULL;
+}

+ 1230 - 0
drivers/media/common/siano/smsdvb-main.c

@@ -0,0 +1,1230 @@
+/****************************************************************
+
+Siano Mobile Silicon, Inc.
+MDTV receiver kernel modules.
+Copyright (C) 2006-2008, Uri Shkolnik
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+****************************************************************/
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <asm/div64.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+
+#include "smscoreapi.h"
+#include "sms-cards.h"
+
+#include "smsdvb.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static struct list_head g_smsdvb_clients;
+static struct mutex g_smsdvb_clientslock;
+
+static int sms_dbg;
+module_param_named(debug, sms_dbg, int, 0644);
+MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
+
+
+u32 sms_to_guard_interval_table[] = {
+	[0] = GUARD_INTERVAL_1_32,
+	[1] = GUARD_INTERVAL_1_16,
+	[2] = GUARD_INTERVAL_1_8,
+	[3] = GUARD_INTERVAL_1_4,
+};
+
+u32 sms_to_code_rate_table[] = {
+	[0] = FEC_1_2,
+	[1] = FEC_2_3,
+	[2] = FEC_3_4,
+	[3] = FEC_5_6,
+	[4] = FEC_7_8,
+};
+
+
+u32 sms_to_hierarchy_table[] = {
+	[0] = HIERARCHY_NONE,
+	[1] = HIERARCHY_1,
+	[2] = HIERARCHY_2,
+	[3] = HIERARCHY_4,
+};
+
+u32 sms_to_modulation_table[] = {
+	[0] = QPSK,
+	[1] = QAM_16,
+	[2] = QAM_64,
+	[3] = DQPSK,
+};
+
+
+/* Events that may come from DVB v3 adapter */
+static void sms_board_dvb3_event(struct smsdvb_client_t *client,
+		enum SMS_DVB3_EVENTS event) {
+
+	struct smscore_device_t *coredev = client->coredev;
+	switch (event) {
+	case DVB3_EVENT_INIT:
+		sms_debug("DVB3_EVENT_INIT");
+		sms_board_event(coredev, BOARD_EVENT_BIND);
+		break;
+	case DVB3_EVENT_SLEEP:
+		sms_debug("DVB3_EVENT_SLEEP");
+		sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
+		break;
+	case DVB3_EVENT_HOTPLUG:
+		sms_debug("DVB3_EVENT_HOTPLUG");
+		sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
+		break;
+	case DVB3_EVENT_FE_LOCK:
+		if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
+			client->event_fe_state = DVB3_EVENT_FE_LOCK;
+			sms_debug("DVB3_EVENT_FE_LOCK");
+			sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
+		}
+		break;
+	case DVB3_EVENT_FE_UNLOCK:
+		if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
+			client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
+			sms_debug("DVB3_EVENT_FE_UNLOCK");
+			sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
+		}
+		break;
+	case DVB3_EVENT_UNC_OK:
+		if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
+			client->event_unc_state = DVB3_EVENT_UNC_OK;
+			sms_debug("DVB3_EVENT_UNC_OK");
+			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
+		}
+		break;
+	case DVB3_EVENT_UNC_ERR:
+		if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
+			client->event_unc_state = DVB3_EVENT_UNC_ERR;
+			sms_debug("DVB3_EVENT_UNC_ERR");
+			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
+		}
+		break;
+
+	default:
+		sms_err("Unknown dvb3 api event");
+		break;
+	}
+}
+
+static void smsdvb_stats_not_ready(struct dvb_frontend *fe)
+{
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+	struct smscore_device_t *coredev = client->coredev;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int i, n_layers;
+
+	switch (smscore_get_device_mode(coredev)) {
+	case DEVICE_MODE_ISDBT:
+	case DEVICE_MODE_ISDBT_BDA:
+		n_layers = 4;
+	default:
+		n_layers = 1;
+	}
+
+	/* Global stats */
+	c->strength.len = 1;
+	c->cnr.len = 1;
+	c->strength.stat[0].scale = FE_SCALE_DECIBEL;
+	c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+
+	/* Per-layer stats */
+	c->post_bit_error.len = n_layers;
+	c->post_bit_count.len = n_layers;
+	c->block_error.len = n_layers;
+	c->block_count.len = n_layers;
+
+	/*
+	 * Put all of them at FE_SCALE_NOT_AVAILABLE. They're dynamically
+	 * changed when the stats become available.
+	 */
+	for (i = 0; i < n_layers; i++) {
+		c->post_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
+		c->post_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
+		c->block_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
+		c->block_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
+	}
+}
+
+static inline int sms_to_mode(u32 mode)
+{
+	switch (mode) {
+	case 2:
+		return TRANSMISSION_MODE_2K;
+	case 4:
+		return TRANSMISSION_MODE_4K;
+	case 8:
+		return TRANSMISSION_MODE_8K;
+	}
+	return TRANSMISSION_MODE_AUTO;
+}
+
+static inline int sms_to_status(u32 is_demod_locked, u32 is_rf_locked)
+{
+	if (is_demod_locked)
+		return FE_HAS_SIGNAL  | FE_HAS_CARRIER | FE_HAS_VITERBI |
+		       FE_HAS_SYNC    | FE_HAS_LOCK;
+
+	if (is_rf_locked)
+		return FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
+	return 0;
+}
+
+static inline u32 sms_to_bw(u32 value)
+{
+	return value * 1000000;
+}
+
+#define convert_from_table(value, table, defval) ({			\
+	u32 __ret;							\
+	if (value < ARRAY_SIZE(table))					\
+		__ret = table[value];					\
+	else								\
+		__ret = defval;						\
+	__ret;								\
+})
+
+#define sms_to_guard_interval(value)					\
+	convert_from_table(value, sms_to_guard_interval_table,		\
+			   GUARD_INTERVAL_AUTO);
+
+#define sms_to_code_rate(value)						\
+	convert_from_table(value, sms_to_code_rate_table,		\
+			   FEC_NONE);
+
+#define sms_to_hierarchy(value)						\
+	convert_from_table(value, sms_to_hierarchy_table,		\
+			   FEC_NONE);
+
+#define sms_to_modulation(value)					\
+	convert_from_table(value, sms_to_modulation_table,		\
+			   FEC_NONE);
+
+static void smsdvb_update_tx_params(struct smsdvb_client_t *client,
+				    struct sms_tx_stats *p)
+{
+	struct dvb_frontend *fe = &client->frontend;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	c->frequency = p->frequency;
+	client->fe_status = sms_to_status(p->is_demod_locked, 0);
+	c->bandwidth_hz = sms_to_bw(p->bandwidth);
+	c->transmission_mode = sms_to_mode(p->transmission_mode);
+	c->guard_interval = sms_to_guard_interval(p->guard_interval);
+	c->code_rate_HP = sms_to_code_rate(p->code_rate);
+	c->code_rate_LP = sms_to_code_rate(p->lp_code_rate);
+	c->hierarchy = sms_to_hierarchy(p->hierarchy);
+	c->modulation = sms_to_modulation(p->constellation);
+}
+
+static void smsdvb_update_per_slices(struct smsdvb_client_t *client,
+				     struct RECEPTION_STATISTICS_PER_SLICES_S *p)
+{
+	struct dvb_frontend *fe = &client->frontend;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	u64 tmp;
+
+	client->fe_status = sms_to_status(p->is_demod_locked, p->is_rf_locked);
+	c->modulation = sms_to_modulation(p->constellation);
+
+	/* signal Strength, in DBm */
+	c->strength.stat[0].uvalue = p->in_band_power * 1000;
+
+	/* Carrier to noise ratio, in DB */
+	c->cnr.stat[0].svalue = p->snr * 1000;
+
+	/* PER/BER requires demod lock */
+	if (!p->is_demod_locked)
+		return;
+
+	/* TS PER */
+	client->last_per = c->block_error.stat[0].uvalue;
+	c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->block_error.stat[0].uvalue += p->ets_packets;
+	c->block_count.stat[0].uvalue += p->ets_packets + p->ts_packets;
+
+	/* ber */
+	c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_error.stat[0].uvalue += p->ber_error_count;
+	c->post_bit_count.stat[0].uvalue += p->ber_bit_count;
+
+	/* Legacy PER/BER */
+	tmp = p->ets_packets * 65535;
+	do_div(tmp, p->ts_packets + p->ets_packets);
+	client->legacy_per = tmp;
+}
+
+static void smsdvb_update_dvb_stats(struct smsdvb_client_t *client,
+				    struct sms_stats *p)
+{
+	struct dvb_frontend *fe = &client->frontend;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	if (client->prt_dvb_stats)
+		client->prt_dvb_stats(client->debug_data, p);
+
+	client->fe_status = sms_to_status(p->is_demod_locked, p->is_rf_locked);
+
+	/* Update DVB modulation parameters */
+	c->frequency = p->frequency;
+	client->fe_status = sms_to_status(p->is_demod_locked, 0);
+	c->bandwidth_hz = sms_to_bw(p->bandwidth);
+	c->transmission_mode = sms_to_mode(p->transmission_mode);
+	c->guard_interval = sms_to_guard_interval(p->guard_interval);
+	c->code_rate_HP = sms_to_code_rate(p->code_rate);
+	c->code_rate_LP = sms_to_code_rate(p->lp_code_rate);
+	c->hierarchy = sms_to_hierarchy(p->hierarchy);
+	c->modulation = sms_to_modulation(p->constellation);
+
+	/* update reception data */
+	c->lna = p->is_external_lna_on ? 1 : 0;
+
+	/* Carrier to noise ratio, in DB */
+	c->cnr.stat[0].svalue = p->SNR * 1000;
+
+	/* signal Strength, in DBm */
+	c->strength.stat[0].uvalue = p->in_band_pwr * 1000;
+
+	/* PER/BER requires demod lock */
+	if (!p->is_demod_locked)
+		return;
+
+	/* TS PER */
+	client->last_per = c->block_error.stat[0].uvalue;
+	c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->block_error.stat[0].uvalue += p->error_ts_packets;
+	c->block_count.stat[0].uvalue += p->total_ts_packets;
+
+	/* ber */
+	c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_error.stat[0].uvalue += p->ber_error_count;
+	c->post_bit_count.stat[0].uvalue += p->ber_bit_count;
+
+	/* Legacy PER/BER */
+	client->legacy_ber = p->ber;
+};
+
+static void smsdvb_update_isdbt_stats(struct smsdvb_client_t *client,
+				      struct sms_isdbt_stats *p)
+{
+	struct dvb_frontend *fe = &client->frontend;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct sms_isdbt_layer_stats *lr;
+	int i, n_layers;
+
+	if (client->prt_isdb_stats)
+		client->prt_isdb_stats(client->debug_data, p);
+
+	client->fe_status = sms_to_status(p->is_demod_locked, p->is_rf_locked);
+
+	/*
+	 * Firmware 2.1 seems to report only lock status and
+	 * signal strength. The signal strength indicator is at the
+	 * wrong field.
+	 */
+	if (p->statistics_type == 0) {
+		c->strength.stat[0].uvalue = ((s32)p->transmission_mode) * 1000;
+		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		return;
+	}
+
+	/* Update ISDB-T transmission parameters */
+	c->frequency = p->frequency;
+	c->bandwidth_hz = sms_to_bw(p->bandwidth);
+	c->transmission_mode = sms_to_mode(p->transmission_mode);
+	c->guard_interval = sms_to_guard_interval(p->guard_interval);
+	c->isdbt_partial_reception = p->partial_reception ? 1 : 0;
+	n_layers = p->num_of_layers;
+	if (n_layers < 1)
+		n_layers = 1;
+	if (n_layers > 3)
+		n_layers = 3;
+	c->isdbt_layer_enabled = 0;
+
+	/* update reception data */
+	c->lna = p->is_external_lna_on ? 1 : 0;
+
+	/* Carrier to noise ratio, in DB */
+	c->cnr.stat[0].svalue = p->SNR * 1000;
+
+	/* signal Strength, in DBm */
+	c->strength.stat[0].uvalue = p->in_band_pwr * 1000;
+
+	/* PER/BER and per-layer stats require demod lock */
+	if (!p->is_demod_locked)
+		return;
+
+	client->last_per = c->block_error.stat[0].uvalue;
+
+	/* Clears global counters, as the code below will sum it again */
+	c->block_error.stat[0].uvalue = 0;
+	c->block_count.stat[0].uvalue = 0;
+	c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_error.stat[0].uvalue = 0;
+	c->post_bit_count.stat[0].uvalue = 0;
+	c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+
+	for (i = 0; i < n_layers; i++) {
+		lr = &p->layer_info[i];
+
+		/* Update per-layer transmission parameters */
+		if (lr->number_of_segments > 0 && lr->number_of_segments < 13) {
+			c->isdbt_layer_enabled |= 1 << i;
+			c->layer[i].segment_count = lr->number_of_segments;
+		} else {
+			continue;
+		}
+		c->layer[i].modulation = sms_to_modulation(lr->constellation);
+
+		/* TS PER */
+		c->block_error.stat[i + 1].scale = FE_SCALE_COUNTER;
+		c->block_count.stat[i + 1].scale = FE_SCALE_COUNTER;
+		c->block_error.stat[i + 1].uvalue += lr->error_ts_packets;
+		c->block_count.stat[i + 1].uvalue += lr->total_ts_packets;
+
+		/* Update global PER counter */
+		c->block_error.stat[0].uvalue += lr->error_ts_packets;
+		c->block_count.stat[0].uvalue += lr->total_ts_packets;
+
+		/* BER */
+		c->post_bit_error.stat[i + 1].scale = FE_SCALE_COUNTER;
+		c->post_bit_count.stat[i + 1].scale = FE_SCALE_COUNTER;
+		c->post_bit_error.stat[i + 1].uvalue += lr->ber_error_count;
+		c->post_bit_count.stat[i + 1].uvalue += lr->ber_bit_count;
+
+		/* Update global BER counter */
+		c->post_bit_error.stat[0].uvalue += lr->ber_error_count;
+		c->post_bit_count.stat[0].uvalue += lr->ber_bit_count;
+	}
+}
+
+static void smsdvb_update_isdbt_stats_ex(struct smsdvb_client_t *client,
+					 struct sms_isdbt_stats_ex *p)
+{
+	struct dvb_frontend *fe = &client->frontend;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct sms_isdbt_layer_stats *lr;
+	int i, n_layers;
+
+	if (client->prt_isdb_stats_ex)
+		client->prt_isdb_stats_ex(client->debug_data, p);
+
+	/* Update ISDB-T transmission parameters */
+	c->frequency = p->frequency;
+	client->fe_status = sms_to_status(p->is_demod_locked, 0);
+	c->bandwidth_hz = sms_to_bw(p->bandwidth);
+	c->transmission_mode = sms_to_mode(p->transmission_mode);
+	c->guard_interval = sms_to_guard_interval(p->guard_interval);
+	c->isdbt_partial_reception = p->partial_reception ? 1 : 0;
+	n_layers = p->num_of_layers;
+	if (n_layers < 1)
+		n_layers = 1;
+	if (n_layers > 3)
+		n_layers = 3;
+	c->isdbt_layer_enabled = 0;
+
+	/* update reception data */
+	c->lna = p->is_external_lna_on ? 1 : 0;
+
+	/* Carrier to noise ratio, in DB */
+	c->cnr.stat[0].svalue = p->SNR * 1000;
+
+	/* signal Strength, in DBm */
+	c->strength.stat[0].uvalue = p->in_band_pwr * 1000;
+
+	/* PER/BER and per-layer stats require demod lock */
+	if (!p->is_demod_locked)
+		return;
+
+	client->last_per = c->block_error.stat[0].uvalue;
+
+	/* Clears global counters, as the code below will sum it again */
+	c->block_error.stat[0].uvalue = 0;
+	c->block_count.stat[0].uvalue = 0;
+	c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_error.stat[0].uvalue = 0;
+	c->post_bit_count.stat[0].uvalue = 0;
+	c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+
+	c->post_bit_error.len = n_layers + 1;
+	c->post_bit_count.len = n_layers + 1;
+	c->block_error.len = n_layers + 1;
+	c->block_count.len = n_layers + 1;
+	for (i = 0; i < n_layers; i++) {
+		lr = &p->layer_info[i];
+
+		/* Update per-layer transmission parameters */
+		if (lr->number_of_segments > 0 && lr->number_of_segments < 13) {
+			c->isdbt_layer_enabled |= 1 << i;
+			c->layer[i].segment_count = lr->number_of_segments;
+		} else {
+			continue;
+		}
+		c->layer[i].modulation = sms_to_modulation(lr->constellation);
+
+		/* TS PER */
+		c->block_error.stat[i + 1].scale = FE_SCALE_COUNTER;
+		c->block_count.stat[i + 1].scale = FE_SCALE_COUNTER;
+		c->block_error.stat[i + 1].uvalue += lr->error_ts_packets;
+		c->block_count.stat[i + 1].uvalue += lr->total_ts_packets;
+
+		/* Update global PER counter */
+		c->block_error.stat[0].uvalue += lr->error_ts_packets;
+		c->block_count.stat[0].uvalue += lr->total_ts_packets;
+
+		/* ber */
+		c->post_bit_error.stat[i + 1].scale = FE_SCALE_COUNTER;
+		c->post_bit_count.stat[i + 1].scale = FE_SCALE_COUNTER;
+		c->post_bit_error.stat[i + 1].uvalue += lr->ber_error_count;
+		c->post_bit_count.stat[i + 1].uvalue += lr->ber_bit_count;
+
+		/* Update global ber counter */
+		c->post_bit_error.stat[0].uvalue += lr->ber_error_count;
+		c->post_bit_count.stat[0].uvalue += lr->ber_bit_count;
+	}
+}
+
+static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
+{
+	struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
+	struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) (((u8 *) cb->p)
+			+ cb->offset);
+	void *p = phdr + 1;
+	struct dvb_frontend *fe = &client->frontend;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	bool is_status_update = false;
+
+	switch (phdr->msg_type) {
+	case MSG_SMS_DVBT_BDA_DATA:
+		/*
+		 * Only feed data to dvb demux if are there any feed listening
+		 * to it and if the device has tuned
+		 */
+		if (client->feed_users && client->has_tuned)
+			dvb_dmx_swfilter(&client->demux, p,
+					 cb->size - sizeof(struct sms_msg_hdr));
+		break;
+
+	case MSG_SMS_RF_TUNE_RES:
+	case MSG_SMS_ISDBT_TUNE_RES:
+		complete(&client->tune_done);
+		break;
+
+	case MSG_SMS_SIGNAL_DETECTED_IND:
+		client->fe_status = FE_HAS_SIGNAL  | FE_HAS_CARRIER |
+				    FE_HAS_VITERBI | FE_HAS_SYNC    |
+				    FE_HAS_LOCK;
+
+		is_status_update = true;
+		break;
+
+	case MSG_SMS_NO_SIGNAL_IND:
+		client->fe_status = 0;
+
+		is_status_update = true;
+		break;
+
+	case MSG_SMS_TRANSMISSION_IND:
+		smsdvb_update_tx_params(client, p);
+
+		is_status_update = true;
+		break;
+
+	case MSG_SMS_HO_PER_SLICES_IND:
+		smsdvb_update_per_slices(client, p);
+
+		is_status_update = true;
+		break;
+
+	case MSG_SMS_GET_STATISTICS_RES:
+		switch (smscore_get_device_mode(client->coredev)) {
+		case DEVICE_MODE_ISDBT:
+		case DEVICE_MODE_ISDBT_BDA:
+			smsdvb_update_isdbt_stats(client, p);
+			break;
+		default:
+			/* Skip sms_msg_statistics_info:request_result field */
+			smsdvb_update_dvb_stats(client, p + sizeof(u32));
+		}
+
+		is_status_update = true;
+		break;
+
+	/* Only for ISDB-T */
+	case MSG_SMS_GET_STATISTICS_EX_RES:
+		/* Skip sms_msg_statistics_info:request_result field? */
+		smsdvb_update_isdbt_stats_ex(client, p + sizeof(u32));
+		is_status_update = true;
+		break;
+	default:
+		sms_info("message not handled");
+	}
+	smscore_putbuffer(client->coredev, cb);
+
+	if (is_status_update) {
+		if (client->fe_status & FE_HAS_LOCK) {
+			sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK);
+			if (client->last_per == c->block_error.stat[0].uvalue)
+				sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK);
+			else
+				sms_board_dvb3_event(client, DVB3_EVENT_UNC_ERR);
+			client->has_tuned = true;
+		} else {
+			smsdvb_stats_not_ready(fe);
+			client->has_tuned = false;
+			sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
+		}
+		complete(&client->stats_done);
+	}
+
+	return 0;
+}
+
+static void smsdvb_unregister_client(struct smsdvb_client_t *client)
+{
+	/* must be called under clientslock */
+
+	list_del(&client->entry);
+
+	smsdvb_debugfs_release(client);
+	smscore_unregister_client(client->smsclient);
+	dvb_unregister_frontend(&client->frontend);
+	dvb_dmxdev_release(&client->dmxdev);
+	dvb_dmx_release(&client->demux);
+	dvb_unregister_adapter(&client->adapter);
+	kfree(client);
+}
+
+static void smsdvb_onremove(void *context)
+{
+	kmutex_lock(&g_smsdvb_clientslock);
+
+	smsdvb_unregister_client((struct smsdvb_client_t *) context);
+
+	kmutex_unlock(&g_smsdvb_clientslock);
+}
+
+static int smsdvb_start_feed(struct dvb_demux_feed *feed)
+{
+	struct smsdvb_client_t *client =
+		container_of(feed->demux, struct smsdvb_client_t, demux);
+	struct sms_msg_data pid_msg;
+
+	sms_debug("add pid %d(%x)",
+		  feed->pid, feed->pid);
+
+	client->feed_users++;
+
+	pid_msg.x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+	pid_msg.x_msg_header.msg_dst_id = HIF_TASK;
+	pid_msg.x_msg_header.msg_flags = 0;
+	pid_msg.x_msg_header.msg_type  = MSG_SMS_ADD_PID_FILTER_REQ;
+	pid_msg.x_msg_header.msg_length = sizeof(pid_msg);
+	pid_msg.msg_data[0] = feed->pid;
+
+	return smsclient_sendrequest(client->smsclient,
+				     &pid_msg, sizeof(pid_msg));
+}
+
+static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
+{
+	struct smsdvb_client_t *client =
+		container_of(feed->demux, struct smsdvb_client_t, demux);
+	struct sms_msg_data pid_msg;
+
+	sms_debug("remove pid %d(%x)",
+		  feed->pid, feed->pid);
+
+	client->feed_users--;
+
+	pid_msg.x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+	pid_msg.x_msg_header.msg_dst_id = HIF_TASK;
+	pid_msg.x_msg_header.msg_flags = 0;
+	pid_msg.x_msg_header.msg_type  = MSG_SMS_REMOVE_PID_FILTER_REQ;
+	pid_msg.x_msg_header.msg_length = sizeof(pid_msg);
+	pid_msg.msg_data[0] = feed->pid;
+
+	return smsclient_sendrequest(client->smsclient,
+				     &pid_msg, sizeof(pid_msg));
+}
+
+static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
+					void *buffer, size_t size,
+					struct completion *completion)
+{
+	int rc;
+
+	rc = smsclient_sendrequest(client->smsclient, buffer, size);
+	if (rc < 0)
+		return rc;
+
+	return wait_for_completion_timeout(completion,
+					   msecs_to_jiffies(2000)) ?
+						0 : -ETIME;
+}
+
+static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
+{
+	int rc;
+	struct sms_msg_hdr msg;
+
+	/* Don't request stats too fast */
+	if (client->get_stats_jiffies &&
+	   (!time_after(jiffies, client->get_stats_jiffies)))
+		return 0;
+	client->get_stats_jiffies = jiffies + msecs_to_jiffies(100);
+
+	msg.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+	msg.msg_dst_id = HIF_TASK;
+	msg.msg_flags = 0;
+	msg.msg_length = sizeof(msg);
+
+	switch (smscore_get_device_mode(client->coredev)) {
+	case DEVICE_MODE_ISDBT:
+	case DEVICE_MODE_ISDBT_BDA:
+		/*
+		* Check for firmware version, to avoid breaking for old cards
+		*/
+		if (client->coredev->fw_version >= 0x800)
+			msg.msg_type = MSG_SMS_GET_STATISTICS_EX_REQ;
+		else
+			msg.msg_type = MSG_SMS_GET_STATISTICS_REQ;
+		break;
+	default:
+		msg.msg_type = MSG_SMS_GET_STATISTICS_REQ;
+	}
+
+	rc = smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg),
+					 &client->stats_done);
+
+	return rc;
+}
+
+static inline int led_feedback(struct smsdvb_client_t *client)
+{
+	if (!(client->fe_status & FE_HAS_LOCK))
+		return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
+
+	return sms_board_led_feedback(client->coredev,
+				     (client->legacy_ber == 0) ?
+				     SMS_LED_HI : SMS_LED_LO);
+}
+
+static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+{
+	int rc;
+	struct smsdvb_client_t *client;
+	client = container_of(fe, struct smsdvb_client_t, frontend);
+
+	rc = smsdvb_send_statistics_request(client);
+
+	*stat = client->fe_status;
+
+	led_feedback(client);
+
+	return rc;
+}
+
+static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	int rc;
+	struct smsdvb_client_t *client;
+
+	client = container_of(fe, struct smsdvb_client_t, frontend);
+
+	rc = smsdvb_send_statistics_request(client);
+
+	*ber = client->legacy_ber;
+
+	led_feedback(client);
+
+	return rc;
+}
+
+static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int rc;
+	s32 power = (s32) c->strength.stat[0].uvalue;
+	struct smsdvb_client_t *client;
+
+	client = container_of(fe, struct smsdvb_client_t, frontend);
+
+	rc = smsdvb_send_statistics_request(client);
+
+	if (power < -95)
+		*strength = 0;
+		else if (power > -29)
+			*strength = 65535;
+		else
+			*strength = (power + 95) * 65535 / 66;
+
+	led_feedback(client);
+
+	return rc;
+}
+
+static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int rc;
+	struct smsdvb_client_t *client;
+
+	client = container_of(fe, struct smsdvb_client_t, frontend);
+
+	rc = smsdvb_send_statistics_request(client);
+
+	/* Preferred scale for SNR with legacy API: 0.1 dB */
+	*snr = ((u32)c->cnr.stat[0].svalue) / 100;
+
+	led_feedback(client);
+
+	return rc;
+}
+
+static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	int rc;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct smsdvb_client_t *client;
+
+	client = container_of(fe, struct smsdvb_client_t, frontend);
+
+	rc = smsdvb_send_statistics_request(client);
+
+	*ucblocks = c->block_error.stat[0].uvalue;
+
+	led_feedback(client);
+
+	return rc;
+}
+
+static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
+				    struct dvb_frontend_tune_settings *tune)
+{
+	sms_debug("");
+
+	tune->min_delay_ms = 400;
+	tune->step_size = 250000;
+	tune->max_drift = 0;
+	return 0;
+}
+
+static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+
+	struct {
+		struct sms_msg_hdr	msg;
+		u32		Data[3];
+	} msg;
+
+	int ret;
+
+	client->fe_status = 0;
+	client->event_fe_state = -1;
+	client->event_unc_state = -1;
+	fe->dtv_property_cache.delivery_system = SYS_DVBT;
+
+	msg.msg.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
+	msg.msg.msg_dst_id = HIF_TASK;
+	msg.msg.msg_flags = 0;
+	msg.msg.msg_type = MSG_SMS_RF_TUNE_REQ;
+	msg.msg.msg_length = sizeof(msg);
+	msg.Data[0] = c->frequency;
+	msg.Data[2] = 12000000;
+
+	sms_info("%s: freq %d band %d", __func__, c->frequency,
+		 c->bandwidth_hz);
+
+	switch (c->bandwidth_hz / 1000000) {
+	case 8:
+		msg.Data[1] = BW_8_MHZ;
+		break;
+	case 7:
+		msg.Data[1] = BW_7_MHZ;
+		break;
+	case 6:
+		msg.Data[1] = BW_6_MHZ;
+		break;
+	case 0:
+		return -EOPNOTSUPP;
+	default:
+		return -EINVAL;
+	}
+	/* Disable LNA, if any. An error is returned if no LNA is present */
+	ret = sms_board_lna_control(client->coredev, 0);
+	if (ret == 0) {
+		fe_status_t status;
+
+		/* tune with LNA off at first */
+		ret = smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg),
+						  &client->tune_done);
+
+		smsdvb_read_status(fe, &status);
+
+		if (status & FE_HAS_LOCK)
+			return ret;
+
+		/* previous tune didn't lock - enable LNA and tune again */
+		sms_board_lna_control(client->coredev, 1);
+	}
+
+	return smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg),
+					   &client->tune_done);
+}
+
+static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+	int board_id = smscore_get_board_id(client->coredev);
+	struct sms_board *board = sms_get_board(board_id);
+	enum sms_device_type_st type = board->type;
+	int ret;
+
+	struct {
+		struct sms_msg_hdr	msg;
+		u32		Data[4];
+	} msg;
+
+	fe->dtv_property_cache.delivery_system = SYS_ISDBT;
+
+	msg.msg.msg_src_id  = DVBT_BDA_CONTROL_MSG_ID;
+	msg.msg.msg_dst_id  = HIF_TASK;
+	msg.msg.msg_flags  = 0;
+	msg.msg.msg_type   = MSG_SMS_ISDBT_TUNE_REQ;
+	msg.msg.msg_length = sizeof(msg);
+
+	if (c->isdbt_sb_segment_idx == -1)
+		c->isdbt_sb_segment_idx = 0;
+
+	if (!c->isdbt_layer_enabled)
+		c->isdbt_layer_enabled = 7;
+
+	msg.Data[0] = c->frequency;
+	msg.Data[1] = BW_ISDBT_1SEG;
+	msg.Data[2] = 12000000;
+	msg.Data[3] = c->isdbt_sb_segment_idx;
+
+	if (c->isdbt_partial_reception) {
+		if ((type == SMS_PELE || type == SMS_RIO) &&
+		    c->isdbt_sb_segment_count > 3)
+			msg.Data[1] = BW_ISDBT_13SEG;
+		else if (c->isdbt_sb_segment_count > 1)
+			msg.Data[1] = BW_ISDBT_3SEG;
+	} else if (type == SMS_PELE || type == SMS_RIO)
+		msg.Data[1] = BW_ISDBT_13SEG;
+
+	c->bandwidth_hz = 6000000;
+
+	sms_info("%s: freq %d segwidth %d segindex %d", __func__,
+		 c->frequency, c->isdbt_sb_segment_count,
+		 c->isdbt_sb_segment_idx);
+
+	/* Disable LNA, if any. An error is returned if no LNA is present */
+	ret = sms_board_lna_control(client->coredev, 0);
+	if (ret == 0) {
+		fe_status_t status;
+
+		/* tune with LNA off at first */
+		ret = smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg),
+						  &client->tune_done);
+
+		smsdvb_read_status(fe, &status);
+
+		if (status & FE_HAS_LOCK)
+			return ret;
+
+		/* previous tune didn't lock - enable LNA and tune again */
+		sms_board_lna_control(client->coredev, 1);
+	}
+	return smsdvb_sendrequest_and_wait(client, &msg, sizeof(msg),
+					   &client->tune_done);
+}
+
+static int smsdvb_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+	struct smscore_device_t *coredev = client->coredev;
+
+	smsdvb_stats_not_ready(fe);
+	c->strength.stat[0].uvalue = 0;
+	c->cnr.stat[0].uvalue = 0;
+
+	client->has_tuned = false;
+
+	switch (smscore_get_device_mode(coredev)) {
+	case DEVICE_MODE_DVBT:
+	case DEVICE_MODE_DVBT_BDA:
+		return smsdvb_dvbt_set_frontend(fe);
+	case DEVICE_MODE_ISDBT:
+	case DEVICE_MODE_ISDBT_BDA:
+		return smsdvb_isdbt_set_frontend(fe);
+	default:
+		return -EINVAL;
+	}
+}
+
+/* Nothing to do here, as stats are automatically updated */
+static int smsdvb_get_frontend(struct dvb_frontend *fe)
+{
+	return 0;
+}
+
+static int smsdvb_init(struct dvb_frontend *fe)
+{
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+
+	sms_board_power(client->coredev, 1);
+
+	sms_board_dvb3_event(client, DVB3_EVENT_INIT);
+	return 0;
+}
+
+static int smsdvb_sleep(struct dvb_frontend *fe)
+{
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+
+	sms_board_led_feedback(client->coredev, SMS_LED_OFF);
+	sms_board_power(client->coredev, 0);
+
+	sms_board_dvb3_event(client, DVB3_EVENT_SLEEP);
+
+	return 0;
+}
+
+static void smsdvb_release(struct dvb_frontend *fe)
+{
+	/* do nothing */
+}
+
+static struct dvb_frontend_ops smsdvb_fe_ops = {
+	.info = {
+		.name			= "Siano Mobile Digital MDTV Receiver",
+		.frequency_min		= 44250000,
+		.frequency_max		= 867250000,
+		.frequency_stepsize	= 250000,
+		.caps = FE_CAN_INVERSION_AUTO |
+			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_RECOVER |
+			FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release = smsdvb_release,
+
+	.set_frontend = smsdvb_set_frontend,
+	.get_frontend = smsdvb_get_frontend,
+	.get_tune_settings = smsdvb_get_tune_settings,
+
+	.read_status = smsdvb_read_status,
+	.read_ber = smsdvb_read_ber,
+	.read_signal_strength = smsdvb_read_signal_strength,
+	.read_snr = smsdvb_read_snr,
+	.read_ucblocks = smsdvb_read_ucblocks,
+
+	.init = smsdvb_init,
+	.sleep = smsdvb_sleep,
+};
+
+static int smsdvb_hotplug(struct smscore_device_t *coredev,
+			  struct device *device, int arrival)
+{
+	struct smsclient_params_t params;
+	struct smsdvb_client_t *client;
+	int rc;
+
+	/* device removal handled by onremove callback */
+	if (!arrival)
+		return 0;
+	client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
+	if (!client) {
+		sms_err("kmalloc() failed");
+		return -ENOMEM;
+	}
+
+	/* register dvb adapter */
+	rc = dvb_register_adapter(&client->adapter,
+				  sms_get_board(
+					smscore_get_board_id(coredev))->name,
+				  THIS_MODULE, device, adapter_nr);
+	if (rc < 0) {
+		sms_err("dvb_register_adapter() failed %d", rc);
+		goto adapter_error;
+	}
+
+	/* init dvb demux */
+	client->demux.dmx.capabilities = DMX_TS_FILTERING;
+	client->demux.filternum = 32; /* todo: nova ??? */
+	client->demux.feednum = 32;
+	client->demux.start_feed = smsdvb_start_feed;
+	client->demux.stop_feed = smsdvb_stop_feed;
+
+	rc = dvb_dmx_init(&client->demux);
+	if (rc < 0) {
+		sms_err("dvb_dmx_init failed %d", rc);
+		goto dvbdmx_error;
+	}
+
+	/* init dmxdev */
+	client->dmxdev.filternum = 32;
+	client->dmxdev.demux = &client->demux.dmx;
+	client->dmxdev.capabilities = 0;
+
+	rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
+	if (rc < 0) {
+		sms_err("dvb_dmxdev_init failed %d", rc);
+		goto dmxdev_error;
+	}
+
+	/* init and register frontend */
+	memcpy(&client->frontend.ops, &smsdvb_fe_ops,
+	       sizeof(struct dvb_frontend_ops));
+
+	switch (smscore_get_device_mode(coredev)) {
+	case DEVICE_MODE_DVBT:
+	case DEVICE_MODE_DVBT_BDA:
+		client->frontend.ops.delsys[0] = SYS_DVBT;
+		break;
+	case DEVICE_MODE_ISDBT:
+	case DEVICE_MODE_ISDBT_BDA:
+		client->frontend.ops.delsys[0] = SYS_ISDBT;
+		break;
+	}
+
+	rc = dvb_register_frontend(&client->adapter, &client->frontend);
+	if (rc < 0) {
+		sms_err("frontend registration failed %d", rc);
+		goto frontend_error;
+	}
+
+	params.initial_id = 1;
+	params.data_type = MSG_SMS_DVBT_BDA_DATA;
+	params.onresponse_handler = smsdvb_onresponse;
+	params.onremove_handler = smsdvb_onremove;
+	params.context = client;
+
+	rc = smscore_register_client(coredev, &params, &client->smsclient);
+	if (rc < 0) {
+		sms_err("smscore_register_client() failed %d", rc);
+		goto client_error;
+	}
+
+	client->coredev = coredev;
+
+	init_completion(&client->tune_done);
+	init_completion(&client->stats_done);
+
+	kmutex_lock(&g_smsdvb_clientslock);
+
+	list_add(&client->entry, &g_smsdvb_clients);
+
+	kmutex_unlock(&g_smsdvb_clientslock);
+
+	client->event_fe_state = -1;
+	client->event_unc_state = -1;
+	sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG);
+
+	sms_info("success");
+	sms_board_setup(coredev);
+
+	if (smsdvb_debugfs_create(client) < 0)
+		sms_info("failed to create debugfs node");
+
+	return 0;
+
+client_error:
+	dvb_unregister_frontend(&client->frontend);
+
+frontend_error:
+	dvb_dmxdev_release(&client->dmxdev);
+
+dmxdev_error:
+	dvb_dmx_release(&client->demux);
+
+dvbdmx_error:
+	dvb_unregister_adapter(&client->adapter);
+
+adapter_error:
+	kfree(client);
+	return rc;
+}
+
+static int __init smsdvb_module_init(void)
+{
+	int rc;
+
+	INIT_LIST_HEAD(&g_smsdvb_clients);
+	kmutex_init(&g_smsdvb_clientslock);
+
+	smsdvb_debugfs_register();
+
+	rc = smscore_register_hotplug(smsdvb_hotplug);
+
+	sms_debug("");
+
+	return rc;
+}
+
+static void __exit smsdvb_module_exit(void)
+{
+	smscore_unregister_hotplug(smsdvb_hotplug);
+
+	kmutex_lock(&g_smsdvb_clientslock);
+
+	while (!list_empty(&g_smsdvb_clients))
+		smsdvb_unregister_client((struct smsdvb_client_t *)g_smsdvb_clients.next);
+
+	smsdvb_debugfs_unregister();
+
+	kmutex_unlock(&g_smsdvb_clientslock);
+}
+
+module_init(smsdvb_module_init);
+module_exit(smsdvb_module_exit);
+
+MODULE_DESCRIPTION("SMS DVB subsystem adaptation module");
+MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
+MODULE_LICENSE("GPL");

+ 0 - 1078
drivers/media/common/siano/smsdvb.c

@@ -1,1078 +0,0 @@
-/****************************************************************
-
-Siano Mobile Silicon, Inc.
-MDTV receiver kernel modules.
-Copyright (C) 2006-2008, Uri Shkolnik
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-****************************************************************/
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-
-#include "smscoreapi.h"
-#include "smsendian.h"
-#include "sms-cards.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-struct smsdvb_client_t {
-	struct list_head entry;
-
-	struct smscore_device_t *coredev;
-	struct smscore_client_t *smsclient;
-
-	struct dvb_adapter      adapter;
-	struct dvb_demux        demux;
-	struct dmxdev           dmxdev;
-	struct dvb_frontend     frontend;
-
-	fe_status_t             fe_status;
-
-	struct completion       tune_done;
-
-	struct SMSHOSTLIB_STATISTICS_DVB_S sms_stat_dvb;
-	int event_fe_state;
-	int event_unc_state;
-};
-
-static struct list_head g_smsdvb_clients;
-static struct mutex g_smsdvb_clientslock;
-
-static int sms_dbg;
-module_param_named(debug, sms_dbg, int, 0644);
-MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
-
-/* Events that may come from DVB v3 adapter */
-static void sms_board_dvb3_event(struct smsdvb_client_t *client,
-		enum SMS_DVB3_EVENTS event) {
-
-	struct smscore_device_t *coredev = client->coredev;
-	switch (event) {
-	case DVB3_EVENT_INIT:
-		sms_debug("DVB3_EVENT_INIT");
-		sms_board_event(coredev, BOARD_EVENT_BIND);
-		break;
-	case DVB3_EVENT_SLEEP:
-		sms_debug("DVB3_EVENT_SLEEP");
-		sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
-		break;
-	case DVB3_EVENT_HOTPLUG:
-		sms_debug("DVB3_EVENT_HOTPLUG");
-		sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
-		break;
-	case DVB3_EVENT_FE_LOCK:
-		if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
-			client->event_fe_state = DVB3_EVENT_FE_LOCK;
-			sms_debug("DVB3_EVENT_FE_LOCK");
-			sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
-		}
-		break;
-	case DVB3_EVENT_FE_UNLOCK:
-		if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
-			client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
-			sms_debug("DVB3_EVENT_FE_UNLOCK");
-			sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
-		}
-		break;
-	case DVB3_EVENT_UNC_OK:
-		if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
-			client->event_unc_state = DVB3_EVENT_UNC_OK;
-			sms_debug("DVB3_EVENT_UNC_OK");
-			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
-		}
-		break;
-	case DVB3_EVENT_UNC_ERR:
-		if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
-			client->event_unc_state = DVB3_EVENT_UNC_ERR;
-			sms_debug("DVB3_EVENT_UNC_ERR");
-			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
-		}
-		break;
-
-	default:
-		sms_err("Unknown dvb3 api event");
-		break;
-	}
-}
-
-
-static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
-				   struct SMSHOSTLIB_STATISTICS_ST *p)
-{
-	if (sms_dbg & 2) {
-		printk(KERN_DEBUG "Reserved = %d", p->Reserved);
-		printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
-		printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
-		printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
-		printk(KERN_DEBUG "SNR = %d", p->SNR);
-		printk(KERN_DEBUG "BER = %d", p->BER);
-		printk(KERN_DEBUG "FIB_CRC = %d", p->FIB_CRC);
-		printk(KERN_DEBUG "TS_PER = %d", p->TS_PER);
-		printk(KERN_DEBUG "MFER = %d", p->MFER);
-		printk(KERN_DEBUG "RSSI = %d", p->RSSI);
-		printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
-		printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
-		printk(KERN_DEBUG "Frequency = %d", p->Frequency);
-		printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
-		printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
-		printk(KERN_DEBUG "ModemState = %d", p->ModemState);
-		printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
-		printk(KERN_DEBUG "CodeRate = %d", p->CodeRate);
-		printk(KERN_DEBUG "LPCodeRate = %d", p->LPCodeRate);
-		printk(KERN_DEBUG "Hierarchy = %d", p->Hierarchy);
-		printk(KERN_DEBUG "Constellation = %d", p->Constellation);
-		printk(KERN_DEBUG "BurstSize = %d", p->BurstSize);
-		printk(KERN_DEBUG "BurstDuration = %d", p->BurstDuration);
-		printk(KERN_DEBUG "BurstCycleTime = %d", p->BurstCycleTime);
-		printk(KERN_DEBUG "CalculatedBurstCycleTime = %d", p->CalculatedBurstCycleTime);
-		printk(KERN_DEBUG "NumOfRows = %d", p->NumOfRows);
-		printk(KERN_DEBUG "NumOfPaddCols = %d", p->NumOfPaddCols);
-		printk(KERN_DEBUG "NumOfPunctCols = %d", p->NumOfPunctCols);
-		printk(KERN_DEBUG "ErrorTSPackets = %d", p->ErrorTSPackets);
-		printk(KERN_DEBUG "TotalTSPackets = %d", p->TotalTSPackets);
-		printk(KERN_DEBUG "NumOfValidMpeTlbs = %d", p->NumOfValidMpeTlbs);
-		printk(KERN_DEBUG "NumOfInvalidMpeTlbs = %d", p->NumOfInvalidMpeTlbs);
-		printk(KERN_DEBUG "NumOfCorrectedMpeTlbs = %d", p->NumOfCorrectedMpeTlbs);
-		printk(KERN_DEBUG "BERErrorCount = %d", p->BERErrorCount);
-		printk(KERN_DEBUG "BERBitCount = %d", p->BERBitCount);
-		printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
-		printk(KERN_DEBUG "PreBER = %d", p->PreBER);
-		printk(KERN_DEBUG "CellId = %d", p->CellId);
-		printk(KERN_DEBUG "DvbhSrvIndHP = %d", p->DvbhSrvIndHP);
-		printk(KERN_DEBUG "DvbhSrvIndLP = %d", p->DvbhSrvIndLP);
-		printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived);
-	}
-
-	pReceptionData->IsDemodLocked = p->IsDemodLocked;
-
-	pReceptionData->SNR = p->SNR;
-	pReceptionData->BER = p->BER;
-	pReceptionData->BERErrorCount = p->BERErrorCount;
-	pReceptionData->InBandPwr = p->InBandPwr;
-	pReceptionData->ErrorTSPackets = p->ErrorTSPackets;
-};
-
-
-static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
-				    struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p)
-{
-	int i;
-
-	if (sms_dbg & 2) {
-		printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
-		printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
-		printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
-		printk(KERN_DEBUG "SNR = %d", p->SNR);
-		printk(KERN_DEBUG "RSSI = %d", p->RSSI);
-		printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
-		printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
-		printk(KERN_DEBUG "Frequency = %d", p->Frequency);
-		printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
-		printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
-		printk(KERN_DEBUG "ModemState = %d", p->ModemState);
-		printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
-		printk(KERN_DEBUG "SystemType = %d", p->SystemType);
-		printk(KERN_DEBUG "PartialReception = %d", p->PartialReception);
-		printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers);
-		printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
-
-		for (i = 0; i < 3; i++) {
-			printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate);
-			printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation);
-			printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER);
-			printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount);
-			printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount);
-			printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER);
-			printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER);
-			printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets);
-			printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets);
-			printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI);
-			printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments);
-			printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors);
-		}
-	}
-
-	pReceptionData->IsDemodLocked = p->IsDemodLocked;
-
-	pReceptionData->SNR = p->SNR;
-	pReceptionData->InBandPwr = p->InBandPwr;
-
-	pReceptionData->ErrorTSPackets = 0;
-	pReceptionData->BER = 0;
-	pReceptionData->BERErrorCount = 0;
-	for (i = 0; i < 3; i++) {
-		pReceptionData->BER += p->LayerInfo[i].BER;
-		pReceptionData->BERErrorCount += p->LayerInfo[i].BERErrorCount;
-		pReceptionData->ErrorTSPackets += p->LayerInfo[i].ErrorTSPackets;
-	}
-}
-
-static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
-{
-	struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
-	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p)
-			+ cb->offset);
-	u32 *pMsgData = (u32 *) phdr + 1;
-	/*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/
-	bool is_status_update = false;
-
-	smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr);
-
-	switch (phdr->msgType) {
-	case MSG_SMS_DVBT_BDA_DATA:
-		dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1),
-				 cb->size - sizeof(struct SmsMsgHdr_ST));
-		break;
-
-	case MSG_SMS_RF_TUNE_RES:
-	case MSG_SMS_ISDBT_TUNE_RES:
-		complete(&client->tune_done);
-		break;
-
-	case MSG_SMS_SIGNAL_DETECTED_IND:
-		sms_info("MSG_SMS_SIGNAL_DETECTED_IND");
-		client->sms_stat_dvb.TransmissionData.IsDemodLocked = true;
-		is_status_update = true;
-		break;
-
-	case MSG_SMS_NO_SIGNAL_IND:
-		sms_info("MSG_SMS_NO_SIGNAL_IND");
-		client->sms_stat_dvb.TransmissionData.IsDemodLocked = false;
-		is_status_update = true;
-		break;
-
-	case MSG_SMS_TRANSMISSION_IND: {
-		sms_info("MSG_SMS_TRANSMISSION_IND");
-
-		pMsgData++;
-		memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData,
-				sizeof(struct TRANSMISSION_STATISTICS_S));
-
-		/* Mo need to correct guard interval
-		 * (as opposed to old statistics message).
-		 */
-		CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData);
-		CORRECT_STAT_TRANSMISSON_MODE(
-				client->sms_stat_dvb.TransmissionData);
-		is_status_update = true;
-		break;
-	}
-	case MSG_SMS_HO_PER_SLICES_IND: {
-		struct RECEPTION_STATISTICS_S *pReceptionData =
-				&client->sms_stat_dvb.ReceptionData;
-		struct SRVM_SIGNAL_STATUS_S SignalStatusData;
-
-		/*sms_info("MSG_SMS_HO_PER_SLICES_IND");*/
-		pMsgData++;
-		SignalStatusData.result = pMsgData[0];
-		SignalStatusData.snr = pMsgData[1];
-		SignalStatusData.inBandPower = (s32) pMsgData[2];
-		SignalStatusData.tsPackets = pMsgData[3];
-		SignalStatusData.etsPackets = pMsgData[4];
-		SignalStatusData.constellation = pMsgData[5];
-		SignalStatusData.hpCode = pMsgData[6];
-		SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03;
-		SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03;
-		SignalStatusData.cellId = pMsgData[9] & 0xFFFF;
-		SignalStatusData.reason = pMsgData[10];
-		SignalStatusData.requestId = pMsgData[11];
-		pReceptionData->IsRfLocked = pMsgData[16];
-		pReceptionData->IsDemodLocked = pMsgData[17];
-		pReceptionData->ModemState = pMsgData[12];
-		pReceptionData->SNR = pMsgData[1];
-		pReceptionData->BER = pMsgData[13];
-		pReceptionData->RSSI = pMsgData[14];
-		CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData);
-
-		pReceptionData->InBandPwr = (s32) pMsgData[2];
-		pReceptionData->CarrierOffset = (s32) pMsgData[15];
-		pReceptionData->TotalTSPackets = pMsgData[3];
-		pReceptionData->ErrorTSPackets = pMsgData[4];
-
-		/* TS PER */
-		if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets)
-				> 0) {
-			pReceptionData->TS_PER = (SignalStatusData.etsPackets
-					* 100) / (SignalStatusData.tsPackets
-					+ SignalStatusData.etsPackets);
-		} else {
-			pReceptionData->TS_PER = 0;
-		}
-
-		pReceptionData->BERBitCount = pMsgData[18];
-		pReceptionData->BERErrorCount = pMsgData[19];
-
-		pReceptionData->MRC_SNR = pMsgData[20];
-		pReceptionData->MRC_InBandPwr = pMsgData[21];
-		pReceptionData->MRC_RSSI = pMsgData[22];
-
-		is_status_update = true;
-		break;
-	}
-	case MSG_SMS_GET_STATISTICS_RES: {
-		union {
-			struct SMSHOSTLIB_STATISTICS_ISDBT_ST  isdbt;
-			struct SmsMsgStatisticsInfo_ST         dvb;
-		} *p = (void *) (phdr + 1);
-		struct RECEPTION_STATISTICS_S *pReceptionData =
-				&client->sms_stat_dvb.ReceptionData;
-
-		sms_info("MSG_SMS_GET_STATISTICS_RES");
-
-		is_status_update = true;
-
-		switch (smscore_get_device_mode(client->coredev)) {
-		case DEVICE_MODE_ISDBT:
-		case DEVICE_MODE_ISDBT_BDA:
-			smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt);
-			break;
-		default:
-			smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat);
-		}
-		if (!pReceptionData->IsDemodLocked) {
-			pReceptionData->SNR = 0;
-			pReceptionData->BER = 0;
-			pReceptionData->BERErrorCount = 0;
-			pReceptionData->InBandPwr = 0;
-			pReceptionData->ErrorTSPackets = 0;
-		}
-
-		complete(&client->tune_done);
-		break;
-	}
-	default:
-		sms_info("Unhandled message %d", phdr->msgType);
-
-	}
-	smscore_putbuffer(client->coredev, cb);
-
-	if (is_status_update) {
-		if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) {
-			client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER
-				| FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-			sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK);
-			if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets
-					== 0)
-				sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK);
-			else
-				sms_board_dvb3_event(client,
-						DVB3_EVENT_UNC_ERR);
-
-		} else {
-			if (client->sms_stat_dvb.ReceptionData.IsRfLocked)
-				client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
-			else
-				client->fe_status = 0;
-			sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
-		}
-	}
-
-	return 0;
-}
-
-static void smsdvb_unregister_client(struct smsdvb_client_t *client)
-{
-	/* must be called under clientslock */
-
-	list_del(&client->entry);
-
-	smscore_unregister_client(client->smsclient);
-	dvb_unregister_frontend(&client->frontend);
-	dvb_dmxdev_release(&client->dmxdev);
-	dvb_dmx_release(&client->demux);
-	dvb_unregister_adapter(&client->adapter);
-	kfree(client);
-}
-
-static void smsdvb_onremove(void *context)
-{
-	kmutex_lock(&g_smsdvb_clientslock);
-
-	smsdvb_unregister_client((struct smsdvb_client_t *) context);
-
-	kmutex_unlock(&g_smsdvb_clientslock);
-}
-
-static int smsdvb_start_feed(struct dvb_demux_feed *feed)
-{
-	struct smsdvb_client_t *client =
-		container_of(feed->demux, struct smsdvb_client_t, demux);
-	struct SmsMsgData_ST PidMsg;
-
-	sms_debug("add pid %d(%x)",
-		  feed->pid, feed->pid);
-
-	PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	PidMsg.xMsgHeader.msgDstId = HIF_TASK;
-	PidMsg.xMsgHeader.msgFlags = 0;
-	PidMsg.xMsgHeader.msgType  = MSG_SMS_ADD_PID_FILTER_REQ;
-	PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
-	PidMsg.msgData[0] = feed->pid;
-
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
-	return smsclient_sendrequest(client->smsclient,
-				     &PidMsg, sizeof(PidMsg));
-}
-
-static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
-{
-	struct smsdvb_client_t *client =
-		container_of(feed->demux, struct smsdvb_client_t, demux);
-	struct SmsMsgData_ST PidMsg;
-
-	sms_debug("remove pid %d(%x)",
-		  feed->pid, feed->pid);
-
-	PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	PidMsg.xMsgHeader.msgDstId = HIF_TASK;
-	PidMsg.xMsgHeader.msgFlags = 0;
-	PidMsg.xMsgHeader.msgType  = MSG_SMS_REMOVE_PID_FILTER_REQ;
-	PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
-	PidMsg.msgData[0] = feed->pid;
-
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
-	return smsclient_sendrequest(client->smsclient,
-				     &PidMsg, sizeof(PidMsg));
-}
-
-static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
-					void *buffer, size_t size,
-					struct completion *completion)
-{
-	int rc;
-
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)buffer);
-	rc = smsclient_sendrequest(client->smsclient, buffer, size);
-	if (rc < 0)
-		return rc;
-
-	return wait_for_completion_timeout(completion,
-					   msecs_to_jiffies(2000)) ?
-						0 : -ETIME;
-}
-
-static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
-{
-	int rc;
-	struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ,
-				    DVBT_BDA_CONTROL_MSG_ID,
-				    HIF_TASK,
-				    sizeof(struct SmsMsgHdr_ST), 0 };
-
-	rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
-					  &client->tune_done);
-
-	return rc;
-}
-
-static inline int led_feedback(struct smsdvb_client_t *client)
-{
-	if (client->fe_status & FE_HAS_LOCK)
-		return sms_board_led_feedback(client->coredev,
-			(client->sms_stat_dvb.ReceptionData.BER
-			== 0) ? SMS_LED_HI : SMS_LED_LO);
-	else
-		return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
-}
-
-static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
-{
-	int rc;
-	struct smsdvb_client_t *client;
-	client = container_of(fe, struct smsdvb_client_t, frontend);
-
-	rc = smsdvb_send_statistics_request(client);
-
-	*stat = client->fe_status;
-
-	led_feedback(client);
-
-	return rc;
-}
-
-static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	int rc;
-	struct smsdvb_client_t *client;
-	client = container_of(fe, struct smsdvb_client_t, frontend);
-
-	rc = smsdvb_send_statistics_request(client);
-
-	*ber = client->sms_stat_dvb.ReceptionData.BER;
-
-	led_feedback(client);
-
-	return rc;
-}
-
-static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	int rc;
-
-	struct smsdvb_client_t *client;
-	client = container_of(fe, struct smsdvb_client_t, frontend);
-
-	rc = smsdvb_send_statistics_request(client);
-
-	if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95)
-		*strength = 0;
-		else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29)
-			*strength = 100;
-		else
-			*strength =
-				(client->sms_stat_dvb.ReceptionData.InBandPwr
-				+ 95) * 3 / 2;
-
-	led_feedback(client);
-
-	return rc;
-}
-
-static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	int rc;
-	struct smsdvb_client_t *client;
-	client = container_of(fe, struct smsdvb_client_t, frontend);
-
-	rc = smsdvb_send_statistics_request(client);
-
-	*snr = client->sms_stat_dvb.ReceptionData.SNR;
-
-	led_feedback(client);
-
-	return rc;
-}
-
-static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	int rc;
-	struct smsdvb_client_t *client;
-	client = container_of(fe, struct smsdvb_client_t, frontend);
-
-	rc = smsdvb_send_statistics_request(client);
-
-	*ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets;
-
-	led_feedback(client);
-
-	return rc;
-}
-
-static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
-				    struct dvb_frontend_tune_settings *tune)
-{
-	sms_debug("");
-
-	tune->min_delay_ms = 400;
-	tune->step_size = 250000;
-	tune->max_drift = 0;
-	return 0;
-}
-
-static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-
-	struct {
-		struct SmsMsgHdr_ST	Msg;
-		u32		Data[3];
-	} Msg;
-
-	int ret;
-
-	client->fe_status = FE_HAS_SIGNAL;
-	client->event_fe_state = -1;
-	client->event_unc_state = -1;
-	fe->dtv_property_cache.delivery_system = SYS_DVBT;
-
-	Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	Msg.Msg.msgDstId = HIF_TASK;
-	Msg.Msg.msgFlags = 0;
-	Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ;
-	Msg.Msg.msgLength = sizeof(Msg);
-	Msg.Data[0] = c->frequency;
-	Msg.Data[2] = 12000000;
-
-	sms_info("%s: freq %d band %d", __func__, c->frequency,
-		 c->bandwidth_hz);
-
-	switch (c->bandwidth_hz / 1000000) {
-	case 8:
-		Msg.Data[1] = BW_8_MHZ;
-		break;
-	case 7:
-		Msg.Data[1] = BW_7_MHZ;
-		break;
-	case 6:
-		Msg.Data[1] = BW_6_MHZ;
-		break;
-	case 0:
-		return -EOPNOTSUPP;
-	default:
-		return -EINVAL;
-	}
-	/* Disable LNA, if any. An error is returned if no LNA is present */
-	ret = sms_board_lna_control(client->coredev, 0);
-	if (ret == 0) {
-		fe_status_t status;
-
-		/* tune with LNA off at first */
-		ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
-						  &client->tune_done);
-
-		smsdvb_read_status(fe, &status);
-
-		if (status & FE_HAS_LOCK)
-			return ret;
-
-		/* previous tune didn't lock - enable LNA and tune again */
-		sms_board_lna_control(client->coredev, 1);
-	}
-
-	return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
-					   &client->tune_done);
-}
-
-static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-
-	struct {
-		struct SmsMsgHdr_ST	Msg;
-		u32		Data[4];
-	} Msg;
-
-	fe->dtv_property_cache.delivery_system = SYS_ISDBT;
-
-	Msg.Msg.msgSrcId  = DVBT_BDA_CONTROL_MSG_ID;
-	Msg.Msg.msgDstId  = HIF_TASK;
-	Msg.Msg.msgFlags  = 0;
-	Msg.Msg.msgType   = MSG_SMS_ISDBT_TUNE_REQ;
-	Msg.Msg.msgLength = sizeof(Msg);
-
-	if (c->isdbt_sb_segment_idx == -1)
-		c->isdbt_sb_segment_idx = 0;
-
-	switch (c->isdbt_sb_segment_count) {
-	case 3:
-		Msg.Data[1] = BW_ISDBT_3SEG;
-		break;
-	case 1:
-		Msg.Data[1] = BW_ISDBT_1SEG;
-		break;
-	case 0:	/* AUTO */
-		switch (c->bandwidth_hz / 1000000) {
-		case 8:
-		case 7:
-			c->isdbt_sb_segment_count = 3;
-			Msg.Data[1] = BW_ISDBT_3SEG;
-			break;
-		case 6:
-			c->isdbt_sb_segment_count = 1;
-			Msg.Data[1] = BW_ISDBT_1SEG;
-			break;
-		default: /* Assumes 6 MHZ bw */
-			c->isdbt_sb_segment_count = 1;
-			c->bandwidth_hz = 6000;
-			Msg.Data[1] = BW_ISDBT_1SEG;
-			break;
-		}
-		break;
-	default:
-		sms_info("Segment count %d not supported", c->isdbt_sb_segment_count);
-		return -EINVAL;
-	}
-
-	Msg.Data[0] = c->frequency;
-	Msg.Data[2] = 12000000;
-	Msg.Data[3] = c->isdbt_sb_segment_idx;
-
-	sms_info("%s: freq %d segwidth %d segindex %d\n", __func__,
-		 c->frequency, c->isdbt_sb_segment_count,
-		 c->isdbt_sb_segment_idx);
-
-	return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
-					   &client->tune_done);
-}
-
-static int smsdvb_set_frontend(struct dvb_frontend *fe)
-{
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-	struct smscore_device_t *coredev = client->coredev;
-
-	switch (smscore_get_device_mode(coredev)) {
-	case DEVICE_MODE_DVBT:
-	case DEVICE_MODE_DVBT_BDA:
-		return smsdvb_dvbt_set_frontend(fe);
-	case DEVICE_MODE_ISDBT:
-	case DEVICE_MODE_ISDBT_BDA:
-		return smsdvb_isdbt_set_frontend(fe);
-	default:
-		return -EINVAL;
-	}
-}
-
-static int smsdvb_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-	struct smscore_device_t *coredev = client->coredev;
-	struct TRANSMISSION_STATISTICS_S *td =
-		&client->sms_stat_dvb.TransmissionData;
-
-	switch (smscore_get_device_mode(coredev)) {
-	case DEVICE_MODE_DVBT:
-	case DEVICE_MODE_DVBT_BDA:
-		fep->frequency = td->Frequency;
-
-		switch (td->Bandwidth) {
-		case 6:
-			fep->bandwidth_hz = 6000000;
-			break;
-		case 7:
-			fep->bandwidth_hz = 7000000;
-			break;
-		case 8:
-			fep->bandwidth_hz = 8000000;
-			break;
-		}
-
-		switch (td->TransmissionMode) {
-		case 2:
-			fep->transmission_mode = TRANSMISSION_MODE_2K;
-			break;
-		case 8:
-			fep->transmission_mode = TRANSMISSION_MODE_8K;
-		}
-
-		switch (td->GuardInterval) {
-		case 0:
-			fep->guard_interval = GUARD_INTERVAL_1_32;
-			break;
-		case 1:
-			fep->guard_interval = GUARD_INTERVAL_1_16;
-			break;
-		case 2:
-			fep->guard_interval = GUARD_INTERVAL_1_8;
-			break;
-		case 3:
-			fep->guard_interval = GUARD_INTERVAL_1_4;
-			break;
-		}
-
-		switch (td->CodeRate) {
-		case 0:
-			fep->code_rate_HP = FEC_1_2;
-			break;
-		case 1:
-			fep->code_rate_HP = FEC_2_3;
-			break;
-		case 2:
-			fep->code_rate_HP = FEC_3_4;
-			break;
-		case 3:
-			fep->code_rate_HP = FEC_5_6;
-			break;
-		case 4:
-			fep->code_rate_HP = FEC_7_8;
-			break;
-		}
-
-		switch (td->LPCodeRate) {
-		case 0:
-			fep->code_rate_LP = FEC_1_2;
-			break;
-		case 1:
-			fep->code_rate_LP = FEC_2_3;
-			break;
-		case 2:
-			fep->code_rate_LP = FEC_3_4;
-			break;
-		case 3:
-			fep->code_rate_LP = FEC_5_6;
-			break;
-		case 4:
-			fep->code_rate_LP = FEC_7_8;
-			break;
-		}
-
-		switch (td->Constellation) {
-		case 0:
-			fep->modulation = QPSK;
-			break;
-		case 1:
-			fep->modulation = QAM_16;
-			break;
-		case 2:
-			fep->modulation = QAM_64;
-			break;
-		}
-
-		switch (td->Hierarchy) {
-		case 0:
-			fep->hierarchy = HIERARCHY_NONE;
-			break;
-		case 1:
-			fep->hierarchy = HIERARCHY_1;
-			break;
-		case 2:
-			fep->hierarchy = HIERARCHY_2;
-			break;
-		case 3:
-			fep->hierarchy = HIERARCHY_4;
-			break;
-		}
-
-		fep->inversion = INVERSION_AUTO;
-		break;
-	case DEVICE_MODE_ISDBT:
-	case DEVICE_MODE_ISDBT_BDA:
-		fep->frequency = td->Frequency;
-		fep->bandwidth_hz = 6000000;
-		/* todo: retrive the other parameters */
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int smsdvb_init(struct dvb_frontend *fe)
-{
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-
-	sms_board_power(client->coredev, 1);
-
-	sms_board_dvb3_event(client, DVB3_EVENT_INIT);
-	return 0;
-}
-
-static int smsdvb_sleep(struct dvb_frontend *fe)
-{
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-
-	sms_board_led_feedback(client->coredev, SMS_LED_OFF);
-	sms_board_power(client->coredev, 0);
-
-	sms_board_dvb3_event(client, DVB3_EVENT_SLEEP);
-
-	return 0;
-}
-
-static void smsdvb_release(struct dvb_frontend *fe)
-{
-	/* do nothing */
-}
-
-static struct dvb_frontend_ops smsdvb_fe_ops = {
-	.info = {
-		.name			= "Siano Mobile Digital MDTV Receiver",
-		.frequency_min		= 44250000,
-		.frequency_max		= 867250000,
-		.frequency_stepsize	= 250000,
-		.caps = FE_CAN_INVERSION_AUTO |
-			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
-			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_RECOVER |
-			FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release = smsdvb_release,
-
-	.set_frontend = smsdvb_set_frontend,
-	.get_frontend = smsdvb_get_frontend,
-	.get_tune_settings = smsdvb_get_tune_settings,
-
-	.read_status = smsdvb_read_status,
-	.read_ber = smsdvb_read_ber,
-	.read_signal_strength = smsdvb_read_signal_strength,
-	.read_snr = smsdvb_read_snr,
-	.read_ucblocks = smsdvb_read_ucblocks,
-
-	.init = smsdvb_init,
-	.sleep = smsdvb_sleep,
-};
-
-static int smsdvb_hotplug(struct smscore_device_t *coredev,
-			  struct device *device, int arrival)
-{
-	struct smsclient_params_t params;
-	struct smsdvb_client_t *client;
-	int rc;
-
-	/* device removal handled by onremove callback */
-	if (!arrival)
-		return 0;
-	client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
-	if (!client) {
-		sms_err("kmalloc() failed");
-		return -ENOMEM;
-	}
-
-	/* register dvb adapter */
-	rc = dvb_register_adapter(&client->adapter,
-				  sms_get_board(
-					smscore_get_board_id(coredev))->name,
-				  THIS_MODULE, device, adapter_nr);
-	if (rc < 0) {
-		sms_err("dvb_register_adapter() failed %d", rc);
-		goto adapter_error;
-	}
-
-	/* init dvb demux */
-	client->demux.dmx.capabilities = DMX_TS_FILTERING;
-	client->demux.filternum = 32; /* todo: nova ??? */
-	client->demux.feednum = 32;
-	client->demux.start_feed = smsdvb_start_feed;
-	client->demux.stop_feed = smsdvb_stop_feed;
-
-	rc = dvb_dmx_init(&client->demux);
-	if (rc < 0) {
-		sms_err("dvb_dmx_init failed %d", rc);
-		goto dvbdmx_error;
-	}
-
-	/* init dmxdev */
-	client->dmxdev.filternum = 32;
-	client->dmxdev.demux = &client->demux.dmx;
-	client->dmxdev.capabilities = 0;
-
-	rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
-	if (rc < 0) {
-		sms_err("dvb_dmxdev_init failed %d", rc);
-		goto dmxdev_error;
-	}
-
-	/* init and register frontend */
-	memcpy(&client->frontend.ops, &smsdvb_fe_ops,
-	       sizeof(struct dvb_frontend_ops));
-
-	switch (smscore_get_device_mode(coredev)) {
-	case DEVICE_MODE_DVBT:
-	case DEVICE_MODE_DVBT_BDA:
-		client->frontend.ops.delsys[0] = SYS_DVBT;
-		break;
-	case DEVICE_MODE_ISDBT:
-	case DEVICE_MODE_ISDBT_BDA:
-		client->frontend.ops.delsys[0] = SYS_ISDBT;
-		break;
-	}
-
-	rc = dvb_register_frontend(&client->adapter, &client->frontend);
-	if (rc < 0) {
-		sms_err("frontend registration failed %d", rc);
-		goto frontend_error;
-	}
-
-	params.initial_id = 1;
-	params.data_type = MSG_SMS_DVBT_BDA_DATA;
-	params.onresponse_handler = smsdvb_onresponse;
-	params.onremove_handler = smsdvb_onremove;
-	params.context = client;
-
-	rc = smscore_register_client(coredev, &params, &client->smsclient);
-	if (rc < 0) {
-		sms_err("smscore_register_client() failed %d", rc);
-		goto client_error;
-	}
-
-	client->coredev = coredev;
-
-	init_completion(&client->tune_done);
-
-	kmutex_lock(&g_smsdvb_clientslock);
-
-	list_add(&client->entry, &g_smsdvb_clients);
-
-	kmutex_unlock(&g_smsdvb_clientslock);
-
-	client->event_fe_state = -1;
-	client->event_unc_state = -1;
-	sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG);
-
-	sms_info("success");
-	sms_board_setup(coredev);
-
-	return 0;
-
-client_error:
-	dvb_unregister_frontend(&client->frontend);
-
-frontend_error:
-	dvb_dmxdev_release(&client->dmxdev);
-
-dmxdev_error:
-	dvb_dmx_release(&client->demux);
-
-dvbdmx_error:
-	dvb_unregister_adapter(&client->adapter);
-
-adapter_error:
-	kfree(client);
-	return rc;
-}
-
-static int __init smsdvb_module_init(void)
-{
-	int rc;
-
-	INIT_LIST_HEAD(&g_smsdvb_clients);
-	kmutex_init(&g_smsdvb_clientslock);
-
-	rc = smscore_register_hotplug(smsdvb_hotplug);
-
-	sms_debug("");
-
-	return rc;
-}
-
-static void __exit smsdvb_module_exit(void)
-{
-	smscore_unregister_hotplug(smsdvb_hotplug);
-
-	kmutex_lock(&g_smsdvb_clientslock);
-
-	while (!list_empty(&g_smsdvb_clients))
-	       smsdvb_unregister_client(
-			(struct smsdvb_client_t *) g_smsdvb_clients.next);
-
-	kmutex_unlock(&g_smsdvb_clientslock);
-}
-
-module_init(smsdvb_module_init);
-module_exit(smsdvb_module_exit);
-
-MODULE_DESCRIPTION("SMS DVB subsystem adaptation module");
-MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
-MODULE_LICENSE("GPL");

+ 130 - 0
drivers/media/common/siano/smsdvb.h

@@ -0,0 +1,130 @@
+/***********************************************************************
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+
+ *  This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ***********************************************************************/
+
+struct smsdvb_debugfs;
+struct smsdvb_client_t;
+
+typedef void (*sms_prt_dvb_stats_t)(struct smsdvb_debugfs *debug_data,
+				    struct sms_stats *p);
+
+typedef void (*sms_prt_isdb_stats_t)(struct smsdvb_debugfs *debug_data,
+				     struct sms_isdbt_stats *p);
+
+typedef void (*sms_prt_isdb_stats_ex_t)
+			(struct smsdvb_debugfs *debug_data,
+			 struct sms_isdbt_stats_ex *p);
+
+
+struct smsdvb_client_t {
+	struct list_head entry;
+
+	struct smscore_device_t *coredev;
+	struct smscore_client_t *smsclient;
+
+	struct dvb_adapter      adapter;
+	struct dvb_demux        demux;
+	struct dmxdev           dmxdev;
+	struct dvb_frontend     frontend;
+
+	fe_status_t             fe_status;
+
+	struct completion       tune_done;
+	struct completion       stats_done;
+
+	int last_per;
+
+	int legacy_ber, legacy_per;
+
+	int event_fe_state;
+	int event_unc_state;
+
+	unsigned long		get_stats_jiffies;
+
+	int			feed_users;
+	bool			has_tuned;
+
+	/* stats debugfs data */
+	struct dentry		*debugfs;
+
+	struct smsdvb_debugfs	*debug_data;
+
+	sms_prt_dvb_stats_t	prt_dvb_stats;
+	sms_prt_isdb_stats_t	prt_isdb_stats;
+	sms_prt_isdb_stats_ex_t	prt_isdb_stats_ex;
+};
+
+/*
+ * This struct is a mix of struct sms_rx_stats_ex and
+ * struct sms_srvm_signal_status.
+ * It was obtained by comparing the way it was filled by the original code
+ */
+struct RECEPTION_STATISTICS_PER_SLICES_S {
+	u32 result;
+	u32 snr;
+	s32 in_band_power;
+	u32 ts_packets;
+	u32 ets_packets;
+	u32 constellation;
+	u32 hp_code;
+	u32 tps_srv_ind_lp;
+	u32 tps_srv_ind_hp;
+	u32 cell_id;
+	u32 reason;
+	u32 request_id;
+	u32 modem_state;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
+
+	u32 ber;		/* Post Viterbi BER [1E-5] */
+	s32 RSSI;		/* dBm */
+	s32 carrier_offset;	/* Carrier Offset in bin/1024 */
+
+	u32 is_rf_locked;		/* 0 - not locked, 1 - locked */
+	u32 is_demod_locked;	/* 0 - not locked, 1 - locked */
+
+	u32 ber_bit_count;	/* Total number of SYNC bits. */
+	u32 ber_error_count;	/* Number of erronous SYNC bits. */
+
+	s32 MRC_SNR;		/* dB */
+	s32 mrc_in_band_pwr;	/* In band power in dBM */
+	s32 MRC_RSSI;		/* dBm */
+};
+
+/* From smsdvb-debugfs.c */
+#ifdef CONFIG_SMS_SIANO_DEBUGFS
+
+int smsdvb_debugfs_create(struct smsdvb_client_t *client);
+void smsdvb_debugfs_release(struct smsdvb_client_t *client);
+int smsdvb_debugfs_register(void);
+void smsdvb_debugfs_unregister(void);
+
+#else
+
+static inline int smsdvb_debugfs_create(struct smsdvb_client_t *client)
+{
+	return 0;
+}
+
+static inline void smsdvb_debugfs_release(struct smsdvb_client_t *client) {}
+
+static inline int smsdvb_debugfs_register(void)
+{
+	return 0;
+};
+
+static inline void smsdvb_debugfs_unregister(void) {};
+
+#endif
+

+ 22 - 22
drivers/media/common/siano/smsendian.c

@@ -28,23 +28,23 @@
 void smsendian_handle_tx_message(void *buffer)
 {
 #ifdef __BIG_ENDIAN
-	struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer;
+	struct sms_msg_data *msg = (struct sms_msg_data *)buffer;
 	int i;
-	int msgWords;
+	int msg_words;
 
-	switch (msg->xMsgHeader.msgType) {
+	switch (msg->x_msg_header.msg_type) {
 	case MSG_SMS_DATA_DOWNLOAD_REQ:
 	{
-		msg->msgData[0] = le32_to_cpu(msg->msgData[0]);
+		msg->msg_data[0] = le32_to_cpu(msg->msg_data[0]);
 		break;
 	}
 
 	default:
-		msgWords = (msg->xMsgHeader.msgLength -
-				sizeof(struct SmsMsgHdr_ST))/4;
+		msg_words = (msg->x_msg_header.msg_length -
+				sizeof(struct sms_msg_hdr))/4;
 
-		for (i = 0; i < msgWords; i++)
-			msg->msgData[i] = le32_to_cpu(msg->msgData[i]);
+		for (i = 0; i < msg_words; i++)
+			msg->msg_data[i] = le32_to_cpu(msg->msg_data[i]);
 
 		break;
 	}
@@ -55,16 +55,16 @@ EXPORT_SYMBOL_GPL(smsendian_handle_tx_message);
 void smsendian_handle_rx_message(void *buffer)
 {
 #ifdef __BIG_ENDIAN
-	struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer;
+	struct sms_msg_data *msg = (struct sms_msg_data *)buffer;
 	int i;
-	int msgWords;
+	int msg_words;
 
-	switch (msg->xMsgHeader.msgType) {
+	switch (msg->x_msg_header.msg_type) {
 	case MSG_SMS_GET_VERSION_EX_RES:
 	{
-		struct SmsVersionRes_ST *ver =
-			(struct SmsVersionRes_ST *) msg;
-		ver->ChipModel = le16_to_cpu(ver->ChipModel);
+		struct sms_version_res *ver =
+			(struct sms_version_res *) msg;
+		ver->chip_model = le16_to_cpu(ver->chip_model);
 		break;
 	}
 
@@ -77,11 +77,11 @@ void smsendian_handle_rx_message(void *buffer)
 
 	default:
 	{
-		msgWords = (msg->xMsgHeader.msgLength -
-				sizeof(struct SmsMsgHdr_ST))/4;
+		msg_words = (msg->x_msg_header.msg_length -
+				sizeof(struct sms_msg_hdr))/4;
 
-		for (i = 0; i < msgWords; i++)
-			msg->msgData[i] = le32_to_cpu(msg->msgData[i]);
+		for (i = 0; i < msg_words; i++)
+			msg->msg_data[i] = le32_to_cpu(msg->msg_data[i]);
 
 		break;
 	}
@@ -93,11 +93,11 @@ EXPORT_SYMBOL_GPL(smsendian_handle_rx_message);
 void smsendian_handle_message_header(void *msg)
 {
 #ifdef __BIG_ENDIAN
-	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)msg;
+	struct sms_msg_hdr *phdr = (struct sms_msg_hdr *)msg;
 
-	phdr->msgType = le16_to_cpu(phdr->msgType);
-	phdr->msgLength = le16_to_cpu(phdr->msgLength);
-	phdr->msgFlags = le16_to_cpu(phdr->msgFlags);
+	phdr->msg_type = le16_to_cpu(phdr->msg_type);
+	phdr->msg_length = le16_to_cpu(phdr->msg_length);
+	phdr->msg_flags = le16_to_cpu(phdr->msg_flags);
 #endif /* __BIG_ENDIAN */
 }
 EXPORT_SYMBOL_GPL(smsendian_handle_message_header);

+ 0 - 1
drivers/media/common/siano/smsir.h

@@ -40,7 +40,6 @@ struct ir_t {
 	char phys[32];
 
 	char *rc_codes;
-	u64 protocol;
 
 	u32 timeout;
 	u32 controller;

+ 0 - 39
drivers/media/dvb-core/demux.h

@@ -83,45 +83,6 @@ enum dmx_success {
 #define TS_DEMUX        8   /* in case TS_PACKET is set, send the TS to
 			       the demux device, not to the dvr device */
 
-/* PES type for filters which write to built-in decoder */
-/* these should be kept identical to the types in dmx.h */
-
-enum dmx_ts_pes
-{  /* also send packets to decoder (if it exists) */
-	DMX_TS_PES_AUDIO0,
-	DMX_TS_PES_VIDEO0,
-	DMX_TS_PES_TELETEXT0,
-	DMX_TS_PES_SUBTITLE0,
-	DMX_TS_PES_PCR0,
-
-	DMX_TS_PES_AUDIO1,
-	DMX_TS_PES_VIDEO1,
-	DMX_TS_PES_TELETEXT1,
-	DMX_TS_PES_SUBTITLE1,
-	DMX_TS_PES_PCR1,
-
-	DMX_TS_PES_AUDIO2,
-	DMX_TS_PES_VIDEO2,
-	DMX_TS_PES_TELETEXT2,
-	DMX_TS_PES_SUBTITLE2,
-	DMX_TS_PES_PCR2,
-
-	DMX_TS_PES_AUDIO3,
-	DMX_TS_PES_VIDEO3,
-	DMX_TS_PES_TELETEXT3,
-	DMX_TS_PES_SUBTITLE3,
-	DMX_TS_PES_PCR3,
-
-	DMX_TS_PES_OTHER
-};
-
-#define DMX_TS_PES_AUDIO    DMX_TS_PES_AUDIO0
-#define DMX_TS_PES_VIDEO    DMX_TS_PES_VIDEO0
-#define DMX_TS_PES_TELETEXT DMX_TS_PES_TELETEXT0
-#define DMX_TS_PES_SUBTITLE DMX_TS_PES_SUBTITLE0
-#define DMX_TS_PES_PCR      DMX_TS_PES_PCR0
-
-
 struct dmx_ts_feed {
 	int is_filtering; /* Set to non-zero when filtering in progress */
 	struct dmx_demux *parent; /* Back-pointer */

+ 3 - 2
drivers/media/dvb-core/dmxdev.c

@@ -569,7 +569,7 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev,
 	dmx_output_t otype;
 	int ret;
 	int ts_type;
-	dmx_pes_type_t ts_pes;
+	enum dmx_ts_pes ts_pes;
 	struct dmx_ts_feed *tsfeed;
 
 	feed->ts = NULL;
@@ -852,7 +852,8 @@ static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
 				 struct dmxdev_filter *dmxdevfilter,
 				 struct dmx_sct_filter_params *params)
 {
-	dprintk("function : %s\n", __func__);
+	dprintk("function : %s, PID=0x%04x, flags=%02x, timeout=%d\n",
+		__func__, params->pid, params->flags, params->timeout);
 
 	dvb_dmxdev_filter_stop(dmxdevfilter);
 

+ 1 - 2
drivers/media/dvb-core/dvb-usb-ids.h

@@ -124,8 +124,7 @@
 #define USB_PID_DIBCOM_STK7770P				0x1e80
 #define USB_PID_DIBCOM_NIM7090				0x1bb2
 #define USB_PID_DIBCOM_TFE7090PVR			0x1bb4
-#define USB_PID_DIBCOM_TFE7090E				0x1bb7
-#define USB_PID_DIBCOM_TFE7790E				0x1e6e
+#define USB_PID_DIBCOM_TFE7790P				0x1e6e
 #define USB_PID_DIBCOM_NIM9090M				0x2383
 #define USB_PID_DIBCOM_NIM9090MD			0x2384
 #define USB_PID_DPOSH_M9206_COLD			0x9206

+ 16 - 14
drivers/media/dvb-core/dvb_demux.c

@@ -440,20 +440,22 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
 		if (!dvb_demux_feed_err_pkts)
 			return;
 	} else /* if TEI bit is set, pid may be wrong- skip pkt counter */
-	if (demux->cnt_storage && dvb_demux_tscheck) {
-		/* check pkt counter */
-		if (pid < MAX_PID) {
-			if ((buf[3] & 0xf) != demux->cnt_storage[pid])
-				dprintk_tscheck("TS packet counter mismatch. "
-						"PID=0x%x expected 0x%x "
-						"got 0x%x\n",
+		if (demux->cnt_storage && dvb_demux_tscheck) {
+			/* check pkt counter */
+			if (pid < MAX_PID) {
+				if (buf[3] & 0x10)
+					demux->cnt_storage[pid] =
+						(demux->cnt_storage[pid] + 1) & 0xf;
+
+				if ((buf[3] & 0xf) != demux->cnt_storage[pid]) {
+					dprintk_tscheck("TS packet counter mismatch. PID=0x%x expected 0x%x got 0x%x\n",
 						pid, demux->cnt_storage[pid],
 						buf[3] & 0xf);
-
-			demux->cnt_storage[pid] = ((buf[3] & 0xf) + 1)&0xf;
+					demux->cnt_storage[pid] = buf[3] & 0xf;
+				}
+			}
+			/* end check */
 		}
-		/* end check */
-	}
 
 	list_for_each_entry(feed, &demux->feed_list, list_head) {
 		if ((feed->pid != pid) && (feed->pid != 0x2000))
@@ -672,7 +674,7 @@ static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type,
 		return -ERESTARTSYS;
 
 	if (ts_type & TS_DECODER) {
-		if (pes_type >= DMX_TS_PES_OTHER) {
+		if (pes_type >= DMX_PES_OTHER) {
 			mutex_unlock(&demux->mutex);
 			return -EINVAL;
 		}
@@ -844,7 +846,7 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx,
 
 	feed->pid = 0xffff;
 
-	if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER)
+	if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_PES_OTHER)
 		demux->pesfilter[feed->pes_type] = NULL;
 
 	mutex_unlock(&demux->mutex);
@@ -1266,7 +1268,7 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
 
 	INIT_LIST_HEAD(&dvbdemux->frontend_list);
 
-	for (i = 0; i < DMX_TS_PES_OTHER; i++) {
+	for (i = 0; i < DMX_PES_OTHER; i++) {
 		dvbdemux->pesfilter[i] = NULL;
 		dvbdemux->pids[i] = 0xffff;
 	}

+ 2 - 2
drivers/media/dvb-core/dvb_demux.h

@@ -119,8 +119,8 @@ struct dvb_demux {
 
 	struct list_head frontend_list;
 
-	struct dvb_demux_feed *pesfilter[DMX_TS_PES_OTHER];
-	u16 pids[DMX_TS_PES_OTHER];
+	struct dvb_demux_feed *pesfilter[DMX_PES_OTHER];
+	u16 pids[DMX_PES_OTHER];
 	int playing;
 	int recording;
 

+ 184 - 149
drivers/media/dvb-core/dvb_frontend.c

@@ -920,7 +920,7 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
 	u32 delsys;
 
 	delsys = c->delivery_system;
-	memset(c, 0, sizeof(struct dtv_frontend_properties));
+	memset(c, 0, offsetof(struct dtv_frontend_properties, strength));
 	c->delivery_system = delsys;
 
 	c->state = DTV_CLEAR;
@@ -1509,9 +1509,74 @@ static bool is_dvbv3_delsys(u32 delsys)
 	return status;
 }
 
-static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
+/**
+ * emulate_delivery_system - emulate a DVBv5 delivery system with a DVBv3 type
+ * @fe:			struct frontend;
+ * @delsys:			DVBv5 type that will be used for emulation
+ *
+ * Provides emulation for delivery systems that are compatible with the old
+ * DVBv3 call. Among its usages, it provices support for ISDB-T, and allows
+ * using a DVB-S2 only frontend just like it were a DVB-S, if the frontent
+ * parameters are compatible with DVB-S spec.
+ */
+static int emulate_delivery_system(struct dvb_frontend *fe, u32 delsys)
 {
-	int ncaps, i;
+	int i;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	c->delivery_system = delsys;
+
+	/*
+	 * If the call is for ISDB-T, put it into full-seg, auto mode, TV
+	 */
+	if (c->delivery_system == SYS_ISDBT) {
+		dev_dbg(fe->dvb->device,
+			"%s: Using defaults for SYS_ISDBT\n",
+			__func__);
+
+		if (!c->bandwidth_hz)
+			c->bandwidth_hz = 6000000;
+
+		c->isdbt_partial_reception = 0;
+		c->isdbt_sb_mode = 0;
+		c->isdbt_sb_subchannel = 0;
+		c->isdbt_sb_segment_idx = 0;
+		c->isdbt_sb_segment_count = 0;
+		c->isdbt_layer_enabled = 7;
+		for (i = 0; i < 3; i++) {
+			c->layer[i].fec = FEC_AUTO;
+			c->layer[i].modulation = QAM_AUTO;
+			c->layer[i].interleaving = 0;
+			c->layer[i].segment_count = 0;
+		}
+	}
+	dev_dbg(fe->dvb->device, "%s: change delivery system on cache to %d\n",
+		__func__, c->delivery_system);
+
+	return 0;
+}
+
+/**
+ * dvbv5_set_delivery_system - Sets the delivery system for a DVBv5 API call
+ * @fe:			frontend struct
+ * @desired_system:	delivery system requested by the user
+ *
+ * A DVBv5 call know what's the desired system it wants. So, set it.
+ *
+ * There are, however, a few known issues with early DVBv5 applications that
+ * are also handled by this logic:
+ *
+ * 1) Some early apps use SYS_UNDEFINED as the desired delivery system.
+ *    This is an API violation, but, as we don't want to break userspace,
+ *    convert it to the first supported delivery system.
+ * 2) Some apps might be using a DVBv5 call in a wrong way, passing, for
+ *    example, SYS_DVBT instead of SYS_ISDBT. This is because early usage of
+ *    ISDB-T provided backward compat with DVB-T.
+ */
+static int dvbv5_set_delivery_system(struct dvb_frontend *fe,
+				     u32 desired_system)
+{
+	int ncaps;
 	u32 delsys = SYS_UNDEFINED;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	enum dvbv3_emulation_type type;
@@ -1522,166 +1587,136 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
 	 * assume that the application wants to use the first supported
 	 * delivery system.
 	 */
-	if (c->delivery_system == SYS_UNDEFINED)
-	        c->delivery_system = fe->ops.delsys[0];
+	if (desired_system == SYS_UNDEFINED)
+		desired_system = fe->ops.delsys[0];
 
-	if (desired_system == SYS_UNDEFINED) {
-		/*
-		 * A DVBv3 call doesn't know what's the desired system.
-		 * Also, DVBv3 applications don't know that ops.info->type
-		 * could be changed, and they simply dies when it doesn't
-		 * match.
-		 * So, don't change the current delivery system, as it
-		 * may be trying to do the wrong thing, like setting an
-		 * ISDB-T frontend as DVB-T. Instead, find the closest
-		 * DVBv3 system that matches the delivery system.
-		 */
-		if (is_dvbv3_delsys(c->delivery_system)) {
+	/*
+	 * This is a DVBv5 call. So, it likely knows the supported
+	 * delivery systems. So, check if the desired delivery system is
+	 * supported
+	 */
+	ncaps = 0;
+	while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+		if (fe->ops.delsys[ncaps] == desired_system) {
+			c->delivery_system = desired_system;
 			dev_dbg(fe->dvb->device,
-					"%s: Using delivery system to %d\n",
-					__func__, c->delivery_system);
-			return 0;
-		}
-		type = dvbv3_type(c->delivery_system);
-		switch (type) {
-		case DVBV3_QPSK:
-			desired_system = SYS_DVBS;
-			break;
-		case DVBV3_QAM:
-			desired_system = SYS_DVBC_ANNEX_A;
-			break;
-		case DVBV3_ATSC:
-			desired_system = SYS_ATSC;
-			break;
-		case DVBV3_OFDM:
-			desired_system = SYS_DVBT;
-			break;
-		default:
-			dev_dbg(fe->dvb->device, "%s: This frontend doesn't support DVBv3 calls\n",
-					__func__);
-			return -EINVAL;
-		}
-		/*
-		 * Get a delivery system that is compatible with DVBv3
-		 * NOTE: in order for this to work with softwares like Kaffeine that
-		 *	uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to
-		 *	DVB-S, drivers that support both should put the SYS_DVBS entry
-		 *	before the SYS_DVBS2, otherwise it won't switch back to DVB-S.
-		 *	The real fix is that userspace applications should not use DVBv3
-		 *	and not trust on calling FE_SET_FRONTEND to switch the delivery
-		 *	system.
-		 */
-		ncaps = 0;
-		while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
-			if (fe->ops.delsys[ncaps] == desired_system) {
-				delsys = desired_system;
-				break;
-			}
-			ncaps++;
-		}
-		if (delsys == SYS_UNDEFINED) {
-			dev_dbg(fe->dvb->device, "%s: Couldn't find a delivery system that matches %d\n",
+					"%s: Changing delivery system to %d\n",
 					__func__, desired_system);
+			return 0;
 		}
-	} else {
-		/*
-		 * This is a DVBv5 call. So, it likely knows the supported
-		 * delivery systems.
-		 */
+		ncaps++;
+	}
 
-		/* Check if the desired delivery system is supported */
-		ncaps = 0;
-		while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
-			if (fe->ops.delsys[ncaps] == desired_system) {
-				c->delivery_system = desired_system;
-				dev_dbg(fe->dvb->device,
-						"%s: Changing delivery system to %d\n",
-						__func__, desired_system);
-				return 0;
-			}
-			ncaps++;
-		}
-		type = dvbv3_type(desired_system);
+	/*
+	 * The requested delivery system isn't supported. Maybe userspace
+	 * is requesting a DVBv3 compatible delivery system.
+	 *
+	 * The emulation only works if the desired system is one of the
+	 * delivery systems supported by DVBv3 API
+	 */
+	if (!is_dvbv3_delsys(desired_system)) {
+		dev_dbg(fe->dvb->device,
+			"%s: Delivery system %d not supported.\n",
+			__func__, desired_system);
+		return -EINVAL;
+	}
 
-		/*
-		 * The delivery system is not supported. See if it can be
-		 * emulated.
-		 * The emulation only works if the desired system is one of the
-		 * DVBv3 delivery systems
-		 */
-		if (!is_dvbv3_delsys(desired_system)) {
-			dev_dbg(fe->dvb->device,
-					"%s: can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n",
-					__func__);
-			return -EINVAL;
-		}
+	type = dvbv3_type(desired_system);
 
-		/*
-		 * Get the last non-DVBv3 delivery system that has the same type
-		 * of the desired system
-		 */
-		ncaps = 0;
-		while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
-			if ((dvbv3_type(fe->ops.delsys[ncaps]) == type) &&
-			    !is_dvbv3_delsys(fe->ops.delsys[ncaps]))
-				delsys = fe->ops.delsys[ncaps];
-			ncaps++;
-		}
-		/* There's nothing compatible with the desired delivery system */
-		if (delsys == SYS_UNDEFINED) {
-			dev_dbg(fe->dvb->device,
-					"%s: Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n",
-					__func__);
-			return -EINVAL;
-		}
+	/*
+	* Get the last non-DVBv3 delivery system that has the same type
+	* of the desired system
+	*/
+	ncaps = 0;
+	while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+		if (dvbv3_type(fe->ops.delsys[ncaps]) == type)
+			delsys = fe->ops.delsys[ncaps];
+		ncaps++;
 	}
 
-	c->delivery_system = delsys;
+	/* There's nothing compatible with the desired delivery system */
+	if (delsys == SYS_UNDEFINED) {
+		dev_dbg(fe->dvb->device,
+			"%s: Delivery system %d not supported on emulation mode.\n",
+			__func__, desired_system);
+		return -EINVAL;
+	}
+
+	dev_dbg(fe->dvb->device,
+		"%s: Using delivery system %d emulated as if it were %d\n",
+		__func__, delsys, desired_system);
+
+	return emulate_delivery_system(fe, desired_system);
+}
+
+/**
+ * dvbv3_set_delivery_system - Sets the delivery system for a DVBv3 API call
+ * @fe:	frontend struct
+ *
+ * A DVBv3 call doesn't know what's the desired system it wants. It also
+ * doesn't allow to switch between different types. Due to that, userspace
+ * should use DVBv5 instead.
+ * However, in order to avoid breaking userspace API, limited backward
+ * compatibility support is provided.
+ *
+ * There are some delivery systems that are incompatible with DVBv3 calls.
+ *
+ * This routine should work fine for frontends that support just one delivery
+ * system.
+ *
+ * For frontends that support multiple frontends:
+ * 1) It defaults to use the first supported delivery system. There's an
+ *    userspace application that allows changing it at runtime;
+ *
+ * 2) If the current delivery system is not compatible with DVBv3, it gets
+ *    the first one that it is compatible.
+ *
+ * NOTE: in order for this to work with applications like Kaffeine that
+ *	uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to
+ *	DVB-S, drivers that support both DVB-S and DVB-S2 should have the
+ *	SYS_DVBS entry before the SYS_DVBS2, otherwise it won't switch back
+ *	to DVB-S.
+ */
+static int dvbv3_set_delivery_system(struct dvb_frontend *fe)
+{
+	int ncaps;
+	u32 delsys = SYS_UNDEFINED;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	/* If not set yet, defaults to the first supported delivery system */
+	if (c->delivery_system == SYS_UNDEFINED)
+		c->delivery_system = fe->ops.delsys[0];
 
 	/*
-	 * The DVBv3 or DVBv5 call is requesting a different system. So,
-	 * emulation is needed.
-	 *
-	 * Emulate newer delivery systems like ISDBT, DVBT and DTMB
-	 * for older DVBv5 applications. The emulation will try to use
-	 * the auto mode for most things, and will assume that the desired
-	 * delivery system is the last one at the ops.delsys[] array
+	 * Trivial case: just use the current one, if it already a DVBv3
+	 * delivery system
 	 */
-	dev_dbg(fe->dvb->device,
-			"%s: Using delivery system %d emulated as if it were a %d\n",
-			__func__, delsys, desired_system);
+	if (is_dvbv3_delsys(c->delivery_system)) {
+		dev_dbg(fe->dvb->device,
+				"%s: Using delivery system to %d\n",
+				__func__, c->delivery_system);
+		return 0;
+	}
 
 	/*
-	 * For now, handles ISDB-T calls. More code may be needed here for the
-	 * other emulated stuff
+	 * Seek for the first delivery system that it is compatible with a
+	 * DVBv3 standard
 	 */
-	if (type == DVBV3_OFDM) {
-		if (c->delivery_system == SYS_ISDBT) {
-			dev_dbg(fe->dvb->device,
-					"%s: Using defaults for SYS_ISDBT\n",
-					__func__);
-
-			if (!c->bandwidth_hz)
-				c->bandwidth_hz = 6000000;
-
-			c->isdbt_partial_reception = 0;
-			c->isdbt_sb_mode = 0;
-			c->isdbt_sb_subchannel = 0;
-			c->isdbt_sb_segment_idx = 0;
-			c->isdbt_sb_segment_count = 0;
-			c->isdbt_layer_enabled = 0;
-			for (i = 0; i < 3; i++) {
-				c->layer[i].fec = FEC_AUTO;
-				c->layer[i].modulation = QAM_AUTO;
-				c->layer[i].interleaving = 0;
-				c->layer[i].segment_count = 0;
-			}
+	ncaps = 0;
+	while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+		if (dvbv3_type(fe->ops.delsys[ncaps]) != DVBV3_UNKNOWN) {
+			delsys = fe->ops.delsys[ncaps];
+			break;
 		}
+		ncaps++;
 	}
-	dev_dbg(fe->dvb->device, "%s: change delivery system on cache to %d\n",
-			__func__, c->delivery_system);
-
-	return 0;
+	if (delsys == SYS_UNDEFINED) {
+		dev_dbg(fe->dvb->device,
+			"%s: Couldn't find a delivery system that works with FE_SET_FRONTEND\n",
+			__func__);
+		return -EINVAL;
+	}
+	return emulate_delivery_system(fe, delsys);
 }
 
 static int dtv_property_process_set(struct dvb_frontend *fe,
@@ -1742,7 +1777,7 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
 		c->rolloff = tvp->u.data;
 		break;
 	case DTV_DELIVERY_SYSTEM:
-		r = set_delivery_system(fe, tvp->u.data);
+		r = dvbv5_set_delivery_system(fe, tvp->u.data);
 		break;
 	case DTV_VOLTAGE:
 		c->voltage = tvp->u.data;
@@ -2335,7 +2370,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
 		break;
 
 	case FE_SET_FRONTEND:
-		err = set_delivery_system(fe, SYS_UNDEFINED);
+		err = dvbv3_set_delivery_system(fe);
 		if (err)
 			break;
 
@@ -2594,7 +2629,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
 	 * first supported delivery system (ops->delsys[0])
 	 */
 
-        fe->dtv_property_cache.delivery_system = fe->ops.delsys[0];
+	fe->dtv_property_cache.delivery_system = fe->ops.delsys[0];
 	dvb_frontend_clear_cache(fe);
 
 	mutex_unlock(&frontend_mutex);

+ 2 - 2
drivers/media/dvb-core/dvb_frontend.h

@@ -245,8 +245,8 @@ struct analog_demod_ops {
 
 	void (*set_params)(struct dvb_frontend *fe,
 			   struct analog_parameters *params);
-	int  (*has_signal)(struct dvb_frontend *fe);
-	int  (*get_afc)(struct dvb_frontend *fe);
+	int  (*has_signal)(struct dvb_frontend *fe, u16 *signal);
+	int  (*get_afc)(struct dvb_frontend *fe, s32 *afc);
 	void (*tuner_status)(struct dvb_frontend *fe);
 	void (*standby)(struct dvb_frontend *fe);
 	void (*release)(struct dvb_frontend *fe);

+ 1 - 1
drivers/media/dvb-core/dvb_net.c

@@ -1044,7 +1044,7 @@ static int dvb_net_feed_start(struct net_device *dev)
 		ret = priv->tsfeed->set(priv->tsfeed,
 					priv->pid, /* pid */
 					TS_PACKET, /* type */
-					DMX_TS_PES_OTHER, /* pes type */
+					DMX_PES_OTHER, /* pes type */
 					32768,     /* circular buffer size */
 					timeout    /* timeout */
 					);

+ 1 - 1
drivers/media/dvb-frontends/Kconfig

@@ -210,7 +210,7 @@ config DVB_SI21XX
 config DVB_TS2020
 	tristate "Montage Tehnology TS2020 based tuners"
 	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
+	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
 	  A DVB-S/S2 silicon tuner. Say Y when you want to support this tuner.
 

+ 3 - 2
drivers/media/dvb-frontends/a8293.h

@@ -21,12 +21,13 @@
 #ifndef A8293_H
 #define A8293_H
 
+#include <linux/kconfig.h>
+
 struct a8293_config {
 	u8 i2c_addr;
 };
 
-#if defined(CONFIG_DVB_A8293) || \
-	(defined(CONFIG_DVB_A8293_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_A8293)
 extern struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
 	struct i2c_adapter *i2c, const struct a8293_config *cfg);
 #else

+ 2 - 2
drivers/media/dvb-frontends/af9013.h

@@ -25,6 +25,7 @@
 #ifndef AF9013_H
 #define AF9013_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 /* AF9013/5 GPIOs (mostly guessed)
@@ -102,8 +103,7 @@ struct af9013_config {
 	u8 gpio[4];
 };
 
-#if defined(CONFIG_DVB_AF9013) || \
-	(defined(CONFIG_DVB_AF9013_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_AF9013)
 extern struct dvb_frontend *af9013_attach(const struct af9013_config *config,
 	struct i2c_adapter *i2c);
 #else

+ 114 - 24
drivers/media/dvb-frontends/af9033.c

@@ -156,6 +156,37 @@ static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val,
 	return 0;
 }
 
+/* write reg val table using reg addr auto increment */
+static int af9033_wr_reg_val_tab(struct af9033_state *state,
+		const struct reg_val *tab, int tab_len)
+{
+	int ret, i, j;
+	u8 buf[tab_len];
+
+	dev_dbg(&state->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len);
+
+	for (i = 0, j = 0; i < tab_len; i++) {
+		buf[j] = tab[i].val;
+
+		if (i == tab_len - 1 || tab[i].reg != tab[i + 1].reg - 1) {
+			ret = af9033_wr_regs(state, tab[i].reg - j, buf, j + 1);
+			if (ret < 0)
+				goto err;
+
+			j = 0;
+		} else {
+			j++;
+		}
+	}
+
+	return 0;
+
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
 static u32 af9033_div(struct af9033_state *state, u32 a, u32 b, u32 x)
 {
 	u32 r = 0, c = 0, i;
@@ -223,6 +254,7 @@ static int af9033_init(struct dvb_frontend *fe)
 		{ 0x80f986, state->ts_mode_parallel, 0x01 },
 		{ 0x00d827, 0x00, 0xff },
 		{ 0x00d829, 0x00, 0xff },
+		{ 0x800045, state->cfg.adc_multiplier, 0xff },
 	};
 
 	/* program clock control */
@@ -286,14 +318,29 @@ static int af9033_init(struct dvb_frontend *fe)
 
 	/* load OFSM settings */
 	dev_dbg(&state->i2c->dev, "%s: load ofsm settings\n", __func__);
-	len = ARRAY_SIZE(ofsm_init);
-	init = ofsm_init;
-	for (i = 0; i < len; i++) {
-		ret = af9033_wr_reg(state, init[i].reg, init[i].val);
-		if (ret < 0)
-			goto err;
+	switch (state->cfg.tuner) {
+	case AF9033_TUNER_IT9135_38:
+	case AF9033_TUNER_IT9135_51:
+	case AF9033_TUNER_IT9135_52:
+		len = ARRAY_SIZE(ofsm_init_it9135_v1);
+		init = ofsm_init_it9135_v1;
+		break;
+	case AF9033_TUNER_IT9135_60:
+	case AF9033_TUNER_IT9135_61:
+	case AF9033_TUNER_IT9135_62:
+		len = ARRAY_SIZE(ofsm_init_it9135_v2);
+		init = ofsm_init_it9135_v2;
+		break;
+	default:
+		len = ARRAY_SIZE(ofsm_init);
+		init = ofsm_init;
+		break;
 	}
 
+	ret = af9033_wr_reg_val_tab(state, init, len);
+	if (ret < 0)
+		goto err;
+
 	/* load tuner specific settings */
 	dev_dbg(&state->i2c->dev, "%s: load tuner specific settings\n",
 			__func__);
@@ -322,6 +369,30 @@ static int af9033_init(struct dvb_frontend *fe)
 		len = ARRAY_SIZE(tuner_init_fc0012);
 		init = tuner_init_fc0012;
 		break;
+	case AF9033_TUNER_IT9135_38:
+		len = ARRAY_SIZE(tuner_init_it9135_38);
+		init = tuner_init_it9135_38;
+		break;
+	case AF9033_TUNER_IT9135_51:
+		len = ARRAY_SIZE(tuner_init_it9135_51);
+		init = tuner_init_it9135_51;
+		break;
+	case AF9033_TUNER_IT9135_52:
+		len = ARRAY_SIZE(tuner_init_it9135_52);
+		init = tuner_init_it9135_52;
+		break;
+	case AF9033_TUNER_IT9135_60:
+		len = ARRAY_SIZE(tuner_init_it9135_60);
+		init = tuner_init_it9135_60;
+		break;
+	case AF9033_TUNER_IT9135_61:
+		len = ARRAY_SIZE(tuner_init_it9135_61);
+		init = tuner_init_it9135_61;
+		break;
+	case AF9033_TUNER_IT9135_62:
+		len = ARRAY_SIZE(tuner_init_it9135_62);
+		init = tuner_init_it9135_62;
+		break;
 	default:
 		dev_dbg(&state->i2c->dev, "%s: unsupported tuner ID=%d\n",
 				__func__, state->cfg.tuner);
@@ -329,11 +400,9 @@ static int af9033_init(struct dvb_frontend *fe)
 		goto err;
 	}
 
-	for (i = 0; i < len; i++) {
-		ret = af9033_wr_reg(state, init[i].reg, init[i].val);
-		if (ret < 0)
-			goto err;
-	}
+	ret = af9033_wr_reg_val_tab(state, init, len);
+	if (ret < 0)
+		goto err;
 
 	if (state->cfg.ts_mode == AF9033_TS_MODE_SERIAL) {
 		ret = af9033_wr_reg_mask(state, 0x00d91c, 0x01, 0x01);
@@ -349,6 +418,15 @@ static int af9033_init(struct dvb_frontend *fe)
 			goto err;
 	}
 
+	switch (state->cfg.tuner) {
+	case AF9033_TUNER_IT9135_60:
+	case AF9033_TUNER_IT9135_61:
+	case AF9033_TUNER_IT9135_62:
+		ret = af9033_wr_reg(state, 0x800000, 0x01);
+		if (ret < 0)
+			goto err;
+	}
+
 	state->bandwidth_hz = 0; /* force to program all parameters */
 
 	return 0;
@@ -415,7 +493,8 @@ err:
 static int af9033_get_tune_settings(struct dvb_frontend *fe,
 		struct dvb_frontend_tune_settings *fesettings)
 {
-	fesettings->min_delay_ms = 800;
+	/* 800 => 2000 because IT9135 v2 is slow to gain lock */
+	fesettings->min_delay_ms = 2000;
 	fesettings->step_size = 0;
 	fesettings->max_drift = 0;
 
@@ -498,17 +577,17 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
 		if (spec_inv == -1)
 			freq_cw = 0x800000 - freq_cw;
 
-		/* get adc multiplies */
-		ret = af9033_rd_reg(state, 0x800045, &tmp);
-		if (ret < 0)
-			goto err;
-
-		if (tmp == 1)
+		if (state->cfg.adc_multiplier == AF9033_ADC_MULTIPLIER_2X)
 			freq_cw /= 2;
 
 		buf[0] = (freq_cw >>  0) & 0xff;
 		buf[1] = (freq_cw >>  8) & 0xff;
 		buf[2] = (freq_cw >> 16) & 0x7f;
+
+		/* FIXME: there seems to be calculation error here... */
+		if (if_frequency == 0)
+			buf[2] = 0;
+
 		ret = af9033_wr_regs(state, 0x800029, buf, 3);
 		if (ret < 0)
 			goto err;
@@ -934,13 +1013,24 @@ struct dvb_frontend *af9033_attach(const struct af9033_config *config,
 			buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
 
 	/* sleep */
-	ret = af9033_wr_reg(state, 0x80004c, 1);
-	if (ret < 0)
-		goto err;
+	switch (state->cfg.tuner) {
+	case AF9033_TUNER_IT9135_38:
+	case AF9033_TUNER_IT9135_51:
+	case AF9033_TUNER_IT9135_52:
+	case AF9033_TUNER_IT9135_60:
+	case AF9033_TUNER_IT9135_61:
+	case AF9033_TUNER_IT9135_62:
+		/* IT9135 did not like to sleep at that early */
+		break;
+	default:
+		ret = af9033_wr_reg(state, 0x80004c, 1);
+		if (ret < 0)
+			goto err;
 
-	ret = af9033_wr_reg(state, 0x800000, 0);
-	if (ret < 0)
-		goto err;
+		ret = af9033_wr_reg(state, 0x800000, 0);
+		if (ret < 0)
+			goto err;
+	}
 
 	/* configure internal TS mode */
 	switch (state->cfg.ts_mode) {

+ 18 - 2
drivers/media/dvb-frontends/af9033.h

@@ -22,6 +22,8 @@
 #ifndef AF9033_H
 #define AF9033_H
 
+#include <linux/kconfig.h>
+
 struct af9033_config {
 	/*
 	 * I2C address
@@ -35,6 +37,13 @@ struct af9033_config {
 	 */
 	u32 clock;
 
+	/*
+	 * ADC multiplier
+	 */
+#define AF9033_ADC_MULTIPLIER_1X   0
+#define AF9033_ADC_MULTIPLIER_2X   1
+	u8 adc_multiplier;
+
 	/*
 	 * tuner
 	 */
@@ -44,6 +53,14 @@ struct af9033_config {
 #define AF9033_TUNER_MXL5007T    0xa0 /* MaxLinear MxL5007T */
 #define AF9033_TUNER_TDA18218    0xa1 /* NXP TDA 18218HN */
 #define AF9033_TUNER_FC2580      0x32 /* FCI FC2580 */
+/* 50-5f Omega */
+#define AF9033_TUNER_IT9135_38   0x38 /* Omega */
+#define AF9033_TUNER_IT9135_51   0x51 /* Omega LNA config 1 */
+#define AF9033_TUNER_IT9135_52   0x52 /* Omega LNA config 2 */
+/* 60-6f Omega v2 */
+#define AF9033_TUNER_IT9135_60   0x60 /* Omega v2 */
+#define AF9033_TUNER_IT9135_61   0x61 /* Omega v2 LNA config 1 */
+#define AF9033_TUNER_IT9135_62   0x62 /* Omega v2 LNA config 2 */
 	u8 tuner;
 
 	/*
@@ -61,8 +78,7 @@ struct af9033_config {
 };
 
 
-#if defined(CONFIG_DVB_AF9033) || \
-	(defined(CONFIG_DVB_AF9033_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_AF9033)
 extern struct dvb_frontend *af9033_attach(const struct af9033_config *config,
 	struct i2c_adapter *i2c);
 #else

+ 1505 - 1
drivers/media/dvb-frontends/af9033_priv.h

@@ -547,5 +547,1509 @@ static const struct reg_val tuner_init_fc2580[] = {
 	{ 0x80f1e6, 0x01 },
 };
 
-#endif /* AF9033_PRIV_H */
+static const struct reg_val ofsm_init_it9135_v1[] = {
+	{ 0x800051, 0x01 },
+	{ 0x800070, 0x0a },
+	{ 0x80007e, 0x04 },
+	{ 0x800081, 0x0a },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800099, 0x01 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000c2, 0x05 },
+	{ 0x8000c6, 0x19 },
+	{ 0x80f000, 0x0f },
+	{ 0x80f016, 0x10 },
+	{ 0x80f017, 0x04 },
+	{ 0x80f018, 0x05 },
+	{ 0x80f019, 0x04 },
+	{ 0x80f01a, 0x05 },
+	{ 0x80f021, 0x03 },
+	{ 0x80f022, 0x0a },
+	{ 0x80f023, 0x0a },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f02c, 0x01 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5df, 0xfb },
+	{ 0x80f5e0, 0x00 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f5f8, 0x01 },
+	{ 0x80f5fd, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
+
+/* ITE Tech IT9135 Omega tuner init
+   AF9033_TUNER_IT9135_38   = 0x38 */
+static const struct reg_val tuner_init_it9135_38[] = {
+	{ 0x800043, 0x00 },
+	{ 0x800046, 0x38 },
+	{ 0x800051, 0x01 },
+	{ 0x80005f, 0x00 },
+	{ 0x800060, 0x00 },
+	{ 0x800068, 0x0a },
+	{ 0x800070, 0x0a },
+	{ 0x800071, 0x05 },
+	{ 0x800072, 0x02 },
+	{ 0x800075, 0x8c },
+	{ 0x800076, 0x8c },
+	{ 0x800077, 0x8c },
+	{ 0x800078, 0xc8 },
+	{ 0x800079, 0x01 },
+	{ 0x80007e, 0x04 },
+	{ 0x80007f, 0x00 },
+	{ 0x800081, 0x0a },
+	{ 0x800082, 0x12 },
+	{ 0x800083, 0x02 },
+	{ 0x800084, 0x0a },
+	{ 0x800085, 0x03 },
+	{ 0x800086, 0xc8 },
+	{ 0x800087, 0xb8 },
+	{ 0x800088, 0xd0 },
+	{ 0x800089, 0xc3 },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800093, 0x00 },
+	{ 0x800094, 0x00 },
+	{ 0x800095, 0x00 },
+	{ 0x800096, 0x00 },
+	{ 0x800099, 0x01 },
+	{ 0x80009b, 0x3c },
+	{ 0x80009c, 0x28 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a4, 0x5a },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000b3, 0x02 },
+	{ 0x8000b4, 0x32 },
+	{ 0x8000b6, 0x14 },
+	{ 0x8000c0, 0x11 },
+	{ 0x8000c1, 0x00 },
+	{ 0x8000c2, 0x05 },
+	{ 0x8000c4, 0x00 },
+	{ 0x8000c6, 0x19 },
+	{ 0x8000c7, 0x00 },
+	{ 0x8000cc, 0x2e },
+	{ 0x8000cd, 0x51 },
+	{ 0x8000ce, 0x33 },
+	{ 0x8000f3, 0x05 },
+	{ 0x8000f4, 0x8c },
+	{ 0x8000f5, 0x8c },
+	{ 0x8000f8, 0x03 },
+	{ 0x8000f9, 0x06 },
+	{ 0x8000fa, 0x06 },
+	{ 0x8000fc, 0x02 },
+	{ 0x8000fd, 0x02 },
+	{ 0x8000fe, 0x02 },
+	{ 0x8000ff, 0x09 },
+	{ 0x800100, 0x50 },
+	{ 0x800101, 0x7b },
+	{ 0x800102, 0x77 },
+	{ 0x800103, 0x00 },
+	{ 0x800104, 0x02 },
+	{ 0x800105, 0xc8 },
+	{ 0x800106, 0x05 },
+	{ 0x800107, 0x7b },
+	{ 0x800109, 0x02 },
+	{ 0x800115, 0x0a },
+	{ 0x800116, 0x03 },
+	{ 0x800117, 0x02 },
+	{ 0x800118, 0x80 },
+	{ 0x80011a, 0xc8 },
+	{ 0x80011b, 0x7b },
+	{ 0x80011c, 0x8a },
+	{ 0x80011d, 0xa0 },
+	{ 0x800122, 0x02 },
+	{ 0x800123, 0x18 },
+	{ 0x800124, 0xc3 },
+	{ 0x800127, 0x00 },
+	{ 0x800128, 0x07 },
+	{ 0x80012a, 0x53 },
+	{ 0x80012b, 0x51 },
+	{ 0x80012c, 0x4e },
+	{ 0x80012d, 0x43 },
+	{ 0x800137, 0x01 },
+	{ 0x800138, 0x00 },
+	{ 0x800139, 0x07 },
+	{ 0x80013a, 0x00 },
+	{ 0x80013b, 0x06 },
+	{ 0x80013d, 0x00 },
+	{ 0x80013e, 0x01 },
+	{ 0x80013f, 0x5b },
+	{ 0x800140, 0xc8 },
+	{ 0x800141, 0x59 },
+	{ 0x80f000, 0x0f },
+	{ 0x80f016, 0x10 },
+	{ 0x80f017, 0x04 },
+	{ 0x80f018, 0x05 },
+	{ 0x80f019, 0x04 },
+	{ 0x80f01a, 0x05 },
+	{ 0x80f01f, 0x8c },
+	{ 0x80f020, 0x00 },
+	{ 0x80f021, 0x03 },
+	{ 0x80f022, 0x0a },
+	{ 0x80f023, 0x0a },
+	{ 0x80f029, 0x8c },
+	{ 0x80f02a, 0x00 },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f02c, 0x01 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f077, 0x01 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f085, 0x00 },
+	{ 0x80f086, 0x02 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f24c, 0x88 },
+	{ 0x80f24d, 0x95 },
+	{ 0x80f24e, 0x9a },
+	{ 0x80f24f, 0x90 },
+	{ 0x80f25a, 0x07 },
+	{ 0x80f25b, 0xe8 },
+	{ 0x80f25c, 0x03 },
+	{ 0x80f25d, 0xb0 },
+	{ 0x80f25e, 0x04 },
+	{ 0x80f270, 0x01 },
+	{ 0x80f271, 0x02 },
+	{ 0x80f272, 0x01 },
+	{ 0x80f273, 0x02 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5df, 0xfb },
+	{ 0x80f5e0, 0x00 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f5f8, 0x01 },
+	{ 0x80f5fd, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
+
+/* ITE Tech IT9135 Omega LNA config 1 tuner init
+   AF9033_TUNER_IT9135_51   = 0x51 */
+static const struct reg_val tuner_init_it9135_51[] = {
+	{ 0x800043, 0x00 },
+	{ 0x800046, 0x51 },
+	{ 0x800051, 0x01 },
+	{ 0x80005f, 0x00 },
+	{ 0x800060, 0x00 },
+	{ 0x800068, 0x0a },
+	{ 0x800070, 0x0a },
+	{ 0x800071, 0x06 },
+	{ 0x800072, 0x02 },
+	{ 0x800075, 0x8c },
+	{ 0x800076, 0x8c },
+	{ 0x800077, 0x8c },
+	{ 0x800078, 0xc8 },
+	{ 0x800079, 0x01 },
+	{ 0x80007e, 0x04 },
+	{ 0x80007f, 0x00 },
+	{ 0x800081, 0x0a },
+	{ 0x800082, 0x12 },
+	{ 0x800083, 0x02 },
+	{ 0x800084, 0x0a },
+	{ 0x800085, 0x03 },
+	{ 0x800086, 0xc0 },
+	{ 0x800087, 0x96 },
+	{ 0x800088, 0xcf },
+	{ 0x800089, 0xc3 },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800093, 0x00 },
+	{ 0x800094, 0x00 },
+	{ 0x800095, 0x00 },
+	{ 0x800096, 0x00 },
+	{ 0x800099, 0x01 },
+	{ 0x80009b, 0x3c },
+	{ 0x80009c, 0x28 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a4, 0x5a },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000b3, 0x02 },
+	{ 0x8000b4, 0x3c },
+	{ 0x8000b6, 0x14 },
+	{ 0x8000c0, 0x11 },
+	{ 0x8000c1, 0x00 },
+	{ 0x8000c2, 0x05 },
+	{ 0x8000c4, 0x00 },
+	{ 0x8000c6, 0x19 },
+	{ 0x8000c7, 0x00 },
+	{ 0x8000cc, 0x2e },
+	{ 0x8000cd, 0x51 },
+	{ 0x8000ce, 0x33 },
+	{ 0x8000f3, 0x05 },
+	{ 0x8000f4, 0x8c },
+	{ 0x8000f5, 0x8c },
+	{ 0x8000f8, 0x03 },
+	{ 0x8000f9, 0x06 },
+	{ 0x8000fa, 0x06 },
+	{ 0x8000fc, 0x03 },
+	{ 0x8000fd, 0x02 },
+	{ 0x8000fe, 0x02 },
+	{ 0x8000ff, 0x09 },
+	{ 0x800100, 0x50 },
+	{ 0x800101, 0x7a },
+	{ 0x800102, 0x77 },
+	{ 0x800103, 0x01 },
+	{ 0x800104, 0x02 },
+	{ 0x800105, 0xb0 },
+	{ 0x800106, 0x02 },
+	{ 0x800107, 0x7a },
+	{ 0x800109, 0x02 },
+	{ 0x800115, 0x0a },
+	{ 0x800116, 0x03 },
+	{ 0x800117, 0x02 },
+	{ 0x800118, 0x80 },
+	{ 0x80011a, 0xc0 },
+	{ 0x80011b, 0x7a },
+	{ 0x80011c, 0xac },
+	{ 0x80011d, 0x8c },
+	{ 0x800122, 0x02 },
+	{ 0x800123, 0x70 },
+	{ 0x800124, 0xa4 },
+	{ 0x800127, 0x00 },
+	{ 0x800128, 0x07 },
+	{ 0x80012a, 0x53 },
+	{ 0x80012b, 0x51 },
+	{ 0x80012c, 0x4e },
+	{ 0x80012d, 0x43 },
+	{ 0x800137, 0x01 },
+	{ 0x800138, 0x00 },
+	{ 0x800139, 0x07 },
+	{ 0x80013a, 0x00 },
+	{ 0x80013b, 0x06 },
+	{ 0x80013d, 0x00 },
+	{ 0x80013e, 0x01 },
+	{ 0x80013f, 0x5b },
+	{ 0x800140, 0xc0 },
+	{ 0x800141, 0x59 },
+	{ 0x80f000, 0x0f },
+	{ 0x80f016, 0x10 },
+	{ 0x80f017, 0x04 },
+	{ 0x80f018, 0x05 },
+	{ 0x80f019, 0x04 },
+	{ 0x80f01a, 0x05 },
+	{ 0x80f01f, 0x8c },
+	{ 0x80f020, 0x00 },
+	{ 0x80f021, 0x03 },
+	{ 0x80f022, 0x0a },
+	{ 0x80f023, 0x0a },
+	{ 0x80f029, 0x8c },
+	{ 0x80f02a, 0x00 },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f02c, 0x01 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f077, 0x01 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f085, 0xc0 },
+	{ 0x80f086, 0x01 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f24c, 0x88 },
+	{ 0x80f24d, 0x95 },
+	{ 0x80f24e, 0x9a },
+	{ 0x80f24f, 0x90 },
+	{ 0x80f25a, 0x07 },
+	{ 0x80f25b, 0xe8 },
+	{ 0x80f25c, 0x03 },
+	{ 0x80f25d, 0xb0 },
+	{ 0x80f25e, 0x04 },
+	{ 0x80f270, 0x01 },
+	{ 0x80f271, 0x02 },
+	{ 0x80f272, 0x01 },
+	{ 0x80f273, 0x02 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5df, 0xfb },
+	{ 0x80f5e0, 0x00 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f5f8, 0x01 },
+	{ 0x80f5fd, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
+
+/* ITE Tech IT9135 Omega LNA config 2 tuner init
+   AF9033_TUNER_IT9135_52   = 0x52 */
+static const struct reg_val tuner_init_it9135_52[] = {
+	{ 0x800043, 0x00 },
+	{ 0x800046, 0x52 },
+	{ 0x800051, 0x01 },
+	{ 0x80005f, 0x00 },
+	{ 0x800060, 0x00 },
+	{ 0x800068, 0x10 },
+	{ 0x800070, 0x0a },
+	{ 0x800071, 0x05 },
+	{ 0x800072, 0x02 },
+	{ 0x800075, 0x8c },
+	{ 0x800076, 0x8c },
+	{ 0x800077, 0x8c },
+	{ 0x800078, 0xa0 },
+	{ 0x800079, 0x01 },
+	{ 0x80007e, 0x04 },
+	{ 0x80007f, 0x00 },
+	{ 0x800081, 0x0a },
+	{ 0x800082, 0x17 },
+	{ 0x800083, 0x03 },
+	{ 0x800084, 0x0a },
+	{ 0x800085, 0x03 },
+	{ 0x800086, 0xb3 },
+	{ 0x800087, 0x97 },
+	{ 0x800088, 0xc0 },
+	{ 0x800089, 0x9e },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800093, 0x00 },
+	{ 0x800094, 0x00 },
+	{ 0x800095, 0x00 },
+	{ 0x800096, 0x00 },
+	{ 0x800099, 0x01 },
+	{ 0x80009b, 0x3c },
+	{ 0x80009c, 0x28 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a4, 0x5c },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000b3, 0x02 },
+	{ 0x8000b4, 0x3c },
+	{ 0x8000b6, 0x14 },
+	{ 0x8000c0, 0x11 },
+	{ 0x8000c1, 0x00 },
+	{ 0x8000c2, 0x05 },
+	{ 0x8000c4, 0x00 },
+	{ 0x8000c6, 0x19 },
+	{ 0x8000c7, 0x00 },
+	{ 0x8000cc, 0x2e },
+	{ 0x8000cd, 0x51 },
+	{ 0x8000ce, 0x33 },
+	{ 0x8000f3, 0x05 },
+	{ 0x8000f4, 0x91 },
+	{ 0x8000f5, 0x8c },
+	{ 0x8000f8, 0x03 },
+	{ 0x8000f9, 0x06 },
+	{ 0x8000fa, 0x06 },
+	{ 0x8000fc, 0x03 },
+	{ 0x8000fd, 0x02 },
+	{ 0x8000fe, 0x02 },
+	{ 0x8000ff, 0x09 },
+	{ 0x800100, 0x50 },
+	{ 0x800101, 0x74 },
+	{ 0x800102, 0x77 },
+	{ 0x800103, 0x02 },
+	{ 0x800104, 0x02 },
+	{ 0x800105, 0xa4 },
+	{ 0x800106, 0x02 },
+	{ 0x800107, 0x6e },
+	{ 0x800109, 0x02 },
+	{ 0x800115, 0x0a },
+	{ 0x800116, 0x03 },
+	{ 0x800117, 0x02 },
+	{ 0x800118, 0x80 },
+	{ 0x80011a, 0xcd },
+	{ 0x80011b, 0x62 },
+	{ 0x80011c, 0xa4 },
+	{ 0x80011d, 0x8c },
+	{ 0x800122, 0x03 },
+	{ 0x800123, 0x18 },
+	{ 0x800124, 0x9e },
+	{ 0x800127, 0x00 },
+	{ 0x800128, 0x07 },
+	{ 0x80012a, 0x53 },
+	{ 0x80012b, 0x51 },
+	{ 0x80012c, 0x4e },
+	{ 0x80012d, 0x43 },
+	{ 0x800137, 0x00 },
+	{ 0x800138, 0x00 },
+	{ 0x800139, 0x07 },
+	{ 0x80013a, 0x00 },
+	{ 0x80013b, 0x06 },
+	{ 0x80013d, 0x00 },
+	{ 0x80013e, 0x01 },
+	{ 0x80013f, 0x5b },
+	{ 0x800140, 0xb6 },
+	{ 0x800141, 0x59 },
+	{ 0x80f000, 0x0f },
+	{ 0x80f016, 0x10 },
+	{ 0x80f017, 0x04 },
+	{ 0x80f018, 0x05 },
+	{ 0x80f019, 0x04 },
+	{ 0x80f01a, 0x05 },
+	{ 0x80f01f, 0x8c },
+	{ 0x80f020, 0x00 },
+	{ 0x80f021, 0x03 },
+	{ 0x80f022, 0x0a },
+	{ 0x80f023, 0x0a },
+	{ 0x80f029, 0x8c },
+	{ 0x80f02a, 0x00 },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f02c, 0x01 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f077, 0x01 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f085, 0xc0 },
+	{ 0x80f086, 0x01 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f24c, 0x88 },
+	{ 0x80f24d, 0x95 },
+	{ 0x80f24e, 0x9a },
+	{ 0x80f24f, 0x90 },
+	{ 0x80f25a, 0x07 },
+	{ 0x80f25b, 0xe8 },
+	{ 0x80f25c, 0x03 },
+	{ 0x80f25d, 0xb0 },
+	{ 0x80f25e, 0x04 },
+	{ 0x80f270, 0x01 },
+	{ 0x80f271, 0x02 },
+	{ 0x80f272, 0x01 },
+	{ 0x80f273, 0x02 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5df, 0xfb },
+	{ 0x80f5e0, 0x00 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f5f8, 0x01 },
+	{ 0x80f5fd, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
+
+static const struct reg_val ofsm_init_it9135_v2[] = {
+	{ 0x800051, 0x01 },
+	{ 0x800070, 0x0a },
+	{ 0x80007e, 0x04 },
+	{ 0x800081, 0x0a },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800099, 0x01 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000c2, 0x05 },
+	{ 0x8000c6, 0x19 },
+	{ 0x80f000, 0x0f },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
+
+/* ITE Tech IT9135 Omega v2 tuner init
+   AF9033_TUNER_IT9135_60   = 0x60 */
+static const struct reg_val tuner_init_it9135_60[] = {
+	{ 0x800043, 0x00 },
+	{ 0x800046, 0x60 },
+	{ 0x800051, 0x01 },
+	{ 0x80005f, 0x00 },
+	{ 0x800060, 0x00 },
+	{ 0x800068, 0x0a },
+	{ 0x80006a, 0x03 },
+	{ 0x800070, 0x0a },
+	{ 0x800071, 0x05 },
+	{ 0x800072, 0x02 },
+	{ 0x800075, 0x8c },
+	{ 0x800076, 0x8c },
+	{ 0x800077, 0x8c },
+	{ 0x800078, 0x8c },
+	{ 0x800079, 0x01 },
+	{ 0x80007e, 0x04 },
+	{ 0x800081, 0x0a },
+	{ 0x800082, 0x18 },
+	{ 0x800084, 0x0a },
+	{ 0x800085, 0x33 },
+	{ 0x800086, 0xbe },
+	{ 0x800087, 0xa0 },
+	{ 0x800088, 0xc6 },
+	{ 0x800089, 0xb6 },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800093, 0x00 },
+	{ 0x800094, 0x00 },
+	{ 0x800095, 0x00 },
+	{ 0x800096, 0x00 },
+	{ 0x800099, 0x01 },
+	{ 0x80009b, 0x3c },
+	{ 0x80009c, 0x28 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a4, 0x5a },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000b3, 0x02 },
+	{ 0x8000b4, 0x3a },
+	{ 0x8000b6, 0x14 },
+	{ 0x8000c0, 0x11 },
+	{ 0x8000c1, 0x00 },
+	{ 0x8000c2, 0x05 },
+	{ 0x8000c3, 0x01 },
+	{ 0x8000c4, 0x00 },
+	{ 0x8000c6, 0x19 },
+	{ 0x8000c7, 0x00 },
+	{ 0x8000cb, 0x32 },
+	{ 0x8000cc, 0x2c },
+	{ 0x8000cd, 0x4f },
+	{ 0x8000ce, 0x30 },
+	{ 0x8000f3, 0x05 },
+	{ 0x8000f4, 0xa0 },
+	{ 0x8000f5, 0x8c },
+	{ 0x8000f8, 0x03 },
+	{ 0x8000f9, 0x06 },
+	{ 0x8000fa, 0x06 },
+	{ 0x8000fc, 0x03 },
+	{ 0x8000fd, 0x03 },
+	{ 0x8000fe, 0x02 },
+	{ 0x8000ff, 0x0a },
+	{ 0x800100, 0x50 },
+	{ 0x800101, 0x7b },
+	{ 0x800102, 0x8c },
+	{ 0x800103, 0x00 },
+	{ 0x800104, 0x02 },
+	{ 0x800105, 0xbe },
+	{ 0x800106, 0x00 },
+	{ 0x800109, 0x02 },
+	{ 0x800115, 0x0a },
+	{ 0x800116, 0x03 },
+	{ 0x80011a, 0xbe },
+	{ 0x800124, 0xae },
+	{ 0x800127, 0x00 },
+	{ 0x80012a, 0x56 },
+	{ 0x80012b, 0x50 },
+	{ 0x80012c, 0x47 },
+	{ 0x80012d, 0x42 },
+	{ 0x800137, 0x00 },
+	{ 0x80013b, 0x08 },
+	{ 0x80013f, 0x5b },
+	{ 0x800141, 0x59 },
+	{ 0x800142, 0xf9 },
+	{ 0x800143, 0x19 },
+	{ 0x800144, 0x00 },
+	{ 0x800145, 0x8c },
+	{ 0x800146, 0x8c },
+	{ 0x800147, 0x8c },
+	{ 0x800148, 0x6e },
+	{ 0x800149, 0x8c },
+	{ 0x80014a, 0x50 },
+	{ 0x80014b, 0x8c },
+	{ 0x80014d, 0xac },
+	{ 0x80014e, 0xc6 },
+	{ 0x80014f, 0x03 },
+	{ 0x800151, 0x1e },
+	{ 0x800153, 0xbc },
+	{ 0x800178, 0x09 },
+	{ 0x800181, 0x94 },
+	{ 0x800182, 0x6e },
+	{ 0x800185, 0x24 },
+	{ 0x800189, 0xbe },
+	{ 0x80018c, 0x03 },
+	{ 0x80018d, 0x5f },
+	{ 0x80018f, 0xa0 },
+	{ 0x800190, 0x5a },
+	{ 0x80ed02, 0xff },
+	{ 0x80ee42, 0xff },
+	{ 0x80ee82, 0xff },
+	{ 0x80f000, 0x0f },
+	{ 0x80f01f, 0x8c },
+	{ 0x80f020, 0x00 },
+	{ 0x80f029, 0x8c },
+	{ 0x80f02a, 0x00 },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f077, 0x01 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f24c, 0x88 },
+	{ 0x80f24d, 0x95 },
+	{ 0x80f24e, 0x9a },
+	{ 0x80f24f, 0x90 },
+	{ 0x80f25a, 0x07 },
+	{ 0x80f25b, 0xe8 },
+	{ 0x80f25c, 0x03 },
+	{ 0x80f25d, 0xb0 },
+	{ 0x80f25e, 0x04 },
+	{ 0x80f270, 0x01 },
+	{ 0x80f271, 0x02 },
+	{ 0x80f272, 0x01 },
+	{ 0x80f273, 0x02 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
+
+/* ITE Tech IT9135 Omega v2 LNA config 1 tuner init
+   AF9033_TUNER_IT9135_61   = 0x61 */
+static const struct reg_val tuner_init_it9135_61[] = {
+	{ 0x800043, 0x00 },
+	{ 0x800046, 0x61 },
+	{ 0x800051, 0x01 },
+	{ 0x80005f, 0x00 },
+	{ 0x800060, 0x00 },
+	{ 0x800068, 0x06 },
+	{ 0x80006a, 0x03 },
+	{ 0x800070, 0x0a },
+	{ 0x800071, 0x05 },
+	{ 0x800072, 0x02 },
+	{ 0x800075, 0x8c },
+	{ 0x800076, 0x8c },
+	{ 0x800077, 0x8c },
+	{ 0x800078, 0x90 },
+	{ 0x800079, 0x01 },
+	{ 0x80007e, 0x04 },
+	{ 0x800081, 0x0a },
+	{ 0x800082, 0x12 },
+	{ 0x800084, 0x0a },
+	{ 0x800085, 0x33 },
+	{ 0x800086, 0xbc },
+	{ 0x800087, 0x9c },
+	{ 0x800088, 0xcc },
+	{ 0x800089, 0xa8 },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800093, 0x00 },
+	{ 0x800094, 0x00 },
+	{ 0x800095, 0x00 },
+	{ 0x800096, 0x00 },
+	{ 0x800099, 0x01 },
+	{ 0x80009b, 0x3c },
+	{ 0x80009c, 0x28 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a4, 0x5c },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000b3, 0x02 },
+	{ 0x8000b4, 0x3a },
+	{ 0x8000b6, 0x14 },
+	{ 0x8000c0, 0x11 },
+	{ 0x8000c1, 0x00 },
+	{ 0x8000c2, 0x05 },
+	{ 0x8000c3, 0x01 },
+	{ 0x8000c4, 0x00 },
+	{ 0x8000c6, 0x19 },
+	{ 0x8000c7, 0x00 },
+	{ 0x8000cb, 0x32 },
+	{ 0x8000cc, 0x2c },
+	{ 0x8000cd, 0x4f },
+	{ 0x8000ce, 0x30 },
+	{ 0x8000f3, 0x05 },
+	{ 0x8000f4, 0xa0 },
+	{ 0x8000f5, 0x8c },
+	{ 0x8000f8, 0x03 },
+	{ 0x8000f9, 0x06 },
+	{ 0x8000fa, 0x06 },
+	{ 0x8000fc, 0x03 },
+	{ 0x8000fd, 0x03 },
+	{ 0x8000fe, 0x02 },
+	{ 0x8000ff, 0x08 },
+	{ 0x800100, 0x50 },
+	{ 0x800101, 0x7b },
+	{ 0x800102, 0x8c },
+	{ 0x800103, 0x01 },
+	{ 0x800104, 0x02 },
+	{ 0x800105, 0xc8 },
+	{ 0x800106, 0x00 },
+	{ 0x800109, 0x02 },
+	{ 0x800115, 0x0a },
+	{ 0x800116, 0x03 },
+	{ 0x80011a, 0xc6 },
+	{ 0x800124, 0xa8 },
+	{ 0x800127, 0x00 },
+	{ 0x80012a, 0x59 },
+	{ 0x80012b, 0x50 },
+	{ 0x80012c, 0x47 },
+	{ 0x80012d, 0x42 },
+	{ 0x800137, 0x00 },
+	{ 0x80013b, 0x05 },
+	{ 0x80013f, 0x5b },
+	{ 0x800141, 0x59 },
+	{ 0x800142, 0xf9 },
+	{ 0x800143, 0x59 },
+	{ 0x800144, 0x01 },
+	{ 0x800145, 0x8c },
+	{ 0x800146, 0x8c },
+	{ 0x800147, 0x8c },
+	{ 0x800148, 0x7b },
+	{ 0x800149, 0x8c },
+	{ 0x80014a, 0x50 },
+	{ 0x80014b, 0x8c },
+	{ 0x80014d, 0xa8 },
+	{ 0x80014e, 0xc6 },
+	{ 0x80014f, 0x03 },
+	{ 0x800151, 0x28 },
+	{ 0x800153, 0xcc },
+	{ 0x800178, 0x09 },
+	{ 0x800181, 0x9c },
+	{ 0x800182, 0x76 },
+	{ 0x800185, 0x28 },
+	{ 0x800189, 0xaa },
+	{ 0x80018c, 0x03 },
+	{ 0x80018d, 0x5f },
+	{ 0x80018f, 0xfb },
+	{ 0x800190, 0x5c },
+	{ 0x80ed02, 0xff },
+	{ 0x80ee42, 0xff },
+	{ 0x80ee82, 0xff },
+	{ 0x80f000, 0x0f },
+	{ 0x80f01f, 0x8c },
+	{ 0x80f020, 0x00 },
+	{ 0x80f029, 0x8c },
+	{ 0x80f02a, 0x00 },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f077, 0x01 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f24c, 0x88 },
+	{ 0x80f24d, 0x95 },
+	{ 0x80f24e, 0x9a },
+	{ 0x80f24f, 0x90 },
+	{ 0x80f25a, 0x07 },
+	{ 0x80f25b, 0xe8 },
+	{ 0x80f25c, 0x03 },
+	{ 0x80f25d, 0xb0 },
+	{ 0x80f25e, 0x04 },
+	{ 0x80f270, 0x01 },
+	{ 0x80f271, 0x02 },
+	{ 0x80f272, 0x01 },
+	{ 0x80f273, 0x02 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
+
+/* ITE Tech IT9135 Omega v2 LNA config 2 tuner init
+   AF9033_TUNER_IT9135_62   = 0x62 */
+static const struct reg_val tuner_init_it9135_62[] = {
+	{ 0x800043, 0x00 },
+	{ 0x800046, 0x62 },
+	{ 0x800051, 0x01 },
+	{ 0x80005f, 0x00 },
+	{ 0x800060, 0x00 },
+	{ 0x800068, 0x0a },
+	{ 0x80006a, 0x03 },
+	{ 0x800070, 0x0a },
+	{ 0x800071, 0x05 },
+	{ 0x800072, 0x02 },
+	{ 0x800075, 0x8c },
+	{ 0x800076, 0x8c },
+	{ 0x800077, 0x8c },
+	{ 0x800078, 0x8c },
+	{ 0x800079, 0x01 },
+	{ 0x80007e, 0x04 },
+	{ 0x800081, 0x0a },
+	{ 0x800082, 0x12 },
+	{ 0x800084, 0x0a },
+	{ 0x800085, 0x33 },
+	{ 0x800086, 0xb8 },
+	{ 0x800087, 0x9c },
+	{ 0x800088, 0xb2 },
+	{ 0x800089, 0xa6 },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800093, 0x00 },
+	{ 0x800094, 0x00 },
+	{ 0x800095, 0x00 },
+	{ 0x800096, 0x00 },
+	{ 0x800099, 0x01 },
+	{ 0x80009b, 0x3c },
+	{ 0x80009c, 0x28 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a4, 0x5a },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000b3, 0x02 },
+	{ 0x8000b4, 0x3a },
+	{ 0x8000b6, 0x14 },
+	{ 0x8000c0, 0x11 },
+	{ 0x8000c1, 0x00 },
+	{ 0x8000c2, 0x05 },
+	{ 0x8000c3, 0x01 },
+	{ 0x8000c4, 0x00 },
+	{ 0x8000c6, 0x19 },
+	{ 0x8000c7, 0x00 },
+	{ 0x8000cb, 0x32 },
+	{ 0x8000cc, 0x2c },
+	{ 0x8000cd, 0x4f },
+	{ 0x8000ce, 0x30 },
+	{ 0x8000f3, 0x05 },
+	{ 0x8000f4, 0x8c },
+	{ 0x8000f5, 0x8c },
+	{ 0x8000f8, 0x03 },
+	{ 0x8000f9, 0x06 },
+	{ 0x8000fa, 0x06 },
+	{ 0x8000fc, 0x02 },
+	{ 0x8000fd, 0x03 },
+	{ 0x8000fe, 0x02 },
+	{ 0x8000ff, 0x09 },
+	{ 0x800100, 0x50 },
+	{ 0x800101, 0x6e },
+	{ 0x800102, 0x8c },
+	{ 0x800103, 0x02 },
+	{ 0x800104, 0x02 },
+	{ 0x800105, 0xc2 },
+	{ 0x800106, 0x00 },
+	{ 0x800109, 0x02 },
+	{ 0x800115, 0x0a },
+	{ 0x800116, 0x03 },
+	{ 0x80011a, 0xb8 },
+	{ 0x800124, 0xa8 },
+	{ 0x800127, 0x00 },
+	{ 0x80012a, 0x53 },
+	{ 0x80012b, 0x51 },
+	{ 0x80012c, 0x4e },
+	{ 0x80012d, 0x43 },
+	{ 0x800137, 0x00 },
+	{ 0x80013b, 0x05 },
+	{ 0x80013f, 0x5b },
+	{ 0x800141, 0x59 },
+	{ 0x800142, 0xf9 },
+	{ 0x800143, 0x59 },
+	{ 0x800144, 0x00 },
+	{ 0x800145, 0x8c },
+	{ 0x800146, 0x8c },
+	{ 0x800147, 0x8c },
+	{ 0x800148, 0x7b },
+	{ 0x800149, 0x8c },
+	{ 0x80014a, 0x50 },
+	{ 0x80014b, 0x70 },
+	{ 0x80014d, 0x96 },
+	{ 0x80014e, 0xd0 },
+	{ 0x80014f, 0x03 },
+	{ 0x800151, 0x28 },
+	{ 0x800153, 0xb2 },
+	{ 0x800178, 0x09 },
+	{ 0x800181, 0x9c },
+	{ 0x800182, 0x6e },
+	{ 0x800185, 0x24 },
+	{ 0x800189, 0xb8 },
+	{ 0x80018c, 0x03 },
+	{ 0x80018d, 0x5f },
+	{ 0x80018f, 0xfb },
+	{ 0x800190, 0x5a },
+	{ 0x80ed02, 0xff },
+	{ 0x80ee42, 0xff },
+	{ 0x80ee82, 0xff },
+	{ 0x80f000, 0x0f },
+	{ 0x80f01f, 0x8c },
+	{ 0x80f020, 0x00 },
+	{ 0x80f029, 0x8c },
+	{ 0x80f02a, 0x00 },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f077, 0x01 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f24c, 0x88 },
+	{ 0x80f24d, 0x95 },
+	{ 0x80f24e, 0x9a },
+	{ 0x80f24f, 0x90 },
+	{ 0x80f25a, 0x07 },
+	{ 0x80f25b, 0xe8 },
+	{ 0x80f25c, 0x03 },
+	{ 0x80f25d, 0xb0 },
+	{ 0x80f25e, 0x04 },
+	{ 0x80f270, 0x01 },
+	{ 0x80f271, 0x02 },
+	{ 0x80f272, 0x01 },
+	{ 0x80f273, 0x02 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
 
+#endif /* AF9033_PRIV_H */

+ 2 - 2
drivers/media/dvb-frontends/atbm8830.h

@@ -22,6 +22,7 @@
 #ifndef __ATBM8830_H__
 #define __ATBM8830_H__
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 #include <linux/i2c.h>
 
@@ -60,8 +61,7 @@ struct atbm8830_config {
 	u8 agc_hold_loop;
 };
 
-#if defined(CONFIG_DVB_ATBM8830) || \
-	(defined(CONFIG_DVB_ATBM8830_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_ATBM8830)
 extern struct dvb_frontend *atbm8830_attach(const struct atbm8830_config *config,
 		struct i2c_adapter *i2c);
 #else

+ 2 - 2
drivers/media/dvb-frontends/au8522.h

@@ -22,6 +22,7 @@
 #ifndef __AU8522_H__
 #define __AU8522_H__
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 enum au8522_if_freq {
@@ -60,8 +61,7 @@ struct au8522_config {
 	enum au8522_if_freq qam_if;
 };
 
-#if defined(CONFIG_DVB_AU8522) || 				\
-	    (defined(CONFIG_DVB_AU8522_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_AU8522_DTV)
 extern struct dvb_frontend *au8522_attach(const struct au8522_config *config,
 					  struct i2c_adapter *i2c);
 #else

+ 38 - 87
drivers/media/dvb-frontends/au8522_decoder.c

@@ -229,15 +229,11 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
 	/* Provide reasonable defaults for picture tuning values */
 	au8522_writereg(state, AU8522_TVDEC_SHARPNESSREG009H, 0x07);
 	au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, 0xed);
-	state->brightness = 0xed - 128;
 	au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, 0x79);
-	state->contrast = 0x79;
 	au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH, 0x80);
 	au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH, 0x80);
-	state->saturation = 0x80;
 	au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00);
 	au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00);
-	state->hue = 0x00;
 
 	/* Other decoder registers */
 	au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00);
@@ -489,75 +485,32 @@ static void set_audio_input(struct au8522_state *state, int aud_input)
 
 /* ----------------------------------------------------------------------- */
 
-static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int au8522_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct au8522_state *state = to_state(sd);
+	struct au8522_state *state =
+		container_of(ctrl->handler, struct au8522_state, hdl);
 
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		state->brightness = ctrl->value;
 		au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH,
-				ctrl->value - 128);
+				ctrl->val - 128);
 		break;
 	case V4L2_CID_CONTRAST:
-		state->contrast = ctrl->value;
 		au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH,
-				ctrl->value);
+				ctrl->val);
 		break;
 	case V4L2_CID_SATURATION:
-		state->saturation = ctrl->value;
 		au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH,
-				ctrl->value);
+				ctrl->val);
 		au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH,
-				ctrl->value);
+				ctrl->val);
 		break;
 	case V4L2_CID_HUE:
-		state->hue = ctrl->value;
 		au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH,
-				ctrl->value >> 8);
+				ctrl->val >> 8);
 		au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH,
-				ctrl->value & 0xFF);
-		break;
-	case V4L2_CID_AUDIO_VOLUME:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_MUTE:
-		/* Not yet implemented */
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct au8522_state *state = to_state(sd);
-
-	/* Note that we are using values cached in the state structure instead
-	   of reading the registers due to issues with i2c reads not working
-	   properly/consistently yet on the HVR-950q */
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		ctrl->value = state->brightness;
-		break;
-	case V4L2_CID_CONTRAST:
-		ctrl->value = state->contrast;
+				ctrl->val & 0xFF);
 		break;
-	case V4L2_CID_SATURATION:
-		ctrl->value = state->saturation;
-		break;
-	case V4L2_CID_HUE:
-		ctrl->value = state->hue;
-		break;
-	case V4L2_CID_AUDIO_VOLUME:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_MUTE:
-		/* Not yet supported */
 	default:
 		return -EINVAL;
 	}
@@ -583,7 +536,7 @@ static int au8522_g_register(struct v4l2_subdev *sd,
 }
 
 static int au8522_s_register(struct v4l2_subdev *sd,
-			     struct v4l2_dbg_register *reg)
+			     const struct v4l2_dbg_register *reg)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct au8522_state *state = to_state(sd);
@@ -616,26 +569,6 @@ static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
 	return 0;
 }
 
-static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
-{
-	switch (qc->id) {
-	case V4L2_CID_CONTRAST:
-		return v4l2_ctrl_query_fill(qc, 0, 255, 1,
-					    AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
-	case V4L2_CID_BRIGHTNESS:
-		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 109);
-	case V4L2_CID_SATURATION:
-		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
-	case V4L2_CID_HUE:
-		return v4l2_ctrl_query_fill(qc, -32768, 32768, 1, 0);
-	default:
-		break;
-	}
-
-	qc->type = 0;
-	return -EINVAL;
-}
-
 static int au8522_reset(struct v4l2_subdev *sd, u32 val)
 {
 	struct au8522_state *state = to_state(sd);
@@ -712,20 +645,11 @@ static int au8522_g_chip_ident(struct v4l2_subdev *sd,
 	return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev);
 }
 
-static int au8522_log_status(struct v4l2_subdev *sd)
-{
-	/* FIXME: Add some status info here */
-	return 0;
-}
-
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops au8522_core_ops = {
-	.log_status = au8522_log_status,
+	.log_status = v4l2_ctrl_subdev_log_status,
 	.g_chip_ident = au8522_g_chip_ident,
-	.g_ctrl = au8522_g_ctrl,
-	.s_ctrl = au8522_s_ctrl,
-	.queryctrl = au8522_queryctrl,
 	.reset = au8522_reset,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register = au8522_g_register,
@@ -753,12 +677,17 @@ static const struct v4l2_subdev_ops au8522_ops = {
 	.video = &au8522_video_ops,
 };
 
+static const struct v4l2_ctrl_ops au8522_ctrl_ops = {
+	.s_ctrl = au8522_s_ctrl,
+};
+
 /* ----------------------------------------------------------------------- */
 
 static int au8522_probe(struct i2c_client *client,
 			const struct i2c_device_id *did)
 {
 	struct au8522_state *state;
+	struct v4l2_ctrl_handler *hdl;
 	struct v4l2_subdev *sd;
 	int instance;
 	struct au8522_config *demod_config;
@@ -799,6 +728,27 @@ static int au8522_probe(struct i2c_client *client,
 	sd = &state->sd;
 	v4l2_i2c_subdev_init(sd, client, &au8522_ops);
 
+	hdl = &state->hdl;
+	v4l2_ctrl_handler_init(hdl, 4);
+	v4l2_ctrl_new_std(hdl, &au8522_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 109);
+	v4l2_ctrl_new_std(hdl, &au8522_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 255, 1,
+			AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
+	v4l2_ctrl_new_std(hdl, &au8522_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(hdl, &au8522_ctrl_ops,
+			V4L2_CID_HUE, -32768, 32767, 1, 0);
+	sd->ctrl_handler = hdl;
+	if (hdl->error) {
+		int err = hdl->error;
+
+		v4l2_ctrl_handler_free(hdl);
+		kfree(demod_config);
+		kfree(state);
+		return err;
+	}
+
 	state->c = client;
 	state->vid_input = AU8522_COMPOSITE_CH1;
 	state->aud_input = AU8522_AUDIO_NONE;
@@ -815,6 +765,7 @@ static int au8522_remove(struct i2c_client *client)
 {
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
 	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(sd->ctrl_handler);
 	au8522_release_state(to_state(sd));
 	return 0;
 }

+ 2 - 4
drivers/media/dvb-frontends/au8522_priv.h

@@ -29,6 +29,7 @@
 #include <linux/delay.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 #include "au8522.h"
@@ -65,10 +66,7 @@ struct au8522_state {
 	int aud_input;
 	u32 id;
 	u32 rev;
-	u8 brightness;
-	u8 contrast;
-	u8 saturation;
-	s16 hue;
+	struct v4l2_ctrl_handler hdl;
 };
 
 /* These are routines shared by both the VSB/QAM demodulator and the analog

+ 2 - 2
drivers/media/dvb-frontends/cx22702.h

@@ -28,6 +28,7 @@
 #ifndef CX22702_H
 #define CX22702_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct cx22702_config {
@@ -40,8 +41,7 @@ struct cx22702_config {
 	u8 output_mode;
 };
 
-#if defined(CONFIG_DVB_CX22702) || (defined(CONFIG_DVB_CX22702_MODULE) \
-	&& defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_CX22702)
 extern struct dvb_frontend *cx22702_attach(
 	const struct cx22702_config *config,
 	struct i2c_adapter *i2c);

+ 3 - 2
drivers/media/dvb-frontends/cx24113.h

@@ -22,6 +22,8 @@
 #ifndef CX24113_H
 #define CX24113_H
 
+#include <linux/kconfig.h>
+
 struct dvb_frontend;
 
 struct cx24113_config {
@@ -30,8 +32,7 @@ struct cx24113_config {
 	u32 xtal_khz;
 };
 
-#if defined(CONFIG_DVB_TUNER_CX24113) || \
-	(defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_TUNER_CX24113)
 extern struct dvb_frontend *cx24113_attach(struct dvb_frontend *,
 	const struct cx24113_config *config, struct i2c_adapter *i2c);
 

+ 2 - 2
drivers/media/dvb-frontends/cx24116.h

@@ -21,6 +21,7 @@
 #ifndef CX24116_H
 #define CX24116_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct cx24116_config {
@@ -40,8 +41,7 @@ struct cx24116_config {
 	u16 i2c_wr_max;
 };
 
-#if defined(CONFIG_DVB_CX24116) || \
-	(defined(CONFIG_DVB_CX24116_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_CX24116)
 extern struct dvb_frontend *cx24116_attach(
 	const struct cx24116_config *config,
 	struct i2c_adapter *i2c);

+ 7 - 21
drivers/media/dvb-frontends/cx24123.c

@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <asm/div64.h>
 
 #include "dvb_frontend.h"
 #include "cx24123.h"
@@ -452,7 +453,8 @@ static u32 cx24123_int_log2(u32 a, u32 b)
 
 static int cx24123_set_symbolrate(struct cx24123_state *state, u32 srate)
 {
-	u32 tmp, sample_rate, ratio, sample_gain;
+	u64 tmp;
+	u32 sample_rate, ratio, sample_gain;
 	u8 pll_mult;
 
 	/*  check if symbol rate is within limits */
@@ -482,27 +484,11 @@ static int cx24123_set_symbolrate(struct cx24123_state *state, u32 srate)
 
 	sample_rate = pll_mult * XTAL;
 
-	/*
-	    SYSSymbolRate[21:0] = (srate << 23) / sample_rate
-
-	    We have to use 32 bit unsigned arithmetic without precision loss.
-	    The maximum srate is 45000000 or 0x02AEA540. This number has
-	    only 6 clear bits on top, hence we can shift it left only 6 bits
-	    at a time. Borrowed from cx24110.c
-	*/
-
-	tmp = srate << 6;
-	ratio = tmp / sample_rate;
-
-	tmp = (tmp % sample_rate) << 6;
-	ratio = (ratio << 6) + (tmp / sample_rate);
-
-	tmp = (tmp % sample_rate) << 6;
-	ratio = (ratio << 6) + (tmp / sample_rate);
-
-	tmp = (tmp % sample_rate) << 5;
-	ratio = (ratio << 5) + (tmp / sample_rate);
+	/* SYSSymbolRate[21:0] = (srate << 23) / sample_rate */
 
+	tmp = ((u64)srate) << 23;
+	do_div(tmp, sample_rate);
+	ratio = (u32) tmp;
 
 	cx24123_writereg(state, 0x01, pll_mult * 6);
 

+ 2 - 2
drivers/media/dvb-frontends/cx24123.h

@@ -21,6 +21,7 @@
 #ifndef CX24123_H
 #define CX24123_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct cx24123_config {
@@ -38,8 +39,7 @@ struct cx24123_config {
 	void (*agc_callback) (struct dvb_frontend *);
 };
 
-#if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) \
-	&& defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_CX24123)
 extern struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
 					   struct i2c_adapter *i2c);
 extern struct i2c_adapter *cx24123_get_tuner_i2c_adapter(struct dvb_frontend *);

+ 2 - 2
drivers/media/dvb-frontends/cxd2820r.h

@@ -22,6 +22,7 @@
 #ifndef CXD2820R_H
 #define CXD2820R_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 #define CXD2820R_GPIO_D (0 << 0) /* disable */
@@ -65,8 +66,7 @@ struct cxd2820r_config {
 };
 
 
-#if defined(CONFIG_DVB_CXD2820R) || \
-	(defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_CXD2820R)
 extern struct dvb_frontend *cxd2820r_attach(
 	const struct cxd2820r_config *config,
 	struct i2c_adapter *i2c,

+ 2 - 1
drivers/media/dvb-frontends/cxd2820r_core.c

@@ -660,7 +660,8 @@ static const struct dvb_frontend_ops cxd2820r_ops = {
 			FE_CAN_GUARD_INTERVAL_AUTO	|
 			FE_CAN_HIERARCHY_AUTO		|
 			FE_CAN_MUTE_TS			|
-			FE_CAN_2G_MODULATION
+			FE_CAN_2G_MODULATION		|
+			FE_CAN_MULTISTREAM
 		},
 
 	.release		= cxd2820r_release,

+ 17 - 0
drivers/media/dvb-frontends/cxd2820r_t2.c

@@ -124,6 +124,23 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
 	buf[1] = ((if_ctl >>  8) & 0xff);
 	buf[2] = ((if_ctl >>  0) & 0xff);
 
+	/* PLP filtering */
+	if (c->stream_id > 255) {
+		dev_dbg(&priv->i2c->dev, "%s: Disable PLP filtering\n", __func__);
+		ret = cxd2820r_wr_reg(priv, 0x023ad , 0);
+		if (ret)
+			goto error;
+	} else {
+		dev_dbg(&priv->i2c->dev, "%s: Enable PLP filtering = %d\n", __func__,
+				c->stream_id);
+		ret = cxd2820r_wr_reg(priv, 0x023af , c->stream_id & 0xFF);
+		if (ret)
+			goto error;
+		ret = cxd2820r_wr_reg(priv, 0x023ad , 1);
+		if (ret)
+			goto error;
+	}
+
 	ret = cxd2820r_wr_regs(priv, 0x020b6, buf, 3);
 	if (ret)
 		goto error;

+ 208 - 226
drivers/media/dvb-frontends/dib0090.c

@@ -528,20 +528,19 @@ static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_
 	u16 PllCfg, i, v;
 
 	HARD_RESET(state);
-
 	dib0090_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
-	dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL);	/* PLL, DIG_CLK and CRYSTAL remain */
+	if (cfg->in_soc)
+		return;
 
-	if (!cfg->in_soc) {
-		/* adcClkOutRatio=8->7, release reset */
-		dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
-		if (cfg->clkoutdrive != 0)
-			dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
-					  | (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
-		else
-			dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
-					  | (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
-	}
+	dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL);	/* PLL, DIG_CLK and CRYSTAL remain */
+	/* adcClkOutRatio=8->7, release reset */
+	dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
+	if (cfg->clkoutdrive != 0)
+		dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
+				| (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
+	else
+		dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
+				| (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
 
 	/* Read Pll current config * */
 	PllCfg = dib0090_read_reg(state, 0x21);
@@ -694,192 +693,174 @@ void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
 EXPORT_SYMBOL(dib0090_dcc_freq);
 
 static const u16 bb_ramp_pwm_normal_socs[] = {
-	550,			/* max BB gain in 10th of dB */
-	(1 << 9) | 8,		/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
+	550, /* max BB gain in 10th of dB */
+	(1<<9) | 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
 	440,
-	(4 << 9) | 0,		/* BB_RAMP3 = 26dB */
-	(0 << 9) | 208,		/* BB_RAMP4 */
-	(4 << 9) | 208,		/* BB_RAMP5 = 29dB */
-	(0 << 9) | 440,		/* BB_RAMP6 */
+	(4  << 9) | 0, /* BB_RAMP3 = 26dB */
+	(0  << 9) | 208, /* BB_RAMP4 */
+	(4  << 9) | 208, /* BB_RAMP5 = 29dB */
+	(0  << 9) | 440, /* BB_RAMP6 */
 };
 
-static const u16 rf_ramp_pwm_cband_7090[] = {
-	280,			/* max RF gain in 10th of dB */
-	18,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
-	504,			/* ramp_max = maximum X used on the ramp */
-	(29 << 10) | 364,	/* RF_RAMP5, LNA 1 = 8dB */
-	(0 << 10) | 504,	/* RF_RAMP6, LNA 1 */
-	(60 << 10) | 228,	/* RF_RAMP7, LNA 2 = 7.7dB */
-	(0 << 10) | 364,	/* RF_RAMP8, LNA 2 */
-	(34 << 10) | 109,	/* GAIN_4_1, LNA 3 = 6.8dB */
-	(0 << 10) | 228,	/* GAIN_4_2, LNA 3 */
-	(37 << 10) | 0,		/* RF_RAMP3, LNA 4 = 6.2dB */
-	(0 << 10) | 109,	/* RF_RAMP4, LNA 4 */
+static const u16 rf_ramp_pwm_cband_7090p[] = {
+	280, /* max RF gain in 10th of dB */
+	18, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	504, /* ramp_max = maximum X used on the ramp */
+	(29 << 10) | 364, /* RF_RAMP5, LNA 1 = 8dB */
+	(0  << 10) | 504, /* RF_RAMP6, LNA 1 */
+	(60 << 10) | 228, /* RF_RAMP7, LNA 2 = 7.7dB */
+	(0  << 10) | 364, /* RF_RAMP8, LNA 2 */
+	(34 << 10) | 109, /* GAIN_4_1, LNA 3 = 6.8dB */
+	(0  << 10) | 228, /* GAIN_4_2, LNA 3 */
+	(37 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */
+	(0  << 10) | 109, /* RF_RAMP4, LNA 4 */
 };
 
-static const uint16_t rf_ramp_pwm_cband_7090e_sensitivity[] = {
-	186,
-	40,
-	746,
-	(10 << 10) | 345,
-	(0  << 10) | 746,
-	(0 << 10) | 0,
-	(0  << 10) | 0,
-	(28 << 10) | 200,
-	(0  << 10) | 345,
-	(20 << 10) | 0,
-	(0  << 10) | 200,
+static const u16 rf_ramp_pwm_cband_7090e_sensitivity[] = {
+	186, /* max RF gain in 10th of dB */
+	40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	746, /* ramp_max = maximum X used on the ramp */
+	(10 << 10) | 345, /* RF_RAMP5, LNA 1 = 10dB */
+	(0  << 10) | 746, /* RF_RAMP6, LNA 1 */
+	(0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */
+	(0  << 10) | 0, /* RF_RAMP8, LNA 2 */
+	(28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */
+	(0  << 10) | 345, /* GAIN_4_2, LNA 3 */
+	(20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */
+	(0  << 10) | 200, /* RF_RAMP4, LNA 4 */
 };
 
-static const uint16_t rf_ramp_pwm_cband_7090e_aci[] = {
-	86,
-	40,
-	345,
-	(0 << 10) | 0,
-	(0 << 10) | 0,
-	(0 << 10) | 0,
-	(0 << 10) | 0,
-	(28 << 10) | 200,
-	(0  << 10) | 345,
-	(20 << 10) | 0,
-	(0  << 10) | 200,
+static const u16 rf_ramp_pwm_cband_7090e_aci[] = {
+	86, /* max RF gain in 10th of dB */
+	40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	345, /* ramp_max = maximum X used on the ramp */
+	(0 << 10) | 0, /* RF_RAMP5, LNA 1 = 8dB */ /* 7.47 dB */
+	(0 << 10) | 0, /* RF_RAMP6, LNA 1 */
+	(0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */
+	(0 << 10) | 0, /* RF_RAMP8, LNA 2 */
+	(28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */
+	(0  << 10) | 345, /* GAIN_4_2, LNA 3 */
+	(20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */
+	(0  << 10) | 200, /* RF_RAMP4, LNA 4 */
 };
 
 static const u16 rf_ramp_pwm_cband_8090[] = {
-	345,			/* max RF gain in 10th of dB */
-	29,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
-	1000,			/* ramp_max = maximum X used on the ramp */
-	(35 << 10) | 772,	/* RF_RAMP3, LNA 1 = 8dB */
-	(0 << 10) | 1000,	/* RF_RAMP4, LNA 1 */
-	(58 << 10) | 496,	/* RF_RAMP5, LNA 2 = 9.5dB */
-	(0 << 10) | 772,	/* RF_RAMP6, LNA 2 */
-	(27 << 10) | 200,	/* RF_RAMP7, LNA 3 = 10.5dB */
-	(0 << 10) | 496,	/* RF_RAMP8, LNA 3 */
-	(40 << 10) | 0,		/* GAIN_4_1, LNA 4 = 7dB */
-	(0 << 10) | 200,	/* GAIN_4_2, LNA 4 */
+	345, /* max RF gain in 10th of dB */
+	29, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	1000, /* ramp_max = maximum X used on the ramp */
+	(35 << 10) | 772, /* RF_RAMP3, LNA 1 = 8dB */
+	(0  << 10) | 1000, /* RF_RAMP4, LNA 1 */
+	(58 << 10) | 496, /* RF_RAMP5, LNA 2 = 9.5dB */
+	(0  << 10) | 772, /* RF_RAMP6, LNA 2 */
+	(27 << 10) | 200, /* RF_RAMP7, LNA 3 = 10.5dB */
+	(0  << 10) | 496, /* RF_RAMP8, LNA 3 */
+	(40 << 10) | 0, /* GAIN_4_1, LNA 4 = 7dB */
+	(0  << 10) | 200, /* GAIN_4_2, LNA 4 */
 };
 
 static const u16 rf_ramp_pwm_uhf_7090[] = {
-	407,			/* max RF gain in 10th of dB */
-	13,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
-	529,			/* ramp_max = maximum X used on the ramp */
-	(23 << 10) | 0,		/* RF_RAMP3, LNA 1 = 14.7dB */
-	(0 << 10) | 176,	/* RF_RAMP4, LNA 1 */
-	(63 << 10) | 400,	/* RF_RAMP5, LNA 2 = 8dB */
-	(0 << 10) | 529,	/* RF_RAMP6, LNA 2 */
-	(48 << 10) | 316,	/* RF_RAMP7, LNA 3 = 6.8dB */
-	(0 << 10) | 400,	/* RF_RAMP8, LNA 3 */
-	(29 << 10) | 176,	/* GAIN_4_1, LNA 4 = 11.5dB */
-	(0 << 10) | 316,	/* GAIN_4_2, LNA 4 */
+	407, /* max RF gain in 10th of dB */
+	13, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	529, /* ramp_max = maximum X used on the ramp */
+	(23 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
+	(0  << 10) | 176, /* RF_RAMP4, LNA 1 */
+	(63 << 10) | 400, /* RF_RAMP5, LNA 2 = 8dB */
+	(0  << 10) | 529, /* RF_RAMP6, LNA 2 */
+	(48 << 10) | 316, /* RF_RAMP7, LNA 3 = 6.8dB */
+	(0  << 10) | 400, /* RF_RAMP8, LNA 3 */
+	(29 << 10) | 176, /* GAIN_4_1, LNA 4 = 11.5dB */
+	(0  << 10) | 316, /* GAIN_4_2, LNA 4 */
 };
 
 static const u16 rf_ramp_pwm_uhf_8090[] = {
-	388,			/* max RF gain in 10th of dB */
-	26,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
-	1008,			/* ramp_max = maximum X used on the ramp */
-	(11 << 10) | 0,		/* RF_RAMP3, LNA 1 = 14.7dB */
-	(0 << 10) | 369,	/* RF_RAMP4, LNA 1 */
-	(41 << 10) | 809,	/* RF_RAMP5, LNA 2 = 8dB */
-	(0 << 10) | 1008,	/* RF_RAMP6, LNA 2 */
-	(27 << 10) | 659,	/* RF_RAMP7, LNA 3 = 6dB */
-	(0 << 10) | 809,	/* RF_RAMP8, LNA 3 */
-	(14 << 10) | 369,	/* GAIN_4_1, LNA 4 = 11.5dB */
-	(0 << 10) | 659,	/* GAIN_4_2, LNA 4 */
+	388, /* max RF gain in 10th of dB */
+	26, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	1008, /* ramp_max = maximum X used on the ramp */
+	(11 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
+	(0  << 10) | 369, /* RF_RAMP4, LNA 1 */
+	(41 << 10) | 809, /* RF_RAMP5, LNA 2 = 8dB */
+	(0  << 10) | 1008, /* RF_RAMP6, LNA 2 */
+	(27 << 10) | 659, /* RF_RAMP7, LNA 3 = 6dB */
+	(0  << 10) | 809, /* RF_RAMP8, LNA 3 */
+	(14 << 10) | 369, /* GAIN_4_1, LNA 4 = 11.5dB */
+	(0  << 10) | 659, /* GAIN_4_2, LNA 4 */
 };
 
-static const u16 rf_ramp_pwm_cband[] = {
-	0,			/* max RF gain in 10th of dB */
-	0,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
-	0,			/* ramp_max = maximum X used on the ramp */
-	(0 << 10) | 0,		/* 0x2c, LNA 1 = 0dB */
-	(0 << 10) | 0,		/* 0x2d, LNA 1 */
-	(0 << 10) | 0,		/* 0x2e, LNA 2 = 0dB */
-	(0 << 10) | 0,		/* 0x2f, LNA 2 */
-	(0 << 10) | 0,		/* 0x30, LNA 3 = 0dB */
-	(0 << 10) | 0,		/* 0x31, LNA 3 */
-	(0 << 10) | 0,		/* GAIN_4_1, LNA 4 = 0dB */
-	(0 << 10) | 0,		/* GAIN_4_2, LNA 4 */
-};
-
-static const u16 rf_ramp_vhf[] = {
-	412,			/* max RF gain in 10th of dB */
-	132, 307, 127,		/* LNA1,  13.2dB */
-	105, 412, 255,		/* LNA2,  10.5dB */
-	50, 50, 127,		/* LNA3,  5dB */
-	125, 175, 127,		/* LNA4,  12.5dB */
-	0, 0, 127,		/* CBAND, 0dB */
-};
-
-static const u16 rf_ramp_uhf[] = {
-	412,			/* max RF gain in 10th of dB */
-	132, 307, 127,		/* LNA1  : total gain = 13.2dB, point on the ramp where this amp is full gain, value to write to get full gain */
-	105, 412, 255,		/* LNA2  : 10.5 dB */
-	50, 50, 127,		/* LNA3  :  5.0 dB */
-	125, 175, 127,		/* LNA4  : 12.5 dB */
-	0, 0, 127,		/* CBAND :  0.0 dB */
+/* GENERAL PWM ramp definition for all other Krosus */
+static const u16 bb_ramp_pwm_normal[] = {
+	500, /* max BB gain in 10th of dB */
+	8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
+	400,
+	(2  << 9) | 0, /* BB_RAMP3 = 21dB */
+	(0  << 9) | 168, /* BB_RAMP4 */
+	(2  << 9) | 168, /* BB_RAMP5 = 29dB */
+	(0  << 9) | 400, /* BB_RAMP6 */
 };
 
-static const u16 rf_ramp_cband_broadmatching[] =	/* for p1G only */
-{
-	314,			/* Calibrated at 200MHz order has been changed g4-g3-g2-g1 */
-	84, 314, 127,		/* LNA1 */
-	80, 230, 255,		/* LNA2 */
-	80, 150, 127,		/* LNA3  It was measured 12dB, do not lock if 120 */
-	70, 70, 127,		/* LNA4 */
-	0, 0, 127,		/* CBAND */
+static const u16 bb_ramp_pwm_boost[] = {
+	550, /* max BB gain in 10th of dB */
+	8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
+	440,
+	(2  << 9) | 0, /* BB_RAMP3 = 26dB */
+	(0  << 9) | 208, /* BB_RAMP4 */
+	(2  << 9) | 208, /* BB_RAMP5 = 29dB */
+	(0  << 9) | 440, /* BB_RAMP6 */
 };
 
-static const u16 rf_ramp_cband[] = {
-	332,			/* max RF gain in 10th of dB */
-	132, 252, 127,		/* LNA1,  dB */
-	80, 332, 255,		/* LNA2,  dB */
-	0, 0, 127,		/* LNA3,  dB */
-	0, 0, 127,		/* LNA4,  dB */
-	120, 120, 127,		/* LT1 CBAND */
+static const u16 rf_ramp_pwm_cband[] = {
+	314, /* max RF gain in 10th of dB */
+	33, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	1023, /* ramp_max = maximum X used on the ramp */
+	(8  << 10) | 743, /* RF_RAMP3, LNA 1 = 0dB */
+	(0  << 10) | 1023, /* RF_RAMP4, LNA 1 */
+	(15 << 10) | 469, /* RF_RAMP5, LNA 2 = 0dB */
+	(0  << 10) | 742, /* RF_RAMP6, LNA 2 */
+	(9  << 10) | 234, /* RF_RAMP7, LNA 3 = 0dB */
+	(0  << 10) | 468, /* RF_RAMP8, LNA 3 */
+	(9  << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
+	(0  << 10) | 233, /* GAIN_4_2, LNA 4 */
 };
 
 static const u16 rf_ramp_pwm_vhf[] = {
-	404,			/* max RF gain in 10th of dB */
-	25,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
-	1011,			/* ramp_max = maximum X used on the ramp */
-	(6 << 10) | 417,	/* 0x2c, LNA 1 = 13.2dB */
-	(0 << 10) | 756,	/* 0x2d, LNA 1 */
-	(16 << 10) | 756,	/* 0x2e, LNA 2 = 10.5dB */
-	(0 << 10) | 1011,	/* 0x2f, LNA 2 */
-	(16 << 10) | 290,	/* 0x30, LNA 3 = 5dB */
-	(0 << 10) | 417,	/* 0x31, LNA 3 */
-	(7 << 10) | 0,		/* GAIN_4_1, LNA 4 = 12.5dB */
-	(0 << 10) | 290,	/* GAIN_4_2, LNA 4 */
+	398, /* max RF gain in 10th of dB */
+	24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	954, /* ramp_max = maximum X used on the ramp */
+	(7  << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */
+	(0  << 10) | 290, /* RF_RAMP4, LNA 1 */
+	(16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */
+	(0  << 10) | 954, /* RF_RAMP6, LNA 2 */
+	(17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */
+	(0  << 10) | 699, /* RF_RAMP8, LNA 3 */
+	(7  << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */
+	(0  << 10) | 580, /* GAIN_4_2, LNA 4 */
 };
 
 static const u16 rf_ramp_pwm_uhf[] = {
-	404,			/* max RF gain in 10th of dB */
-	25,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
-	1011,			/* ramp_max = maximum X used on the ramp */
-	(6 << 10) | 417,	/* 0x2c, LNA 1 = 13.2dB */
-	(0 << 10) | 756,	/* 0x2d, LNA 1 */
-	(16 << 10) | 756,	/* 0x2e, LNA 2 = 10.5dB */
-	(0 << 10) | 1011,	/* 0x2f, LNA 2 */
-	(16 << 10) | 0,		/* 0x30, LNA 3 = 5dB */
-	(0 << 10) | 127,	/* 0x31, LNA 3 */
-	(7 << 10) | 127,	/* GAIN_4_1, LNA 4 = 12.5dB */
-	(0 << 10) | 417,	/* GAIN_4_2, LNA 4 */
+	398, /* max RF gain in 10th of dB */
+	24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	954, /* ramp_max = maximum X used on the ramp */
+	(7  << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */
+	(0  << 10) | 290, /* RF_RAMP4, LNA 1 */
+	(16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */
+	(0  << 10) | 954, /* RF_RAMP6, LNA 2 */
+	(17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */
+	(0  << 10) | 699, /* RF_RAMP8, LNA 3 */
+	(7  << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */
+	(0  << 10) | 580, /* GAIN_4_2, LNA 4 */
 };
 
-static const u16 bb_ramp_boost[] = {
-	550,			/* max BB gain in 10th of dB */
-	260, 260, 26,		/* BB1, 26dB */
-	290, 550, 29,		/* BB2, 29dB */
-};
-
-static const u16 bb_ramp_pwm_normal[] = {
-	500,			/* max RF gain in 10th of dB */
-	8,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x34 */
-	400,
-	(2 << 9) | 0,		/* 0x35 = 21dB */
-	(0 << 9) | 168,		/* 0x36 */
-	(2 << 9) | 168,		/* 0x37 = 29dB */
-	(0 << 9) | 400,		/* 0x38 */
+static const u16 rf_ramp_pwm_sband[] = {
+	253, /* max RF gain in 10th of dB */
+	38, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	961,
+	(4  << 10) | 0, /* RF_RAMP3, LNA 1 = 14.1dB */
+	(0  << 10) | 508, /* RF_RAMP4, LNA 1 */
+	(9  << 10) | 508, /* RF_RAMP5, LNA 2 = 11.2dB */
+	(0  << 10) | 961, /* RF_RAMP6, LNA 2 */
+	(0  << 10) | 0, /* RF_RAMP7, LNA 3 = 0dB */
+	(0  << 10) | 0, /* RF_RAMP8, LNA 3 */
+	(0  << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
+	(0  << 10) | 0, /* GAIN_4_2, LNA 4 */
 };
 
 struct slope {
@@ -1089,70 +1070,69 @@ static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
 void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
 {
 	struct dib0090_state *state = fe->tuner_priv;
-	/* reset the AGC */
+	u16 *bb_ramp = (u16 *)&bb_ramp_pwm_normal; /* default baseband config */
+	u16 *rf_ramp = NULL;
+	u8 en_pwm_rf_mux = 1;
 
+	/* reset the AGC */
 	if (state->config->use_pwm_agc) {
-#ifdef CONFIG_BAND_SBAND
-		if (state->current_band == BAND_SBAND) {
-			dib0090_set_rframp_pwm(state, rf_ramp_pwm_sband);
-			dib0090_set_bbramp_pwm(state, bb_ramp_pwm_boost);
-		} else
-#endif
-#ifdef CONFIG_BAND_CBAND
 		if (state->current_band == BAND_CBAND) {
 			if (state->identity.in_soc) {
-				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
+				bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
 				if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
-					dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_8090);
-				else if (state->identity.version == SOC_7090_P1G_11R1
-						|| state->identity.version == SOC_7090_P1G_21R1) {
+					rf_ramp = (u16 *)&rf_ramp_pwm_cband_8090;
+				else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1) {
 					if (state->config->is_dib7090e) {
 						if (state->rf_ramp == NULL)
-							dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090e_sensitivity);
+							rf_ramp = (u16 *)&rf_ramp_pwm_cband_7090e_sensitivity;
 						else
-							dib0090_set_rframp_pwm(state, state->rf_ramp);
+							rf_ramp = (u16 *)state->rf_ramp;
 					} else
-						dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090);
+						rf_ramp = (u16 *)&rf_ramp_pwm_cband_7090p;
 				}
-			} else {
-				dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband);
-				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
-			}
+			} else
+				rf_ramp = (u16 *)&rf_ramp_pwm_cband;
 		} else
-#endif
-#ifdef CONFIG_BAND_VHF
-		if (state->current_band == BAND_VHF) {
-			if (state->identity.in_soc) {
-				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
-			} else {
-				dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf);
-				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
+
+			if (state->current_band == BAND_VHF) {
+				if (state->identity.in_soc) {
+					bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
+					/* rf_ramp = &rf_ramp_pwm_vhf_socs; */ /* TODO */
+				} else
+					rf_ramp = (u16 *)&rf_ramp_pwm_vhf;
+			} else if (state->current_band == BAND_UHF) {
+				if (state->identity.in_soc) {
+					bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
+					if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
+						rf_ramp = (u16 *)&rf_ramp_pwm_uhf_8090;
+					else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
+						rf_ramp = (u16 *)&rf_ramp_pwm_uhf_7090;
+				} else
+					rf_ramp = (u16 *)&rf_ramp_pwm_uhf;
 			}
+		if (rf_ramp)
+			dib0090_set_rframp_pwm(state, rf_ramp);
+		dib0090_set_bbramp_pwm(state, bb_ramp);
+
+		/* activate the ramp generator using PWM control */
+		dprintk("ramp RF gain = %d BAND = %s version = %d", state->rf_ramp[0], (state->current_band == BAND_CBAND) ? "CBAND" : "NOT CBAND", state->identity.version & 0x1f);
+
+		if ((state->rf_ramp[0] == 0) || (state->current_band == BAND_CBAND && (state->identity.version & 0x1f) <= P1D_E_F)) {
+			dprintk("DE-Engage mux for direct gain reg control");
+			en_pwm_rf_mux = 0;
 		} else
-#endif
-		{
-			if (state->identity.in_soc) {
-				if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
-					dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_8090);
-				else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
-					dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_7090);
-				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
-			} else {
-				dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf);
-				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
-			}
-		}
+			dprintk("Engage mux for PWM control");
 
-		if (state->rf_ramp[0] != 0)
-			dib0090_write_reg(state, 0x32, (3 << 11));
-		else
-			dib0090_write_reg(state, 0x32, (0 << 11));
+		dib0090_write_reg(state, 0x32, (en_pwm_rf_mux << 12) | (en_pwm_rf_mux << 11));
 
-		dib0090_write_reg(state, 0x04, 0x03);
-		dib0090_write_reg(state, 0x39, (1 << 10));
+		/* Set fast servo cutoff to start AGC; 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast*/
+		if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
+			dib0090_write_reg(state, 0x04, 3);
+		else
+			dib0090_write_reg(state, 0x04, 1);
+		dib0090_write_reg(state, 0x39, (1 << 10)); /* 0 gain by default */
 	}
 }
-
 EXPORT_SYMBOL(dib0090_pwm_gain_reset);
 
 void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff)
@@ -1193,22 +1173,22 @@ int dib0090_gain_control(struct dvb_frontend *fe)
 #endif
 #ifdef CONFIG_BAND_VHF
 		if (state->current_band == BAND_VHF && !state->identity.p1g) {
-			dib0090_set_rframp(state, rf_ramp_vhf);
-			dib0090_set_bbramp(state, bb_ramp_boost);
+			dib0090_set_rframp(state, rf_ramp_pwm_vhf);
+			dib0090_set_bbramp(state, bb_ramp_pwm_normal);
 		} else
 #endif
 #ifdef CONFIG_BAND_CBAND
 		if (state->current_band == BAND_CBAND && !state->identity.p1g) {
-			dib0090_set_rframp(state, rf_ramp_cband);
-			dib0090_set_bbramp(state, bb_ramp_boost);
+			dib0090_set_rframp(state, rf_ramp_pwm_cband);
+			dib0090_set_bbramp(state, bb_ramp_pwm_normal);
 		} else
 #endif
 		if ((state->current_band == BAND_CBAND || state->current_band == BAND_VHF) && state->identity.p1g) {
-			dib0090_set_rframp(state, rf_ramp_cband_broadmatching);
-			dib0090_set_bbramp(state, bb_ramp_boost);
+			dib0090_set_rframp(state, rf_ramp_pwm_cband_7090p);
+			dib0090_set_bbramp(state, bb_ramp_pwm_normal_socs);
 		} else {
-			dib0090_set_rframp(state, rf_ramp_uhf);
-			dib0090_set_bbramp(state, bb_ramp_boost);
+			dib0090_set_rframp(state, rf_ramp_pwm_uhf);
+			dib0090_set_bbramp(state, bb_ramp_pwm_normal);
 		}
 
 		dib0090_write_reg(state, 0x32, 0);
@@ -1553,14 +1533,16 @@ static void dib0090_set_EFUSE(struct dib0090_state *state)
 
 		if ((c >= CAP_VALUE_MAX) || (c <= CAP_VALUE_MIN))
 			c = 32;
+		else
+			c += 14;
 		if ((h >= HR_MAX) || (h <= HR_MIN))
 			h = 34;
 		if ((n >= POLY_MAX) || (n <= POLY_MIN))
 			n = 3;
 
-		dib0090_write_reg(state, 0x13, (h << 10)) ;
-		e2 = (n<<11) | ((h>>2)<<6) | (c);
-		dib0090_write_reg(state, 0x2, e2) ; /* Load the BB_2 */
+		dib0090_write_reg(state, 0x13, (h << 10));
+		e2 = (n << 11) | ((h >> 2)<<6) | c;
+		dib0090_write_reg(state, 0x2, e2); /* Load the BB_2 */
 	}
 }
 

+ 3 - 2
drivers/media/dvb-frontends/dib3000mc.h

@@ -13,6 +13,8 @@
 #ifndef DIB3000MC_H
 #define DIB3000MC_H
 
+#include <linux/kconfig.h>
+
 #include "dibx000_common.h"
 
 struct dib3000mc_config {
@@ -39,8 +41,7 @@ struct dib3000mc_config {
 #define DEFAULT_DIB3000MC_I2C_ADDRESS 16
 #define DEFAULT_DIB3000P_I2C_ADDRESS  24
 
-#if defined(CONFIG_DVB_DIB3000MC) || (defined(CONFIG_DVB_DIB3000MC_MODULE) && \
-				      defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_DIB3000MC)
 extern struct dvb_frontend *dib3000mc_attach(struct i2c_adapter *i2c_adap,
 					     u8 i2c_addr,
 					     struct dib3000mc_config *cfg);

+ 3 - 2
drivers/media/dvb-frontends/dib7000m.h

@@ -1,6 +1,8 @@
 #ifndef DIB7000M_H
 #define DIB7000M_H
 
+#include <linux/kconfig.h>
+
 #include "dibx000_common.h"
 
 struct dib7000m_config {
@@ -38,8 +40,7 @@ struct dib7000m_config {
 
 #define DEFAULT_DIB7000M_I2C_ADDRESS 18
 
-#if defined(CONFIG_DVB_DIB7000M) || (defined(CONFIG_DVB_DIB7000M_MODULE) && \
-				     defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_DIB7000M)
 extern struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap,
 					    u8 i2c_addr,
 					    struct dib7000m_config *cfg);

+ 16 - 1
drivers/media/dvb-frontends/dib7000p.c

@@ -429,6 +429,13 @@ int dib7000p_get_agc_values(struct dvb_frontend *fe,
 }
 EXPORT_SYMBOL(dib7000p_get_agc_values);
 
+int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	return dib7000p_write_word(state, 108,  v);
+}
+EXPORT_SYMBOL(dib7000p_set_agc1_min);
+
 static void dib7000p_reset_pll(struct dib7000p_state *state)
 {
 	struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
@@ -821,6 +828,7 @@ static int dib7000p_agc_startup(struct dvb_frontend *demod)
 	u8 agc_split;
 	u16 reg;
 	u32 upd_demod_gain_period = 0x1000;
+	s32 frequency_offset = 0;
 
 	switch (state->agc_state) {
 	case 0:
@@ -841,7 +849,14 @@ static int dib7000p_agc_startup(struct dvb_frontend *demod)
 		if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency / 1000)) != 0)
 			return -1;
 
-		dib7000p_set_dds(state, 0);
+		if (demod->ops.tuner_ops.get_frequency) {
+			u32 frequency_tuner;
+
+			demod->ops.tuner_ops.get_frequency(demod, &frequency_tuner);
+			frequency_offset = (s32)frequency_tuner / 1000 - ch->frequency / 1000;
+		}
+
+		dib7000p_set_dds(state, frequency_offset);
 		ret = 7;
 		(*agc_state)++;
 		break;

+ 10 - 2
drivers/media/dvb-frontends/dib7000p.h

@@ -1,6 +1,8 @@
 #ifndef DIB7000P_H
 #define DIB7000P_H
 
+#include <linux/kconfig.h>
+
 #include "dibx000_common.h"
 
 struct dib7000p_config {
@@ -44,8 +46,7 @@ struct dib7000p_config {
 
 #define DEFAULT_DIB7000P_I2C_ADDRESS 18
 
-#if defined(CONFIG_DVB_DIB7000P) || (defined(CONFIG_DVB_DIB7000P_MODULE) && \
-					defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_DIB7000P)
 extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
 extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
 extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
@@ -62,6 +63,7 @@ extern struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe);
 extern int dib7090_slave_reset(struct dvb_frontend *fe);
 extern int dib7000p_get_agc_values(struct dvb_frontend *fe,
 		u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd);
+extern int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v);
 #else
 static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
 {
@@ -153,6 +155,12 @@ static inline int dib7000p_get_agc_values(struct dvb_frontend *fe,
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return -ENODEV;
 }
+
+static inline int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
 #endif
 
 #endif

+ 1340 - 928
drivers/media/dvb-frontends/dib8000.c

@@ -23,8 +23,8 @@
 #define LAYER_B   2
 #define LAYER_C   3
 
-#define FE_CALLBACK_TIME_NEVER 0xffffffff
 #define MAX_NUMBER_OF_FRONTENDS 6
+/* #define DIB8000_AGC_FREEZE */
 
 static int debug;
 module_param(debug, int, 0644);
@@ -32,8 +32,6 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
 
 #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0)
 
-#define FE_STATUS_TUNE_FAILED 0
-
 struct i2c_device {
 	struct i2c_adapter *adap;
 	u8 addr;
@@ -42,6 +40,23 @@ struct i2c_device {
 	struct mutex *i2c_buffer_lock;
 };
 
+enum param_loop_step {
+	LOOP_TUNE_1,
+	LOOP_TUNE_2
+};
+
+enum dib8000_autosearch_step {
+	AS_START = 0,
+	AS_SEARCHING_FFT,
+	AS_SEARCHING_GUARD,
+	AS_DONE = 100,
+};
+
+enum timeout_mode {
+	SYMBOL_DEPENDENT_OFF = 0,
+	SYMBOL_DEPENDENT_ON,
+};
+
 struct dib8000_state {
 	struct dib8000_config cfg;
 
@@ -72,7 +87,7 @@ struct dib8000_state {
 	u16 revision;
 	u8 isdbt_cfg_loaded;
 	enum frontend_tune_state tune_state;
-	u32 status;
+	s32 status;
 
 	struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
 
@@ -85,6 +100,30 @@ struct dib8000_state {
 
 	u16 tuner_enable;
 	struct i2c_adapter dib8096p_tuner_adap;
+	u16 current_demod_bw;
+
+	u16 seg_mask;
+	u16 seg_diff_mask;
+	u16 mode;
+	u8 layer_b_nb_seg;
+	u8 layer_c_nb_seg;
+
+	u8 channel_parameters_set;
+	u16 autosearch_state;
+	u16 found_nfft;
+	u16 found_guard;
+	u8 subchannel;
+	u8 symbol_duration;
+	u32 timeout;
+	u8 longest_intlv_layer;
+	u16 output_mode;
+
+#ifdef DIB8000_AGC_FREEZE
+	u16 agc1_max;
+	u16 agc1_min;
+	u16 agc2_max;
+	u16 agc2_min;
+#endif
 };
 
 enum dib8000_power_mode {
@@ -338,9 +377,9 @@ static void dib8000_set_acquisition_mode(struct dib8000_state *state)
 static int dib8000_set_output_mode(struct dvb_frontend *fe, int mode)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
-
 	u16 outreg, fifo_threshold, smo_mode, sram = 0x0205;	/* by default SDRAM deintlv is enabled */
 
+	state->output_mode = mode;
 	outreg = 0;
 	fifo_threshold = 1792;
 	smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1);
@@ -399,8 +438,9 @@ static int dib8000_set_output_mode(struct dvb_frontend *fe, int mode)
 static int dib8000_set_diversity_in(struct dvb_frontend *fe, int onoff)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
-	u16 sync_wait = dib8000_read_word(state, 273) & 0xfff0;
+	u16 tmp, sync_wait = dib8000_read_word(state, 273) & 0xfff0;
 
+	dprintk("set diversity input to %i", onoff);
 	if (!state->differential_constellation) {
 		dib8000_write_word(state, 272, 1 << 9);	//dvsy_off_lmod4 = 1
 		dib8000_write_word(state, 273, sync_wait | (1 << 2) | 2);	// sync_enable = 1; comb_mode = 2
@@ -424,6 +464,13 @@ static int dib8000_set_diversity_in(struct dvb_frontend *fe, int onoff)
 		dib8000_write_word(state, 271, 1);
 		break;
 	}
+
+	if (state->revision == 0x8002) {
+		tmp = dib8000_read_word(state, 903);
+		dib8000_write_word(state, 903, tmp & ~(1 << 3));
+		msleep(30);
+		dib8000_write_word(state, 903, tmp | (1 << 3));
+	}
 	return 0;
 }
 
@@ -468,27 +515,6 @@ static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_pow
 	dib8000_write_word(state, 1280, reg_1280);
 }
 
-static int dib8000_init_sdram(struct dib8000_state *state)
-{
-	u16 reg = 0;
-	dprintk("Init sdram");
-
-	reg = dib8000_read_word(state, 274)&0xfff0;
-	/* P_dintlv_delay_ram = 7 because of MobileSdram */
-	dib8000_write_word(state, 274, reg | 0x7);
-
-	dib8000_write_word(state, 1803, (7<<2));
-
-	reg = dib8000_read_word(state, 1280);
-	/* force restart P_restart_sdram */
-	dib8000_write_word(state, 1280,  reg | (1<<2));
-
-	/* release restart P_restart_sdram */
-	dib8000_write_word(state, 1280,  reg);
-
-	return 0;
-}
-
 static int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_states no)
 {
 	int ret = 0;
@@ -584,18 +610,23 @@ static int dib8000_set_bandwidth(struct dvb_frontend *fe, u32 bw)
 
 static int dib8000_sad_calib(struct dib8000_state *state)
 {
+	u8 sad_sel = 3;
+
 	if (state->revision == 0x8090) {
-		dprintk("%s: the sad calibration is not needed for the dib8096P",
-				__func__);
-		return 0;
-	}
-	/* internal */
-	dib8000_write_word(state, 923, (0 << 1) | (0 << 0));
-	dib8000_write_word(state, 924, 776);	// 0.625*3.3 / 4096
+		dib8000_write_word(state, 922, (sad_sel << 2));
+		dib8000_write_word(state, 923, 2048);
+
+		dib8000_write_word(state, 922, (sad_sel << 2) | 0x1);
+		dib8000_write_word(state, 922, (sad_sel << 2));
+	} else {
+		/* internal */
+		dib8000_write_word(state, 923, (0 << 1) | (0 << 0));
+		dib8000_write_word(state, 924, 776);
 
-	/* do the calibration */
-	dib8000_write_word(state, 923, (1 << 0));
-	dib8000_write_word(state, 923, (0 << 0));
+		/* do the calibration */
+		dib8000_write_word(state, 923, (1 << 0));
+		dib8000_write_word(state, 923, (0 << 0));
+	}
 
 	msleep(1);
 	return 0;
@@ -609,8 +640,8 @@ int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
 	state->wbd_ref = value;
 	return dib8000_write_word(state, 106, value);
 }
-
 EXPORT_SYMBOL(dib8000_set_wbd_ref);
+
 static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw)
 {
 	dprintk("ifreq: %d %x, inversion: %d", bw->ifreq, bw->ifreq, bw->ifreq >> 25);
@@ -685,20 +716,23 @@ static void dib8000_reset_pll(struct dib8000_state *state)
 }
 
 int dib8000_update_pll(struct dvb_frontend *fe,
-		struct dibx000_bandwidth_config *pll)
+		struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
 	u16 reg_1857, reg_1856 = dib8000_read_word(state, 1856);
-	u8 loopdiv, prediv;
+	u8 loopdiv, prediv, oldprediv = state->cfg.pll->pll_prediv ;
 	u32 internal, xtal;
 
 	/* get back old values */
 	prediv = reg_1856 & 0x3f;
 	loopdiv = (reg_1856 >> 6) & 0x3f;
 
-	if ((pll != NULL) && (pll->pll_prediv != prediv ||
-				pll->pll_ratio != loopdiv)) {
-		dprintk("Updating pll (prediv: old =  %d new = %d ; loopdiv : old = %d new = %d)", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio);
+	if ((pll == NULL) || (pll->pll_prediv == prediv &&
+				pll->pll_ratio == loopdiv))
+		return -EINVAL;
+
+	dprintk("Updating pll (prediv: old =  %d new = %d ; loopdiv : old = %d new = %d)", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio);
+	if (state->revision == 0x8090) {
 		reg_1856 &= 0xf000;
 		reg_1857 = dib8000_read_word(state, 1857);
 		/* disable PLL */
@@ -729,10 +763,33 @@ int dib8000_update_pll(struct dvb_frontend *fe,
 		reg_1856 = dib8000_read_word(state, 1856);
 		dprintk("PLL Updated with prediv = %d and loopdiv = %d",
 				reg_1856&0x3f, (reg_1856>>6)&0x3f);
+	} else {
+		if (bw != state->current_demod_bw) {
+			/** Bandwidth change => force PLL update **/
+			dprintk("PLL: Bandwidth Change %d MHz -> %d MHz (prediv: %d->%d)", state->current_demod_bw / 1000, bw / 1000, oldprediv, state->cfg.pll->pll_prediv);
+
+			if (state->cfg.pll->pll_prediv != oldprediv) {
+				/** Full PLL change only if prediv is changed **/
+
+				/** full update => bypass and reconfigure **/
+				dprintk("PLL: New Setting for %d MHz Bandwidth (prediv: %d, ratio: %d)", bw/1000, state->cfg.pll->pll_prediv, state->cfg.pll->pll_ratio);
+				dib8000_write_word(state, 902, dib8000_read_word(state, 902) | (1<<3)); /* bypass PLL */
+				dib8000_reset_pll(state);
+				dib8000_write_word(state, 898, 0x0004); /* sad */
+			} else
+				ratio = state->cfg.pll->pll_ratio;
 
-		return 0;
-	}
-	return -EINVAL;
+			state->current_demod_bw = bw;
+		}
+
+		if (ratio != 0) {
+			/** ratio update => only change ratio **/
+			dprintk("PLL: Update ratio (prediv: %d, ratio: %d)", state->cfg.pll->pll_prediv, ratio);
+			dib8000_write_word(state, 901, (state->cfg.pll->pll_prediv << 8) | (ratio << 0)); /* only the PLL ratio is updated. */
+		}
+}
+
+	return 0;
 }
 EXPORT_SYMBOL(dib8000_update_pll);
 
@@ -928,7 +985,7 @@ static int dib8000_reset(struct dvb_frontend *fe)
 	dib8000_set_power_mode(state, DIB8000_POWER_ALL);
 
 	/* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
-	dib8000_set_adc_state(state, DIBX000_VBG_ENABLE);
+	dib8000_set_adc_state(state, DIBX000_ADC_OFF);
 
 	/* restart all parts */
 	dib8000_write_word(state, 770, 0xffff);
@@ -992,12 +1049,11 @@ static int dib8000_reset(struct dvb_frontend *fe)
 			l = *n++;
 		}
 	}
-	if (state->revision != 0x8090)
-		dib8000_write_word(state, 903, (0 << 4) | 2);
+
 	state->isdbt_cfg_loaded = 0;
 
 	//div_cfg override for special configs
-	if (state->cfg.div_cfg != 0)
+	if ((state->revision != 8090) && (state->cfg.div_cfg != 0))
 		dib8000_write_word(state, 903, state->cfg.div_cfg);
 
 	/* unforce divstr regardless whether i2c enumeration was done or not */
@@ -1006,10 +1062,12 @@ static int dib8000_reset(struct dvb_frontend *fe)
 	dib8000_set_bandwidth(fe, 6000);
 
 	dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON);
-	if (state->revision != 0x8090) {
-		dib8000_sad_calib(state);
+	dib8000_sad_calib(state);
+	if (state->revision != 0x8090)
 		dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
-	}
+
+	/* ber_rs_len = 3 */
+	dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5));
 
 	dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);
 
@@ -1441,6 +1499,7 @@ static int dib8096p_set_output_mode(struct dvb_frontend *fe, int mode)
 	u8 prefer_mpeg_mux_use = 1;
 	int ret = 0;
 
+	state->output_mode = mode;
 	dib8096p_host_bus_drive(state, 1);
 
 	fifo_threshold = 1792;
@@ -1879,782 +1938,643 @@ static const u16 adc_target_16dB[11] = {
 };
 static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
 
-static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosearching)
+static u16 dib8000_set_layer(struct dib8000_state *state, u8 layer_index, u16 max_constellation)
 {
-	u16 mode, max_constellation, seg_diff_mask = 0, nbseg_diff = 0;
-	u8 guard, crate, constellation, timeI;
-	u16 i, coeff[4], P_cfr_left_edge = 0, P_cfr_right_edge = 0, seg_mask13 = 0x1fff;	// All 13 segments enabled
-	const s16 *ncoeff = NULL, *ana_fe;
-	u16 tmcc_pow = 0;
-	u16 coff_pow = 0x2800;
-	u16 init_prbs = 0xfff;
-	u16 ana_gain = 0;
-
-	if (state->revision == 0x8090)
-		dib8000_init_sdram(state);
-
-	if (state->ber_monitored_layer != LAYER_ALL)
-		dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer);
-	else
-		dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60);
-
-	i = dib8000_read_word(state, 26) & 1;	// P_dds_invspec
-	dib8000_write_word(state, 26, state->fe[0]->dtv_property_cache.inversion^i);
-
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
-		//compute new dds_freq for the seg and adjust prbs
-		int seg_offset =
-			state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx -
-			(state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) -
-			(state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2);
-		int clk = state->cfg.pll->internal;
-		u32 segtodds = ((u32) (430 << 23) / clk) << 3;	// segtodds = SegBW / Fclk * pow(2,26)
-		int dds_offset = seg_offset * segtodds;
-		int new_dds, sub_channel;
-		if ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
-			dds_offset -= (int)(segtodds / 2);
-
-		if (state->cfg.pll->ifreq == 0) {
-			if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0) {
-				dib8000_write_word(state, 26, dib8000_read_word(state, 26) | 1);
-				new_dds = dds_offset;
-			} else
-				new_dds = dds_offset;
-
-			// We shift tuning frequency if the wanted segment is :
-			//  - the segment of center frequency with an odd total number of segments
-			//  - the segment to the left of center frequency with an even total number of segments
-			//  - the segment to the right of center frequency with an even total number of segments
-			if ((state->fe[0]->dtv_property_cache.delivery_system == SYS_ISDBT)
-				&& (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1)
-					&& (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2)
-					  && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx ==
-				  ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
-					 || (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
-						 && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx == (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2)))
-					 || (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
-						 && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx ==
-							 ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
-					)) {
-				new_dds -= ((u32) (850 << 22) / clk) << 4;	// new_dds = 850 (freq shift in KHz) / Fclk * pow(2,26)
-			}
-		} else {
-			if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0)
-				new_dds = state->cfg.pll->ifreq - dds_offset;
-			else
-				new_dds = state->cfg.pll->ifreq + dds_offset;
-		}
-		dib8000_write_word(state, 27, (u16) ((new_dds >> 16) & 0x01ff));
-		dib8000_write_word(state, 28, (u16) (new_dds & 0xffff));
-		if (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2)
-			sub_channel = ((state->fe[0]->dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset) + 1) % 41) / 3;
-		else
-			sub_channel = ((state->fe[0]->dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset)) % 41) / 3;
-		sub_channel -= 6;
+	u8  cr, constellation, time_intlv;
+	struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
 
-		if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K
-				|| state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_4K) {
-			dib8000_write_word(state, 219, dib8000_read_word(state, 219) | 0x1);	//adp_pass =1
-			dib8000_write_word(state, 190, dib8000_read_word(state, 190) | (0x1 << 14));	//pha3_force_pha_shift = 1
-		} else {
-			dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe);	//adp_pass =0
-			dib8000_write_word(state, 190, dib8000_read_word(state, 190) & 0xbfff);	//pha3_force_pha_shift = 0
-		}
-
-		switch (state->fe[0]->dtv_property_cache.transmission_mode) {
-		case TRANSMISSION_MODE_2K:
-			switch (sub_channel) {
-			case -6:
-				init_prbs = 0x0;
-				break;	// 41, 0, 1
-			case -5:
-				init_prbs = 0x423;
-				break;	// 02~04
-			case -4:
-				init_prbs = 0x9;
-				break;	// 05~07
-			case -3:
-				init_prbs = 0x5C7;
-				break;	// 08~10
-			case -2:
-				init_prbs = 0x7A6;
-				break;	// 11~13
-			case -1:
-				init_prbs = 0x3D8;
-				break;	// 14~16
-			case 0:
-				init_prbs = 0x527;
-				break;	// 17~19
-			case 1:
-				init_prbs = 0x7FF;
-				break;	// 20~22
-			case 2:
-				init_prbs = 0x79B;
-				break;	// 23~25
-			case 3:
-				init_prbs = 0x3D6;
-				break;	// 26~28
-			case 4:
-				init_prbs = 0x3A2;
-				break;	// 29~31
-			case 5:
-				init_prbs = 0x53B;
-				break;	// 32~34
-			case 6:
-				init_prbs = 0x2F4;
-				break;	// 35~37
-			default:
-			case 7:
-				init_prbs = 0x213;
-				break;	// 38~40
-			}
-			break;
-
-		case TRANSMISSION_MODE_4K:
-			switch (sub_channel) {
-			case -6:
-				init_prbs = 0x0;
-				break;	// 41, 0, 1
-			case -5:
-				init_prbs = 0x208;
-				break;	// 02~04
-			case -4:
-				init_prbs = 0xC3;
-				break;	// 05~07
-			case -3:
-				init_prbs = 0x7B9;
-				break;	// 08~10
-			case -2:
-				init_prbs = 0x423;
-				break;	// 11~13
-			case -1:
-				init_prbs = 0x5C7;
-				break;	// 14~16
-			case 0:
-				init_prbs = 0x3D8;
-				break;	// 17~19
-			case 1:
-				init_prbs = 0x7FF;
-				break;	// 20~22
-			case 2:
-				init_prbs = 0x3D6;
-				break;	// 23~25
-			case 3:
-				init_prbs = 0x53B;
-				break;	// 26~28
-			case 4:
-				init_prbs = 0x213;
-				break;	// 29~31
-			case 5:
-				init_prbs = 0x29;
-				break;	// 32~34
-			case 6:
-				init_prbs = 0xD0;
-				break;	// 35~37
-			default:
-			case 7:
-				init_prbs = 0x48E;
-				break;	// 38~40
-			}
-			break;
-
-		default:
-		case TRANSMISSION_MODE_8K:
-			switch (sub_channel) {
-			case -6:
-				init_prbs = 0x0;
-				break;	// 41, 0, 1
-			case -5:
-				init_prbs = 0x740;
-				break;	// 02~04
-			case -4:
-				init_prbs = 0x069;
-				break;	// 05~07
-			case -3:
-				init_prbs = 0x7DD;
-				break;	// 08~10
-			case -2:
-				init_prbs = 0x208;
-				break;	// 11~13
-			case -1:
-				init_prbs = 0x7B9;
-				break;	// 14~16
-			case 0:
-				init_prbs = 0x5C7;
-				break;	// 17~19
-			case 1:
-				init_prbs = 0x7FF;
-				break;	// 20~22
-			case 2:
-				init_prbs = 0x53B;
-				break;	// 23~25
-			case 3:
-				init_prbs = 0x29;
-				break;	// 26~28
-			case 4:
-				init_prbs = 0x48E;
-				break;	// 29~31
-			case 5:
-				init_prbs = 0x4C4;
-				break;	// 32~34
-			case 6:
-				init_prbs = 0x367;
-				break;	// 33~37
-			default:
-			case 7:
-				init_prbs = 0x684;
-				break;	// 38~40
-			}
-			break;
-		}
-	} else {
-		dib8000_write_word(state, 27, (u16) ((state->cfg.pll->ifreq >> 16) & 0x01ff));
-		dib8000_write_word(state, 28, (u16) (state->cfg.pll->ifreq & 0xffff));
-		dib8000_write_word(state, 26, (u16) ((state->cfg.pll->ifreq >> 25) & 0x0003));
-	}
-	/*P_mode == ?? */
-	dib8000_write_word(state, 10, (seq << 4));
-	//  dib8000_write_word(state, 287, (dib8000_read_word(state, 287) & 0xe000) | 0x1000);
-
-	switch (state->fe[0]->dtv_property_cache.guard_interval) {
-	case GUARD_INTERVAL_1_32:
-		guard = 0;
-		break;
-	case GUARD_INTERVAL_1_16:
-		guard = 1;
-		break;
-	case GUARD_INTERVAL_1_8:
-		guard = 2;
-		break;
-	case GUARD_INTERVAL_1_4:
-	default:
-		guard = 3;
-		break;
-	}
-
-	dib8000_write_word(state, 1, (init_prbs << 2) | (guard & 0x3));	// ADDR 1
-
-	max_constellation = DQPSK;
-	for (i = 0; i < 3; i++) {
-		switch (state->fe[0]->dtv_property_cache.layer[i].modulation) {
-		case DQPSK:
+	switch (c->layer[layer_index].modulation) {
+	case DQPSK:
 			constellation = 0;
 			break;
-		case QPSK:
+	case  QPSK:
 			constellation = 1;
 			break;
-		case QAM_16:
+	case QAM_16:
 			constellation = 2;
 			break;
-		case QAM_64:
-		default:
+	case QAM_64:
+	default:
 			constellation = 3;
 			break;
-		}
+	}
 
-		switch (state->fe[0]->dtv_property_cache.layer[i].fec) {
-		case FEC_1_2:
-			crate = 1;
+	switch (c->layer[layer_index].fec) {
+	case FEC_1_2:
+			cr = 1;
 			break;
-		case FEC_2_3:
-			crate = 2;
+	case FEC_2_3:
+			cr = 2;
 			break;
-		case FEC_3_4:
-			crate = 3;
+	case FEC_3_4:
+			cr = 3;
 			break;
-		case FEC_5_6:
-			crate = 5;
+	case FEC_5_6:
+			cr = 5;
 			break;
-		case FEC_7_8:
-		default:
-			crate = 7;
+	case FEC_7_8:
+	default:
+			cr = 7;
 			break;
-		}
+	}
 
-		if ((state->fe[0]->dtv_property_cache.layer[i].interleaving > 0) &&
-				((state->fe[0]->dtv_property_cache.layer[i].interleaving <= 3) ||
-				 (state->fe[0]->dtv_property_cache.layer[i].interleaving == 4 && state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1))
-			)
-			timeI = state->fe[0]->dtv_property_cache.layer[i].interleaving;
-		else
-			timeI = 0;
-		dib8000_write_word(state, 2 + i, (constellation << 10) | ((state->fe[0]->dtv_property_cache.layer[i].segment_count & 0xf) << 6) |
-					(crate << 3) | timeI);
-		if (state->fe[0]->dtv_property_cache.layer[i].segment_count > 0) {
-			switch (max_constellation) {
-			case DQPSK:
-			case QPSK:
-				if (state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_16 ||
-					state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_64)
-					max_constellation = state->fe[0]->dtv_property_cache.layer[i].modulation;
+	if ((c->layer[layer_index].interleaving > 0) && ((c->layer[layer_index].interleaving <= 3) || (c->layer[layer_index].interleaving == 4 && c->isdbt_sb_mode == 1)))
+		time_intlv = c->layer[layer_index].interleaving;
+	else
+		time_intlv = 0;
+
+	dib8000_write_word(state, 2 + layer_index, (constellation << 10) | ((c->layer[layer_index].segment_count & 0xf) << 6) | (cr << 3) | time_intlv);
+	if (c->layer[layer_index].segment_count > 0) {
+		switch (max_constellation) {
+		case DQPSK:
+		case QPSK:
+				if (c->layer[layer_index].modulation == QAM_16 || c->layer[layer_index].modulation == QAM_64)
+					max_constellation = c->layer[layer_index].modulation;
 				break;
-			case QAM_16:
-				if (state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_64)
-					max_constellation = state->fe[0]->dtv_property_cache.layer[i].modulation;
+		case QAM_16:
+				if (c->layer[layer_index].modulation == QAM_64)
+					max_constellation = c->layer[layer_index].modulation;
 				break;
-			}
 		}
 	}
 
-	mode = fft_to_mode(state);
+	return  max_constellation;
+}
 
-	//dib8000_write_word(state, 5, 13); /*p_last_seg = 13*/
+static const u16 adp_Q64[4] = {0x0148, 0xfff0, 0x00a4, 0xfff8}; /* P_adp_regul_cnt 0.04, P_adp_noise_cnt -0.002, P_adp_regul_ext 0.02, P_adp_noise_ext -0.001 */
+static const u16 adp_Q16[4] = {0x023d, 0xffdf, 0x00a4, 0xfff0}; /* P_adp_regul_cnt 0.07, P_adp_noise_cnt -0.004, P_adp_regul_ext 0.02, P_adp_noise_ext -0.002 */
+static const u16 adp_Qdefault[4] = {0x099a, 0xffae, 0x0333, 0xfff8}; /* P_adp_regul_cnt 0.3,  P_adp_noise_cnt -0.01,  P_adp_regul_ext 0.1,  P_adp_noise_ext -0.002 */
+static u16 dib8000_adp_fine_tune(struct dib8000_state *state, u16 max_constellation)
+{
+	u16 i, ana_gain = 0;
+	const u16 *adp;
 
-	dib8000_write_word(state, 274, (dib8000_read_word(state, 274) & 0xffcf) |
-				((state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 5) | ((state->fe[0]->dtv_property_cache.
-												 isdbt_sb_mode & 1) << 4));
+	/* channel estimation fine configuration */
+	switch (max_constellation) {
+	case QAM_64:
+			ana_gain = 0x7;
+			adp = &adp_Q64[0];
+			break;
+	case QAM_16:
+			ana_gain = 0x7;
+			adp = &adp_Q16[0];
+			break;
+	default:
+			ana_gain = 0;
+			adp = &adp_Qdefault[0];
+			break;
+	}
 
-	dprintk("mode = %d ; guard = %d", mode, state->fe[0]->dtv_property_cache.guard_interval);
+	for (i = 0; i < 4; i++)
+		dib8000_write_word(state, 215 + i, adp[i]);
 
-	/* signal optimization parameter */
+	return ana_gain;
+}
 
-	if (state->fe[0]->dtv_property_cache.isdbt_partial_reception) {
-		seg_diff_mask = (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) << permu_seg[0];
-		for (i = 1; i < 3; i++)
-			nbseg_diff +=
-				(state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count;
-		for (i = 0; i < nbseg_diff; i++)
-			seg_diff_mask |= 1 << permu_seg[i + 1];
-	} else {
-		for (i = 0; i < 3; i++)
-			nbseg_diff +=
-				(state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count;
-		for (i = 0; i < nbseg_diff; i++)
-			seg_diff_mask |= 1 << permu_seg[i];
+static void dib8000_update_ana_gain(struct dib8000_state *state, u16 ana_gain)
+{
+	u16 i;
+
+	dib8000_write_word(state, 116, ana_gain);
+
+	/* update ADC target depending on ana_gain */
+	if (ana_gain) { /* set -16dB ADC target for ana_gain=-1 */
+		for (i = 0; i < 10; i++)
+			dib8000_write_word(state, 80 + i, adc_target_16dB[i]);
+	} else { /* set -22dB ADC target for ana_gain=0 */
+		for (i = 0; i < 10; i++)
+			dib8000_write_word(state, 80 + i, adc_target_16dB[i] - 355);
 	}
-	dprintk("nbseg_diff = %X (%d)", seg_diff_mask, seg_diff_mask);
+}
 
-	state->differential_constellation = (seg_diff_mask != 0);
-	if (state->revision != 0x8090)
-		dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
-	else
-		dib8096p_set_diversity_in(state->fe[0], state->diversity_onoff);
+static void dib8000_load_ana_fe_coefs(struct dib8000_state *state, const s16 *ana_fe)
+{
+	u16 mode = 0;
+
+	if (state->isdbt_cfg_loaded == 0)
+		for (mode = 0; mode < 24; mode++)
+			dib8000_write_word(state, 117 + mode, ana_fe[mode]);
+}
+
+static const u16 lut_prbs_2k[14] = {
+	0, 0x423, 0x009, 0x5C7, 0x7A6, 0x3D8, 0x527, 0x7FF, 0x79B, 0x3D6, 0x3A2, 0x53B, 0x2F4, 0x213
+};
+static const u16 lut_prbs_4k[14] = {
+	0, 0x208, 0x0C3, 0x7B9, 0x423, 0x5C7, 0x3D8, 0x7FF, 0x3D6, 0x53B, 0x213, 0x029, 0x0D0, 0x48E
+};
+static const u16 lut_prbs_8k[14] = {
+	0, 0x740, 0x069, 0x7DD, 0x208, 0x7B9, 0x5C7, 0x7FF, 0x53B, 0x029, 0x48E, 0x4C4, 0x367, 0x684
+};
 
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
-		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1)
-			seg_mask13 = 0x00E0;
-		else		// 1-segment
-			seg_mask13 = 0x0040;
-	} else
-		seg_mask13 = 0x1fff;
+static u16 dib8000_get_init_prbs(struct dib8000_state *state, u16 subchannel)
+{
+	int sub_channel_prbs_group = 0;
 
-	// WRITE: Mode & Diff mask
-	dib8000_write_word(state, 0, (mode << 13) | seg_diff_mask);
+	sub_channel_prbs_group = (subchannel / 3) + 1;
+	dprintk("sub_channel_prbs_group = %d , subchannel =%d prbs = 0x%04x", sub_channel_prbs_group, subchannel, lut_prbs_8k[sub_channel_prbs_group]);
 
-	if ((seg_diff_mask) || (state->fe[0]->dtv_property_cache.isdbt_sb_mode))
-		dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200);
-	else
-		dib8000_write_word(state, 268, (2 << 9) | 39);	//init value
+	switch (state->fe[0]->dtv_property_cache.transmission_mode) {
+	case TRANSMISSION_MODE_2K:
+			return lut_prbs_2k[sub_channel_prbs_group];
+	case TRANSMISSION_MODE_4K:
+			return lut_prbs_4k[sub_channel_prbs_group];
+	default:
+	case TRANSMISSION_MODE_8K:
+			return lut_prbs_8k[sub_channel_prbs_group];
+	}
+}
+
+static void dib8000_set_13seg_channel(struct dib8000_state *state)
+{
+	u16 i;
+	u16 coff_pow = 0x2800;
+
+	state->seg_mask = 0x1fff; /* All 13 segments enabled */
+
+	/* ---- COFF ---- Carloff, the most robust --- */
+	if (state->isdbt_cfg_loaded == 0) {  /* if not Sound Broadcasting mode : put default values for 13 segments */
+		dib8000_write_word(state, 180, (16 << 6) | 9);
+		dib8000_write_word(state, 187, (4 << 12) | (8 << 5) | 0x2);
+		coff_pow = 0x2800;
+		for (i = 0; i < 6; i++)
+			dib8000_write_word(state, 181+i, coff_pow);
+
+		/* P_ctrl_corm_thres4pre_freq_inh=1, P_ctrl_pre_freq_mode_sat=1 */
+		/* P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 3, P_pre_freq_win_len=1 */
+		dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (3 << 5) | 1);
+
+		/* P_ctrl_pre_freq_win_len=8, P_ctrl_pre_freq_thres_lockin=6 */
+		dib8000_write_word(state, 340, (8 << 6) | (6 << 0));
+		/* P_ctrl_pre_freq_thres_lockout=4, P_small_use_tmcc/ac/cp=1 */
+		dib8000_write_word(state, 341, (4 << 3) | (1 << 2) | (1 << 1) | (1 << 0));
+
+		dib8000_write_word(state, 228, 0);  /* default value */
+		dib8000_write_word(state, 265, 31); /* default value */
+		dib8000_write_word(state, 205, 0x200f); /* init value */
+	}
+
+	/*
+	 * make the cpil_coff_lock more robust but slower p_coff_winlen
+	 * 6bits; p_coff_thres_lock 6bits (for coff lock if needed)
+	 */
+
+	if (state->cfg.pll->ifreq == 0)
+		dib8000_write_word(state, 266, ~state->seg_mask | state->seg_diff_mask | 0x40); /* P_equal_noise_seg_inh */
+
+	dib8000_load_ana_fe_coefs(state, ana_fe_coeff_13seg);
+}
+
+static void dib8000_set_subchannel_prbs(struct dib8000_state *state, u16 init_prbs)
+{
+	u16 reg_1;
+
+	reg_1 = dib8000_read_word(state, 1);
+	dib8000_write_word(state, 1, (init_prbs << 2) | (reg_1 & 0x3)); /* ADDR 1 */
+}
 
-	// ---- SMALL ----
-	// P_small_seg_diff
-	dib8000_write_word(state, 352, seg_diff_mask);	// ADDR 352
+static void dib8000_small_fine_tune(struct dib8000_state *state)
+{
+	u16 i;
+	const s16 *ncoeff;
+	struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
 
-	dib8000_write_word(state, 353, seg_mask13);	// ADDR 353
+	dib8000_write_word(state, 352, state->seg_diff_mask);
+	dib8000_write_word(state, 353, state->seg_mask);
 
-/*	// P_small_narrow_band=0, P_small_last_seg=13, P_small_offset_num_car=5 */
+	/* P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5 */
+	dib8000_write_word(state, 351, (c->isdbt_sb_mode << 9) | (c->isdbt_sb_mode << 8) | (13 << 4) | 5);
 
-	// ---- SMALL ----
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
-		switch (state->fe[0]->dtv_property_cache.transmission_mode) {
+	if (c->isdbt_sb_mode) {
+		/* ---- SMALL ---- */
+		switch (c->transmission_mode) {
 		case TRANSMISSION_MODE_2K:
-			if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
-				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK)
-					ncoeff = coeff_2k_sb_1seg_dqpsk;
-				else	// QPSK or QAM
-					ncoeff = coeff_2k_sb_1seg;
-			} else {	// 3-segments
-				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) {
-					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK)
-						ncoeff = coeff_2k_sb_3seg_0dqpsk_1dqpsk;
-					else	// QPSK or QAM on external segments
-						ncoeff = coeff_2k_sb_3seg_0dqpsk;
-				} else {	// QPSK or QAM on central segment
-					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK)
-						ncoeff = coeff_2k_sb_3seg_1dqpsk;
-					else	// QPSK or QAM on external segments
-						ncoeff = coeff_2k_sb_3seg;
+				if (c->isdbt_partial_reception == 0) { /* 1-seg */
+					if (c->layer[0].modulation == DQPSK) /* DQPSK */
+						ncoeff = coeff_2k_sb_1seg_dqpsk;
+					else /* QPSK or QAM */
+						ncoeff = coeff_2k_sb_1seg;
+				} else { /* 3-segments */
+					if (c->layer[0].modulation == DQPSK) { /* DQPSK on central segment */
+						if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */
+							ncoeff = coeff_2k_sb_3seg_0dqpsk_1dqpsk;
+						else /* QPSK or QAM on external segments */
+							ncoeff = coeff_2k_sb_3seg_0dqpsk;
+					} else { /* QPSK or QAM on central segment */
+						if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */
+							ncoeff = coeff_2k_sb_3seg_1dqpsk;
+						else /* QPSK or QAM on external segments */
+							ncoeff = coeff_2k_sb_3seg;
+					}
 				}
-			}
-			break;
-
+				break;
 		case TRANSMISSION_MODE_4K:
-			if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
-				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK)
-					ncoeff = coeff_4k_sb_1seg_dqpsk;
-				else	// QPSK or QAM
-					ncoeff = coeff_4k_sb_1seg;
-			} else {	// 3-segments
-				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) {
-					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) {
-						ncoeff = coeff_4k_sb_3seg_0dqpsk_1dqpsk;
-					} else {	// QPSK or QAM on external segments
-						ncoeff = coeff_4k_sb_3seg_0dqpsk;
+				if (c->isdbt_partial_reception == 0) { /* 1-seg */
+					if (c->layer[0].modulation == DQPSK) /* DQPSK */
+						ncoeff = coeff_4k_sb_1seg_dqpsk;
+					else /* QPSK or QAM */
+						ncoeff = coeff_4k_sb_1seg;
+				} else { /* 3-segments */
+					if (c->layer[0].modulation == DQPSK) { /* DQPSK on central segment */
+						if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */
+							ncoeff = coeff_4k_sb_3seg_0dqpsk_1dqpsk;
+						else /* QPSK or QAM on external segments */
+							ncoeff = coeff_4k_sb_3seg_0dqpsk;
+					} else { /* QPSK or QAM on central segment */
+						if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */
+							ncoeff = coeff_4k_sb_3seg_1dqpsk;
+						else /* QPSK or QAM on external segments */
+							ncoeff = coeff_4k_sb_3seg;
 					}
-				} else {	// QPSK or QAM on central segment
-					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) {
-						ncoeff = coeff_4k_sb_3seg_1dqpsk;
-					} else	// QPSK or QAM on external segments
-						ncoeff = coeff_4k_sb_3seg;
 				}
-			}
-			break;
-
+				break;
 		case TRANSMISSION_MODE_AUTO:
 		case TRANSMISSION_MODE_8K:
 		default:
-			if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
-				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK)
-					ncoeff = coeff_8k_sb_1seg_dqpsk;
-				else	// QPSK or QAM
-					ncoeff = coeff_8k_sb_1seg;
-			} else {	// 3-segments
-				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) {
-					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) {
-						ncoeff = coeff_8k_sb_3seg_0dqpsk_1dqpsk;
-					} else {	// QPSK or QAM on external segments
-						ncoeff = coeff_8k_sb_3seg_0dqpsk;
+				if (c->isdbt_partial_reception == 0) { /* 1-seg */
+					if (c->layer[0].modulation == DQPSK) /* DQPSK */
+						ncoeff = coeff_8k_sb_1seg_dqpsk;
+					else /* QPSK or QAM */
+						ncoeff = coeff_8k_sb_1seg;
+				} else { /* 3-segments */
+					if (c->layer[0].modulation == DQPSK) { /* DQPSK on central segment */
+						if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */
+							ncoeff = coeff_8k_sb_3seg_0dqpsk_1dqpsk;
+						else /* QPSK or QAM on external segments */
+							ncoeff = coeff_8k_sb_3seg_0dqpsk;
+					} else { /* QPSK or QAM on central segment */
+						if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */
+							ncoeff = coeff_8k_sb_3seg_1dqpsk;
+						else /* QPSK or QAM on external segments */
+							ncoeff = coeff_8k_sb_3seg;
 					}
-				} else {	// QPSK or QAM on central segment
-					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) {
-						ncoeff = coeff_8k_sb_3seg_1dqpsk;
-					} else	// QPSK or QAM on external segments
-						ncoeff = coeff_8k_sb_3seg;
 				}
-			}
-			break;
+				break;
 		}
+
 		for (i = 0; i < 8; i++)
 			dib8000_write_word(state, 343 + i, ncoeff[i]);
 	}
+}
+
+static const u16 coff_thres_1seg[3] = {300, 150, 80};
+static const u16 coff_thres_3seg[3] = {350, 300, 250};
+static void dib8000_set_sb_channel(struct dib8000_state *state)
+{
+	struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
+	const u16 *coff;
+	u16 i;
+
+	if (c->transmission_mode == TRANSMISSION_MODE_2K || c->transmission_mode == TRANSMISSION_MODE_4K) {
+		dib8000_write_word(state, 219, dib8000_read_word(state, 219) | 0x1); /* adp_pass =1 */
+		dib8000_write_word(state, 190, dib8000_read_word(state, 190) | (0x1 << 14)); /* pha3_force_pha_shift = 1 */
+	} else {
+		dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); /* adp_pass =0 */
+		dib8000_write_word(state, 190, dib8000_read_word(state, 190) & 0xbfff); /* pha3_force_pha_shift = 0 */
+	}
 
-	// P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5
-	dib8000_write_word(state, 351,
-				(state->fe[0]->dtv_property_cache.isdbt_sb_mode << 9) | (state->fe[0]->dtv_property_cache.isdbt_sb_mode << 8) | (13 << 4) | 5);
+	if (c->isdbt_partial_reception == 1) /* 3-segments */
+		state->seg_mask = 0x00E0;
+	else /* 1-segment */
+		state->seg_mask = 0x0040;
 
-	// ---- COFF ----
-	// Carloff, the most robust
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
+	dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200);
 
-		// P_coff_cpil_alpha=4, P_coff_inh=0, P_coff_cpil_winlen=64
-		// P_coff_narrow_band=1, P_coff_square_val=1, P_coff_one_seg=~partial_rcpt, P_coff_use_tmcc=1, P_coff_use_ac=1
-		dib8000_write_word(state, 187,
-					(4 << 12) | (0 << 11) | (63 << 5) | (0x3 << 3) | ((~state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 2)
-					| 0x3);
+	/* ---- COFF ---- Carloff, the most robust --- */
+	/* P_coff_cpil_alpha=4, P_coff_inh=0, P_coff_cpil_winlen=64, P_coff_narrow_band=1, P_coff_square_val=1, P_coff_one_seg=~partial_rcpt, P_coff_use_tmcc=1, P_coff_use_ac=1 */
+	dib8000_write_word(state, 187, (4 << 12) | (0 << 11) | (63 << 5) | (0x3 << 3) | ((~c->isdbt_partial_reception & 1) << 2) | 0x3);
 
-/*		// P_small_coef_ext_enable = 1 */
-/*		dib8000_write_word(state, 351, dib8000_read_word(state, 351) | 0x200); */
+	dib8000_write_word(state, 340, (16 << 6) | (8 << 0)); /* P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8 */
+	dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0));/* P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1 */
 
-		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
+	/* Sound Broadcasting mode 1 seg */
+	if (c->isdbt_partial_reception == 0) {
+		/* P_coff_winlen=63, P_coff_thres_lock=15, P_coff_one_seg_width = (P_mode == 3) , P_coff_one_seg_sym = (P_mode-1) */
+		if (state->mode == 3)
+			dib8000_write_word(state, 180, 0x1fcf | ((state->mode - 1) << 14));
+		else
+			dib8000_write_word(state, 180, 0x0fcf | ((state->mode - 1) << 14));
 
-			// P_coff_winlen=63, P_coff_thres_lock=15, P_coff_one_seg_width= (P_mode == 3) , P_coff_one_seg_sym= (P_mode-1)
-			if (mode == 3)
-				dib8000_write_word(state, 180, 0x1fcf | ((mode - 1) << 14));
-			else
-				dib8000_write_word(state, 180, 0x0fcf | ((mode - 1) << 14));
-			// P_ctrl_corm_thres4pre_freq_inh=1,P_ctrl_pre_freq_mode_sat=1,
-			// P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 5, P_pre_freq_win_len=4
-			dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (5 << 5) | 4);
-			// P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8
-			dib8000_write_word(state, 340, (16 << 6) | (8 << 0));
-			// P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1
-			dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0));
-
-			// P_coff_corthres_8k, 4k, 2k and P_coff_cpilthres_8k, 4k, 2k
-			dib8000_write_word(state, 181, 300);
-			dib8000_write_word(state, 182, 150);
-			dib8000_write_word(state, 183, 80);
-			dib8000_write_word(state, 184, 300);
-			dib8000_write_word(state, 185, 150);
-			dib8000_write_word(state, 186, 80);
-		} else {	// Sound Broadcasting mode 3 seg
-			// P_coff_one_seg_sym= 1, P_coff_one_seg_width= 1, P_coff_winlen=63, P_coff_thres_lock=15
-			/*	if (mode == 3) */
-			/*		dib8000_write_word(state, 180, 0x2fca | ((0) << 14)); */
-			/*	else */
-			/*		dib8000_write_word(state, 180, 0x2fca | ((1) << 14)); */
-			dib8000_write_word(state, 180, 0x1fcf | (1 << 14));
-
-			// P_ctrl_corm_thres4pre_freq_inh = 1, P_ctrl_pre_freq_mode_sat=1,
-			// P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 4, P_pre_freq_win_len=4
-			dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (4 << 5) | 4);
-			// P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8
-			dib8000_write_word(state, 340, (16 << 6) | (8 << 0));
-			//P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1
-			dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0));
-
-			// P_coff_corthres_8k, 4k, 2k and P_coff_cpilthres_8k, 4k, 2k
-			dib8000_write_word(state, 181, 350);
-			dib8000_write_word(state, 182, 300);
-			dib8000_write_word(state, 183, 250);
-			dib8000_write_word(state, 184, 350);
-			dib8000_write_word(state, 185, 300);
-			dib8000_write_word(state, 186, 250);
-		}
+		/* P_ctrl_corm_thres4pre_freq_inh=1,P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 5, P_pre_freq_win_len=4 */
+		dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (5 << 5) | 4);
+		coff = &coff_thres_1seg[0];
+	} else {   /* Sound Broadcasting mode 3 seg */
+		dib8000_write_word(state, 180, 0x1fcf | (1 << 14));
+		/* P_ctrl_corm_thres4pre_freq_inh = 1, P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 4, P_pre_freq_win_len=4 */
+		dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (4 << 5) | 4);
+		coff = &coff_thres_3seg[0];
+	}
 
-	} else if (state->isdbt_cfg_loaded == 0) {	// if not Sound Broadcasting mode : put default values for 13 segments
-		dib8000_write_word(state, 180, (16 << 6) | 9);
-		dib8000_write_word(state, 187, (4 << 12) | (8 << 5) | 0x2);
-		coff_pow = 0x2800;
-		for (i = 0; i < 6; i++)
-			dib8000_write_word(state, 181 + i, coff_pow);
+	dib8000_write_word(state, 228, 1); /* P_2d_mode_byp=1 */
+	dib8000_write_word(state, 205, dib8000_read_word(state, 205) & 0xfff0); /* P_cspu_win_cut = 0 */
 
-		// P_ctrl_corm_thres4pre_freq_inh=1, P_ctrl_pre_freq_mode_sat=1,
-		// P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 3, P_pre_freq_win_len=1
-		dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (3 << 5) | 1);
+	if (c->isdbt_partial_reception == 0 && c->transmission_mode == TRANSMISSION_MODE_2K)
+		dib8000_write_word(state, 265, 15); /* P_equal_noise_sel = 15 */
 
-		// P_ctrl_pre_freq_win_len=8, P_ctrl_pre_freq_thres_lockin=6
-		dib8000_write_word(state, 340, (8 << 6) | (6 << 0));
-		// P_ctrl_pre_freq_thres_lockout=4, P_small_use_tmcc/ac/cp=1
-		dib8000_write_word(state, 341, (4 << 3) | (1 << 2) | (1 << 1) | (1 << 0));
+	/* Write COFF thres */
+	for (i = 0 ; i < 3; i++) {
+		dib8000_write_word(state, 181+i, coff[i]);
+		dib8000_write_word(state, 184+i, coff[i]);
 	}
-	// ---- FFT ----
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1 && state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
-		dib8000_write_word(state, 178, 64);	// P_fft_powrange=64
-	else
-		dib8000_write_word(state, 178, 32);	// P_fft_powrange=32
 
-	/* make the cpil_coff_lock more robust but slower p_coff_winlen
+	/*
+	 * make the cpil_coff_lock more robust but slower p_coff_winlen
 	 * 6bits; p_coff_thres_lock 6bits (for coff lock if needed)
 	 */
-	/* if ( ( nbseg_diff>0)&&(nbseg_diff<13))
-		dib8000_write_word(state, 187, (dib8000_read_word(state, 187) & 0xfffb) | (1 << 3)); */
-
-	dib8000_write_word(state, 189, ~seg_mask13 | seg_diff_mask);	/* P_lmod4_seg_inh       */
-	dib8000_write_word(state, 192, ~seg_mask13 | seg_diff_mask);	/* P_pha3_seg_inh        */
-	dib8000_write_word(state, 225, ~seg_mask13 | seg_diff_mask);	/* P_tac_seg_inh         */
-	if ((!state->fe[0]->dtv_property_cache.isdbt_sb_mode) && (state->cfg.pll->ifreq == 0))
-		dib8000_write_word(state, 266, ~seg_mask13 | seg_diff_mask | 0x40);	/* P_equal_noise_seg_inh */
-	else
-		dib8000_write_word(state, 266, ~seg_mask13 | seg_diff_mask);	/* P_equal_noise_seg_inh */
-	dib8000_write_word(state, 287, ~seg_mask13 | 0x1000);	/* P_tmcc_seg_inh        */
-	//dib8000_write_word(state, 288, ~seg_mask13 | seg_diff_mask); /* P_tmcc_seg_eq_inh */
-	if (!autosearching)
-		dib8000_write_word(state, 288, (~seg_mask13 | seg_diff_mask) & 0x1fff);	/* P_tmcc_seg_eq_inh */
+
+	dib8000_write_word(state, 266, ~state->seg_mask | state->seg_diff_mask); /* P_equal_noise_seg_inh */
+
+	if (c->isdbt_partial_reception == 0)
+		dib8000_write_word(state, 178, 64); /* P_fft_powrange = 64 */
 	else
-		dib8000_write_word(state, 288, 0x1fff);	//disable equalisation of the tmcc when autosearch to be able to find the DQPSK channels.
-	dprintk("287 = %X (%d)", ~seg_mask13 | 0x1000, ~seg_mask13 | 0x1000);
-
-	dib8000_write_word(state, 211, seg_mask13 & (~seg_diff_mask));	/* P_des_seg_enabled     */
-
-	/* offset loop parameters */
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
-		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
-			/* P_timf_alpha = (11-P_mode), P_corm_alpha=6, P_corm_thres=0x80 */
-			dib8000_write_word(state, 32, ((11 - mode) << 12) | (6 << 8) | 0x40);
-
-		else		// Sound Broadcasting mode 3 seg
-			/* P_timf_alpha = (10-P_mode), P_corm_alpha=6, P_corm_thres=0x80 */
-			dib8000_write_word(state, 32, ((10 - mode) << 12) | (6 << 8) | 0x60);
-	} else
-		// TODO in 13 seg, timf_alpha can always be the same or not ?
-		/* P_timf_alpha = (9-P_mode, P_corm_alpha=6, P_corm_thres=0x80 */
-		dib8000_write_word(state, 32, ((9 - mode) << 12) | (6 << 8) | 0x80);
-
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
-		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
-			/* P_ctrl_pha_off_max=3   P_ctrl_sfreq_inh =0  P_ctrl_sfreq_step = (11-P_mode)  */
-			dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (10 - mode));
-
-		else		// Sound Broadcasting mode 3 seg
-			/* P_ctrl_pha_off_max=3   P_ctrl_sfreq_inh =0  P_ctrl_sfreq_step = (10-P_mode)  */
-			dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (9 - mode));
-	} else
-		/* P_ctrl_pha_off_max=3   P_ctrl_sfreq_inh =0  P_ctrl_sfreq_step = 9  */
-		dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (8 - mode));
+		dib8000_write_word(state, 178, 32); /* P_fft_powrange = 32 */
+}
 
-	/* P_dvsy_sync_wait - reuse mode */
-	switch (state->fe[0]->dtv_property_cache.transmission_mode) {
-	case TRANSMISSION_MODE_8K:
-		mode = 256;
-		break;
-	case TRANSMISSION_MODE_4K:
-		mode = 128;
-		break;
-	default:
-	case TRANSMISSION_MODE_2K:
-		mode = 64;
-		break;
+static void dib8000_set_isdbt_common_channel(struct dib8000_state *state, u8 seq, u8 autosearching)
+{
+	u16 p_cfr_left_edge  = 0, p_cfr_right_edge = 0;
+	u16 tmcc_pow = 0, ana_gain = 0, tmp = 0, i = 0, nbseg_diff = 0 ;
+	u16 max_constellation = DQPSK;
+	int init_prbs;
+	struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
+
+	/* P_mode */
+	dib8000_write_word(state, 10, (seq << 4));
+
+	/* init mode */
+	state->mode = fft_to_mode(state);
+
+	/* set guard */
+	tmp = dib8000_read_word(state, 1);
+	dib8000_write_word(state, 1, (tmp&0xfffc) | (c->guard_interval & 0x3));
+
+	dib8000_write_word(state, 274, (dib8000_read_word(state, 274) & 0xffcf) | ((c->isdbt_partial_reception & 1) << 5) | ((c->isdbt_sb_mode & 1) << 4));
+
+	/* signal optimization parameter */
+	if (c->isdbt_partial_reception) {
+		state->seg_diff_mask = (c->layer[0].modulation == DQPSK) << permu_seg[0];
+		for (i = 1; i < 3; i++)
+			nbseg_diff += (c->layer[i].modulation == DQPSK) * c->layer[i].segment_count;
+		for (i = 0; i < nbseg_diff; i++)
+			state->seg_diff_mask |= 1 << permu_seg[i+1];
+	} else {
+		for (i = 0; i < 3; i++)
+			nbseg_diff += (c->layer[i].modulation == DQPSK) * c->layer[i].segment_count;
+		for (i = 0; i < nbseg_diff; i++)
+			state->seg_diff_mask |= 1 << permu_seg[i];
 	}
-	if (state->cfg.diversity_delay == 0)
-		mode = (mode * (1 << (guard)) * 3) / 2 + 48;	// add 50% SFN margin + compensate for one DVSY-fifo
+
+	if (state->seg_diff_mask)
+		dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200);
 	else
-		mode = (mode * (1 << (guard)) * 3) / 2 + state->cfg.diversity_delay;	// add 50% SFN margin + compensate for DVSY-fifo
-	mode <<= 4;
-	dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | mode);
+		dib8000_write_word(state, 268, (2 << 9) | 39); /*init value */
 
-	/* channel estimation fine configuration */
-	switch (max_constellation) {
-	case QAM_64:
-		ana_gain = 0x7;	// -1 : avoid def_est saturation when ADC target is -16dB
-		coeff[0] = 0x0148;	/* P_adp_regul_cnt 0.04 */
-		coeff[1] = 0xfff0;	/* P_adp_noise_cnt -0.002 */
-		coeff[2] = 0x00a4;	/* P_adp_regul_ext 0.02 */
-		coeff[3] = 0xfff8;	/* P_adp_noise_ext -0.001 */
-		//if (!state->cfg.hostbus_diversity) //if diversity, we should prehaps use the configuration of the max_constallation -1
-		break;
-	case QAM_16:
-		ana_gain = 0x7;	// -1 : avoid def_est saturation when ADC target is -16dB
-		coeff[0] = 0x023d;	/* P_adp_regul_cnt 0.07 */
-		coeff[1] = 0xffdf;	/* P_adp_noise_cnt -0.004 */
-		coeff[2] = 0x00a4;	/* P_adp_regul_ext 0.02 */
-		coeff[3] = 0xfff0;	/* P_adp_noise_ext -0.002 */
-		//if (!((state->cfg.hostbus_diversity) && (max_constellation == QAM_16)))
-		break;
-	default:
-		ana_gain = 0;	// 0 : goes along with ADC target at -22dB to keep good mobile performance and lock at sensitivity level
-		coeff[0] = 0x099a;	/* P_adp_regul_cnt 0.3 */
-		coeff[1] = 0xffae;	/* P_adp_noise_cnt -0.01 */
-		coeff[2] = 0x0333;	/* P_adp_regul_ext 0.1 */
-		coeff[3] = 0xfff8;	/* P_adp_noise_ext -0.002 */
-		break;
+	for (i = 0; i < 3; i++)
+		max_constellation = dib8000_set_layer(state, i, max_constellation);
+	if (autosearching == 0) {
+		state->layer_b_nb_seg = c->layer[1].segment_count;
+		state->layer_c_nb_seg = c->layer[2].segment_count;
 	}
-	for (mode = 0; mode < 4; mode++)
-		dib8000_write_word(state, 215 + mode, coeff[mode]);
 
-	// update ana_gain depending on max constellation
-	dib8000_write_word(state, 116, ana_gain);
-	// update ADC target depending on ana_gain
-	if (ana_gain) {		// set -16dB ADC target for ana_gain=-1
-		for (i = 0; i < 10; i++)
-			dib8000_write_word(state, 80 + i, adc_target_16dB[i]);
-	} else {		// set -22dB ADC target for ana_gain=0
-		for (i = 0; i < 10; i++)
-			dib8000_write_word(state, 80 + i, adc_target_16dB[i] - 355);
+	/* WRITE: Mode & Diff mask */
+	dib8000_write_word(state, 0, (state->mode << 13) | state->seg_diff_mask);
+
+	state->differential_constellation = (state->seg_diff_mask != 0);
+
+	/* channel estimation fine configuration */
+	ana_gain = dib8000_adp_fine_tune(state, max_constellation);
+
+	/* update ana_gain depending on max constellation */
+	dib8000_update_ana_gain(state, ana_gain);
+
+	/* ---- ANA_FE ---- */
+	if (c->isdbt_partial_reception) /* 3-segments */
+		dib8000_load_ana_fe_coefs(state, ana_fe_coeff_3seg);
+	else
+		dib8000_load_ana_fe_coefs(state, ana_fe_coeff_1seg); /* 1-segment */
+
+	/* TSB or ISDBT ? apply it now */
+	if (c->isdbt_sb_mode) {
+		dib8000_set_sb_channel(state);
+		if (c->isdbt_sb_subchannel < 14)
+			init_prbs = dib8000_get_init_prbs(state, c->isdbt_sb_subchannel);
+		else
+			init_prbs = 0;
+	} else {
+		dib8000_set_13seg_channel(state);
+		init_prbs = 0xfff;
 	}
 
-	// ---- ANA_FE ----
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
-		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1)
-			ana_fe = ana_fe_coeff_3seg;
-		else		// 1-segment
-			ana_fe = ana_fe_coeff_1seg;
-	} else
-		ana_fe = ana_fe_coeff_13seg;
+	/* SMALL */
+	dib8000_small_fine_tune(state);
 
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1 || state->isdbt_cfg_loaded == 0)
-		for (mode = 0; mode < 24; mode++)
-			dib8000_write_word(state, 117 + mode, ana_fe[mode]);
+	dib8000_set_subchannel_prbs(state, init_prbs);
 
-	// ---- CHAN_BLK ----
+	/* ---- CHAN_BLK ---- */
 	for (i = 0; i < 13; i++) {
-		if ((((~seg_diff_mask) >> i) & 1) == 1) {
-			P_cfr_left_edge += (1 << i) * ((i == 0) || ((((seg_mask13 & (~seg_diff_mask)) >> (i - 1)) & 1) == 0));
-			P_cfr_right_edge += (1 << i) * ((i == 12) || ((((seg_mask13 & (~seg_diff_mask)) >> (i + 1)) & 1) == 0));
-		}
-	}
-	dib8000_write_word(state, 222, P_cfr_left_edge);	// P_cfr_left_edge
-	dib8000_write_word(state, 223, P_cfr_right_edge);	// P_cfr_right_edge
-	// "P_cspu_left_edge"  not used => do not care
-	// "P_cspu_right_edge" not used => do not care
-
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
-		dib8000_write_word(state, 228, 1);	// P_2d_mode_byp=1
-		dib8000_write_word(state, 205, dib8000_read_word(state, 205) & 0xfff0);	// P_cspu_win_cut = 0
-		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0
-			&& state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K) {
-			//dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); // P_adp_pass = 0
-			dib8000_write_word(state, 265, 15);	// P_equal_noise_sel = 15
+		if ((((~state->seg_diff_mask) >> i) & 1) == 1) {
+			p_cfr_left_edge  += (1 << i) * ((i == 0) || ((((state->seg_mask & (~state->seg_diff_mask)) >> (i - 1)) & 1) == 0));
+			p_cfr_right_edge += (1 << i) * ((i == 12) || ((((state->seg_mask & (~state->seg_diff_mask)) >> (i + 1)) & 1) == 0));
 		}
-	} else if (state->isdbt_cfg_loaded == 0) {
-		dib8000_write_word(state, 228, 0);	// default value
-		dib8000_write_word(state, 265, 31);	// default value
-		dib8000_write_word(state, 205, 0x200f);	// init value
 	}
-	// ---- TMCC ----
+	dib8000_write_word(state, 222, p_cfr_left_edge); /* p_cfr_left_edge */
+	dib8000_write_word(state, 223, p_cfr_right_edge); /* p_cfr_right_edge */
+	/* "P_cspu_left_edge" & "P_cspu_right_edge" not used => do not care */
+
+	dib8000_write_word(state, 189, ~state->seg_mask | state->seg_diff_mask); /* P_lmod4_seg_inh */
+	dib8000_write_word(state, 192, ~state->seg_mask | state->seg_diff_mask); /* P_pha3_seg_inh */
+	dib8000_write_word(state, 225, ~state->seg_mask | state->seg_diff_mask); /* P_tac_seg_inh */
+
+	if (!autosearching)
+		dib8000_write_word(state, 288, (~state->seg_mask | state->seg_diff_mask) & 0x1fff); /* P_tmcc_seg_eq_inh */
+	else
+		dib8000_write_word(state, 288, 0x1fff); /*disable equalisation of the tmcc when autosearch to be able to find the DQPSK channels. */
+
+	dib8000_write_word(state, 211, state->seg_mask & (~state->seg_diff_mask)); /* P_des_seg_enabled */
+	dib8000_write_word(state, 287, ~state->seg_mask | 0x1000); /* P_tmcc_seg_inh */
+
+	dib8000_write_word(state, 178, 32); /* P_fft_powrange = 32 */
+
+	/* ---- TMCC ---- */
 	for (i = 0; i < 3; i++)
-		tmcc_pow +=
-			(((state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * 4 + 1) * state->fe[0]->dtv_property_cache.layer[i].segment_count);
-	// Quantif of "P_tmcc_dec_thres_?k" is (0, 5+mode, 9);
-	// Threshold is set at 1/4 of max power.
-	tmcc_pow *= (1 << (9 - 2));
-
-	dib8000_write_word(state, 290, tmcc_pow);	// P_tmcc_dec_thres_2k
-	dib8000_write_word(state, 291, tmcc_pow);	// P_tmcc_dec_thres_4k
-	dib8000_write_word(state, 292, tmcc_pow);	// P_tmcc_dec_thres_8k
-	//dib8000_write_word(state, 287, (1 << 13) | 0x1000 );
-	// ---- PHA3 ----
+		tmcc_pow += (((c->layer[i].modulation == DQPSK) * 4 + 1) * c->layer[i].segment_count) ;
 
+	/* Quantif of "P_tmcc_dec_thres_?k" is (0, 5+mode, 9); */
+	/* Threshold is set at 1/4 of max power. */
+	tmcc_pow *= (1 << (9-2));
+	dib8000_write_word(state, 290, tmcc_pow); /* P_tmcc_dec_thres_2k */
+	dib8000_write_word(state, 291, tmcc_pow); /* P_tmcc_dec_thres_4k */
+	dib8000_write_word(state, 292, tmcc_pow); /* P_tmcc_dec_thres_8k */
+	/*dib8000_write_word(state, 287, (1 << 13) | 0x1000 ); */
+
+	/* ---- PHA3 ---- */
 	if (state->isdbt_cfg_loaded == 0)
-		dib8000_write_word(state, 250, 3285);	/*p_2d_hspeed_thr0 */
+		dib8000_write_word(state, 250, 3285); /* p_2d_hspeed_thr0 */
 
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1)
-		state->isdbt_cfg_loaded = 0;
-	else
-		state->isdbt_cfg_loaded = 1;
+	state->isdbt_cfg_loaded = 0;
+}
+
+static u32 dib8000_wait_lock(struct dib8000_state *state, u32 internal,
+			     u32 wait0_ms, u32 wait1_ms, u32 wait2_ms)
+{
+	u32 value = 0;	/* P_search_end0 wait time */
+	u16 reg = 11;	/* P_search_end0 start addr */
 
+	for (reg = 11; reg < 16; reg += 2) {
+		if (reg == 11) {
+			if (state->revision == 0x8090)
+				value = internal * wait1_ms;
+			else
+				value = internal * wait0_ms;
+		} else if (reg == 13)
+			value = internal * wait1_ms;
+		else if (reg == 15)
+			value = internal * wait2_ms;
+		dib8000_write_word(state, reg, (u16)((value >> 16) & 0xffff));
+		dib8000_write_word(state, (reg + 1), (u16)(value & 0xffff));
+	}
+	return value;
 }
 
 static int dib8000_autosearch_start(struct dvb_frontend *fe)
 {
-	u8 factor;
-	u32 value;
 	struct dib8000_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
+	u8 slist = 0;
+	u32 value, internal = state->cfg.pll->internal;
 
-	int slist = 0;
-
-	state->fe[0]->dtv_property_cache.inversion = 0;
-	if (!state->fe[0]->dtv_property_cache.isdbt_sb_mode)
-		state->fe[0]->dtv_property_cache.layer[0].segment_count = 13;
-	state->fe[0]->dtv_property_cache.layer[0].modulation = QAM_64;
-	state->fe[0]->dtv_property_cache.layer[0].fec = FEC_2_3;
-	state->fe[0]->dtv_property_cache.layer[0].interleaving = 0;
-
-	//choose the right list, in sb, always do everything
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
-		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
-		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
-		slist = 7;
-		dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));
-	} else {
-		if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) {
-			if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) {
-				slist = 7;
-				dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));	// P_mode = 1 to have autosearch start ok with mode2
-			} else
-				slist = 3;
-		} else {
-			if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) {
-				slist = 2;
-				dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));	// P_mode = 1
-			} else
-				slist = 0;
-		}
+	if (state->revision == 0x8090)
+		internal = dib8000_read32(state, 23) / 1000;
 
-		if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO)
-			state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
-		if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO)
-			state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
+	if (state->autosearch_state == AS_SEARCHING_FFT) {
+		dib8000_write_word(state,  37, 0x0065); /* P_ctrl_pha_off_max default values */
+		dib8000_write_word(state, 116, 0x0000); /* P_ana_gain to 0 */
 
-		dprintk("using list for autosearch : %d", slist);
-		dib8000_set_channel(state, (unsigned char)slist, 1);
-		//dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));  // P_mode = 1
+		dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x1fff) | (0 << 13) | (1 << 15)); /* P_mode = 0, P_restart_search=1 */
+		dib8000_write_word(state, 1, (dib8000_read_word(state, 1) & 0xfffc) | 0); /* P_guard = 0 */
+		dib8000_write_word(state, 6, 0); /* P_lock0_mask = 0 */
+		dib8000_write_word(state, 7, 0); /* P_lock1_mask = 0 */
+		dib8000_write_word(state, 8, 0); /* P_lock2_mask = 0 */
+		dib8000_write_word(state, 10, (dib8000_read_word(state, 10) & 0x200) | (16 << 4) | (0 << 0)); /* P_search_list=16, P_search_maxtrial=0 */
 
-		factor = 1;
+		if (state->revision == 0x8090)
+			value = dib8000_wait_lock(state, internal, 10, 10, 10); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
+		else
+			value = dib8000_wait_lock(state, internal, 20, 20, 20); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
+
+		dib8000_write_word(state, 17, 0);
+		dib8000_write_word(state, 18, 200); /* P_search_rstst = 200 */
+		dib8000_write_word(state, 19, 0);
+		dib8000_write_word(state, 20, 400); /* P_search_rstend = 400 */
+		dib8000_write_word(state, 21, (value >> 16) & 0xffff); /* P_search_checkst */
+		dib8000_write_word(state, 22, value & 0xffff);
 
-		//set lock_mask values
+		if (state->revision == 0x8090)
+			dib8000_write_word(state, 32, (dib8000_read_word(state, 32) & 0xf0ff) | (0 << 8)); /* P_corm_alpha = 0 */
+		else
+			dib8000_write_word(state, 32, (dib8000_read_word(state, 32) & 0xf0ff) | (9 << 8)); /* P_corm_alpha = 3 */
+		dib8000_write_word(state, 355, 2); /* P_search_param_max = 2 */
+
+		/* P_search_param_select = (1 | 1<<4 | 1 << 8) */
+		dib8000_write_word(state, 356, 0);
+		dib8000_write_word(state, 357, 0x111);
+
+		dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (1 << 13)); /* P_restart_ccg = 1 */
+		dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (0 << 13)); /* P_restart_ccg = 0 */
+		dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x7ff) | (0 << 15) | (1 << 13)); /* P_restart_search = 0; */
+	} else if (state->autosearch_state == AS_SEARCHING_GUARD) {
+		c->transmission_mode = TRANSMISSION_MODE_8K;
+		c->guard_interval = GUARD_INTERVAL_1_8;
+		c->inversion = 0;
+		c->layer[0].modulation = QAM_64;
+		c->layer[0].fec = FEC_2_3;
+		c->layer[0].interleaving = 0;
+		c->layer[0].segment_count = 13;
+
+		slist = 16;
+		c->transmission_mode = state->found_nfft;
+
+		dib8000_set_isdbt_common_channel(state, slist, 1);
+
+		/* set lock_mask values */
 		dib8000_write_word(state, 6, 0x4);
-		dib8000_write_word(state, 7, 0x8);
+		if (state->revision == 0x8090)
+			dib8000_write_word(state, 7, ((1 << 12) | (1 << 11) | (1 << 10)));/* tmcc_dec_lock, tmcc_sync_lock, tmcc_data_lock, tmcc_bch_uncor */
+		else
+			dib8000_write_word(state, 7, 0x8);
 		dib8000_write_word(state, 8, 0x1000);
 
-		//set lock_mask wait time values
-		value = 50 * state->cfg.pll->internal * factor;
-		dib8000_write_word(state, 11, (u16) ((value >> 16) & 0xffff));	// lock0 wait time
-		dib8000_write_word(state, 12, (u16) (value & 0xffff));	// lock0 wait time
-		value = 100 * state->cfg.pll->internal * factor;
-		dib8000_write_word(state, 13, (u16) ((value >> 16) & 0xffff));	// lock1 wait time
-		dib8000_write_word(state, 14, (u16) (value & 0xffff));	// lock1 wait time
-		value = 1000 * state->cfg.pll->internal * factor;
-		dib8000_write_word(state, 15, (u16) ((value >> 16) & 0xffff));	// lock2 wait time
-		dib8000_write_word(state, 16, (u16) (value & 0xffff));	// lock2 wait time
+		/* set lock_mask wait time values */
+		if (state->revision == 0x8090)
+			dib8000_wait_lock(state, internal, 50, 100, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
+		else
+			dib8000_wait_lock(state, internal, 50, 200, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
+
+		dib8000_write_word(state, 355, 3); /* P_search_param_max = 3 */
+
+		/* P_search_param_select = 0xf; look for the 4 different guard intervals */
+		dib8000_write_word(state, 356, 0);
+		dib8000_write_word(state, 357, 0xf);
 
 		value = dib8000_read_word(state, 0);
-		dib8000_write_word(state, 0, (u16) ((1 << 15) | value));
-		dib8000_read_word(state, 1284);	// reset the INT. n_irq_pending
-		dib8000_write_word(state, 0, (u16) value);
+		dib8000_write_word(state, 0, (u16)((1 << 15) | value));
+		dib8000_read_word(state, 1284);  /* reset the INT. n_irq_pending */
+		dib8000_write_word(state, 0, (u16)value);
+	} else {
+		c->inversion = 0;
+		c->layer[0].modulation = QAM_64;
+		c->layer[0].fec = FEC_2_3;
+		c->layer[0].interleaving = 0;
+		c->layer[0].segment_count = 13;
+		if (!c->isdbt_sb_mode)
+			c->layer[0].segment_count = 13;
+
+		/* choose the right list, in sb, always do everything */
+		if (c->isdbt_sb_mode) {
+			slist = 7;
+			dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));
+		} else {
+			if (c->guard_interval == GUARD_INTERVAL_AUTO) {
+				if (c->transmission_mode == TRANSMISSION_MODE_AUTO) {
+					c->transmission_mode = TRANSMISSION_MODE_8K;
+					c->guard_interval = GUARD_INTERVAL_1_8;
+					slist = 7;
+					dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));  /* P_mode = 1 to have autosearch start ok with mode2 */
+				} else {
+					c->guard_interval = GUARD_INTERVAL_1_8;
+					slist = 3;
+				}
+			} else {
+				if (c->transmission_mode == TRANSMISSION_MODE_AUTO) {
+					c->transmission_mode = TRANSMISSION_MODE_8K;
+					slist = 2;
+					dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));  /* P_mode = 1 */
+				} else
+					slist = 0;
+			}
+		}
+		dprintk("Using list for autosearch : %d", slist);
 
-	}
+		dib8000_set_isdbt_common_channel(state, slist, 1);
 
+		/* set lock_mask values */
+		dib8000_write_word(state, 6, 0x4);
+		if (state->revision == 0x8090)
+			dib8000_write_word(state, 7, (1 << 12) | (1 << 11) | (1 << 10));
+		else
+			dib8000_write_word(state, 7, 0x8);
+		dib8000_write_word(state, 8, 0x1000);
+
+		/* set lock_mask wait time values */
+		if (state->revision == 0x8090)
+			dib8000_wait_lock(state, internal, 50, 200, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
+		else
+			dib8000_wait_lock(state, internal, 50, 100, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
+
+		value = dib8000_read_word(state, 0);
+		dib8000_write_word(state, 0, (u16)((1 << 15) | value));
+		dib8000_read_word(state, 1284);  /* reset the INT. n_irq_pending */
+		dib8000_write_word(state, 0, (u16)value);
+	}
 	return 0;
 }
 
@@ -2663,96 +2583,635 @@ static int dib8000_autosearch_irq(struct dvb_frontend *fe)
 	struct dib8000_state *state = fe->demodulator_priv;
 	u16 irq_pending = dib8000_read_word(state, 1284);
 
-	if (irq_pending & 0x1) {	// failed
-		dprintk("dib8000_autosearch_irq failed");
-		return 1;
-	}
+	if (state->autosearch_state == AS_SEARCHING_FFT) {
+		if (irq_pending & 0x1) {
+			dprintk("dib8000_autosearch_irq: max correlation result available");
+			return 3;
+		}
+	} else {
+		if (irq_pending & 0x1) {	/* failed */
+			dprintk("dib8000_autosearch_irq failed");
+			return 1;
+		}
 
-	if (irq_pending & 0x2) {	// succeeded
-		dprintk("dib8000_autosearch_irq succeeded");
-		return 2;
+		if (irq_pending & 0x2) {	/* succeeded */
+			dprintk("dib8000_autosearch_irq succeeded");
+			return 2;
+		}
 	}
 
 	return 0;		// still pending
 }
 
-static int dib8000_tune(struct dvb_frontend *fe)
+static void dib8000_viterbi_state(struct dib8000_state *state, u8 onoff)
 {
-	struct dib8000_state *state = fe->demodulator_priv;
-	int ret = 0;
-	u16 lock, value, mode;
+	u16 tmp;
 
-	// we are already tuned - just resuming from suspend
-	if (state == NULL)
-		return -EINVAL;
+	tmp = dib8000_read_word(state, 771);
+	if (onoff) /* start P_restart_chd : channel_decoder */
+		dib8000_write_word(state, 771, tmp & 0xfffd);
+	else /* stop P_restart_chd : channel_decoder */
+		dib8000_write_word(state, 771, tmp | (1<<1));
+}
 
-	mode = fft_to_mode(state);
+static void dib8000_set_dds(struct dib8000_state *state, s32 offset_khz)
+{
+	s16 unit_khz_dds_val;
+	u32 abs_offset_khz = ABS(offset_khz);
+	u32 dds = state->cfg.pll->ifreq & 0x1ffffff;
+	u8 invert = !!(state->cfg.pll->ifreq & (1 << 25));
+	u8 ratio;
 
-	dib8000_set_bandwidth(fe, state->fe[0]->dtv_property_cache.bandwidth_hz / 1000);
-	dib8000_set_channel(state, 0, 0);
+	if (state->revision == 0x8090) {
+		ratio = 4;
+		unit_khz_dds_val = (1<<26) / (dib8000_read32(state, 23) / 1000);
+		if (offset_khz < 0)
+			dds = (1 << 26) - (abs_offset_khz * unit_khz_dds_val);
+		else
+			dds = (abs_offset_khz * unit_khz_dds_val);
 
-	// restart demod
-	ret |= dib8000_write_word(state, 770, 0x4000);
-	ret |= dib8000_write_word(state, 770, 0x0000);
-	msleep(45);
+		if (invert)
+			dds = (1<<26) - dds;
+	} else {
+		ratio = 2;
+		unit_khz_dds_val = (u16) (67108864 / state->cfg.pll->internal);
 
-	/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3 */
-	/*  ret |= dib8000_write_word(state, 29, (0 << 9) | (4 << 5) | (0 << 4) | (3 << 0) );  workaround inh_isi stays at 1 */
+		if (offset_khz < 0)
+			unit_khz_dds_val *= -1;
 
-	// never achieved a lock before - wait for timfreq to update
-	if (state->timf == 0) {
-		if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
-			if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
-				msleep(300);
-			else	// Sound Broadcasting mode 3 seg
-				msleep(500);
-		} else		// 13 seg
-			msleep(200);
+		/* IF tuner */
+		if (invert)
+			dds -= abs_offset_khz * unit_khz_dds_val;
+		else
+			dds += abs_offset_khz * unit_khz_dds_val;
 	}
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
-		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
 
-			/* P_timf_alpha = (13-P_mode) , P_corm_alpha=6, P_corm_thres=0x40  alpha to check on board */
-			dib8000_write_word(state, 32, ((13 - mode) << 12) | (6 << 8) | 0x40);
-			//dib8000_write_word(state, 32, (8 << 12) | (6 << 8) | 0x80);
+	dprintk("setting a DDS frequency offset of %c%dkHz", invert ? '-' : ' ', dds / unit_khz_dds_val);
 
-			/*  P_ctrl_sfreq_step= (12-P_mode)   P_ctrl_sfreq_inh =0     P_ctrl_pha_off_max  */
-			ret |= dib8000_write_word(state, 37, (12 - mode) | ((5 + mode) << 5));
+	if (abs_offset_khz <= (state->cfg.pll->internal / ratio)) {
+		/* Max dds offset is the half of the demod freq */
+		dib8000_write_word(state, 26, invert);
+		dib8000_write_word(state, 27, (u16)(dds >> 16) & 0x1ff);
+		dib8000_write_word(state, 28, (u16)(dds & 0xffff));
+	}
+}
+
+static void dib8000_set_frequency_offset(struct dib8000_state *state)
+{
+	struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
+	int i;
+	u32 current_rf;
+	int total_dds_offset_khz;
+
+	if (state->fe[0]->ops.tuner_ops.get_frequency)
+		state->fe[0]->ops.tuner_ops.get_frequency(state->fe[0], &current_rf);
+	else
+		current_rf = c->frequency;
+	current_rf /= 1000;
+	total_dds_offset_khz = (int)current_rf - (int)c->frequency / 1000;
 
-		} else {	// Sound Broadcasting mode 3 seg
+	if (c->isdbt_sb_mode) {
+		state->subchannel = c->isdbt_sb_subchannel;
 
-			/* P_timf_alpha = (12-P_mode) , P_corm_alpha=6, P_corm_thres=0x60  alpha to check on board */
-			dib8000_write_word(state, 32, ((12 - mode) << 12) | (6 << 8) | 0x60);
+		i = dib8000_read_word(state, 26) & 1; /* P_dds_invspec */
+		dib8000_write_word(state, 26, c->inversion ^ i);
 
-			ret |= dib8000_write_word(state, 37, (11 - mode) | ((5 + mode) << 5));
+		if (state->cfg.pll->ifreq == 0) { /* low if tuner */
+			if ((c->inversion ^ i) == 0)
+				dib8000_write_word(state, 26, dib8000_read_word(state, 26) | 1);
+		} else {
+			if ((c->inversion ^ i) == 0)
+				total_dds_offset_khz *= -1;
 		}
+	}
+
+	dprintk("%dkhz tuner offset (frequency = %dHz & current_rf = %dHz) total_dds_offset_hz = %d", c->frequency - current_rf, c->frequency, current_rf, total_dds_offset_khz);
+
+	/* apply dds offset now */
+	dib8000_set_dds(state, total_dds_offset_khz);
+}
 
-	} else {		// 13 seg
-		/* P_timf_alpha = 8 , P_corm_alpha=6, P_corm_thres=0x80  alpha to check on board */
-		dib8000_write_word(state, 32, ((11 - mode) << 12) | (6 << 8) | 0x80);
+static u16 LUT_isdbt_symbol_duration[4] = { 26, 101, 63 };
 
-		ret |= dib8000_write_word(state, 37, (10 - mode) | ((5 + mode) << 5));
+static u32 dib8000_get_symbol_duration(struct dib8000_state *state)
+{
+	struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
+	u16 i;
 
+	switch (c->transmission_mode) {
+	case TRANSMISSION_MODE_2K:
+			i = 0;
+			break;
+	case TRANSMISSION_MODE_4K:
+			i = 2;
+			break;
+	default:
+	case TRANSMISSION_MODE_AUTO:
+	case TRANSMISSION_MODE_8K:
+			i = 1;
+			break;
 	}
 
-	// we achieved a coff_cpil_lock - it's time to update the timf
-	if (state->revision != 0x8090)
-		lock = dib8000_read_word(state, 568);
+	return (LUT_isdbt_symbol_duration[i] / (c->bandwidth_hz / 1000)) + 1;
+}
+
+static void dib8000_set_isdbt_loop_params(struct dib8000_state *state, enum param_loop_step loop_step)
+{
+	struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
+	u16 reg_32 = 0, reg_37 = 0;
+
+	switch (loop_step) {
+	case LOOP_TUNE_1:
+			if (c->isdbt_sb_mode)  {
+				if (c->isdbt_partial_reception == 0) {
+					reg_32 = ((11 - state->mode) << 12) | (6 << 8) | 0x40; /* P_timf_alpha = (11-P_mode), P_corm_alpha=6, P_corm_thres=0x40 */
+					reg_37 = (3 << 5) | (0 << 4) | (10 - state->mode); /* P_ctrl_pha_off_max=3   P_ctrl_sfreq_inh =0  P_ctrl_sfreq_step = (10-P_mode)  */
+				} else { /* Sound Broadcasting mode 3 seg */
+					reg_32 = ((10 - state->mode) << 12) | (6 << 8) | 0x60; /* P_timf_alpha = (10-P_mode), P_corm_alpha=6, P_corm_thres=0x60 */
+					reg_37 = (3 << 5) | (0 << 4) | (9 - state->mode); /* P_ctrl_pha_off_max=3   P_ctrl_sfreq_inh =0  P_ctrl_sfreq_step = (9-P_mode)  */
+				}
+			} else { /* 13-seg start conf offset loop parameters */
+				reg_32 = ((9 - state->mode) << 12) | (6 << 8) | 0x80; /* P_timf_alpha = (9-P_mode, P_corm_alpha=6, P_corm_thres=0x80 */
+				reg_37 = (3 << 5) | (0 << 4) | (8 - state->mode); /* P_ctrl_pha_off_max=3   P_ctrl_sfreq_inh =0  P_ctrl_sfreq_step = 9  */
+			}
+			break;
+	case LOOP_TUNE_2:
+			if (c->isdbt_sb_mode)  {
+				if (c->isdbt_partial_reception == 0) {  /* Sound Broadcasting mode 1 seg */
+					reg_32 = ((13-state->mode) << 12) | (6 << 8) | 0x40; /* P_timf_alpha = (13-P_mode) , P_corm_alpha=6, P_corm_thres=0x40*/
+					reg_37 = (12-state->mode) | ((5 + state->mode) << 5);
+				} else {  /* Sound Broadcasting mode 3 seg */
+					reg_32 = ((12-state->mode) << 12) | (6 << 8) | 0x60; /* P_timf_alpha = (12-P_mode) , P_corm_alpha=6, P_corm_thres=0x60 */
+					reg_37 = (11-state->mode) | ((5 + state->mode) << 5);
+				}
+			} else {  /* 13 seg */
+				reg_32 = ((11-state->mode) << 12) | (6 << 8) | 0x80; /* P_timf_alpha = 8 , P_corm_alpha=6, P_corm_thres=0x80 */
+				reg_37 = ((5+state->mode) << 5) | (10 - state->mode);
+			}
+			break;
+	}
+	dib8000_write_word(state, 32, reg_32);
+	dib8000_write_word(state, 37, reg_37);
+}
+
+static void dib8000_demod_restart(struct dib8000_state *state)
+{
+	dib8000_write_word(state, 770, 0x4000);
+	dib8000_write_word(state, 770, 0x0000);
+	return;
+}
+
+static void dib8000_set_sync_wait(struct dib8000_state *state)
+{
+	struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
+	u16 sync_wait = 64;
+
+	/* P_dvsy_sync_wait - reuse mode */
+	switch (c->transmission_mode) {
+	case TRANSMISSION_MODE_8K:
+			sync_wait = 256;
+			break;
+	case TRANSMISSION_MODE_4K:
+			sync_wait = 128;
+			break;
+	default:
+	case TRANSMISSION_MODE_2K:
+			sync_wait =  64;
+			break;
+	}
+
+	if (state->cfg.diversity_delay == 0)
+		sync_wait = (sync_wait * (1 << (c->guard_interval)) * 3) / 2 + 48; /* add 50% SFN margin + compensate for one DVSY-fifo */
 	else
-		lock = dib8000_read_word(state, 570);
-	if ((lock >> 11) & 0x1)
-		dib8000_update_timf(state);
+		sync_wait = (sync_wait * (1 << (c->guard_interval)) * 3) / 2 + state->cfg.diversity_delay; /* add 50% SFN margin + compensate for DVSY-fifo */
 
-	//now that tune is finished, lock0 should lock on fec_mpeg to output this lock on MP_LOCK. It's changed in autosearch start
-	dib8000_write_word(state, 6, 0x200);
+	dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | (sync_wait << 4));
+}
 
-	if (state->revision == 0x8002) {
-		value = dib8000_read_word(state, 903);
-		dib8000_write_word(state, 903, value & ~(1 << 3));
-		msleep(1);
-		dib8000_write_word(state, 903, value | (1 << 3));
+static u32 dib8000_get_timeout(struct dib8000_state *state, u32 delay, enum timeout_mode mode)
+{
+	if (mode == SYMBOL_DEPENDENT_ON)
+		return systime() + (delay * state->symbol_duration);
+	else
+		return systime() + delay;
+}
+
+static s32 dib8000_get_status(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	return state->status;
+}
+
+enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	return state->tune_state;
+}
+EXPORT_SYMBOL(dib8000_get_tune_state);
+
+int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+
+	state->tune_state = tune_state;
+	return 0;
+}
+EXPORT_SYMBOL(dib8000_set_tune_state);
+
+static int dib8000_tune_restart_from_demod(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+
+	state->status = FE_STATUS_TUNE_PENDING;
+	state->tune_state = CT_DEMOD_START;
+	return 0;
+}
+
+static u16 dib8000_read_lock(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+
+	if (state->revision == 0x8090)
+		return dib8000_read_word(state, 570);
+	return dib8000_read_word(state, 568);
+}
+
+static int dib8090p_init_sdram(struct dib8000_state *state)
+{
+	u16 reg = 0;
+	dprintk("init sdram");
+
+	reg = dib8000_read_word(state, 274) & 0xfff0;
+	dib8000_write_word(state, 274, reg | 0x7); /* P_dintlv_delay_ram = 7 because of MobileSdram */
+
+	dib8000_write_word(state, 1803, (7 << 2));
+
+	reg = dib8000_read_word(state, 1280);
+	dib8000_write_word(state, 1280,  reg | (1 << 2)); /* force restart P_restart_sdram */
+	dib8000_write_word(state, 1280,  reg); /* release restart P_restart_sdram */
+
+	return 0;
+}
+
+static int dib8000_tune(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
+	enum frontend_tune_state *tune_state = &state->tune_state;
+
+	u16 locks, deeper_interleaver = 0, i;
+	int ret = 1; /* 1 symbol duration (in 100us unit) delay most of the time */
+
+	u32 *timeout = &state->timeout;
+	u32 now = systime();
+#ifdef DIB8000_AGC_FREEZE
+	u16 agc1, agc2;
+#endif
+
+	u32 corm[4] = {0, 0, 0, 0};
+	u8 find_index, max_value;
+
+#if 0
+	if (*tune_state < CT_DEMOD_STOP)
+		dprintk("IN: context status = %d, TUNE_STATE %d autosearch step = %u systime = %u", state->channel_parameters_set, *tune_state, state->autosearch_state, now);
+#endif
+
+	switch (*tune_state) {
+	case CT_DEMOD_START: /* 30 */
+			if (state->revision == 0x8090)
+				dib8090p_init_sdram(state);
+			state->status = FE_STATUS_TUNE_PENDING;
+			if ((c->delivery_system != SYS_ISDBT) ||
+					(c->inversion == INVERSION_AUTO) ||
+					(c->transmission_mode == TRANSMISSION_MODE_AUTO) ||
+					(c->guard_interval == GUARD_INTERVAL_AUTO) ||
+					(((c->isdbt_layer_enabled & (1 << 0)) != 0) &&
+					 (c->layer[0].segment_count != 0xff) &&
+					 (c->layer[0].segment_count != 0) &&
+					 ((c->layer[0].modulation == QAM_AUTO) ||
+					  (c->layer[0].fec == FEC_AUTO))) ||
+					(((c->isdbt_layer_enabled & (1 << 1)) != 0) &&
+					 (c->layer[1].segment_count != 0xff) &&
+					 (c->layer[1].segment_count != 0) &&
+					 ((c->layer[1].modulation == QAM_AUTO) ||
+					  (c->layer[1].fec == FEC_AUTO))) ||
+					(((c->isdbt_layer_enabled & (1 << 2)) != 0) &&
+					 (c->layer[2].segment_count != 0xff) &&
+					 (c->layer[2].segment_count != 0) &&
+					 ((c->layer[2].modulation == QAM_AUTO) ||
+					  (c->layer[2].fec == FEC_AUTO))) ||
+					(((c->layer[0].segment_count == 0) ||
+					  ((c->isdbt_layer_enabled & (1 << 0)) == 0)) &&
+					 ((c->layer[1].segment_count == 0) ||
+					  ((c->isdbt_layer_enabled & (2 << 0)) == 0)) &&
+					 ((c->layer[2].segment_count == 0) || ((c->isdbt_layer_enabled & (3 << 0)) == 0))))
+				state->channel_parameters_set = 0; /* auto search */
+			else
+				state->channel_parameters_set = 1; /* channel parameters are known */
+
+			dib8000_viterbi_state(state, 0); /* force chan dec in restart */
+
+			/* Layer monit */
+			dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60);
+
+			dib8000_set_frequency_offset(state);
+			dib8000_set_bandwidth(fe, c->bandwidth_hz / 1000);
+
+			if (state->channel_parameters_set == 0) { /* The channel struct is unknown, search it ! */
+#ifdef DIB8000_AGC_FREEZE
+				if (state->revision != 0x8090) {
+					state->agc1_max = dib8000_read_word(state, 108);
+					state->agc1_min = dib8000_read_word(state, 109);
+					state->agc2_max = dib8000_read_word(state, 110);
+					state->agc2_min = dib8000_read_word(state, 111);
+					agc1 = dib8000_read_word(state, 388);
+					agc2 = dib8000_read_word(state, 389);
+					dib8000_write_word(state, 108, agc1);
+					dib8000_write_word(state, 109, agc1);
+					dib8000_write_word(state, 110, agc2);
+					dib8000_write_word(state, 111, agc2);
+				}
+#endif
+				state->autosearch_state = AS_SEARCHING_FFT;
+				state->found_nfft = TRANSMISSION_MODE_AUTO;
+				state->found_guard = GUARD_INTERVAL_AUTO;
+				*tune_state = CT_DEMOD_SEARCH_NEXT;
+			} else { /* we already know the channel struct so TUNE only ! */
+				state->autosearch_state = AS_DONE;
+				*tune_state = CT_DEMOD_STEP_3;
+			}
+			state->symbol_duration = dib8000_get_symbol_duration(state);
+			break;
+
+	case CT_DEMOD_SEARCH_NEXT: /* 51 */
+			dib8000_autosearch_start(fe);
+			if (state->revision == 0x8090)
+				ret = 50;
+			else
+				ret = 15;
+			*tune_state = CT_DEMOD_STEP_1;
+			break;
+
+	case CT_DEMOD_STEP_1: /* 31 */
+			switch (dib8000_autosearch_irq(fe)) {
+			case 1: /* fail */
+					state->status = FE_STATUS_TUNE_FAILED;
+					state->autosearch_state = AS_DONE;
+					*tune_state = CT_DEMOD_STOP; /* else we are done here */
+					break;
+			case 2: /* Succes */
+					state->status = FE_STATUS_FFT_SUCCESS; /* signal to the upper layer, that there was a channel found and the parameters can be read */
+					*tune_state = CT_DEMOD_STEP_3;
+					if (state->autosearch_state == AS_SEARCHING_GUARD)
+						*tune_state = CT_DEMOD_STEP_2;
+					else
+						state->autosearch_state = AS_DONE;
+					break;
+			case 3: /* Autosearch FFT max correlation endded */
+					*tune_state = CT_DEMOD_STEP_2;
+					break;
+			}
+			break;
+
+	case CT_DEMOD_STEP_2:
+			switch (state->autosearch_state) {
+			case AS_SEARCHING_FFT:
+					/* searching for the correct FFT */
+				if (state->revision == 0x8090) {
+					corm[2] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
+					corm[1] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
+					corm[0] = (dib8000_read_word(state, 600) << 16) | (dib8000_read_word(state, 601));
+				} else {
+					corm[2] = (dib8000_read_word(state, 594) << 16) | (dib8000_read_word(state, 595));
+					corm[1] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
+					corm[0] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
+				}
+					/* dprintk("corm fft: %u %u %u", corm[0], corm[1], corm[2]); */
+
+					max_value = 0;
+					for (find_index = 1 ; find_index < 3 ; find_index++) {
+						if (corm[max_value] < corm[find_index])
+							max_value = find_index ;
+					}
+
+					switch (max_value) {
+					case 0:
+							state->found_nfft = TRANSMISSION_MODE_2K;
+							break;
+					case 1:
+							state->found_nfft = TRANSMISSION_MODE_4K;
+							break;
+					case 2:
+					default:
+							state->found_nfft = TRANSMISSION_MODE_8K;
+							break;
+					}
+					/* dprintk("Autosearch FFT has found Mode %d", max_value + 1); */
+
+					*tune_state = CT_DEMOD_SEARCH_NEXT;
+					state->autosearch_state = AS_SEARCHING_GUARD;
+					if (state->revision == 0x8090)
+						ret = 50;
+					else
+						ret = 10;
+					break;
+			case AS_SEARCHING_GUARD:
+					/* searching for the correct guard interval */
+					if (state->revision == 0x8090)
+						state->found_guard = dib8000_read_word(state, 572) & 0x3;
+					else
+						state->found_guard = dib8000_read_word(state, 570) & 0x3;
+					/* dprintk("guard interval found=%i", state->found_guard); */
+
+					*tune_state = CT_DEMOD_STEP_3;
+					break;
+			default:
+					/* the demod should never be in this state */
+					state->status = FE_STATUS_TUNE_FAILED;
+					state->autosearch_state = AS_DONE;
+					*tune_state = CT_DEMOD_STOP; /* else we are done here */
+					break;
+			}
+			break;
+
+	case CT_DEMOD_STEP_3: /* 33 */
+			state->symbol_duration = dib8000_get_symbol_duration(state);
+			dib8000_set_isdbt_loop_params(state, LOOP_TUNE_1);
+			dib8000_set_isdbt_common_channel(state, 0, 0);/* setting the known channel parameters here */
+			*tune_state = CT_DEMOD_STEP_4;
+			break;
+
+	case CT_DEMOD_STEP_4: /* (34) */
+			dib8000_demod_restart(state);
+
+			dib8000_set_sync_wait(state);
+			dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
+
+			locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */
+			/* coff should lock over P_coff_winlen ofdm symbols : give 3 times this lenght to lock */
+			*timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON);
+			*tune_state = CT_DEMOD_STEP_5;
+			break;
+
+	case CT_DEMOD_STEP_5: /* (35) */
+			locks = dib8000_read_lock(fe);
+			if (locks & (0x3 << 11)) { /* coff-lock and off_cpil_lock achieved */
+				dib8000_update_timf(state); /* we achieved a coff_cpil_lock - it's time to update the timf */
+				if (!state->differential_constellation) {
+					/* 2 times lmod4_win_len + 10 symbols (pipe delay after coff + nb to compute a 1st correlation) */
+					*timeout = dib8000_get_timeout(state, (20 * ((dib8000_read_word(state, 188)>>5)&0x1f)), SYMBOL_DEPENDENT_ON);
+					*tune_state = CT_DEMOD_STEP_7;
+				} else {
+					*tune_state = CT_DEMOD_STEP_8;
+				}
+			} else if (now > *timeout) {
+				*tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
+			}
+			break;
+
+	case CT_DEMOD_STEP_6: /* (36)  if there is an input (diversity) */
+			if ((state->fe[1] != NULL) && (state->output_mode != OUTMODE_DIVERSITY)) {
+				/* if there is a diversity fe in input and this fe is has not already failled : wait here until this this fe has succedeed or failled */
+				if (dib8000_get_status(state->fe[1]) <= FE_STATUS_STD_SUCCESS) /* Something is locked on the input fe */
+					*tune_state = CT_DEMOD_STEP_8; /* go for mpeg */
+				else if (dib8000_get_status(state->fe[1]) >= FE_STATUS_TUNE_TIME_TOO_SHORT) { /* fe in input failled also, break the current one */
+					*tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
+					dib8000_viterbi_state(state, 1); /* start viterbi chandec */
+					dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
+					state->status = FE_STATUS_TUNE_FAILED;
+				}
+			} else {
+				dib8000_viterbi_state(state, 1); /* start viterbi chandec */
+				dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
+				*tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
+				state->status = FE_STATUS_TUNE_FAILED;
+			}
+			break;
+
+	case CT_DEMOD_STEP_7: /* 37 */
+			locks = dib8000_read_lock(fe);
+			if (locks & (1<<10)) { /* lmod4_lock */
+				ret = 14; /* wait for 14 symbols */
+				*tune_state = CT_DEMOD_STEP_8;
+			} else if (now > *timeout)
+				*tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
+			break;
+
+	case CT_DEMOD_STEP_8: /* 38 */
+			dib8000_viterbi_state(state, 1); /* start viterbi chandec */
+			dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
+
+			/* mpeg will never lock on this condition because init_prbs is not set : search for it !*/
+			if (c->isdbt_sb_mode
+			    && c->isdbt_sb_subchannel < 14
+			    && !state->differential_constellation) {
+				state->subchannel = 0;
+				*tune_state = CT_DEMOD_STEP_11;
+			} else {
+				*tune_state = CT_DEMOD_STEP_9;
+				state->status = FE_STATUS_LOCKED;
+			}
+			break;
+
+	case CT_DEMOD_STEP_9: /* 39 */
+			if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */
+				/* defines timeout for mpeg lock depending on interleaver lenght of longest layer */
+				for (i = 0; i < 3; i++) {
+					if (c->layer[i].interleaving >= deeper_interleaver) {
+						dprintk("layer%i: time interleaver = %d ", i, c->layer[i].interleaving);
+						if (c->layer[i].segment_count > 0) { /* valid layer */
+							deeper_interleaver = c->layer[0].interleaving;
+							state->longest_intlv_layer = i;
+						}
+					}
+				}
+
+				if (deeper_interleaver == 0)
+					locks = 2; /* locks is the tmp local variable name */
+				else if (deeper_interleaver == 3)
+					locks = 8;
+				else
+					locks = 2 * deeper_interleaver;
+
+				if (state->diversity_onoff != 0) /* because of diversity sync */
+					locks *= 2;
+
+				*timeout = now + (2000 * locks); /* give the mpeg lock 800ms if sram is present */
+				dprintk("Deeper interleaver mode = %d on layer %d : timeout mult factor = %d => will use timeout = %d", deeper_interleaver, state->longest_intlv_layer, locks, *timeout);
+
+				*tune_state = CT_DEMOD_STEP_10;
+			} else
+				*tune_state = CT_DEMOD_STOP;
+			break;
+
+	case CT_DEMOD_STEP_10: /* 40 */
+			locks = dib8000_read_lock(fe);
+			if (locks&(1<<(7-state->longest_intlv_layer))) { /* mpeg lock : check the longest one */
+				dprintk("Mpeg locks [ L0 : %d | L1 : %d | L2 : %d ]", (locks>>7)&0x1, (locks>>6)&0x1, (locks>>5)&0x1);
+				if (c->isdbt_sb_mode
+				    && c->isdbt_sb_subchannel < 14
+				    && !state->differential_constellation)
+					/* signal to the upper layer, that there was a channel found and the parameters can be read */
+					state->status = FE_STATUS_DEMOD_SUCCESS;
+				else
+					state->status = FE_STATUS_DATA_LOCKED;
+				*tune_state = CT_DEMOD_STOP;
+			} else if (now > *timeout) {
+				if (c->isdbt_sb_mode
+				    && c->isdbt_sb_subchannel < 14
+				    && !state->differential_constellation) { /* continue to try init prbs autosearch */
+					state->subchannel += 3;
+					*tune_state = CT_DEMOD_STEP_11;
+				} else { /* we are done mpeg of the longest interleaver xas not locking but let's try if an other layer has locked in the same time */
+					if (locks & (0x7<<5)) {
+						dprintk("Mpeg locks [ L0 : %d | L1 : %d | L2 : %d ]", (locks>>7)&0x1, (locks>>6)&0x1, (locks>>5)&0x1);
+						state->status = FE_STATUS_DATA_LOCKED;
+					} else
+						state->status = FE_STATUS_TUNE_FAILED;
+					*tune_state = CT_DEMOD_STOP;
+				}
+			}
+			break;
+
+	case CT_DEMOD_STEP_11:  /* 41 : init prbs autosearch */
+			if (state->subchannel <= 41) {
+				dib8000_set_subchannel_prbs(state, dib8000_get_init_prbs(state, state->subchannel));
+				*tune_state = CT_DEMOD_STEP_9;
+			} else {
+				*tune_state = CT_DEMOD_STOP;
+				state->status = FE_STATUS_TUNE_FAILED;
+			}
+			break;
+
+	default:
+			break;
 	}
 
+	/* tuning is finished - cleanup the demod */
+	switch (*tune_state) {
+	case CT_DEMOD_STOP: /* (42) */
+#ifdef DIB8000_AGC_FREEZE
+			if ((state->revision != 0x8090) && (state->agc1_max != 0)) {
+				dib8000_write_word(state, 108, state->agc1_max);
+				dib8000_write_word(state, 109, state->agc1_min);
+				dib8000_write_word(state, 110, state->agc2_max);
+				dib8000_write_word(state, 111, state->agc2_min);
+				state->agc1_max = 0;
+				state->agc1_min = 0;
+				state->agc2_max = 0;
+				state->agc2_min = 0;
+			}
+#endif
+			ret = FE_CALLBACK_TIME_NEVER;
+			break;
+	default:
+			break;
+	}
+
+	if ((ret > 0) && (*tune_state > CT_DEMOD_STEP_3))
+		return ret * state->symbol_duration;
+	if ((ret > 0) && (ret < state->symbol_duration))
+		return state->symbol_duration; /* at least one symbol */
 	return ret;
 }
 
@@ -2767,7 +3226,7 @@ static int dib8000_wakeup(struct dvb_frontend *fe)
 	if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
 		dprintk("could not start Slow ADC");
 
-	if (state->revision != 0x8090)
+	if (state->revision == 0x8090)
 		dib8000_sad_calib(state);
 
 	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
@@ -2797,21 +3256,6 @@ static int dib8000_sleep(struct dvb_frontend *fe)
 	return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF);
 }
 
-enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	return state->tune_state;
-}
-EXPORT_SYMBOL(dib8000_get_tune_state);
-
-int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	state->tune_state = tune_state;
-	return 0;
-}
-EXPORT_SYMBOL(dib8000_set_tune_state);
-
 static int dib8000_get_frontend(struct dvb_frontend *fe)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
@@ -2961,19 +3405,19 @@ static int dib8000_get_frontend(struct dvb_frontend *fe)
 static int dib8000_set_frontend(struct dvb_frontend *fe)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
-	u8 nbr_pending, exit_condition, index_frontend;
-	s8 index_frontend_success = -1;
-	int time, ret;
-	int  time_slave = FE_CALLBACK_TIME_NEVER;
+	struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
+	int l, i, active, time, ret, time_slave = FE_CALLBACK_TIME_NEVER;
+	u8 exit_condition, index_frontend;
+	u32 delay, callback_time;
 
-	if (state->fe[0]->dtv_property_cache.frequency == 0) {
+	if (c->frequency == 0) {
 		dprintk("dib8000: must at least specify frequency ");
 		return 0;
 	}
 
-	if (state->fe[0]->dtv_property_cache.bandwidth_hz == 0) {
+	if (c->bandwidth_hz == 0) {
 		dprintk("dib8000: no bandwidth specified, set to default ");
-		state->fe[0]->dtv_property_cache.bandwidth_hz = 6000000;
+		c->bandwidth_hz = 6000000;
 	}
 
 	for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
@@ -2981,18 +3425,36 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
 		state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_ISDBT;
 		memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties));
 
-		if (state->revision != 0x8090)
-			dib8000_set_output_mode(state->fe[index_frontend],
-					OUTMODE_HIGH_Z);
-		else
-			dib8096p_set_output_mode(state->fe[index_frontend],
-					OUTMODE_HIGH_Z);
+		/* set output mode and diversity input */
+		if (state->revision != 0x8090) {
+			dib8000_set_diversity_in(state->fe[index_frontend], 1);
+			if (index_frontend != 0)
+				dib8000_set_output_mode(state->fe[index_frontend],
+						OUTMODE_DIVERSITY);
+			else
+				dib8000_set_output_mode(state->fe[0], OUTMODE_HIGH_Z);
+		} else {
+			dib8096p_set_diversity_in(state->fe[index_frontend], 1);
+			if (index_frontend != 0)
+				dib8096p_set_output_mode(state->fe[index_frontend],
+						OUTMODE_DIVERSITY);
+			else
+				dib8096p_set_output_mode(state->fe[0], OUTMODE_HIGH_Z);
+		}
+
+		/* tune the tuner */
 		if (state->fe[index_frontend]->ops.tuner_ops.set_params)
 			state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend]);
 
 		dib8000_set_tune_state(state->fe[index_frontend], CT_AGC_START);
 	}
 
+	/* turn off the diversity of the last chip */
+	if (state->revision != 0x8090)
+		dib8000_set_diversity_in(state->fe[index_frontend - 1], 0);
+	else
+		dib8096p_set_diversity_in(state->fe[index_frontend - 1], 0);
+
 	/* start up the AGC */
 	do {
 		time = dib8000_agc_startup(state->fe[0]);
@@ -3019,139 +3481,88 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
 	for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
 		dib8000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
 
-	if ((state->fe[0]->dtv_property_cache.delivery_system != SYS_ISDBT) ||
-			(state->fe[0]->dtv_property_cache.inversion == INVERSION_AUTO) ||
-			(state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) ||
-			(state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) ||
-			(((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) != 0) &&
-			 (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0xff) &&
-			 (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0) &&
-			 ((state->fe[0]->dtv_property_cache.layer[0].modulation == QAM_AUTO) ||
-			  (state->fe[0]->dtv_property_cache.layer[0].fec == FEC_AUTO))) ||
-			(((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 1)) != 0) &&
-			 (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0xff) &&
-			 (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0) &&
-			 ((state->fe[0]->dtv_property_cache.layer[1].modulation == QAM_AUTO) ||
-			  (state->fe[0]->dtv_property_cache.layer[1].fec == FEC_AUTO))) ||
-			(((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 2)) != 0) &&
-			 (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0xff) &&
-			 (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0) &&
-			 ((state->fe[0]->dtv_property_cache.layer[2].modulation == QAM_AUTO) ||
-			  (state->fe[0]->dtv_property_cache.layer[2].fec == FEC_AUTO))) ||
-			(((state->fe[0]->dtv_property_cache.layer[0].segment_count == 0) ||
-			  ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) == 0)) &&
-			 ((state->fe[0]->dtv_property_cache.layer[1].segment_count == 0) ||
-			  ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (2 << 0)) == 0)) &&
-			 ((state->fe[0]->dtv_property_cache.layer[2].segment_count == 0) || ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (3 << 0)) == 0)))) {
-		int i = 100;
-		u8 found = 0;
-		u8 tune_failed = 0;
-
+	active = 1;
+	do {
+		callback_time = FE_CALLBACK_TIME_NEVER;
 		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-			dib8000_set_bandwidth(state->fe[index_frontend], fe->dtv_property_cache.bandwidth_hz / 1000);
-			dib8000_autosearch_start(state->fe[index_frontend]);
-		}
-
-		do {
-			msleep(20);
-			nbr_pending = 0;
-			exit_condition = 0; /* 0: tune pending; 1: tune failed; 2:tune success */
-			for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-				if (((tune_failed >> index_frontend) & 0x1) == 0) {
-					found = dib8000_autosearch_irq(state->fe[index_frontend]);
-					switch (found) {
-					case 0: /* tune pending */
-						 nbr_pending++;
-						 break;
-					case 2:
-						 dprintk("autosearch succeed on the frontend%i", index_frontend);
-						 exit_condition = 2;
-						 index_frontend_success = index_frontend;
-						 break;
-					default:
-						 dprintk("unhandled autosearch result");
-					case 1:
-						 tune_failed |= (1 << index_frontend);
-						 dprintk("autosearch failed for the frontend%i", index_frontend);
-						 break;
+			delay = dib8000_tune(state->fe[index_frontend]);
+			if (delay != FE_CALLBACK_TIME_NEVER)
+				delay += systime();
+
+			/* we are in autosearch */
+			if (state->channel_parameters_set == 0) { /* searching */
+				if ((dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_DEMOD_SUCCESS) || (dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_FFT_SUCCESS)) {
+					dprintk("autosearch succeeded on fe%i", index_frontend);
+					dib8000_get_frontend(state->fe[index_frontend]); /* we read the channel parameters from the frontend which was successful */
+					state->channel_parameters_set = 1;
+
+					for (l = 0; (l < MAX_NUMBER_OF_FRONTENDS) && (state->fe[l] != NULL); l++) {
+						if (l != index_frontend) { /* and for all frontend except the successful one */
+							dib8000_tune_restart_from_demod(state->fe[l]);
+
+							state->fe[l]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode;
+							state->fe[l]->dtv_property_cache.inversion = state->fe[index_frontend]->dtv_property_cache.inversion;
+							state->fe[l]->dtv_property_cache.transmission_mode = state->fe[index_frontend]->dtv_property_cache.transmission_mode;
+							state->fe[l]->dtv_property_cache.guard_interval = state->fe[index_frontend]->dtv_property_cache.guard_interval;
+							state->fe[l]->dtv_property_cache.isdbt_partial_reception = state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception;
+							for (i = 0; i < 3; i++) {
+								state->fe[l]->dtv_property_cache.layer[i].segment_count = state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count;
+								state->fe[l]->dtv_property_cache.layer[i].interleaving = state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving;
+								state->fe[l]->dtv_property_cache.layer[i].fec = state->fe[index_frontend]->dtv_property_cache.layer[i].fec;
+								state->fe[l]->dtv_property_cache.layer[i].modulation = state->fe[index_frontend]->dtv_property_cache.layer[i].modulation;
+							}
+
+						}
 					}
 				}
 			}
-
-			/* if all tune are done and no success, exit: tune failed */
-			if ((nbr_pending == 0) && (exit_condition == 0))
-				exit_condition = 1;
-		} while ((exit_condition == 0) && i--);
-
-		if (exit_condition == 1) { /* tune failed */
-			dprintk("tune failed");
-			return 0;
+			if (delay < callback_time)
+				callback_time = delay;
+		}
+		/* tuning is done when the master frontend is done (failed or success) */
+		if (dib8000_get_status(state->fe[0]) == FE_STATUS_TUNE_FAILED ||
+				dib8000_get_status(state->fe[0]) == FE_STATUS_LOCKED ||
+				dib8000_get_status(state->fe[0]) == FE_STATUS_DATA_LOCKED) {
+			active = 0;
+			/* we need to wait for all frontends to be finished */
+			for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+				if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_DEMOD_STOP)
+					active = 1;
+			}
+			if (active == 0)
+				dprintk("tuning done with status %d", dib8000_get_status(state->fe[0]));
 		}
 
-		dprintk("tune success on frontend%i", index_frontend_success);
-
-		dib8000_get_frontend(fe);
-	}
+		if ((active == 1) && (callback_time == FE_CALLBACK_TIME_NEVER)) {
+			dprintk("strange callback time something went wrong");
+			active = 0;
+		}
 
-	for (index_frontend = 0, ret = 0; (ret >= 0) && (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
-		ret = dib8000_tune(state->fe[index_frontend]);
+		while ((active == 1) && (systime() < callback_time))
+			msleep(100);
+	} while (active);
 
-	/* set output mode and diversity input */
-	if (state->revision != 0x8090) {
+	/* set output mode */
+	if (state->revision != 0x8090)
 		dib8000_set_output_mode(state->fe[0], state->cfg.output_mode);
-		for (index_frontend = 1;
-				(index_frontend < MAX_NUMBER_OF_FRONTENDS) &&
-				(state->fe[index_frontend] != NULL);
-				index_frontend++) {
-			dib8000_set_output_mode(state->fe[index_frontend],
-					OUTMODE_DIVERSITY);
-			dib8000_set_diversity_in(state->fe[index_frontend-1], 1);
-		}
-
-		/* turn off the diversity of the last chip */
-		dib8000_set_diversity_in(state->fe[index_frontend-1], 0);
-	} else {
+	else {
 		dib8096p_set_output_mode(state->fe[0], state->cfg.output_mode);
 		if (state->cfg.enMpegOutput == 0) {
 			dib8096p_setDibTxMux(state, MPEG_ON_DIBTX);
 			dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
 		}
-		for (index_frontend = 1;
-				(index_frontend < MAX_NUMBER_OF_FRONTENDS) &&
-				(state->fe[index_frontend] != NULL);
-				index_frontend++) {
-			dib8096p_set_output_mode(state->fe[index_frontend],
-					OUTMODE_DIVERSITY);
-			dib8096p_set_diversity_in(state->fe[index_frontend-1], 1);
-		}
-
-		/* turn off the diversity of the last chip */
-		dib8096p_set_diversity_in(state->fe[index_frontend-1], 0);
 	}
 
 	return ret;
 }
 
-static u16 dib8000_read_lock(struct dvb_frontend *fe)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-
-	if (state->revision == 0x8090)
-		return dib8000_read_word(state, 570);
-	return dib8000_read_word(state, 568);
-}
-
 static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
 	u16 lock_slave = 0, lock;
 	u8 index_frontend;
 
-	if (state->revision == 0x8090)
-		lock = dib8000_read_word(state, 570);
-	else
-		lock = dib8000_read_word(state, 568);
-
+	lock = dib8000_read_lock(fe);
 	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
 		lock_slave |= dib8000_read_lock(state->fe[index_frontend]);
 
@@ -3545,10 +3956,11 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s
 	dib8000_reset(fe);
 
 	dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5));	/* ber_rs_len = 3 */
+	state->current_demod_bw = 6000;
 
 	return fe;
 
- error:
+error:
 	kfree(state);
 	return NULL;
 }

+ 4 - 2
drivers/media/dvb-frontends/dib8000.h

@@ -33,6 +33,8 @@ struct dib8000_config {
 	u8 output_mode;
 	u8 refclksel;
 	u8 enMpegOutput:1;
+
+	struct dibx000_bandwidth_config *plltable;
 };
 
 #define DEFAULT_DIB8000_I2C_ADDRESS 18
@@ -58,7 +60,7 @@ extern int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ);
 extern u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
 		uint8_t op, uint32_t timf);
 extern int dib8000_update_pll(struct dvb_frontend *fe,
-		struct dibx000_bandwidth_config *pll);
+		struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio);
 extern int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
 extern int dib8000_remove_slave_frontend(struct dvb_frontend *fe);
 extern struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index);
@@ -147,7 +149,7 @@ static inline u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
 	return 0;
 }
 static inline int dib8000_update_pll(struct dvb_frontend *fe,
-		struct dibx000_bandwidth_config *pll)
+		struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return -ENODEV;

+ 2 - 1
drivers/media/dvb-frontends/dibx000_common.h

@@ -193,7 +193,8 @@ enum frontend_tune_state {
 	CT_DEMOD_STEP_8,
 	CT_DEMOD_STEP_9,
 	CT_DEMOD_STEP_10,
-	CT_DEMOD_SEARCH_NEXT = 41,
+	CT_DEMOD_STEP_11,
+	CT_DEMOD_SEARCH_NEXT = 51,
 	CT_DEMOD_STEP_LOCKED,
 	CT_DEMOD_STOP,
 

+ 2 - 2
drivers/media/dvb-frontends/drxd.h

@@ -24,6 +24,7 @@
 #ifndef _DRXD_H_
 #define _DRXD_H_
 
+#include <linux/kconfig.h>
 #include <linux/types.h>
 #include <linux/i2c.h>
 
@@ -51,8 +52,7 @@ struct drxd_config {
 	 s16(*osc_deviation) (void *priv, s16 dev, int flag);
 };
 
-#if defined(CONFIG_DVB_DRXD) || \
-			(defined(CONFIG_DVB_DRXD_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_DRXD)
 extern
 struct dvb_frontend *drxd_attach(const struct drxd_config *config,
 				 void *priv, struct i2c_adapter *i2c,

+ 2 - 2
drivers/media/dvb-frontends/drxk.h

@@ -1,6 +1,7 @@
 #ifndef _DRXK_H_
 #define _DRXK_H_
 
+#include <linux/kconfig.h>
 #include <linux/types.h>
 #include <linux/i2c.h>
 
@@ -52,8 +53,7 @@ struct drxk_config {
 	int		 qam_demod_parameter_count;
 };
 
-#if defined(CONFIG_DVB_DRXK) || (defined(CONFIG_DVB_DRXK_MODULE) \
-        && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_DRXK)
 extern struct dvb_frontend *drxk_attach(const struct drxk_config *config,
 					struct i2c_adapter *i2c);
 #else

+ 256 - 53
drivers/media/dvb-frontends/drxk_hard.c

@@ -1947,8 +1947,7 @@ static int ShutDown(struct drxk_state *state)
 	return 0;
 }
 
-static int GetLockStatus(struct drxk_state *state, u32 *pLockStatus,
-			 u32 Time)
+static int GetLockStatus(struct drxk_state *state, u32 *pLockStatus)
 {
 	int status = -EINVAL;
 
@@ -2490,32 +2489,6 @@ error:
 	return status;
 }
 
-static int ReadIFAgc(struct drxk_state *state, u32 *pValue)
-{
-	u16 agcDacLvl;
-	int status;
-	u16 Level = 0;
-
-	dprintk(1, "\n");
-
-	status = read16(state, IQM_AF_AGC_IF__A, &agcDacLvl);
-	if (status < 0) {
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-		return status;
-	}
-
-	*pValue = 0;
-
-	if (agcDacLvl > DRXK_AGC_DAC_OFFSET)
-		Level = agcDacLvl - DRXK_AGC_DAC_OFFSET;
-	if (Level < 14000)
-		*pValue = (14000 - Level) / 4;
-	else
-		*pValue = 0;
-
-	return status;
-}
-
 static int GetQAMSignalToNoise(struct drxk_state *state,
 			       s32 *pSignalToNoise)
 {
@@ -2654,12 +2627,7 @@ static int GetDVBTSignalToNoise(struct drxk_state *state,
 		/* log(x) x = (16bits + 16bits) << 15 ->32 bits  */
 		c = Log10Times100(SqrErrIQ);
 
-		iMER = a + b;
-		/* No negative MER, clip to zero */
-		if (iMER > c)
-			iMER -= c;
-		else
-			iMER = 0;
+		iMER = a + b - c;
 	}
 	*pSignalToNoise = iMER;
 
@@ -6380,46 +6348,257 @@ static int drxk_set_parameters(struct dvb_frontend *fe)
 	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
 	Start(state, 0, IF);
 
+	/* After set_frontend, stats aren't avaliable */
+	p->strength.stat[0].scale = FE_SCALE_RELATIVE;
+	p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
 	/* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */
 
 	return 0;
 }
 
-static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
+static int get_strength(struct drxk_state *state, u64 *strength)
 {
+	int status;
+	struct SCfgAgc   rfAgc, ifAgc;
+	u32          totalGain  = 0;
+	u32          atten      = 0;
+	u32          agcRange   = 0;
+	u16            scu_lvl  = 0;
+	u16            scu_coc  = 0;
+	/* FIXME: those are part of the tuner presets */
+	u16 tunerRfGain         = 50; /* Default value on az6007 driver */
+	u16 tunerIfGain         = 40; /* Default value on az6007 driver */
+
+	*strength = 0;
+
+	if (IsDVBT(state)) {
+		rfAgc = state->m_dvbtRfAgcCfg;
+		ifAgc = state->m_dvbtIfAgcCfg;
+	} else if (IsQAM(state)) {
+		rfAgc = state->m_qamRfAgcCfg;
+		ifAgc = state->m_qamIfAgcCfg;
+	} else {
+		rfAgc = state->m_atvRfAgcCfg;
+		ifAgc = state->m_atvIfAgcCfg;
+	}
+
+	if (rfAgc.ctrlMode == DRXK_AGC_CTRL_AUTO) {
+		/* SCU outputLevel */
+		status = read16(state, SCU_RAM_AGC_RF_IACCU_HI__A, &scu_lvl);
+		if (status < 0)
+			return status;
+
+		/* SCU c.o.c. */
+		read16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, &scu_coc);
+		if (status < 0)
+			return status;
+
+		if (((u32) scu_lvl + (u32) scu_coc) < 0xffff)
+			rfAgc.outputLevel = scu_lvl + scu_coc;
+		else
+			rfAgc.outputLevel = 0xffff;
+
+		/* Take RF gain into account */
+		totalGain += tunerRfGain;
+
+		/* clip output value */
+		if (rfAgc.outputLevel < rfAgc.minOutputLevel)
+			rfAgc.outputLevel = rfAgc.minOutputLevel;
+		if (rfAgc.outputLevel > rfAgc.maxOutputLevel)
+			rfAgc.outputLevel = rfAgc.maxOutputLevel;
+
+		agcRange = (u32) (rfAgc.maxOutputLevel - rfAgc.minOutputLevel);
+		if (agcRange > 0) {
+			atten += 100UL *
+				((u32)(tunerRfGain)) *
+				((u32)(rfAgc.outputLevel - rfAgc.minOutputLevel))
+				/ agcRange;
+		}
+	}
+
+	if (ifAgc.ctrlMode == DRXK_AGC_CTRL_AUTO) {
+		status = read16(state, SCU_RAM_AGC_IF_IACCU_HI__A,
+				&ifAgc.outputLevel);
+		if (status < 0)
+			return status;
+
+		status = read16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A,
+				&ifAgc.top);
+		if (status < 0)
+			return status;
+
+		/* Take IF gain into account */
+		totalGain += (u32) tunerIfGain;
+
+		/* clip output value */
+		if (ifAgc.outputLevel < ifAgc.minOutputLevel)
+			ifAgc.outputLevel = ifAgc.minOutputLevel;
+		if (ifAgc.outputLevel > ifAgc.maxOutputLevel)
+			ifAgc.outputLevel = ifAgc.maxOutputLevel;
+
+		agcRange  = (u32) (ifAgc.maxOutputLevel - ifAgc.minOutputLevel);
+		if (agcRange > 0) {
+			atten += 100UL *
+				((u32)(tunerIfGain)) *
+				((u32)(ifAgc.outputLevel - ifAgc.minOutputLevel))
+				/ agcRange;
+		}
+	}
+
+	/*
+	 * Convert to 0..65535 scale.
+	 * If it can't be measured (AGC is disabled), just show 100%.
+	 */
+	if (totalGain > 0)
+		*strength = (65535UL * atten / totalGain / 100);
+	else
+		*strength = 65535;
+
+	return 0;
+}
+
+static int drxk_get_stats(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	struct drxk_state *state = fe->demodulator_priv;
+	int status;
 	u32 stat;
-
-	dprintk(1, "\n");
+	u16 reg16;
+	u32 post_bit_count;
+	u32 post_bit_err_count;
+	u32 post_bit_error_scale;
+	u32 pre_bit_err_count;
+	u32 pre_bit_count;
+	u32 pkt_count;
+	u32 pkt_error_count;
+	s32 cnr;
 
 	if (state->m_DrxkState == DRXK_NO_DEV)
 		return -ENODEV;
 	if (state->m_DrxkState == DRXK_UNINITIALIZED)
 		return -EAGAIN;
 
-	*status = 0;
-	GetLockStatus(state, &stat, 0);
+	/* get status */
+	state->fe_status = 0;
+	GetLockStatus(state, &stat);
 	if (stat == MPEG_LOCK)
-		*status |= 0x1f;
+		state->fe_status |= 0x1f;
 	if (stat == FEC_LOCK)
-		*status |= 0x0f;
+		state->fe_status |= 0x0f;
 	if (stat == DEMOD_LOCK)
-		*status |= 0x07;
-	return 0;
+		state->fe_status |= 0x07;
+
+	/*
+	 * Estimate signal strength from AGC
+	 */
+	get_strength(state, &c->strength.stat[0].uvalue);
+	c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+
+
+	if (stat >= DEMOD_LOCK) {
+		GetSignalToNoise(state, &cnr);
+		c->cnr.stat[0].svalue = cnr * 100;
+		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+	} else {
+		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	}
+
+	if (stat < FEC_LOCK) {
+		c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		return 0;
+	}
+
+	/* Get post BER */
+
+	/* BER measurement is valid if at least FEC lock is achieved */
+
+	/* OFDM_EC_VD_REQ_SMB_CNT__A and/or OFDM_EC_VD_REQ_BIT_CNT can be written
+		to set nr of symbols or bits over which
+		to measure EC_VD_REG_ERR_BIT_CNT__A . See CtrlSetCfg(). */
+
+	/* Read registers for post/preViterbi BER calculation */
+	status = read16(state, OFDM_EC_VD_ERR_BIT_CNT__A, &reg16);
+	if (status < 0)
+		goto error;
+	pre_bit_err_count = reg16;
+
+	status = read16(state, OFDM_EC_VD_IN_BIT_CNT__A , &reg16);
+	if (status < 0)
+		goto error;
+	pre_bit_count = reg16;
+
+	/* Number of bit-errors */
+	status = read16(state, FEC_RS_NR_BIT_ERRORS__A, &reg16);
+	if (status < 0)
+		goto error;
+	post_bit_err_count = reg16;
+
+	status = read16(state, FEC_RS_MEASUREMENT_PRESCALE__A, &reg16);
+	if (status < 0)
+		goto error;
+	post_bit_error_scale = reg16;
+
+	status = read16(state, FEC_RS_MEASUREMENT_PERIOD__A, &reg16);
+	if (status < 0)
+		goto error;
+	pkt_count = reg16;
+
+	status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, &reg16);
+	if (status < 0)
+		goto error;
+	pkt_error_count = reg16;
+	write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0);
+
+	post_bit_err_count *= post_bit_error_scale;
+
+	post_bit_count = pkt_count * 204 * 8;
+
+	/* Store the results */
+	c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->block_error.stat[0].uvalue += pkt_error_count;
+	c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->block_count.stat[0].uvalue += pkt_count;
+
+	c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->pre_bit_error.stat[0].uvalue += pre_bit_err_count;
+	c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->pre_bit_count.stat[0].uvalue += pre_bit_count;
+
+	c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_error.stat[0].uvalue += post_bit_err_count;
+	c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+	c->post_bit_count.stat[0].uvalue += post_bit_count;
+
+error:
+	return status;
 }
 
-static int drxk_read_ber(struct dvb_frontend *fe, u32 *ber)
+
+static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
 	struct drxk_state *state = fe->demodulator_priv;
+	int rc;
 
 	dprintk(1, "\n");
 
-	if (state->m_DrxkState == DRXK_NO_DEV)
-		return -ENODEV;
-	if (state->m_DrxkState == DRXK_UNINITIALIZED)
-		return -EAGAIN;
+	rc = drxk_get_stats(fe);
+	if (rc < 0)
+		return rc;
+
+	*status = state->fe_status;
 
-	*ber = 0;
 	return 0;
 }
 
@@ -6427,7 +6606,7 @@ static int drxk_read_signal_strength(struct dvb_frontend *fe,
 				     u16 *strength)
 {
 	struct drxk_state *state = fe->demodulator_priv;
-	u32 val = 0;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
 	dprintk(1, "\n");
 
@@ -6436,8 +6615,7 @@ static int drxk_read_signal_strength(struct dvb_frontend *fe,
 	if (state->m_DrxkState == DRXK_UNINITIALIZED)
 		return -EAGAIN;
 
-	ReadIFAgc(state, &val);
-	*strength = val & 0xffff;
+	*strength = c->strength.stat[0].uvalue;
 	return 0;
 }
 
@@ -6454,6 +6632,10 @@ static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr)
 		return -EAGAIN;
 
 	GetSignalToNoise(state, &snr2);
+
+	/* No negative SNR, clip to zero */
+	if (snr2 < 0)
+		snr2 = 0;
 	*snr = snr2 & 0xffff;
 	return 0;
 }
@@ -6529,7 +6711,6 @@ static struct dvb_frontend_ops drxk_ops = {
 	.get_tune_settings = drxk_get_tune_settings,
 
 	.read_status = drxk_read_status,
-	.read_ber = drxk_read_ber,
 	.read_signal_strength = drxk_read_signal_strength,
 	.read_snr = drxk_read_snr,
 	.read_ucblocks = drxk_read_ucblocks,
@@ -6538,6 +6719,7 @@ static struct dvb_frontend_ops drxk_ops = {
 struct dvb_frontend *drxk_attach(const struct drxk_config *config,
 				 struct i2c_adapter *i2c)
 {
+	struct dtv_frontend_properties *p;
 	struct drxk_state *state = NULL;
 	u8 adr = config->adr;
 	int status;
@@ -6618,6 +6800,27 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
 	} else if (init_drxk(state) < 0)
 		goto error;
 
+
+	/* Initialize stats */
+	p = &state->frontend.dtv_property_cache;
+	p->strength.len = 1;
+	p->cnr.len = 1;
+	p->block_error.len = 1;
+	p->block_count.len = 1;
+	p->pre_bit_error.len = 1;
+	p->pre_bit_count.len = 1;
+	p->post_bit_error.len = 1;
+	p->post_bit_count.len = 1;
+
+	p->strength.stat[0].scale = FE_SCALE_RELATIVE;
+	p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
 	printk(KERN_INFO "drxk: frontend initialized.\n");
 	return &state->frontend;
 

+ 2 - 0
drivers/media/dvb-frontends/drxk_hard.h

@@ -345,6 +345,8 @@ struct drxk_state {
 	bool	antenna_dvbt;
 	u16	antenna_gpio;
 
+	fe_status_t fe_status;
+
 	/* Firmware */
 	const char *microcode_name;
 	struct completion fw_wait_load;

+ 3 - 0
drivers/media/dvb-frontends/drxk_map.h

@@ -10,6 +10,7 @@
 #define    FEC_RS_COMM_EXEC_STOP                                           0x0
 #define  FEC_RS_MEASUREMENT_PERIOD__A                                      0x1C30012
 #define  FEC_RS_MEASUREMENT_PRESCALE__A                                    0x1C30013
+#define FEC_RS_NR_BIT_ERRORS__A                                            0x1C30014
 #define  FEC_OC_MODE__A                                                    0x1C40011
 #define    FEC_OC_MODE_PARITY__M                                           0x1
 #define  FEC_OC_DTO_MODE__A                                                0x1C40014
@@ -129,6 +130,8 @@
 #define  OFDM_EC_SB_PRIOR__A                                               0x3410013
 #define    OFDM_EC_SB_PRIOR_HI                                             0x0
 #define    OFDM_EC_SB_PRIOR_LO                                             0x1
+#define OFDM_EC_VD_ERR_BIT_CNT__A                                          0x3420017
+#define OFDM_EC_VD_IN_BIT_CNT__A                                           0x3420018
 #define  OFDM_EQ_TOP_TD_TPS_CONST__A                                       0x3010054
 #define  OFDM_EQ_TOP_TD_TPS_CONST__M                                       0x3
 #define    OFDM_EQ_TOP_TD_TPS_CONST_64QAM                                  0x2

+ 2 - 2
drivers/media/dvb-frontends/ds3000.h

@@ -22,6 +22,7 @@
 #ifndef DS3000_H
 #define DS3000_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct ds3000_config {
@@ -34,8 +35,7 @@ struct ds3000_config {
 	void (*set_lock_led)(struct dvb_frontend *fe, int offon);
 };
 
-#if defined(CONFIG_DVB_DS3000) || \
-			(defined(CONFIG_DVB_DS3000_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_DS3000)
 extern struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
 					struct i2c_adapter *i2c);
 #else

+ 2 - 2
drivers/media/dvb-frontends/dvb_dummy_fe.h

@@ -22,11 +22,11 @@
 #ifndef DVB_DUMMY_FE_H
 #define DVB_DUMMY_FE_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
 
-#if defined(CONFIG_DVB_DUMMY_FE) || (defined(CONFIG_DVB_DUMMY_FE_MODULE) && \
-defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_DUMMY_FE)
 extern struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void);
 extern struct dvb_frontend* dvb_dummy_fe_qpsk_attach(void);
 extern struct dvb_frontend* dvb_dummy_fe_qam_attach(void);

+ 2 - 2
drivers/media/dvb-frontends/ec100.h

@@ -22,6 +22,7 @@
 #ifndef EC100_H
 #define EC100_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct ec100_config {
@@ -30,8 +31,7 @@ struct ec100_config {
 };
 
 
-#if defined(CONFIG_DVB_EC100) || \
-	(defined(CONFIG_DVB_EC100_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_EC100)
 extern struct dvb_frontend *ec100_attach(const struct ec100_config *config,
 	struct i2c_adapter *i2c);
 #else

+ 2 - 2
drivers/media/dvb-frontends/hd29l2.h

@@ -23,6 +23,7 @@
 #ifndef HD29L2_H
 #define HD29L2_H
 
+#include <linux/kconfig.h>
 #include <linux/dvb/frontend.h>
 
 struct hd29l2_config {
@@ -50,8 +51,7 @@ struct hd29l2_config {
 };
 
 
-#if defined(CONFIG_DVB_HD29L2) || \
-	(defined(CONFIG_DVB_HD29L2_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_DVB_HD29L2)
 extern struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config,
 	struct i2c_adapter *i2c);
 #else

+ 27 - 1
drivers/media/dvb-frontends/isl6421.c

@@ -89,6 +89,30 @@ static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
 	return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
 }
 
+static int isl6421_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+	struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
+	struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0,
+			       .buf = &isl6421->config,
+			       .len = sizeof(isl6421->config) };
+
+	switch (tone) {
+	case SEC_TONE_ON:
+		isl6421->config |= ISL6421_ENT1;
+		break;
+	case SEC_TONE_OFF:
+		isl6421->config &= ~ISL6421_ENT1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	isl6421->config |= isl6421->override_or;
+	isl6421->config &= isl6421->override_and;
+
+	return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
 static void isl6421_release(struct dvb_frontend *fe)
 {
 	/* power off */
@@ -100,7 +124,7 @@ static void isl6421_release(struct dvb_frontend *fe)
 }
 
 struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
-		   u8 override_set, u8 override_clear)
+		   u8 override_set, u8 override_clear, bool override_tone)
 {
 	struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL);
 	if (!isl6421)
@@ -131,6 +155,8 @@ struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter
 	/* override frontend ops */
 	fe->ops.set_voltage = isl6421_set_voltage;
 	fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage;
+	if (override_tone)
+		fe->ops.set_tone = isl6421_set_tone;
 
 	return fe;
 }

+ 2 - 2
drivers/media/dvb-frontends/isl6421.h

@@ -42,10 +42,10 @@
 #if IS_ENABLED(CONFIG_DVB_ISL6421)
 /* override_set and override_clear control which system register bits (above) to always set & clear */
 extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
-			  u8 override_set, u8 override_clear);
+			  u8 override_set, u8 override_clear, bool override_tone);
 #else
 static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
-						  u8 override_set, u8 override_clear)
+						  u8 override_set, u8 override_clear, bool override_tone)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio