Эх сурвалжийг харах

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

* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (247 commits)
  [media] gspca - sunplus: Fix some warnings and simplify code
  [media] gspca: Fix some warnings tied to 'no debug'
  [media] gspca: Unset debug by default
  [media] gspca - cpia1: Remove a bad conditional compilation instruction
  [media] gspca - main: Remove USB traces
  [media] gspca - main: Version change to 2.13
  [media] gspca - stk014 / t613: Accept the index 0 in querymenu
  [media] gspca - kinect: Remove __devinitdata
  [media] gspca - cpia1: Fix some warnings
  [media] video/Kconfig: Fix mis-classified devices
  [media] support for medion dvb stick 1660:1921
  [media] tm6000: fix uninitialized field, change prink to dprintk
  [media] cx231xx: Add support for Iconbit U100
  [media] saa7134 add new TV cards
  [media] Use a more consistent value for RC repeat period
  [media] cx18: Move spinlock and vb_type initialisation into stream_init
  [media] tm6000: remove tm6010 sif audio start and stop
  [media] tm6000: remove unused exports
  [media] tm6000: add pts logging
  [media] tm6000: change from ioctl to unlocked_ioctl
  ...
Linus Torvalds 14 жил өмнө
parent
commit
df462b3dbe
100 өөрчлөгдсөн 11086 нэмэгдсэн , 2690 устгасан
  1. 1 0
      Documentation/DocBook/.gitignore
  2. 8 0
      Documentation/DocBook/dvb/dvbapi.xml
  3. 337 68
      Documentation/DocBook/dvb/dvbproperty.xml
  4. 16 4
      Documentation/DocBook/dvb/frontend.h.xml
  5. 2 0
      Documentation/DocBook/media-entities.tmpl
  6. 147 0
      Documentation/DocBook/v4l/pixfmt-m420.xml
  7. 43 0
      Documentation/DocBook/v4l/pixfmt-y10b.xml
  8. 2 0
      Documentation/DocBook/v4l/pixfmt.xml
  9. 46 0
      Documentation/DocBook/v4l/subdev-formats.xml
  10. 4 0
      Documentation/DocBook/v4l/videodev2.h.xml
  11. 23 0
      Documentation/feature-removal-schedule.txt
  12. 1 1
      Documentation/ioctl/ioctl-number.txt
  13. 1 1
      Documentation/video4linux/CARDLIST.em28xx
  14. 0 1
      Documentation/video4linux/Zoran
  15. 1 0
      Documentation/video4linux/gspca.txt
  16. 239 0
      Documentation/video4linux/uvcvideo.txt
  17. 1 6
      drivers/media/common/saa7146_core.c
  18. 8 0
      drivers/media/common/tuners/Kconfig
  19. 1 0
      drivers/media/common/tuners/Makefile
  20. 2 0
      drivers/media/common/tuners/mxl5005s.c
  21. 265 0
      drivers/media/common/tuners/tda18212.c
  22. 48 0
      drivers/media/common/tuners/tda18212.h
  23. 44 0
      drivers/media/common/tuners/tda18212_priv.h
  24. 4 0
      drivers/media/common/tuners/tda18271-fe.c
  25. 26 6
      drivers/media/common/tuners/xc5000.c
  26. 1 3
      drivers/media/dvb/b2c2/flexcop-pci.c
  27. 1 1
      drivers/media/dvb/bt8xx/bt878.c
  28. 57 60
      drivers/media/dvb/dvb-core/dvb_demux.c
  29. 193 172
      drivers/media/dvb/dvb-core/dvb_frontend.c
  30. 3 0
      drivers/media/dvb/dvb-core/dvb_frontend.h
  31. 5 0
      drivers/media/dvb/dvb-usb/Kconfig
  32. 13 4
      drivers/media/dvb/dvb-usb/a800.c
  33. 521 99
      drivers/media/dvb/dvb-usb/anysee.c
  34. 21 2
      drivers/media/dvb/dvb-usb/anysee.h
  35. 16 6
      drivers/media/dvb/dvb-usb/au6610.c
  36. 9 2
      drivers/media/dvb/dvb-usb/ce6230.c
  37. 3 2
      drivers/media/dvb/dvb-usb/dib0700.h
  38. 133 87
      drivers/media/dvb/dvb-usb/dib0700_core.c
  39. 6 2
      drivers/media/dvb/dvb-usb/dib0700_devices.c
  40. 1 1
      drivers/media/dvb/dvb-usb/dibusb-common.c
  41. 21 10
      drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
  42. 1 0
      drivers/media/dvb/dvb-usb/dvb-usb-ids.h
  43. 8 2
      drivers/media/dvb/dvb-usb/dw2102.c
  44. 15 3
      drivers/media/dvb/dvb-usb/ec168.c
  45. 19 4
      drivers/media/dvb/dvb-usb/friio.c
  46. 136 29
      drivers/media/dvb/dvb-usb/lmedm04.c
  47. 3 2
      drivers/media/dvb/dvb-usb/lmedm04.h
  48. 30 19
      drivers/media/dvb/dvb-usb/m920x.c
  49. 1 1
      drivers/media/dvb/dvb-usb/nova-t-usb2.c
  50. 21 12
      drivers/media/dvb/dvb-usb/opera1.c
  51. 59 21
      drivers/media/dvb/dvb-usb/vp702x-fe.c
  52. 167 46
      drivers/media/dvb/dvb-usb/vp702x.c
  53. 7 0
      drivers/media/dvb/dvb-usb/vp702x.h
  54. 34 13
      drivers/media/dvb/dvb-usb/vp7045.c
  55. 12 7
      drivers/media/dvb/frontends/Kconfig
  56. 5 1
      drivers/media/dvb/frontends/Makefile
  57. 146 0
      drivers/media/dvb/frontends/bsbe1-d01a.h
  58. 1 1
      drivers/media/dvb/frontends/bsru6.h
  59. 17 4
      drivers/media/dvb/frontends/cx24116.c
  60. 3 0
      drivers/media/dvb/frontends/cx24116.h
  61. 118 0
      drivers/media/dvb/frontends/cxd2820r.h
  62. 338 0
      drivers/media/dvb/frontends/cxd2820r_c.c
  63. 915 0
      drivers/media/dvb/frontends/cxd2820r_core.c
  64. 166 0
      drivers/media/dvb/frontends/cxd2820r_priv.h
  65. 449 0
      drivers/media/dvb/frontends/cxd2820r_t.c
  66. 423 0
      drivers/media/dvb/frontends/cxd2820r_t2.c
  67. 30 10
      drivers/media/dvb/frontends/dib0070.c
  68. 54 17
      drivers/media/dvb/frontends/dib0090.c
  69. 32 17
      drivers/media/dvb/frontends/dib7000m.c
  70. 52 20
      drivers/media/dvb/frontends/dib7000p.c
  71. 94 32
      drivers/media/dvb/frontends/dib8000.c
  72. 114 62
      drivers/media/dvb/frontends/dib9000.c
  73. 65 44
      drivers/media/dvb/frontends/dibx000_common.c
  74. 5 0
      drivers/media/dvb/frontends/dibx000_common.h
  75. 0 1511
      drivers/media/dvb/frontends/drx397xD.c
  76. 0 130
      drivers/media/dvb/frontends/drx397xD.h
  77. 0 40
      drivers/media/dvb/frontends/drx397xD_fw.h
  78. 61 0
      drivers/media/dvb/frontends/drxd.h
  79. 929 0
      drivers/media/dvb/frontends/drxd_firm.c
  80. 115 0
      drivers/media/dvb/frontends/drxd_firm.h
  81. 3001 0
      drivers/media/dvb/frontends/drxd_hard.c
  82. 1013 0
      drivers/media/dvb/frontends/drxd_map_firm.h
  83. 1 1
      drivers/media/dvb/frontends/eds1547.h
  84. 6 4
      drivers/media/dvb/frontends/ix2505v.c
  85. 1 1
      drivers/media/dvb/frontends/stv0288.c
  86. 8 2
      drivers/media/dvb/frontends/stv0299.c
  87. 1 1
      drivers/media/dvb/frontends/z0194a.h
  88. 1 1
      drivers/media/dvb/mantis/hopper_cards.c
  89. 1 1
      drivers/media/dvb/mantis/mantis_cards.c
  90. 2 3
      drivers/media/dvb/mantis/mantis_pci.c
  91. 1 1
      drivers/media/dvb/mantis/mantis_vp1033.c
  92. 3 2
      drivers/media/dvb/pt1/pt1.c
  93. 1 2
      drivers/media/dvb/siano/smsusb.c
  94. 2 0
      drivers/media/dvb/ttpci/Kconfig
  95. 21 0
      drivers/media/dvb/ttpci/budget-ci.c
  96. 27 33
      drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
  97. 42 18
      drivers/media/radio/si470x/radio-si470x-common.c
  98. 32 31
      drivers/media/radio/si470x/radio-si470x-i2c.c
  99. 3 1
      drivers/media/radio/si470x/radio-si470x.h
  100. 0 2
      drivers/media/radio/wl128x/fmdrv.h

+ 1 - 0
Documentation/DocBook/.gitignore

@@ -8,3 +8,4 @@
 *.dvi
 *.log
 *.out
+media/

+ 8 - 0
Documentation/DocBook/dvb/dvbapi.xml

@@ -34,6 +34,14 @@
 
 <revhistory>
 <!-- Put document revisions here, newest first. -->
+<revision>
+	<revnumber>2.0.4</revnumber>
+	<date>2011-05-06</date>
+	<authorinitials>mcc</authorinitials>
+	<revremark>
+		Add more information about DVB APIv5, better describing the frontend GET/SET props ioctl's.
+	</revremark>
+</revision>
 <revision>
 	<revnumber>2.0.3</revnumber>
 	<date>2010-07-03</date>

+ 337 - 68
Documentation/DocBook/dvb/dvbproperty.xml

@@ -1,6 +1,327 @@
-<section id="FE_GET_PROPERTY">
+<section id="FE_GET_SET_PROPERTY">
 <title>FE_GET_PROPERTY/FE_SET_PROPERTY</title>
 
+<programlisting>
+/* Reserved fields should be set to 0 */
+struct dtv_property {
+	__u32 cmd;
+	union {
+		__u32 data;
+		struct {
+			__u8 data[32];
+			__u32 len;
+			__u32 reserved1[3];
+			void *reserved2;
+		} buffer;
+	} u;
+	int result;
+} __attribute__ ((packed));
+
+/* num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl */
+#define DTV_IOCTL_MAX_MSGS 64
+
+struct dtv_properties {
+	__u32 num;
+	struct dtv_property *props;
+};
+</programlisting>
+
+<section id="FE_GET_PROPERTY">
+<title>FE_GET_PROPERTY</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl call returns one or more frontend properties. This call only
+ requires read-only access to the device.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request = <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>,
+ dtv_properties &#x22C6;props);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int num</para>
+</entry><entry
+ align="char">
+<para>Equals <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link> for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>struct dtv_property *props</para>
+</entry><entry
+ align="char">
+<para>Points to the location where the front-end property commands are stored.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>ERRORS</para>
+<informaltable><tgroup cols="2"><tbody><row>
+  <entry align="char"><para>EINVAL</para></entry>
+  <entry align="char"><para>Invalid parameter(s) received or number of parameters out of the range.</para></entry>
+ </row><row>
+  <entry align="char"><para>ENOMEM</para></entry>
+  <entry align="char"><para>Out of memory.</para></entry>
+ </row><row>
+  <entry align="char"><para>EFAULT</para></entry>
+  <entry align="char"><para>Failure while copying data from/to userspace.</para></entry>
+ </row><row>
+  <entry align="char"><para>EOPNOTSUPP</para></entry>
+  <entry align="char"><para>Property type not supported.</para></entry>
+ </row></tbody></tgroup></informaltable>
+</section>
+
+<section id="FE_SET_PROPERTY">
+<title>FE_SET_PROPERTY</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl call sets one or more frontend properties. This call only
+ requires read-only access to the device.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request = <link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link>,
+ dtv_properties &#x22C6;props);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int num</para>
+</entry><entry
+ align="char">
+<para>Equals <link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link> for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>struct dtv_property *props</para>
+</entry><entry
+ align="char">
+<para>Points to the location where the front-end property commands are stored.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>ERRORS
+</para>
+<informaltable><tgroup cols="2"><tbody><row>
+  <entry align="char"><para>EINVAL</para></entry>
+  <entry align="char"><para>Invalid parameter(s) received or number of parameters out of the range.</para></entry>
+ </row><row>
+  <entry align="char"><para>ENOMEM</para></entry>
+  <entry align="char"><para>Out of memory.</para></entry>
+ </row><row>
+  <entry align="char"><para>EFAULT</para></entry>
+  <entry align="char"><para>Failure while copying data from/to userspace.</para></entry>
+ </row><row>
+  <entry align="char"><para>EOPNOTSUPP</para></entry>
+  <entry align="char"><para>Property type not supported.</para></entry>
+ </row></tbody></tgroup></informaltable>
+</section>
+
+<para>
+On <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>/<link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link>,
+the actual action is determined by the dtv_property cmd/data pairs. With one single ioctl, is possible to
+get/set up to 64 properties. The actual meaning of each property is described on the next sections.
+</para>
+
+<para>The Available frontend property types are:</para>
+<programlisting>
+#define DTV_UNDEFINED		0
+#define DTV_TUNE		1
+#define DTV_CLEAR		2
+#define DTV_FREQUENCY		3
+#define DTV_MODULATION		4
+#define DTV_BANDWIDTH_HZ	5
+#define DTV_INVERSION		6
+#define DTV_DISEQC_MASTER	7
+#define DTV_SYMBOL_RATE		8
+#define DTV_INNER_FEC		9
+#define DTV_VOLTAGE		10
+#define DTV_TONE		11
+#define DTV_PILOT		12
+#define DTV_ROLLOFF		13
+#define DTV_DISEQC_SLAVE_REPLY	14
+#define DTV_FE_CAPABILITY_COUNT	15
+#define DTV_FE_CAPABILITY	16
+#define DTV_DELIVERY_SYSTEM	17
+#define DTV_ISDBT_PARTIAL_RECEPTION	18
+#define DTV_ISDBT_SOUND_BROADCASTING	19
+#define DTV_ISDBT_SB_SUBCHANNEL_ID	20
+#define DTV_ISDBT_SB_SEGMENT_IDX	21
+#define DTV_ISDBT_SB_SEGMENT_COUNT	22
+#define DTV_ISDBT_LAYERA_FEC			23
+#define DTV_ISDBT_LAYERA_MODULATION		24
+#define DTV_ISDBT_LAYERA_SEGMENT_COUNT		25
+#define DTV_ISDBT_LAYERA_TIME_INTERLEAVING	26
+#define DTV_ISDBT_LAYERB_FEC			27
+#define DTV_ISDBT_LAYERB_MODULATION		28
+#define DTV_ISDBT_LAYERB_SEGMENT_COUNT		29
+#define DTV_ISDBT_LAYERB_TIME_INTERLEAVING	30
+#define DTV_ISDBT_LAYERC_FEC			31
+#define DTV_ISDBT_LAYERC_MODULATION		32
+#define DTV_ISDBT_LAYERC_SEGMENT_COUNT		33
+#define DTV_ISDBT_LAYERC_TIME_INTERLEAVING	34
+#define DTV_API_VERSION		35
+#define DTV_CODE_RATE_HP	36
+#define DTV_CODE_RATE_LP	37
+#define DTV_GUARD_INTERVAL	38
+#define DTV_TRANSMISSION_MODE	39
+#define DTV_HIERARCHY		40
+#define DTV_ISDBT_LAYER_ENABLED	41
+#define DTV_ISDBS_TS_ID		42
+</programlisting>
+
+<section id="fe_property_common">
+	<title>Parameters that are common to all Digital TV standards</title>
+	<section id="DTV_FREQUENCY">
+		<title><constant>DTV_FREQUENCY</constant></title>
+
+		<para>Central frequency of the channel, in HZ.</para>
+
+		<para>Notes:</para>
+		<para>1)For ISDB-T, the channels are usually transmitted with an offset of 143kHz.
+			E.g. a valid frequncy could be 474143 kHz. The stepping is bound to the bandwidth of
+			the channel which is 6MHz.</para>
+
+		<para>2)As in ISDB-Tsb the channel consists of only one or three segments the
+			frequency step is 429kHz, 3*429 respectively. As for ISDB-T the
+			central frequency of the channel is expected.</para>
+	</section>
+
+	<section id="DTV_BANDWIDTH_HZ">
+		<title><constant>DTV_BANDWIDTH_HZ</constant></title>
+
+		<para>Bandwidth for the channel, in HZ.</para>
+
+		<para>Possible values:
+			<constant>1712000</constant>,
+			<constant>5000000</constant>,
+			<constant>6000000</constant>,
+			<constant>7000000</constant>,
+			<constant>8000000</constant>,
+			<constant>10000000</constant>.
+		</para>
+
+		<para>Notes:</para>
+
+		<para>1) For ISDB-T it should be always 6000000Hz (6MHz)</para>
+		<para>2) For ISDB-Tsb it can vary depending on the number of connected segments</para>
+		<para>3) Bandwidth doesn't apply for DVB-C transmissions, as the bandwidth
+			 for DVB-C depends on the symbol rate</para>
+		<para>4) Bandwidth in ISDB-T is fixed (6MHz) or can be easily derived from
+			other parameters (DTV_ISDBT_SB_SEGMENT_IDX,
+			DTV_ISDBT_SB_SEGMENT_COUNT).</para>
+		<para>5) DVB-T supports 6, 7 and 8MHz.</para>
+		<para>6) In addition, DVB-T2 supports 1.172, 5 and 10MHz.</para>
+	</section>
+
+	<section id="DTV_DELIVERY_SYSTEM">
+		<title><constant>DTV_DELIVERY_SYSTEM</constant></title>
+
+		<para>Specifies the type of Delivery system</para>
+
+		<para>Possible values: </para>
+<programlisting>
+typedef enum fe_delivery_system {
+	SYS_UNDEFINED,
+	SYS_DVBC_ANNEX_AC,
+	SYS_DVBC_ANNEX_B,
+	SYS_DVBT,
+	SYS_DSS,
+	SYS_DVBS,
+	SYS_DVBS2,
+	SYS_DVBH,
+	SYS_ISDBT,
+	SYS_ISDBS,
+	SYS_ISDBC,
+	SYS_ATSC,
+	SYS_ATSCMH,
+	SYS_DMBTH,
+	SYS_CMMB,
+	SYS_DAB,
+	SYS_DVBT2,
+} fe_delivery_system_t;
+</programlisting>
+
+	</section>
+
+	<section id="DTV_TRANSMISSION_MODE">
+		<title><constant>DTV_TRANSMISSION_MODE</constant></title>
+
+		<para>Specifies the number of carriers used by the standard</para>
+
+		<para>Possible values are:</para>
+<programlisting>
+typedef enum fe_transmit_mode {
+	TRANSMISSION_MODE_2K,
+	TRANSMISSION_MODE_8K,
+	TRANSMISSION_MODE_AUTO,
+	TRANSMISSION_MODE_4K,
+	TRANSMISSION_MODE_1K,
+	TRANSMISSION_MODE_16K,
+	TRANSMISSION_MODE_32K,
+} fe_transmit_mode_t;
+</programlisting>
+
+		<para>Notes:</para>
+		<para>1) ISDB-T supports three carrier/symbol-size: 8K, 4K, 2K. It is called
+			'mode' in the standard: Mode 1 is 2K, mode 2 is 4K, mode 3 is 8K</para>
+
+		<para>2) If <constant>DTV_TRANSMISSION_MODE</constant> is set the <constant>TRANSMISSION_MODE_AUTO</constant> the
+			hardware will try to find the correct FFT-size (if capable) and will
+			use TMCC to fill in the missing parameters.</para>
+		<para>3) DVB-T specifies 2K and 8K as valid sizes.</para>
+		<para>4) DVB-T2 specifies 1K, 2K, 4K, 8K, 16K and 32K.</para>
+	</section>
+
+	<section id="DTV_GUARD_INTERVAL">
+		<title><constant>DTV_GUARD_INTERVAL</constant></title>
+
+		<para>Possible values are:</para>
+<programlisting>
+typedef enum fe_guard_interval {
+	GUARD_INTERVAL_1_32,
+	GUARD_INTERVAL_1_16,
+	GUARD_INTERVAL_1_8,
+	GUARD_INTERVAL_1_4,
+	GUARD_INTERVAL_AUTO,
+	GUARD_INTERVAL_1_128,
+	GUARD_INTERVAL_19_128,
+	GUARD_INTERVAL_19_256,
+} fe_guard_interval_t;
+</programlisting>
+
+		<para>Notes:</para>
+		<para>1) If <constant>DTV_GUARD_INTERVAL</constant> is set the <constant>GUARD_INTERVAL_AUTO</constant> the hardware will
+			try to find the correct guard interval (if capable) and will use TMCC to fill
+			in the missing parameters.</para>
+		<para>2) Intervals 1/128, 19/128 and 19/256 are used only for DVB-T2 at present</para>
+	</section>
+</section>
+
 <section id="isdbt">
 	<title>ISDB-T frontend</title>
 	<para>This section describes shortly what are the possible parameters in the Linux
@@ -32,73 +353,6 @@
 
 	<para>Parameters used by ISDB-T and ISDB-Tsb.</para>
 
-	<section id="isdbt-parms">
-		<title>Parameters that are common with DVB-T and ATSC</title>
-
-		<section id="isdbt-freq">
-			<title><constant>DTV_FREQUENCY</constant></title>
-
-			<para>Central frequency of the channel.</para>
-
-			<para>For ISDB-T the channels are usually transmitted with an offset of 143kHz. E.g. a
-				valid frequncy could be 474143 kHz. The stepping is bound to the bandwidth of
-				the channel which is 6MHz.</para>
-
-			<para>As in ISDB-Tsb the channel consists of only one or three segments the
-				frequency step is 429kHz, 3*429 respectively. As for ISDB-T the
-				central frequency of the channel is expected.</para>
-		</section>
-
-		<section id="isdbt-bw">
-			<title><constant>DTV_BANDWIDTH_HZ</constant> (optional)</title>
-
-			<para>Possible values:</para>
-
-			<para>For ISDB-T it should be always 6000000Hz (6MHz)</para>
-			<para>For ISDB-Tsb it can vary depending on the number of connected segments</para>
-
-			<para>Note: Hardware specific values might be given here, but standard
-				applications should not bother to set a value to this field as
-				standard demods are ignoring it anyway.</para>
-
-			<para>Bandwidth in ISDB-T is fixed (6MHz) or can be easily derived from
-				other parameters (DTV_ISDBT_SB_SEGMENT_IDX,
-				DTV_ISDBT_SB_SEGMENT_COUNT).</para>
-		</section>
-
-		<section id="isdbt-delivery-sys">
-			<title><constant>DTV_DELIVERY_SYSTEM</constant></title>
-
-			<para>Possible values: <constant>SYS_ISDBT</constant></para>
-		</section>
-
-		<section id="isdbt-tx-mode">
-			<title><constant>DTV_TRANSMISSION_MODE</constant></title>
-
-			<para>ISDB-T supports three carrier/symbol-size: 8K, 4K, 2K. It is called
-				'mode' in the standard: Mode 1 is 2K, mode 2 is 4K, mode 3 is 8K</para>
-
-			<para>Possible values: <constant>TRANSMISSION_MODE_2K</constant>, <constant>TRANSMISSION_MODE_8K</constant>,
-				<constant>TRANSMISSION_MODE_AUTO</constant>, <constant>TRANSMISSION_MODE_4K</constant></para>
-
-			<para>If <constant>DTV_TRANSMISSION_MODE</constant> is set the <constant>TRANSMISSION_MODE_AUTO</constant> the
-				hardware will try to find the correct FFT-size (if capable) and will
-				use TMCC to fill in the missing parameters.</para>
-
-			<para><constant>TRANSMISSION_MODE_4K</constant> is added at the same time as the other new parameters.</para>
-		</section>
-
-		<section id="isdbt-guard-interval">
-			<title><constant>DTV_GUARD_INTERVAL</constant></title>
-
-			<para>Possible values: <constant>GUARD_INTERVAL_1_32</constant>, <constant>GUARD_INTERVAL_1_16</constant>, <constant>GUARD_INTERVAL_1_8</constant>,
-				<constant>GUARD_INTERVAL_1_4</constant>, <constant>GUARD_INTERVAL_AUTO</constant></para>
-
-			<para>If <constant>DTV_GUARD_INTERVAL</constant> is set the <constant>GUARD_INTERVAL_AUTO</constant> the hardware will
-				try to find the correct guard interval (if capable) and will use TMCC to fill
-				in the missing parameters.</para>
-		</section>
-	</section>
 	<section id="isdbt-new-parms">
 		<title>ISDB-T only parameters</title>
 
@@ -314,5 +568,20 @@
 			</section>
 		</section>
 	</section>
+	<section id="dvbt2-params">
+		<title>DVB-T2 parameters</title>
+		
+		<para>This section covers parameters that apply only to the DVB-T2 delivery method. DVB-T2
+			support is currently in the early stages development so expect this section to grow
+			and become more detailed with time.</para>
+
+		<section id="dvbt2-plp-id">
+			<title><constant>DTV_DVBT2_PLP_ID</constant></title>
+
+			<para>DVB-T2 supports Physical Layer Pipes (PLP) to allow transmission of
+				many data types via a single multiplex. The API will soon support this
+				at which point this section will be expanded.</para>
+		</section>
+	</section>
 </section>
 </section>

+ 16 - 4
Documentation/DocBook/dvb/frontend.h.xml

@@ -176,14 +176,20 @@ typedef enum fe_transmit_mode {
         TRANSMISSION_MODE_2K,
         TRANSMISSION_MODE_8K,
         TRANSMISSION_MODE_AUTO,
-        TRANSMISSION_MODE_4K
+        TRANSMISSION_MODE_4K,
+        TRANSMISSION_MODE_1K,
+        TRANSMISSION_MODE_16K,
+        TRANSMISSION_MODE_32K,
 } fe_transmit_mode_t;
 
 typedef enum fe_bandwidth {
         BANDWIDTH_8_MHZ,
         BANDWIDTH_7_MHZ,
         BANDWIDTH_6_MHZ,
-        BANDWIDTH_AUTO
+        BANDWIDTH_AUTO,
+        BANDWIDTH_5_MHZ,
+        BANDWIDTH_10_MHZ,
+        BANDWIDTH_1_712_MHZ,
 } fe_bandwidth_t;
 
 
@@ -192,7 +198,10 @@ typedef enum fe_guard_interval {
         GUARD_INTERVAL_1_16,
         GUARD_INTERVAL_1_8,
         GUARD_INTERVAL_1_4,
-        GUARD_INTERVAL_AUTO
+        GUARD_INTERVAL_AUTO,
+        GUARD_INTERVAL_1_128,
+        GUARD_INTERVAL_19_128,
+        GUARD_INTERVAL_19_256,
 } fe_guard_interval_t;
 
 
@@ -306,7 +315,9 @@ struct dvb_frontend_event {
 
 #define DTV_ISDBS_TS_ID         42
 
-#define DTV_MAX_COMMAND                         DTV_ISDBS_TS_ID
+#define DTV_DVBT2_PLP_ID	43
+
+#define DTV_MAX_COMMAND                         DTV_DVBT2_PLP_ID
 
 typedef enum fe_pilot {
         PILOT_ON,
@@ -338,6 +349,7 @@ typedef enum fe_delivery_system {
         SYS_DMBTH,
         SYS_CMMB,
         SYS_DAB,
+        SYS_DVBT2,
 } fe_delivery_system_t;
 
 struct dtv_cmds_h {

+ 2 - 0
Documentation/DocBook/media-entities.tmpl

@@ -270,6 +270,7 @@
 <!ENTITY sub-write SYSTEM "v4l/func-write.xml">
 <!ENTITY sub-io SYSTEM "v4l/io.xml">
 <!ENTITY sub-grey SYSTEM "v4l/pixfmt-grey.xml">
+<!ENTITY sub-m420 SYSTEM "v4l/pixfmt-m420.xml">
 <!ENTITY sub-nv12 SYSTEM "v4l/pixfmt-nv12.xml">
 <!ENTITY sub-nv12m SYSTEM "v4l/pixfmt-nv12m.xml">
 <!ENTITY sub-nv12mt SYSTEM "v4l/pixfmt-nv12mt.xml">
@@ -295,6 +296,7 @@
 <!ENTITY sub-srggb8 SYSTEM "v4l/pixfmt-srggb8.xml">
 <!ENTITY sub-y10 SYSTEM "v4l/pixfmt-y10.xml">
 <!ENTITY sub-y12 SYSTEM "v4l/pixfmt-y12.xml">
+<!ENTITY sub-y10b SYSTEM "v4l/pixfmt-y10b.xml">
 <!ENTITY sub-pixfmt SYSTEM "v4l/pixfmt.xml">
 <!ENTITY sub-cropcap SYSTEM "v4l/vidioc-cropcap.xml">
 <!ENTITY sub-dbg-g-register SYSTEM "v4l/vidioc-dbg-g-register.xml">

+ 147 - 0
Documentation/DocBook/v4l/pixfmt-m420.xml

@@ -0,0 +1,147 @@
+    <refentry id="V4L2-PIX-FMT-M420">
+      <refmeta>
+	<refentrytitle>V4L2_PIX_FMT_M420 ('M420')</refentrytitle>
+	&manvol;
+      </refmeta>
+      <refnamediv>
+	<refname><constant>V4L2_PIX_FMT_M420</constant></refname>
+	<refpurpose>Format with &frac12; horizontal and vertical chroma
+	resolution, also known as YUV 4:2:0. Hybrid plane line-interleaved
+	layout.</refpurpose>
+      </refnamediv>
+      <refsect1>
+	<title>Description</title>
+
+	<para>M420 is a YUV format with &frac12; horizontal and vertical chroma
+	subsampling (YUV 4:2:0). Pixels are organized as interleaved luma and
+	chroma planes. Two lines of luma data are followed by one line of chroma
+	data.</para>
+	<para>The luma plane has one byte per pixel. The chroma plane contains
+	interleaved CbCr pixels subsampled by &frac12; in the horizontal and
+	vertical directions. Each CbCr pair belongs to four pixels. For example,
+Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to
+Y'<subscript>00</subscript>, Y'<subscript>01</subscript>,
+Y'<subscript>10</subscript>, Y'<subscript>11</subscript>.</para>
+
+	<para>All line lengths are identical: if the Y lines include pad bytes
+	so do the CbCr lines.</para>
+
+	<example>
+	  <title><constant>V4L2_PIX_FMT_M420</constant> 4 &times; 4
+pixel image</title>
+
+	  <formalpara>
+	    <title>Byte Order.</title>
+	    <para>Each cell is one byte.
+		<informaltable frame="none">
+		<tgroup cols="5" align="center">
+		  <colspec align="left" colwidth="2*" />
+		  <tbody valign="top">
+		    <row>
+		      <entry>start&nbsp;+&nbsp;0:</entry>
+		      <entry>Y'<subscript>00</subscript></entry>
+		      <entry>Y'<subscript>01</subscript></entry>
+		      <entry>Y'<subscript>02</subscript></entry>
+		      <entry>Y'<subscript>03</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start&nbsp;+&nbsp;4:</entry>
+		      <entry>Y'<subscript>10</subscript></entry>
+		      <entry>Y'<subscript>11</subscript></entry>
+		      <entry>Y'<subscript>12</subscript></entry>
+		      <entry>Y'<subscript>13</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start&nbsp;+&nbsp;8:</entry>
+		      <entry>Cb<subscript>00</subscript></entry>
+		      <entry>Cr<subscript>00</subscript></entry>
+		      <entry>Cb<subscript>01</subscript></entry>
+		      <entry>Cr<subscript>01</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start&nbsp;+&nbsp;16:</entry>
+		      <entry>Y'<subscript>20</subscript></entry>
+		      <entry>Y'<subscript>21</subscript></entry>
+		      <entry>Y'<subscript>22</subscript></entry>
+		      <entry>Y'<subscript>23</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start&nbsp;+&nbsp;20:</entry>
+		      <entry>Y'<subscript>30</subscript></entry>
+		      <entry>Y'<subscript>31</subscript></entry>
+		      <entry>Y'<subscript>32</subscript></entry>
+		      <entry>Y'<subscript>33</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start&nbsp;+&nbsp;24:</entry>
+		      <entry>Cb<subscript>10</subscript></entry>
+		      <entry>Cr<subscript>10</subscript></entry>
+		      <entry>Cb<subscript>11</subscript></entry>
+		      <entry>Cr<subscript>11</subscript></entry>
+		    </row>
+		  </tbody>
+		</tgroup>
+		</informaltable>
+	      </para>
+	  </formalpara>
+
+	  <formalpara>
+	    <title>Color Sample Location.</title>
+	    <para>
+		<informaltable frame="none">
+		<tgroup cols="7" align="center">
+		  <tbody valign="top">
+		    <row>
+		      <entry></entry>
+		      <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
+		      <entry>2</entry><entry></entry><entry>3</entry>
+		    </row>
+		    <row>
+		      <entry>0</entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry>
+		    </row>
+		    <row>
+		      <entry></entry>
+		      <entry></entry><entry>C</entry><entry></entry><entry></entry>
+		      <entry></entry><entry>C</entry><entry></entry>
+		    </row>
+		    <row>
+		      <entry>1</entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry>
+		    </row>
+		    <row>
+		      <entry></entry>
+		    </row>
+		    <row>
+		      <entry>2</entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry>
+		    </row>
+		    <row>
+		      <entry></entry>
+		      <entry></entry><entry>C</entry><entry></entry><entry></entry>
+		      <entry></entry><entry>C</entry><entry></entry>
+		    </row>
+		    <row>
+		      <entry>3</entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry>
+		    </row>
+		  </tbody>
+		</tgroup>
+		</informaltable>
+	      </para>
+	  </formalpara>
+	</example>
+      </refsect1>
+    </refentry>
+
+  <!--
+Local Variables:
+mode: sgml
+sgml-parent-document: "pixfmt.sgml"
+indent-tabs-mode: nil
+End:
+  -->

+ 43 - 0
Documentation/DocBook/v4l/pixfmt-y10b.xml

@@ -0,0 +1,43 @@
+<refentry id="V4L2-PIX-FMT-Y10BPACK">
+  <refmeta>
+    <refentrytitle>V4L2_PIX_FMT_Y10BPACK ('Y10B')</refentrytitle>
+    &manvol;
+  </refmeta>
+  <refnamediv>
+    <refname><constant>V4L2_PIX_FMT_Y10BPACK</constant></refname>
+    <refpurpose>Grey-scale image as a bit-packed array</refpurpose>
+  </refnamediv>
+  <refsect1>
+    <title>Description</title>
+
+    <para>This is a packed grey-scale image format with a depth of 10 bits per
+      pixel. Pixels are stored in a bit-packed array of 10bit bits per pixel,
+      with no padding between them and with the most significant bits coming
+      first from the left.</para>
+
+    <example>
+      <title><constant>V4L2_PIX_FMT_Y10BPACK</constant> 4 pixel data stream taking 5 bytes</title>
+
+      <formalpara>
+	<title>Bit-packed representation</title>
+	<para>pixels cross the byte boundary and have a ratio of 5 bytes for each 4
+          pixels.
+	  <informaltable frame="all">
+	    <tgroup cols="5" align="center">
+	      <colspec align="left" colwidth="2*" />
+	      <tbody valign="top">
+		<row>
+		  <entry>Y'<subscript>00[9:2]</subscript></entry>
+		  <entry>Y'<subscript>00[1:0]</subscript>Y'<subscript>01[9:4]</subscript></entry>
+		  <entry>Y'<subscript>01[3:0]</subscript>Y'<subscript>02[9:6]</subscript></entry>
+		  <entry>Y'<subscript>02[5:0]</subscript>Y'<subscript>03[9:8]</subscript></entry>
+		  <entry>Y'<subscript>03[7:0]</subscript></entry>
+		</row>
+	      </tbody>
+	    </tgroup>
+	  </informaltable>
+	</para>
+      </formalpara>
+    </example>
+  </refsect1>
+</refentry>

+ 2 - 0
Documentation/DocBook/v4l/pixfmt.xml

@@ -697,6 +697,7 @@ information.</para>
     &sub-grey;
     &sub-y10;
     &sub-y12;
+    &sub-y10b;
     &sub-y16;
     &sub-yuyv;
     &sub-uyvy;
@@ -712,6 +713,7 @@ information.</para>
     &sub-nv12m;
     &sub-nv12mt;
     &sub-nv16;
+    &sub-m420;
   </section>
 
   <section>

+ 46 - 0
Documentation/DocBook/v4l/subdev-formats.xml

@@ -2522,5 +2522,51 @@
 	</tgroup>
       </table>
     </section>
+
+    <section>
+      <title>JPEG Compressed Formats</title>
+
+      <para>Those data formats consist of an ordered sequence of 8-bit bytes
+	obtained from JPEG compression process. Additionally to the
+	<constant>_JPEG</constant> prefix the format code is made of
+	the following information.
+	<itemizedlist>
+	  <listitem>The number of bus samples per entropy encoded byte.</listitem>
+	  <listitem>The bus width.</listitem>
+	</itemizedlist>
+
+	<para>For instance, for a JPEG baseline process and an 8-bit bus width
+	  the format will be named <constant>V4L2_MBUS_FMT_JPEG_1X8</constant>.
+	</para>
+      </para>
+
+      <para>The following table lists existing JPEG compressed formats.</para>
+
+      <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-jpeg">
+	<title>JPEG Formats</title>
+	<tgroup cols="3">
+	  <colspec colname="id" align="left" />
+	  <colspec colname="code" align="left"/>
+	  <colspec colname="remarks" align="left"/>
+	  <thead>
+	    <row>
+	      <entry>Identifier</entry>
+	      <entry>Code</entry>
+	      <entry>Remarks</entry>
+	    </row>
+	  </thead>
+	  <tbody valign="top">
+	    <row id="V4L2-MBUS-FMT-JPEG-1X8">
+	      <entry>V4L2_MBUS_FMT_JPEG_1X8</entry>
+	      <entry>0x4001</entry>
+	      <entry>Besides of its usage for the parallel bus this format is
+		recommended for transmission of JPEG data over MIPI CSI bus
+		using the User Defined 8-bit Data types.
+	      </entry>
+	    </row>
+	  </tbody>
+	</tgroup>
+      </table>
+    </section>
   </section>
 </section>

+ 4 - 0
Documentation/DocBook/v4l/videodev2.h.xml

@@ -311,6 +311,9 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
 #define <link linkend="V4L2-PIX-FMT-Y10">V4L2_PIX_FMT_Y10</link>     v4l2_fourcc('Y', '1', '0', ' ') /* 10  Greyscale     */
 #define <link linkend="V4L2-PIX-FMT-Y16">V4L2_PIX_FMT_Y16</link>     v4l2_fourcc('Y', '1', '6', ' ') /* 16  Greyscale     */
 
+/* Grey bit-packed formats */
+#define <link linkend="V4L2-PIX-FMT-Y10BPACK">V4L2_PIX_FMT_Y10BPACK</link>    v4l2_fourcc('Y', '1', '0', 'B') /* 10  Greyscale bit-packed */
+
 /* Palette formats */
 #define <link linkend="V4L2-PIX-FMT-PAL8">V4L2_PIX_FMT_PAL8</link>    v4l2_fourcc('P', 'A', 'L', '8') /*  8  8-bit palette */
 
@@ -333,6 +336,7 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
 #define <link linkend="V4L2-PIX-FMT-YUV420">V4L2_PIX_FMT_YUV420</link>  v4l2_fourcc('Y', 'U', '1', '2') /* 12  YUV 4:2:0     */
 #define <link linkend="V4L2-PIX-FMT-HI240">V4L2_PIX_FMT_HI240</link>   v4l2_fourcc('H', 'I', '2', '4') /*  8  8-bit color   */
 #define <link linkend="V4L2-PIX-FMT-HM12">V4L2_PIX_FMT_HM12</link>    v4l2_fourcc('H', 'M', '1', '2') /*  8  YUV 4:2:0 16x16 macroblocks */
+#define <link linkend="V4L2-PIX-FMT-M420">V4L2_PIX_FMT_M420</link>    v4l2_fourcc('M', '4', '2', '0') /* 12  YUV 4:2:0 2 lines y, 1 line uv interleaved */
 
 /* two planes -- one Y, one Cr + Cb interleaved  */
 #define <link linkend="V4L2-PIX-FMT-NV12">V4L2_PIX_FMT_NV12</link>    v4l2_fourcc('N', 'V', '1', '2') /* 12  Y/CbCr 4:2:0  */

+ 23 - 0
Documentation/feature-removal-schedule.txt

@@ -551,3 +551,26 @@ Why:	These legacy callbacks should no longer be used as i2c-core offers
 Who:	Jean Delvare <khali@linux-fr.org>
 
 ----------------------------
+
+What:	Support for UVCIOC_CTRL_ADD in the uvcvideo driver
+When:	2.6.42
+Why:	The information passed to the driver by this ioctl is now queried
+	dynamically from the device.
+Who:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+----------------------------
+
+What:	Support for UVCIOC_CTRL_MAP_OLD in the uvcvideo driver
+When:	2.6.42
+Why:	Used only by applications compiled against older driver versions.
+	Superseded by UVCIOC_CTRL_MAP which supports V4L2 menu controls.
+Who:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+----------------------------
+
+What:	Support for UVCIOC_CTRL_GET and UVCIOC_CTRL_SET in the uvcvideo driver
+When:	2.6.42
+Why:	Superseded by the UVCIOC_CTRL_QUERY ioctl.
+Who:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+----------------------------

+ 1 - 1
Documentation/ioctl/ioctl-number.txt

@@ -166,7 +166,6 @@ Code  Seq#(hex)	Include File		Comments
 'T'	all	arch/x86/include/asm/ioctls.h	conflict!
 'T'	C0-DF	linux/if_tun.h		conflict!
 'U'	all	sound/asound.h		conflict!
-'U'	00-0F	drivers/media/video/uvc/uvcvideo.h	conflict!
 'U'	00-CF	linux/uinput.h		conflict!
 'U'	00-EF	linux/usbdevice_fs.h
 'U'	C0-CF	drivers/bluetooth/hci_uart.h
@@ -259,6 +258,7 @@ Code  Seq#(hex)	Include File		Comments
 't'	80-8F	linux/isdn_ppp.h
 't'	90	linux/toshiba.h
 'u'	00-1F	linux/smb_fs.h		gone
+'u'	20-3F	linux/uvcvideo.h	USB video class host driver
 'v'	00-1F	linux/ext2_fs.h		conflict!
 'v'	00-1F	linux/fs.h		conflict!
 'v'	00-0F	linux/sonypi.h		conflict!

+ 1 - 1
Documentation/video4linux/CARDLIST.em28xx

@@ -54,7 +54,7 @@
  53 -> Pinnacle Hybrid Pro                      (em2881)
  54 -> Kworld VS-DVB-T 323UR                    (em2882)        [eb1a:e323]
  55 -> Terratec Cinnergy Hybrid T USB XS (em2882) (em2882)        [0ccd:005e,0ccd:0042]
- 56 -> Pinnacle Hybrid Pro (2)                  (em2882)        [2304:0226]
+ 56 -> Pinnacle Hybrid Pro (330e)               (em2882)        [2304:0226]
  57 -> Kworld PlusTV HD Hybrid 330              (em2883)        [eb1a:a316]
  58 -> Compro VideoMate ForYou/Stereo           (em2820/em2840) [185b:2041]
  60 -> Hauppauge WinTV HVR 850                  (em2883)        [2040:651f]

+ 0 - 1
Documentation/video4linux/Zoran

@@ -130,7 +130,6 @@ Card number: 4
 
 Note: No module for the mse3000 is available yet
 Note: No module for the vpx3224 is available yet
-Note: use encoder=X or decoder=X for non-default i2c chips
 
 ===========================
 

+ 1 - 0
Documentation/video4linux/gspca.txt

@@ -275,6 +275,7 @@ pac7302		093a:2629	Genious iSlim 300
 pac7302		093a:262a	Webcam 300k
 pac7302		093a:262c	Philips SPC 230 NC
 jeilinj		0979:0280	Sakar 57379
+jeilinj		0979:0280	Sportscam DV15
 zc3xx		0ac8:0302	Z-star Vimicro zc0302
 vc032x		0ac8:0321	Vimicro generic vc0321
 vc032x		0ac8:0323	Vimicro Vc0323

+ 239 - 0
Documentation/video4linux/uvcvideo.txt

@@ -0,0 +1,239 @@
+Linux USB Video Class (UVC) driver
+==================================
+
+This file documents some driver-specific aspects of the UVC driver, such as
+driver-specific ioctls and implementation notes.
+
+Questions and remarks can be sent to the Linux UVC development mailing list at
+linux-uvc-devel@lists.berlios.de.
+
+
+Extension Unit (XU) support
+---------------------------
+
+1. Introduction
+
+The UVC specification allows for vendor-specific extensions through extension
+units (XUs). The Linux UVC driver supports extension unit controls (XU controls)
+through two separate mechanisms:
+
+  - through mappings of XU controls to V4L2 controls
+  - through a driver-specific ioctl interface
+
+The first one allows generic V4L2 applications to use XU controls by mapping
+certain XU controls onto V4L2 controls, which then show up during ordinary
+control enumeration.
+
+The second mechanism requires uvcvideo-specific knowledge for the application to
+access XU controls but exposes the entire UVC XU concept to user space for
+maximum flexibility.
+
+Both mechanisms complement each other and are described in more detail below.
+
+
+2. Control mappings
+
+The UVC driver provides an API for user space applications to define so-called
+control mappings at runtime. These allow for individual XU controls or byte
+ranges thereof to be mapped to new V4L2 controls. Such controls appear and
+function exactly like normal V4L2 controls (i.e. the stock controls, such as
+brightness, contrast, etc.). However, reading or writing of such a V4L2 controls
+triggers a read or write of the associated XU control.
+
+The ioctl used to create these control mappings is called UVCIOC_CTRL_MAP.
+Previous driver versions (before 0.2.0) required another ioctl to be used
+beforehand (UVCIOC_CTRL_ADD) to pass XU control information to the UVC driver.
+This is no longer necessary as newer uvcvideo versions query the information
+directly from the device.
+
+For details on the UVCIOC_CTRL_MAP ioctl please refer to the section titled
+"IOCTL reference" below.
+
+
+3. Driver specific XU control interface
+
+For applications that need to access XU controls directly, e.g. for testing
+purposes, firmware upload, or accessing binary controls, a second mechanism to
+access XU controls is provided in the form of a driver-specific ioctl, namely
+UVCIOC_CTRL_QUERY.
+
+A call to this ioctl allows applications to send queries to the UVC driver that
+directly map to the low-level UVC control requests.
+
+In order to make such a request the UVC unit ID of the control's extension unit
+and the control selector need to be known. This information either needs to be
+hardcoded in the application or queried using other ways such as by parsing the
+UVC descriptor or, if available, using the media controller API to enumerate a
+device's entities.
+
+Unless the control size is already known it is necessary to first make a
+UVC_GET_LEN requests in order to be able to allocate a sufficiently large buffer
+and set the buffer size to the correct value. Similarly, to find out whether
+UVC_GET_CUR or UVC_SET_CUR are valid requests for a given control, a
+UVC_GET_INFO request should be made. The bits 0 (GET supported) and 1 (SET
+supported) of the resulting byte indicate which requests are valid.
+
+With the addition of the UVCIOC_CTRL_QUERY ioctl the UVCIOC_CTRL_GET and
+UVCIOC_CTRL_SET ioctls have become obsolete since their functionality is a
+subset of the former ioctl. For the time being they are still supported but
+application developers are encouraged to use UVCIOC_CTRL_QUERY instead.
+
+For details on the UVCIOC_CTRL_QUERY ioctl please refer to the section titled
+"IOCTL reference" below.
+
+
+4. Security
+
+The API doesn't currently provide a fine-grained access control facility. The
+UVCIOC_CTRL_ADD and UVCIOC_CTRL_MAP ioctls require super user permissions.
+
+Suggestions on how to improve this are welcome.
+
+
+5. Debugging
+
+In order to debug problems related to XU controls or controls in general it is
+recommended to enable the UVC_TRACE_CONTROL bit in the module parameter 'trace'.
+This causes extra output to be written into the system log.
+
+
+6. IOCTL reference
+
+---- UVCIOC_CTRL_MAP - Map a UVC control to a V4L2 control ----
+
+Argument: struct uvc_xu_control_mapping
+
+Description:
+	This ioctl creates a mapping between a UVC control or part of a UVC
+	control and a V4L2 control. Once mappings are defined, userspace
+	applications can access vendor-defined UVC control through the V4L2
+	control API.
+
+	To create a mapping, applications fill the uvc_xu_control_mapping
+	structure with information about an existing UVC control defined with
+	UVCIOC_CTRL_ADD and a new V4L2 control.
+
+	A UVC control can be mapped to several V4L2 controls. For instance,
+	a UVC pan/tilt control could be mapped to separate pan and tilt V4L2
+	controls. The UVC control is divided into non overlapping fields using
+	the 'size' and 'offset' fields and are then independantly mapped to
+	V4L2 control.
+
+	For signed integer V4L2 controls the data_type field should be set to
+	UVC_CTRL_DATA_TYPE_SIGNED. Other values are currently ignored.
+
+Return value:
+	On success 0 is returned. On error -1 is returned and errno is set
+	appropriately.
+
+	ENOMEM
+		Not enough memory to perform the operation.
+	EPERM
+		Insufficient privileges (super user privileges are required).
+	EINVAL
+		No such UVC control.
+	EOVERFLOW
+		The requested offset and size would overflow the UVC control.
+	EEXIST
+		Mapping already exists.
+
+Data types:
+	* struct uvc_xu_control_mapping
+
+	__u32	id		V4L2 control identifier
+	__u8	name[32]	V4L2 control name
+	__u8	entity[16]	UVC extension unit GUID
+	__u8	selector	UVC control selector
+	__u8	size		V4L2 control size (in bits)
+	__u8	offset		V4L2 control offset (in bits)
+	enum v4l2_ctrl_type
+		v4l2_type	V4L2 control type
+	enum uvc_control_data_type
+		data_type	UVC control data type
+	struct uvc_menu_info
+		*menu_info	Array of menu entries (for menu controls only)
+	__u32	menu_count	Number of menu entries (for menu controls only)
+
+	* struct uvc_menu_info
+
+	__u32	value		Menu entry value used by the device
+	__u8	name[32]	Menu entry name
+
+
+	* enum uvc_control_data_type
+
+	UVC_CTRL_DATA_TYPE_RAW		Raw control (byte array)
+	UVC_CTRL_DATA_TYPE_SIGNED	Signed integer
+	UVC_CTRL_DATA_TYPE_UNSIGNED	Unsigned integer
+	UVC_CTRL_DATA_TYPE_BOOLEAN	Boolean
+	UVC_CTRL_DATA_TYPE_ENUM		Enumeration
+	UVC_CTRL_DATA_TYPE_BITMASK	Bitmask
+
+
+---- UVCIOC_CTRL_QUERY - Query a UVC XU control ----
+
+Argument: struct uvc_xu_control_query
+
+Description:
+	This ioctl queries a UVC XU control identified by its extension unit ID
+	and control selector.
+
+	There are a number of different queries available that closely
+	correspond to the low-level control requests described in the UVC
+	specification. These requests are:
+
+	UVC_GET_CUR
+		Obtain the current value of the control.
+	UVC_GET_MIN
+		Obtain the minimum value of the control.
+	UVC_GET_MAX
+		Obtain the maximum value of the control.
+	UVC_GET_DEF
+		Obtain the default value of the control.
+	UVC_GET_RES
+		Query the resolution of the control, i.e. the step size of the
+		allowed control values.
+	UVC_GET_LEN
+		Query the size of the control in bytes.
+	UVC_GET_INFO
+		Query the control information bitmap, which indicates whether
+		get/set requests are supported.
+	UVC_SET_CUR
+		Update the value of the control.
+
+	Applications must set the 'size' field to the correct length for the
+	control. Exceptions are the UVC_GET_LEN and UVC_GET_INFO queries, for
+	which the size must be set to 2 and 1, respectively. The 'data' field
+	must point to a valid writable buffer big enough to hold the indicated
+	number of data bytes.
+
+	Data is copied directly from the device without any driver-side
+	processing. Applications are responsible for data buffer formatting,
+	including little-endian/big-endian conversion. This is particularly
+	important for the result of the UVC_GET_LEN requests, which is always
+	returned as a little-endian 16-bit integer by the device.
+
+Return value:
+	On success 0 is returned. On error -1 is returned and errno is set
+	appropriately.
+
+	ENOENT
+		The device does not support the given control or the specified
+		extension unit could not be found.
+	ENOBUFS
+		The specified buffer size is incorrect (too big or too small).
+	EINVAL
+		An invalid request code was passed.
+	EBADRQC
+		The given request is not supported by the given control.
+	EFAULT
+		The data pointer references an inaccessible memory area.
+
+Data types:
+	* struct uvc_xu_control_query
+
+	__u8	unit		Extension unit ID
+	__u8	selector	Control selector
+	__u8	query		Request code to send to the device
+	__u16	size		Control data size (in bytes)
+	__u8	*data		Control value

+ 1 - 6
drivers/media/common/saa7146_core.c

@@ -378,12 +378,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
 	dev->pci = pci;
 
 	/* get chip-revision; this is needed to enable bug-fixes */
-	err = pci_read_config_dword(pci, PCI_CLASS_REVISION, &dev->revision);
-	if (err < 0) {
-		ERR(("pci_read_config_dword() failed.\n"));
-		goto err_disable;
-	}
-	dev->revision &= 0xf;
+	dev->revision = pci->revision;
 
 	/* remap the memory from virtual to physical address */
 

+ 8 - 0
drivers/media/common/tuners/Kconfig

@@ -186,4 +186,12 @@ config MEDIA_TUNER_TDA18218
 	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  NXP TDA18218 silicon tuner driver.
+
+config MEDIA_TUNER_TDA18212
+	tristate "NXP TDA18212 silicon tuner"
+	depends on VIDEO_MEDIA && I2C
+	default m if MEDIA_TUNER_CUSTOMISE
+	help
+	  NXP TDA18212 silicon tuner driver.
+
 endmenu

+ 1 - 0
drivers/media/common/tuners/Makefile

@@ -25,6 +25,7 @@ obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o
 obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o
 obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o
 obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o
+obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends

+ 2 - 0
drivers/media/common/tuners/mxl5005s.c

@@ -4024,6 +4024,8 @@ static int mxl5005s_set_params(struct dvb_frontend *fe,
 			case BANDWIDTH_8_MHZ:
 				req_bw  = MXL5005S_BANDWIDTH_8MHZ;
 				break;
+			default:
+				return -EINVAL;
 			}
 		}
 

+ 265 - 0
drivers/media/common/tuners/tda18212.c

@@ -0,0 +1,265 @@
+/*
+ * NXP TDA18212HN silicon tuner driver
+ *
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "tda18212_priv.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+/* write multiple registers */
+static int tda18212_wr_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
+	int len)
+{
+	int ret;
+	u8 buf[len+1];
+	struct i2c_msg msg[1] = {
+		{
+			.addr = priv->cfg->i2c_address,
+			.flags = 0,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	buf[0] = reg;
+	memcpy(&buf[1], val, len);
+
+	ret = i2c_transfer(priv->i2c, msg, 1);
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* read multiple registers */
+static int tda18212_rd_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
+	int len)
+{
+	int ret;
+	u8 buf[len];
+	struct i2c_msg msg[2] = {
+		{
+			.addr = priv->cfg->i2c_address,
+			.flags = 0,
+			.len = 1,
+			.buf = &reg,
+		}, {
+			.addr = priv->cfg->i2c_address,
+			.flags = I2C_M_RD,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	ret = i2c_transfer(priv->i2c, msg, 2);
+	if (ret == 2) {
+		memcpy(val, buf, len);
+		ret = 0;
+	} else {
+		warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+
+	return ret;
+}
+
+/* write single register */
+static int tda18212_wr_reg(struct tda18212_priv *priv, u8 reg, u8 val)
+{
+	return tda18212_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register */
+static int tda18212_rd_reg(struct tda18212_priv *priv, u8 reg, u8 *val)
+{
+	return tda18212_rd_regs(priv, reg, val, 1);
+}
+
+#if 0 /* keep, useful when developing driver */
+static void tda18212_dump_regs(struct tda18212_priv *priv)
+{
+	int i;
+	u8 buf[256];
+
+	#define TDA18212_RD_LEN 32
+	for (i = 0; i < sizeof(buf); i += TDA18212_RD_LEN)
+		tda18212_rd_regs(priv, i, &buf[i], TDA18212_RD_LEN);
+
+	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 32, 1, buf,
+		sizeof(buf), true);
+
+	return;
+}
+#endif
+
+static int tda18212_set_params(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
+{
+	struct tda18212_priv *priv = fe->tuner_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i;
+	u32 if_khz;
+	u8 buf[9];
+	static const u8 bw_params[][3] = {
+		/*  0f    13    23 */
+		{ 0xb3, 0x20, 0x03 }, /* DVB-T 6 MHz */
+		{ 0xb3, 0x31, 0x01 }, /* DVB-T 7 MHz */
+		{ 0xb3, 0x22, 0x01 }, /* DVB-T 8 MHz */
+		{ 0x92, 0x53, 0x03 }, /* DVB-C */
+	};
+
+	dbg("%s: delsys=%d RF=%d BW=%d", __func__,
+		c->delivery_system, c->frequency, c->bandwidth_hz);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
+
+	switch (c->delivery_system) {
+	case SYS_DVBT:
+		switch (c->bandwidth_hz) {
+		case 6000000:
+			if_khz = priv->cfg->if_dvbt_6;
+			i = 0;
+			break;
+		case 7000000:
+			if_khz = priv->cfg->if_dvbt_7;
+			i = 1;
+			break;
+		case 8000000:
+			if_khz = priv->cfg->if_dvbt_8;
+			i = 2;
+			break;
+		default:
+			ret = -EINVAL;
+			goto error;
+		}
+		break;
+	case SYS_DVBC_ANNEX_AC:
+		if_khz = priv->cfg->if_dvbc;
+		i = 3;
+		break;
+	default:
+		ret = -EINVAL;
+		goto error;
+	}
+
+	ret = tda18212_wr_reg(priv, 0x23, bw_params[i][2]);
+	if (ret)
+		goto error;
+
+	ret = tda18212_wr_reg(priv, 0x06, 0x00);
+	if (ret)
+		goto error;
+
+	ret = tda18212_wr_reg(priv, 0x0f, bw_params[i][0]);
+	if (ret)
+		goto error;
+
+	buf[0] = 0x02;
+	buf[1] = bw_params[i][1];
+	buf[2] = 0x03; /* default value */
+	buf[3] = if_khz / 50;
+	buf[4] = ((c->frequency / 1000) >> 16) & 0xff;
+	buf[5] = ((c->frequency / 1000) >>  8) & 0xff;
+	buf[6] = ((c->frequency / 1000) >>  0) & 0xff;
+	buf[7] = 0xc1;
+	buf[8] = 0x01;
+	ret = tda18212_wr_regs(priv, 0x12, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+exit:
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
+
+	return ret;
+
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	goto exit;
+}
+
+static int tda18212_release(struct dvb_frontend *fe)
+{
+	kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+static const struct dvb_tuner_ops tda18212_tuner_ops = {
+	.info = {
+		.name           = "NXP TDA18212",
+
+		.frequency_min  =  48000000,
+		.frequency_max  = 864000000,
+		.frequency_step =      1000,
+	},
+
+	.release       = tda18212_release,
+
+	.set_params    = tda18212_set_params,
+};
+
+struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, struct tda18212_config *cfg)
+{
+	struct tda18212_priv *priv = NULL;
+	int ret;
+	u8 val;
+
+	priv = kzalloc(sizeof(struct tda18212_priv), GFP_KERNEL);
+	if (priv == NULL)
+		return NULL;
+
+	priv->cfg = cfg;
+	priv->i2c = i2c;
+	fe->tuner_priv = priv;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
+
+	/* check if the tuner is there */
+	ret = tda18212_rd_reg(priv, 0x00, &val);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
+
+	dbg("%s: ret:%d chip ID:%02x", __func__, ret, val);
+	if (ret || val != 0xc7) {
+		kfree(priv);
+		return NULL;
+	}
+
+	info("NXP TDA18212HN successfully identified.");
+
+	memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops,
+		sizeof(struct dvb_tuner_ops));
+
+	return fe;
+}
+EXPORT_SYMBOL(tda18212_attach);
+
+MODULE_DESCRIPTION("NXP TDA18212HN silicon tuner driver");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_LICENSE("GPL");

+ 48 - 0
drivers/media/common/tuners/tda18212.h

@@ -0,0 +1,48 @@
+/*
+ * NXP TDA18212HN silicon tuner driver
+ *
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef TDA18212_H
+#define TDA18212_H
+
+#include "dvb_frontend.h"
+
+struct tda18212_config {
+	u8 i2c_address;
+
+	u16 if_dvbt_6;
+	u16 if_dvbt_7;
+	u16 if_dvbt_8;
+	u16 if_dvbc;
+};
+
+#if defined(CONFIG_MEDIA_TUNER_TDA18212) || \
+	(defined(CONFIG_MEDIA_TUNER_TDA18212_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, struct tda18212_config *cfg);
+#else
+static inline struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, struct tda18212_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif

+ 44 - 0
drivers/media/common/tuners/tda18212_priv.h

@@ -0,0 +1,44 @@
+/*
+ * NXP TDA18212HN silicon tuner driver
+ *
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef TDA18212_PRIV_H
+#define TDA18212_PRIV_H
+
+#include "tda18212.h"
+
+#define LOG_PREFIX "tda18212"
+
+#undef dbg
+#define dbg(f, arg...) \
+	if (debug) \
+		printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
+#undef err
+#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
+#undef info
+#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
+#undef warn
+#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
+
+struct tda18212_priv {
+	struct tda18212_config *cfg;
+	struct i2c_adapter *i2c;
+};
+
+#endif

+ 4 - 0
drivers/media/common/tuners/tda18271-fe.c

@@ -976,6 +976,10 @@ static int tda18271_set_params(struct dvb_frontend *fe,
 			tda_warn("bandwidth not set!\n");
 			return -EINVAL;
 		}
+	} else if (fe->ops.info.type == FE_QAM) {
+		/* DVB-C */
+		map = &std_map->qam_8;
+		bw = 8000000;
 	} else {
 		tda_warn("modulation type not supported!\n");
 		return -EINVAL;

+ 26 - 6
drivers/media/common/tuners/xc5000.c

@@ -628,6 +628,15 @@ static void xc_debug_dump(struct xc5000_priv *priv)
 	dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
 }
 
+/*
+ * As defined on EN 300 429, the DVB-C roll-off factor is 0.15.
+ * So, the amount of the needed bandwith is given by:
+ * 	Bw = Symbol_rate * (1 + 0.15)
+ * As such, the maximum symbol rate supported by 6 MHz is given by:
+ *	max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
+ */
+#define MAX_SYMBOL_RATE_6MHz	5217391
+
 static int xc5000_set_params(struct dvb_frontend *fe,
 	struct dvb_frontend_parameters *params)
 {
@@ -688,21 +697,32 @@ static int xc5000_set_params(struct dvb_frontend *fe,
 		}
 		priv->rf_mode = XC_RF_MODE_AIR;
 	} else if (fe->ops.info.type == FE_QAM) {
-		dprintk(1, "%s() QAM\n", __func__);
 		switch (params->u.qam.modulation) {
+		case QAM_256:
+		case QAM_AUTO:
 		case QAM_16:
 		case QAM_32:
 		case QAM_64:
 		case QAM_128:
-		case QAM_256:
-		case QAM_AUTO:
 			dprintk(1, "%s() QAM modulation\n", __func__);
-			priv->bandwidth = BANDWIDTH_8_MHZ;
-			priv->video_standard = DTV7_8;
-			priv->freq_hz = params->frequency - 2750000;
 			priv->rf_mode = XC_RF_MODE_CABLE;
+			/*
+			 * Using a 8MHz bandwidth sometimes fail
+			 * with 6MHz-spaced channels, due to inter-carrier
+			 * interference. So, use DTV6 firmware
+			 */
+			if (params->u.qam.symbol_rate <= MAX_SYMBOL_RATE_6MHz) {
+				priv->bandwidth = BANDWIDTH_6_MHZ;
+				priv->video_standard = DTV6;
+				priv->freq_hz = params->frequency - 1750000;
+			} else {
+				priv->bandwidth = BANDWIDTH_8_MHZ;
+				priv->video_standard = DTV7_8;
+				priv->freq_hz = params->frequency - 2750000;
+			}
 			break;
 		default:
+			dprintk(1, "%s() Unsupported QAM type\n", __func__);
 			return -EINVAL;
 		}
 	} else {

+ 1 - 3
drivers/media/dvb/b2c2/flexcop-pci.c

@@ -290,10 +290,8 @@ static void flexcop_pci_dma_exit(struct flexcop_pci *fc_pci)
 static int flexcop_pci_init(struct flexcop_pci *fc_pci)
 {
 	int ret;
-	u8 card_rev;
 
-	pci_read_config_byte(fc_pci->pdev, PCI_CLASS_REVISION, &card_rev);
-	info("card revision %x", card_rev);
+	info("card revision %x", fc_pci->pdev->revision);
 
 	if ((ret = pci_enable_device(fc_pci->pdev)) != 0)
 		return ret;

+ 1 - 1
drivers/media/dvb/bt8xx/bt878.c

@@ -460,7 +460,7 @@ static int __devinit bt878_probe(struct pci_dev *dev,
 		goto fail0;
 	}
 
-	pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision);
+	bt->revision = dev->revision;
 	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
 
 

+ 57 - 60
drivers/media/dvb/dvb-core/dvb_demux.c

@@ -478,97 +478,94 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
 
 EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
 
-void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
+static inline int find_next_packet(const u8 *buf, int pos, size_t count,
+				   const int pktsize)
 {
-	int p = 0, i, j;
+	int start = pos, lost;
 
-	spin_lock(&demux->lock);
-
-	if (demux->tsbufp) {
-		i = demux->tsbufp;
-		j = 188 - i;
-		if (count < j) {
-			memcpy(&demux->tsbuf[i], buf, count);
-			demux->tsbufp += count;
-			goto bailout;
-		}
-		memcpy(&demux->tsbuf[i], buf, j);
-		if (demux->tsbuf[0] == 0x47)
-			dvb_dmx_swfilter_packet(demux, demux->tsbuf);
-		demux->tsbufp = 0;
-		p += j;
+	while (pos < count) {
+		if (buf[pos] == 0x47 ||
+		    (pktsize == 204 && buf[pos] == 0xB8))
+			break;
+		pos++;
 	}
 
-	while (p < count) {
-		if (buf[p] == 0x47) {
-			if (count - p >= 188) {
-				dvb_dmx_swfilter_packet(demux, &buf[p]);
-				p += 188;
-			} else {
-				i = count - p;
-				memcpy(demux->tsbuf, &buf[p], i);
-				demux->tsbufp = i;
-				goto bailout;
-			}
-		} else
-			p++;
+	lost = pos - start;
+	if (lost) {
+		/* This garbage is part of a valid packet? */
+		int backtrack = pos - pktsize;
+		if (backtrack >= 0 && (buf[backtrack] == 0x47 ||
+		    (pktsize == 204 && buf[backtrack] == 0xB8)))
+			return backtrack;
 	}
 
-bailout:
-	spin_unlock(&demux->lock);
+	return pos;
 }
 
-EXPORT_SYMBOL(dvb_dmx_swfilter);
-
-void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
+/* Filter all pktsize= 188 or 204 sized packets and skip garbage. */
+static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf,
+		size_t count, const int pktsize)
 {
 	int p = 0, i, j;
-	u8 tmppack[188];
+	const u8 *q;
 
 	spin_lock(&demux->lock);
 
-	if (demux->tsbufp) {
+	if (demux->tsbufp) { /* tsbuf[0] is now 0x47. */
 		i = demux->tsbufp;
-		j = 204 - i;
+		j = pktsize - i;
 		if (count < j) {
 			memcpy(&demux->tsbuf[i], buf, count);
 			demux->tsbufp += count;
 			goto bailout;
 		}
 		memcpy(&demux->tsbuf[i], buf, j);
-		if ((demux->tsbuf[0] == 0x47) || (demux->tsbuf[0] == 0xB8)) {
-			memcpy(tmppack, demux->tsbuf, 188);
-			if (tmppack[0] == 0xB8)
-				tmppack[0] = 0x47;
-			dvb_dmx_swfilter_packet(demux, tmppack);
-		}
+		if (demux->tsbuf[0] == 0x47) /* double check */
+			dvb_dmx_swfilter_packet(demux, demux->tsbuf);
 		demux->tsbufp = 0;
 		p += j;
 	}
 
-	while (p < count) {
-		if ((buf[p] == 0x47) || (buf[p] == 0xB8)) {
-			if (count - p >= 204) {
-				memcpy(tmppack, &buf[p], 188);
-				if (tmppack[0] == 0xB8)
-					tmppack[0] = 0x47;
-				dvb_dmx_swfilter_packet(demux, tmppack);
-				p += 204;
-			} else {
-				i = count - p;
-				memcpy(demux->tsbuf, &buf[p], i);
-				demux->tsbufp = i;
-				goto bailout;
-			}
-		} else {
-			p++;
+	while (1) {
+		p = find_next_packet(buf, p, count, pktsize);
+		if (p >= count)
+			break;
+		if (count - p < pktsize)
+			break;
+
+		q = &buf[p];
+
+		if (pktsize == 204 && (*q == 0xB8)) {
+			memcpy(demux->tsbuf, q, 188);
+			demux->tsbuf[0] = 0x47;
+			q = demux->tsbuf;
 		}
+		dvb_dmx_swfilter_packet(demux, q);
+		p += pktsize;
+	}
+
+	i = count - p;
+	if (i) {
+		memcpy(demux->tsbuf, &buf[p], i);
+		demux->tsbufp = i;
+		if (pktsize == 204 && demux->tsbuf[0] == 0xB8)
+			demux->tsbuf[0] = 0x47;
 	}
 
 bailout:
 	spin_unlock(&demux->lock);
 }
 
+void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
+{
+	_dvb_dmx_swfilter(demux, buf, count, 188);
+}
+EXPORT_SYMBOL(dvb_dmx_swfilter);
+
+void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
+{
+	_dvb_dmx_swfilter(demux, buf, count, 204);
+}
 EXPORT_SYMBOL(dvb_dmx_swfilter_204);
 
 static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux)

+ 193 - 172
drivers/media/dvb/dvb-core/dvb_frontend.c

@@ -105,7 +105,8 @@ struct dvb_frontend_private {
 
 	/* thread/frontend values */
 	struct dvb_device *dvbdev;
-	struct dvb_frontend_parameters parameters;
+	struct dvb_frontend_parameters parameters_in;
+	struct dvb_frontend_parameters parameters_out;
 	struct dvb_fe_events events;
 	struct semaphore sem;
 	struct list_head list_head;
@@ -160,12 +161,11 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
 
 	e = &events->events[events->eventw];
 
-	memcpy (&e->parameters, &fepriv->parameters,
-		sizeof (struct dvb_frontend_parameters));
-
 	if (status & FE_HAS_LOCK)
 		if (fe->ops.get_frontend)
-			fe->ops.get_frontend(fe, &e->parameters);
+			fe->ops.get_frontend(fe, &fepriv->parameters_out);
+
+	e->parameters = fepriv->parameters_out;
 
 	events->eventw = wp;
 
@@ -277,12 +277,12 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
 	int ready = 0;
 	int fe_set_err = 0;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	int original_inversion = fepriv->parameters.inversion;
-	u32 original_frequency = fepriv->parameters.frequency;
+	int original_inversion = fepriv->parameters_in.inversion;
+	u32 original_frequency = fepriv->parameters_in.frequency;
 
 	/* are we using autoinversion? */
 	autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
-			 (fepriv->parameters.inversion == INVERSION_AUTO));
+			 (fepriv->parameters_in.inversion == INVERSION_AUTO));
 
 	/* setup parameters correctly */
 	while(!ready) {
@@ -348,18 +348,19 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
 		fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
 
 	/* set the frontend itself */
-	fepriv->parameters.frequency += fepriv->lnb_drift;
+	fepriv->parameters_in.frequency += fepriv->lnb_drift;
 	if (autoinversion)
-		fepriv->parameters.inversion = fepriv->inversion;
+		fepriv->parameters_in.inversion = fepriv->inversion;
 	if (fe->ops.set_frontend)
-		fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters);
+		fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters_in);
+	fepriv->parameters_out = fepriv->parameters_in;
 	if (fe_set_err < 0) {
 		fepriv->state = FESTATE_ERROR;
 		return fe_set_err;
 	}
 
-	fepriv->parameters.frequency = original_frequency;
-	fepriv->parameters.inversion = original_inversion;
+	fepriv->parameters_in.frequency = original_frequency;
+	fepriv->parameters_in.inversion = original_inversion;
 
 	fepriv->auto_sub_step++;
 	return 0;
@@ -383,7 +384,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
 		if (fepriv->state & FESTATE_RETUNE) {
 			if (fe->ops.set_frontend)
 				retval = fe->ops.set_frontend(fe,
-							&fepriv->parameters);
+							&fepriv->parameters_in);
+			fepriv->parameters_out = fepriv->parameters_in;
 			if (retval < 0)
 				fepriv->state = FESTATE_ERROR;
 			else
@@ -413,8 +415,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
 
 		/* if we're tuned, then we have determined the correct inversion */
 		if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
-		    (fepriv->parameters.inversion == INVERSION_AUTO)) {
-			fepriv->parameters.inversion = fepriv->inversion;
+		    (fepriv->parameters_in.inversion == INVERSION_AUTO)) {
+			fepriv->parameters_in.inversion = fepriv->inversion;
 		}
 		return;
 	}
@@ -594,12 +596,14 @@ restart:
 
 				if (fepriv->state & FESTATE_RETUNE) {
 					dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__);
-					params = &fepriv->parameters;
+					params = &fepriv->parameters_in;
 					fepriv->state = FESTATE_TUNED;
 				}
 
 				if (fe->ops.tune)
 					fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
+				if (params)
+					fepriv->parameters_out = *params;
 
 				if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) {
 					dprintk("%s: state changed, adding current state\n", __func__);
@@ -612,11 +616,9 @@ restart:
 				dvb_frontend_swzigzag(fe);
 				break;
 			case DVBFE_ALGO_CUSTOM:
-				params = NULL; /* have we been asked to RETUNE ?	*/
 				dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state);
 				if (fepriv->state & FESTATE_RETUNE) {
 					dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__);
-					params = &fepriv->parameters;
 					fepriv->state = FESTATE_TUNED;
 				}
 				/* Case where we are going to search for a carrier
@@ -625,7 +627,7 @@ restart:
 				 */
 				if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) {
 					if (fe->ops.search) {
-						fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters);
+						fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters_in);
 						/* We did do a search as was requested, the flags are
 						 * now unset as well and has the flags wrt to search.
 						 */
@@ -636,11 +638,12 @@ restart:
 				/* Track the carrier if the search was successful */
 				if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) {
 					if (fe->ops.track)
-						fe->ops.track(fe, &fepriv->parameters);
+						fe->ops.track(fe, &fepriv->parameters_in);
 				} else {
 					fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
 					fepriv->delay = HZ / 2;
 				}
+				fepriv->parameters_out = fepriv->parameters_in;
 				fe->ops.read_status(fe, &s);
 				if (s != fepriv->status) {
 					dvb_frontend_add_event(fe, s); /* update event list */
@@ -860,34 +863,34 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
 
 static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
 {
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int i;
 
-	memset(&(fe->dtv_property_cache), 0,
-			sizeof(struct dtv_frontend_properties));
-
-	fe->dtv_property_cache.state = DTV_CLEAR;
-	fe->dtv_property_cache.delivery_system = SYS_UNDEFINED;
-	fe->dtv_property_cache.inversion = INVERSION_AUTO;
-	fe->dtv_property_cache.fec_inner = FEC_AUTO;
-	fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
-	fe->dtv_property_cache.bandwidth_hz = BANDWIDTH_AUTO;
-	fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
-	fe->dtv_property_cache.hierarchy = HIERARCHY_AUTO;
-	fe->dtv_property_cache.symbol_rate = QAM_AUTO;
-	fe->dtv_property_cache.code_rate_HP = FEC_AUTO;
-	fe->dtv_property_cache.code_rate_LP = FEC_AUTO;
-
-	fe->dtv_property_cache.isdbt_partial_reception = -1;
-	fe->dtv_property_cache.isdbt_sb_mode = -1;
-	fe->dtv_property_cache.isdbt_sb_subchannel = -1;
-	fe->dtv_property_cache.isdbt_sb_segment_idx = -1;
-	fe->dtv_property_cache.isdbt_sb_segment_count = -1;
-	fe->dtv_property_cache.isdbt_layer_enabled = 0x7;
+	memset(c, 0, sizeof(struct dtv_frontend_properties));
+
+	c->state = DTV_CLEAR;
+	c->delivery_system = SYS_UNDEFINED;
+	c->inversion = INVERSION_AUTO;
+	c->fec_inner = FEC_AUTO;
+	c->transmission_mode = TRANSMISSION_MODE_AUTO;
+	c->bandwidth_hz = BANDWIDTH_AUTO;
+	c->guard_interval = GUARD_INTERVAL_AUTO;
+	c->hierarchy = HIERARCHY_AUTO;
+	c->symbol_rate = QAM_AUTO;
+	c->code_rate_HP = FEC_AUTO;
+	c->code_rate_LP = FEC_AUTO;
+
+	c->isdbt_partial_reception = -1;
+	c->isdbt_sb_mode = -1;
+	c->isdbt_sb_subchannel = -1;
+	c->isdbt_sb_segment_idx = -1;
+	c->isdbt_sb_segment_count = -1;
+	c->isdbt_layer_enabled = 0x7;
 	for (i = 0; i < 3; i++) {
-		fe->dtv_property_cache.layer[i].fec = FEC_AUTO;
-		fe->dtv_property_cache.layer[i].modulation = QAM_AUTO;
-		fe->dtv_property_cache.layer[i].interleaving = -1;
-		fe->dtv_property_cache.layer[i].segment_count = -1;
+		c->layer[i].fec = FEC_AUTO;
+		c->layer[i].modulation = QAM_AUTO;
+		c->layer[i].interleaving = -1;
+		c->layer[i].segment_count = -1;
 	}
 
 	return 0;
@@ -1020,10 +1023,9 @@ static int is_legacy_delivery_system(fe_delivery_system_t s)
  * it's being used for the legacy or new API, reducing code and complexity.
  */
 static void dtv_property_cache_sync(struct dvb_frontend *fe,
-				    struct dvb_frontend_parameters *p)
+				    struct dtv_frontend_properties *c,
+				    const struct dvb_frontend_parameters *p)
 {
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-
 	c->frequency = p->frequency;
 	c->inversion = p->inversion;
 
@@ -1074,9 +1076,9 @@ static void dtv_property_cache_sync(struct dvb_frontend *fe,
  */
 static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
 {
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	struct dvb_frontend_parameters *p = &fepriv->parameters;
+	struct dvb_frontend_parameters *p = &fepriv->parameters_in;
 
 	p->frequency = c->frequency;
 	p->inversion = c->inversion;
@@ -1086,14 +1088,12 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
 		dprintk("%s() Preparing QPSK req\n", __func__);
 		p->u.qpsk.symbol_rate = c->symbol_rate;
 		p->u.qpsk.fec_inner = c->fec_inner;
-		c->delivery_system = SYS_DVBS;
 		break;
 	case FE_QAM:
 		dprintk("%s() Preparing QAM req\n", __func__);
 		p->u.qam.symbol_rate = c->symbol_rate;
 		p->u.qam.fec_inner = c->fec_inner;
 		p->u.qam.modulation = c->modulation;
-		c->delivery_system = SYS_DVBC_ANNEX_AC;
 		break;
 	case FE_OFDM:
 		dprintk("%s() Preparing OFDM req\n", __func__);
@@ -1111,15 +1111,10 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
 		p->u.ofdm.transmission_mode = c->transmission_mode;
 		p->u.ofdm.guard_interval = c->guard_interval;
 		p->u.ofdm.hierarchy_information = c->hierarchy;
-		c->delivery_system = SYS_DVBT;
 		break;
 	case FE_ATSC:
 		dprintk("%s() Preparing VSB req\n", __func__);
 		p->u.vsb.modulation = c->modulation;
-		if ((c->modulation == VSB_8) || (c->modulation == VSB_16))
-			c->delivery_system = SYS_ATSC;
-		else
-			c->delivery_system = SYS_DVBC_ANNEX_B;
 		break;
 	}
 }
@@ -1129,9 +1124,9 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
  */
 static void dtv_property_adv_params_sync(struct dvb_frontend *fe)
 {
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	struct dvb_frontend_parameters *p = &fepriv->parameters;
+	struct dvb_frontend_parameters *p = &fepriv->parameters_in;
 
 	p->frequency = c->frequency;
 	p->inversion = c->inversion;
@@ -1148,10 +1143,9 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe)
 		break;
 	}
 
-	if(c->delivery_system == SYS_ISDBT) {
-		/* Fake out a generic DVB-T request so we pass validation in the ioctl */
-		p->frequency = c->frequency;
-		p->inversion = c->inversion;
+	/* Fake out a generic DVB-T request so we pass validation in the ioctl */
+	if ((c->delivery_system == SYS_ISDBT) ||
+	    (c->delivery_system == SYS_DVBT2)) {
 		p->u.ofdm.constellation = QAM_AUTO;
 		p->u.ofdm.code_rate_HP = FEC_AUTO;
 		p->u.ofdm.code_rate_LP = FEC_AUTO;
@@ -1171,7 +1165,7 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe)
 
 static void dtv_property_cache_submit(struct dvb_frontend *fe)
 {
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
 	/* For legacy delivery systems we don't need the delivery_system to
 	 * be specified, but we populate the older structures from the cache
@@ -1204,133 +1198,149 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
 				    struct dtv_property *tvp,
 				    struct file *file)
 {
-	int r = 0;
-
-	/* Allow the frontend to validate incoming properties */
-	if (fe->ops.get_property)
-		r = fe->ops.get_property(fe, tvp);
+	const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dtv_frontend_properties cdetected;
+	int r;
 
-	if (r < 0)
-		return r;
+	/*
+	 * If the driver implements a get_frontend function, then convert
+	 * detected parameters to S2API properties.
+	 */
+	if (fe->ops.get_frontend) {
+		cdetected = *c;
+		dtv_property_cache_sync(fe, &cdetected, &fepriv->parameters_out);
+		c = &cdetected;
+	}
 
 	switch(tvp->cmd) {
 	case DTV_FREQUENCY:
-		tvp->u.data = fe->dtv_property_cache.frequency;
+		tvp->u.data = c->frequency;
 		break;
 	case DTV_MODULATION:
-		tvp->u.data = fe->dtv_property_cache.modulation;
+		tvp->u.data = c->modulation;
 		break;
 	case DTV_BANDWIDTH_HZ:
-		tvp->u.data = fe->dtv_property_cache.bandwidth_hz;
+		tvp->u.data = c->bandwidth_hz;
 		break;
 	case DTV_INVERSION:
-		tvp->u.data = fe->dtv_property_cache.inversion;
+		tvp->u.data = c->inversion;
 		break;
 	case DTV_SYMBOL_RATE:
-		tvp->u.data = fe->dtv_property_cache.symbol_rate;
+		tvp->u.data = c->symbol_rate;
 		break;
 	case DTV_INNER_FEC:
-		tvp->u.data = fe->dtv_property_cache.fec_inner;
+		tvp->u.data = c->fec_inner;
 		break;
 	case DTV_PILOT:
-		tvp->u.data = fe->dtv_property_cache.pilot;
+		tvp->u.data = c->pilot;
 		break;
 	case DTV_ROLLOFF:
-		tvp->u.data = fe->dtv_property_cache.rolloff;
+		tvp->u.data = c->rolloff;
 		break;
 	case DTV_DELIVERY_SYSTEM:
-		tvp->u.data = fe->dtv_property_cache.delivery_system;
+		tvp->u.data = c->delivery_system;
 		break;
 	case DTV_VOLTAGE:
-		tvp->u.data = fe->dtv_property_cache.voltage;
+		tvp->u.data = c->voltage;
 		break;
 	case DTV_TONE:
-		tvp->u.data = fe->dtv_property_cache.sectone;
+		tvp->u.data = c->sectone;
 		break;
 	case DTV_API_VERSION:
 		tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR;
 		break;
 	case DTV_CODE_RATE_HP:
-		tvp->u.data = fe->dtv_property_cache.code_rate_HP;
+		tvp->u.data = c->code_rate_HP;
 		break;
 	case DTV_CODE_RATE_LP:
-		tvp->u.data = fe->dtv_property_cache.code_rate_LP;
+		tvp->u.data = c->code_rate_LP;
 		break;
 	case DTV_GUARD_INTERVAL:
-		tvp->u.data = fe->dtv_property_cache.guard_interval;
+		tvp->u.data = c->guard_interval;
 		break;
 	case DTV_TRANSMISSION_MODE:
-		tvp->u.data = fe->dtv_property_cache.transmission_mode;
+		tvp->u.data = c->transmission_mode;
 		break;
 	case DTV_HIERARCHY:
-		tvp->u.data = fe->dtv_property_cache.hierarchy;
+		tvp->u.data = c->hierarchy;
 		break;
 
 	/* ISDB-T Support here */
 	case DTV_ISDBT_PARTIAL_RECEPTION:
-		tvp->u.data = fe->dtv_property_cache.isdbt_partial_reception;
+		tvp->u.data = c->isdbt_partial_reception;
 		break;
 	case DTV_ISDBT_SOUND_BROADCASTING:
-		tvp->u.data = fe->dtv_property_cache.isdbt_sb_mode;
+		tvp->u.data = c->isdbt_sb_mode;
 		break;
 	case DTV_ISDBT_SB_SUBCHANNEL_ID:
-		tvp->u.data = fe->dtv_property_cache.isdbt_sb_subchannel;
+		tvp->u.data = c->isdbt_sb_subchannel;
 		break;
 	case DTV_ISDBT_SB_SEGMENT_IDX:
-		tvp->u.data = fe->dtv_property_cache.isdbt_sb_segment_idx;
+		tvp->u.data = c->isdbt_sb_segment_idx;
 		break;
 	case DTV_ISDBT_SB_SEGMENT_COUNT:
-		tvp->u.data = fe->dtv_property_cache.isdbt_sb_segment_count;
+		tvp->u.data = c->isdbt_sb_segment_count;
 		break;
 	case DTV_ISDBT_LAYER_ENABLED:
-		tvp->u.data = fe->dtv_property_cache.isdbt_layer_enabled;
+		tvp->u.data = c->isdbt_layer_enabled;
 		break;
 	case DTV_ISDBT_LAYERA_FEC:
-		tvp->u.data = fe->dtv_property_cache.layer[0].fec;
+		tvp->u.data = c->layer[0].fec;
 		break;
 	case DTV_ISDBT_LAYERA_MODULATION:
-		tvp->u.data = fe->dtv_property_cache.layer[0].modulation;
+		tvp->u.data = c->layer[0].modulation;
 		break;
 	case DTV_ISDBT_LAYERA_SEGMENT_COUNT:
-		tvp->u.data = fe->dtv_property_cache.layer[0].segment_count;
+		tvp->u.data = c->layer[0].segment_count;
 		break;
 	case DTV_ISDBT_LAYERA_TIME_INTERLEAVING:
-		tvp->u.data = fe->dtv_property_cache.layer[0].interleaving;
+		tvp->u.data = c->layer[0].interleaving;
 		break;
 	case DTV_ISDBT_LAYERB_FEC:
-		tvp->u.data = fe->dtv_property_cache.layer[1].fec;
+		tvp->u.data = c->layer[1].fec;
 		break;
 	case DTV_ISDBT_LAYERB_MODULATION:
-		tvp->u.data = fe->dtv_property_cache.layer[1].modulation;
+		tvp->u.data = c->layer[1].modulation;
 		break;
 	case DTV_ISDBT_LAYERB_SEGMENT_COUNT:
-		tvp->u.data = fe->dtv_property_cache.layer[1].segment_count;
+		tvp->u.data = c->layer[1].segment_count;
 		break;
 	case DTV_ISDBT_LAYERB_TIME_INTERLEAVING:
-		tvp->u.data = fe->dtv_property_cache.layer[1].interleaving;
+		tvp->u.data = c->layer[1].interleaving;
 		break;
 	case DTV_ISDBT_LAYERC_FEC:
-		tvp->u.data = fe->dtv_property_cache.layer[2].fec;
+		tvp->u.data = c->layer[2].fec;
 		break;
 	case DTV_ISDBT_LAYERC_MODULATION:
-		tvp->u.data = fe->dtv_property_cache.layer[2].modulation;
+		tvp->u.data = c->layer[2].modulation;
 		break;
 	case DTV_ISDBT_LAYERC_SEGMENT_COUNT:
-		tvp->u.data = fe->dtv_property_cache.layer[2].segment_count;
+		tvp->u.data = c->layer[2].segment_count;
 		break;
 	case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
-		tvp->u.data = fe->dtv_property_cache.layer[2].interleaving;
+		tvp->u.data = c->layer[2].interleaving;
 		break;
 	case DTV_ISDBS_TS_ID:
-		tvp->u.data = fe->dtv_property_cache.isdbs_ts_id;
+		tvp->u.data = c->isdbs_ts_id;
+		break;
+	case DTV_DVBT2_PLP_ID:
+		tvp->u.data = c->dvbt2_plp_id;
 		break;
 	default:
-		r = -1;
+		return -EINVAL;
+	}
+
+	/* Allow the frontend to override outgoing properties */
+	if (fe->ops.get_property) {
+		r = fe->ops.get_property(fe, tvp);
+		if (r < 0)
+			return r;
 	}
 
 	dtv_property_dump(tvp);
 
-	return r;
+	return 0;
 }
 
 static int dtv_property_process_set(struct dvb_frontend *fe,
@@ -1338,15 +1348,16 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
 				    struct file *file)
 {
 	int r = 0;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	dtv_property_dump(tvp);
 
 	/* Allow the frontend to validate incoming properties */
-	if (fe->ops.set_property)
+	if (fe->ops.set_property) {
 		r = fe->ops.set_property(fe, tvp);
-
-	if (r < 0)
-		return r;
+		if (r < 0)
+			return r;
+	}
 
 	switch(tvp->cmd) {
 	case DTV_CLEAR:
@@ -1361,126 +1372,129 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
 		 * tunerequest so we can pass validation in the FE_SET_FRONTEND
 		 * ioctl.
 		 */
-		fe->dtv_property_cache.state = tvp->cmd;
+		c->state = tvp->cmd;
 		dprintk("%s() Finalised property cache\n", __func__);
 		dtv_property_cache_submit(fe);
 
-		r |= dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND,
-			&fepriv->parameters);
+		r = dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND,
+			&fepriv->parameters_in);
 		break;
 	case DTV_FREQUENCY:
-		fe->dtv_property_cache.frequency = tvp->u.data;
+		c->frequency = tvp->u.data;
 		break;
 	case DTV_MODULATION:
-		fe->dtv_property_cache.modulation = tvp->u.data;
+		c->modulation = tvp->u.data;
 		break;
 	case DTV_BANDWIDTH_HZ:
-		fe->dtv_property_cache.bandwidth_hz = tvp->u.data;
+		c->bandwidth_hz = tvp->u.data;
 		break;
 	case DTV_INVERSION:
-		fe->dtv_property_cache.inversion = tvp->u.data;
+		c->inversion = tvp->u.data;
 		break;
 	case DTV_SYMBOL_RATE:
-		fe->dtv_property_cache.symbol_rate = tvp->u.data;
+		c->symbol_rate = tvp->u.data;
 		break;
 	case DTV_INNER_FEC:
-		fe->dtv_property_cache.fec_inner = tvp->u.data;
+		c->fec_inner = tvp->u.data;
 		break;
 	case DTV_PILOT:
-		fe->dtv_property_cache.pilot = tvp->u.data;
+		c->pilot = tvp->u.data;
 		break;
 	case DTV_ROLLOFF:
-		fe->dtv_property_cache.rolloff = tvp->u.data;
+		c->rolloff = tvp->u.data;
 		break;
 	case DTV_DELIVERY_SYSTEM:
-		fe->dtv_property_cache.delivery_system = tvp->u.data;
+		c->delivery_system = tvp->u.data;
 		break;
 	case DTV_VOLTAGE:
-		fe->dtv_property_cache.voltage = tvp->u.data;
+		c->voltage = tvp->u.data;
 		r = dvb_frontend_ioctl_legacy(file, FE_SET_VOLTAGE,
-			(void *)fe->dtv_property_cache.voltage);
+			(void *)c->voltage);
 		break;
 	case DTV_TONE:
-		fe->dtv_property_cache.sectone = tvp->u.data;
+		c->sectone = tvp->u.data;
 		r = dvb_frontend_ioctl_legacy(file, FE_SET_TONE,
-			(void *)fe->dtv_property_cache.sectone);
+			(void *)c->sectone);
 		break;
 	case DTV_CODE_RATE_HP:
-		fe->dtv_property_cache.code_rate_HP = tvp->u.data;
+		c->code_rate_HP = tvp->u.data;
 		break;
 	case DTV_CODE_RATE_LP:
-		fe->dtv_property_cache.code_rate_LP = tvp->u.data;
+		c->code_rate_LP = tvp->u.data;
 		break;
 	case DTV_GUARD_INTERVAL:
-		fe->dtv_property_cache.guard_interval = tvp->u.data;
+		c->guard_interval = tvp->u.data;
 		break;
 	case DTV_TRANSMISSION_MODE:
-		fe->dtv_property_cache.transmission_mode = tvp->u.data;
+		c->transmission_mode = tvp->u.data;
 		break;
 	case DTV_HIERARCHY:
-		fe->dtv_property_cache.hierarchy = tvp->u.data;
+		c->hierarchy = tvp->u.data;
 		break;
 
 	/* ISDB-T Support here */
 	case DTV_ISDBT_PARTIAL_RECEPTION:
-		fe->dtv_property_cache.isdbt_partial_reception = tvp->u.data;
+		c->isdbt_partial_reception = tvp->u.data;
 		break;
 	case DTV_ISDBT_SOUND_BROADCASTING:
-		fe->dtv_property_cache.isdbt_sb_mode = tvp->u.data;
+		c->isdbt_sb_mode = tvp->u.data;
 		break;
 	case DTV_ISDBT_SB_SUBCHANNEL_ID:
-		fe->dtv_property_cache.isdbt_sb_subchannel = tvp->u.data;
+		c->isdbt_sb_subchannel = tvp->u.data;
 		break;
 	case DTV_ISDBT_SB_SEGMENT_IDX:
-		fe->dtv_property_cache.isdbt_sb_segment_idx = tvp->u.data;
+		c->isdbt_sb_segment_idx = tvp->u.data;
 		break;
 	case DTV_ISDBT_SB_SEGMENT_COUNT:
-		fe->dtv_property_cache.isdbt_sb_segment_count = tvp->u.data;
+		c->isdbt_sb_segment_count = tvp->u.data;
 		break;
 	case DTV_ISDBT_LAYER_ENABLED:
-		fe->dtv_property_cache.isdbt_layer_enabled = tvp->u.data;
+		c->isdbt_layer_enabled = tvp->u.data;
 		break;
 	case DTV_ISDBT_LAYERA_FEC:
-		fe->dtv_property_cache.layer[0].fec = tvp->u.data;
+		c->layer[0].fec = tvp->u.data;
 		break;
 	case DTV_ISDBT_LAYERA_MODULATION:
-		fe->dtv_property_cache.layer[0].modulation = tvp->u.data;
+		c->layer[0].modulation = tvp->u.data;
 		break;
 	case DTV_ISDBT_LAYERA_SEGMENT_COUNT:
-		fe->dtv_property_cache.layer[0].segment_count = tvp->u.data;
+		c->layer[0].segment_count = tvp->u.data;
 		break;
 	case DTV_ISDBT_LAYERA_TIME_INTERLEAVING:
-		fe->dtv_property_cache.layer[0].interleaving = tvp->u.data;
+		c->layer[0].interleaving = tvp->u.data;
 		break;
 	case DTV_ISDBT_LAYERB_FEC:
-		fe->dtv_property_cache.layer[1].fec = tvp->u.data;
+		c->layer[1].fec = tvp->u.data;
 		break;
 	case DTV_ISDBT_LAYERB_MODULATION:
-		fe->dtv_property_cache.layer[1].modulation = tvp->u.data;
+		c->layer[1].modulation = tvp->u.data;
 		break;
 	case DTV_ISDBT_LAYERB_SEGMENT_COUNT:
-		fe->dtv_property_cache.layer[1].segment_count = tvp->u.data;
+		c->layer[1].segment_count = tvp->u.data;
 		break;
 	case DTV_ISDBT_LAYERB_TIME_INTERLEAVING:
-		fe->dtv_property_cache.layer[1].interleaving = tvp->u.data;
+		c->layer[1].interleaving = tvp->u.data;
 		break;
 	case DTV_ISDBT_LAYERC_FEC:
-		fe->dtv_property_cache.layer[2].fec = tvp->u.data;
+		c->layer[2].fec = tvp->u.data;
 		break;
 	case DTV_ISDBT_LAYERC_MODULATION:
-		fe->dtv_property_cache.layer[2].modulation = tvp->u.data;
+		c->layer[2].modulation = tvp->u.data;
 		break;
 	case DTV_ISDBT_LAYERC_SEGMENT_COUNT:
-		fe->dtv_property_cache.layer[2].segment_count = tvp->u.data;
+		c->layer[2].segment_count = tvp->u.data;
 		break;
 	case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
-		fe->dtv_property_cache.layer[2].interleaving = tvp->u.data;
+		c->layer[2].interleaving = tvp->u.data;
 		break;
 	case DTV_ISDBS_TS_ID:
-		fe->dtv_property_cache.isdbs_ts_id = tvp->u.data;
+		c->isdbs_ts_id = tvp->u.data;
+		break;
+	case DTV_DVBT2_PLP_ID:
+		c->dvbt2_plp_id = tvp->u.data;
 		break;
 	default:
-		r = -1;
+		return -EINVAL;
 	}
 
 	return r;
@@ -1491,6 +1505,7 @@ static int dvb_frontend_ioctl(struct file *file,
 {
 	struct dvb_device *dvbdev = file->private_data;
 	struct dvb_frontend *fe = dvbdev->priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	int err = -EOPNOTSUPP;
 
@@ -1510,7 +1525,7 @@ static int dvb_frontend_ioctl(struct file *file,
 	if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY))
 		err = dvb_frontend_ioctl_properties(file, cmd, parg);
 	else {
-		fe->dtv_property_cache.state = DTV_UNDEFINED;
+		c->state = DTV_UNDEFINED;
 		err = dvb_frontend_ioctl_legacy(file, cmd, parg);
 	}
 
@@ -1523,6 +1538,7 @@ static int dvb_frontend_ioctl_properties(struct file *file,
 {
 	struct dvb_device *dvbdev = file->private_data;
 	struct dvb_frontend *fe = dvbdev->priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int err = 0;
 
 	struct dtv_properties *tvps = NULL;
@@ -1554,11 +1570,13 @@ static int dvb_frontend_ioctl_properties(struct file *file,
 		}
 
 		for (i = 0; i < tvps->num; i++) {
-			(tvp + i)->result = dtv_property_process_set(fe, tvp + i, file);
-			err |= (tvp + i)->result;
+			err = dtv_property_process_set(fe, tvp + i, file);
+			if (err < 0)
+				goto out;
+			(tvp + i)->result = err;
 		}
 
-		if(fe->dtv_property_cache.state == DTV_TUNE)
+		if (c->state == DTV_TUNE)
 			dprintk("%s() Property cache is full, tuning\n", __func__);
 
 	} else
@@ -1586,8 +1604,10 @@ static int dvb_frontend_ioctl_properties(struct file *file,
 		}
 
 		for (i = 0; i < tvps->num; i++) {
-			(tvp + i)->result = dtv_property_process_get(fe, tvp + i, file);
-			err |= (tvp + i)->result;
+			err = dtv_property_process_get(fe, tvp + i, file);
+			if (err < 0)
+				goto out;
+			(tvp + i)->result = err;
 		}
 
 		if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) {
@@ -1787,10 +1807,11 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
 		break;
 
 	case FE_SET_FRONTEND: {
+		struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 		struct dvb_frontend_tune_settings fetunesettings;
 
-		if(fe->dtv_property_cache.state == DTV_TUNE) {
-			if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) {
+		if (c->state == DTV_TUNE) {
+			if (dvb_frontend_check_parameters(fe, &fepriv->parameters_in) < 0) {
 				err = -EINVAL;
 				break;
 			}
@@ -1800,9 +1821,9 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
 				break;
 			}
 
-			memcpy (&fepriv->parameters, parg,
+			memcpy (&fepriv->parameters_in, parg,
 				sizeof (struct dvb_frontend_parameters));
-			dtv_property_cache_sync(fe, &fepriv->parameters);
+			dtv_property_cache_sync(fe, c, &fepriv->parameters_in);
 		}
 
 		memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
@@ -1811,15 +1832,15 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
 
 		/* force auto frequency inversion if requested */
 		if (dvb_force_auto_inversion) {
-			fepriv->parameters.inversion = INVERSION_AUTO;
+			fepriv->parameters_in.inversion = INVERSION_AUTO;
 			fetunesettings.parameters.inversion = INVERSION_AUTO;
 		}
 		if (fe->ops.info.type == FE_OFDM) {
 			/* without hierarchical coding code_rate_LP is irrelevant,
 			 * so we tolerate the otherwise invalid FEC_NONE setting */
-			if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
-			    fepriv->parameters.u.ofdm.code_rate_LP == FEC_NONE)
-				fepriv->parameters.u.ofdm.code_rate_LP = FEC_AUTO;
+			if (fepriv->parameters_in.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
+			    fepriv->parameters_in.u.ofdm.code_rate_LP == FEC_NONE)
+				fepriv->parameters_in.u.ofdm.code_rate_LP = FEC_AUTO;
 		}
 
 		/* get frontend-specific tuning settings */
@@ -1832,8 +1853,8 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
 			switch(fe->ops.info.type) {
 			case FE_QPSK:
 				fepriv->min_delay = HZ/20;
-				fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000;
-				fepriv->max_drift = fepriv->parameters.u.qpsk.symbol_rate / 2000;
+				fepriv->step_size = fepriv->parameters_in.u.qpsk.symbol_rate / 16000;
+				fepriv->max_drift = fepriv->parameters_in.u.qpsk.symbol_rate / 2000;
 				break;
 
 			case FE_QAM:
@@ -1875,8 +1896,8 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
 
 	case FE_GET_FRONTEND:
 		if (fe->ops.get_frontend) {
-			memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters));
-			err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg);
+			err = fe->ops.get_frontend(fe, &fepriv->parameters_out);
+			memcpy(parg, &fepriv->parameters_out, sizeof(struct dvb_frontend_parameters));
 		}
 		break;
 

+ 3 - 0
drivers/media/dvb/dvb-core/dvb_frontend.h

@@ -358,6 +358,9 @@ struct dtv_frontend_properties {
 
 	/* ISDB-T specifics */
 	u32			isdbs_ts_id;
+
+	/* DVB-T2 specifics */
+	u32                     dvbt2_plp_id;
 };
 
 struct dvb_frontend {

+ 5 - 0
drivers/media/dvb/dvb-usb/Kconfig

@@ -292,6 +292,11 @@ config DVB_USB_ANYSEE
 	select DVB_MT352 if !DVB_FE_CUSTOMISE
 	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
 	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
+	select MEDIA_TUNER_TDA18212 if !MEDIA_TUNER_CUSTOMISE
+	select DVB_CX24116 if !DVB_FE_CUSTOMISE
+	select DVB_STV0900 if !DVB_FE_CUSTOMISE
+	select DVB_STV6110 if !DVB_FE_CUSTOMISE
+	select DVB_ISL6423 if !DVB_FE_CUSTOMISE
 	help
 	  Say Y here to support the Anysee E30, Anysee E30 Plus or
 	  Anysee E30 C Plus DVB USB2.0 receiver.

+ 13 - 4
drivers/media/dvb/dvb-usb/a800.c

@@ -78,17 +78,26 @@ static struct rc_map_table rc_map_a800_table[] = {
 
 static int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
-	u8 key[5];
+	int ret;
+	u8 *key = kmalloc(5, GFP_KERNEL);
+	if (!key)
+		return -ENOMEM;
+
 	if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0),
 				0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5,
-				2000) != 5)
-		return -ENODEV;
+				2000) != 5) {
+		ret = -ENODEV;
+		goto out;
+	}
 
 	/* call the universal NEC remote processor, to find out the key's state and event */
 	dvb_usb_nec_rc_key_to_event(d,key,event,state);
 	if (key[0] != 0)
 		deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
-	return 0;
+	ret = 0;
+out:
+	kfree(key);
+	return ret;
 }
 
 /* USB Driver stuff */

+ 521 - 99
drivers/media/dvb/dvb-usb/anysee.c

@@ -36,6 +36,11 @@
 #include "mt352.h"
 #include "mt352_priv.h"
 #include "zl10353.h"
+#include "tda18212.h"
+#include "cx24116.h"
+#include "stv0900.h"
+#include "stv6110.h"
+#include "isl6423.h"
 
 /* debug */
 static int dvb_usb_anysee_debug;
@@ -105,6 +110,27 @@ static int anysee_write_reg(struct dvb_usb_device *d, u16 reg, u8 val)
 	return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
 }
 
+/* write single register with mask */
+static int anysee_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val,
+	u8 mask)
+{
+	int ret;
+	u8 tmp;
+
+	/* no need for read if whole reg is written */
+	if (mask != 0xff) {
+		ret = anysee_read_reg(d, reg, &tmp);
+		if (ret)
+			return ret;
+
+		val &= mask;
+		tmp &= ~mask;
+		val |= tmp;
+	}
+
+	return anysee_write_reg(d, reg, val);
+}
+
 static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id)
 {
 	u8 buf[] = {CMD_GET_HW_INFO};
@@ -162,18 +188,18 @@ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
 		if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
 			u8 buf[6];
 			buf[0] = CMD_I2C_READ;
-			buf[1] = msg[i].addr + 1;
+			buf[1] = (msg[i].addr << 1) | 0x01;
 			buf[2] = msg[i].buf[0];
-			buf[3] = 0x00;
-			buf[4] = 0x00;
-			buf[5] = 0x01;
+			buf[3] = msg[i].buf[1];
+			buf[4] = msg[i].len-1;
+			buf[5] = msg[i+1].len;
 			ret = anysee_ctrl_msg(d, buf, sizeof(buf), msg[i+1].buf,
 				msg[i+1].len);
 			inc = 2;
 		} else {
 			u8 buf[4+msg[i].len];
 			buf[0] = CMD_I2C_WRITE;
-			buf[1] = msg[i].addr;
+			buf[1] = (msg[i].addr << 1);
 			buf[2] = msg[i].len;
 			buf[3] = 0x01;
 			memcpy(&buf[4], msg[i].buf, msg[i].len);
@@ -224,7 +250,7 @@ static int anysee_mt352_demod_init(struct dvb_frontend *fe)
 
 /* Callbacks for DVB USB */
 static struct tda10023_config anysee_tda10023_config = {
-	.demod_address = 0x1a,
+	.demod_address = (0x1a >> 1),
 	.invert = 0,
 	.xtal   = 16000000,
 	.pll_m  = 11,
@@ -235,143 +261,539 @@ static struct tda10023_config anysee_tda10023_config = {
 };
 
 static struct mt352_config anysee_mt352_config = {
-	.demod_address = 0x1e,
+	.demod_address = (0x1e >> 1),
 	.demod_init    = anysee_mt352_demod_init,
 };
 
 static struct zl10353_config anysee_zl10353_config = {
-	.demod_address = 0x1e,
+	.demod_address = (0x1e >> 1),
 	.parallel_ts = 1,
 };
 
+static struct zl10353_config anysee_zl10353_tda18212_config2 = {
+	.demod_address = (0x1e >> 1),
+	.parallel_ts = 1,
+	.disable_i2c_gate_ctrl = 1,
+	.no_tuner = 1,
+	.if2 = 41500,
+};
+
+static struct zl10353_config anysee_zl10353_tda18212_config = {
+	.demod_address = (0x18 >> 1),
+	.parallel_ts = 1,
+	.disable_i2c_gate_ctrl = 1,
+	.no_tuner = 1,
+	.if2 = 41500,
+};
+
+static struct tda10023_config anysee_tda10023_tda18212_config = {
+	.demod_address = (0x1a >> 1),
+	.xtal   = 16000000,
+	.pll_m  = 12,
+	.pll_p  = 3,
+	.pll_n  = 1,
+	.output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C,
+	.deltaf = 0xba02,
+};
+
+static struct tda18212_config anysee_tda18212_config = {
+	.i2c_address = (0xc0 >> 1),
+	.if_dvbt_6 = 4150,
+	.if_dvbt_7 = 4150,
+	.if_dvbt_8 = 4150,
+	.if_dvbc = 5000,
+};
+
+static struct cx24116_config anysee_cx24116_config = {
+	.demod_address = (0xaa >> 1),
+	.mpg_clk_pos_pol = 0x00,
+	.i2c_wr_max = 48,
+};
+
+static struct stv0900_config anysee_stv0900_config = {
+	.demod_address = (0xd0 >> 1),
+	.demod_mode = 0,
+	.xtal = 8000000,
+	.clkmode = 3,
+	.diseqc_mode = 2,
+	.tun1_maddress = 0,
+	.tun1_adc = 1, /* 1 Vpp */
+	.path1_mode = 3,
+};
+
+static struct stv6110_config anysee_stv6110_config = {
+	.i2c_address = (0xc0 >> 1),
+	.mclk = 16000000,
+	.clk_div = 1,
+};
+
+static struct isl6423_config anysee_isl6423_config = {
+	.current_max = SEC_CURRENT_800m,
+	.curlim  = SEC_CURRENT_LIM_OFF,
+	.mod_extern = 1,
+	.addr = (0x10 >> 1),
+};
+
+/*
+ * New USB device strings: Mfr=1, Product=2, SerialNumber=0
+ * Manufacturer: AMT.CO.KR
+ *
+ * E30 VID=04b4 PID=861f HW=2 FW=2.1 Product=????????
+ * PCB: ?
+ * parts: DNOS404ZH102A(MT352, DTT7579(?))
+ *
+ * E30 VID=04b4 PID=861f HW=2 FW=2.1 Product=????????
+ * PCB: ?
+ * parts: DNOS404ZH103A(ZL10353, DTT7579(?))
+ *
+ * E30 Plus VID=04b4 PID=861f HW=6 FW=1.0 "anysee"
+ * PCB: 507CD (rev1.1)
+ * parts: DNOS404ZH103A(ZL10353, DTT7579(?)), CST56I01
+ * OEA=80 OEB=00 OEC=00 OED=ff OEF=fe
+ * IOA=4f IOB=ff IOC=00 IOD=06 IOF=01
+ * IOD[0] ZL10353 1=enabled
+ * IOA[7] TS 0=enabled
+ * tuner is not behind ZL10353 I2C-gate (no care if gate disabled or not)
+ *
+ * E30 C Plus VID=04b4 PID=861f HW=10 FW=1.0 "anysee-DC(LP)"
+ * PCB: 507DC (rev0.2)
+ * parts: TDA10023, DTOS403IH102B TM, CST56I01
+ * OEA=80 OEB=00 OEC=00 OED=ff OEF=fe
+ * IOA=4f IOB=ff IOC=00 IOD=26 IOF=01
+ * IOD[0] TDA10023 1=enabled
+ *
+ * E30 S2 Plus VID=04b4 PID=861f HW=11 FW=0.1 "anysee-S2(LP)"
+ * PCB: 507SI (rev2.1)
+ * parts: BS2N10WCC01(CX24116, CX24118), ISL6423, TDA8024
+ * OEA=80 OEB=00 OEC=ff OED=ff OEF=fe
+ * IOA=4d IOB=ff IOC=00 IOD=26 IOF=01
+ * IOD[0] CX24116 1=enabled
+ *
+ * E30 C Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)"
+ * PCB: 507FA (rev0.4)
+ * parts: TDA10023, DTOS403IH102B TM, TDA8024
+ * OEA=80 OEB=00 OEC=ff OED=ff OEF=ff
+ * IOA=4d IOB=ff IOC=00 IOD=00 IOF=c0
+ * IOD[5] TDA10023 1=enabled
+ * IOE[0] tuner 1=enabled
+ *
+ * E30 Combo Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)"
+ * PCB: 507FA (rev1.1)
+ * parts: ZL10353, TDA10023, DTOS403IH102B TM, TDA8024
+ * OEA=80 OEB=00 OEC=ff OED=ff OEF=ff
+ * IOA=4d IOB=ff IOC=00 IOD=00 IOF=c0
+ * DVB-C:
+ * IOD[5] TDA10023 1=enabled
+ * IOE[0] tuner 1=enabled
+ * DVB-T:
+ * IOD[0] ZL10353 1=enabled
+ * IOE[0] tuner 0=enabled
+ * tuner is behind ZL10353 I2C-gate
+ *
+ * E7 TC VID=1c73 PID=861f HW=18 FW=0.7 AMTCI=0.5 "anysee-E7TC(LP)"
+ * PCB: 508TC (rev0.6)
+ * parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212)
+ * OEA=80 OEB=00 OEC=03 OED=f7 OEF=ff
+ * IOA=4d IOB=00 IOC=cc IOD=48 IOF=e4
+ * IOA[7] TS 1=enabled
+ * IOE[4] TDA18212 1=enabled
+ * DVB-C:
+ * IOD[6] ZL10353 0=disabled
+ * IOD[5] TDA10023 1=enabled
+ * IOE[0] IF 1=enabled
+ * DVB-T:
+ * IOD[5] TDA10023 0=disabled
+ * IOD[6] ZL10353 1=enabled
+ * IOE[0] IF 0=enabled
+ *
+ * E7 S2 VID=1c73 PID=861f HW=19 FW=0.4 AMTCI=0.5 "anysee-E7S2(LP)"
+ * PCB: 508S2 (rev0.7)
+ * parts: DNBU10512IST(STV0903, STV6110), ISL6423
+ * OEA=80 OEB=00 OEC=03 OED=f7 OEF=ff
+ * IOA=4d IOB=00 IOC=c4 IOD=08 IOF=e4
+ * IOA[7] TS 1=enabled
+ * IOE[5] STV0903 1=enabled
+ *
+ */
+
 static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	int ret;
 	struct anysee_state *state = adap->dev->priv;
 	u8 hw_info[3];
-	u8 io_d; /* IO port D */
+	u8 tmp;
+	struct i2c_msg msg[2] = {
+		{
+			.addr = anysee_tda18212_config.i2c_address,
+			.flags = 0,
+			.len = 1,
+			.buf = "\x00",
+		}, {
+			.addr = anysee_tda18212_config.i2c_address,
+			.flags = I2C_M_RD,
+			.len = 1,
+			.buf = &tmp,
+		}
+	};
 
-	/* check which hardware we have
-	   We must do this call two times to get reliable values (hw bug). */
+	/* Check which hardware we have.
+	 * We must do this call two times to get reliable values (hw bug).
+	 */
 	ret = anysee_get_hw_info(adap->dev, hw_info);
 	if (ret)
-		return ret;
+		goto error;
+
 	ret = anysee_get_hw_info(adap->dev, hw_info);
 	if (ret)
-		return ret;
+		goto error;
 
 	/* Meaning of these info bytes are guessed. */
-	info("firmware version:%d.%d.%d hardware id:%d",
-		0, hw_info[1], hw_info[2], hw_info[0]);
+	info("firmware version:%d.%d hardware id:%d",
+		hw_info[1], hw_info[2], hw_info[0]);
 
-	ret = anysee_read_reg(adap->dev, 0xb0, &io_d); /* IO port D */
-	if (ret)
-		return ret;
-	deb_info("%s: IO port D:%02x\n", __func__, io_d);
-
-	/* Select demod using trial and error method. */
-
-	/* Try to attach demodulator in following order:
-	      model      demod     hw  firmware
-	   1. E30        MT352     02  0.2.1
-	   2. E30        ZL10353   02  0.2.1
-	   3. E30 Combo  ZL10353   0f  0.1.2    DVB-T/C combo
-	   4. E30 Plus   ZL10353   06  0.1.0
-	   5. E30C Plus  TDA10023  0a  0.1.0    rev 0.2
-	      E30C Plus  TDA10023  0f  0.1.2    rev 0.4
-	      E30 Combo  TDA10023  0f  0.1.2    DVB-T/C combo
-	*/
-
-	/* Zarlink MT352 DVB-T demod inside of Samsung DNOS404ZH102A NIM */
-	adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config,
-			      &adap->dev->i2c_adap);
-	if (adap->fe != NULL) {
-		state->tuner = DVB_PLL_THOMSON_DTT7579;
-		return 0;
-	}
+	state->hw = hw_info[0];
 
-	/* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */
-	adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
-			      &adap->dev->i2c_adap);
-	if (adap->fe != NULL) {
-		state->tuner = DVB_PLL_THOMSON_DTT7579;
-		return 0;
-	}
+	switch (state->hw) {
+	case ANYSEE_HW_02: /* 2 */
+		/* E30 */
+
+		/* attach demod */
+		adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config,
+			&adap->dev->i2c_adap);
+		if (adap->fe)
+			break;
+
+		/* attach demod */
+		adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
+			&adap->dev->i2c_adap);
+
+		break;
+	case ANYSEE_HW_507CD: /* 6 */
+		/* E30 Plus */
 
-	/* for E30 Combo Plus DVB-T demodulator */
-	if (dvb_usb_anysee_delsys) {
-		ret = anysee_write_reg(adap->dev, 0xb0, 0x01);
+		/* enable DVB-T demod on IOD[0] */
+		ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
 		if (ret)
-			return ret;
+			goto error;
+
+		/* enable transport stream on IOA[7] */
+		ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (0 << 7), 0x80);
+		if (ret)
+			goto error;
 
-		/* Zarlink ZL10353 DVB-T demod */
+		/* attach demod */
 		adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
-				      &adap->dev->i2c_adap);
-		if (adap->fe != NULL) {
-			state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A;
-			return 0;
+			&adap->dev->i2c_adap);
+
+		break;
+	case ANYSEE_HW_507DC: /* 10 */
+		/* E30 C Plus */
+
+		/* enable DVB-C demod on IOD[0] */
+		ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
+		if (ret)
+			goto error;
+
+		/* attach demod */
+		adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config,
+			&adap->dev->i2c_adap, 0x48);
+
+		break;
+	case ANYSEE_HW_507SI: /* 11 */
+		/* E30 S2 Plus */
+
+		/* enable DVB-S/S2 demod on IOD[0] */
+		ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
+		if (ret)
+			goto error;
+
+		/* attach demod */
+		adap->fe = dvb_attach(cx24116_attach, &anysee_cx24116_config,
+			&adap->dev->i2c_adap);
+
+		break;
+	case ANYSEE_HW_507FA: /* 15 */
+		/* E30 Combo Plus */
+		/* E30 C Plus */
+
+		/* enable tuner on IOE[4] */
+		ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
+		if (ret)
+			goto error;
+
+		/* probe TDA18212 */
+		tmp = 0;
+		ret = i2c_transfer(&adap->dev->i2c_adap, msg, 2);
+		if (ret == 2 && tmp == 0xc7)
+			deb_info("%s: TDA18212 found\n", __func__);
+		else
+			tmp = 0;
+
+		/* disable tuner on IOE[4] */
+		ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10);
+		if (ret)
+			goto error;
+
+		if (dvb_usb_anysee_delsys) {
+			/* disable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
+				0x20);
+			if (ret)
+				goto error;
+
+			/* enable DVB-T demod on IOD[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
+				0x01);
+			if (ret)
+				goto error;
+
+			/* attach demod */
+			if (tmp == 0xc7) {
+				/* TDA18212 config */
+				adap->fe = dvb_attach(zl10353_attach,
+					&anysee_zl10353_tda18212_config2,
+					&adap->dev->i2c_adap);
+			} else {
+				/* PLL config */
+				adap->fe = dvb_attach(zl10353_attach,
+					&anysee_zl10353_config,
+					&adap->dev->i2c_adap);
+			}
+		} else {
+			/* disable DVB-T demod on IOD[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
+				0x01);
+			if (ret)
+				goto error;
+
+			/* enable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+				0x20);
+			if (ret)
+				goto error;
+
+			/* attach demod */
+			if (tmp == 0xc7) {
+				/* TDA18212 config */
+				adap->fe = dvb_attach(tda10023_attach,
+					&anysee_tda10023_tda18212_config,
+					&adap->dev->i2c_adap, 0x48);
+			} else {
+				/* PLL config */
+				adap->fe = dvb_attach(tda10023_attach,
+					&anysee_tda10023_config,
+					&adap->dev->i2c_adap, 0x48);
+			}
 		}
-	}
 
-	/* connect demod on IO port D for TDA10023 & ZL10353 */
-	ret = anysee_write_reg(adap->dev, 0xb0, 0x25);
-	if (ret)
-		return ret;
+		break;
+	case ANYSEE_HW_508TC: /* 18 */
+		/* E7 TC */
 
-	/* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */
-	adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
-			      &adap->dev->i2c_adap);
-	if (adap->fe != NULL) {
-		state->tuner = DVB_PLL_THOMSON_DTT7579;
-		return 0;
-	}
+		/* enable transport stream on IOA[7] */
+		ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
+		if (ret)
+			goto error;
+
+		if (dvb_usb_anysee_delsys) {
+			/* disable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
+				0x20);
+			if (ret)
+				goto error;
+
+			/* enable DVB-T demod on IOD[6] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
+				0x40);
+			if (ret)
+				goto error;
+
+			/* enable IF route on IOE[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
+				0x01);
+			if (ret)
+				goto error;
+
+			/* attach demod */
+			adap->fe = dvb_attach(zl10353_attach,
+				&anysee_zl10353_tda18212_config,
+				&adap->dev->i2c_adap);
+		} else {
+			/* disable DVB-T demod on IOD[6] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
+				0x40);
+			if (ret)
+				goto error;
+
+			/* enable DVB-C demod on IOD[5] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
+				0x20);
+			if (ret)
+				goto error;
+
+			/* enable IF route on IOE[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
+				0x01);
+			if (ret)
+				goto error;
+
+			/* attach demod */
+			adap->fe = dvb_attach(tda10023_attach,
+				&anysee_tda10023_tda18212_config,
+				&adap->dev->i2c_adap, 0x48);
+		}
 
-	/* IO port E - E30C rev 0.4 board requires this */
-	ret = anysee_write_reg(adap->dev, 0xb1, 0xa7);
-	if (ret)
-		return ret;
+		break;
+	case ANYSEE_HW_508S2: /* 19 */
+		/* E7 S2 */
 
-	/* Philips TDA10023 DVB-C demod */
-	adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config,
-			      &adap->dev->i2c_adap, 0x48);
-	if (adap->fe != NULL) {
-		state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A;
-		return 0;
-	}
+		/* enable transport stream on IOA[7] */
+		ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
+		if (ret)
+			goto error;
 
-	/* return IO port D to init value for safe */
-	ret = anysee_write_reg(adap->dev, 0xb0, io_d);
-	if (ret)
-		return ret;
+		/* enable DVB-S/S2 demod on IOE[5] */
+		ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20);
+		if (ret)
+			goto error;
+
+		/* attach demod */
+		adap->fe = dvb_attach(stv0900_attach, &anysee_stv0900_config,
+			&adap->dev->i2c_adap, 0);
 
-	err("Unknown Anysee version: %02x %02x %02x. "\
-	    "Please report the <linux-dvb@linuxtv.org>.",
-	    hw_info[0], hw_info[1], hw_info[2]);
+		break;
+	}
 
-	return -ENODEV;
+	if (!adap->fe) {
+		/* we have no frontend :-( */
+		ret = -ENODEV;
+		err("Unsupported Anysee version. " \
+			"Please report the <linux-media@vger.kernel.org>.");
+	}
+error:
+	return ret;
 }
 
 static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct anysee_state *state = adap->dev->priv;
+	struct dvb_frontend *fe;
+	int ret;
 	deb_info("%s:\n", __func__);
 
-	switch (state->tuner) {
-	case DVB_PLL_THOMSON_DTT7579:
-		/* Thomson dtt7579 (not sure) PLL inside of:
-		   Samsung DNOS404ZH102A NIM
-		   Samsung DNOS404ZH103A NIM */
-		dvb_attach(dvb_pll_attach, adap->fe, 0x61,
-			   NULL, DVB_PLL_THOMSON_DTT7579);
+	switch (state->hw) {
+	case ANYSEE_HW_02: /* 2 */
+		/* E30 */
+
+		/* attach tuner */
+		fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1),
+			NULL, DVB_PLL_THOMSON_DTT7579);
+
+		break;
+	case ANYSEE_HW_507CD: /* 6 */
+		/* E30 Plus */
+
+		/* attach tuner */
+		fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1),
+			&adap->dev->i2c_adap, DVB_PLL_THOMSON_DTT7579);
+
+		break;
+	case ANYSEE_HW_507DC: /* 10 */
+		/* E30 C Plus */
+
+		/* attach tuner */
+		fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1),
+			&adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
+
+		break;
+	case ANYSEE_HW_507SI: /* 11 */
+		/* E30 S2 Plus */
+
+		/* attach LNB controller */
+		fe = dvb_attach(isl6423_attach, adap->fe, &adap->dev->i2c_adap,
+			&anysee_isl6423_config);
+
+		break;
+	case ANYSEE_HW_507FA: /* 15 */
+		/* E30 Combo Plus */
+		/* E30 C Plus */
+
+		if (dvb_usb_anysee_delsys) {
+			/* enable DVB-T tuner on IOE[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
+				0x01);
+			if (ret)
+				goto error;
+		} else {
+			/* enable DVB-C tuner on IOE[0] */
+			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
+				0x01);
+			if (ret)
+				goto error;
+		}
+
+		/* Try first attach TDA18212 silicon tuner on IOE[4], if that
+		 * fails attach old simple PLL. */
+
+		/* enable tuner on IOE[4] */
+		ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
+		if (ret)
+			goto error;
+
+		/* attach tuner */
+		fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap,
+			&anysee_tda18212_config);
+		if (fe)
+			break;
+
+		/* disable tuner on IOE[4] */
+		ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10);
+		if (ret)
+			goto error;
+
+		/* attach tuner */
+		fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1),
+			&adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
+
 		break;
-	case DVB_PLL_SAMSUNG_DTOS403IH102A:
-		/* Unknown PLL inside of Samsung DTOS403IH102A tuner module */
-		dvb_attach(dvb_pll_attach, adap->fe, 0xc0,
-			   &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
+	case ANYSEE_HW_508TC: /* 18 */
+		/* E7 TC */
+
+		/* enable tuner on IOE[4] */
+		ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
+		if (ret)
+			goto error;
+
+		/* attach tuner */
+		fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap,
+			&anysee_tda18212_config);
+
 		break;
+	case ANYSEE_HW_508S2: /* 19 */
+		/* E7 S2 */
+
+		/* attach tuner */
+		fe = dvb_attach(stv6110_attach, adap->fe,
+			&anysee_stv6110_config, &adap->dev->i2c_adap);
+
+		if (fe) {
+			/* attach LNB controller */
+			fe = dvb_attach(isl6423_attach, adap->fe,
+				&adap->dev->i2c_adap, &anysee_isl6423_config);
+		}
+
+		break;
+	default:
+		fe = NULL;
 	}
 
-	return 0;
+	if (fe)
+		ret = 0;
+	else
+		ret = -ENODEV;
+
+error:
+	return ret;
 }
 
 static int anysee_rc_query(struct dvb_usb_device *d)

+ 21 - 2
drivers/media/dvb/dvb-usb/anysee.h

@@ -57,10 +57,29 @@ enum cmd {
 };
 
 struct anysee_state {
-	u8 tuner;
+	u8 hw; /* PCB ID */
 	u8 seq;
 };
 
+#define ANYSEE_HW_02     2 /* E30 */
+#define ANYSEE_HW_507CD  6 /* E30 Plus */
+#define ANYSEE_HW_507DC 10 /* E30 C Plus */
+#define ANYSEE_HW_507SI 11 /* E30 S2 Plus */
+#define ANYSEE_HW_507FA 15 /* E30 Combo Plus / E30 C Plus */
+#define ANYSEE_HW_508TC 18 /* E7 TC */
+#define ANYSEE_HW_508S2 19 /* E7 S2 */
+
+#define REG_IOA       0x80 /* Port A (bit addressable) */
+#define REG_IOB       0x90 /* Port B (bit addressable) */
+#define REG_IOC       0xa0 /* Port C (bit addressable) */
+#define REG_IOD       0xb0 /* Port D (bit addressable) */
+#define REG_IOE       0xb1 /* Port E (NOT bit addressable) */
+#define REG_OEA       0xb2 /* Port A Output Enable */
+#define REG_OEB       0xb3 /* Port B Output Enable */
+#define REG_OEC       0xb4 /* Port C Output Enable */
+#define REG_OED       0xb5 /* Port D Output Enable */
+#define REG_OEE       0xb6 /* Port E Output Enable */
+
 #endif
 
 /***************************************************************************
@@ -136,7 +155,7 @@ General reply packet(s) are always used if not own reply defined.
 ----------------------------------------------------------------------------
 |    04 | 0x00
 ----------------------------------------------------------------------------
-|    05 | 0x01
+|    05 | data length
 ----------------------------------------------------------------------------
 | 06-59 | don't care
 ----------------------------------------------------------------------------

+ 16 - 6
drivers/media/dvb/dvb-usb/au6610.c

@@ -33,8 +33,16 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
 {
 	int ret;
 	u16 index;
-	u8 usb_buf[6]; /* enough for all known requests,
-			  read returns 5 and write 6 bytes */
+	u8 *usb_buf;
+
+	/*
+	 * allocate enough for all known requests,
+	 * read returns 5 and write 6 bytes
+	 */
+	usb_buf = kmalloc(6, GFP_KERNEL);
+	if (!usb_buf)
+		return -ENOMEM;
+
 	switch (wlen) {
 	case 1:
 		index = wbuf[0] << 8;
@@ -45,14 +53,15 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
 		break;
 	default:
 		warn("wlen = %x, aborting.", wlen);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto error;
 	}
 
 	ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation,
 			      USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index,
-			      usb_buf, sizeof(usb_buf), AU6610_USB_TIMEOUT);
+			      usb_buf, 6, AU6610_USB_TIMEOUT);
 	if (ret < 0)
-		return ret;
+		goto error;
 
 	switch (operation) {
 	case AU6610_REQ_I2C_READ:
@@ -60,7 +69,8 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
 		/* requested value is always 5th byte in buffer */
 		rbuf[0] = usb_buf[4];
 	}
-
+error:
+	kfree(usb_buf);
 	return ret;
 }
 

+ 9 - 2
drivers/media/dvb/dvb-usb/ce6230.c

@@ -39,7 +39,7 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
 	u8 requesttype;
 	u16 value;
 	u16 index;
-	u8 buf[req->data_len];
+	u8 *buf;
 
 	request = req->cmd;
 	value = req->value;
@@ -62,6 +62,12 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
 		goto error;
 	}
 
+	buf = kmalloc(req->data_len, GFP_KERNEL);
+	if (!buf) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
 	if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) {
 		/* write */
 		memcpy(buf, req->data, req->data_len);
@@ -74,7 +80,7 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
 	msleep(1); /* avoid I2C errors */
 
 	ret = usb_control_msg(udev, pipe, request, requesttype, value, index,
-				buf, sizeof(buf), CE6230_USB_TIMEOUT);
+				buf, req->data_len, CE6230_USB_TIMEOUT);
 
 	ce6230_debug_dump(request, requesttype, value, index, buf,
 		req->data_len, deb_xfer);
@@ -88,6 +94,7 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
 	if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
 		memcpy(req->data, buf, req->data_len);
 
+	kfree(buf);
 error:
 	return ret;
 }

+ 3 - 2
drivers/media/dvb/dvb-usb/dib0700.h

@@ -46,8 +46,9 @@ struct dib0700_state {
 	u8 is_dib7000pc;
 	u8 fw_use_new_i2c_api;
 	u8 disable_streaming_master_mode;
-    u32 fw_version;
-    u32 nb_packet_buffer_size;
+	u32 fw_version;
+	u32 nb_packet_buffer_size;
+	u8 buf[255];
 };
 
 extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,

+ 133 - 87
drivers/media/dvb/dvb-usb/dib0700_core.c

@@ -27,19 +27,25 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
 			u32 *romversion, u32 *ramversion, u32 *fwtype)
 {
-	u8 b[16];
-	int ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
+	struct dib0700_state *st = d->priv;
+	int ret;
+
+	ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
 				  REQUEST_GET_VERSION,
 				  USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
-				  b, sizeof(b), USB_CTRL_GET_TIMEOUT);
+				  st->buf, 16, USB_CTRL_GET_TIMEOUT);
 	if (hwversion != NULL)
-		*hwversion  = (b[0] << 24)  | (b[1] << 16)  | (b[2] << 8)  | b[3];
+		*hwversion  = (st->buf[0] << 24)  | (st->buf[1] << 16)  |
+			(st->buf[2] << 8)  | st->buf[3];
 	if (romversion != NULL)
-		*romversion = (b[4] << 24)  | (b[5] << 16)  | (b[6] << 8)  | b[7];
+		*romversion = (st->buf[4] << 24)  | (st->buf[5] << 16)  |
+			(st->buf[6] << 8)  | st->buf[7];
 	if (ramversion != NULL)
-		*ramversion = (b[8] << 24)  | (b[9] << 16)  | (b[10] << 8) | b[11];
+		*ramversion = (st->buf[8] << 24)  | (st->buf[9] << 16)  |
+			(st->buf[10] << 8) | st->buf[11];
 	if (fwtype != NULL)
-		*fwtype     = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15];
+		*fwtype     = (st->buf[12] << 24) | (st->buf[13] << 16) |
+			(st->buf[14] << 8) | st->buf[15];
 	return ret;
 }
 
@@ -101,24 +107,31 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen
 
 int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
 {
-	u8 buf[3] = { REQUEST_SET_GPIO, gpio, ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6) };
-	return dib0700_ctrl_wr(d, buf, sizeof(buf));
+	struct dib0700_state *st = d->priv;
+	s16 ret;
+
+	st->buf[0] = REQUEST_SET_GPIO;
+	st->buf[1] = gpio;
+	st->buf[2] = ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6);
+
+	ret = dib0700_ctrl_wr(d, st->buf, 3);
+
+	return ret;
 }
 
 static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
 {
 	struct dib0700_state *st = d->priv;
-	u8 b[3];
 	int ret;
 
 	if (st->fw_version >= 0x10201) {
-		b[0] = REQUEST_SET_USB_XFER_LEN;
-		b[1] = (nb_ts_packets >> 8) & 0xff;
-		b[2] = nb_ts_packets & 0xff;
+		st->buf[0] = REQUEST_SET_USB_XFER_LEN;
+		st->buf[1] = (nb_ts_packets >> 8) & 0xff;
+		st->buf[2] = nb_ts_packets & 0xff;
 
 		deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
 
-		ret = dib0700_ctrl_wr(d, b, sizeof(b));
+		ret = dib0700_ctrl_wr(d, st->buf, 3);
 	} else {
 		deb_info("this firmware does not allow to change the USB xfer len\n");
 		ret = -EIO;
@@ -137,11 +150,11 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
 	   properly support i2c read calls not preceded by a write */
 
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	struct dib0700_state *st = d->priv;
 	uint8_t bus_mode = 1;  /* 0=eeprom bus, 1=frontend bus */
 	uint8_t gen_mode = 0; /* 0=master i2c, 1=gpio i2c */
 	uint8_t en_start = 0;
 	uint8_t en_stop = 0;
-	uint8_t buf[255]; /* TBV: malloc ? */
 	int result, i;
 
 	/* Ensure nobody else hits the i2c bus while we're sending our
@@ -195,24 +208,24 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
 
 		} else {
 			/* Write request */
-			buf[0] = REQUEST_NEW_I2C_WRITE;
-			buf[1] = msg[i].addr << 1;
-			buf[2] = (en_start << 7) | (en_stop << 6) |
+			st->buf[0] = REQUEST_NEW_I2C_WRITE;
+			st->buf[1] = msg[i].addr << 1;
+			st->buf[2] = (en_start << 7) | (en_stop << 6) |
 				(msg[i].len & 0x3F);
 			/* I2C ctrl + FE bus; */
-			buf[3] = ((gen_mode << 6) & 0xC0) |
+			st->buf[3] = ((gen_mode << 6) & 0xC0) |
 				 ((bus_mode << 4) & 0x30);
 			/* The Actual i2c payload */
-			memcpy(&buf[4], msg[i].buf, msg[i].len);
+			memcpy(&st->buf[4], msg[i].buf, msg[i].len);
 
 			deb_data(">>> ");
-			debug_dump(buf, msg[i].len + 4, deb_data);
+			debug_dump(st->buf, msg[i].len + 4, deb_data);
 
 			result = usb_control_msg(d->udev,
 						 usb_sndctrlpipe(d->udev, 0),
 						 REQUEST_NEW_I2C_WRITE,
 						 USB_TYPE_VENDOR | USB_DIR_OUT,
-						 0, 0, buf, msg[i].len + 4,
+						 0, 0, st->buf, msg[i].len + 4,
 						 USB_CTRL_GET_TIMEOUT);
 			if (result < 0) {
 				deb_info("i2c write error (status = %d)\n", result);
@@ -231,27 +244,29 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
 				   struct i2c_msg *msg, int num)
 {
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	struct dib0700_state *st = d->priv;
 	int i,len;
-	u8 buf[255];
 
 	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
 		return -EAGAIN;
 
 	for (i = 0; i < num; i++) {
 		/* fill in the address */
-		buf[1] = msg[i].addr << 1;
+		st->buf[1] = msg[i].addr << 1;
 		/* fill the buffer */
-		memcpy(&buf[2], msg[i].buf, msg[i].len);
+		memcpy(&st->buf[2], msg[i].buf, msg[i].len);
 
 		/* write/read request */
 		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
-			buf[0] = REQUEST_I2C_READ;
-			buf[1] |= 1;
+			st->buf[0] = REQUEST_I2C_READ;
+			st->buf[1] |= 1;
 
 			/* special thing in the current firmware: when length is zero the read-failed */
-			if ((len = dib0700_ctrl_rd(d, buf, msg[i].len + 2, msg[i+1].buf, msg[i+1].len)) <= 0) {
+			len = dib0700_ctrl_rd(d, st->buf, msg[i].len + 2,
+					msg[i+1].buf, msg[i+1].len);
+			if (len <= 0) {
 				deb_info("I2C read failed on address 0x%02x\n",
-					 msg[i].addr);
+						msg[i].addr);
 				break;
 			}
 
@@ -259,13 +274,13 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
 
 			i++;
 		} else {
-			buf[0] = REQUEST_I2C_WRITE;
-			if (dib0700_ctrl_wr(d, buf, msg[i].len + 2) < 0)
+			st->buf[0] = REQUEST_I2C_WRITE;
+			if (dib0700_ctrl_wr(d, st->buf, msg[i].len + 2) < 0)
 				break;
 		}
 	}
-
 	mutex_unlock(&d->i2c_mutex);
+
 	return i;
 }
 
@@ -297,15 +312,23 @@ struct i2c_algorithm dib0700_i2c_algo = {
 int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
 			struct dvb_usb_device_description **desc, int *cold)
 {
-	u8 b[16];
-	s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0),
+	s16 ret;
+	u8 *b;
+
+	b = kmalloc(16, GFP_KERNEL);
+	if (!b)
+		return	-ENOMEM;
+
+
+	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
 		REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT);
 
 	deb_info("FW GET_VERSION length: %d\n",ret);
 
 	*cold = ret <= 0;
-
 	deb_info("cold: %d\n", *cold);
+
+	kfree(b);
 	return 0;
 }
 
@@ -313,43 +336,50 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
 	u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv,
 	u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
 {
-	u8 b[10];
-	b[0] = REQUEST_SET_CLOCK;
-	b[1] = (en_pll << 7) | (pll_src << 6) | (pll_range << 5) | (clock_gpio3 << 4);
-	b[2] = (pll_prediv >> 8)  & 0xff; // MSB
-	b[3] =  pll_prediv        & 0xff; // LSB
-	b[4] = (pll_loopdiv >> 8) & 0xff; // MSB
-	b[5] =  pll_loopdiv       & 0xff; // LSB
-	b[6] = (free_div >> 8)    & 0xff; // MSB
-	b[7] =  free_div          & 0xff; // LSB
-	b[8] = (dsuScaler >> 8)   & 0xff; // MSB
-	b[9] =  dsuScaler         & 0xff; // LSB
-
-	return dib0700_ctrl_wr(d, b, 10);
+	struct dib0700_state *st = d->priv;
+	s16 ret;
+
+	st->buf[0] = REQUEST_SET_CLOCK;
+	st->buf[1] = (en_pll << 7) | (pll_src << 6) |
+		(pll_range << 5) | (clock_gpio3 << 4);
+	st->buf[2] = (pll_prediv >> 8)  & 0xff; /* MSB */
+	st->buf[3] =  pll_prediv        & 0xff; /* LSB */
+	st->buf[4] = (pll_loopdiv >> 8) & 0xff; /* MSB */
+	st->buf[5] =  pll_loopdiv       & 0xff; /* LSB */
+	st->buf[6] = (free_div >> 8)    & 0xff; /* MSB */
+	st->buf[7] =  free_div          & 0xff; /* LSB */
+	st->buf[8] = (dsuScaler >> 8)   & 0xff; /* MSB */
+	st->buf[9] =  dsuScaler         & 0xff; /* LSB */
+
+	ret = dib0700_ctrl_wr(d, st->buf, 10);
+
+	return ret;
 }
 
 int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
 {
+	struct dib0700_state *st = d->priv;
 	u16 divider;
-	u8 b[8];
 
 	if (scl_kHz == 0)
 		return -EINVAL;
 
-	b[0] = REQUEST_SET_I2C_PARAM;
+	st->buf[0] = REQUEST_SET_I2C_PARAM;
 	divider = (u16) (30000 / scl_kHz);
-	b[2] = (u8) (divider >> 8);
-	b[3] = (u8) (divider & 0xff);
+	st->buf[1] = 0;
+	st->buf[2] = (u8) (divider >> 8);
+	st->buf[3] = (u8) (divider & 0xff);
 	divider = (u16) (72000 / scl_kHz);
-	b[4] = (u8) (divider >> 8);
-	b[5] = (u8) (divider & 0xff);
+	st->buf[4] = (u8) (divider >> 8);
+	st->buf[5] = (u8) (divider & 0xff);
 	divider = (u16) (72000 / scl_kHz); /* clock: 72MHz */
-	b[6] = (u8) (divider >> 8);
-	b[7] = (u8) (divider & 0xff);
+	st->buf[6] = (u8) (divider >> 8);
+	st->buf[7] = (u8) (divider & 0xff);
 
 	deb_info("setting I2C speed: %04x %04x %04x (%d kHz).",
-		(b[2] << 8) | (b[3]), (b[4] << 8) | b[5], (b[6] << 8) | b[7], scl_kHz);
-	return dib0700_ctrl_wr(d, b, 8);
+		(st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) |
+		st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz);
+	return dib0700_ctrl_wr(d, st->buf, 8);
 }
 
 
@@ -364,32 +394,45 @@ int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3)
 
 static int dib0700_jumpram(struct usb_device *udev, u32 address)
 {
-	int ret, actlen;
-	u8 buf[8] = { REQUEST_JUMPRAM, 0, 0, 0,
-		(address >> 24) & 0xff,
-		(address >> 16) & 0xff,
-		(address >> 8)  & 0xff,
-		 address        & 0xff };
+	int ret = 0, actlen;
+	u8 *buf;
+
+	buf = kmalloc(8, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	buf[0] = REQUEST_JUMPRAM;
+	buf[1] = 0;
+	buf[2] = 0;
+	buf[3] = 0;
+	buf[4] = (address >> 24) & 0xff;
+	buf[5] = (address >> 16) & 0xff;
+	buf[6] = (address >> 8)  & 0xff;
+	buf[7] =  address        & 0xff;
 
 	if ((ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x01),buf,8,&actlen,1000)) < 0) {
 		deb_fw("jumpram to 0x%x failed\n",address);
-		return ret;
+		goto out;
 	}
 	if (actlen != 8) {
 		deb_fw("jumpram to 0x%x failed\n",address);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
-	return 0;
+out:
+	kfree(buf);
+	return ret;
 }
 
 int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw)
 {
 	struct hexline hx;
 	int pos = 0, ret, act_len, i, adap_num;
-	u8 b[16];
+	u8 *buf;
 	u32 fw_version;
 
-	u8 buf[260];
+	buf = kmalloc(260, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
 
 	while ((ret = dvb_usb_get_hexline(fw, &hx, &pos)) > 0) {
 		deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n",
@@ -411,7 +454,7 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
 
 		if (ret < 0) {
 			err("firmware download failed at %d with %d",pos,ret);
-			return ret;
+			goto out;
 		}
 	}
 
@@ -432,8 +475,8 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
 	usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
 				  REQUEST_GET_VERSION,
 				  USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
-				  b, sizeof(b), USB_CTRL_GET_TIMEOUT);
-	fw_version = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
+				  buf, 16, USB_CTRL_GET_TIMEOUT);
+	fw_version = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11];
 
 	/* set the buffer size - DVB-USB is allocating URB buffers
 	 * only after the firwmare download was successful */
@@ -451,14 +494,14 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
 			}
 		}
 	}
-
+out:
+	kfree(buf);
 	return ret;
 }
 
 int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
 	struct dib0700_state *st = adap->dev->priv;
-	u8 b[4];
 	int ret;
 
 	if ((onoff != 0) && (st->fw_version >= 0x10201)) {
@@ -472,15 +515,17 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 		}
 	}
 
-	b[0] = REQUEST_ENABLE_VIDEO;
-	b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */
+	st->buf[0] = REQUEST_ENABLE_VIDEO;
+	/* this bit gives a kind of command,
+	 * rather than enabling something or not */
+	st->buf[1] = (onoff << 4) | 0x00;
 
 	if (st->disable_streaming_master_mode == 1)
-		b[2] = 0x00;
+		st->buf[2] = 0x00;
 	else
-		b[2] = 0x01 << 4; /* Master mode */
+		st->buf[2] = 0x01 << 4; /* Master mode */
 
-	b[3] = 0x00;
+	st->buf[3] = 0x00;
 
 	deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id);
 
@@ -499,20 +544,23 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 			st->channel_state |=	1 << (3-adap->stream.props.endpoint);
 	}
 
-	b[2] |= st->channel_state;
+	st->buf[2] |= st->channel_state;
 
-	deb_info("data for streaming: %x %x\n", b[1], b[2]);
+	deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]);
 
-	return dib0700_ctrl_wr(adap->dev, b, 4);
+	return dib0700_ctrl_wr(adap->dev, st->buf, 4);
 }
 
 int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
 {
 	struct dvb_usb_device *d = rc->priv;
 	struct dib0700_state *st = d->priv;
-	u8 rc_setup[3] = { REQUEST_SET_RC, 0, 0 };
 	int new_proto, ret;
 
+	st->buf[0] = REQUEST_SET_RC;
+	st->buf[1] = 0;
+	st->buf[2] = 0;
+
 	/* Set the IR mode */
 	if (rc_type == RC_TYPE_RC5)
 		new_proto = 1;
@@ -526,9 +574,9 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
 	} else
 		return -EINVAL;
 
-	rc_setup[1] = new_proto;
+	st->buf[1] = new_proto;
 
-	ret = dib0700_ctrl_wr(d, rc_setup, sizeof(rc_setup));
+	ret = dib0700_ctrl_wr(d, st->buf, 3);
 	if (ret < 0) {
 		err("ir protocol setup failed");
 		return ret;
@@ -561,7 +609,6 @@ struct dib0700_rc_response {
 static void dib0700_rc_urb_completion(struct urb *purb)
 {
 	struct dvb_usb_device *d = purb->context;
-	struct dib0700_state *st;
 	struct dib0700_rc_response *poll_reply;
 	u32 uninitialized_var(keycode);
 	u8 toggle;
@@ -576,7 +623,6 @@ static void dib0700_rc_urb_completion(struct urb *purb)
 		return;
 	}
 
-	st = d->priv;
 	poll_reply = purb->transfer_buffer;
 
 	if (purb->status < 0) {

+ 6 - 2
drivers/media/dvb/dvb-usb/dib0700_devices.c

@@ -2439,7 +2439,6 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
 
 	dib0700_set_i2c_speed(adap->dev, 340);
 	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
-
 	if (adap->fe == NULL)
 		return -ENODEV;
 
@@ -2802,6 +2801,7 @@ struct usb_device_id dib0700_usb_id_table[] = {
 	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_NIM7090) },
 	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_TFE7090PVR) },
 	{ USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2) },
+/* 75 */{ USB_DEVICE(USB_VID_MEDION,    USB_PID_CREATIX_CTX1921) },
 	{ 0 }		/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -3411,7 +3411,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			},
 		},
 
-		.num_device_descs = 3,
+		.num_device_descs = 4,
 		.devices = {
 			{   "DiBcom STK7770P reference design",
 				{ &dib0700_usb_id_table[59], NULL },
@@ -3427,6 +3427,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 				{ &dib0700_usb_id_table[74], NULL },
 				{ NULL },
 			},
+			{   "Medion CTX1921 DVB-T USB",
+				{ &dib0700_usb_id_table[75], NULL },
+				{ NULL },
+			},
 		},
 
 		.rc.core = {

+ 1 - 1
drivers/media/dvb/dvb-usb/dibusb-common.c

@@ -408,7 +408,7 @@ struct rc_map_table rc_map_dibusb_table[] = {
 
 	{ 0x8008, KEY_DVD },
 	{ 0x8009, KEY_AUDIO },
-	{ 0x800a, KEY_MEDIA },      /* Pictures */
+	{ 0x800a, KEY_IMAGES },      /* Pictures */
 	{ 0x800b, KEY_VIDEO },
 
 	{ 0x800c, KEY_BACK },

+ 21 - 10
drivers/media/dvb/dvb-usb/dvb-usb-dvb.c

@@ -12,7 +12,7 @@
 static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
 {
 	struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
-	int newfeedcount,ret;
+	int newfeedcount, ret;
 
 	if (adap == NULL)
 		return -ENODEV;
@@ -24,9 +24,13 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
 		deb_ts("stop feeding\n");
 		usb_urb_kill(&adap->stream);
 
-		if (adap->props.streaming_ctrl != NULL)
-			if ((ret = adap->props.streaming_ctrl(adap,0)))
+		if (adap->props.streaming_ctrl != NULL) {
+			ret = adap->props.streaming_ctrl(adap, 0);
+			if (ret < 0) {
 				err("error while stopping stream.");
+				return ret;
+			}
+		}
 	}
 
 	adap->feedcount = newfeedcount;
@@ -49,17 +53,24 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
 
 		deb_ts("controlling pid parser\n");
 		if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER &&
-			adap->props.caps & DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
-			adap->props.pid_filter_ctrl != NULL)
-			if (adap->props.pid_filter_ctrl(adap,adap->pid_filtering) < 0)
+			adap->props.caps &
+			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
+			adap->props.pid_filter_ctrl != NULL) {
+			ret = adap->props.pid_filter_ctrl(adap,
+				adap->pid_filtering);
+			if (ret < 0) {
 				err("could not handle pid_parser");
-
+				return ret;
+			}
+		}
 		deb_ts("start feeding\n");
-		if (adap->props.streaming_ctrl != NULL)
-			if (adap->props.streaming_ctrl(adap,1)) {
+		if (adap->props.streaming_ctrl != NULL) {
+			ret = adap->props.streaming_ctrl(adap, 1);
+			if (ret < 0) {
 				err("error while enabling fifo.");
-				return -ENODEV;
+				return ret;
 			}
+		}
 
 	}
 	return 0;

+ 1 - 0
drivers/media/dvb/dvb-usb/dvb-usb-ids.h

@@ -91,6 +91,7 @@
 #define USB_PID_COMPRO_VIDEOMATE_U500_PC		0x1e80
 #define USB_PID_CONCEPTRONIC_CTVDIGRCU			0xe397
 #define USB_PID_CONEXANT_D680_DMB			0x86d6
+#define USB_PID_CREATIX_CTX1921				0x1921
 #define USB_PID_DIBCOM_HOOK_DEFAULT			0x0064
 #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM		0x0065
 #define USB_PID_DIBCOM_MOD3000_COLD			0x0bb8

+ 8 - 2
drivers/media/dvb/dvb-usb/dw2102.c

@@ -121,12 +121,16 @@ static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
 			u16 index, u8 * data, u16 len, int flags)
 {
 	int ret;
-	u8 u8buf[len];
-
+	u8 *u8buf;
 	unsigned int pipe = (flags == DW210X_READ_MSG) ?
 				usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
 	u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
 
+	u8buf = kmalloc(len, GFP_KERNEL);
+	if (!u8buf)
+		return -ENOMEM;
+
+
 	if (flags == DW210X_WRITE_MSG)
 		memcpy(u8buf, data, len);
 	ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
@@ -134,6 +138,8 @@ static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
 
 	if (flags == DW210X_READ_MSG)
 		memcpy(data, u8buf, len);
+
+	kfree(u8buf);
 	return ret;
 }
 

+ 15 - 3
drivers/media/dvb/dvb-usb/ec168.c

@@ -36,7 +36,9 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
 	int ret;
 	unsigned int pipe;
 	u8 request, requesttype;
-	u8 buf[req->size];
+	u8 *buf;
+
+
 
 	switch (req->cmd) {
 	case DOWNLOAD_FIRMWARE:
@@ -72,6 +74,12 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
 		goto error;
 	}
 
+	buf = kmalloc(req->size, GFP_KERNEL);
+	if (!buf) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
 	if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) {
 		/* write */
 		memcpy(buf, req->data, req->size);
@@ -84,13 +92,13 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
 	msleep(1); /* avoid I2C errors */
 
 	ret = usb_control_msg(udev, pipe, request, requesttype, req->value,
-		req->index, buf, sizeof(buf), EC168_USB_TIMEOUT);
+		req->index, buf, req->size, EC168_USB_TIMEOUT);
 
 	ec168_debug_dump(request, requesttype, req->value, req->index, buf,
 		req->size, deb_xfer);
 
 	if (ret < 0)
-		goto error;
+		goto err_dealloc;
 	else
 		ret = 0;
 
@@ -98,7 +106,11 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
 	if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
 		memcpy(req->data, buf, req->size);
 
+	kfree(buf);
 	return ret;
+
+err_dealloc:
+	kfree(buf);
 error:
 	deb_info("%s: failed:%d\n", __func__, ret);
 	return ret;

+ 19 - 4
drivers/media/dvb/dvb-usb/friio.c

@@ -142,17 +142,20 @@ static u32 gl861_i2c_func(struct i2c_adapter *adapter)
 	return I2C_FUNC_I2C;
 }
 
-
 static int friio_ext_ctl(struct dvb_usb_adapter *adap,
 			 u32 sat_color, int lnb_on)
 {
 	int i;
 	int ret;
 	struct i2c_msg msg;
-	u8 buf[2];
+	u8 *buf;
 	u32 mask;
 	u8 lnb = (lnb_on) ? FRIIO_CTL_LNB : 0;
 
+	buf = kmalloc(2, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
 	msg.addr = 0x00;
 	msg.flags = 0;
 	msg.len = 2;
@@ -189,6 +192,7 @@ static int friio_ext_ctl(struct dvb_usb_adapter *adap,
 	buf[1] |= FRIIO_CTL_CLK;
 	ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
 
+	kfree(buf);
 	return (ret == 70);
 }
 
@@ -219,11 +223,20 @@ static int friio_initialize(struct dvb_usb_device *d)
 	int ret;
 	int i;
 	int retry = 0;
-	u8 rbuf[2];
-	u8 wbuf[3];
+	u8 *rbuf, *wbuf;
 
 	deb_info("%s called.\n", __func__);
 
+	wbuf = kmalloc(3, GFP_KERNEL);
+	if (!wbuf)
+		return -ENOMEM;
+
+	rbuf = kmalloc(2, GFP_KERNEL);
+	if (!rbuf) {
+		kfree(wbuf);
+		return -ENOMEM;
+	}
+
 	/* use gl861_i2c_msg instead of gl861_i2c_xfer(), */
 	/* because the i2c device is not set up yet. */
 	wbuf[0] = 0x11;
@@ -358,6 +371,8 @@ restart:
 	return 0;
 
 error:
+	kfree(wbuf);
+	kfree(rbuf);
 	deb_info("%s:ret == %d\n", __func__, ret);
 	return -EIO;
 }

+ 136 - 29
drivers/media/dvb/dvb-usb/lmedm04.c

@@ -62,8 +62,6 @@
  *	LME2510: SHARP:BS2F7HZ0194(MV0194) cannot cold reset and share system
  * with other tuners. After a cold reset streaming will not start.
  *
- *	PID functions have been removed from this driver version due to
- * problems with different firmware and application versions.
  */
 #define DVB_USB_LOG_PREFIX "LME2510(C)"
 #include <linux/usb.h>
@@ -104,6 +102,10 @@ static int dvb_usb_lme2510_firmware;
 module_param_named(firmware, dvb_usb_lme2510_firmware, int, 0644);
 MODULE_PARM_DESC(firmware, "set default firmware 0=Sharp7395 1=LG");
 
+static int pid_filter;
+module_param_named(pid, pid_filter, int, 0644);
+MODULE_PARM_DESC(pid, "set default 0=on 1=off");
+
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
@@ -125,6 +127,7 @@ struct lme2510_state {
 	u8 i2c_tuner_gate_r;
 	u8 i2c_tuner_addr;
 	u8 stream_on;
+	u8 pid_size;
 	void *buffer;
 	struct urb *lme_urb;
 	void *usb_buffer;
@@ -167,14 +170,14 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
 	}
 	buff = st->usb_buffer;
 
-	/* the read/write capped at 512 */
-	memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen);
-
 	ret = mutex_lock_interruptible(&d->usb_mutex);
 
 	if (ret < 0)
 		return -EAGAIN;
 
+	/* the read/write capped at 512 */
+	memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen);
+
 	ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01));
 
 	ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01);
@@ -216,6 +219,37 @@ static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u32 keypress)
 	return 0;
 }
 
+static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out)
+{
+	struct lme2510_state *st = d->priv;
+	static u8 pid_buff[] = LME_ZERO_PID;
+	static u8 rbuf[1];
+	u8 pid_no = index * 2;
+	u8 pid_len = pid_no + 2;
+	int ret = 0;
+	deb_info(1, "PID Setting Pid %04x", pid_out);
+
+	if (st->pid_size == 0)
+		ret |= lme2510_stream_restart(d);
+
+	pid_buff[2] = pid_no;
+	pid_buff[3] = (u8)pid_out & 0xff;
+	pid_buff[4] = pid_no + 1;
+	pid_buff[5] = (u8)(pid_out >> 8);
+
+	if (pid_len > st->pid_size)
+		st->pid_size = pid_len;
+	pid_buff[7] = 0x80 + st->pid_size;
+
+	ret |= lme2510_usb_talk(d, pid_buff ,
+		sizeof(pid_buff) , rbuf, sizeof(rbuf));
+
+	if (st->stream_on)
+		ret |= lme2510_stream_restart(d);
+
+	return ret;
+}
+
 static void lme2510_int_response(struct urb *lme_urb)
 {
 	struct dvb_usb_adapter *adap = lme_urb->context;
@@ -326,16 +360,68 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap)
 	return 0;
 }
 
+static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	struct lme2510_state *st = adap->dev->priv;
+	static u8 clear_pid_reg[] = LME_CLEAR_PID;
+	static u8 rbuf[1];
+	int ret;
+
+	deb_info(1, "PID Clearing Filter");
+
+	ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
+	if (ret < 0)
+		return -EAGAIN;
+
+	if (!onoff)
+		ret |= lme2510_usb_talk(adap->dev, clear_pid_reg,
+			sizeof(clear_pid_reg), rbuf, sizeof(rbuf));
+
+	st->pid_size = 0;
+
+	mutex_unlock(&adap->dev->i2c_mutex);
+
+	return 0;
+}
+
+static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
+	int onoff)
+{
+	int ret = 0;
+
+	deb_info(3, "%s PID=%04x Index=%04x onoff=%02x", __func__,
+		pid, index, onoff);
+
+	if (onoff)
+		if (!pid_filter) {
+			ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
+			if (ret < 0)
+				return -EAGAIN;
+			ret |= lme2510_enable_pid(adap->dev, index, pid);
+			mutex_unlock(&adap->dev->i2c_mutex);
+	}
+
+
+	return ret;
+}
+
+
 static int lme2510_return_status(struct usb_device *dev)
 {
 	int ret = 0;
-	u8 data[10] = {0};
+	u8 *data;
+
+	data = kzalloc(10, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	ret |= usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 			0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200);
 	info("Firmware Status: %x (%x)", ret , data[2]);
 
-	return (ret < 0) ? -ENODEV : data[2];
+	ret = (ret < 0) ? -ENODEV : data[2];
+	kfree(data);
+	return ret;
 }
 
 static int lme2510_msg(struct dvb_usb_device *d,
@@ -591,9 +677,10 @@ static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 	else {
 		deb_info(1, "STM Steam Off");
 		/* mutex is here only to avoid collision with I2C */
-		ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
+		if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
+			return -EAGAIN;
 
-		ret |= lme2510_usb_talk(adap->dev, clear_reg_3,
+		ret = lme2510_usb_talk(adap->dev, clear_reg_3,
 				sizeof(clear_reg_3), rbuf, rlen);
 		st->stream_on = 0;
 		st->i2c_talk_onoff = 1;
@@ -655,7 +742,7 @@ static int lme2510_download_firmware(struct usb_device *dev,
 					const struct firmware *fw)
 {
 	int ret = 0;
-	u8 data[512] = {0};
+	u8 *data;
 	u16 j, wlen, len_in, start, end;
 	u8 packet_size, dlen, i;
 	u8 *fw_data;
@@ -663,6 +750,11 @@ static int lme2510_download_firmware(struct usb_device *dev,
 	packet_size = 0x31;
 	len_in = 1;
 
+	data = kzalloc(512, GFP_KERNEL);
+	if (!data) {
+		info("FRM Could not start Firmware Download (Buffer allocation failed)");
+		return -ENOMEM;
+	}
 
 	info("FRM Starting Firmware Download");
 
@@ -678,15 +770,15 @@ static int lme2510_download_firmware(struct usb_device *dev,
 				data[0] = i | 0x80;
 				dlen = (u8)(end - j)-1;
 			}
-		data[1] = dlen;
-		memcpy(&data[2], fw_data, dlen+1);
-		wlen = (u8) dlen + 4;
-		data[wlen-1] = check_sum(fw_data, dlen+1);
-		deb_info(1, "Data S=%02x:E=%02x CS= %02x", data[3],
+			data[1] = dlen;
+			memcpy(&data[2], fw_data, dlen+1);
+			wlen = (u8) dlen + 4;
+			data[wlen-1] = check_sum(fw_data, dlen+1);
+			deb_info(1, "Data S=%02x:E=%02x CS= %02x", data[3],
 				data[dlen+2], data[dlen+3]);
-		ret |= lme2510_bulk_write(dev, data,  wlen, 1);
-		ret |= lme2510_bulk_read(dev, data, len_in , 1);
-		ret |= (data[0] == 0x88) ? 0 : -1;
+			ret |= lme2510_bulk_write(dev, data,  wlen, 1);
+			ret |= lme2510_bulk_read(dev, data, len_in , 1);
+			ret |= (data[0] == 0x88) ? 0 : -1;
 		}
 	}
 
@@ -706,7 +798,7 @@ static int lme2510_download_firmware(struct usb_device *dev,
 	else
 		info("FRM Firmware Download Completed - Resetting Device");
 
-
+	kfree(data);
 	return (ret < 0) ? -ENODEV : 0;
 }
 
@@ -747,7 +839,7 @@ static int lme_firmware_switch(struct usb_device *udev, int cold)
 			fw_lme = fw_s0194;
 			ret = request_firmware(&fw, fw_lme, &udev->dev);
 			if (ret == 0) {
-				cold = 0;/*lme2510-s0194 cannot cold reset*/
+				cold = 0;
 				break;
 			}
 			dvb_usb_lme2510_firmware = TUNER_LG;
@@ -769,8 +861,10 @@ static int lme_firmware_switch(struct usb_device *udev, int cold)
 		case TUNER_S7395:
 			fw_lme = fw_c_s7395;
 			ret = request_firmware(&fw, fw_lme, &udev->dev);
-			if (ret == 0)
+			if (ret == 0) {
+				cold = 0;
 				break;
+			}
 			dvb_usb_lme2510_firmware = TUNER_LG;
 		case TUNER_LG:
 			fw_lme = fw_c_lg;
@@ -796,14 +890,14 @@ static int lme_firmware_switch(struct usb_device *udev, int cold)
 		ret = lme2510_download_firmware(udev, fw);
 	}
 
+	release_firmware(fw);
+
 	if (cold) {
 		info("FRM Changing to %s firmware", fw_lme);
 		lme_coldreset(udev);
 		return -ENODEV;
 	}
 
-	release_firmware(fw);
-
 	return ret;
 }
 
@@ -1017,12 +1111,13 @@ static int lme2510_powerup(struct dvb_usb_device *d, int onoff)
 	static u8 rbuf[1];
 	int ret, len = 3, rlen = 1;
 
-	ret = mutex_lock_interruptible(&d->i2c_mutex);
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
 
 	if (onoff)
-		ret |= lme2510_usb_talk(d, lnb_on, len, rbuf, rlen);
+		ret = lme2510_usb_talk(d, lnb_on, len, rbuf, rlen);
 	else
-		ret |= lme2510_usb_talk(d, lnb_off, len, rbuf, rlen);
+		ret = lme2510_usb_talk(d, lnb_off, len, rbuf, rlen);
 
 	st->i2c_talk_onoff = 1;
 
@@ -1086,7 +1181,13 @@ static struct dvb_usb_device_properties lme2510_properties = {
 	.num_adapters = 1,
 	.adapter = {
 		{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER|
+				DVB_USB_ADAP_NEED_PID_FILTERING|
+				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 			.streaming_ctrl   = lme2510_streaming_ctrl,
+			.pid_filter_count = 15,
+			.pid_filter = lme2510_pid_filter,
+			.pid_filter_ctrl  = lme2510_pid_filter_ctrl,
 			.frontend_attach  = dm04_lme2510_frontend_attach,
 			.tuner_attach = dm04_lme2510_tuner,
 			/* parameter for the MPEG2-data transfer */
@@ -1122,7 +1223,13 @@ static struct dvb_usb_device_properties lme2510c_properties = {
 	.num_adapters = 1,
 	.adapter = {
 		{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER|
+				DVB_USB_ADAP_NEED_PID_FILTERING|
+				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 			.streaming_ctrl   = lme2510_streaming_ctrl,
+			.pid_filter_count = 15,
+			.pid_filter = lme2510_pid_filter,
+			.pid_filter_ctrl  = lme2510_pid_filter_ctrl,
 			.frontend_attach  = dm04_lme2510_frontend_attach,
 			.tuner_attach = dm04_lme2510_tuner,
 			/* parameter for the MPEG2-data transfer */
@@ -1151,7 +1258,7 @@ static struct dvb_usb_device_properties lme2510c_properties = {
 	}
 };
 
-void *lme2510_exit_int(struct dvb_usb_device *d)
+static void *lme2510_exit_int(struct dvb_usb_device *d)
 {
 	struct lme2510_state *st = d->priv;
 	struct dvb_usb_adapter *adap = &d->adapter[0];
@@ -1178,7 +1285,7 @@ void *lme2510_exit_int(struct dvb_usb_device *d)
 	return buffer;
 }
 
-void lme2510_exit(struct usb_interface *intf)
+static void lme2510_exit(struct usb_interface *intf)
 {
 	struct dvb_usb_device *d = usb_get_intfdata(intf);
 	void *usb_buffer;
@@ -1220,5 +1327,5 @@ module_exit(lme2510_module_exit);
 
 MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
 MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
-MODULE_VERSION("1.80");
+MODULE_VERSION("1.86");
 MODULE_LICENSE("GPL");

+ 3 - 2
drivers/media/dvb/dvb-usb/lmedm04.h

@@ -40,6 +40,7 @@
 */
 #define LME_ST_ON_W	{0x06, 0x00}
 #define LME_CLEAR_PID   {0x03, 0x02, 0x20, 0xa0}
+#define LME_ZERO_PID	{0x03, 0x06, 0x00, 0x00, 0x01, 0x00, 0x20, 0x9c}
 
 /*  LNB Voltage
  *  07 XX XX
@@ -108,14 +109,14 @@ static u8 s7395_inittab[] = {
 	0x3d, 0x30,
 	0x40, 0x63,
 	0x41, 0x04,
-	0x42, 0x60,
+	0x42, 0x20,
 	0x43, 0x00,
 	0x44, 0x00,
 	0x45, 0x00,
 	0x46, 0x00,
 	0x47, 0x00,
 	0x4a, 0x00,
-	0x50, 0x12,
+	0x50, 0x10,
 	0x51, 0x36,
 	0x52, 0x21,
 	0x53, 0x94,

+ 30 - 19
drivers/media/dvb/dvb-usb/m920x.c

@@ -134,13 +134,17 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
 	struct m920x_state *m = d->priv;
 	int i, ret = 0;
-	u8 rc_state[2];
+	u8 *rc_state;
+
+	rc_state = kmalloc(2, GFP_KERNEL);
+	if (!rc_state)
+		return -ENOMEM;
 
 	if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0)
-		goto unlock;
+		goto out;
 
 	if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
-		goto unlock;
+		goto out;
 
 	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
 		if (rc5_data(&d->props.rc.legacy.rc_map_table[i]) == rc_state[1]) {
@@ -149,7 +153,7 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 			switch(rc_state[0]) {
 			case 0x80:
 				*state = REMOTE_NO_KEY_PRESSED;
-				goto unlock;
+				goto out;
 
 			case 0x88: /* framing error or "invalid code" */
 			case 0x99:
@@ -157,7 +161,7 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 			case 0xd8:
 				*state = REMOTE_NO_KEY_PRESSED;
 				m->rep_count = 0;
-				goto unlock;
+				goto out;
 
 			case 0x93:
 			case 0x92:
@@ -165,7 +169,7 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 			case 0x82:
 				m->rep_count = 0;
 				*state = REMOTE_KEY_PRESSED;
-				goto unlock;
+				goto out;
 
 			case 0x91:
 			case 0x81: /* pinnacle PCTV310e */
@@ -174,12 +178,12 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 					*state = REMOTE_KEY_REPEAT;
 				else
 					*state = REMOTE_NO_KEY_PRESSED;
-				goto unlock;
+				goto out;
 
 			default:
 				deb("Unexpected rc state %02x\n", rc_state[0]);
 				*state = REMOTE_NO_KEY_PRESSED;
-				goto unlock;
+				goto out;
 			}
 		}
 
@@ -188,8 +192,8 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 
 	*state = REMOTE_NO_KEY_PRESSED;
 
- unlock:
-
+ out:
+	kfree(rc_state);
 	return ret;
 }
 
@@ -339,13 +343,19 @@ static int m920x_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, in
 static int m920x_firmware_download(struct usb_device *udev, const struct firmware *fw)
 {
 	u16 value, index, size;
-	u8 read[4], *buff;
+	u8 *read, *buff;
 	int i, pass, ret = 0;
 
 	buff = kmalloc(65536, GFP_KERNEL);
 	if (buff == NULL)
 		return -ENOMEM;
 
+	read = kmalloc(4, GFP_KERNEL);
+	if (!read) {
+		kfree(buff);
+		return -ENOMEM;
+	}
+
 	if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0)
 		goto done;
 	deb("%x %x %x %x\n", read[0], read[1], read[2], read[3]);
@@ -396,6 +406,7 @@ static int m920x_firmware_download(struct usb_device *udev, const struct firmwar
 	deb("firmware uploaded!\n");
 
  done:
+	kfree(read);
 	kfree(buff);
 
 	return ret;
@@ -632,9 +643,9 @@ static struct rc_map_table rc_map_pinnacle310e_table[] = {
 	{ 0x16, KEY_POWER },
 	{ 0x17, KEY_FAVORITES },
 	{ 0x0f, KEY_TEXT },
-	{ 0x48, KEY_MEDIA },		/* preview */
+	{ 0x48, KEY_PROGRAM },		/* preview */
 	{ 0x1c, KEY_EPG },
-	{ 0x04, KEY_LIST },			/* record list */
+	{ 0x04, KEY_LIST },		/* record list */
 	{ 0x03, KEY_1 },
 	{ 0x01, KEY_2 },
 	{ 0x06, KEY_3 },
@@ -674,14 +685,14 @@ static struct rc_map_table rc_map_pinnacle310e_table[] = {
 	{ 0x0e, KEY_MUTE },
 /*	{ 0x49, KEY_LR },	*/		/* L/R */
 	{ 0x07, KEY_SLEEP },		/* Hibernate */
-	{ 0x08, KEY_MEDIA },		/* A/V */
-	{ 0x0e, KEY_MENU },			/* Recall */
+	{ 0x08, KEY_VIDEO },		/* A/V */
+	{ 0x0e, KEY_MENU },		/* Recall */
 	{ 0x45, KEY_ZOOMIN },
 	{ 0x46, KEY_ZOOMOUT },
-	{ 0x18, KEY_TV },			/* Red */
-	{ 0x53, KEY_VCR },			/* Green */
-	{ 0x5e, KEY_SAT },			/* Yellow */
-	{ 0x5f, KEY_PLAYER },		/* Blue */
+	{ 0x18, KEY_RED },		/* Red */
+	{ 0x53, KEY_GREEN },		/* Green */
+	{ 0x5e, KEY_YELLOW },		/* Yellow */
+	{ 0x5f, KEY_BLUE },		/* Blue */
 };
 
 /* DVB USB Driver stuff */

+ 1 - 1
drivers/media/dvb/dvb-usb/nova-t-usb2.c

@@ -47,7 +47,7 @@ static struct rc_map_table rc_map_haupp_table[] = {
 	{ 0x1e17, KEY_RIGHT },
 	{ 0x1e18, KEY_VIDEO },
 	{ 0x1e19, KEY_AUDIO },
-	{ 0x1e1a, KEY_MEDIA },
+	{ 0x1e1a, KEY_IMAGES },
 	{ 0x1e1b, KEY_EPG },
 	{ 0x1e1c, KEY_TV },
 	{ 0x1e1e, KEY_NEXT },

+ 21 - 12
drivers/media/dvb/dvb-usb/opera1.c

@@ -53,27 +53,36 @@ static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value,
 			    u8 * data, u16 len, int flags)
 {
 	int ret;
-	u8 r;
-	u8 u8buf[len];
-
+	u8 tmp;
+	u8 *buf;
 	unsigned int pipe = (flags == OPERA_READ_MSG) ?
 		usb_rcvctrlpipe(dev,0) : usb_sndctrlpipe(dev, 0);
 	u8 request_type = (flags == OPERA_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
 
+	buf = kmalloc(len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
 	if (flags == OPERA_WRITE_MSG)
-		memcpy(u8buf, data, len);
-	ret =
-		usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
-			value, 0x0, u8buf, len, 2000);
+		memcpy(buf, data, len);
+	ret = usb_control_msg(dev, pipe, request,
+			request_type | USB_TYPE_VENDOR, value, 0x0,
+			buf, len, 2000);
 
 	if (request == OPERA_TUNER_REQ) {
+		tmp = buf[0];
 		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-				OPERA_TUNER_REQ, USB_DIR_IN | USB_TYPE_VENDOR,
-				0x01, 0x0, &r, 1, 2000)<1 || r!=0x08)
-					return 0;
+			    OPERA_TUNER_REQ, USB_DIR_IN | USB_TYPE_VENDOR,
+			    0x01, 0x0, buf, 1, 2000) < 1 || buf[0] != 0x08) {
+			ret = 0;
+			goto out;
+		}
+		buf[0] = tmp;
 	}
 	if (flags == OPERA_READ_MSG)
-		memcpy(data, u8buf, len);
+		memcpy(data, buf, len);
+out:
+	kfree(buf);
 	return ret;
 }
 
@@ -189,7 +198,7 @@ static int opera1_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate,
 static u8 opera1_inittab[] = {
 	0x00, 0xa1,
 	0x01, 0x15,
-	0x02, 0x00,
+	0x02, 0x30,
 	0x03, 0x00,
 	0x04, 0x7d,
 	0x05, 0x05,

+ 59 - 21
drivers/media/dvb/dvb-usb/vp702x-fe.c

@@ -41,14 +41,23 @@ struct vp702x_fe_state {
 
 static int vp702x_fe_refresh_state(struct vp702x_fe_state *st)
 {
-	u8 buf[10];
-	if (time_after(jiffies,st->next_status_check)) {
-		vp702x_usb_in_op(st->d,READ_STATUS,0,0,buf,10);
+	struct vp702x_device_state *dst = st->d->priv;
+	u8 *buf;
 
+	if (time_after(jiffies, st->next_status_check)) {
+		mutex_lock(&dst->buf_mutex);
+		buf = dst->buf;
+
+		vp702x_usb_in_op(st->d, READ_STATUS, 0, 0, buf, 10);
 		st->lock = buf[4];
-		vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x11,0,&st->snr,1);
-		vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x15,0,&st->sig,1);
 
+		vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x11, 0, buf, 1);
+		st->snr = buf[0];
+
+		vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x15, 0, buf, 1);
+		st->sig = buf[0];
+
+		mutex_unlock(&dst->buf_mutex);
 		st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
 	}
 	return 0;
@@ -130,11 +139,17 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
 				  struct dvb_frontend_parameters *fep)
 {
 	struct vp702x_fe_state *st = fe->demodulator_priv;
+	struct vp702x_device_state *dst = st->d->priv;
 	u32 freq = fep->frequency/1000;
 	/*CalFrequency*/
 /*	u16 frequencyRef[16] = { 2, 4, 8, 16, 32, 64, 128, 256, 24, 5, 10, 20, 40, 80, 160, 320 }; */
 	u64 sr;
-	u8 cmd[8] = { 0 },ibuf[10];
+	u8 *cmd;
+
+	mutex_lock(&dst->buf_mutex);
+
+	cmd = dst->buf;
+	memset(cmd, 0, 10);
 
 	cmd[0] = (freq >> 8) & 0x7f;
 	cmd[1] =  freq       & 0xff;
@@ -170,13 +185,15 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
 	st->status_check_interval = 250;
 	st->next_status_check = jiffies;
 
-	vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
+	vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100);
 
-	if (ibuf[2] == 0 && ibuf[3] == 0)
+	if (cmd[2] == 0 && cmd[3] == 0)
 		deb_fe("tuning failed.\n");
 	else
 		deb_fe("tuning succeeded.\n");
 
+	mutex_unlock(&dst->buf_mutex);
+
 	return 0;
 }
 
@@ -204,27 +221,32 @@ static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
 static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
 				    struct dvb_diseqc_master_cmd *m)
 {
+	u8 *cmd;
 	struct vp702x_fe_state *st = fe->demodulator_priv;
-	u8 cmd[8],ibuf[10];
-	memset(cmd,0,8);
+	struct vp702x_device_state *dst = st->d->priv;
 
 	deb_fe("%s\n",__func__);
 
 	if (m->msg_len > 4)
 		return -EINVAL;
 
+	mutex_lock(&dst->buf_mutex);
+
+	cmd = dst->buf;
 	cmd[1] = SET_DISEQC_CMD;
 	cmd[2] = m->msg_len;
 	memcpy(&cmd[3], m->msg, m->msg_len);
-	cmd[7] = vp702x_chksum(cmd,0,7);
+	cmd[7] = vp702x_chksum(cmd, 0, 7);
 
-	vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
+	vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100);
 
-	if (ibuf[2] == 0 && ibuf[3] == 0)
+	if (cmd[2] == 0 && cmd[3] == 0)
 		deb_fe("diseqc cmd failed.\n");
 	else
 		deb_fe("diseqc cmd succeeded.\n");
 
+	mutex_unlock(&dst->buf_mutex);
+
 	return 0;
 }
 
@@ -237,7 +259,9 @@ static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd
 static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 {
 	struct vp702x_fe_state *st = fe->demodulator_priv;
-	u8 ibuf[10];
+	struct vp702x_device_state *dst = st->d->priv;
+	u8 *buf;
+
 	deb_fe("%s\n",__func__);
 
 	st->tone_mode = tone;
@@ -247,14 +271,21 @@ static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 	else
 		st->lnb_buf[2] = 0x00;
 
-	st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7);
+	st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7);
+
+	mutex_lock(&dst->buf_mutex);
+
+	buf = dst->buf;
+	memcpy(buf, st->lnb_buf, 8);
 
-	vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100);
-	if (ibuf[2] == 0 && ibuf[3] == 0)
+	vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100);
+	if (buf[2] == 0 && buf[3] == 0)
 		deb_fe("set_tone cmd failed.\n");
 	else
 		deb_fe("set_tone cmd succeeded.\n");
 
+	mutex_unlock(&dst->buf_mutex);
+
 	return 0;
 }
 
@@ -262,7 +293,8 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
 		voltage)
 {
 	struct vp702x_fe_state *st = fe->demodulator_priv;
-	u8 ibuf[10];
+	struct vp702x_device_state *dst = st->d->priv;
+	u8 *buf;
 	deb_fe("%s\n",__func__);
 
 	st->voltage = voltage;
@@ -272,14 +304,20 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
 	else
 		st->lnb_buf[4] = 0x00;
 
-	st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7);
+	st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7);
+
+	mutex_lock(&dst->buf_mutex);
+
+	buf = dst->buf;
+	memcpy(buf, st->lnb_buf, 8);
 
-	vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100);
-	if (ibuf[2] == 0 && ibuf[3] == 0)
+	vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100);
+	if (buf[2] == 0 && buf[3] == 0)
 		deb_fe("set_voltage cmd failed.\n");
 	else
 		deb_fe("set_voltage cmd succeeded.\n");
 
+	mutex_unlock(&dst->buf_mutex);
 	return 0;
 }
 

+ 167 - 46
drivers/media/dvb/dvb-usb/vp702x.c

@@ -15,6 +15,7 @@
  * see Documentation/dvb/README.dvb-usb for more information
  */
 #include "vp702x.h"
+#include <linux/mutex.h>
 
 /* debug */
 int dvb_usb_vp702x_debug;
@@ -23,27 +24,23 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DV
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-struct vp702x_state {
+struct vp702x_adapter_state {
 	int pid_filter_count;
 	int pid_filter_can_bypass;
 	u8  pid_filter_state;
 };
 
-struct vp702x_device_state {
-	u8 power_state;
-};
-
-/* check for mutex FIXME */
-int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+static int vp702x_usb_in_op_unlocked(struct dvb_usb_device *d, u8 req,
+				     u16 value, u16 index, u8 *b, int blen)
 {
-	int ret = -1;
+	int ret;
 
-		ret = usb_control_msg(d->udev,
-			usb_rcvctrlpipe(d->udev,0),
-			req,
-			USB_TYPE_VENDOR | USB_DIR_IN,
-			value,index,b,blen,
-			2000);
+	ret = usb_control_msg(d->udev,
+		usb_rcvctrlpipe(d->udev, 0),
+		req,
+		USB_TYPE_VENDOR | USB_DIR_IN,
+		value, index, b, blen,
+		2000);
 
 	if (ret < 0) {
 		warn("usb in operation failed. (%d)", ret);
@@ -58,8 +55,20 @@ int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8
 	return ret;
 }
 
-static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
-			     u16 index, u8 *b, int blen)
+int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value,
+			    u16 index, u8 *b, int blen)
+{
+	int ret;
+
+	mutex_lock(&d->usb_mutex);
+	ret = vp702x_usb_in_op_unlocked(d, req, value, index, b, blen);
+	mutex_unlock(&d->usb_mutex);
+
+	return ret;
+}
+
+int vp702x_usb_out_op_unlocked(struct dvb_usb_device *d, u8 req, u16 value,
+				      u16 index, u8 *b, int blen)
 {
 	int ret;
 	deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index);
@@ -77,6 +86,18 @@ static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
 		return 0;
 }
 
+int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+			     u16 index, u8 *b, int blen)
+{
+	int ret;
+
+	mutex_lock(&d->usb_mutex);
+	ret = vp702x_usb_out_op_unlocked(d, req, value, index, b, blen);
+	mutex_unlock(&d->usb_mutex);
+
+	return ret;
+}
+
 int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec)
 {
 	int ret;
@@ -84,50 +105,93 @@ int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int il
 	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
 		return ret;
 
-	ret = vp702x_usb_out_op(d,REQUEST_OUT,0,0,o,olen);
+	ret = vp702x_usb_out_op_unlocked(d, REQUEST_OUT, 0, 0, o, olen);
 	msleep(msec);
-	ret = vp702x_usb_in_op(d,REQUEST_IN,0,0,i,ilen);
+	ret = vp702x_usb_in_op_unlocked(d, REQUEST_IN, 0, 0, i, ilen);
 
 	mutex_unlock(&d->usb_mutex);
-
 	return ret;
 }
 
 static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o,
 				int olen, u8 *i, int ilen, int msec)
 {
-	u8 bout[olen+2];
-	u8 bin[ilen+1];
+	struct vp702x_device_state *st = d->priv;
 	int ret = 0;
+	u8 *buf;
+	int buflen = max(olen + 2, ilen + 1);
+
+	ret = mutex_lock_interruptible(&st->buf_mutex);
+	if (ret < 0)
+		return ret;
+
+	if (buflen > st->buf_len) {
+		buf = kmalloc(buflen, GFP_KERNEL);
+		if (!buf) {
+			mutex_unlock(&st->buf_mutex);
+			return -ENOMEM;
+		}
+		info("successfully reallocated a bigger buffer");
+		kfree(st->buf);
+		st->buf = buf;
+		st->buf_len = buflen;
+	} else {
+		buf = st->buf;
+	}
 
-	bout[0] = 0x00;
-	bout[1] = cmd;
-	memcpy(&bout[2],o,olen);
+	buf[0] = 0x00;
+	buf[1] = cmd;
+	memcpy(&buf[2], o, olen);
 
-	ret = vp702x_usb_inout_op(d, bout, olen+2, bin, ilen+1,msec);
+	ret = vp702x_usb_inout_op(d, buf, olen+2, buf, ilen+1, msec);
 
 	if (ret == 0)
-		memcpy(i,&bin[1],ilen);
+		memcpy(i, &buf[1], ilen);
+	mutex_unlock(&st->buf_mutex);
 
 	return ret;
 }
 
 static int vp702x_set_pld_mode(struct dvb_usb_adapter *adap, u8 bypass)
 {
-	u8 buf[16] = { 0 };
-	return vp702x_usb_in_op(adap->dev, 0xe0, (bypass << 8) | 0x0e, 0, buf, 16);
+	int ret;
+	struct vp702x_device_state *st = adap->dev->priv;
+	u8 *buf;
+
+	mutex_lock(&st->buf_mutex);
+
+	buf = st->buf;
+	memset(buf, 0, 16);
+
+	ret = vp702x_usb_in_op(adap->dev, 0xe0, (bypass << 8) | 0x0e,
+			0, buf, 16);
+	mutex_unlock(&st->buf_mutex);
+	return ret;
 }
 
 static int vp702x_set_pld_state(struct dvb_usb_adapter *adap, u8 state)
 {
-	u8 buf[16] = { 0 };
-	return vp702x_usb_in_op(adap->dev, 0xe0, (state << 8) | 0x0f, 0, buf, 16);
+	int ret;
+	struct vp702x_device_state *st = adap->dev->priv;
+	u8 *buf;
+
+	mutex_lock(&st->buf_mutex);
+
+	buf = st->buf;
+	memset(buf, 0, 16);
+	ret = vp702x_usb_in_op(adap->dev, 0xe0, (state << 8) | 0x0f,
+			0, buf, 16);
+
+	mutex_unlock(&st->buf_mutex);
+
+	return ret;
 }
 
 static int vp702x_set_pid(struct dvb_usb_adapter *adap, u16 pid, u8 id, int onoff)
 {
-	struct vp702x_state *st = adap->priv;
-	u8 buf[16] = { 0 };
+	struct vp702x_adapter_state *st = adap->priv;
+	struct vp702x_device_state *dst = adap->dev->priv;
+	u8 *buf;
 
 	if (onoff)
 		st->pid_filter_state |=  (1 << id);
@@ -139,32 +203,45 @@ static int vp702x_set_pid(struct dvb_usb_adapter *adap, u16 pid, u8 id, int onof
 	id = 0x10 + id*2;
 
 	vp702x_set_pld_state(adap, st->pid_filter_state);
+
+	mutex_lock(&dst->buf_mutex);
+
+	buf = dst->buf;
+	memset(buf, 0, 16);
 	vp702x_usb_in_op(adap->dev, 0xe0, (((pid >> 8) & 0xff) << 8) | (id), 0, buf, 16);
 	vp702x_usb_in_op(adap->dev, 0xe0, (((pid     ) & 0xff) << 8) | (id+1), 0, buf, 16);
+
+	mutex_unlock(&dst->buf_mutex);
+
 	return 0;
 }
 
 
 static int vp702x_init_pid_filter(struct dvb_usb_adapter *adap)
 {
-	struct vp702x_state *st = adap->priv;
+	struct vp702x_adapter_state *st = adap->priv;
+	struct vp702x_device_state *dst = adap->dev->priv;
 	int i;
-	u8 b[10] = { 0 };
+	u8 *b;
 
 	st->pid_filter_count = 8;
 	st->pid_filter_can_bypass = 1;
 	st->pid_filter_state = 0x00;
 
-	vp702x_set_pld_mode(adap, 1); // bypass
+	vp702x_set_pld_mode(adap, 1); /* bypass */
 
 	for (i = 0; i < st->pid_filter_count; i++)
 		vp702x_set_pid(adap, 0xffff, i, 1);
 
+	mutex_lock(&dst->buf_mutex);
+	b = dst->buf;
+	memset(b, 0, 10);
 	vp702x_usb_in_op(adap->dev, 0xb5, 3, 0, b, 10);
 	vp702x_usb_in_op(adap->dev, 0xb5, 0, 0, b, 10);
 	vp702x_usb_in_op(adap->dev, 0xb5, 1, 0, b, 10);
+	mutex_unlock(&dst->buf_mutex);
+	/*vp702x_set_pld_mode(d, 0); // filter */
 
-	//vp702x_set_pld_mode(d, 0); // filter
 	return 0;
 }
 
@@ -182,18 +259,23 @@ static struct rc_map_table rc_map_vp702x_table[] = {
 /* remote control stuff (does not work with my box) */
 static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
-	u8 key[10];
+	u8 *key;
 	int i;
 
 /* remove the following return to enabled remote querying */
 	return 0;
 
+	key = kmalloc(10, GFP_KERNEL);
+	if (!key)
+		return -ENOMEM;
+
 	vp702x_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10);
 
 	deb_rc("remote query key: %x %d\n",key[1],key[1]);
 
 	if (key[1] == 0x44) {
 		*state = REMOTE_NO_KEY_PRESSED;
+		kfree(key);
 		return 0;
 	}
 
@@ -203,15 +285,23 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 			*event = rc_map_vp702x_table[i].keycode;
 			break;
 		}
+	kfree(key);
 	return 0;
 }
 
 
 static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
 {
-	u8 i;
+	u8 i, *buf;
+	struct vp702x_device_state *st = d->priv;
+
+	mutex_lock(&st->buf_mutex);
+	buf = st->buf;
 	for (i = 6; i < 12; i++)
-		vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &mac[i - 6], 1);
+		vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &buf[i - 6], 1);
+
+	memcpy(mac, buf, 6);
+	mutex_unlock(&st->buf_mutex);
 	return 0;
 }
 
@@ -221,7 +311,8 @@ static int vp702x_frontend_attach(struct dvb_usb_adapter *adap)
 
 	vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 0, 7, NULL, 0);
 
-	if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0, buf, 10, 10))
+	if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0,
+				   buf, 10, 10))
 		return -EIO;
 
 	buf[9] = '\0';
@@ -240,8 +331,38 @@ static struct dvb_usb_device_properties vp702x_properties;
 static int vp702x_usb_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
 {
-	return dvb_usb_device_init(intf, &vp702x_properties,
-				   THIS_MODULE, NULL, adapter_nr);
+	struct dvb_usb_device *d;
+	struct vp702x_device_state *st;
+	int ret;
+
+	ret = dvb_usb_device_init(intf, &vp702x_properties,
+				   THIS_MODULE, &d, adapter_nr);
+	if (ret)
+		goto out;
+
+	st = d->priv;
+	st->buf_len = 16;
+	st->buf = kmalloc(st->buf_len, GFP_KERNEL);
+	if (!st->buf) {
+		ret = -ENOMEM;
+		dvb_usb_device_exit(intf);
+		goto out;
+	}
+	mutex_init(&st->buf_mutex);
+
+out:
+	return ret;
+
+}
+
+static void vp702x_usb_disconnect(struct usb_interface *intf)
+{
+	struct dvb_usb_device *d = usb_get_intfdata(intf);
+	struct vp702x_device_state *st = d->priv;
+	mutex_lock(&st->buf_mutex);
+	kfree(st->buf);
+	mutex_unlock(&st->buf_mutex);
+	dvb_usb_device_exit(intf);
 }
 
 static struct usb_device_id vp702x_usb_table [] = {
@@ -278,7 +399,7 @@ static struct dvb_usb_device_properties vp702x_properties = {
 					}
 				}
 			},
-			.size_of_priv     = sizeof(struct vp702x_state),
+			.size_of_priv     = sizeof(struct vp702x_adapter_state),
 		}
 	},
 	.read_mac_address = vp702x_read_mac_addr,
@@ -307,9 +428,9 @@ static struct dvb_usb_device_properties vp702x_properties = {
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver vp702x_usb_driver = {
 	.name		= "dvb_usb_vp702x",
-	.probe 		= vp702x_usb_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table 	= vp702x_usb_table,
+	.probe		= vp702x_usb_probe,
+	.disconnect	= vp702x_usb_disconnect,
+	.id_table	= vp702x_usb_table,
 };
 
 /* module stuff */

+ 7 - 0
drivers/media/dvb/dvb-usb/vp702x.h

@@ -98,6 +98,13 @@ extern int dvb_usb_vp702x_debug;
 #define RESET_TUNER		0xBE
 /* IN  i: 0, v: 0, no extra buffer */
 
+struct vp702x_device_state {
+	struct mutex buf_mutex;
+	int buf_len;
+	u8 *buf;
+};
+
+
 extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
 
 extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec);

+ 34 - 13
drivers/media/dvb/dvb-usb/vp7045.c

@@ -28,9 +28,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec)
 {
 	int ret = 0;
-	u8 inbuf[12] = { 0 }, outbuf[20] = { 0 };
+	u8 *buf = d->priv;
 
-	outbuf[0] = cmd;
+	buf[0] = cmd;
 
 	if (outlen > 19)
 		outlen = 19;
@@ -38,19 +38,21 @@ int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in,
 	if (inlen > 11)
 		inlen = 11;
 
+	ret = mutex_lock_interruptible(&d->usb_mutex);
+	if (ret)
+		return ret;
+
 	if (out != NULL && outlen > 0)
-		memcpy(&outbuf[1], out, outlen);
+		memcpy(&buf[1], out, outlen);
 
 	deb_xfer("out buffer: ");
-	debug_dump(outbuf,outlen+1,deb_xfer);
+	debug_dump(buf, outlen+1, deb_xfer);
 
-	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
-		return ret;
 
 	if (usb_control_msg(d->udev,
 			usb_sndctrlpipe(d->udev,0),
 			TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0,
-			outbuf, 20, 2000) != 20) {
+			buf, 20, 2000) != 20) {
 		err("USB control message 'out' went wrong.");
 		ret = -EIO;
 		goto unlock;
@@ -61,17 +63,17 @@ int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in,
 	if (usb_control_msg(d->udev,
 			usb_rcvctrlpipe(d->udev,0),
 			TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
-			inbuf, 12, 2000) != 12) {
+			buf, 12, 2000) != 12) {
 		err("USB control message 'in' went wrong.");
 		ret = -EIO;
 		goto unlock;
 	}
 
 	deb_xfer("in buffer: ");
-	debug_dump(inbuf,12,deb_xfer);
+	debug_dump(buf, 12, deb_xfer);
 
 	if (in != NULL && inlen > 0)
-		memcpy(in,&inbuf[1],inlen);
+		memcpy(in, &buf[1], inlen);
 
 unlock:
 	mutex_unlock(&d->usb_mutex);
@@ -222,8 +224,26 @@ static struct dvb_usb_device_properties vp7045_properties;
 static int vp7045_usb_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
 {
-	return dvb_usb_device_init(intf, &vp7045_properties,
-				   THIS_MODULE, NULL, adapter_nr);
+	struct dvb_usb_device *d;
+	int ret = dvb_usb_device_init(intf, &vp7045_properties,
+				   THIS_MODULE, &d, adapter_nr);
+	if (ret)
+		return ret;
+
+	d->priv = kmalloc(20, GFP_KERNEL);
+	if (!d->priv) {
+		dvb_usb_device_exit(intf);
+		return -ENOMEM;
+	}
+
+	return ret;
+}
+
+static void vp7045_usb_disconnect(struct usb_interface *intf)
+{
+	struct dvb_usb_device *d = usb_get_intfdata(intf);
+	kfree(d->priv);
+	dvb_usb_device_exit(intf);
 }
 
 static struct usb_device_id vp7045_usb_table [] = {
@@ -238,6 +258,7 @@ MODULE_DEVICE_TABLE(usb, vp7045_usb_table);
 static struct dvb_usb_device_properties vp7045_properties = {
 	.usb_ctrl = CYPRESS_FX2,
 	.firmware = "dvb-usb-vp7045-01.fw",
+	.size_of_priv = sizeof(u8 *),
 
 	.num_adapters = 1,
 	.adapter = {
@@ -284,7 +305,7 @@ static struct dvb_usb_device_properties vp7045_properties = {
 static struct usb_driver vp7045_usb_driver = {
 	.name		= "dvb_usb_vp7045",
 	.probe		= vp7045_usb_probe,
-	.disconnect = dvb_usb_device_exit,
+	.disconnect	= vp7045_usb_disconnect,
 	.id_table	= vp7045_usb_table,
 };
 

+ 12 - 7
drivers/media/dvb/frontends/Kconfig

@@ -263,18 +263,16 @@ config DVB_S5H1432
 	help
 	  A DVB-T tuner module. Say Y when you want to support this frontend.
 
-config DVB_DRX397XD
-	tristate "Micronas DRX3975D/DRX3977D based"
+config DVB_DRXD
+	tristate "Micronas DRXD driver"
 	depends on DVB_CORE && I2C
 	default m if DVB_FE_CUSTOMISE
 	help
 	  A DVB-T tuner module. Say Y when you want to support this frontend.
 
-	  TODO:
-	  This driver needs external firmware. Please use the command
-	  "<kerneldir>/Documentation/dvb/get_dvb_firmware drx397xD" to
-	  download/extract them, and then copy them to /usr/lib/hotplug/firmware
-	  or /lib/firmware (depending on configuration of firmware hotplug).
+	  Note: this driver was based on vendor driver reference code (released
+	  under the GPL) as opposed to the existing drx397xd driver, which
+	  was written via reverse engineering.
 
 config DVB_L64781
 	tristate "LSI L64781"
@@ -385,6 +383,13 @@ config DVB_STV0367
 	help
 	  A DVB-T/C tuner module. Say Y when you want to support this frontend.
 
+config DVB_CXD2820R
+	tristate "Sony CXD2820R"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  Say Y when you want to support this frontend.
+
 comment "DVB-C (cable) frontends"
 	depends on DVB_CORE
 

+ 5 - 1
drivers/media/dvb/frontends/Makefile

@@ -8,6 +8,8 @@ EXTRA_CFLAGS += -Idrivers/media/common/tuners/
 stb0899-objs = stb0899_drv.o stb0899_algo.o
 stv0900-objs = stv0900_core.o stv0900_sw.o
 au8522-objs = au8522_dig.o au8522_decoder.o
+drxd-objs = drxd_firm.o drxd_hard.o
+cxd2820r-objs = cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o
 
 obj-$(CONFIG_DVB_PLL) += dvb-pll.o
 obj-$(CONFIG_DVB_STV0299) += stv0299.o
@@ -36,7 +38,7 @@ obj-$(CONFIG_DVB_ZL10036) += zl10036.o
 obj-$(CONFIG_DVB_ZL10039) += zl10039.o
 obj-$(CONFIG_DVB_ZL10353) += zl10353.o
 obj-$(CONFIG_DVB_CX22702) += cx22702.o
-obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o
+obj-$(CONFIG_DVB_DRXD) += drxd.o
 obj-$(CONFIG_DVB_TDA10021) += tda10021.o
 obj-$(CONFIG_DVB_TDA10023) += tda10023.o
 obj-$(CONFIG_DVB_STV0297) += stv0297.o
@@ -85,3 +87,5 @@ obj-$(CONFIG_DVB_MB86A16) += mb86a16.o
 obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
 obj-$(CONFIG_DVB_IX2505V) += ix2505v.o
 obj-$(CONFIG_DVB_STV0367) += stv0367.o
+obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
+

+ 146 - 0
drivers/media/dvb/frontends/bsbe1-d01a.h

@@ -0,0 +1,146 @@
+/*
+ * bsbe1-d01a.h - ALPS BSBE1-D01A tuner support
+ *
+ * Copyright (C) 2011 Oliver Endriss <o.endriss@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef BSBE1_D01A_H
+#define BSBE1_D01A_H
+
+#include "stb6000.h"
+#include "stv0288.h"
+
+static u8 stv0288_bsbe1_d01a_inittab[] = {
+	0x01, 0x15,
+	0x02, 0x20,
+	0x09, 0x0,
+	0x0a, 0x4,
+	0x0b, 0x0,
+	0x0c, 0x0,
+	0x0d, 0x0,
+	0x0e, 0xd4,
+	0x0f, 0x30,
+	0x11, 0x80,
+	0x12, 0x03,
+	0x13, 0x48,
+	0x14, 0x84,
+	0x15, 0x45,
+	0x16, 0xb7,
+	0x17, 0x9c,
+	0x18, 0x0,
+	0x19, 0xa6,
+	0x1a, 0x88,
+	0x1b, 0x8f,
+	0x1c, 0xf0,
+	0x20, 0x0b,
+	0x21, 0x54,
+	0x22, 0x0,
+	0x23, 0x0,
+	0x2b, 0xff,
+	0x2c, 0xf7,
+	0x30, 0x0,
+	0x31, 0x1e,
+	0x32, 0x14,
+	0x33, 0x0f,
+	0x34, 0x09,
+	0x35, 0x0c,
+	0x36, 0x05,
+	0x37, 0x2f,
+	0x38, 0x16,
+	0x39, 0xbd,
+	0x3a, 0x03,
+	0x3b, 0x13,
+	0x3c, 0x11,
+	0x3d, 0x30,
+	0x40, 0x63,
+	0x41, 0x04,
+	0x42, 0x60,
+	0x43, 0x00,
+	0x44, 0x00,
+	0x45, 0x00,
+	0x46, 0x00,
+	0x47, 0x00,
+	0x4a, 0x00,
+	0x50, 0x10,
+	0x51, 0x36,
+	0x52, 0x09,
+	0x53, 0x94,
+	0x54, 0x62,
+	0x55, 0x29,
+	0x56, 0x64,
+	0x57, 0x2b,
+	0x58, 0x54,
+	0x59, 0x86,
+	0x5a, 0x0,
+	0x5b, 0x9b,
+	0x5c, 0x08,
+	0x5d, 0x7f,
+	0x5e, 0x0,
+	0x5f, 0xff,
+	0x70, 0x0,
+	0x71, 0x0,
+	0x72, 0x0,
+	0x74, 0x0,
+	0x75, 0x0,
+	0x76, 0x0,
+	0x81, 0x0,
+	0x82, 0x3f,
+	0x83, 0x3f,
+	0x84, 0x0,
+	0x85, 0x0,
+	0x88, 0x0,
+	0x89, 0x0,
+	0x8a, 0x0,
+	0x8b, 0x0,
+	0x8c, 0x0,
+	0x90, 0x0,
+	0x91, 0x0,
+	0x92, 0x0,
+	0x93, 0x0,
+	0x94, 0x1c,
+	0x97, 0x0,
+	0xa0, 0x48,
+	0xa1, 0x0,
+	0xb0, 0xb8,
+	0xb1, 0x3a,
+	0xb2, 0x10,
+	0xb3, 0x82,
+	0xb4, 0x80,
+	0xb5, 0x82,
+	0xb6, 0x82,
+	0xb7, 0x82,
+	0xb8, 0x20,
+	0xb9, 0x0,
+	0xf0, 0x0,
+	0xf1, 0x0,
+	0xf2, 0xc0,
+	0xff, 0xff,
+};
+
+static struct stv0288_config stv0288_bsbe1_d01a_config = {
+	.demod_address = 0x68,
+	.min_delay_ms = 100,
+	.inittab = stv0288_bsbe1_d01a_inittab,
+};
+
+#endif

+ 1 - 1
drivers/media/dvb/frontends/bsru6.h

@@ -27,7 +27,7 @@
 
 static u8 alps_bsru6_inittab[] = {
 	0x01, 0x15,
-	0x02, 0x00,
+	0x02, 0x30,
 	0x03, 0x00,
 	0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
 	0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1 */

+ 17 - 4
drivers/media/dvb/frontends/cx24116.c

@@ -137,7 +137,7 @@ MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, "\
 /* SNR measurements */
 static int esno_snr;
 module_param(esno_snr, int, 0644);
-MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, "\
+MODULE_PARM_DESC(esno_snr, "SNR return units, 0=PERCENTAGE 0-100, "\
 	"1=ESNO(db * 10) (default:0)");
 
 enum cmds {
@@ -566,7 +566,7 @@ static int cx24116_load_firmware(struct dvb_frontend *fe,
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 	struct cx24116_cmd cmd;
-	int i, ret;
+	int i, ret, len, max, remaining;
 	unsigned char vers[4];
 
 	dprintk("%s\n", __func__);
@@ -603,8 +603,21 @@ static int cx24116_load_firmware(struct dvb_frontend *fe,
 	cx24116_writereg(state, 0xF5, 0x00);
 	cx24116_writereg(state, 0xF6, 0x00);
 
-	/* write the entire firmware as one transaction */
-	cx24116_writeregN(state, 0xF7, fw->data, fw->size);
+	/* Split firmware to the max I2C write len and write.
+	 * Writes whole firmware as one write when i2c_wr_max is set to 0. */
+	if (state->config->i2c_wr_max)
+		max = state->config->i2c_wr_max;
+	else
+		max = INT_MAX; /* enough for 32k firmware */
+
+	for (remaining = fw->size; remaining > 0; remaining -= max - 1) {
+		len = remaining;
+		if (len > max - 1)
+			len = max - 1;
+
+		cx24116_writeregN(state, 0xF7, &fw->data[fw->size - remaining],
+			len);
+	}
 
 	cx24116_writereg(state, 0xF4, 0x10);
 	cx24116_writereg(state, 0xF0, 0x00);

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

@@ -35,6 +35,9 @@ struct cx24116_config {
 
 	/* Need to set MPEG parameters */
 	u8 mpg_clk_pos_pol:0x02;
+
+	/* max bytes I2C provider can write at once */
+	u16 i2c_wr_max;
 };
 
 #if defined(CONFIG_DVB_CX24116) || \

+ 118 - 0
drivers/media/dvb/frontends/cxd2820r.h

@@ -0,0 +1,118 @@
+/*
+ * Sony CXD2820R demodulator driver
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#ifndef CXD2820R_H
+#define CXD2820R_H
+
+#include <linux/dvb/frontend.h>
+
+#define CXD2820R_GPIO_D (0 << 0) /* disable */
+#define CXD2820R_GPIO_E (1 << 0) /* enable */
+#define CXD2820R_GPIO_O (0 << 1) /* output */
+#define CXD2820R_GPIO_I (1 << 1) /* input */
+#define CXD2820R_GPIO_L (0 << 2) /* output low */
+#define CXD2820R_GPIO_H (1 << 2) /* output high */
+
+#define CXD2820R_TS_SERIAL        0x08
+#define CXD2820R_TS_SERIAL_MSB    0x28
+#define CXD2820R_TS_PARALLEL      0x30
+#define CXD2820R_TS_PARALLEL_MSB  0x70
+
+struct cxd2820r_config {
+	/* Demodulator I2C address.
+	 * Driver determines DVB-C slave I2C address automatically from master
+	 * address.
+	 * Default: none, must set
+	 * Values: 0x6c, 0x6d
+	 */
+	u8 i2c_address;
+
+	/* TS output mode.
+	 * Default: none, must set.
+	 * Values:
+	 */
+	u8 ts_mode;
+
+	/* IF AGC polarity.
+	 * Default: 0
+	 * Values: 0, 1
+	 */
+	int if_agc_polarity:1;
+
+	/* Spectrum inversion.
+	 * Default: 0
+	 * Values: 0, 1
+	 */
+	int spec_inv:1;
+
+	/* IFs for all used modes.
+	 * Default: none, must set
+	 * Values: <kHz>
+	 */
+	u16 if_dvbt_6;
+	u16 if_dvbt_7;
+	u16 if_dvbt_8;
+	u16 if_dvbt2_5;
+	u16 if_dvbt2_6;
+	u16 if_dvbt2_7;
+	u16 if_dvbt2_8;
+	u16 if_dvbc;
+
+	/* GPIOs for all used modes.
+	 * Default: none, disabled
+	 * Values: <see above>
+	 */
+	u8 gpio_dvbt[3];
+	u8 gpio_dvbt2[3];
+	u8 gpio_dvbc[3];
+};
+
+
+#if defined(CONFIG_DVB_CXD2820R) || \
+	(defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE))
+extern struct dvb_frontend *cxd2820r_attach(
+	const struct cxd2820r_config *config,
+	struct i2c_adapter *i2c,
+	struct dvb_frontend *fe
+);
+extern struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(
+	struct dvb_frontend *fe
+);
+#else
+static inline struct dvb_frontend *cxd2820r_attach(
+	const struct cxd2820r_config *config,
+	struct i2c_adapter *i2c,
+	struct dvb_frontend *fe
+)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+static inline struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(
+	struct dvb_frontend *fe
+)
+{
+	return NULL;
+}
+
+#endif
+
+#endif /* CXD2820R_H */

+ 338 - 0
drivers/media/dvb/frontends/cxd2820r_c.c

@@ -0,0 +1,338 @@
+/*
+ * Sony CXD2820R demodulator driver
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include "cxd2820r_priv.h"
+
+int cxd2820r_set_frontend_c(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *params)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i;
+	u8 buf[2];
+	u16 if_ctl;
+	u64 num;
+	struct reg_val_mask tab[] = {
+		{ 0x00080, 0x01, 0xff },
+		{ 0x00081, 0x05, 0xff },
+		{ 0x00085, 0x07, 0xff },
+		{ 0x00088, 0x01, 0xff },
+
+		{ 0x00082, 0x20, 0x60 },
+		{ 0x1016a, 0x48, 0xff },
+		{ 0x100a5, 0x00, 0x01 },
+		{ 0x10020, 0x06, 0x07 },
+		{ 0x10059, 0x50, 0xff },
+		{ 0x10087, 0x0c, 0x3c },
+		{ 0x1008b, 0x07, 0xff },
+		{ 0x1001f, priv->cfg.if_agc_polarity << 7, 0x80 },
+		{ 0x10070, priv->cfg.ts_mode, 0xff },
+	};
+
+	dbg("%s: RF=%d SR=%d", __func__, c->frequency, c->symbol_rate);
+
+	/* update GPIOs */
+	ret = cxd2820r_gpio(fe);
+	if (ret)
+		goto error;
+
+	/* program tuner */
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe, params);
+
+	if (priv->delivery_system !=  SYS_DVBC_ANNEX_AC) {
+		for (i = 0; i < ARRAY_SIZE(tab); i++) {
+			ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
+				tab[i].val, tab[i].mask);
+			if (ret)
+				goto error;
+		}
+	}
+
+	priv->delivery_system = SYS_DVBC_ANNEX_AC;
+	priv->ber_running = 0; /* tune stops BER counter */
+
+	num = priv->cfg.if_dvbc;
+	num *= 0x4000;
+	if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
+	buf[0] = (if_ctl >> 8) & 0x3f;
+	buf[1] = (if_ctl >> 0) & 0xff;
+
+	ret = cxd2820r_wr_regs(priv, 0x10042, buf, 2);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_get_frontend_c(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret;
+	u8 buf[2];
+
+	ret = cxd2820r_rd_regs(priv, 0x1001a, buf, 2);
+	if (ret)
+		goto error;
+
+	c->symbol_rate = 2500 * ((buf[0] & 0x0f) << 8 | buf[1]);
+
+	ret = cxd2820r_rd_reg(priv, 0x10019, &buf[0]);
+	if (ret)
+		goto error;
+
+	switch ((buf[0] >> 0) & 0x03) {
+	case 0:
+		c->modulation = QAM_16;
+		break;
+	case 1:
+		c->modulation = QAM_32;
+		break;
+	case 2:
+		c->modulation = QAM_64;
+		break;
+	case 3:
+		c->modulation = QAM_128;
+		break;
+	case 4:
+		c->modulation = QAM_256;
+		break;
+	}
+
+	switch ((buf[0] >> 7) & 0x01) {
+	case 0:
+		c->inversion = INVERSION_OFF;
+		break;
+	case 1:
+		c->inversion = INVERSION_ON;
+		break;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[3], start_ber = 0;
+	*ber = 0;
+
+	if (priv->ber_running) {
+		ret = cxd2820r_rd_regs(priv, 0x10076, buf, sizeof(buf));
+		if (ret)
+			goto error;
+
+		if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) {
+			*ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0];
+			start_ber = 1;
+		}
+	} else {
+		priv->ber_running = 1;
+		start_ber = 1;
+	}
+
+	if (start_ber) {
+		/* (re)start BER */
+		ret = cxd2820r_wr_reg(priv, 0x10079, 0x01);
+		if (ret)
+			goto error;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe,
+	u16 *strength)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+	u16 tmp;
+
+	ret = cxd2820r_rd_regs(priv, 0x10049, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+	tmp = (buf[0] & 0x03) << 8 | buf[1];
+	tmp = (~tmp & 0x03ff);
+
+	if (tmp == 512)
+		/* ~no signal */
+		tmp = 0;
+	else if (tmp > 350)
+		tmp = 350;
+
+	/* scale value to 0x0000-0xffff */
+	*strength = tmp * 0xffff / (350-0);
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 tmp;
+	unsigned int A, B;
+	/* report SNR in dB * 10 */
+
+	ret = cxd2820r_rd_reg(priv, 0x10019, &tmp);
+	if (ret)
+		goto error;
+
+	if (((tmp >> 0) & 0x03) % 2) {
+		A = 875;
+		B = 650;
+	} else {
+		A = 950;
+		B = 760;
+	}
+
+	ret = cxd2820r_rd_reg(priv, 0x1004d, &tmp);
+	if (ret)
+		goto error;
+
+	#define CXD2820R_LOG2_E_24 24204406 /* log2(e) << 24 */
+	if (tmp)
+		*snr = A * (intlog2(B / tmp) >> 5) / (CXD2820R_LOG2_E_24 >> 5)
+			/ 10;
+	else
+		*snr = 0;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	*ucblocks = 0;
+	/* no way to read ? */
+	return 0;
+}
+
+int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+	*status = 0;
+
+	ret = cxd2820r_rd_regs(priv, 0x10088, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+	if (((buf[0] >> 0) & 0x01) == 1) {
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+			FE_HAS_VITERBI | FE_HAS_SYNC;
+
+		if (((buf[1] >> 3) & 0x01) == 1) {
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+		}
+	}
+
+	dbg("%s: lock=%02x %02x", __func__, buf[0], buf[1]);
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_init_c(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+
+	ret = cxd2820r_wr_reg(priv, 0x00085, 0x07);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_sleep_c(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret, i;
+	struct reg_val_mask tab[] = {
+		{ 0x000ff, 0x1f, 0xff },
+		{ 0x00085, 0x00, 0xff },
+		{ 0x00088, 0x01, 0xff },
+		{ 0x00081, 0x00, 0xff },
+		{ 0x00080, 0x00, 0xff },
+	};
+
+	dbg("%s", __func__);
+
+	priv->delivery_system = SYS_UNDEFINED;
+
+	for (i = 0; i < ARRAY_SIZE(tab); i++) {
+		ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val,
+			tab[i].mask);
+		if (ret)
+			goto error;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s)
+{
+	s->min_delay_ms = 500;
+	s->step_size = 0; /* no zigzag */
+	s->max_drift = 0;
+
+	return 0;
+}
+

+ 915 - 0
drivers/media/dvb/frontends/cxd2820r_core.c

@@ -0,0 +1,915 @@
+/*
+ * Sony CXD2820R demodulator driver
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include "cxd2820r_priv.h"
+
+int cxd2820r_debug;
+module_param_named(debug, cxd2820r_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+/* write multiple registers */
+static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
+	u8 *val, int len)
+{
+	int ret;
+	u8 buf[len+1];
+	struct i2c_msg msg[1] = {
+		{
+			.addr = i2c,
+			.flags = 0,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	buf[0] = reg;
+	memcpy(&buf[1], val, len);
+
+	ret = i2c_transfer(priv->i2c, msg, 1);
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* read multiple registers */
+static int cxd2820r_rd_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
+	u8 *val, int len)
+{
+	int ret;
+	u8 buf[len];
+	struct i2c_msg msg[2] = {
+		{
+			.addr = i2c,
+			.flags = 0,
+			.len = 1,
+			.buf = &reg,
+		}, {
+			.addr = i2c,
+			.flags = I2C_M_RD,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	ret = i2c_transfer(priv->i2c, msg, 2);
+	if (ret == 2) {
+		memcpy(val, buf, len);
+		ret = 0;
+	} else {
+		warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+
+	return ret;
+}
+
+/* write multiple registers */
+int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
+	int len)
+{
+	int ret;
+	u8 i2c_addr;
+	u8 reg = (reginfo >> 0) & 0xff;
+	u8 bank = (reginfo >> 8) & 0xff;
+	u8 i2c = (reginfo >> 16) & 0x01;
+
+	/* select I2C */
+	if (i2c)
+		i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */
+	else
+		i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */
+
+	/* switch bank if needed */
+	if (bank != priv->bank[i2c]) {
+		ret = cxd2820r_wr_regs_i2c(priv, i2c_addr, 0x00, &bank, 1);
+		if (ret)
+			return ret;
+		priv->bank[i2c] = bank;
+	}
+	return cxd2820r_wr_regs_i2c(priv, i2c_addr, reg, val, len);
+}
+
+/* read multiple registers */
+int cxd2820r_rd_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
+	int len)
+{
+	int ret;
+	u8 i2c_addr;
+	u8 reg = (reginfo >> 0) & 0xff;
+	u8 bank = (reginfo >> 8) & 0xff;
+	u8 i2c = (reginfo >> 16) & 0x01;
+
+	/* select I2C */
+	if (i2c)
+		i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */
+	else
+		i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */
+
+	/* switch bank if needed */
+	if (bank != priv->bank[i2c]) {
+		ret = cxd2820r_wr_regs_i2c(priv, i2c_addr, 0x00, &bank, 1);
+		if (ret)
+			return ret;
+		priv->bank[i2c] = bank;
+	}
+	return cxd2820r_rd_regs_i2c(priv, i2c_addr, reg, val, len);
+}
+
+/* write single register */
+int cxd2820r_wr_reg(struct cxd2820r_priv *priv, u32 reg, u8 val)
+{
+	return cxd2820r_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register */
+int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val)
+{
+	return cxd2820r_rd_regs(priv, reg, val, 1);
+}
+
+/* write single register with mask */
+int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val,
+	u8 mask)
+{
+	int ret;
+	u8 tmp;
+
+	/* no need for read if whole reg is written */
+	if (mask != 0xff) {
+		ret = cxd2820r_rd_reg(priv, reg, &tmp);
+		if (ret)
+			return ret;
+
+		val &= mask;
+		tmp &= ~mask;
+		val |= tmp;
+	}
+
+	return cxd2820r_wr_reg(priv, reg, val);
+}
+
+int cxd2820r_gpio(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret, i;
+	u8 *gpio, tmp0, tmp1;
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+	switch (fe->dtv_property_cache.delivery_system) {
+	case SYS_DVBT:
+		gpio = priv->cfg.gpio_dvbt;
+		break;
+	case SYS_DVBT2:
+		gpio = priv->cfg.gpio_dvbt2;
+		break;
+	case SYS_DVBC_ANNEX_AC:
+		gpio = priv->cfg.gpio_dvbc;
+		break;
+	default:
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* update GPIOs only when needed */
+	if (!memcmp(gpio, priv->gpio, sizeof(priv->gpio)))
+		return 0;
+
+	tmp0 = 0x00;
+	tmp1 = 0x00;
+	for (i = 0; i < sizeof(priv->gpio); i++) {
+		/* enable / disable */
+		if (gpio[i] & CXD2820R_GPIO_E)
+			tmp0 |= (2 << 6) >> (2 * i);
+		else
+			tmp0 |= (1 << 6) >> (2 * i);
+
+		/* input / output */
+		if (gpio[i] & CXD2820R_GPIO_I)
+			tmp1 |= (1 << (3 + i));
+		else
+			tmp1 |= (0 << (3 + i));
+
+		/* high / low */
+		if (gpio[i] & CXD2820R_GPIO_H)
+			tmp1 |= (1 << (0 + i));
+		else
+			tmp1 |= (0 << (0 + i));
+
+		dbg("%s: GPIO i=%d %02x %02x", __func__, i, tmp0, tmp1);
+	}
+
+	dbg("%s: wr gpio=%02x %02x", __func__, tmp0, tmp1);
+
+	/* write bits [7:2] */
+	ret = cxd2820r_wr_reg_mask(priv, 0x00089, tmp0, 0xfc);
+	if (ret)
+		goto error;
+
+	/* write bits [5:0] */
+	ret = cxd2820r_wr_reg_mask(priv, 0x0008e, tmp1, 0x3f);
+	if (ret)
+		goto error;
+
+	memcpy(priv->gpio, gpio, sizeof(priv->gpio));
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+/* lock FE */
+static int cxd2820r_lock(struct cxd2820r_priv *priv, int active_fe)
+{
+	int ret = 0;
+	dbg("%s: active_fe=%d", __func__, active_fe);
+
+	mutex_lock(&priv->fe_lock);
+
+	/* -1=NONE, 0=DVB-T/T2, 1=DVB-C */
+	if (priv->active_fe == active_fe)
+		;
+	else if (priv->active_fe == -1)
+		priv->active_fe = active_fe;
+	else
+		ret = -EBUSY;
+
+	mutex_unlock(&priv->fe_lock);
+
+	return ret;
+}
+
+/* unlock FE */
+static void cxd2820r_unlock(struct cxd2820r_priv *priv, int active_fe)
+{
+	dbg("%s: active_fe=%d", __func__, active_fe);
+
+	mutex_lock(&priv->fe_lock);
+
+	/* -1=NONE, 0=DVB-T/T2, 1=DVB-C */
+	if (priv->active_fe == active_fe)
+		priv->active_fe = -1;
+
+	mutex_unlock(&priv->fe_lock);
+
+	return;
+}
+
+/* 64 bit div with round closest, like DIV_ROUND_CLOSEST but 64 bit */
+u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor)
+{
+	return div_u64(dividend + (divisor / 2), divisor);
+}
+
+static int cxd2820r_set_frontend(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret;
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+	if (fe->ops.info.type == FE_OFDM) {
+		/* DVB-T/T2 */
+		ret = cxd2820r_lock(priv, 0);
+		if (ret)
+			return ret;
+
+		switch (priv->delivery_system) {
+		case SYS_UNDEFINED:
+			if (c->delivery_system == SYS_DVBT) {
+				/* SLEEP => DVB-T */
+				ret = cxd2820r_set_frontend_t(fe, p);
+			} else {
+				/* SLEEP => DVB-T2 */
+				ret = cxd2820r_set_frontend_t2(fe, p);
+			}
+			break;
+		case SYS_DVBT:
+			if (c->delivery_system == SYS_DVBT) {
+				/* DVB-T => DVB-T */
+				ret = cxd2820r_set_frontend_t(fe, p);
+			} else if (c->delivery_system == SYS_DVBT2) {
+				/* DVB-T => DVB-T2 */
+				ret = cxd2820r_sleep_t(fe);
+				ret = cxd2820r_set_frontend_t2(fe, p);
+			}
+			break;
+		case SYS_DVBT2:
+			if (c->delivery_system == SYS_DVBT2) {
+				/* DVB-T2 => DVB-T2 */
+				ret = cxd2820r_set_frontend_t2(fe, p);
+			} else if (c->delivery_system == SYS_DVBT) {
+				/* DVB-T2 => DVB-T */
+				ret = cxd2820r_sleep_t2(fe);
+				ret = cxd2820r_set_frontend_t(fe, p);
+			}
+			break;
+		default:
+			dbg("%s: error state=%d", __func__,
+				priv->delivery_system);
+			ret = -EINVAL;
+		}
+	} else {
+		/* DVB-C */
+		ret = cxd2820r_lock(priv, 1);
+		if (ret)
+			return ret;
+
+		ret = cxd2820r_set_frontend_c(fe, p);
+	}
+
+	return ret;
+}
+
+static int cxd2820r_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+	if (fe->ops.info.type == FE_OFDM) {
+		/* DVB-T/T2 */
+		ret = cxd2820r_lock(priv, 0);
+		if (ret)
+			return ret;
+
+		switch (fe->dtv_property_cache.delivery_system) {
+		case SYS_DVBT:
+			ret = cxd2820r_read_status_t(fe, status);
+			break;
+		case SYS_DVBT2:
+			ret = cxd2820r_read_status_t2(fe, status);
+			break;
+		default:
+			ret = -EINVAL;
+		}
+	} else {
+		/* DVB-C */
+		ret = cxd2820r_lock(priv, 1);
+		if (ret)
+			return ret;
+
+		ret = cxd2820r_read_status_c(fe, status);
+	}
+
+	return ret;
+}
+
+static int cxd2820r_get_frontend(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+	if (fe->ops.info.type == FE_OFDM) {
+		/* DVB-T/T2 */
+		ret = cxd2820r_lock(priv, 0);
+		if (ret)
+			return ret;
+
+		switch (fe->dtv_property_cache.delivery_system) {
+		case SYS_DVBT:
+			ret = cxd2820r_get_frontend_t(fe, p);
+			break;
+		case SYS_DVBT2:
+			ret = cxd2820r_get_frontend_t2(fe, p);
+			break;
+		default:
+			ret = -EINVAL;
+		}
+	} else {
+		/* DVB-C */
+		ret = cxd2820r_lock(priv, 1);
+		if (ret)
+			return ret;
+
+		ret = cxd2820r_get_frontend_c(fe, p);
+	}
+
+	return ret;
+}
+
+static int cxd2820r_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+	if (fe->ops.info.type == FE_OFDM) {
+		/* DVB-T/T2 */
+		ret = cxd2820r_lock(priv, 0);
+		if (ret)
+			return ret;
+
+		switch (fe->dtv_property_cache.delivery_system) {
+		case SYS_DVBT:
+			ret = cxd2820r_read_ber_t(fe, ber);
+			break;
+		case SYS_DVBT2:
+			ret = cxd2820r_read_ber_t2(fe, ber);
+			break;
+		default:
+			ret = -EINVAL;
+		}
+	} else {
+		/* DVB-C */
+		ret = cxd2820r_lock(priv, 1);
+		if (ret)
+			return ret;
+
+		ret = cxd2820r_read_ber_c(fe, ber);
+	}
+
+	return ret;
+}
+
+static int cxd2820r_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+	if (fe->ops.info.type == FE_OFDM) {
+		/* DVB-T/T2 */
+		ret = cxd2820r_lock(priv, 0);
+		if (ret)
+			return ret;
+
+		switch (fe->dtv_property_cache.delivery_system) {
+		case SYS_DVBT:
+			ret = cxd2820r_read_signal_strength_t(fe, strength);
+			break;
+		case SYS_DVBT2:
+			ret = cxd2820r_read_signal_strength_t2(fe, strength);
+			break;
+		default:
+			ret = -EINVAL;
+		}
+	} else {
+		/* DVB-C */
+		ret = cxd2820r_lock(priv, 1);
+		if (ret)
+			return ret;
+
+		ret = cxd2820r_read_signal_strength_c(fe, strength);
+	}
+
+	return ret;
+}
+
+static int cxd2820r_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+	if (fe->ops.info.type == FE_OFDM) {
+		/* DVB-T/T2 */
+		ret = cxd2820r_lock(priv, 0);
+		if (ret)
+			return ret;
+
+		switch (fe->dtv_property_cache.delivery_system) {
+		case SYS_DVBT:
+			ret = cxd2820r_read_snr_t(fe, snr);
+			break;
+		case SYS_DVBT2:
+			ret = cxd2820r_read_snr_t2(fe, snr);
+			break;
+		default:
+			ret = -EINVAL;
+		}
+	} else {
+		/* DVB-C */
+		ret = cxd2820r_lock(priv, 1);
+		if (ret)
+			return ret;
+
+		ret = cxd2820r_read_snr_c(fe, snr);
+	}
+
+	return ret;
+}
+
+static int cxd2820r_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+	if (fe->ops.info.type == FE_OFDM) {
+		/* DVB-T/T2 */
+		ret = cxd2820r_lock(priv, 0);
+		if (ret)
+			return ret;
+
+		switch (fe->dtv_property_cache.delivery_system) {
+		case SYS_DVBT:
+			ret = cxd2820r_read_ucblocks_t(fe, ucblocks);
+			break;
+		case SYS_DVBT2:
+			ret = cxd2820r_read_ucblocks_t2(fe, ucblocks);
+			break;
+		default:
+			ret = -EINVAL;
+		}
+	} else {
+		/* DVB-C */
+		ret = cxd2820r_lock(priv, 1);
+		if (ret)
+			return ret;
+
+		ret = cxd2820r_read_ucblocks_c(fe, ucblocks);
+	}
+
+	return ret;
+}
+
+static int cxd2820r_init(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+	priv->delivery_system = SYS_UNDEFINED;
+	/* delivery system is unknown at that (init) phase */
+
+	if (fe->ops.info.type == FE_OFDM) {
+		/* DVB-T/T2 */
+		ret = cxd2820r_lock(priv, 0);
+		if (ret)
+			return ret;
+
+		ret = cxd2820r_init_t(fe);
+	} else {
+		/* DVB-C */
+		ret = cxd2820r_lock(priv, 1);
+		if (ret)
+			return ret;
+
+		ret = cxd2820r_init_c(fe);
+	}
+
+	return ret;
+}
+
+static int cxd2820r_sleep(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+	if (fe->ops.info.type == FE_OFDM) {
+		/* DVB-T/T2 */
+		ret = cxd2820r_lock(priv, 0);
+		if (ret)
+			return ret;
+
+		switch (fe->dtv_property_cache.delivery_system) {
+		case SYS_DVBT:
+			ret = cxd2820r_sleep_t(fe);
+			break;
+		case SYS_DVBT2:
+			ret = cxd2820r_sleep_t2(fe);
+			break;
+		default:
+			ret = -EINVAL;
+		}
+
+		cxd2820r_unlock(priv, 0);
+	} else {
+		/* DVB-C */
+		ret = cxd2820r_lock(priv, 1);
+		if (ret)
+			return ret;
+
+		ret = cxd2820r_sleep_c(fe);
+
+		cxd2820r_unlock(priv, 1);
+	}
+
+	return ret;
+}
+
+static int cxd2820r_get_tune_settings(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+	if (fe->ops.info.type == FE_OFDM) {
+		/* DVB-T/T2 */
+		ret = cxd2820r_lock(priv, 0);
+		if (ret)
+			return ret;
+
+		switch (fe->dtv_property_cache.delivery_system) {
+		case SYS_DVBT:
+			ret = cxd2820r_get_tune_settings_t(fe, s);
+			break;
+		case SYS_DVBT2:
+			ret = cxd2820r_get_tune_settings_t2(fe, s);
+			break;
+		default:
+			ret = -EINVAL;
+		}
+	} else {
+		/* DVB-C */
+		ret = cxd2820r_lock(priv, 1);
+		if (ret)
+			return ret;
+
+		ret = cxd2820r_get_tune_settings_c(fe, s);
+	}
+
+	return ret;
+}
+
+static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i;
+	fe_status_t status = 0;
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+	/* switch between DVB-T and DVB-T2 when tune fails */
+	if (priv->last_tune_failed) {
+		if (priv->delivery_system == SYS_DVBT)
+			c->delivery_system = SYS_DVBT2;
+		else
+			c->delivery_system = SYS_DVBT;
+	}
+
+	/* set frontend */
+	ret = cxd2820r_set_frontend(fe, p);
+	if (ret)
+		goto error;
+
+
+	/* frontend lock wait loop count */
+	switch (priv->delivery_system) {
+	case SYS_DVBT:
+		i = 20;
+		break;
+	case SYS_DVBT2:
+		i = 40;
+		break;
+	case SYS_UNDEFINED:
+	default:
+		i = 0;
+		break;
+	}
+
+	/* wait frontend lock */
+	for (; i > 0; i--) {
+		dbg("%s: LOOP=%d", __func__, i);
+		msleep(50);
+		ret = cxd2820r_read_status(fe, &status);
+		if (ret)
+			goto error;
+
+		if (status & FE_HAS_SIGNAL)
+			break;
+	}
+
+	/* check if we have a valid signal */
+	if (status) {
+		priv->last_tune_failed = 0;
+		return DVBFE_ALGO_SEARCH_SUCCESS;
+	} else {
+		priv->last_tune_failed = 1;
+		return DVBFE_ALGO_SEARCH_AGAIN;
+	}
+
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return DVBFE_ALGO_SEARCH_ERROR;
+}
+
+static int cxd2820r_get_frontend_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_CUSTOM;
+}
+
+static void cxd2820r_release(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	dbg("%s", __func__);
+
+	if (fe->ops.info.type == FE_OFDM) {
+		i2c_del_adapter(&priv->tuner_i2c_adapter);
+		kfree(priv);
+	}
+
+	return;
+}
+
+static u32 cxd2820r_tuner_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static int cxd2820r_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
+	struct i2c_msg msg[], int num)
+{
+	struct cxd2820r_priv *priv = i2c_get_adapdata(i2c_adap);
+	u8 obuf[msg[0].len + 2];
+	struct i2c_msg msg2[2] = {
+		{
+			.addr = priv->cfg.i2c_address,
+			.flags = 0,
+			.len = sizeof(obuf),
+			.buf = obuf,
+		}, {
+			.addr = priv->cfg.i2c_address,
+			.flags = I2C_M_RD,
+			.len = msg[1].len,
+			.buf = msg[1].buf,
+		}
+	};
+
+	obuf[0] = 0x09;
+	obuf[1] = (msg[0].addr << 1);
+	if (num == 2) { /* I2C read */
+		obuf[1] = (msg[0].addr << 1) | I2C_M_RD; /* I2C RD flag */
+		msg2[0].len = sizeof(obuf) - 1; /* maybe HW bug ? */
+	}
+	memcpy(&obuf[2], msg[0].buf, msg[0].len);
+
+	return i2c_transfer(priv->i2c, msg2, num);
+}
+
+static struct i2c_algorithm cxd2820r_tuner_i2c_algo = {
+	.master_xfer   = cxd2820r_tuner_i2c_xfer,
+	.functionality = cxd2820r_tuner_i2c_func,
+};
+
+struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	return &priv->tuner_i2c_adapter;
+}
+EXPORT_SYMBOL(cxd2820r_get_tuner_i2c_adapter);
+
+static struct dvb_frontend_ops cxd2820r_ops[2];
+
+struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
+	struct i2c_adapter *i2c, struct dvb_frontend *fe)
+{
+	int ret;
+	struct cxd2820r_priv *priv = NULL;
+	u8 tmp;
+
+	if (fe == NULL) {
+		/* FE0 */
+		/* allocate memory for the internal priv */
+		priv = kzalloc(sizeof(struct cxd2820r_priv), GFP_KERNEL);
+		if (priv == NULL)
+			goto error;
+
+		/* setup the priv */
+		priv->i2c = i2c;
+		memcpy(&priv->cfg, cfg, sizeof(struct cxd2820r_config));
+		mutex_init(&priv->fe_lock);
+
+		priv->active_fe = -1; /* NONE */
+
+		/* check if the demod is there */
+		priv->bank[0] = priv->bank[1] = 0xff;
+		ret = cxd2820r_rd_reg(priv, 0x000fd, &tmp);
+		dbg("%s: chip id=%02x", __func__, tmp);
+		if (ret || tmp != 0xe1)
+			goto error;
+
+		/* create frontends */
+		memcpy(&priv->fe[0].ops, &cxd2820r_ops[0],
+			sizeof(struct dvb_frontend_ops));
+		memcpy(&priv->fe[1].ops, &cxd2820r_ops[1],
+			sizeof(struct dvb_frontend_ops));
+
+		priv->fe[0].demodulator_priv = priv;
+		priv->fe[1].demodulator_priv = priv;
+
+		/* create tuner i2c adapter */
+		strlcpy(priv->tuner_i2c_adapter.name,
+			"CXD2820R tuner I2C adapter",
+			sizeof(priv->tuner_i2c_adapter.name));
+		priv->tuner_i2c_adapter.algo = &cxd2820r_tuner_i2c_algo;
+		priv->tuner_i2c_adapter.algo_data = NULL;
+		i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
+		if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
+			err("tuner I2C bus could not be initialized");
+			goto error;
+		}
+
+		return &priv->fe[0];
+
+	} else {
+		/* FE1: FE0 given as pointer, just return FE1 we have
+		 * already created */
+		priv = fe->demodulator_priv;
+		return &priv->fe[1];
+	}
+
+error:
+	kfree(priv);
+	return NULL;
+}
+EXPORT_SYMBOL(cxd2820r_attach);
+
+static struct dvb_frontend_ops cxd2820r_ops[2] = {
+	{
+		/* DVB-T/T2 */
+		.info = {
+			.name = "Sony CXD2820R (DVB-T/T2)",
+			.type = FE_OFDM,
+			.caps =
+				FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
+				FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 |
+				FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+				FE_CAN_QPSK | FE_CAN_QAM_16 |
+				FE_CAN_QAM_64 | FE_CAN_QAM_256 |
+				FE_CAN_QAM_AUTO |
+				FE_CAN_TRANSMISSION_MODE_AUTO |
+				FE_CAN_GUARD_INTERVAL_AUTO |
+				FE_CAN_HIERARCHY_AUTO |
+				FE_CAN_MUTE_TS |
+				FE_CAN_2G_MODULATION
+		},
+
+		.release = cxd2820r_release,
+		.init = cxd2820r_init,
+		.sleep = cxd2820r_sleep,
+
+		.get_tune_settings = cxd2820r_get_tune_settings,
+
+		.get_frontend = cxd2820r_get_frontend,
+
+		.get_frontend_algo = cxd2820r_get_frontend_algo,
+		.search = cxd2820r_search,
+
+		.read_status = cxd2820r_read_status,
+		.read_snr = cxd2820r_read_snr,
+		.read_ber = cxd2820r_read_ber,
+		.read_ucblocks = cxd2820r_read_ucblocks,
+		.read_signal_strength = cxd2820r_read_signal_strength,
+	},
+	{
+		/* DVB-C */
+		.info = {
+			.name = "Sony CXD2820R (DVB-C)",
+			.type = FE_QAM,
+			.caps =
+				FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
+				FE_CAN_QAM_128 | FE_CAN_QAM_256 |
+				FE_CAN_FEC_AUTO
+		},
+
+		.release = cxd2820r_release,
+		.init = cxd2820r_init,
+		.sleep = cxd2820r_sleep,
+
+		.get_tune_settings = cxd2820r_get_tune_settings,
+
+		.set_frontend = cxd2820r_set_frontend,
+		.get_frontend = cxd2820r_get_frontend,
+
+		.read_status = cxd2820r_read_status,
+		.read_snr = cxd2820r_read_snr,
+		.read_ber = cxd2820r_read_ber,
+		.read_ucblocks = cxd2820r_read_ucblocks,
+		.read_signal_strength = cxd2820r_read_signal_strength,
+	},
+};
+
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Sony CXD2820R demodulator driver");
+MODULE_LICENSE("GPL");

+ 166 - 0
drivers/media/dvb/frontends/cxd2820r_priv.h

@@ -0,0 +1,166 @@
+/*
+ * Sony CXD2820R demodulator driver
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#ifndef CXD2820R_PRIV_H
+#define CXD2820R_PRIV_H
+
+#include <linux/dvb/version.h>
+#include "dvb_frontend.h"
+#include "dvb_math.h"
+#include "cxd2820r.h"
+
+#define LOG_PREFIX "cxd2820r"
+
+#undef dbg
+#define dbg(f, arg...) \
+	if (cxd2820r_debug) \
+		printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
+#undef err
+#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
+#undef info
+#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
+#undef warn
+#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
+
+struct reg_val_mask {
+	u32 reg;
+	u8  val;
+	u8  mask;
+};
+
+struct cxd2820r_priv {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend fe[2];
+	struct cxd2820r_config cfg;
+	struct i2c_adapter tuner_i2c_adapter;
+
+	struct mutex fe_lock; /* FE lock */
+	int active_fe:2; /* FE lock, -1=NONE, 0=DVB-T/T2, 1=DVB-C */
+
+	int ber_running:1;
+
+	u8 bank[2];
+	u8 gpio[3];
+
+	fe_delivery_system_t delivery_system;
+	int last_tune_failed:1; /* for switch between T and T2 tune */
+};
+
+/* cxd2820r_core.c */
+
+extern int cxd2820r_debug;
+
+int cxd2820r_gpio(struct dvb_frontend *fe);
+
+int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val,
+	u8 mask);
+
+int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
+	int len);
+
+u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor);
+
+int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
+	int len);
+
+int cxd2820r_rd_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
+	int len);
+
+int cxd2820r_wr_reg(struct cxd2820r_priv *priv, u32 reg, u8 val);
+
+int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val);
+
+/* cxd2820r_c.c */
+
+int cxd2820r_get_frontend_c(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p);
+
+int cxd2820r_set_frontend_c(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *params);
+
+int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status);
+
+int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber);
+
+int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe, u16 *strength);
+
+int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr);
+
+int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks);
+
+int cxd2820r_init_c(struct dvb_frontend *fe);
+
+int cxd2820r_sleep_c(struct dvb_frontend *fe);
+
+int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s);
+
+/* cxd2820r_t.c */
+
+int cxd2820r_get_frontend_t(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p);
+
+int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *params);
+
+int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status);
+
+int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber);
+
+int cxd2820r_read_signal_strength_t(struct dvb_frontend *fe, u16 *strength);
+
+int cxd2820r_read_snr_t(struct dvb_frontend *fe, u16 *snr);
+
+int cxd2820r_read_ucblocks_t(struct dvb_frontend *fe, u32 *ucblocks);
+
+int cxd2820r_init_t(struct dvb_frontend *fe);
+
+int cxd2820r_sleep_t(struct dvb_frontend *fe);
+
+int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s);
+
+/* cxd2820r_t2.c */
+
+int cxd2820r_get_frontend_t2(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p);
+
+int cxd2820r_set_frontend_t2(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *params);
+
+int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status);
+
+int cxd2820r_read_ber_t2(struct dvb_frontend *fe, u32 *ber);
+
+int cxd2820r_read_signal_strength_t2(struct dvb_frontend *fe, u16 *strength);
+
+int cxd2820r_read_snr_t2(struct dvb_frontend *fe, u16 *snr);
+
+int cxd2820r_read_ucblocks_t2(struct dvb_frontend *fe, u32 *ucblocks);
+
+int cxd2820r_init_t2(struct dvb_frontend *fe);
+
+int cxd2820r_sleep_t2(struct dvb_frontend *fe);
+
+int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s);
+
+#endif /* CXD2820R_PRIV_H */

+ 449 - 0
drivers/media/dvb/frontends/cxd2820r_t.c

@@ -0,0 +1,449 @@
+/*
+ * Sony CXD2820R demodulator driver
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include "cxd2820r_priv.h"
+
+int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i;
+	u32 if_khz, if_ctl;
+	u64 num;
+	u8 buf[3], bw_param;
+	u8 bw_params1[][5] = {
+		{ 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
+		{ 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */
+		{ 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */
+	};
+	u8 bw_params2[][2] = {
+		{ 0x1f, 0xdc }, /* 6 MHz */
+		{ 0x12, 0xf8 }, /* 7 MHz */
+		{ 0x01, 0xe0 }, /* 8 MHz */
+	};
+	struct reg_val_mask tab[] = {
+		{ 0x00080, 0x00, 0xff },
+		{ 0x00081, 0x03, 0xff },
+		{ 0x00085, 0x07, 0xff },
+		{ 0x00088, 0x01, 0xff },
+
+		{ 0x00070, priv->cfg.ts_mode, 0xff },
+		{ 0x000cb, priv->cfg.if_agc_polarity << 6, 0x40 },
+		{ 0x000a5, 0x00, 0x01 },
+		{ 0x00082, 0x20, 0x60 },
+		{ 0x000c2, 0xc3, 0xff },
+		{ 0x0016a, 0x50, 0xff },
+		{ 0x00427, 0x41, 0xff },
+	};
+
+	dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz);
+
+	/* update GPIOs */
+	ret = cxd2820r_gpio(fe);
+	if (ret)
+		goto error;
+
+	/* program tuner */
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe, p);
+
+	if (priv->delivery_system != SYS_DVBT) {
+		for (i = 0; i < ARRAY_SIZE(tab); i++) {
+			ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
+				tab[i].val, tab[i].mask);
+			if (ret)
+				goto error;
+		}
+	}
+
+	priv->delivery_system = SYS_DVBT;
+	priv->ber_running = 0; /* tune stops BER counter */
+
+	switch (c->bandwidth_hz) {
+	case 6000000:
+		if_khz = priv->cfg.if_dvbt_6;
+		i = 0;
+		bw_param = 2;
+		break;
+	case 7000000:
+		if_khz = priv->cfg.if_dvbt_7;
+		i = 1;
+		bw_param = 1;
+		break;
+	case 8000000:
+		if_khz = priv->cfg.if_dvbt_8;
+		i = 2;
+		bw_param = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	num = if_khz;
+	num *= 0x1000000;
+	if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
+	buf[0] = ((if_ctl >> 16) & 0xff);
+	buf[1] = ((if_ctl >>  8) & 0xff);
+	buf[2] = ((if_ctl >>  0) & 0xff);
+
+	ret = cxd2820r_wr_regs(priv, 0x000b6, buf, 3);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_regs(priv, 0x0009f, bw_params1[i], 5);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_reg_mask(priv, 0x000d7, bw_param << 6, 0xc0);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_regs(priv, 0x000d9, bw_params2[i], 2);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_get_frontend_t(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret;
+	u8 buf[2];
+
+	ret = cxd2820r_rd_regs(priv, 0x0002f, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+	switch ((buf[0] >> 6) & 0x03) {
+	case 0:
+		c->modulation = QPSK;
+		break;
+	case 1:
+		c->modulation = QAM_16;
+		break;
+	case 2:
+		c->modulation = QAM_64;
+		break;
+	}
+
+	switch ((buf[1] >> 1) & 0x03) {
+	case 0:
+		c->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		c->transmission_mode = TRANSMISSION_MODE_8K;
+		break;
+	}
+
+	switch ((buf[1] >> 3) & 0x03) {
+	case 0:
+		c->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		c->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		c->guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		c->guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	}
+
+	switch ((buf[0] >> 3) & 0x07) {
+	case 0:
+		c->hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		c->hierarchy = HIERARCHY_1;
+		break;
+	case 2:
+		c->hierarchy = HIERARCHY_2;
+		break;
+	case 3:
+		c->hierarchy = HIERARCHY_4;
+		break;
+	}
+
+	switch ((buf[0] >> 0) & 0x07) {
+	case 0:
+		c->code_rate_HP = FEC_1_2;
+		break;
+	case 1:
+		c->code_rate_HP = FEC_2_3;
+		break;
+	case 2:
+		c->code_rate_HP = FEC_3_4;
+		break;
+	case 3:
+		c->code_rate_HP = FEC_5_6;
+		break;
+	case 4:
+		c->code_rate_HP = FEC_7_8;
+		break;
+	}
+
+	switch ((buf[1] >> 5) & 0x07) {
+	case 0:
+		c->code_rate_LP = FEC_1_2;
+		break;
+	case 1:
+		c->code_rate_LP = FEC_2_3;
+		break;
+	case 2:
+		c->code_rate_LP = FEC_3_4;
+		break;
+	case 3:
+		c->code_rate_LP = FEC_5_6;
+		break;
+	case 4:
+		c->code_rate_LP = FEC_7_8;
+		break;
+	}
+
+	ret = cxd2820r_rd_reg(priv, 0x007c6, &buf[0]);
+	if (ret)
+		goto error;
+
+	switch ((buf[0] >> 0) & 0x01) {
+	case 0:
+		c->inversion = INVERSION_OFF;
+		break;
+	case 1:
+		c->inversion = INVERSION_ON;
+		break;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[3], start_ber = 0;
+	*ber = 0;
+
+	if (priv->ber_running) {
+		ret = cxd2820r_rd_regs(priv, 0x00076, buf, sizeof(buf));
+		if (ret)
+			goto error;
+
+		if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) {
+			*ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0];
+			start_ber = 1;
+		}
+	} else {
+		priv->ber_running = 1;
+		start_ber = 1;
+	}
+
+	if (start_ber) {
+		/* (re)start BER */
+		ret = cxd2820r_wr_reg(priv, 0x00079, 0x01);
+		if (ret)
+			goto error;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_signal_strength_t(struct dvb_frontend *fe,
+	u16 *strength)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+	u16 tmp;
+
+	ret = cxd2820r_rd_regs(priv, 0x00026, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+	tmp = (buf[0] & 0x0f) << 8 | buf[1];
+	tmp = ~tmp & 0x0fff;
+
+	/* scale value to 0x0000-0xffff from 0x0000-0x0fff */
+	*strength = tmp * 0xffff / 0x0fff;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_snr_t(struct dvb_frontend *fe, u16 *snr)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+	u16 tmp;
+	/* report SNR in dB * 10 */
+
+	ret = cxd2820r_rd_regs(priv, 0x00028, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+	tmp = (buf[0] & 0x1f) << 8 | buf[1];
+	#define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */
+	if (tmp)
+		*snr = (intlog10(tmp) - CXD2820R_LOG10_8_24) / ((1 << 24)
+			/ 100);
+	else
+		*snr = 0;
+
+	dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp);
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_ucblocks_t(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	*ucblocks = 0;
+	/* no way to read ? */
+	return 0;
+}
+
+int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[4];
+	*status = 0;
+
+	ret = cxd2820r_rd_reg(priv, 0x00010, &buf[0]);
+	if (ret)
+		goto error;
+
+	if ((buf[0] & 0x07) == 6) {
+		ret = cxd2820r_rd_reg(priv, 0x00073, &buf[1]);
+		if (ret)
+			goto error;
+
+		if (((buf[1] >> 3) & 0x01) == 1) {
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+		} else {
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI | FE_HAS_SYNC;
+		}
+	} else {
+		ret = cxd2820r_rd_reg(priv, 0x00014, &buf[2]);
+		if (ret)
+			goto error;
+
+		if ((buf[2] & 0x0f) >= 4) {
+			ret = cxd2820r_rd_reg(priv, 0x00a14, &buf[3]);
+			if (ret)
+				goto error;
+
+			if (((buf[3] >> 4) & 0x01) == 1)
+				*status |= FE_HAS_SIGNAL;
+		}
+	}
+
+	dbg("%s: lock=%02x %02x %02x %02x", __func__,
+		buf[0], buf[1], buf[2], buf[3]);
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_init_t(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+
+	ret = cxd2820r_wr_reg(priv, 0x00085, 0x07);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_sleep_t(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret, i;
+	struct reg_val_mask tab[] = {
+		{ 0x000ff, 0x1f, 0xff },
+		{ 0x00085, 0x00, 0xff },
+		{ 0x00088, 0x01, 0xff },
+		{ 0x00081, 0x00, 0xff },
+		{ 0x00080, 0x00, 0xff },
+	};
+
+	dbg("%s", __func__);
+
+	priv->delivery_system = SYS_UNDEFINED;
+
+	for (i = 0; i < ARRAY_SIZE(tab); i++) {
+		ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val,
+			tab[i].mask);
+		if (ret)
+			goto error;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s)
+{
+	s->min_delay_ms = 500;
+	s->step_size = fe->ops.info.frequency_stepsize * 2;
+	s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
+
+	return 0;
+}
+

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

@@ -0,0 +1,423 @@
+/*
+ * Sony CXD2820R demodulator driver
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include "cxd2820r_priv.h"
+
+int cxd2820r_set_frontend_t2(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *params)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i;
+	u32 if_khz, if_ctl;
+	u64 num;
+	u8 buf[3], bw_param;
+	u8 bw_params1[][5] = {
+		{ 0x1c, 0xb3, 0x33, 0x33, 0x33 }, /* 5 MHz */
+		{ 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
+		{ 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */
+		{ 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */
+	};
+	struct reg_val_mask tab[] = {
+		{ 0x00080, 0x02, 0xff },
+		{ 0x00081, 0x20, 0xff },
+		{ 0x00085, 0x07, 0xff },
+		{ 0x00088, 0x01, 0xff },
+		{ 0x02069, 0x01, 0xff },
+
+		{ 0x0207f, 0x2a, 0xff },
+		{ 0x02082, 0x0a, 0xff },
+		{ 0x02083, 0x0a, 0xff },
+		{ 0x020cb, priv->cfg.if_agc_polarity << 6, 0x40 },
+		{ 0x02070, priv->cfg.ts_mode, 0xff },
+		{ 0x020b5, priv->cfg.spec_inv << 4, 0x10 },
+		{ 0x02567, 0x07, 0x0f },
+		{ 0x02569, 0x03, 0x03 },
+		{ 0x02595, 0x1a, 0xff },
+		{ 0x02596, 0x50, 0xff },
+		{ 0x02a8c, 0x00, 0xff },
+		{ 0x02a8d, 0x34, 0xff },
+		{ 0x02a45, 0x06, 0x07 },
+		{ 0x03f10, 0x0d, 0xff },
+		{ 0x03f11, 0x02, 0xff },
+		{ 0x03f12, 0x01, 0xff },
+		{ 0x03f23, 0x2c, 0xff },
+		{ 0x03f51, 0x13, 0xff },
+		{ 0x03f52, 0x01, 0xff },
+		{ 0x03f53, 0x00, 0xff },
+		{ 0x027e6, 0x14, 0xff },
+		{ 0x02786, 0x02, 0x07 },
+		{ 0x02787, 0x40, 0xe0 },
+		{ 0x027ef, 0x10, 0x18 },
+	};
+
+	dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz);
+
+	/* update GPIOs */
+	ret = cxd2820r_gpio(fe);
+	if (ret)
+		goto error;
+
+	/* program tuner */
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe, params);
+
+	if (priv->delivery_system != SYS_DVBT2) {
+		for (i = 0; i < ARRAY_SIZE(tab); i++) {
+			ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
+				tab[i].val, tab[i].mask);
+			if (ret)
+				goto error;
+		}
+	}
+
+	priv->delivery_system = SYS_DVBT2;
+
+	switch (c->bandwidth_hz) {
+	case 5000000:
+		if_khz = priv->cfg.if_dvbt2_5;
+		i = 0;
+		bw_param = 3;
+		break;
+	case 6000000:
+		if_khz = priv->cfg.if_dvbt2_6;
+		i = 1;
+		bw_param = 2;
+		break;
+	case 7000000:
+		if_khz = priv->cfg.if_dvbt2_7;
+		i = 2;
+		bw_param = 1;
+		break;
+	case 8000000:
+		if_khz = priv->cfg.if_dvbt2_8;
+		i = 3;
+		bw_param = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	num = if_khz;
+	num *= 0x1000000;
+	if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
+	buf[0] = ((if_ctl >> 16) & 0xff);
+	buf[1] = ((if_ctl >>  8) & 0xff);
+	buf[2] = ((if_ctl >>  0) & 0xff);
+
+	ret = cxd2820r_wr_regs(priv, 0x020b6, buf, 3);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_regs(priv, 0x0209f, bw_params1[i], 5);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_reg_mask(priv, 0x020d7, bw_param << 6, 0xc0);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+
+}
+
+int cxd2820r_get_frontend_t2(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *p)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret;
+	u8 buf[2];
+
+	ret = cxd2820r_rd_regs(priv, 0x0205c, buf, 2);
+	if (ret)
+		goto error;
+
+	switch ((buf[0] >> 0) & 0x07) {
+	case 0:
+		c->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		c->transmission_mode = TRANSMISSION_MODE_8K;
+		break;
+	case 2:
+		c->transmission_mode = TRANSMISSION_MODE_4K;
+		break;
+	case 3:
+		c->transmission_mode = TRANSMISSION_MODE_1K;
+		break;
+	case 4:
+		c->transmission_mode = TRANSMISSION_MODE_16K;
+		break;
+	case 5:
+		c->transmission_mode = TRANSMISSION_MODE_32K;
+		break;
+	}
+
+	switch ((buf[1] >> 4) & 0x07) {
+	case 0:
+		c->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		c->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		c->guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		c->guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	case 4:
+		c->guard_interval = GUARD_INTERVAL_1_128;
+		break;
+	case 5:
+		c->guard_interval = GUARD_INTERVAL_19_128;
+		break;
+	case 6:
+		c->guard_interval = GUARD_INTERVAL_19_256;
+		break;
+	}
+
+	ret = cxd2820r_rd_regs(priv, 0x0225b, buf, 2);
+	if (ret)
+		goto error;
+
+	switch ((buf[0] >> 0) & 0x07) {
+	case 0:
+		c->fec_inner = FEC_1_2;
+		break;
+	case 1:
+		c->fec_inner = FEC_3_5;
+		break;
+	case 2:
+		c->fec_inner = FEC_2_3;
+		break;
+	case 3:
+		c->fec_inner = FEC_3_4;
+		break;
+	case 4:
+		c->fec_inner = FEC_4_5;
+		break;
+	case 5:
+		c->fec_inner = FEC_5_6;
+		break;
+	}
+
+	switch ((buf[1] >> 0) & 0x07) {
+	case 0:
+		c->modulation = QPSK;
+		break;
+	case 1:
+		c->modulation = QAM_16;
+		break;
+	case 2:
+		c->modulation = QAM_64;
+		break;
+	case 3:
+		c->modulation = QAM_256;
+		break;
+	}
+
+	ret = cxd2820r_rd_reg(priv, 0x020b5, &buf[0]);
+	if (ret)
+		goto error;
+
+	switch ((buf[0] >> 4) & 0x01) {
+	case 0:
+		c->inversion = INVERSION_OFF;
+		break;
+	case 1:
+		c->inversion = INVERSION_ON;
+		break;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[1];
+	*status = 0;
+
+	ret = cxd2820r_rd_reg(priv, 0x02010 , &buf[0]);
+	if (ret)
+		goto error;
+
+	if ((buf[0] & 0x07) == 6) {
+		if (((buf[0] >> 5) & 0x01) == 1) {
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+		} else {
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI | FE_HAS_SYNC;
+		}
+	}
+
+	dbg("%s: lock=%02x", __func__, buf[0]);
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_ber_t2(struct dvb_frontend *fe, u32 *ber)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[4];
+	unsigned int errbits;
+	*ber = 0;
+	/* FIXME: correct calculation */
+
+	ret = cxd2820r_rd_regs(priv, 0x02039, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+	if ((buf[0] >> 4) & 0x01) {
+		errbits = (buf[0] & 0x0f) << 24 | buf[1] << 16 |
+			buf[2] << 8 | buf[3];
+
+		if (errbits)
+			*ber = errbits * 64 / 16588800;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_signal_strength_t2(struct dvb_frontend *fe,
+	u16 *strength)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+	u16 tmp;
+
+	ret = cxd2820r_rd_regs(priv, 0x02026, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+	tmp = (buf[0] & 0x0f) << 8 | buf[1];
+	tmp = ~tmp & 0x0fff;
+
+	/* scale value to 0x0000-0xffff from 0x0000-0x0fff */
+	*strength = tmp * 0xffff / 0x0fff;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_snr_t2(struct dvb_frontend *fe, u16 *snr)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+	u16 tmp;
+	/* report SNR in dB * 10 */
+
+	ret = cxd2820r_rd_regs(priv, 0x02028, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+	tmp = (buf[0] & 0x0f) << 8 | buf[1];
+	#define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */
+	if (tmp)
+		*snr = (intlog10(tmp) - CXD2820R_LOG10_8_24) / ((1 << 24)
+			/ 100);
+	else
+		*snr = 0;
+
+	dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp);
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_ucblocks_t2(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	*ucblocks = 0;
+	/* no way to read ? */
+	return 0;
+}
+
+int cxd2820r_sleep_t2(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret, i;
+	struct reg_val_mask tab[] = {
+		{ 0x000ff, 0x1f, 0xff },
+		{ 0x00085, 0x00, 0xff },
+		{ 0x00088, 0x01, 0xff },
+		{ 0x02069, 0x00, 0xff },
+		{ 0x00081, 0x00, 0xff },
+		{ 0x00080, 0x00, 0xff },
+	};
+
+	dbg("%s", __func__);
+
+	for (i = 0; i < ARRAY_SIZE(tab); i++) {
+		ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val,
+			tab[i].mask);
+		if (ret)
+			goto error;
+	}
+
+	priv->delivery_system = SYS_UNDEFINED;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s)
+{
+	s->min_delay_ms = 1500;
+	s->step_size = fe->ops.info.frequency_stepsize * 2;
+	s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
+
+	return 0;
+}
+

+ 30 - 10
drivers/media/dvb/frontends/dib0070.c

@@ -73,27 +73,47 @@ struct dib0070_state {
 
     u8  wbd_gain_current;
 	u16 wbd_offset_3_3[2];
+
+	/* for the I2C transfer */
+	struct i2c_msg msg[2];
+	u8 i2c_write_buffer[3];
+	u8 i2c_read_buffer[2];
 };
 
 static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
 {
-	u8 b[2];
-	struct i2c_msg msg[2] = {
-		{ .addr = state->cfg->i2c_address, .flags = 0,        .buf = &reg, .len = 1 },
-		{ .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b,  .len = 2 },
-	};
-	if (i2c_transfer(state->i2c, msg, 2) != 2) {
+	state->i2c_write_buffer[0] = reg;
+
+	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+	state->msg[0].addr = state->cfg->i2c_address;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 1;
+	state->msg[1].addr = state->cfg->i2c_address;
+	state->msg[1].flags = I2C_M_RD;
+	state->msg[1].buf = state->i2c_read_buffer;
+	state->msg[1].len = 2;
+
+	if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
 		printk(KERN_WARNING "DiB0070 I2C read failed\n");
 		return 0;
 	}
-	return (b[0] << 8) | b[1];
+	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
 }
 
 static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
 {
-	u8 b[3] = { reg, val >> 8, val & 0xff };
-	struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 };
-	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+	state->i2c_write_buffer[0] = reg;
+	state->i2c_write_buffer[1] = val >> 8;
+	state->i2c_write_buffer[2] = val & 0xff;
+
+	memset(state->msg, 0, sizeof(struct i2c_msg));
+	state->msg[0].addr = state->cfg->i2c_address;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 3;
+
+	if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
 		printk(KERN_WARNING "DiB0070 I2C write failed\n");
 		return -EREMOTEIO;
 	}

+ 54 - 17
drivers/media/dvb/frontends/dib0090.c

@@ -191,6 +191,11 @@ struct dib0090_state {
 	u8 wbd_calibration_gain;
 	const struct dib0090_wbd_slope *current_wbd_table;
 	u16 wbdmux;
+
+	/* for the I2C transfer */
+	struct i2c_msg msg[2];
+	u8 i2c_write_buffer[3];
+	u8 i2c_read_buffer[2];
 };
 
 struct dib0090_fw_state {
@@ -198,27 +203,48 @@ struct dib0090_fw_state {
 	struct dvb_frontend *fe;
 	struct dib0090_identity identity;
 	const struct dib0090_config *config;
+
+	/* for the I2C transfer */
+	struct i2c_msg msg;
+	u8 i2c_write_buffer[2];
+	u8 i2c_read_buffer[2];
 };
 
 static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
 {
-	u8 b[2];
-	struct i2c_msg msg[2] = {
-		{.addr = state->config->i2c_address, .flags = 0, .buf = &reg, .len = 1},
-		{.addr = state->config->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2},
-	};
-	if (i2c_transfer(state->i2c, msg, 2) != 2) {
+	state->i2c_write_buffer[0] = reg;
+
+	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+	state->msg[0].addr = state->config->i2c_address;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 1;
+	state->msg[1].addr = state->config->i2c_address;
+	state->msg[1].flags = I2C_M_RD;
+	state->msg[1].buf = state->i2c_read_buffer;
+	state->msg[1].len = 2;
+
+	if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
 		printk(KERN_WARNING "DiB0090 I2C read failed\n");
 		return 0;
 	}
-	return (b[0] << 8) | b[1];
+
+	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
 }
 
 static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
 {
-	u8 b[3] = { reg & 0xff, val >> 8, val & 0xff };
-	struct i2c_msg msg = {.addr = state->config->i2c_address, .flags = 0, .buf = b, .len = 3 };
-	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+	state->i2c_write_buffer[0] = reg & 0xff;
+	state->i2c_write_buffer[1] = val >> 8;
+	state->i2c_write_buffer[2] = val & 0xff;
+
+	memset(state->msg, 0, sizeof(struct i2c_msg));
+	state->msg[0].addr = state->config->i2c_address;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 3;
+
+	if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
 		printk(KERN_WARNING "DiB0090 I2C write failed\n");
 		return -EREMOTEIO;
 	}
@@ -227,20 +253,31 @@ static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
 
 static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
 {
-	u8 b[2];
-	struct i2c_msg msg = {.addr = reg, .flags = I2C_M_RD, .buf = b, .len = 2 };
-	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+	state->i2c_write_buffer[0] = reg;
+
+	memset(&state->msg, 0, sizeof(struct i2c_msg));
+	state->msg.addr = reg;
+	state->msg.flags = I2C_M_RD;
+	state->msg.buf = state->i2c_read_buffer;
+	state->msg.len = 2;
+	if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
 		printk(KERN_WARNING "DiB0090 I2C read failed\n");
 		return 0;
 	}
-	return (b[0] << 8) | b[1];
+	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
 }
 
 static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
 {
-	u8 b[2] = { val >> 8, val & 0xff };
-	struct i2c_msg msg = {.addr = reg, .flags = 0, .buf = b, .len = 2 };
-	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+	state->i2c_write_buffer[0] = val >> 8;
+	state->i2c_write_buffer[1] = val & 0xff;
+
+	memset(&state->msg, 0, sizeof(struct i2c_msg));
+	state->msg.addr = reg;
+	state->msg.flags = 0;
+	state->msg.buf = state->i2c_write_buffer;
+	state->msg.len = 2;
+	if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
 		printk(KERN_WARNING "DiB0090 I2C write failed\n");
 		return -EREMOTEIO;
 	}

+ 32 - 17
drivers/media/dvb/frontends/dib7000m.c

@@ -50,6 +50,11 @@ struct dib7000m_state {
 	u16 revision;
 
 	u8 agc_state;
+
+	/* for the I2C transfer */
+	struct i2c_msg msg[2];
+	u8 i2c_write_buffer[4];
+	u8 i2c_read_buffer[2];
 };
 
 enum dib7000m_power_mode {
@@ -64,29 +69,39 @@ enum dib7000m_power_mode {
 
 static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
 {
-	u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
-	u8 rb[2];
-	struct i2c_msg msg[2] = {
-		{ .addr = state->i2c_addr >> 1, .flags = 0,        .buf = wb, .len = 2 },
-		{ .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
-	};
-
-	if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
+	state->i2c_write_buffer[0] = (reg >> 8) | 0x80;
+	state->i2c_write_buffer[1] = reg & 0xff;
+
+	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c_addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 2;
+	state->msg[1].addr = state->i2c_addr >> 1;
+	state->msg[1].flags = I2C_M_RD;
+	state->msg[1].buf = state->i2c_read_buffer;
+	state->msg[1].len = 2;
+
+	if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
 		dprintk("i2c read error on %d",reg);
 
-	return (rb[0] << 8) | rb[1];
+	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
 }
 
 static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
 {
-	u8 b[4] = {
-		(reg >> 8) & 0xff, reg & 0xff,
-		(val >> 8) & 0xff, val & 0xff,
-	};
-	struct i2c_msg msg = {
-		.addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
-	};
-	return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+	state->i2c_write_buffer[1] = reg & 0xff;
+	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
+	state->i2c_write_buffer[3] = val & 0xff;
+
+	memset(&state->msg[0], 0, sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c_addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 4;
+
+	return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
 }
 static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
 {

+ 52 - 20
drivers/media/dvb/frontends/dib7000p.c

@@ -63,6 +63,11 @@ struct dib7000p_state {
 
 	u16 tuner_enable;
 	struct i2c_adapter dib7090_tuner_adap;
+
+	/* for the I2C transfer */
+	struct i2c_msg msg[2];
+	u8 i2c_write_buffer[4];
+	u8 i2c_read_buffer[2];
 };
 
 enum dib7000p_power_mode {
@@ -76,29 +81,39 @@ static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff);
 
 static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
 {
-	u8 wb[2] = { reg >> 8, reg & 0xff };
-	u8 rb[2];
-	struct i2c_msg msg[2] = {
-		{.addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
-		{.addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2},
-	};
+	state->i2c_write_buffer[0] = reg >> 8;
+	state->i2c_write_buffer[1] = reg & 0xff;
+
+	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c_addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 2;
+	state->msg[1].addr = state->i2c_addr >> 1;
+	state->msg[1].flags = I2C_M_RD;
+	state->msg[1].buf = state->i2c_read_buffer;
+	state->msg[1].len = 2;
 
-	if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
+	if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
 		dprintk("i2c read error on %d", reg);
 
-	return (rb[0] << 8) | rb[1];
+	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
 }
 
 static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
 {
-	u8 b[4] = {
-		(reg >> 8) & 0xff, reg & 0xff,
-		(val >> 8) & 0xff, val & 0xff,
-	};
-	struct i2c_msg msg = {
-		.addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
-	};
-	return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+	state->i2c_write_buffer[1] = reg & 0xff;
+	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
+	state->i2c_write_buffer[3] = val & 0xff;
+
+	memset(&state->msg[0], 0, sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c_addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 4;
+
+	return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
 }
 
 static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
@@ -1550,11 +1565,24 @@ static void dib7000p_release(struct dvb_frontend *demod)
 
 int dib7000pc_detection(struct i2c_adapter *i2c_adap)
 {
-	u8 tx[2], rx[2];
+	u8 *tx, *rx;
 	struct i2c_msg msg[2] = {
-		{.addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2},
-		{.addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2},
+		{.addr = 18 >> 1, .flags = 0, .len = 2},
+		{.addr = 18 >> 1, .flags = I2C_M_RD, .len = 2},
 	};
+	int ret = 0;
+
+	tx = kzalloc(2*sizeof(u8), GFP_KERNEL);
+	if (!tx)
+		return -ENOMEM;
+	rx = kzalloc(2*sizeof(u8), GFP_KERNEL);
+	if (!rx) {
+		goto rx_memory_error;
+		ret = -ENOMEM;
+	}
+
+	msg[0].buf = tx;
+	msg[1].buf = rx;
 
 	tx[0] = 0x03;
 	tx[1] = 0x00;
@@ -1574,7 +1602,11 @@ int dib7000pc_detection(struct i2c_adapter *i2c_adap)
 		}
 
 	dprintk("-D-  DiB7000PC not detected");
-	return 0;
+
+	kfree(rx);
+rx_memory_error:
+	kfree(tx);
+	return ret;
 }
 EXPORT_SYMBOL(dib7000pc_detection);
 

+ 94 - 32
drivers/media/dvb/frontends/dib8000.c

@@ -35,6 +35,8 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
 struct i2c_device {
 	struct i2c_adapter *adap;
 	u8 addr;
+	u8 *i2c_write_buffer;
+	u8 *i2c_read_buffer;
 };
 
 struct dib8000_state {
@@ -70,6 +72,11 @@ struct dib8000_state {
 	u32 status;
 
 	struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
+
+	/* for the I2C transfer */
+	struct i2c_msg msg[2];
+	u8 i2c_write_buffer[4];
+	u8 i2c_read_buffer[2];
 };
 
 enum dib8000_power_mode {
@@ -79,22 +86,41 @@ enum dib8000_power_mode {
 
 static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
 {
-	u8 wb[2] = { reg >> 8, reg & 0xff };
-	u8 rb[2];
 	struct i2c_msg msg[2] = {
-		{.addr = i2c->addr >> 1,.flags = 0,.buf = wb,.len = 2},
-		{.addr = i2c->addr >> 1,.flags = I2C_M_RD,.buf = rb,.len = 2},
+		{.addr = i2c->addr >> 1, .flags = 0,
+			.buf = i2c->i2c_write_buffer, .len = 2},
+		{.addr = i2c->addr >> 1, .flags = I2C_M_RD,
+			.buf = i2c->i2c_read_buffer, .len = 2},
 	};
 
+	msg[0].buf[0] = reg >> 8;
+	msg[0].buf[1] = reg & 0xff;
+
 	if (i2c_transfer(i2c->adap, msg, 2) != 2)
 		dprintk("i2c read error on %d", reg);
 
-	return (rb[0] << 8) | rb[1];
+	return (msg[1].buf[0] << 8) | msg[1].buf[1];
 }
 
 static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
 {
-	return dib8000_i2c_read16(&state->i2c, reg);
+	state->i2c_write_buffer[0] = reg >> 8;
+	state->i2c_write_buffer[1] = reg & 0xff;
+
+	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c.addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 2;
+	state->msg[1].addr = state->i2c.addr >> 1;
+	state->msg[1].flags = I2C_M_RD;
+	state->msg[1].buf = state->i2c_read_buffer;
+	state->msg[1].len = 2;
+
+	if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2)
+		dprintk("i2c read error on %d", reg);
+
+	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
 }
 
 static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
@@ -109,19 +135,34 @@ static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
 
 static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
 {
-	u8 b[4] = {
-		(reg >> 8) & 0xff, reg & 0xff,
-		(val >> 8) & 0xff, val & 0xff,
-	};
-	struct i2c_msg msg = {
-		.addr = i2c->addr >> 1,.flags = 0,.buf = b,.len = 4
-	};
-	return i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+	struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0,
+		.buf = i2c->i2c_write_buffer, .len = 4};
+	int ret = 0;
+
+	msg.buf[0] = (reg >> 8) & 0xff;
+	msg.buf[1] = reg & 0xff;
+	msg.buf[2] = (val >> 8) & 0xff;
+	msg.buf[3] = val & 0xff;
+
+	ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+
+	return ret;
 }
 
 static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
 {
-	return dib8000_i2c_write16(&state->i2c, reg, val);
+	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+	state->i2c_write_buffer[1] = reg & 0xff;
+	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
+	state->i2c_write_buffer[3] = val & 0xff;
+
+	memset(&state->msg[0], 0, sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c.addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 4;
+
+	return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
 }
 
 static const s16 coeff_2k_sb_1seg_dqpsk[8] = {
@@ -980,30 +1021,31 @@ static void dib8000_update_timf(struct dib8000_state *state)
 	dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default);
 }
 
+static const u16 adc_target_16dB[11] = {
+	(1 << 13) - 825 - 117,
+	(1 << 13) - 837 - 117,
+	(1 << 13) - 811 - 117,
+	(1 << 13) - 766 - 117,
+	(1 << 13) - 737 - 117,
+	(1 << 13) - 693 - 117,
+	(1 << 13) - 648 - 117,
+	(1 << 13) - 619 - 117,
+	(1 << 13) - 575 - 117,
+	(1 << 13) - 531 - 117,
+	(1 << 13) - 501 - 117
+};
+static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
+
 static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosearching)
 {
 	u16 mode, max_constellation, seg_diff_mask = 0, nbseg_diff = 0;
 	u8 guard, crate, constellation, timeI;
-	u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
 	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;
-	u16 adc_target_16dB[11] = {
-		(1 << 13) - 825 - 117,
-		(1 << 13) - 837 - 117,
-		(1 << 13) - 811 - 117,
-		(1 << 13) - 766 - 117,
-		(1 << 13) - 737 - 117,
-		(1 << 13) - 693 - 117,
-		(1 << 13) - 648 - 117,
-		(1 << 13) - 619 - 117,
-		(1 << 13) - 575 - 117,
-		(1 << 13) - 531 - 117,
-		(1 << 13) - 501 - 117
-	};
 
 	if (state->ber_monitored_layer != LAYER_ALL)
 		dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer);
@@ -2379,10 +2421,22 @@ EXPORT_SYMBOL(dib8000_get_slave_frontend);
 
 int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
 {
-	int k = 0;
+	int k = 0, ret = 0;
 	u8 new_addr = 0;
 	struct i2c_device client = {.adap = host };
 
+	client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+	if (!client.i2c_write_buffer) {
+		dprintk("%s: not enough memory", __func__);
+		return -ENOMEM;
+	}
+	client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+	if (!client.i2c_read_buffer) {
+		dprintk("%s: not enough memory", __func__);
+		ret = -ENOMEM;
+		goto error_memory;
+	}
+
 	for (k = no_of_demods - 1; k >= 0; k--) {
 		/* designated i2c address */
 		new_addr = first_addr + (k << 1);
@@ -2394,7 +2448,8 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau
 			client.addr = default_addr;
 			if (dib8000_identify(&client) == 0) {
 				dprintk("#%d: not identified", k);
-				return -EINVAL;
+				ret  = -EINVAL;
+				goto error;
 			}
 		}
 
@@ -2420,7 +2475,12 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau
 		dib8000_i2c_write16(&client, 1286, 0);
 	}
 
-	return 0;
+error:
+	kfree(client.i2c_read_buffer);
+error_memory:
+	kfree(client.i2c_write_buffer);
+
+	return ret;
 }
 
 EXPORT_SYMBOL(dib8000_i2c_enumeration);
@@ -2519,6 +2579,8 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s
 	memcpy(&state->cfg, cfg, sizeof(struct dib8000_config));
 	state->i2c.adap = i2c_adap;
 	state->i2c.addr = i2c_addr;
+	state->i2c.i2c_write_buffer = state->i2c_write_buffer;
+	state->i2c.i2c_read_buffer = state->i2c_read_buffer;
 	state->gpio_val = cfg->gpio_val;
 	state->gpio_dir = cfg->gpio_dir;
 

+ 114 - 62
drivers/media/dvb/frontends/dib9000.c

@@ -27,6 +27,8 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
 struct i2c_device {
 	struct i2c_adapter *i2c_adap;
 	u8 i2c_addr;
+	u8 *i2c_read_buffer;
+	u8 *i2c_write_buffer;
 };
 
 /* lock */
@@ -92,11 +94,16 @@ struct dib9000_state {
 
 	struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
 	u16 component_bus_speed;
+
+	/* for the I2C transfer */
+	struct i2c_msg msg[2];
+	u8 i2c_write_buffer[255];
+	u8 i2c_read_buffer[255];
 };
 
-u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0
+	0, 0, 0, 0, 0, 0, 0, 0
 };
 
 enum dib9000_power_mode {
@@ -217,25 +224,33 @@ static u16 dib9000_read16_attr(struct dib9000_state *state, u16 reg, u8 * b, u32
 	u32 chunk_size = 126;
 	u32 l;
 	int ret;
-	u8 wb[2] = { reg >> 8, reg & 0xff };
-	struct i2c_msg msg[2] = {
-		{.addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
-		{.addr = state->i2c.i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = len},
-	};
 
 	if (state->platform.risc.fw_is_running && (reg < 1024))
 		return dib9000_risc_apb_access_read(state, reg, attribute, NULL, 0, b, len);
 
+	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c.i2c_addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 2;
+	state->msg[1].addr = state->i2c.i2c_addr >> 1;
+	state->msg[1].flags = I2C_M_RD;
+	state->msg[1].buf = b;
+	state->msg[1].len = len;
+
+	state->i2c_write_buffer[0] = reg >> 8;
+	state->i2c_write_buffer[1] = reg & 0xff;
+
 	if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
-		wb[0] |= (1 << 5);
+		state->i2c_write_buffer[0] |= (1 << 5);
 	if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
-		wb[0] |= (1 << 4);
+		state->i2c_write_buffer[0] |= (1 << 4);
 
 	do {
 		l = len < chunk_size ? len : chunk_size;
-		msg[1].len = l;
-		msg[1].buf = b;
-		ret = i2c_transfer(state->i2c.i2c_adap, msg, 2) != 2 ? -EREMOTEIO : 0;
+		state->msg[1].len = l;
+		state->msg[1].buf = b;
+		ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 2) != 2 ? -EREMOTEIO : 0;
 		if (ret != 0) {
 			dprintk("i2c read error on %d", reg);
 			return -EREMOTEIO;
@@ -253,50 +268,47 @@ static u16 dib9000_read16_attr(struct dib9000_state *state, u16 reg, u8 * b, u32
 
 static u16 dib9000_i2c_read16(struct i2c_device *i2c, u16 reg)
 {
-	u8 b[2];
-	u8 wb[2] = { reg >> 8, reg & 0xff };
 	struct i2c_msg msg[2] = {
-		{.addr = i2c->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
-		{.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = 2},
+		{.addr = i2c->i2c_addr >> 1, .flags = 0,
+			.buf = i2c->i2c_write_buffer, .len = 2},
+		{.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD,
+			.buf = i2c->i2c_read_buffer, .len = 2},
 	};
 
+	i2c->i2c_write_buffer[0] = reg >> 8;
+	i2c->i2c_write_buffer[1] = reg & 0xff;
+
 	if (i2c_transfer(i2c->i2c_adap, msg, 2) != 2) {
 		dprintk("read register %x error", reg);
 		return 0;
 	}
 
-	return (b[0] << 8) | b[1];
+	return (i2c->i2c_read_buffer[0] << 8) | i2c->i2c_read_buffer[1];
 }
 
 static inline u16 dib9000_read_word(struct dib9000_state *state, u16 reg)
 {
-	u8 b[2];
-	if (dib9000_read16_attr(state, reg, b, 2, 0) != 0)
+	if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2, 0) != 0)
 		return 0;
-	return (b[0] << 8 | b[1]);
+	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
 }
 
 static inline u16 dib9000_read_word_attr(struct dib9000_state *state, u16 reg, u16 attribute)
 {
-	u8 b[2];
-	if (dib9000_read16_attr(state, reg, b, 2, attribute) != 0)
+	if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2,
+				attribute) != 0)
 		return 0;
-	return (b[0] << 8 | b[1]);
+	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
 }
 
 #define dib9000_read16_noinc_attr(state, reg, b, len, attribute) dib9000_read16_attr(state, reg, b, len, (attribute) | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
 
 static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * buf, u32 len, u16 attribute)
 {
-	u8 b[255];
 	u32 chunk_size = 126;
 	u32 l;
 	int ret;
 
-	struct i2c_msg msg = {
-		.addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = b, .len = len + 2
-	};
-
 	if (state->platform.risc.fw_is_running && (reg < 1024)) {
 		if (dib9000_risc_apb_access_write
 		    (state, reg, DATA_BUS_ACCESS_MODE_16BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | attribute, buf, len) != 0)
@@ -304,20 +316,26 @@ static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 *
 		return 0;
 	}
 
-	b[0] = (reg >> 8) & 0xff;
-	b[1] = (reg) & 0xff;
+	memset(&state->msg[0], 0, sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c.i2c_addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = len + 2;
+
+	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+	state->i2c_write_buffer[1] = (reg) & 0xff;
 
 	if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
-		b[0] |= (1 << 5);
+		state->i2c_write_buffer[0] |= (1 << 5);
 	if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
-		b[0] |= (1 << 4);
+		state->i2c_write_buffer[0] |= (1 << 4);
 
 	do {
 		l = len < chunk_size ? len : chunk_size;
-		msg.len = l + 2;
-		memcpy(&b[2], buf, l);
+		state->msg[0].len = l + 2;
+		memcpy(&state->i2c_write_buffer[2], buf, l);
 
-		ret = i2c_transfer(state->i2c.i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+		ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
 
 		buf += l;
 		len -= l;
@@ -331,11 +349,16 @@ static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 *
 
 static int dib9000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
 {
-	u8 b[4] = { (reg >> 8) & 0xff, reg & 0xff, (val >> 8) & 0xff, val & 0xff };
 	struct i2c_msg msg = {
-		.addr = i2c->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
+		.addr = i2c->i2c_addr >> 1, .flags = 0,
+		.buf = i2c->i2c_write_buffer, .len = 4
 	};
 
+	i2c->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+	i2c->i2c_write_buffer[1] = reg & 0xff;
+	i2c->i2c_write_buffer[2] = (val >> 8) & 0xff;
+	i2c->i2c_write_buffer[3] = val & 0xff;
+
 	return i2c_transfer(i2c->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
 }
 
@@ -1015,8 +1038,8 @@ static int dib9000_fw_memmbx_sync(struct dib9000_state *state, u8 i)
 		return 0;
 	dib9000_risc_mem_write(state, FE_MM_RW_SYNC, &i);
 	do {
-		dib9000_risc_mem_read(state, FE_MM_RW_SYNC, &i, 1);
-	} while (i && index_loop--);
+		dib9000_risc_mem_read(state, FE_MM_RW_SYNC, state->i2c_read_buffer, 1);
+	} while (state->i2c_read_buffer[0] && index_loop--);
 
 	if (index_loop > 0)
 		return 0;
@@ -1139,7 +1162,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
 
 		s8 intlv_native;
 	};
-	struct dibDVBTChannel ch;
+	struct dibDVBTChannel *ch;
 	int ret = 0;
 
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
@@ -1148,9 +1171,12 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
 		ret = -EIO;
 	}
 
-	dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION, (u8 *) &ch, sizeof(struct dibDVBTChannel));
+	dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION,
+			state->i2c_read_buffer, sizeof(struct dibDVBTChannel));
+	ch = (struct dibDVBTChannel *)state->i2c_read_buffer;
+
 
-	switch (ch.spectrum_inversion & 0x7) {
+	switch (ch->spectrum_inversion & 0x7) {
 	case 1:
 		state->fe[0]->dtv_property_cache.inversion = INVERSION_ON;
 		break;
@@ -1162,7 +1188,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
 		state->fe[0]->dtv_property_cache.inversion = INVERSION_AUTO;
 		break;
 	}
-	switch (ch.nfft) {
+	switch (ch->nfft) {
 	case 0:
 		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
 		break;
@@ -1177,7 +1203,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
 		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
 		break;
 	}
-	switch (ch.guard) {
+	switch (ch->guard) {
 	case 0:
 		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
 		break;
@@ -1195,7 +1221,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
 		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
 		break;
 	}
-	switch (ch.constellation) {
+	switch (ch->constellation) {
 	case 2:
 		state->fe[0]->dtv_property_cache.modulation = QAM_64;
 		break;
@@ -1210,7 +1236,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
 		state->fe[0]->dtv_property_cache.modulation = QAM_AUTO;
 		break;
 	}
-	switch (ch.hrch) {
+	switch (ch->hrch) {
 	case 0:
 		state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_NONE;
 		break;
@@ -1222,7 +1248,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
 		state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_AUTO;
 		break;
 	}
-	switch (ch.code_rate_hp) {
+	switch (ch->code_rate_hp) {
 	case 1:
 		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_1_2;
 		break;
@@ -1243,7 +1269,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p
 		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_AUTO;
 		break;
 	}
-	switch (ch.code_rate_lp) {
+	switch (ch->code_rate_lp) {
 	case 1:
 		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_1_2;
 		break;
@@ -1439,9 +1465,10 @@ static int dib9000_fw_tune(struct dvb_frontend *fe, struct dvb_frontend_paramete
 		break;
 	case CT_DEMOD_STEP_1:
 		if (search)
-			dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, (u8 *) &i, 1);
+			dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, state->i2c_read_buffer, 1);
 		else
-			dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, (u8 *) &i, 1);
+			dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, state->i2c_read_buffer, 1);
+		i = (s8)state->i2c_read_buffer[0];
 		switch (i) {	/* something happened */
 		case 0:
 			break;
@@ -2038,14 +2065,17 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
 static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
 {
 	struct dib9000_state *state = fe->demodulator_priv;
-	u16 c[16];
+	u16 *c;
 
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
 	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
 		return -EIO;
-	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
+	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
+			state->i2c_read_buffer, 16 * 2);
 	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
 
+	c = (u16 *)state->i2c_read_buffer;
+
 	*ber = c[10] << 16 | c[11];
 	return 0;
 }
@@ -2054,7 +2084,7 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
 {
 	struct dib9000_state *state = fe->demodulator_priv;
 	u8 index_frontend;
-	u16 c[16];
+	u16 *c = (u16 *)state->i2c_read_buffer;
 	u16 val;
 
 	*strength = 0;
@@ -2069,7 +2099,7 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
 	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
 		return -EIO;
-	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
+	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
 	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
 
 	val = 65535 - c[4];
@@ -2083,14 +2113,14 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
 static u32 dib9000_get_snr(struct dvb_frontend *fe)
 {
 	struct dib9000_state *state = fe->demodulator_priv;
-	u16 c[16];
+	u16 *c = (u16 *)state->i2c_read_buffer;
 	u32 n, s, exp;
 	u16 val;
 
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
 	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
 		return -EIO;
-	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
+	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
 	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
 
 	val = c[7];
@@ -2137,12 +2167,12 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr)
 static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
 {
 	struct dib9000_state *state = fe->demodulator_priv;
-	u16 c[16];
+	u16 *c = (u16 *)state->i2c_read_buffer;
 
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
 	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
 		return -EIO;
-	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
+	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
 	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
 
 	*unc = c[12];
@@ -2151,10 +2181,22 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
 
 int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
 {
-	int k = 0;
+	int k = 0, ret = 0;
 	u8 new_addr = 0;
 	struct i2c_device client = {.i2c_adap = i2c };
 
+	client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+	if (!client.i2c_write_buffer) {
+		dprintk("%s: not enough memory", __func__);
+		return -ENOMEM;
+	}
+	client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+	if (!client.i2c_read_buffer) {
+		dprintk("%s: not enough memory", __func__);
+		ret = -ENOMEM;
+		goto error_memory;
+	}
+
 	client.i2c_addr = default_addr + 16;
 	dib9000_i2c_write16(&client, 1796, 0x0);
 
@@ -2178,7 +2220,8 @@ int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defaul
 			client.i2c_addr = default_addr;
 			if (dib9000_identify(&client) == 0) {
 				dprintk("DiB9000 #%d: not identified", k);
-				return -EIO;
+				ret = -EIO;
+				goto error;
 			}
 		}
 
@@ -2196,7 +2239,12 @@ int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defaul
 		dib9000_i2c_write16(&client, 1795, 0);
 	}
 
-	return 0;
+error:
+	kfree(client.i2c_read_buffer);
+error_memory:
+	kfree(client.i2c_write_buffer);
+
+	return ret;
 }
 EXPORT_SYMBOL(dib9000_i2c_enumeration);
 
@@ -2255,12 +2303,16 @@ struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, c
 	if (st == NULL)
 		return NULL;
 	fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL);
-	if (fe == NULL)
+	if (fe == NULL) {
+		kfree(st);
 		return NULL;
+	}
 
 	memcpy(&st->chip.d9.cfg, cfg, sizeof(struct dib9000_config));
 	st->i2c.i2c_adap = i2c_adap;
 	st->i2c.i2c_addr = i2c_addr;
+	st->i2c.i2c_write_buffer = st->i2c_write_buffer;
+	st->i2c.i2c_read_buffer = st->i2c_read_buffer;
 
 	st->gpio_dir = DIB9000_GPIO_DEFAULT_DIRECTIONS;
 	st->gpio_val = DIB9000_GPIO_DEFAULT_VALUES;

+ 65 - 44
drivers/media/dvb/frontends/dibx000_common.c

@@ -10,30 +10,39 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
 
 static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
 {
-	u8 b[4] = {
-		(reg >> 8) & 0xff, reg & 0xff,
-		(val >> 8) & 0xff, val & 0xff,
-	};
-	struct i2c_msg msg = {
-		.addr = mst->i2c_addr,.flags = 0,.buf = b,.len = 4
-	};
-
-	return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+	mst->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+	mst->i2c_write_buffer[1] = reg & 0xff;
+	mst->i2c_write_buffer[2] = (val >> 8) & 0xff;
+	mst->i2c_write_buffer[3] = val & 0xff;
+
+	memset(mst->msg, 0, sizeof(struct i2c_msg));
+	mst->msg[0].addr = mst->i2c_addr;
+	mst->msg[0].flags = 0;
+	mst->msg[0].buf = mst->i2c_write_buffer;
+	mst->msg[0].len = 4;
+
+	return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
 }
 
 static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
 {
-	u8 wb[2] = { reg >> 8, reg & 0xff };
-	u8 rb[2];
-	struct i2c_msg msg[2] = {
-		{.addr = mst->i2c_addr, .flags = 0, .buf = wb, .len = 2},
-		{.addr = mst->i2c_addr, .flags = I2C_M_RD, .buf = rb, .len = 2},
-	};
-
-	if (i2c_transfer(mst->i2c_adap, msg, 2) != 2)
+	mst->i2c_write_buffer[0] = reg >> 8;
+	mst->i2c_write_buffer[1] = reg & 0xff;
+
+	memset(mst->msg, 0, 2 * sizeof(struct i2c_msg));
+	mst->msg[0].addr = mst->i2c_addr;
+	mst->msg[0].flags = 0;
+	mst->msg[0].buf = mst->i2c_write_buffer;
+	mst->msg[0].len = 2;
+	mst->msg[1].addr = mst->i2c_addr;
+	mst->msg[1].flags = I2C_M_RD;
+	mst->msg[1].buf = mst->i2c_read_buffer;
+	mst->msg[1].len = 2;
+
+	if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)
 		dprintk("i2c read error on %d", reg);
 
-	return (rb[0] << 8) | rb[1];
+	return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
 }
 
 static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
@@ -248,26 +257,32 @@ static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
 					struct i2c_msg msg[], int num)
 {
 	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
-	struct i2c_msg m[2 + num];
-	u8 tx_open[4], tx_close[4];
 
-	memset(m, 0, sizeof(struct i2c_msg) * (2 + num));
+	if (num > 32) {
+		dprintk("%s: too much I2C message to be transmitted (%i).\
+				Maximum is 32", __func__, num);
+		return -ENOMEM;
+	}
+
+	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
 
 	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
 
-	dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1);
-	m[0].addr = mst->i2c_addr;
-	m[0].buf = tx_open;
-	m[0].len = 4;
+	/* open the gate */
+	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
+	mst->msg[0].addr = mst->i2c_addr;
+	mst->msg[0].buf = &mst->i2c_write_buffer[0];
+	mst->msg[0].len = 4;
 
-	memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
+	memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
 
-	dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
-	m[num + 1].addr = mst->i2c_addr;
-	m[num + 1].buf = tx_close;
-	m[num + 1].len = 4;
+	/* close the gate */
+	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
+	mst->msg[num + 1].addr = mst->i2c_addr;
+	mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
+	mst->msg[num + 1].len = 4;
 
-	return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO;
+	return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
 }
 
 static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
@@ -279,26 +294,32 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
 					struct i2c_msg msg[], int num)
 {
 	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
-	struct i2c_msg m[2 + num];
-	u8 tx_open[4], tx_close[4];
 
-	memset(m, 0, sizeof(struct i2c_msg) * (2 + num));
+	if (num > 32) {
+		dprintk("%s: too much I2C message to be transmitted (%i).\
+				Maximum is 32", __func__, num);
+		return -ENOMEM;
+	}
+
+	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
 
 	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
 
-	dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1);
-	m[0].addr = mst->i2c_addr;
-	m[0].buf = tx_open;
-	m[0].len = 4;
+	/* open the gate */
+	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
+	mst->msg[0].addr = mst->i2c_addr;
+	mst->msg[0].buf = &mst->i2c_write_buffer[0];
+	mst->msg[0].len = 4;
 
-	memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
+	memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
 
-	dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
-	m[num + 1].addr = mst->i2c_addr;
-	m[num + 1].buf = tx_close;
-	m[num + 1].len = 4;
+	/* close the gate */
+	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
+	mst->msg[num + 1].addr = mst->i2c_addr;
+	mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
+	mst->msg[num + 1].len = 4;
 
-	return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO;
+	return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
 }
 
 static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {

+ 5 - 0
drivers/media/dvb/frontends/dibx000_common.h

@@ -28,6 +28,11 @@ struct dibx000_i2c_master {
 	u8 i2c_addr;
 
 	u16 base_reg;
+
+	/* for the I2C transfer */
+	struct i2c_msg msg[34];
+	u8 i2c_write_buffer[8];
+	u8 i2c_read_buffer[2];
 };
 
 extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst,

+ 0 - 1511
drivers/media/dvb/frontends/drx397xD.c

@@ -1,1511 +0,0 @@
-/*
- * Driver for Micronas drx397xD demodulator
- *
- * Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define DEBUG			/* uncomment if you want debugging output */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/firmware.h>
-#include <linux/slab.h>
-#include <asm/div64.h>
-
-#include "dvb_frontend.h"
-#include "drx397xD.h"
-
-static const char mod_name[] = "drx397xD";
-
-#define MAX_CLOCK_DRIFT		200	/* maximal 200 PPM allowed */
-
-#define F_SET_0D0h	1
-#define F_SET_0D4h	2
-
-enum fw_ix {
-#define _FW_ENTRY(a, b, c)	b
-#include "drx397xD_fw.h"
-};
-
-/* chip specifics */
-struct drx397xD_state {
-	struct i2c_adapter *i2c;
-	struct dvb_frontend frontend;
-	struct drx397xD_config config;
-	enum fw_ix chip_rev;
-	int flags;
-	u32 bandwidth_parm;	/* internal bandwidth conversions */
-	u32 f_osc;		/* w90: actual osc frequency [Hz] */
-};
-
-/* Firmware */
-static const char *blob_name[] = {
-#define _BLOB_ENTRY(a, b)		a
-#include "drx397xD_fw.h"
-};
-
-enum blob_ix {
-#define _BLOB_ENTRY(a, b)		b
-#include "drx397xD_fw.h"
-};
-
-static struct {
-	const char *name;
-	const struct firmware *file;
-	rwlock_t lock;
-	int refcnt;
-	const u8 *data[ARRAY_SIZE(blob_name)];
-} fw[] = {
-#define _FW_ENTRY(a, b, c)	{					\
-			.name	= a,					\
-			.file	= NULL,					\
-			.lock	= __RW_LOCK_UNLOCKED(fw[c].lock),	\
-			.refcnt = 0,					\
-			.data	= { }		}
-#include "drx397xD_fw.h"
-};
-
-/* use only with writer lock acquired */
-static void _drx_release_fw(struct drx397xD_state *s, enum fw_ix ix)
-{
-	memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
-	if (fw[ix].file)
-		release_firmware(fw[ix].file);
-}
-
-static void drx_release_fw(struct drx397xD_state *s)
-{
-	enum fw_ix ix = s->chip_rev;
-
-	pr_debug("%s\n", __func__);
-
-	write_lock(&fw[ix].lock);
-	if (fw[ix].refcnt) {
-		fw[ix].refcnt--;
-		if (fw[ix].refcnt == 0)
-			_drx_release_fw(s, ix);
-	}
-	write_unlock(&fw[ix].lock);
-}
-
-static int drx_load_fw(struct drx397xD_state *s, enum fw_ix ix)
-{
-	const u8 *data;
-	size_t size, len;
-	int i = 0, j, rc = -EINVAL;
-
-	pr_debug("%s\n", __func__);
-
-	if (ix < 0 || ix >= ARRAY_SIZE(fw))
-		return -EINVAL;
-	s->chip_rev = ix;
-
-	write_lock(&fw[ix].lock);
-	if (fw[ix].file) {
-		rc = 0;
-		goto exit_ok;
-	}
-	memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
-
-	rc = request_firmware(&fw[ix].file, fw[ix].name, s->i2c->dev.parent);
-	if (rc != 0) {
-		printk(KERN_ERR "%s: Firmware \"%s\" not available\n",
-		       mod_name, fw[ix].name);
-		goto exit_err;
-	}
-
-	if (!fw[ix].file->data || fw[ix].file->size < 10)
-		goto exit_corrupt;
-
-	data = fw[ix].file->data;
-	size = fw[ix].file->size;
-
-	if (data[i++] != 2)	/* check firmware version */
-		goto exit_corrupt;
-
-	do {
-		switch (data[i++]) {
-		case 0x00:	/* bytecode */
-			if (i >= size)
-				break;
-			i += data[i];
-		case 0x01:	/* reset */
-		case 0x02:	/* sleep */
-			i++;
-			break;
-		case 0xfe:	/* name */
-			len = strnlen(&data[i], size - i);
-			if (i + len + 1 >= size)
-				goto exit_corrupt;
-			if (data[i + len + 1] != 0)
-				goto exit_corrupt;
-			for (j = 0; j < ARRAY_SIZE(blob_name); j++) {
-				if (strcmp(blob_name[j], &data[i]) == 0) {
-					fw[ix].data[j] = &data[i + len + 1];
-					pr_debug("Loading %s\n", blob_name[j]);
-				}
-			}
-			i += len + 1;
-			break;
-		case 0xff:	/* file terminator */
-			if (i == size) {
-				rc = 0;
-				goto exit_ok;
-			}
-		default:
-			goto exit_corrupt;
-		}
-	} while (i < size);
-
-exit_corrupt:
-	printk(KERN_ERR "%s: Firmware is corrupt\n", mod_name);
-exit_err:
-	_drx_release_fw(s, ix);
-	fw[ix].refcnt--;
-exit_ok:
-	fw[ix].refcnt++;
-	write_unlock(&fw[ix].lock);
-
-	return rc;
-}
-
-/* i2c bus IO */
-static int write_fw(struct drx397xD_state *s, enum blob_ix ix)
-{
-	const u8 *data;
-	int len, rc = 0, i = 0;
-	struct i2c_msg msg = {
-		.addr = s->config.demod_address,
-		.flags = 0
-	};
-
-	if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) {
-		pr_debug("%s drx_fw_ix_t out of range\n", __func__);
-		return -EINVAL;
-	}
-	pr_debug("%s %s\n", __func__, blob_name[ix]);
-
-	read_lock(&fw[s->chip_rev].lock);
-	data = fw[s->chip_rev].data[ix];
-	if (!data) {
-		rc = -EINVAL;
-		goto exit_rc;
-	}
-
-	for (;;) {
-		switch (data[i++]) {
-		case 0:	/* bytecode */
-			len = data[i++];
-			msg.len = len;
-			msg.buf = (__u8 *) &data[i];
-			if (i2c_transfer(s->i2c, &msg, 1) != 1) {
-				rc = -EIO;
-				goto exit_rc;
-			}
-			i += len;
-			break;
-		case 1:	/* reset */
-		case 2:	/* sleep */
-			i++;
-			break;
-		default:
-			goto exit_rc;
-		}
-	}
-exit_rc:
-	read_unlock(&fw[s->chip_rev].lock);
-
-	return rc;
-}
-
-/* Function is not endian safe, use the RD16 wrapper below */
-static int _read16(struct drx397xD_state *s, __le32 i2c_adr)
-{
-	int rc;
-	u8 a[4];
-	__le16 v;
-	struct i2c_msg msg[2] = {
-		{
-			.addr = s->config.demod_address,
-			.flags = 0,
-			.buf = a,
-			.len = sizeof(a)
-		}, {
-			.addr = s->config.demod_address,
-			.flags = I2C_M_RD,
-			.buf = (u8 *)&v,
-			.len = sizeof(v)
-		}
-	};
-
-	*(__le32 *) a = i2c_adr;
-
-	rc = i2c_transfer(s->i2c, msg, 2);
-	if (rc != 2)
-		return -EIO;
-
-	return le16_to_cpu(v);
-}
-
-/* Function is not endian safe, use the WR16.. wrappers below */
-static int _write16(struct drx397xD_state *s, __le32 i2c_adr, __le16 val)
-{
-	u8 a[6];
-	int rc;
-	struct i2c_msg msg = {
-		.addr = s->config.demod_address,
-		.flags = 0,
-		.buf = a,
-		.len = sizeof(a)
-	};
-
-	*(__le32 *)a = i2c_adr;
-	*(__le16 *)&a[4] = val;
-
-	rc = i2c_transfer(s->i2c, &msg, 1);
-	if (rc != 1)
-		return -EIO;
-
-	return 0;
-}
-
-#define WR16(ss, adr, val) \
-		_write16(ss, I2C_ADR_C0(adr), cpu_to_le16(val))
-#define WR16_E0(ss, adr, val) \
-		_write16(ss, I2C_ADR_E0(adr), cpu_to_le16(val))
-#define RD16(ss, adr) \
-		_read16(ss, I2C_ADR_C0(adr))
-
-#define EXIT_RC(cmd)	\
-	if ((rc = (cmd)) < 0)	\
-		goto exit_rc
-
-/* Tuner callback */
-static int PLL_Set(struct drx397xD_state *s,
-		   struct dvb_frontend_parameters *fep, int *df_tuner)
-{
-	struct dvb_frontend *fe = &s->frontend;
-	u32 f_tuner, f = fep->frequency;
-	int rc;
-
-	pr_debug("%s\n", __func__);
-
-	if ((f > s->frontend.ops.tuner_ops.info.frequency_max) ||
-	    (f < s->frontend.ops.tuner_ops.info.frequency_min))
-		return -EINVAL;
-
-	*df_tuner = 0;
-	if (!s->frontend.ops.tuner_ops.set_params ||
-	    !s->frontend.ops.tuner_ops.get_frequency)
-		return -ENOSYS;
-
-	rc = s->frontend.ops.tuner_ops.set_params(fe, fep);
-	if (rc < 0)
-		return rc;
-
-	rc = s->frontend.ops.tuner_ops.get_frequency(fe, &f_tuner);
-	if (rc < 0)
-		return rc;
-
-	*df_tuner = f_tuner - f;
-	pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __func__, f,
-		 f_tuner);
-
-	return 0;
-}
-
-/* Demodulator helper functions */
-static int SC_WaitForReady(struct drx397xD_state *s)
-{
-	int cnt = 1000;
-	int rc;
-
-	pr_debug("%s\n", __func__);
-
-	while (cnt--) {
-		rc = RD16(s, 0x820043);
-		if (rc == 0)
-			return 0;
-	}
-
-	return -1;
-}
-
-static int SC_SendCommand(struct drx397xD_state *s, int cmd)
-{
-	int rc;
-
-	pr_debug("%s\n", __func__);
-
-	WR16(s, 0x820043, cmd);
-	SC_WaitForReady(s);
-	rc = RD16(s, 0x820042);
-	if ((rc & 0xffff) == 0xffff)
-		return -1;
-
-	return 0;
-}
-
-static int HI_Command(struct drx397xD_state *s, u16 cmd)
-{
-	int rc, cnt = 1000;
-
-	pr_debug("%s\n", __func__);
-
-	rc = WR16(s, 0x420032, cmd);
-	if (rc < 0)
-		return rc;
-
-	do {
-		rc = RD16(s, 0x420032);
-		if (rc == 0) {
-			rc = RD16(s, 0x420031);
-			return rc;
-		}
-		if (rc < 0)
-			return rc;
-	} while (--cnt);
-
-	return rc;
-}
-
-static int HI_CfgCommand(struct drx397xD_state *s)
-{
-
-	pr_debug("%s\n", __func__);
-
-	WR16(s, 0x420033, 0x3973);
-	WR16(s, 0x420034, s->config.w50);	/* code 4, log 4 */
-	WR16(s, 0x420035, s->config.w52);	/* code 15,  log 9 */
-	WR16(s, 0x420036, s->config.demod_address << 1);
-	WR16(s, 0x420037, s->config.w56);	/* code (set_i2c ??  initX 1 ), log 1 */
-	/* WR16(s, 0x420033, 0x3973); */
-	if ((s->config.w56 & 8) == 0)
-		return HI_Command(s, 3);
-
-	return WR16(s, 0x420032, 0x3);
-}
-
-static const u8 fastIncrDecLUT_15273[] = {
-	0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14,
-	0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f
-};
-
-static const u8 slowIncrDecLUT_15272[] = {
-	3, 4, 4, 5, 6
-};
-
-static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc)
-{
-	u16 w06 = agc->w06;
-	u16 w08 = agc->w08;
-	u16 w0A = agc->w0A;
-	u16 w0C = agc->w0C;
-	int quot, rem, i, rc = -EINVAL;
-
-	pr_debug("%s\n", __func__);
-
-	if (agc->w04 > 0x3ff)
-		goto exit_rc;
-
-	if (agc->d00 == 1) {
-		EXIT_RC(RD16(s, 0x0c20010));
-		rc &= ~0x10;
-		EXIT_RC(WR16(s, 0x0c20010, rc));
-		return WR16(s, 0x0c20030, agc->w04 & 0x7ff);
-	}
-
-	if (agc->d00 != 0)
-		goto exit_rc;
-	if (w0A < w08)
-		goto exit_rc;
-	if (w0A > 0x3ff)
-		goto exit_rc;
-	if (w0C > 0x3ff)
-		goto exit_rc;
-	if (w06 > 0x3ff)
-		goto exit_rc;
-
-	EXIT_RC(RD16(s, 0x0c20010));
-	rc |= 0x10;
-	EXIT_RC(WR16(s, 0x0c20010, rc));
-
-	EXIT_RC(WR16(s, 0x0c20025, (w06 >> 1) & 0x1ff));
-	EXIT_RC(WR16(s, 0x0c20031, (w0A - w08) >> 1));
-	EXIT_RC(WR16(s, 0x0c20032, ((w0A + w08) >> 1) - 0x1ff));
-
-	quot = w0C / 113;
-	rem = w0C % 113;
-	if (quot <= 8) {
-		quot = 8 - quot;
-	} else {
-		quot = 0;
-		rem += 113;
-	}
-
-	EXIT_RC(WR16(s, 0x0c20024, quot));
-
-	i = fastIncrDecLUT_15273[rem / 8];
-	EXIT_RC(WR16(s, 0x0c2002d, i));
-	EXIT_RC(WR16(s, 0x0c2002e, i));
-
-	i = slowIncrDecLUT_15272[rem / 28];
-	EXIT_RC(WR16(s, 0x0c2002b, i));
-	rc = WR16(s, 0x0c2002c, i);
-exit_rc:
-	return rc;
-}
-
-static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc)
-{
-	u16 w04 = agc->w04;
-	u16 w06 = agc->w06;
-	int rc = -1;
-
-	pr_debug("%s %d 0x%x 0x%x\n", __func__, agc->d00, w04, w06);
-
-	if (w04 > 0x3ff)
-		goto exit_rc;
-
-	switch (agc->d00) {
-	case 1:
-		if (w04 == 0x3ff)
-			w04 = 0x400;
-
-		EXIT_RC(WR16(s, 0x0c20036, w04));
-		s->config.w9C &= ~2;
-		EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
-		EXIT_RC(RD16(s, 0x0c20010));
-		rc &= 0xbfdf;
-		EXIT_RC(WR16(s, 0x0c20010, rc));
-		EXIT_RC(RD16(s, 0x0c20013));
-		rc &= ~2;
-		break;
-	case 0:
-		/* loc_8000659 */
-		s->config.w9C &= ~2;
-		EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
-		EXIT_RC(RD16(s, 0x0c20010));
-		rc &= 0xbfdf;
-		rc |= 0x4000;
-		EXIT_RC(WR16(s, 0x0c20010, rc));
-		EXIT_RC(WR16(s, 0x0c20051, (w06 >> 4) & 0x3f));
-		EXIT_RC(RD16(s, 0x0c20013));
-		rc &= ~2;
-		break;
-	default:
-		s->config.w9C |= 2;
-		EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
-		EXIT_RC(RD16(s, 0x0c20010));
-		rc &= 0xbfdf;
-		EXIT_RC(WR16(s, 0x0c20010, rc));
-
-		EXIT_RC(WR16(s, 0x0c20036, 0));
-
-		EXIT_RC(RD16(s, 0x0c20013));
-		rc |= 2;
-	}
-	rc = WR16(s, 0x0c20013, rc);
-
-exit_rc:
-	return rc;
-}
-
-static int GetLockStatus(struct drx397xD_state *s, int *lockstat)
-{
-	int rc;
-
-	*lockstat = 0;
-
-	rc = RD16(s, 0x082004b);
-	if (rc < 0)
-		return rc;
-
-	if (s->config.d60 != 2)
-		return 0;
-
-	if ((rc & 7) == 7)
-		*lockstat |= 1;
-	if ((rc & 3) == 3)
-		*lockstat |= 2;
-	if (rc & 1)
-		*lockstat |= 4;
-	return 0;
-}
-
-static int CorrectSysClockDeviation(struct drx397xD_state *s)
-{
-	int rc = -EINVAL;
-	int lockstat;
-	u32 clk, clk_limit;
-
-	pr_debug("%s\n", __func__);
-
-	if (s->config.d5C == 0) {
-		EXIT_RC(WR16(s, 0x08200e8, 0x010));
-		EXIT_RC(WR16(s, 0x08200e9, 0x113));
-		s->config.d5C = 1;
-		return rc;
-	}
-	if (s->config.d5C != 1)
-		goto exit_rc;
-
-	rc = RD16(s, 0x0820048);
-
-	rc = GetLockStatus(s, &lockstat);
-	if (rc < 0)
-		goto exit_rc;
-	if ((lockstat & 1) == 0)
-		goto exit_rc;
-
-	EXIT_RC(WR16(s, 0x0420033, 0x200));
-	EXIT_RC(WR16(s, 0x0420034, 0xc5));
-	EXIT_RC(WR16(s, 0x0420035, 0x10));
-	EXIT_RC(WR16(s, 0x0420036, 0x1));
-	EXIT_RC(WR16(s, 0x0420037, 0xa));
-	EXIT_RC(HI_Command(s, 6));
-	EXIT_RC(RD16(s, 0x0420040));
-	clk = rc;
-	EXIT_RC(RD16(s, 0x0420041));
-	clk |= rc << 16;
-
-	if (clk <= 0x26ffff)
-		goto exit_rc;
-	if (clk > 0x610000)
-		goto exit_rc;
-
-	if (!s->bandwidth_parm)
-		return -EINVAL;
-
-	/* round & convert to Hz */
-	clk = ((u64) (clk + 0x800000) * s->bandwidth_parm + (1 << 20)) >> 21;
-	clk_limit = s->config.f_osc * MAX_CLOCK_DRIFT / 1000;
-
-	if (clk - s->config.f_osc * 1000 + clk_limit <= 2 * clk_limit) {
-		s->f_osc = clk;
-		pr_debug("%s: osc %d %d [Hz]\n", __func__,
-			 s->config.f_osc * 1000, clk - s->config.f_osc * 1000);
-	}
-	rc = WR16(s, 0x08200e8, 0);
-
-exit_rc:
-	return rc;
-}
-
-static int ConfigureMPEGOutput(struct drx397xD_state *s, int type)
-{
-	int rc, si, bp;
-
-	pr_debug("%s\n", __func__);
-
-	si = s->config.wA0;
-	if (s->config.w98 == 0) {
-		si |= 1;
-		bp = 0;
-	} else {
-		si &= ~1;
-		bp = 0x200;
-	}
-	if (s->config.w9A == 0)
-		si |= 0x80;
-	else
-		si &= ~0x80;
-
-	EXIT_RC(WR16(s, 0x2150045, 0));
-	EXIT_RC(WR16(s, 0x2150010, si));
-	EXIT_RC(WR16(s, 0x2150011, bp));
-	rc = WR16(s, 0x2150012, (type == 0 ? 0xfff : 0));
-
-exit_rc:
-	return rc;
-}
-
-static int drx_tune(struct drx397xD_state *s,
-		    struct dvb_frontend_parameters *fep)
-{
-	u16 v22 = 0;
-	u16 v1C = 0;
-	u16 v1A = 0;
-	u16 v18 = 0;
-	u32 edi = 0, ebx = 0, ebp = 0, edx = 0;
-	u16 v20 = 0, v1E = 0, v16 = 0, v14 = 0, v12 = 0, v10 = 0, v0E = 0;
-
-	int rc, df_tuner = 0;
-	int a, b, c, d;
-	pr_debug("%s %d\n", __func__, s->config.d60);
-
-	if (s->config.d60 != 2)
-		goto set_tuner;
-	rc = CorrectSysClockDeviation(s);
-	if (rc < 0)
-		goto set_tuner;
-
-	s->config.d60 = 1;
-	rc = ConfigureMPEGOutput(s, 0);
-	if (rc < 0)
-		goto set_tuner;
-set_tuner:
-
-	rc = PLL_Set(s, fep, &df_tuner);
-	if (rc < 0) {
-		printk(KERN_ERR "Error in pll_set\n");
-		goto exit_rc;
-	}
-	msleep(200);
-
-	a = rc = RD16(s, 0x2150016);
-	if (rc < 0)
-		goto exit_rc;
-	b = rc = RD16(s, 0x2150010);
-	if (rc < 0)
-		goto exit_rc;
-	c = rc = RD16(s, 0x2150034);
-	if (rc < 0)
-		goto exit_rc;
-	d = rc = RD16(s, 0x2150035);
-	if (rc < 0)
-		goto exit_rc;
-	rc = WR16(s, 0x2150014, c);
-	rc = WR16(s, 0x2150015, d);
-	rc = WR16(s, 0x2150010, 0);
-	rc = WR16(s, 0x2150000, 2);
-	rc = WR16(s, 0x2150036, 0x0fff);
-	rc = WR16(s, 0x2150016, a);
-
-	rc = WR16(s, 0x2150010, 2);
-	rc = WR16(s, 0x2150007, 0);
-	rc = WR16(s, 0x2150000, 1);
-	rc = WR16(s, 0x2110000, 0);
-	rc = WR16(s, 0x0800000, 0);
-	rc = WR16(s, 0x2800000, 0);
-	rc = WR16(s, 0x2110010, 0x664);
-
-	rc = write_fw(s, DRXD_ResetECRAM);
-	rc = WR16(s, 0x2110000, 1);
-
-	rc = write_fw(s, DRXD_InitSC);
-	if (rc < 0)
-		goto exit_rc;
-
-	rc = SetCfgIfAgc(s, &s->config.ifagc);
-	if (rc < 0)
-		goto exit_rc;
-
-	rc = SetCfgRfAgc(s, &s->config.rfagc);
-	if (rc < 0)
-		goto exit_rc;
-
-	if (fep->u.ofdm.transmission_mode != TRANSMISSION_MODE_2K)
-		v22 = 1;
-	switch (fep->u.ofdm.transmission_mode) {
-	case TRANSMISSION_MODE_8K:
-		edi = 1;
-		if (s->chip_rev == DRXD_FW_B1)
-			break;
-
-		rc = WR16(s, 0x2010010, 0);
-		if (rc < 0)
-			break;
-		v1C = 0x63;
-		v1A = 0x53;
-		v18 = 0x43;
-		break;
-	default:
-		edi = 0;
-		if (s->chip_rev == DRXD_FW_B1)
-			break;
-
-		rc = WR16(s, 0x2010010, 1);
-		if (rc < 0)
-			break;
-
-		v1C = 0x61;
-		v1A = 0x47;
-		v18 = 0x41;
-	}
-
-	switch (fep->u.ofdm.guard_interval) {
-	case GUARD_INTERVAL_1_4:
-		edi |= 0x0c;
-		break;
-	case GUARD_INTERVAL_1_8:
-		edi |= 0x08;
-		break;
-	case GUARD_INTERVAL_1_16:
-		edi |= 0x04;
-		break;
-	case GUARD_INTERVAL_1_32:
-		break;
-	default:
-		v22 |= 2;
-	}
-
-	ebx = 0;
-	ebp = 0;
-	v20 = 0;
-	v1E = 0;
-	v16 = 0;
-	v14 = 0;
-	v12 = 0;
-	v10 = 0;
-	v0E = 0;
-
-	switch (fep->u.ofdm.hierarchy_information) {
-	case HIERARCHY_1:
-		edi |= 0x40;
-		if (s->chip_rev == DRXD_FW_B1)
-			break;
-		rc = WR16(s, 0x1c10047, 1);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x2010012, 1);
-		if (rc < 0)
-			goto exit_rc;
-		ebx = 0x19f;
-		ebp = 0x1fb;
-		v20 = 0x0c0;
-		v1E = 0x195;
-		v16 = 0x1d6;
-		v14 = 0x1ef;
-		v12 = 4;
-		v10 = 5;
-		v0E = 5;
-		break;
-	case HIERARCHY_2:
-		edi |= 0x80;
-		if (s->chip_rev == DRXD_FW_B1)
-			break;
-		rc = WR16(s, 0x1c10047, 2);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x2010012, 2);
-		if (rc < 0)
-			goto exit_rc;
-		ebx = 0x08f;
-		ebp = 0x12f;
-		v20 = 0x0c0;
-		v1E = 0x11e;
-		v16 = 0x1d6;
-		v14 = 0x15e;
-		v12 = 4;
-		v10 = 5;
-		v0E = 5;
-		break;
-	case HIERARCHY_4:
-		edi |= 0xc0;
-		if (s->chip_rev == DRXD_FW_B1)
-			break;
-		rc = WR16(s, 0x1c10047, 3);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x2010012, 3);
-		if (rc < 0)
-			goto exit_rc;
-		ebx = 0x14d;
-		ebp = 0x197;
-		v20 = 0x0c0;
-		v1E = 0x1ce;
-		v16 = 0x1d6;
-		v14 = 0x11a;
-		v12 = 4;
-		v10 = 6;
-		v0E = 5;
-		break;
-	default:
-		v22 |= 8;
-		if (s->chip_rev == DRXD_FW_B1)
-			break;
-		rc = WR16(s, 0x1c10047, 0);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x2010012, 0);
-		if (rc < 0)
-			goto exit_rc;
-				/* QPSK    QAM16  QAM64	*/
-		ebx = 0x19f;	/*                 62	*/
-		ebp = 0x1fb;	/*                 15	*/
-		v20 = 0x16a;	/*  62			*/
-		v1E = 0x195;	/*         62		*/
-		v16 = 0x1bb;	/*  15			*/
-		v14 = 0x1ef;	/*         15		*/
-		v12 = 5;	/*  16			*/
-		v10 = 5;	/*         16		*/
-		v0E = 5;	/*                 16	*/
-	}
-
-	switch (fep->u.ofdm.constellation) {
-	default:
-		v22 |= 4;
-	case QPSK:
-		if (s->chip_rev == DRXD_FW_B1)
-			break;
-
-		rc = WR16(s, 0x1c10046, 0);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x2010011, 0);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x201001a, 0x10);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x201001b, 0);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x201001c, 0);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x1c10062, v20);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x1c1002a, v1C);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x1c10015, v16);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x1c10016, v12);
-		if (rc < 0)
-			goto exit_rc;
-		break;
-	case QAM_16:
-		edi |= 0x10;
-		if (s->chip_rev == DRXD_FW_B1)
-			break;
-
-		rc = WR16(s, 0x1c10046, 1);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x2010011, 1);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x201001a, 0x10);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x201001b, 4);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x201001c, 0);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x1c10062, v1E);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x1c1002a, v1A);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x1c10015, v14);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x1c10016, v10);
-		if (rc < 0)
-			goto exit_rc;
-		break;
-	case QAM_64:
-		edi |= 0x20;
-		rc = WR16(s, 0x1c10046, 2);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x2010011, 2);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x201001a, 0x20);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x201001b, 8);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x201001c, 2);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x1c10062, ebx);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x1c1002a, v18);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x1c10015, ebp);
-		if (rc < 0)
-			goto exit_rc;
-		rc = WR16(s, 0x1c10016, v0E);
-		if (rc < 0)
-			goto exit_rc;
-		break;
-	}
-
-	if (s->config.s20d24 == 1) {
-		rc = WR16(s, 0x2010013, 0);
-	} else {
-		rc = WR16(s, 0x2010013, 1);
-		edi |= 0x1000;
-	}
-
-	switch (fep->u.ofdm.code_rate_HP) {
-	default:
-		v22 |= 0x10;
-	case FEC_1_2:
-		if (s->chip_rev == DRXD_FW_B1)
-			break;
-		rc = WR16(s, 0x2090011, 0);
-		break;
-	case FEC_2_3:
-		edi |= 0x200;
-		if (s->chip_rev == DRXD_FW_B1)
-			break;
-		rc = WR16(s, 0x2090011, 1);
-		break;
-	case FEC_3_4:
-		edi |= 0x400;
-		if (s->chip_rev == DRXD_FW_B1)
-			break;
-		rc = WR16(s, 0x2090011, 2);
-		break;
-	case FEC_5_6:		/* 5 */
-		edi |= 0x600;
-		if (s->chip_rev == DRXD_FW_B1)
-			break;
-		rc = WR16(s, 0x2090011, 3);
-		break;
-	case FEC_7_8:		/* 7 */
-		edi |= 0x800;
-		if (s->chip_rev == DRXD_FW_B1)
-			break;
-		rc = WR16(s, 0x2090011, 4);
-		break;
-	};
-	if (rc < 0)
-		goto exit_rc;
-
-	switch (fep->u.ofdm.bandwidth) {
-	default:
-		rc = -EINVAL;
-		goto exit_rc;
-	case BANDWIDTH_8_MHZ:	/* 0 */
-	case BANDWIDTH_AUTO:
-		rc = WR16(s, 0x0c2003f, 0x32);
-		s->bandwidth_parm = ebx = 0x8b8249;
-		edx = 0;
-		break;
-	case BANDWIDTH_7_MHZ:
-		rc = WR16(s, 0x0c2003f, 0x3b);
-		s->bandwidth_parm = ebx = 0x7a1200;
-		edx = 0x4807;
-		break;
-	case BANDWIDTH_6_MHZ:
-		rc = WR16(s, 0x0c2003f, 0x47);
-		s->bandwidth_parm = ebx = 0x68a1b6;
-		edx = 0x0f07;
-		break;
-	};
-
-	if (rc < 0)
-		goto exit_rc;
-
-	rc = WR16(s, 0x08200ec, edx);
-	if (rc < 0)
-		goto exit_rc;
-
-	rc = RD16(s, 0x0820050);
-	if (rc < 0)
-		goto exit_rc;
-	rc = WR16(s, 0x0820050, rc);
-
-	{
-		/* Configure bandwidth specific factor */
-		ebx = div64_u64(((u64) (s->f_osc) << 21) + (ebx >> 1),
-				     (u64)ebx) - 0x800000;
-		EXIT_RC(WR16(s, 0x0c50010, ebx & 0xffff));
-		EXIT_RC(WR16(s, 0x0c50011, ebx >> 16));
-
-		/* drx397xD oscillator calibration */
-		ebx = div64_u64(((u64) (s->config.f_if + df_tuner) << 28) +
-				     (s->f_osc >> 1), (u64)s->f_osc);
-	}
-	ebx &= 0xfffffff;
-	if (fep->inversion == INVERSION_ON)
-		ebx = 0x10000000 - ebx;
-
-	EXIT_RC(WR16(s, 0x0c30010, ebx & 0xffff));
-	EXIT_RC(WR16(s, 0x0c30011, ebx >> 16));
-
-	EXIT_RC(WR16(s, 0x0800000, 1));
-	EXIT_RC(RD16(s, 0x0800000));
-
-
-	EXIT_RC(SC_WaitForReady(s));
-	EXIT_RC(WR16(s, 0x0820042, 0));
-	EXIT_RC(WR16(s, 0x0820041, v22));
-	EXIT_RC(WR16(s, 0x0820040, edi));
-	EXIT_RC(SC_SendCommand(s, 3));
-
-	rc = RD16(s, 0x0800000);
-
-	SC_WaitForReady(s);
-	WR16(s, 0x0820042, 0);
-	WR16(s, 0x0820041, 1);
-	WR16(s, 0x0820040, 1);
-	SC_SendCommand(s, 1);
-
-
-	rc = WR16(s, 0x2150000, 2);
-	rc = WR16(s, 0x2150016, a);
-	rc = WR16(s, 0x2150010, 4);
-	rc = WR16(s, 0x2150036, 0);
-	rc = WR16(s, 0x2150000, 1);
-	s->config.d60 = 2;
-
-exit_rc:
-	return rc;
-}
-
-/*******************************************************************************
- * DVB interface
- ******************************************************************************/
-
-static int drx397x_init(struct dvb_frontend *fe)
-{
-	struct drx397xD_state *s = fe->demodulator_priv;
-	int rc;
-
-	pr_debug("%s\n", __func__);
-
-	s->config.rfagc.d00 = 2;	/* 0x7c */
-	s->config.rfagc.w04 = 0;
-	s->config.rfagc.w06 = 0x3ff;
-
-	s->config.ifagc.d00 = 0;	/* 0x68 */
-	s->config.ifagc.w04 = 0;
-	s->config.ifagc.w06 = 140;
-	s->config.ifagc.w08 = 0;
-	s->config.ifagc.w0A = 0x3ff;
-	s->config.ifagc.w0C = 0x388;
-
-	/* for signal strength calculations */
-	s->config.ss76 = 820;
-	s->config.ss78 = 2200;
-	s->config.ss7A = 150;
-
-	/* HI_CfgCommand */
-	s->config.w50 = 4;
-	s->config.w52 = 9;
-
-	s->config.f_if = 42800000;	/* d14: intermediate frequency [Hz] */
-	s->config.f_osc = 48000;	/* s66 : oscillator frequency [kHz] */
-	s->config.w92 = 12000;
-
-	s->config.w9C = 0x000e;
-	s->config.w9E = 0x0000;
-
-	/* ConfigureMPEGOutput params */
-	s->config.wA0 = 4;
-	s->config.w98 = 1;
-	s->config.w9A = 1;
-
-	/* get chip revision */
-	rc = RD16(s, 0x2410019);
-	if (rc < 0)
-		return -ENODEV;
-
-	if (rc == 0) {
-		printk(KERN_INFO "%s: chip revision A2\n", mod_name);
-		rc = drx_load_fw(s, DRXD_FW_A2);
-	} else {
-
-		rc = (rc >> 12) - 3;
-		switch (rc) {
-		case 1:
-			s->flags |= F_SET_0D4h;
-		case 0:
-		case 4:
-			s->flags |= F_SET_0D0h;
-			break;
-		case 2:
-		case 5:
-			break;
-		case 3:
-			s->flags |= F_SET_0D4h;
-			break;
-		default:
-			return -ENODEV;
-		};
-		printk(KERN_INFO "%s: chip revision B1.%d\n", mod_name, rc);
-		rc = drx_load_fw(s, DRXD_FW_B1);
-	}
-	if (rc < 0)
-		goto error;
-
-	rc = WR16(s, 0x0420033, 0x3973);
-	if (rc < 0)
-		goto error;
-
-	rc = HI_Command(s, 2);
-
-	msleep(1);
-
-	if (s->chip_rev == DRXD_FW_A2) {
-		rc = WR16(s, 0x043012d, 0x47F);
-		if (rc < 0)
-			goto error;
-	}
-	rc = WR16_E0(s, 0x0400000, 0);
-	if (rc < 0)
-		goto error;
-
-	if (s->config.w92 > 20000 || s->config.w92 % 4000) {
-		printk(KERN_ERR "%s: invalid osc frequency\n", mod_name);
-		rc = -1;
-		goto error;
-	}
-
-	rc = WR16(s, 0x2410010, 1);
-	if (rc < 0)
-		goto error;
-	rc = WR16(s, 0x2410011, 0x15);
-	if (rc < 0)
-		goto error;
-	rc = WR16(s, 0x2410012, s->config.w92 / 4000);
-	if (rc < 0)
-		goto error;
-#ifdef ORIG_FW
-	rc = WR16(s, 0x2410015, 2);
-	if (rc < 0)
-		goto error;
-#endif
-	rc = WR16(s, 0x2410017, 0x3973);
-	if (rc < 0)
-		goto error;
-
-	s->f_osc = s->config.f_osc * 1000;	/* initial estimator */
-
-	s->config.w56 = 1;
-
-	rc = HI_CfgCommand(s);
-	if (rc < 0)
-		goto error;
-
-	rc = write_fw(s, DRXD_InitAtomicRead);
-	if (rc < 0)
-		goto error;
-
-	if (s->chip_rev == DRXD_FW_A2) {
-		rc = WR16(s, 0x2150013, 0);
-		if (rc < 0)
-			goto error;
-	}
-
-	rc = WR16_E0(s, 0x0400002, 0);
-	if (rc < 0)
-		goto error;
-	rc = WR16(s, 0x0400002, 0);
-	if (rc < 0)
-		goto error;
-
-	if (s->chip_rev == DRXD_FW_A2) {
-		rc = write_fw(s, DRXD_ResetCEFR);
-		if (rc < 0)
-			goto error;
-	}
-	rc = write_fw(s, DRXD_microcode);
-	if (rc < 0)
-		goto error;
-
-	s->config.w9C = 0x0e;
-	if (s->flags & F_SET_0D0h) {
-		s->config.w9C = 0;
-		rc = RD16(s, 0x0c20010);
-		if (rc < 0)
-			goto write_DRXD_InitFE_1;
-
-		rc &= ~0x1000;
-		rc = WR16(s, 0x0c20010, rc);
-		if (rc < 0)
-			goto write_DRXD_InitFE_1;
-
-		rc = RD16(s, 0x0c20011);
-		if (rc < 0)
-			goto write_DRXD_InitFE_1;
-
-		rc &= ~0x8;
-		rc = WR16(s, 0x0c20011, rc);
-		if (rc < 0)
-			goto write_DRXD_InitFE_1;
-
-		rc = WR16(s, 0x0c20012, 1);
-	}
-
-write_DRXD_InitFE_1:
-
-	rc = write_fw(s, DRXD_InitFE_1);
-	if (rc < 0)
-		goto error;
-
-	rc = 1;
-	if (s->chip_rev == DRXD_FW_B1) {
-		if (s->flags & F_SET_0D0h)
-			rc = 0;
-	} else {
-		if (s->flags & F_SET_0D0h)
-			rc = 4;
-	}
-
-	rc = WR16(s, 0x0C20012, rc);
-	if (rc < 0)
-		goto error;
-
-	rc = WR16(s, 0x0C20013, s->config.w9E);
-	if (rc < 0)
-		goto error;
-	rc = WR16(s, 0x0C20015, s->config.w9C);
-	if (rc < 0)
-		goto error;
-
-	rc = write_fw(s, DRXD_InitFE_2);
-	if (rc < 0)
-		goto error;
-	rc = write_fw(s, DRXD_InitFT);
-	if (rc < 0)
-		goto error;
-	rc = write_fw(s, DRXD_InitCP);
-	if (rc < 0)
-		goto error;
-	rc = write_fw(s, DRXD_InitCE);
-	if (rc < 0)
-		goto error;
-	rc = write_fw(s, DRXD_InitEQ);
-	if (rc < 0)
-		goto error;
-	rc = write_fw(s, DRXD_InitEC);
-	if (rc < 0)
-		goto error;
-	rc = write_fw(s, DRXD_InitSC);
-	if (rc < 0)
-		goto error;
-
-	rc = SetCfgIfAgc(s, &s->config.ifagc);
-	if (rc < 0)
-		goto error;
-
-	rc = SetCfgRfAgc(s, &s->config.rfagc);
-	if (rc < 0)
-		goto error;
-
-	rc = ConfigureMPEGOutput(s, 1);
-	rc = WR16(s, 0x08201fe, 0x0017);
-	rc = WR16(s, 0x08201ff, 0x0101);
-
-	s->config.d5C = 0;
-	s->config.d60 = 1;
-	s->config.d48 = 1;
-
-error:
-	return rc;
-}
-
-static int drx397x_get_frontend(struct dvb_frontend *fe,
-				struct dvb_frontend_parameters *params)
-{
-	return 0;
-}
-
-static int drx397x_set_frontend(struct dvb_frontend *fe,
-				struct dvb_frontend_parameters *params)
-{
-	struct drx397xD_state *s = fe->demodulator_priv;
-
-	s->config.s20d24 = 1;
-
-	return drx_tune(s, params);
-}
-
-static int drx397x_get_tune_settings(struct dvb_frontend *fe,
-				     struct dvb_frontend_tune_settings
-				     *fe_tune_settings)
-{
-	fe_tune_settings->min_delay_ms = 10000;
-	fe_tune_settings->step_size = 0;
-	fe_tune_settings->max_drift = 0;
-
-	return 0;
-}
-
-static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct drx397xD_state *s = fe->demodulator_priv;
-	int lockstat;
-
-	GetLockStatus(s, &lockstat);
-
-	*status = 0;
-	if (lockstat & 2) {
-		CorrectSysClockDeviation(s);
-		ConfigureMPEGOutput(s, 1);
-		*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI;
-	}
-	if (lockstat & 4)
-		*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
-
-	return 0;
-}
-
-static int drx397x_read_ber(struct dvb_frontend *fe, unsigned int *ber)
-{
-	*ber = 0;
-
-	return 0;
-}
-
-static int drx397x_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	*snr = 0;
-
-	return 0;
-}
-
-static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct drx397xD_state *s = fe->demodulator_priv;
-	int rc;
-
-	if (s->config.ifagc.d00 == 2) {
-		*strength = 0xffff;
-		return 0;
-	}
-	rc = RD16(s, 0x0c20035);
-	if (rc < 0) {
-		*strength = 0;
-		return 0;
-	}
-	rc &= 0x3ff;
-	/* Signal strength is calculated using the following formula:
-	 *
-	 * a = 2200 * 150 / (2200 + 150);
-	 * a = a * 3300 /  (a + 820);
-	 * b = 2200 * 3300 / (2200 + 820);
-	 * c = (((b-a) * rc) >> 10  + a) << 4;
-	 * strength = ~c & 0xffff;
-	 *
-	 * The following does the same but with less rounding errors:
-	 */
-	*strength = ~(7720 + (rc * 30744 >> 10));
-
-	return 0;
-}
-
-static int drx397x_read_ucblocks(struct dvb_frontend *fe,
-				 unsigned int *ucblocks)
-{
-	*ucblocks = 0;
-
-	return 0;
-}
-
-static int drx397x_sleep(struct dvb_frontend *fe)
-{
-	return 0;
-}
-
-static void drx397x_release(struct dvb_frontend *fe)
-{
-	struct drx397xD_state *s = fe->demodulator_priv;
-	printk(KERN_INFO "%s: release demodulator\n", mod_name);
-	if (s) {
-		drx_release_fw(s);
-		kfree(s);
-	}
-
-}
-
-static struct dvb_frontend_ops drx397x_ops = {
-
-	.info = {
-		 .name			= "Micronas DRX397xD DVB-T Frontend",
-		 .type			= FE_OFDM,
-		 .frequency_min		= 47125000,
-		 .frequency_max		= 855250000,
-		 .frequency_stepsize	= 166667,
-		 .frequency_tolerance	= 0,
-		 .caps =				  /* 0x0C01B2EAE */
-			 FE_CAN_FEC_1_2			| /* = 0x2, */
-			 FE_CAN_FEC_2_3			| /* = 0x4, */
-			 FE_CAN_FEC_3_4			| /* = 0x8, */
-			 FE_CAN_FEC_5_6			| /* = 0x20, */
-			 FE_CAN_FEC_7_8			| /* = 0x80, */
-			 FE_CAN_FEC_AUTO		| /* = 0x200, */
-			 FE_CAN_QPSK			| /* = 0x400, */
-			 FE_CAN_QAM_16			| /* = 0x800, */
-			 FE_CAN_QAM_64			| /* = 0x2000, */
-			 FE_CAN_QAM_AUTO		| /* = 0x10000, */
-			 FE_CAN_TRANSMISSION_MODE_AUTO	| /* = 0x20000, */
-			 FE_CAN_GUARD_INTERVAL_AUTO	| /* = 0x80000, */
-			 FE_CAN_HIERARCHY_AUTO		| /* = 0x100000, */
-			 FE_CAN_RECOVER			| /* = 0x40000000, */
-			 FE_CAN_MUTE_TS			  /* = 0x80000000 */
-	 },
-
-	.release = drx397x_release,
-	.init = drx397x_init,
-	.sleep = drx397x_sleep,
-
-	.set_frontend = drx397x_set_frontend,
-	.get_tune_settings = drx397x_get_tune_settings,
-	.get_frontend = drx397x_get_frontend,
-
-	.read_status = drx397x_read_status,
-	.read_snr = drx397x_read_snr,
-	.read_signal_strength = drx397x_read_signal_strength,
-	.read_ber = drx397x_read_ber,
-	.read_ucblocks = drx397x_read_ucblocks,
-};
-
-struct dvb_frontend *drx397xD_attach(const struct drx397xD_config *config,
-				     struct i2c_adapter *i2c)
-{
-	struct drx397xD_state *state;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL);
-	if (!state)
-		goto error;
-
-	/* setup the state */
-	state->i2c = i2c;
-	memcpy(&state->config, config, sizeof(struct drx397xD_config));
-
-	/* check if the demod is there */
-	if (RD16(state, 0x2410019) < 0)
-		goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &drx397x_ops,
-			sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-
-	return &state->frontend;
-error:
-	kfree(state);
-
-	return NULL;
-}
-EXPORT_SYMBOL(drx397xD_attach);
-
-MODULE_DESCRIPTION("Micronas DRX397xD DVB-T Frontend");
-MODULE_AUTHOR("Henk Vergonet");
-MODULE_LICENSE("GPL");
-

+ 0 - 130
drivers/media/dvb/frontends/drx397xD.h

@@ -1,130 +0,0 @@
-/*
- *  Driver for Micronas DVB-T drx397xD demodulator
- *
- *  Copyright (C) 2007 Henk vergonet <Henk.Vergonet@gmail.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
- */
-
-#ifndef _DRX397XD_H_INCLUDED
-#define _DRX397XD_H_INCLUDED
-
-#include <linux/dvb/frontend.h>
-
-#define DRX_F_STEPSIZE	166667
-#define DRX_F_OFFSET	36000000
-
-#define I2C_ADR_C0(x) \
-(	cpu_to_le32( \
-		(u32)( \
-			(((u32)(x) & (u32)0x000000ffUL)      ) | \
-			(((u32)(x) & (u32)0x0000ff00UL) << 16) | \
-			(((u32)(x) & (u32)0x0fff0000UL) >>  8) | \
-			 (	     (u32)0x00c00000UL)          \
-		      )) \
-)
-
-#define I2C_ADR_E0(x) \
-(	cpu_to_le32( \
-		(u32)( \
-			(((u32)(x) & (u32)0x000000ffUL)      ) | \
-			(((u32)(x) & (u32)0x0000ff00UL) << 16) | \
-			(((u32)(x) & (u32)0x0fff0000UL) >>  8) | \
-			 (	     (u32)0x00e00000UL)          \
-		      )) \
-)
-
-struct drx397xD_CfgRfAgc	/* 0x7c */
-{
-	int d00;	/* 2 */
-	u16 w04;
-	u16 w06;
-};
-
-struct drx397xD_CfgIfAgc	/* 0x68 */
-{
-	int d00;	/* 0 */
-	u16 w04;	/* 0 */
-	u16 w06;
-	u16 w08;
-	u16 w0A;
-	u16 w0C;
-};
-
-struct drx397xD_s20 {
-	int d04;
-	u32 d18;
-	u32 d1C;
-	u32 d20;
-	u32 d14;
-	u32 d24;
-	u32 d0C;
-	u32 d08;
-};
-
-struct drx397xD_config
-{
-	/* demodulator's I2C address */
-	u8	demod_address;		/* 0x0f */
-
-	struct drx397xD_CfgIfAgc  ifagc;  /* 0x68 */
-	struct drx397xD_CfgRfAgc  rfagc;  /* 0x7c */
-	u32	s20d24;
-
-	/* HI_CfgCommand parameters */
-	u16	w50, w52, /* w54, */ w56;
-
-	int	d5C;
-	int	d60;
-	int	d48;
-	int	d28;
-
-	u32	f_if;	/* d14: intermediate frequency [Hz]		*/
-			/*	36000000 on Cinergy 2400i DT		*/
-			/*	42800000 on Pinnacle Hybrid PRO 330e	*/
-
-	u16	f_osc;	/* s66: 48000 oscillator frequency [kHz]	*/
-
-	u16	w92;	/* 20000 */
-
-	u16	wA0;
-	u16	w98;
-	u16	w9A;
-
-	u16	w9C;	/* 0xe0 */
-	u16	w9E;	/* 0x00 */
-
-	/* used for signal strength calculations in
-	   drx397x_read_signal_strength
-	*/
-	u16	ss78;	// 2200
-	u16	ss7A;	// 150
-	u16	ss76;	// 820
-};
-
-#if defined(CONFIG_DVB_DRX397XD) || (defined(CONFIG_DVB_DRX397XD_MODULE) && defined(MODULE))
-extern struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config,
-					   struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config,
-					   struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_DRX397XD */
-
-#endif /* _DRX397XD_H_INCLUDED */

+ 0 - 40
drivers/media/dvb/frontends/drx397xD_fw.h

@@ -1,40 +0,0 @@
-/*
- * Firmware definitions for Micronas drx397xD
- *
- * Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef _FW_ENTRY
-	_FW_ENTRY("drx397xD.A2.fw",	DRXD_FW_A2 = 0,	DRXD_FW_A2	),
-	_FW_ENTRY("drx397xD.B1.fw",	DRXD_FW_B1,	DRXD_FW_B1	),
-#undef _FW_ENTRY
-#endif /* _FW_ENTRY */
-
-#ifdef _BLOB_ENTRY
-	_BLOB_ENTRY("InitAtomicRead",	DRXD_InitAtomicRead = 0	),
-	_BLOB_ENTRY("InitCE",		DRXD_InitCE		),
-	_BLOB_ENTRY("InitCP",		DRXD_InitCP		),
-	_BLOB_ENTRY("InitEC",		DRXD_InitEC		),
-	_BLOB_ENTRY("InitEQ",		DRXD_InitEQ		),
-	_BLOB_ENTRY("InitFE_1",		DRXD_InitFE_1		),
-	_BLOB_ENTRY("InitFE_2",		DRXD_InitFE_2		),
-	_BLOB_ENTRY("InitFT",		DRXD_InitFT		),
-	_BLOB_ENTRY("InitSC",		DRXD_InitSC		),
-	_BLOB_ENTRY("ResetCEFR",	DRXD_ResetCEFR		),
-	_BLOB_ENTRY("ResetECRAM",	DRXD_ResetECRAM		),
-	_BLOB_ENTRY("microcode",	DRXD_microcode		),
-#undef _BLOB_ENTRY
-#endif /* _BLOB_ENTRY */

+ 61 - 0
drivers/media/dvb/frontends/drxd.h

@@ -0,0 +1,61 @@
+/*
+ * drxd.h: DRXD DVB-T demodulator driver
+ *
+ * Copyright (C) 2005-2007 Micronas
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef _DRXD_H_
+#define _DRXD_H_
+
+#include <linux/types.h>
+#include <linux/i2c.h>
+
+struct drxd_config {
+	u8 index;
+
+	u8 pll_address;
+	u8 pll_type;
+#define DRXD_PLL_NONE     0
+#define DRXD_PLL_DTT7520X 1
+#define DRXD_PLL_MT3X0823 2
+
+	u32 clock;
+	u8 insert_rs_byte;
+
+	u8 demod_address;
+	u8 demoda_address;
+	u8 demod_revision;
+
+	/* If the tuner is not behind an i2c gate, be sure to flip this bit
+	   or else the i2c bus could get wedged */
+	u8 disable_i2c_gate_ctrl;
+
+	u32 IF;
+	int (*pll_set) (void *priv, void *priv_params,
+			u8 pll_addr, u8 demoda_addr, s32 *off);
+	 s16(*osc_deviation) (void *priv, s16 dev, int flag);
+};
+
+extern
+struct dvb_frontend *drxd_attach(const struct drxd_config *config,
+				 void *priv, struct i2c_adapter *i2c,
+				 struct device *dev);
+extern int drxd_config_i2c(struct dvb_frontend *, int);
+#endif

+ 929 - 0
drivers/media/dvb/frontends/drxd_firm.c

@@ -0,0 +1,929 @@
+/*
+ * drxd_firm.c : DRXD firmware tables
+ *
+ * Copyright (C) 2006-2007 Micronas
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+/* TODO: generate this file with a script from a settings file */
+
+/* Contains A2 firmware version: 1.4.2
+ * Contains B1 firmware version: 3.3.33
+ * Contains settings from driver 1.4.23
+*/
+
+#include "drxd_firm.h"
+
+#define ADDRESS(x)     ((x) & 0xFF), (((x)>>8) & 0xFF), (((x)>>16) & 0xFF), (((x)>>24) & 0xFF)
+#define LENGTH(x)      ((x) & 0xFF), (((x)>>8) & 0xFF)
+
+/* Is written via block write, must be little endian */
+#define DATA16(x)      ((x) & 0xFF), (((x)>>8) & 0xFF)
+
+#define WRBLOCK(a, l) ADDRESS(a), LENGTH(l)
+#define WR16(a, d) ADDRESS(a), LENGTH(1), DATA16(d)
+
+#define END_OF_TABLE      0xFF, 0xFF, 0xFF, 0xFF
+
+/* HI firmware patches */
+
+#define HI_TR_FUNC_ADDR HI_IF_RAM_USR_BEGIN__A
+#define HI_TR_FUNC_SIZE 9	/* size of this function in instruction words */
+
+u8 DRXD_InitAtomicRead[] = {
+	WRBLOCK(HI_TR_FUNC_ADDR, HI_TR_FUNC_SIZE),
+	0x26, 0x00,		/* 0         -> ring.rdy;           */
+	0x60, 0x04,		/* r0rami.dt -> ring.xba;           */
+	0x61, 0x04,		/* r0rami.dt -> ring.xad;           */
+	0xE3, 0x07,		/* HI_RA_RAM_USR_BEGIN -> ring.iad; */
+	0x40, 0x00,		/* (long immediate)                 */
+	0x64, 0x04,		/* r0rami.dt -> ring.len;           */
+	0x65, 0x04,		/* r0rami.dt -> ring.ctl;           */
+	0x26, 0x00,		/* 0         -> ring.rdy;           */
+	0x38, 0x00,		/* 0         -> jumps.ad;           */
+	END_OF_TABLE
+};
+
+/* Pins D0 and D1 of the parallel MPEG output can be used
+   to set the I2C address of a device. */
+
+#define HI_RST_FUNC_ADDR (HI_IF_RAM_USR_BEGIN__A + HI_TR_FUNC_SIZE)
+#define HI_RST_FUNC_SIZE 54	/* size of this function in instruction words */
+
+/* D0 Version */
+u8 DRXD_HiI2cPatch_1[] = {
+	WRBLOCK(HI_RST_FUNC_ADDR, HI_RST_FUNC_SIZE),
+	0xC8, 0x07, 0x01, 0x00,	/* MASK      -> reg0.dt;                        */
+	0xE0, 0x07, 0x15, 0x02,	/* (EC__BLK << 6) + EC_OC_REG__BNK -> ring.xba; */
+	0xE1, 0x07, 0x12, 0x00,	/* EC_OC_REG_OC_MPG_SIO__A -> ring.xad;         */
+	0xA2, 0x00,		/* M_BNK_ID_DAT -> ring.iba;                    */
+	0x23, 0x00,		/* &data     -> ring.iad;                       */
+	0x24, 0x00,		/* 0         -> ring.len;                       */
+	0xA5, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl;   */
+	0x26, 0x00,		/* 0         -> ring.rdy;                       */
+	0x42, 0x00,		/* &data+1   -> w0ram.ad;                       */
+	0xC0, 0x07, 0xFF, 0x0F,	/* -1        -> w0ram.dt;                       */
+	0x63, 0x00,		/* &data+1   -> ring.iad;                       */
+	0x65, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl;  */
+	0x26, 0x00,		/* 0         -> ring.rdy;                       */
+	0xE1, 0x07, 0x38, 0x00,	/* EC_OC_REG_OCR_MPG_USR_DAT__A -> ring.xad;    */
+	0xA5, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl;   */
+	0x26, 0x00,		/* 0         -> ring.rdy;                       */
+	0xE1, 0x07, 0x12, 0x00,	/* EC_OC_REG_OC_MPG_SIO__A -> ring.xad;         */
+	0x23, 0x00,		/* &data     -> ring.iad;                       */
+	0x65, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl;  */
+	0x26, 0x00,		/* 0         -> ring.rdy;                       */
+	0x42, 0x00,		/* &data+1   -> w0ram.ad;                       */
+	0x0F, 0x04,		/* r0ram.dt  -> and.op;                         */
+	0x1C, 0x06,		/* reg0.dt   -> and.tr;                         */
+	0xCF, 0x04,		/* and.rs    -> add.op;                         */
+	0xD0, 0x07, 0x70, 0x00,	/* DEF_DEV_ID -> add.tr;                        */
+	0xD0, 0x04,		/* add.rs    -> add.tr;                         */
+	0xC8, 0x04,		/* add.rs    -> reg0.dt;                        */
+	0x60, 0x00,		/* reg0.dt   -> w0ram.dt;                       */
+	0xC2, 0x07, 0x10, 0x00,	/* SLV0_BASE -> w0rami.ad;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x01, 0x06,		/* reg0.dt   -> w0rami.dt;                      */
+	0xC2, 0x07, 0x20, 0x00,	/* SLV1_BASE -> w0rami.ad;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x01, 0x06,		/* reg0.dt   -> w0rami.dt;                      */
+	0xC2, 0x07, 0x30, 0x00,	/* CMD_BASE  -> w0rami.ad;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x68, 0x00,		/* M_IC_SEL_PT1 -> i2c.sel;                     */
+	0x29, 0x00,		/* M_IC_CMD_RESET -> i2c.cmd;                   */
+	0x28, 0x00,		/* M_IC_SEL_PT0 -> i2c.sel;                     */
+	0x29, 0x00,		/* M_IC_CMD_RESET -> i2c.cmd;                   */
+	0xF8, 0x07, 0x2F, 0x00,	/* 0x2F      -> jumps.ad;                       */
+
+	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 0) + 1)),
+	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
+	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 1) + 1)),
+	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
+	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 2) + 1)),
+	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
+	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 3) + 1)),
+	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
+
+	/* Force quick and dirty reset */
+	WR16(B_HI_CT_REG_COMM_STATE__A, 0),
+	END_OF_TABLE
+};
+
+/* D0,D1 Version */
+u8 DRXD_HiI2cPatch_3[] = {
+	WRBLOCK(HI_RST_FUNC_ADDR, HI_RST_FUNC_SIZE),
+	0xC8, 0x07, 0x03, 0x00,	/* MASK      -> reg0.dt;                        */
+	0xE0, 0x07, 0x15, 0x02,	/* (EC__BLK << 6) + EC_OC_REG__BNK -> ring.xba; */
+	0xE1, 0x07, 0x12, 0x00,	/* EC_OC_REG_OC_MPG_SIO__A -> ring.xad;         */
+	0xA2, 0x00,		/* M_BNK_ID_DAT -> ring.iba;                    */
+	0x23, 0x00,		/* &data     -> ring.iad;                       */
+	0x24, 0x00,		/* 0         -> ring.len;                       */
+	0xA5, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl;   */
+	0x26, 0x00,		/* 0         -> ring.rdy;                       */
+	0x42, 0x00,		/* &data+1   -> w0ram.ad;                       */
+	0xC0, 0x07, 0xFF, 0x0F,	/* -1        -> w0ram.dt;                       */
+	0x63, 0x00,		/* &data+1   -> ring.iad;                       */
+	0x65, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl;  */
+	0x26, 0x00,		/* 0         -> ring.rdy;                       */
+	0xE1, 0x07, 0x38, 0x00,	/* EC_OC_REG_OCR_MPG_USR_DAT__A -> ring.xad;    */
+	0xA5, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl;   */
+	0x26, 0x00,		/* 0         -> ring.rdy;                       */
+	0xE1, 0x07, 0x12, 0x00,	/* EC_OC_REG_OC_MPG_SIO__A -> ring.xad;         */
+	0x23, 0x00,		/* &data     -> ring.iad;                       */
+	0x65, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl;  */
+	0x26, 0x00,		/* 0         -> ring.rdy;                       */
+	0x42, 0x00,		/* &data+1   -> w0ram.ad;                       */
+	0x0F, 0x04,		/* r0ram.dt  -> and.op;                         */
+	0x1C, 0x06,		/* reg0.dt   -> and.tr;                         */
+	0xCF, 0x04,		/* and.rs    -> add.op;                         */
+	0xD0, 0x07, 0x70, 0x00,	/* DEF_DEV_ID -> add.tr;                        */
+	0xD0, 0x04,		/* add.rs    -> add.tr;                         */
+	0xC8, 0x04,		/* add.rs    -> reg0.dt;                        */
+	0x60, 0x00,		/* reg0.dt   -> w0ram.dt;                       */
+	0xC2, 0x07, 0x10, 0x00,	/* SLV0_BASE -> w0rami.ad;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x01, 0x06,		/* reg0.dt   -> w0rami.dt;                      */
+	0xC2, 0x07, 0x20, 0x00,	/* SLV1_BASE -> w0rami.ad;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x01, 0x06,		/* reg0.dt   -> w0rami.dt;                      */
+	0xC2, 0x07, 0x30, 0x00,	/* CMD_BASE  -> w0rami.ad;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x68, 0x00,		/* M_IC_SEL_PT1 -> i2c.sel;                     */
+	0x29, 0x00,		/* M_IC_CMD_RESET -> i2c.cmd;                   */
+	0x28, 0x00,		/* M_IC_SEL_PT0 -> i2c.sel;                     */
+	0x29, 0x00,		/* M_IC_CMD_RESET -> i2c.cmd;                   */
+	0xF8, 0x07, 0x2F, 0x00,	/* 0x2F      -> jumps.ad;                       */
+
+	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 0) + 1)),
+	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
+	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 1) + 1)),
+	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
+	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 2) + 1)),
+	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
+	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 3) + 1)),
+	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
+
+	/* Force quick and dirty reset */
+	WR16(B_HI_CT_REG_COMM_STATE__A, 0),
+	END_OF_TABLE
+};
+
+u8 DRXD_ResetCEFR[] = {
+	WRBLOCK(CE_REG_FR_TREAL00__A, 57),
+	0x52, 0x00,		/* CE_REG_FR_TREAL00__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG00__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL01__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG01__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL02__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG02__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL03__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG03__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL04__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG04__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL05__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG05__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL06__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG06__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL07__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG07__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL08__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG08__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL09__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG09__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL10__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG10__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL11__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG11__A */
+
+	0x52, 0x00,		/* CE_REG_FR_MID_TAP__A */
+
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G00__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G01__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G02__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G03__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G04__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G05__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G06__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G07__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G08__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G09__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G10__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G11__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G12__A */
+
+	0xFF, 0x01,		/* CE_REG_FR_RIO_G00__A */
+	0x90, 0x01,		/* CE_REG_FR_RIO_G01__A */
+	0x0B, 0x01,		/* CE_REG_FR_RIO_G02__A */
+	0xC8, 0x00,		/* CE_REG_FR_RIO_G03__A */
+	0xA0, 0x00,		/* CE_REG_FR_RIO_G04__A */
+	0x85, 0x00,		/* CE_REG_FR_RIO_G05__A */
+	0x72, 0x00,		/* CE_REG_FR_RIO_G06__A */
+	0x64, 0x00,		/* CE_REG_FR_RIO_G07__A */
+	0x59, 0x00,		/* CE_REG_FR_RIO_G08__A */
+	0x50, 0x00,		/* CE_REG_FR_RIO_G09__A */
+	0x49, 0x00,		/* CE_REG_FR_RIO_G10__A */
+
+	0x10, 0x00,		/* CE_REG_FR_MODE__A     */
+	0x78, 0x00,		/* CE_REG_FR_SQS_TRH__A  */
+	0x00, 0x00,		/* CE_REG_FR_RIO_GAIN__A */
+	0x00, 0x02,		/* CE_REG_FR_BYPASS__A   */
+	0x0D, 0x00,		/* CE_REG_FR_PM_SET__A   */
+	0x07, 0x00,		/* CE_REG_FR_ERR_SH__A   */
+	0x04, 0x00,		/* CE_REG_FR_MAN_SH__A   */
+	0x06, 0x00,		/* CE_REG_FR_TAP_SH__A   */
+
+	END_OF_TABLE
+};
+
+u8 DRXD_InitFEA2_1[] = {
+	WRBLOCK(FE_AD_REG_PD__A, 3),
+	0x00, 0x00,		/* FE_AD_REG_PD__A          */
+	0x01, 0x00,		/* FE_AD_REG_INVEXT__A      */
+	0x00, 0x00,		/* FE_AD_REG_CLKNEG__A      */
+
+	WRBLOCK(FE_AG_REG_DCE_AUR_CNT__A, 2),
+	0x10, 0x00,		/* FE_AG_REG_DCE_AUR_CNT__A */
+	0x10, 0x00,		/* FE_AG_REG_DCE_RUR_CNT__A */
+
+	WRBLOCK(FE_AG_REG_ACE_AUR_CNT__A, 2),
+	0x0E, 0x00,		/* FE_AG_REG_ACE_AUR_CNT__A */
+	0x00, 0x00,		/* FE_AG_REG_ACE_RUR_CNT__A */
+
+	WRBLOCK(FE_AG_REG_EGC_FLA_RGN__A, 5),
+	0x04, 0x00,		/* FE_AG_REG_EGC_FLA_RGN__A */
+	0x1F, 0x00,		/* FE_AG_REG_EGC_SLO_RGN__A */
+	0x00, 0x00,		/* FE_AG_REG_EGC_JMP_PSN__A */
+	0x00, 0x00,		/* FE_AG_REG_EGC_FLA_INC__A */
+	0x00, 0x00,		/* FE_AG_REG_EGC_FLA_DEC__A */
+
+	WRBLOCK(FE_AG_REG_GC1_AGC_MAX__A, 2),
+	0xFF, 0x01,		/* FE_AG_REG_GC1_AGC_MAX__A */
+	0x00, 0xFE,		/* FE_AG_REG_GC1_AGC_MIN__A */
+
+	WRBLOCK(FE_AG_REG_IND_WIN__A, 29),
+	0x00, 0x00,		/* FE_AG_REG_IND_WIN__A     */
+	0x05, 0x00,		/* FE_AG_REG_IND_THD_LOL__A */
+	0x0F, 0x00,		/* FE_AG_REG_IND_THD_HIL__A */
+	0x00, 0x00,		/* FE_AG_REG_IND_DEL__A     don't care */
+	0x1E, 0x00,		/* FE_AG_REG_IND_PD1_WRI__A */
+	0x0C, 0x00,		/* FE_AG_REG_PDA_AUR_CNT__A */
+	0x00, 0x00,		/* FE_AG_REG_PDA_RUR_CNT__A */
+	0x00, 0x00,		/* FE_AG_REG_PDA_AVE_DAT__A don't care  */
+	0x00, 0x00,		/* FE_AG_REG_PDC_RUR_CNT__A */
+	0x01, 0x00,		/* FE_AG_REG_PDC_SET_LVL__A */
+	0x02, 0x00,		/* FE_AG_REG_PDC_FLA_RGN__A */
+	0x00, 0x00,		/* FE_AG_REG_PDC_JMP_PSN__A don't care  */
+	0xFF, 0xFF,		/* FE_AG_REG_PDC_FLA_STP__A */
+	0xFF, 0xFF,		/* FE_AG_REG_PDC_SLO_STP__A */
+	0x00, 0x1F,		/* FE_AG_REG_PDC_PD2_WRI__A don't care  */
+	0x00, 0x00,		/* FE_AG_REG_PDC_MAP_DAT__A don't care  */
+	0x02, 0x00,		/* FE_AG_REG_PDC_MAX__A     */
+	0x0C, 0x00,		/* FE_AG_REG_TGA_AUR_CNT__A */
+	0x00, 0x00,		/* FE_AG_REG_TGA_RUR_CNT__A */
+	0x00, 0x00,		/* FE_AG_REG_TGA_AVE_DAT__A don't care  */
+	0x00, 0x00,		/* FE_AG_REG_TGC_RUR_CNT__A */
+	0x22, 0x00,		/* FE_AG_REG_TGC_SET_LVL__A */
+	0x15, 0x00,		/* FE_AG_REG_TGC_FLA_RGN__A */
+	0x00, 0x00,		/* FE_AG_REG_TGC_JMP_PSN__A don't care  */
+	0x01, 0x00,		/* FE_AG_REG_TGC_FLA_STP__A */
+	0x0A, 0x00,		/* FE_AG_REG_TGC_SLO_STP__A */
+	0x00, 0x00,		/* FE_AG_REG_TGC_MAP_DAT__A don't care  */
+	0x10, 0x00,		/* FE_AG_REG_FGA_AUR_CNT__A */
+	0x10, 0x00,		/* FE_AG_REG_FGA_RUR_CNT__A */
+
+	WRBLOCK(FE_AG_REG_BGC_FGC_WRI__A, 2),
+	0x00, 0x00,		/* FE_AG_REG_BGC_FGC_WRI__A */
+	0x00, 0x00,		/* FE_AG_REG_BGC_CGC_WRI__A */
+
+	WRBLOCK(FE_FD_REG_SCL__A, 3),
+	0x05, 0x00,		/* FE_FD_REG_SCL__A         */
+	0x03, 0x00,		/* FE_FD_REG_MAX_LEV__A     */
+	0x05, 0x00,		/* FE_FD_REG_NR__A          */
+
+	WRBLOCK(FE_CF_REG_SCL__A, 5),
+	0x16, 0x00,		/* FE_CF_REG_SCL__A         */
+	0x04, 0x00,		/* FE_CF_REG_MAX_LEV__A     */
+	0x06, 0x00,		/* FE_CF_REG_NR__A          */
+	0x00, 0x00,		/* FE_CF_REG_IMP_VAL__A     */
+	0x01, 0x00,		/* FE_CF_REG_MEAS_VAL__A    */
+
+	WRBLOCK(FE_CU_REG_FRM_CNT_RST__A, 2),
+	0x00, 0x08,		/* FE_CU_REG_FRM_CNT_RST__A */
+	0x00, 0x00,		/* FE_CU_REG_FRM_CNT_STR__A */
+
+	END_OF_TABLE
+};
+
+   /* with PGA */
+/*   WR16COND( DRXD_WITH_PGA, FE_AG_REG_AG_PGA_MODE__A   , 0x0004), */
+   /* without PGA */
+/*   WR16COND( DRXD_WITHOUT_PGA, FE_AG_REG_AG_PGA_MODE__A   , 0x0001), */
+/*   WR16(FE_AG_REG_AG_AGC_SIO__A,  (extAttr -> FeAgRegAgAgcSio), 0x0000 );*/
+/*   WR16(FE_AG_REG_AG_PWD__A        ,(extAttr -> FeAgRegAgPwd), 0x0000 );*/
+
+u8 DRXD_InitFEA2_2[] = {
+	WR16(FE_AG_REG_CDR_RUR_CNT__A, 0x0010),
+	WR16(FE_AG_REG_FGM_WRI__A, 48),
+	/* Activate measurement, activate scale */
+	WR16(FE_FD_REG_MEAS_VAL__A, 0x0001),
+
+	WR16(FE_CU_REG_COMM_EXEC__A, 0x0001),
+	WR16(FE_CF_REG_COMM_EXEC__A, 0x0001),
+	WR16(FE_IF_REG_COMM_EXEC__A, 0x0001),
+	WR16(FE_FD_REG_COMM_EXEC__A, 0x0001),
+	WR16(FE_FS_REG_COMM_EXEC__A, 0x0001),
+	WR16(FE_AD_REG_COMM_EXEC__A, 0x0001),
+	WR16(FE_AG_REG_COMM_EXEC__A, 0x0001),
+	WR16(FE_AG_REG_AG_MODE_LOP__A, 0x895E),
+
+	END_OF_TABLE
+};
+
+u8 DRXD_InitFEB1_1[] = {
+	WR16(B_FE_AD_REG_PD__A, 0x0000),
+	WR16(B_FE_AD_REG_CLKNEG__A, 0x0000),
+	WR16(B_FE_AG_REG_BGC_FGC_WRI__A, 0x0000),
+	WR16(B_FE_AG_REG_BGC_CGC_WRI__A, 0x0000),
+	WR16(B_FE_AG_REG_AG_MODE_LOP__A, 0x000a),
+	WR16(B_FE_AG_REG_IND_PD1_WRI__A, 35),
+	WR16(B_FE_AG_REG_IND_WIN__A, 0),
+	WR16(B_FE_AG_REG_IND_THD_LOL__A, 8),
+	WR16(B_FE_AG_REG_IND_THD_HIL__A, 8),
+	WR16(B_FE_CF_REG_IMP_VAL__A, 1),
+	WR16(B_FE_AG_REG_EGC_FLA_RGN__A, 7),
+	END_OF_TABLE
+};
+
+	/* with PGA */
+/*      WR16(B_FE_AG_REG_AG_PGA_MODE__A   , 0x0000, 0x0000); */
+       /* without PGA */
+/*      WR16(B_FE_AG_REG_AG_PGA_MODE__A   ,
+	     B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 0x0000);*/
+									     /*   WR16(B_FE_AG_REG_AG_AGC_SIO__A,(extAttr -> FeAgRegAgAgcSio), 0x0000 );*//*added HS 23-05-2005 */
+/*   WR16(B_FE_AG_REG_AG_PWD__A    ,(extAttr -> FeAgRegAgPwd), 0x0000 );*/
+
+u8 DRXD_InitFEB1_2[] = {
+	WR16(B_FE_COMM_EXEC__A, 0x0001),
+
+	/* RF-AGC setup */
+	WR16(B_FE_AG_REG_PDA_AUR_CNT__A, 0x0C),
+	WR16(B_FE_AG_REG_PDC_SET_LVL__A, 0x01),
+	WR16(B_FE_AG_REG_PDC_FLA_RGN__A, 0x02),
+	WR16(B_FE_AG_REG_PDC_FLA_STP__A, 0xFFFF),
+	WR16(B_FE_AG_REG_PDC_SLO_STP__A, 0xFFFF),
+	WR16(B_FE_AG_REG_PDC_MAX__A, 0x02),
+	WR16(B_FE_AG_REG_TGA_AUR_CNT__A, 0x0C),
+	WR16(B_FE_AG_REG_TGC_SET_LVL__A, 0x22),
+	WR16(B_FE_AG_REG_TGC_FLA_RGN__A, 0x15),
+	WR16(B_FE_AG_REG_TGC_FLA_STP__A, 0x01),
+	WR16(B_FE_AG_REG_TGC_SLO_STP__A, 0x0A),
+
+	WR16(B_FE_CU_REG_DIV_NFC_CLP__A, 0),
+	WR16(B_FE_CU_REG_CTR_NFC_OCR__A, 25000),
+	WR16(B_FE_CU_REG_CTR_NFC_ICR__A, 1),
+	END_OF_TABLE
+};
+
+u8 DRXD_InitCPA2[] = {
+	WRBLOCK(CP_REG_BR_SPL_OFFSET__A, 2),
+	0x07, 0x00,		/* CP_REG_BR_SPL_OFFSET__A  */
+	0x0A, 0x00,		/* CP_REG_BR_STR_DEL__A     */
+
+	WRBLOCK(CP_REG_RT_ANG_INC0__A, 4),
+	0x00, 0x00,		/* CP_REG_RT_ANG_INC0__A    */
+	0x00, 0x00,		/* CP_REG_RT_ANG_INC1__A    */
+	0x03, 0x00,		/* CP_REG_RT_DETECT_ENA__A  */
+	0x03, 0x00,		/* CP_REG_RT_DETECT_TRH__A  */
+
+	WRBLOCK(CP_REG_AC_NEXP_OFFS__A, 5),
+	0x32, 0x00,		/* CP_REG_AC_NEXP_OFFS__A   */
+	0x62, 0x00,		/* CP_REG_AC_AVER_POW__A    */
+	0x82, 0x00,		/* CP_REG_AC_MAX_POW__A     */
+	0x26, 0x00,		/* CP_REG_AC_WEIGHT_MAN__A  */
+	0x0F, 0x00,		/* CP_REG_AC_WEIGHT_EXP__A  */
+
+	WRBLOCK(CP_REG_AC_AMP_MODE__A, 2),
+	0x02, 0x00,		/* CP_REG_AC_AMP_MODE__A    */
+	0x01, 0x00,		/* CP_REG_AC_AMP_FIX__A     */
+
+	WR16(CP_REG_INTERVAL__A, 0x0005),
+	WR16(CP_REG_RT_EXP_MARG__A, 0x0004),
+	WR16(CP_REG_AC_ANG_MODE__A, 0x0003),
+
+	WR16(CP_REG_COMM_EXEC__A, 0x0001),
+	END_OF_TABLE
+};
+
+u8 DRXD_InitCPB1[] = {
+	WR16(B_CP_REG_BR_SPL_OFFSET__A, 0x0008),
+	WR16(B_CP_COMM_EXEC__A, 0x0001),
+	END_OF_TABLE
+};
+
+u8 DRXD_InitCEA2[] = {
+	WRBLOCK(CE_REG_AVG_POW__A, 4),
+	0x62, 0x00,		/* CE_REG_AVG_POW__A        */
+	0x78, 0x00,		/* CE_REG_MAX_POW__A        */
+	0x62, 0x00,		/* CE_REG_ATT__A            */
+	0x17, 0x00,		/* CE_REG_NRED__A           */
+
+	WRBLOCK(CE_REG_NE_ERR_SELECT__A, 2),
+	0x07, 0x00,		/* CE_REG_NE_ERR_SELECT__A  */
+	0xEB, 0xFF,		/* CE_REG_NE_TD_CAL__A      */
+
+	WRBLOCK(CE_REG_NE_MIXAVG__A, 2),
+	0x06, 0x00,		/* CE_REG_NE_MIXAVG__A      */
+	0x00, 0x00,		/* CE_REG_NE_NUPD_OFS__A    */
+
+	WRBLOCK(CE_REG_PE_NEXP_OFFS__A, 2),
+	0x00, 0x00,		/* CE_REG_PE_NEXP_OFFS__A   */
+	0x00, 0x00,		/* CE_REG_PE_TIMESHIFT__A   */
+
+	WRBLOCK(CE_REG_TP_A0_TAP_NEW__A, 3),
+	0x00, 0x01,		/* CE_REG_TP_A0_TAP_NEW__A       */
+	0x01, 0x00,		/* CE_REG_TP_A0_TAP_NEW_VALID__A */
+	0x0E, 0x00,		/* CE_REG_TP_A0_MU_LMS_STEP__A   */
+
+	WRBLOCK(CE_REG_TP_A1_TAP_NEW__A, 3),
+	0x00, 0x00,		/* CE_REG_TP_A1_TAP_NEW__A        */
+	0x01, 0x00,		/* CE_REG_TP_A1_TAP_NEW_VALID__A  */
+	0x0A, 0x00,		/* CE_REG_TP_A1_MU_LMS_STEP__A    */
+
+	WRBLOCK(CE_REG_FI_SHT_INCR__A, 2),
+	0x12, 0x00,		/* CE_REG_FI_SHT_INCR__A          */
+	0x0C, 0x00,		/* CE_REG_FI_EXP_NORM__A          */
+
+	WRBLOCK(CE_REG_IR_INPUTSEL__A, 3),
+	0x00, 0x00,		/* CE_REG_IR_INPUTSEL__A          */
+	0x00, 0x00,		/* CE_REG_IR_STARTPOS__A          */
+	0xFF, 0x00,		/* CE_REG_IR_NEXP_THRES__A        */
+
+	WR16(CE_REG_TI_NEXP_OFFS__A, 0x0000),
+
+	END_OF_TABLE
+};
+
+u8 DRXD_InitCEB1[] = {
+	WR16(B_CE_REG_TI_PHN_ENABLE__A, 0x0001),
+	WR16(B_CE_REG_FR_PM_SET__A, 0x000D),
+
+	END_OF_TABLE
+};
+
+u8 DRXD_InitEQA2[] = {
+	WRBLOCK(EQ_REG_OT_QNT_THRES0__A, 4),
+	0x1E, 0x00,		/* EQ_REG_OT_QNT_THRES0__A        */
+	0x1F, 0x00,		/* EQ_REG_OT_QNT_THRES1__A        */
+	0x06, 0x00,		/* EQ_REG_OT_CSI_STEP__A          */
+	0x02, 0x00,		/* EQ_REG_OT_CSI_OFFSET__A        */
+
+	WR16(EQ_REG_TD_REQ_SMB_CNT__A, 0x0200),
+	WR16(EQ_REG_IS_CLIP_EXP__A, 0x001F),
+	WR16(EQ_REG_SN_OFFSET__A, (u16) (-7)),
+	WR16(EQ_REG_RC_SEL_CAR__A, 0x0002),
+	WR16(EQ_REG_COMM_EXEC__A, 0x0001),
+	END_OF_TABLE
+};
+
+u8 DRXD_InitEQB1[] = {
+	WR16(B_EQ_REG_COMM_EXEC__A, 0x0001),
+	END_OF_TABLE
+};
+
+u8 DRXD_ResetECRAM[] = {
+	/* Reset packet sync bytes in EC_VD ram */
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000),
+
+	/* Reset packet sync bytes in EC_RS ram */
+	WR16(EC_RS_EC_RAM__A, 0x0000),
+	WR16(EC_RS_EC_RAM__A + 204, 0x0000),
+	END_OF_TABLE
+};
+
+u8 DRXD_InitECA2[] = {
+	WRBLOCK(EC_SB_REG_CSI_HI__A, 6),
+	0x1F, 0x00,		/* EC_SB_REG_CSI_HI__A            */
+	0x1E, 0x00,		/* EC_SB_REG_CSI_LO__A            */
+	0x01, 0x00,		/* EC_SB_REG_SMB_TGL__A           */
+	0x7F, 0x00,		/* EC_SB_REG_SNR_HI__A            */
+	0x7F, 0x00,		/* EC_SB_REG_SNR_MID__A           */
+	0x7F, 0x00,		/* EC_SB_REG_SNR_LO__A            */
+
+	WRBLOCK(EC_RS_REG_REQ_PCK_CNT__A, 2),
+	0x00, 0x10,		/* EC_RS_REG_REQ_PCK_CNT__A       */
+	DATA16(EC_RS_REG_VAL_PCK),	/* EC_RS_REG_VAL__A               */
+
+	WRBLOCK(EC_OC_REG_TMD_TOP_MODE__A, 5),
+	0x03, 0x00,		/* EC_OC_REG_TMD_TOP_MODE__A      */
+	0xF4, 0x01,		/* EC_OC_REG_TMD_TOP_CNT__A       */
+	0xC0, 0x03,		/* EC_OC_REG_TMD_HIL_MAR__A       */
+	0x40, 0x00,		/* EC_OC_REG_TMD_LOL_MAR__A       */
+	0x03, 0x00,		/* EC_OC_REG_TMD_CUR_CNT__A       */
+
+	WRBLOCK(EC_OC_REG_AVR_ASH_CNT__A, 2),
+	0x06, 0x00,		/* EC_OC_REG_AVR_ASH_CNT__A       */
+	0x02, 0x00,		/* EC_OC_REG_AVR_BSH_CNT__A       */
+
+	WRBLOCK(EC_OC_REG_RCN_MODE__A, 7),
+	0x07, 0x00,		/* EC_OC_REG_RCN_MODE__A          */
+	0x00, 0x00,		/* EC_OC_REG_RCN_CRA_LOP__A       */
+	0xc0, 0x00,		/* EC_OC_REG_RCN_CRA_HIP__A       */
+	0x00, 0x10,		/* EC_OC_REG_RCN_CST_LOP__A       */
+	0x00, 0x00,		/* EC_OC_REG_RCN_CST_HIP__A       */
+	0xFF, 0x01,		/* EC_OC_REG_RCN_SET_LVL__A       */
+	0x0D, 0x00,		/* EC_OC_REG_RCN_GAI_LVL__A       */
+
+	WRBLOCK(EC_OC_REG_RCN_CLP_LOP__A, 2),
+	0x00, 0x00,		/* EC_OC_REG_RCN_CLP_LOP__A       */
+	0xC0, 0x00,		/* EC_OC_REG_RCN_CLP_HIP__A       */
+
+	WR16(EC_SB_REG_CSI_OFS__A, 0x0001),
+	WR16(EC_VD_REG_FORCE__A, 0x0002),
+	WR16(EC_VD_REG_REQ_SMB_CNT__A, 0x0001),
+	WR16(EC_VD_REG_RLK_ENA__A, 0x0001),
+	WR16(EC_OD_REG_SYNC__A, 0x0664),
+	WR16(EC_OC_REG_OC_MON_SIO__A, 0x0000),
+	WR16(EC_OC_REG_SNC_ISC_LVL__A, 0x0D0C),
+	/* Output zero on monitorbus pads, power saving */
+	WR16(EC_OC_REG_OCR_MON_UOS__A,
+	     (EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_VAL_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_CLK_ENABLE)),
+	WR16(EC_OC_REG_OCR_MON_WRI__A,
+	     EC_OC_REG_OCR_MON_WRI_INIT),
+
+/*   CHK_ERROR(ResetECRAM(demod)); */
+	/* Reset packet sync bytes in EC_VD ram */
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000),
+
+	/* Reset packet sync bytes in EC_RS ram */
+	WR16(EC_RS_EC_RAM__A, 0x0000),
+	WR16(EC_RS_EC_RAM__A + 204, 0x0000),
+
+	WR16(EC_SB_REG_COMM_EXEC__A, 0x0001),
+	WR16(EC_VD_REG_COMM_EXEC__A, 0x0001),
+	WR16(EC_OD_REG_COMM_EXEC__A, 0x0001),
+	WR16(EC_RS_REG_COMM_EXEC__A, 0x0001),
+	END_OF_TABLE
+};
+
+u8 DRXD_InitECB1[] = {
+	WR16(B_EC_SB_REG_CSI_OFS0__A, 0x0001),
+	WR16(B_EC_SB_REG_CSI_OFS1__A, 0x0001),
+	WR16(B_EC_SB_REG_CSI_OFS2__A, 0x0001),
+	WR16(B_EC_SB_REG_CSI_LO__A, 0x000c),
+	WR16(B_EC_SB_REG_CSI_HI__A, 0x0018),
+	WR16(B_EC_SB_REG_SNR_HI__A, 0x007f),
+	WR16(B_EC_SB_REG_SNR_MID__A, 0x007f),
+	WR16(B_EC_SB_REG_SNR_LO__A, 0x007f),
+
+	WR16(B_EC_OC_REG_DTO_CLKMODE__A, 0x0002),
+	WR16(B_EC_OC_REG_DTO_PER__A, 0x0006),
+	WR16(B_EC_OC_REG_DTO_BUR__A, 0x0001),
+	WR16(B_EC_OC_REG_RCR_CLKMODE__A, 0x0000),
+	WR16(B_EC_OC_REG_RCN_GAI_LVL__A, 0x000D),
+	WR16(B_EC_OC_REG_OC_MPG_SIO__A, 0x0000),
+
+	/* Needed because shadow registers do not have correct default value */
+	WR16(B_EC_OC_REG_RCN_CST_LOP__A, 0x1000),
+	WR16(B_EC_OC_REG_RCN_CST_HIP__A, 0x0000),
+	WR16(B_EC_OC_REG_RCN_CRA_LOP__A, 0x0000),
+	WR16(B_EC_OC_REG_RCN_CRA_HIP__A, 0x00C0),
+	WR16(B_EC_OC_REG_RCN_CLP_LOP__A, 0x0000),
+	WR16(B_EC_OC_REG_RCN_CLP_HIP__A, 0x00C0),
+	WR16(B_EC_OC_REG_DTO_INC_LOP__A, 0x0000),
+	WR16(B_EC_OC_REG_DTO_INC_HIP__A, 0x00C0),
+
+	WR16(B_EC_OD_REG_SYNC__A, 0x0664),
+	WR16(B_EC_RS_REG_REQ_PCK_CNT__A, 0x1000),
+
+/*   CHK_ERROR(ResetECRAM(demod)); */
+	/* Reset packet sync bytes in EC_VD ram */
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000),
+
+	/* Reset packet sync bytes in EC_RS ram */
+	WR16(EC_RS_EC_RAM__A, 0x0000),
+	WR16(EC_RS_EC_RAM__A + 204, 0x0000),
+
+	WR16(B_EC_SB_REG_COMM_EXEC__A, 0x0001),
+	WR16(B_EC_VD_REG_COMM_EXEC__A, 0x0001),
+	WR16(B_EC_OD_REG_COMM_EXEC__A, 0x0001),
+	WR16(B_EC_RS_REG_COMM_EXEC__A, 0x0001),
+	END_OF_TABLE
+};
+
+u8 DRXD_ResetECA2[] = {
+
+	WR16(EC_OC_REG_COMM_EXEC__A, 0x0000),
+	WR16(EC_OD_REG_COMM_EXEC__A, 0x0000),
+
+	WRBLOCK(EC_OC_REG_TMD_TOP_MODE__A, 5),
+	0x03, 0x00,		/* EC_OC_REG_TMD_TOP_MODE__A      */
+	0xF4, 0x01,		/* EC_OC_REG_TMD_TOP_CNT__A       */
+	0xC0, 0x03,		/* EC_OC_REG_TMD_HIL_MAR__A       */
+	0x40, 0x00,		/* EC_OC_REG_TMD_LOL_MAR__A       */
+	0x03, 0x00,		/* EC_OC_REG_TMD_CUR_CNT__A       */
+
+	WRBLOCK(EC_OC_REG_AVR_ASH_CNT__A, 2),
+	0x06, 0x00,		/* EC_OC_REG_AVR_ASH_CNT__A       */
+	0x02, 0x00,		/* EC_OC_REG_AVR_BSH_CNT__A       */
+
+	WRBLOCK(EC_OC_REG_RCN_MODE__A, 7),
+	0x07, 0x00,		/* EC_OC_REG_RCN_MODE__A          */
+	0x00, 0x00,		/* EC_OC_REG_RCN_CRA_LOP__A       */
+	0xc0, 0x00,		/* EC_OC_REG_RCN_CRA_HIP__A       */
+	0x00, 0x10,		/* EC_OC_REG_RCN_CST_LOP__A       */
+	0x00, 0x00,		/* EC_OC_REG_RCN_CST_HIP__A       */
+	0xFF, 0x01,		/* EC_OC_REG_RCN_SET_LVL__A       */
+	0x0D, 0x00,		/* EC_OC_REG_RCN_GAI_LVL__A       */
+
+	WRBLOCK(EC_OC_REG_RCN_CLP_LOP__A, 2),
+	0x00, 0x00,		/* EC_OC_REG_RCN_CLP_LOP__A       */
+	0xC0, 0x00,		/* EC_OC_REG_RCN_CLP_HIP__A       */
+
+	WR16(EC_OD_REG_SYNC__A, 0x0664),
+	WR16(EC_OC_REG_OC_MON_SIO__A, 0x0000),
+	WR16(EC_OC_REG_SNC_ISC_LVL__A, 0x0D0C),
+	/* Output zero on monitorbus pads, power saving */
+	WR16(EC_OC_REG_OCR_MON_UOS__A,
+	     (EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_VAL_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_CLK_ENABLE)),
+	WR16(EC_OC_REG_OCR_MON_WRI__A,
+	     EC_OC_REG_OCR_MON_WRI_INIT),
+
+/*   CHK_ERROR(ResetECRAM(demod)); */
+	/* Reset packet sync bytes in EC_VD ram */
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000),
+
+	/* Reset packet sync bytes in EC_RS ram */
+	WR16(EC_RS_EC_RAM__A, 0x0000),
+	WR16(EC_RS_EC_RAM__A + 204, 0x0000),
+
+	WR16(EC_OD_REG_COMM_EXEC__A, 0x0001),
+	END_OF_TABLE
+};
+
+u8 DRXD_InitSC[] = {
+	WR16(SC_COMM_EXEC__A, 0),
+	WR16(SC_COMM_STATE__A, 0),
+
+#ifdef COMPILE_FOR_QT
+	WR16(SC_RA_RAM_BE_OPT_DELAY__A, 0x100),
+#endif
+
+	/* SC is not started, this is done in SetChannels() */
+	END_OF_TABLE
+};
+
+/* Diversity settings */
+
+u8 DRXD_InitDiversityFront[] = {
+	/* Start demod ********* RF in , diversity out **************************** */
+	WR16(B_SC_RA_RAM_CONFIG__A, B_SC_RA_RAM_CONFIG_FR_ENABLE__M |
+	     B_SC_RA_RAM_CONFIG_FREQSCAN__M),
+
+	WR16(B_SC_RA_RAM_LC_ABS_2K__A, 0x7),
+	WR16(B_SC_RA_RAM_LC_ABS_8K__A, 0x7),
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A, IRLEN_COARSE_8K),
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A, 1 << (11 - IRLEN_COARSE_8K)),
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A, 1 << (17 - IRLEN_COARSE_8K)),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A, IRLEN_FINE_8K),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A, 1 << (11 - IRLEN_FINE_8K)),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A, 1 << (17 - IRLEN_FINE_8K)),
+
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A, IRLEN_COARSE_2K),
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A, 1 << (11 - IRLEN_COARSE_2K)),
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A, 1 << (17 - IRLEN_COARSE_2K)),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A, IRLEN_FINE_2K),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A, 1 << (11 - IRLEN_FINE_2K)),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A, 1 << (17 - IRLEN_FINE_2K)),
+
+	WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, 7),
+	WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, 4),
+	WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, 7),
+	WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, 4),
+	WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, 500),
+
+	WR16(B_CC_REG_DIVERSITY__A, 0x0001),
+	WR16(B_EC_OC_REG_OC_MODE_HIP__A, 0x0010),
+	WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_PASS_B_CE |
+	     B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE | B_EQ_REG_RC_SEL_CAR_MEAS_B_CE),
+
+	/*    0x2a ), *//* CE to PASS mux */
+
+	END_OF_TABLE
+};
+
+u8 DRXD_InitDiversityEnd[] = {
+	/* End demod *********** combining RF in and diversity in, MPEG TS out **** */
+	/* disable near/far; switch on timing slave mode */
+	WR16(B_SC_RA_RAM_CONFIG__A, B_SC_RA_RAM_CONFIG_FR_ENABLE__M |
+	     B_SC_RA_RAM_CONFIG_FREQSCAN__M |
+	     B_SC_RA_RAM_CONFIG_DIV_ECHO_ENABLE__M |
+	     B_SC_RA_RAM_CONFIG_SLAVE__M |
+	     B_SC_RA_RAM_CONFIG_DIV_BLANK_ENABLE__M
+/* MV from CtrlDiversity */
+	    ),
+#ifdef DRXDDIV_SRMM_SLAVING
+	WR16(SC_RA_RAM_LC_ABS_2K__A, 0x3c7),
+	WR16(SC_RA_RAM_LC_ABS_8K__A, 0x3c7),
+#else
+	WR16(SC_RA_RAM_LC_ABS_2K__A, 0x7),
+	WR16(SC_RA_RAM_LC_ABS_8K__A, 0x7),
+#endif
+
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A, IRLEN_COARSE_8K),
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A, 1 << (11 - IRLEN_COARSE_8K)),
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A, 1 << (17 - IRLEN_COARSE_8K)),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A, IRLEN_FINE_8K),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A, 1 << (11 - IRLEN_FINE_8K)),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A, 1 << (17 - IRLEN_FINE_8K)),
+
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A, IRLEN_COARSE_2K),
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A, 1 << (11 - IRLEN_COARSE_2K)),
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A, 1 << (17 - IRLEN_COARSE_2K)),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A, IRLEN_FINE_2K),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A, 1 << (11 - IRLEN_FINE_2K)),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A, 1 << (17 - IRLEN_FINE_2K)),
+
+	WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, 7),
+	WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, 4),
+	WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, 7),
+	WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, 4),
+	WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, 500),
+
+	WR16(B_CC_REG_DIVERSITY__A, 0x0001),
+	END_OF_TABLE
+};
+
+u8 DRXD_DisableDiversity[] = {
+	WR16(B_SC_RA_RAM_LC_ABS_2K__A, B_SC_RA_RAM_LC_ABS_2K__PRE),
+	WR16(B_SC_RA_RAM_LC_ABS_8K__A, B_SC_RA_RAM_LC_ABS_8K__PRE),
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A,
+	     B_SC_RA_RAM_IR_COARSE_8K_LENGTH__PRE),
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A,
+	     B_SC_RA_RAM_IR_COARSE_8K_FREQINC__PRE),
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A,
+	     B_SC_RA_RAM_IR_COARSE_8K_KAISINC__PRE),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A,
+	     B_SC_RA_RAM_IR_FINE_8K_LENGTH__PRE),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A,
+	     B_SC_RA_RAM_IR_FINE_8K_FREQINC__PRE),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A,
+	     B_SC_RA_RAM_IR_FINE_8K_KAISINC__PRE),
+
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A,
+	     B_SC_RA_RAM_IR_COARSE_2K_LENGTH__PRE),
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A,
+	     B_SC_RA_RAM_IR_COARSE_2K_FREQINC__PRE),
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A,
+	     B_SC_RA_RAM_IR_COARSE_2K_KAISINC__PRE),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A,
+	     B_SC_RA_RAM_IR_FINE_2K_LENGTH__PRE),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A,
+	     B_SC_RA_RAM_IR_FINE_2K_FREQINC__PRE),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A,
+	     B_SC_RA_RAM_IR_FINE_2K_KAISINC__PRE),
+
+	WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, B_LC_RA_RAM_FILTER_CRMM_A__PRE),
+	WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, B_LC_RA_RAM_FILTER_CRMM_B__PRE),
+	WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, B_LC_RA_RAM_FILTER_SRMM_A__PRE),
+	WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, B_LC_RA_RAM_FILTER_SRMM_B__PRE),
+	WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, B_LC_RA_RAM_FILTER_SYM_SET__PRE),
+
+	WR16(B_CC_REG_DIVERSITY__A, 0x0000),
+	WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_INIT),	/* combining disabled */
+
+	END_OF_TABLE
+};
+
+u8 DRXD_StartDiversityFront[] = {
+	/* Start demod, RF in and diversity out, no combining */
+	WR16(B_FE_CF_REG_IMP_VAL__A, 0x0),
+	WR16(B_FE_AD_REG_FDB_IN__A, 0x0),
+	WR16(B_FE_AD_REG_INVEXT__A, 0x0),
+	WR16(B_EQ_REG_COMM_MB__A, 0x12),	/* EQ to MB out */
+	WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_PASS_B_CE |	/* CE to PASS mux */
+	     B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE | B_EQ_REG_RC_SEL_CAR_MEAS_B_CE),
+
+	WR16(SC_RA_RAM_ECHO_SHIFT_LIM__A, 2),
+
+	END_OF_TABLE
+};
+
+u8 DRXD_StartDiversityEnd[] = {
+	/* End demod, combining RF in and diversity in, MPEG TS out */
+	WR16(B_FE_CF_REG_IMP_VAL__A, 0x0),	/* disable impulse noise cruncher */
+	WR16(B_FE_AD_REG_INVEXT__A, 0x0),	/* clock inversion (for sohard board) */
+	WR16(B_CP_REG_BR_STR_DEL__A, 10),	/* apperently no mb delay matching is best */
+
+	WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_DIV_ON |	/* org = 0x81 combining enabled */
+	     B_EQ_REG_RC_SEL_CAR_MEAS_A_CC |
+	     B_EQ_REG_RC_SEL_CAR_PASS_A_CC | B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC),
+
+	END_OF_TABLE
+};
+
+u8 DRXD_DiversityDelay8MHZ[] = {
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A, 1150 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A, 1100 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A, 1000 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A, 800 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A, 5420 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A, 5200 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A, 4800 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A, 4000 - 50),
+	END_OF_TABLE
+};
+
+u8 DRXD_DiversityDelay6MHZ[] =	/* also used ok for 7 MHz */
+{
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A, 1100 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A, 1000 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A, 900 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A, 600 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A, 5300 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A, 5000 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A, 4500 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A, 3500 - 50),
+	END_OF_TABLE
+};

+ 115 - 0
drivers/media/dvb/frontends/drxd_firm.h

@@ -0,0 +1,115 @@
+/*
+ * drxd_firm.h
+ *
+ * Copyright (C) 2006-2007 Micronas
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef _DRXD_FIRM_H_
+#define _DRXD_FIRM_H_
+
+#include <linux/types.h>
+#include "drxd_map_firm.h"
+
+#define VERSION_MAJOR 1
+#define VERSION_MINOR 4
+#define VERSION_PATCH 23
+
+#define HI_TR_FUNC_ADDR HI_IF_RAM_USR_BEGIN__A
+
+#define DRXD_MAX_RETRIES (1000)
+#define HI_I2C_DELAY     84
+#define HI_I2C_BRIDGE_DELAY   750
+
+#define EQ_TD_TPS_PWR_UNKNOWN          0x00C0	/* Unknown configurations */
+#define EQ_TD_TPS_PWR_QPSK             0x016a
+#define EQ_TD_TPS_PWR_QAM16_ALPHAN     0x0195
+#define EQ_TD_TPS_PWR_QAM16_ALPHA1     0x0195
+#define EQ_TD_TPS_PWR_QAM16_ALPHA2     0x011E
+#define EQ_TD_TPS_PWR_QAM16_ALPHA4     0x01CE
+#define EQ_TD_TPS_PWR_QAM64_ALPHAN     0x019F
+#define EQ_TD_TPS_PWR_QAM64_ALPHA1     0x019F
+#define EQ_TD_TPS_PWR_QAM64_ALPHA2     0x00F8
+#define EQ_TD_TPS_PWR_QAM64_ALPHA4     0x014D
+
+#define DRXD_DEF_AG_PWD_CONSUMER 0x000E
+#define DRXD_DEF_AG_PWD_PRO 0x0000
+#define DRXD_DEF_AG_AGC_SIO 0x0000
+
+#define DRXD_FE_CTRL_MAX 1023
+
+#define DRXD_OSCDEV_DO_SCAN  (16)
+
+#define DRXD_OSCDEV_DONT_SCAN  (0)
+
+#define DRXD_OSCDEV_STEP  (275)
+
+#define DRXD_SCAN_TIMEOUT    (650)
+
+#define DRXD_BANDWIDTH_8MHZ_IN_HZ  (0x8B8249L)
+#define DRXD_BANDWIDTH_7MHZ_IN_HZ  (0x7A1200L)
+#define DRXD_BANDWIDTH_6MHZ_IN_HZ  (0x68A1B6L)
+
+#define IRLEN_COARSE_8K       (10)
+#define IRLEN_FINE_8K         (10)
+#define IRLEN_COARSE_2K       (7)
+#define IRLEN_FINE_2K         (9)
+#define DIFF_INVALID          (511)
+#define DIFF_TARGET           (4)
+#define DIFF_MARGIN           (1)
+
+extern u8 DRXD_InitAtomicRead[];
+extern u8 DRXD_HiI2cPatch_1[];
+extern u8 DRXD_HiI2cPatch_3[];
+
+extern u8 DRXD_InitSC[];
+
+extern u8 DRXD_ResetCEFR[];
+extern u8 DRXD_InitFEA2_1[];
+extern u8 DRXD_InitFEA2_2[];
+extern u8 DRXD_InitCPA2[];
+extern u8 DRXD_InitCEA2[];
+extern u8 DRXD_InitEQA2[];
+extern u8 DRXD_InitECA2[];
+extern u8 DRXD_ResetECA2[];
+extern u8 DRXD_ResetECRAM[];
+
+extern u8 DRXD_A2_microcode[];
+extern u32 DRXD_A2_microcode_length;
+
+extern u8 DRXD_InitFEB1_1[];
+extern u8 DRXD_InitFEB1_2[];
+extern u8 DRXD_InitCPB1[];
+extern u8 DRXD_InitCEB1[];
+extern u8 DRXD_InitEQB1[];
+extern u8 DRXD_InitECB1[];
+
+extern u8 DRXD_InitDiversityFront[];
+extern u8 DRXD_InitDiversityEnd[];
+extern u8 DRXD_DisableDiversity[];
+extern u8 DRXD_StartDiversityFront[];
+extern u8 DRXD_StartDiversityEnd[];
+
+extern u8 DRXD_DiversityDelay8MHZ[];
+extern u8 DRXD_DiversityDelay6MHZ[];
+
+extern u8 DRXD_B1_microcode[];
+extern u32 DRXD_B1_microcode_length;
+
+#endif

+ 3001 - 0
drivers/media/dvb/frontends/drxd_hard.c

@@ -0,0 +1,3001 @@
+/*
+ * drxd_hard.c: DVB-T Demodulator Micronas DRX3975D-A2,DRX397xD-B1
+ *
+ * Copyright (C) 2003-2007 Micronas
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/version.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "drxd.h"
+#include "drxd_firm.h"
+
+#define DRX_FW_FILENAME_A2 "drxd-a2-1.1.fw"
+#define DRX_FW_FILENAME_B1 "drxd-b1-1.1.fw"
+
+#define CHUNK_SIZE 48
+
+#define DRX_I2C_RMW           0x10
+#define DRX_I2C_BROADCAST     0x20
+#define DRX_I2C_CLEARCRC      0x80
+#define DRX_I2C_SINGLE_MASTER 0xC0
+#define DRX_I2C_MODEFLAGS     0xC0
+#define DRX_I2C_FLAGS         0xF0
+
+#ifndef SIZEOF_ARRAY
+#define SIZEOF_ARRAY(array) (sizeof((array))/sizeof((array)[0]))
+#endif
+
+#define DEFAULT_LOCK_TIMEOUT    1100
+
+#define DRX_CHANNEL_AUTO 0
+#define DRX_CHANNEL_HIGH 1
+#define DRX_CHANNEL_LOW  2
+
+#define DRX_LOCK_MPEG  1
+#define DRX_LOCK_FEC   2
+#define DRX_LOCK_DEMOD 4
+
+/****************************************************************************/
+
+enum CSCDState {
+	CSCD_INIT = 0,
+	CSCD_SET,
+	CSCD_SAVED
+};
+
+enum CDrxdState {
+	DRXD_UNINITIALIZED = 0,
+	DRXD_STOPPED,
+	DRXD_STARTED
+};
+
+enum AGC_CTRL_MODE {
+	AGC_CTRL_AUTO = 0,
+	AGC_CTRL_USER,
+	AGC_CTRL_OFF
+};
+
+enum OperationMode {
+	OM_Default,
+	OM_DVBT_Diversity_Front,
+	OM_DVBT_Diversity_End
+};
+
+struct SCfgAgc {
+	enum AGC_CTRL_MODE ctrlMode;
+	u16 outputLevel;	/* range [0, ... , 1023], 1/n of fullscale range */
+	u16 settleLevel;	/* range [0, ... , 1023], 1/n of fullscale range */
+	u16 minOutputLevel;	/* range [0, ... , 1023], 1/n of fullscale range */
+	u16 maxOutputLevel;	/* range [0, ... , 1023], 1/n of fullscale range */
+	u16 speed;		/* range [0, ... , 1023], 1/n of fullscale range */
+
+	u16 R1;
+	u16 R2;
+	u16 R3;
+};
+
+struct SNoiseCal {
+	int cpOpt;
+	u16 cpNexpOfs;
+	u16 tdCal2k;
+	u16 tdCal8k;
+};
+
+enum app_env {
+	APPENV_STATIC = 0,
+	APPENV_PORTABLE = 1,
+	APPENV_MOBILE = 2
+};
+
+enum EIFFilter {
+	IFFILTER_SAW = 0,
+	IFFILTER_DISCRETE = 1
+};
+
+struct drxd_state {
+	struct dvb_frontend frontend;
+	struct dvb_frontend_ops ops;
+	struct dvb_frontend_parameters param;
+
+	const struct firmware *fw;
+	struct device *dev;
+
+	struct i2c_adapter *i2c;
+	void *priv;
+	struct drxd_config config;
+
+	int i2c_access;
+	int init_done;
+	struct mutex mutex;
+
+	u8 chip_adr;
+	u16 hi_cfg_timing_div;
+	u16 hi_cfg_bridge_delay;
+	u16 hi_cfg_wakeup_key;
+	u16 hi_cfg_ctrl;
+
+	u16 intermediate_freq;
+	u16 osc_clock_freq;
+
+	enum CSCDState cscd_state;
+	enum CDrxdState drxd_state;
+
+	u16 sys_clock_freq;
+	s16 osc_clock_deviation;
+	u16 expected_sys_clock_freq;
+
+	u16 insert_rs_byte;
+	u16 enable_parallel;
+
+	int operation_mode;
+
+	struct SCfgAgc if_agc_cfg;
+	struct SCfgAgc rf_agc_cfg;
+
+	struct SNoiseCal noise_cal;
+
+	u32 fe_fs_add_incr;
+	u32 org_fe_fs_add_incr;
+	u16 current_fe_if_incr;
+
+	u16 m_FeAgRegAgPwd;
+	u16 m_FeAgRegAgAgcSio;
+
+	u16 m_EcOcRegOcModeLop;
+	u16 m_EcOcRegSncSncLvl;
+	u8 *m_InitAtomicRead;
+	u8 *m_HiI2cPatch;
+
+	u8 *m_ResetCEFR;
+	u8 *m_InitFE_1;
+	u8 *m_InitFE_2;
+	u8 *m_InitCP;
+	u8 *m_InitCE;
+	u8 *m_InitEQ;
+	u8 *m_InitSC;
+	u8 *m_InitEC;
+	u8 *m_ResetECRAM;
+	u8 *m_InitDiversityFront;
+	u8 *m_InitDiversityEnd;
+	u8 *m_DisableDiversity;
+	u8 *m_StartDiversityFront;
+	u8 *m_StartDiversityEnd;
+
+	u8 *m_DiversityDelay8MHZ;
+	u8 *m_DiversityDelay6MHZ;
+
+	u8 *microcode;
+	u32 microcode_length;
+
+	int type_A;
+	int PGA;
+	int diversity;
+	int tuner_mirrors;
+
+	enum app_env app_env_default;
+	enum app_env app_env_diversity;
+
+};
+
+/****************************************************************************/
+/* I2C **********************************************************************/
+/****************************************************************************/
+
+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 * data, int len)
+{
+	struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len };
+
+	if (i2c_transfer(adap, &msg, 1) != 1)
+		return -1;
+	return 0;
+}
+
+static int i2c_read(struct i2c_adapter *adap,
+		    u8 adr, u8 *msg, int len, u8 *answ, int alen)
+{
+	struct i2c_msg msgs[2] = {
+		{
+			.addr = adr, .flags = 0,
+			.buf = msg, .len = len
+		}, {
+			.addr = adr, .flags = I2C_M_RD,
+			.buf = answ, .len = alen
+		}
+	};
+	if (i2c_transfer(adap, msgs, 2) != 2)
+		return -1;
+	return 0;
+}
+
+inline u32 MulDiv32(u32 a, u32 b, u32 c)
+{
+	u64 tmp64;
+
+	tmp64 = (u64)a * (u64)b;
+	do_div(tmp64, c);
+
+	return (u32) tmp64;
+}
+
+static int Read16(struct drxd_state *state, u32 reg, u16 *data, u8 flags)
+{
+	u8 adr = state->config.demod_address;
+	u8 mm1[4] = { reg & 0xff, (reg >> 16) & 0xff,
+		flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff
+	};
+	u8 mm2[2];
+	if (i2c_read(state->i2c, adr, mm1, 4, mm2, 2) < 0)
+		return -1;
+	if (data)
+		*data = mm2[0] | (mm2[1] << 8);
+	return mm2[0] | (mm2[1] << 8);
+}
+
+static int Read32(struct drxd_state *state, u32 reg, u32 *data, u8 flags)
+{
+	u8 adr = state->config.demod_address;
+	u8 mm1[4] = { reg & 0xff, (reg >> 16) & 0xff,
+		flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff
+	};
+	u8 mm2[4];
+
+	if (i2c_read(state->i2c, adr, mm1, 4, mm2, 4) < 0)
+		return -1;
+	if (data)
+		*data =
+		    mm2[0] | (mm2[1] << 8) | (mm2[2] << 16) | (mm2[3] << 24);
+	return 0;
+}
+
+static int Write16(struct drxd_state *state, u32 reg, u16 data, u8 flags)
+{
+	u8 adr = state->config.demod_address;
+	u8 mm[6] = { reg & 0xff, (reg >> 16) & 0xff,
+		flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff,
+		data & 0xff, (data >> 8) & 0xff
+	};
+
+	if (i2c_write(state->i2c, adr, mm, 6) < 0)
+		return -1;
+	return 0;
+}
+
+static int Write32(struct drxd_state *state, u32 reg, u32 data, u8 flags)
+{
+	u8 adr = state->config.demod_address;
+	u8 mm[8] = { reg & 0xff, (reg >> 16) & 0xff,
+		flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff,
+		data & 0xff, (data >> 8) & 0xff,
+		(data >> 16) & 0xff, (data >> 24) & 0xff
+	};
+
+	if (i2c_write(state->i2c, adr, mm, 8) < 0)
+		return -1;
+	return 0;
+}
+
+static int write_chunk(struct drxd_state *state,
+		       u32 reg, u8 *data, u32 len, u8 flags)
+{
+	u8 adr = state->config.demod_address;
+	u8 mm[CHUNK_SIZE + 4] = { reg & 0xff, (reg >> 16) & 0xff,
+		flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff
+	};
+	int i;
+
+	for (i = 0; i < len; i++)
+		mm[4 + i] = data[i];
+	if (i2c_write(state->i2c, adr, mm, 4 + len) < 0) {
+		printk(KERN_ERR "error in write_chunk\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int WriteBlock(struct drxd_state *state,
+		      u32 Address, u16 BlockSize, u8 *pBlock, u8 Flags)
+{
+	while (BlockSize > 0) {
+		u16 Chunk = BlockSize > CHUNK_SIZE ? CHUNK_SIZE : BlockSize;
+
+		if (write_chunk(state, Address, pBlock, Chunk, Flags) < 0)
+			return -1;
+		pBlock += Chunk;
+		Address += (Chunk >> 1);
+		BlockSize -= Chunk;
+	}
+	return 0;
+}
+
+static int WriteTable(struct drxd_state *state, u8 * pTable)
+{
+	int status = 0;
+
+	if (pTable == NULL)
+		return 0;
+
+	while (!status) {
+		u16 Length;
+		u32 Address = pTable[0] | (pTable[1] << 8) |
+		    (pTable[2] << 16) | (pTable[3] << 24);
+
+		if (Address == 0xFFFFFFFF)
+			break;
+		pTable += sizeof(u32);
+
+		Length = pTable[0] | (pTable[1] << 8);
+		pTable += sizeof(u16);
+		if (!Length)
+			break;
+		status = WriteBlock(state, Address, Length * 2, pTable, 0);
+		pTable += (Length * 2);
+	}
+	return status;
+}
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static int ResetCEFR(struct drxd_state *state)
+{
+	return WriteTable(state, state->m_ResetCEFR);
+}
+
+static int InitCP(struct drxd_state *state)
+{
+	return WriteTable(state, state->m_InitCP);
+}
+
+static int InitCE(struct drxd_state *state)
+{
+	int status;
+	enum app_env AppEnv = state->app_env_default;
+
+	do {
+		status = WriteTable(state, state->m_InitCE);
+		if (status < 0)
+			break;
+
+		if (state->operation_mode == OM_DVBT_Diversity_Front ||
+		    state->operation_mode == OM_DVBT_Diversity_End) {
+			AppEnv = state->app_env_diversity;
+		}
+		if (AppEnv == APPENV_STATIC) {
+			status = Write16(state, CE_REG_TAPSET__A, 0x0000, 0);
+			if (status < 0)
+				break;
+		} else if (AppEnv == APPENV_PORTABLE) {
+			status = Write16(state, CE_REG_TAPSET__A, 0x0001, 0);
+			if (status < 0)
+				break;
+		} else if (AppEnv == APPENV_MOBILE && state->type_A) {
+			status = Write16(state, CE_REG_TAPSET__A, 0x0002, 0);
+			if (status < 0)
+				break;
+		} else if (AppEnv == APPENV_MOBILE && !state->type_A) {
+			status = Write16(state, CE_REG_TAPSET__A, 0x0006, 0);
+			if (status < 0)
+				break;
+		}
+
+		/* start ce */
+		status = Write16(state, B_CE_REG_COMM_EXEC__A, 0x0001, 0);
+		if (status < 0)
+			break;
+	} while (0);
+	return status;
+}
+
+static int StopOC(struct drxd_state *state)
+{
+	int status = 0;
+	u16 ocSyncLvl = 0;
+	u16 ocModeLop = state->m_EcOcRegOcModeLop;
+	u16 dtoIncLop = 0;
+	u16 dtoIncHip = 0;
+
+	do {
+		/* Store output configuration */
+		status = Read16(state, EC_OC_REG_SNC_ISC_LVL__A, &ocSyncLvl, 0);
+		if (status < 0)
+			break;
+		/* CHK_ERROR(Read16(EC_OC_REG_OC_MODE_LOP__A, &ocModeLop)); */
+		state->m_EcOcRegSncSncLvl = ocSyncLvl;
+		/* m_EcOcRegOcModeLop = ocModeLop; */
+
+		/* Flush FIFO (byte-boundary) at fixed rate */
+		status = Read16(state, EC_OC_REG_RCN_MAP_LOP__A, &dtoIncLop, 0);
+		if (status < 0)
+			break;
+		status = Read16(state, EC_OC_REG_RCN_MAP_HIP__A, &dtoIncHip, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_DTO_INC_LOP__A, dtoIncLop, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_DTO_INC_HIP__A, dtoIncHip, 0);
+		if (status < 0)
+			break;
+		ocModeLop &= ~(EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M);
+		ocModeLop |= EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC;
+		status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, ocModeLop, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_HOLD, 0);
+		if (status < 0)
+			break;
+
+		msleep(1);
+		/* Output pins to '0' */
+		status = Write16(state, EC_OC_REG_OCR_MPG_UOS__A, EC_OC_REG_OCR_MPG_UOS__M, 0);
+		if (status < 0)
+			break;
+
+		/* Force the OC out of sync */
+		ocSyncLvl &= ~(EC_OC_REG_SNC_ISC_LVL_OSC__M);
+		status = Write16(state, EC_OC_REG_SNC_ISC_LVL__A, ocSyncLvl, 0);
+		if (status < 0)
+			break;
+		ocModeLop &= ~(EC_OC_REG_OC_MODE_LOP_PAR_ENA__M);
+		ocModeLop |= EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE;
+		ocModeLop |= 0x2;	/* Magically-out-of-sync */
+		status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, ocModeLop, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_COMM_INT_STA__A, 0x0, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_ACTIVE, 0);
+		if (status < 0)
+			break;
+	} while (0);
+
+	return status;
+}
+
+static int StartOC(struct drxd_state *state)
+{
+	int status = 0;
+
+	do {
+		/* Stop OC */
+		status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_HOLD, 0);
+		if (status < 0)
+			break;
+
+		/* Restore output configuration */
+		status = Write16(state, EC_OC_REG_SNC_ISC_LVL__A, state->m_EcOcRegSncSncLvl, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, state->m_EcOcRegOcModeLop, 0);
+		if (status < 0)
+			break;
+
+		/* Output pins active again */
+		status = Write16(state, EC_OC_REG_OCR_MPG_UOS__A, EC_OC_REG_OCR_MPG_UOS_INIT, 0);
+		if (status < 0)
+			break;
+
+		/* Start OC */
+		status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_ACTIVE, 0);
+		if (status < 0)
+			break;
+	} while (0);
+	return status;
+}
+
+static int InitEQ(struct drxd_state *state)
+{
+	return WriteTable(state, state->m_InitEQ);
+}
+
+static int InitEC(struct drxd_state *state)
+{
+	return WriteTable(state, state->m_InitEC);
+}
+
+static int InitSC(struct drxd_state *state)
+{
+	return WriteTable(state, state->m_InitSC);
+}
+
+static int InitAtomicRead(struct drxd_state *state)
+{
+	return WriteTable(state, state->m_InitAtomicRead);
+}
+
+static int CorrectSysClockDeviation(struct drxd_state *state);
+
+static int DRX_GetLockStatus(struct drxd_state *state, u32 * pLockStatus)
+{
+	u16 ScRaRamLock = 0;
+	const u16 mpeg_lock_mask = (SC_RA_RAM_LOCK_MPEG__M |
+				    SC_RA_RAM_LOCK_FEC__M |
+				    SC_RA_RAM_LOCK_DEMOD__M);
+	const u16 fec_lock_mask = (SC_RA_RAM_LOCK_FEC__M |
+				   SC_RA_RAM_LOCK_DEMOD__M);
+	const u16 demod_lock_mask = SC_RA_RAM_LOCK_DEMOD__M;
+
+	int status;
+
+	*pLockStatus = 0;
+
+	status = Read16(state, SC_RA_RAM_LOCK__A, &ScRaRamLock, 0x0000);
+	if (status < 0) {
+		printk(KERN_ERR "Can't read SC_RA_RAM_LOCK__A status = %08x\n", status);
+		return status;
+	}
+
+	if (state->drxd_state != DRXD_STARTED)
+		return 0;
+
+	if ((ScRaRamLock & mpeg_lock_mask) == mpeg_lock_mask) {
+		*pLockStatus |= DRX_LOCK_MPEG;
+		CorrectSysClockDeviation(state);
+	}
+
+	if ((ScRaRamLock & fec_lock_mask) == fec_lock_mask)
+		*pLockStatus |= DRX_LOCK_FEC;
+
+	if ((ScRaRamLock & demod_lock_mask) == demod_lock_mask)
+		*pLockStatus |= DRX_LOCK_DEMOD;
+	return 0;
+}
+
+/****************************************************************************/
+
+static int SetCfgIfAgc(struct drxd_state *state, struct SCfgAgc *cfg)
+{
+	int status;
+
+	if (cfg->outputLevel > DRXD_FE_CTRL_MAX)
+		return -1;
+
+	if (cfg->ctrlMode == AGC_CTRL_USER) {
+		do {
+			u16 FeAgRegPm1AgcWri;
+			u16 FeAgRegAgModeLop;
+
+			status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &FeAgRegAgModeLop, 0);
+			if (status < 0)
+				break;
+			FeAgRegAgModeLop &= (~FE_AG_REG_AG_MODE_LOP_MODE_4__M);
+			FeAgRegAgModeLop |= FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC;
+			status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, FeAgRegAgModeLop, 0);
+			if (status < 0)
+				break;
+
+			FeAgRegPm1AgcWri = (u16) (cfg->outputLevel &
+						  FE_AG_REG_PM1_AGC_WRI__M);
+			status = Write16(state, FE_AG_REG_PM1_AGC_WRI__A, FeAgRegPm1AgcWri, 0);
+			if (status < 0)
+				break;
+		} while (0);
+	} else if (cfg->ctrlMode == AGC_CTRL_AUTO) {
+		if (((cfg->maxOutputLevel) < (cfg->minOutputLevel)) ||
+		    ((cfg->maxOutputLevel) > DRXD_FE_CTRL_MAX) ||
+		    ((cfg->speed) > DRXD_FE_CTRL_MAX) ||
+		    ((cfg->settleLevel) > DRXD_FE_CTRL_MAX)
+		    )
+			return -1;
+		do {
+			u16 FeAgRegAgModeLop;
+			u16 FeAgRegEgcSetLvl;
+			u16 slope, offset;
+
+			/* == Mode == */
+
+			status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &FeAgRegAgModeLop, 0);
+			if (status < 0)
+				break;
+			FeAgRegAgModeLop &= (~FE_AG_REG_AG_MODE_LOP_MODE_4__M);
+			FeAgRegAgModeLop |=
+			    FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC;
+			status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, FeAgRegAgModeLop, 0);
+			if (status < 0)
+				break;
+
+			/* == Settle level == */
+
+			FeAgRegEgcSetLvl = (u16) ((cfg->settleLevel >> 1) &
+						  FE_AG_REG_EGC_SET_LVL__M);
+			status = Write16(state, FE_AG_REG_EGC_SET_LVL__A, FeAgRegEgcSetLvl, 0);
+			if (status < 0)
+				break;
+
+			/* == Min/Max == */
+
+			slope = (u16) ((cfg->maxOutputLevel -
+					cfg->minOutputLevel) / 2);
+			offset = (u16) ((cfg->maxOutputLevel +
+					 cfg->minOutputLevel) / 2 - 511);
+
+			status = Write16(state, FE_AG_REG_GC1_AGC_RIC__A, slope, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, FE_AG_REG_GC1_AGC_OFF__A, offset, 0);
+			if (status < 0)
+				break;
+
+			/* == Speed == */
+			{
+				const u16 maxRur = 8;
+				const u16 slowIncrDecLUT[] = { 3, 4, 4, 5, 6 };
+				const u16 fastIncrDecLUT[] = { 14, 15, 15, 16,
+					17, 18, 18, 19,
+					20, 21, 22, 23,
+					24, 26, 27, 28,
+					29, 31
+				};
+
+				u16 fineSteps = (DRXD_FE_CTRL_MAX + 1) /
+				    (maxRur + 1);
+				u16 fineSpeed = (u16) (cfg->speed -
+						       ((cfg->speed /
+							 fineSteps) *
+							fineSteps));
+				u16 invRurCount = (u16) (cfg->speed /
+							 fineSteps);
+				u16 rurCount;
+				if (invRurCount > maxRur) {
+					rurCount = 0;
+					fineSpeed += fineSteps;
+				} else {
+					rurCount = maxRur - invRurCount;
+				}
+
+				/*
+				   fastInc = default *
+				   (2^(fineSpeed/fineSteps))
+				   => range[default...2*default>
+				   slowInc = default *
+				   (2^(fineSpeed/fineSteps))
+				 */
+				{
+					u16 fastIncrDec =
+					    fastIncrDecLUT[fineSpeed /
+							   ((fineSteps /
+							     (14 + 1)) + 1)];
+					u16 slowIncrDec =
+					    slowIncrDecLUT[fineSpeed /
+							   (fineSteps /
+							    (3 + 1))];
+
+					status = Write16(state, FE_AG_REG_EGC_RUR_CNT__A, rurCount, 0);
+					if (status < 0)
+						break;
+					status = Write16(state, FE_AG_REG_EGC_FAS_INC__A, fastIncrDec, 0);
+					if (status < 0)
+						break;
+					status = Write16(state, FE_AG_REG_EGC_FAS_DEC__A, fastIncrDec, 0);
+					if (status < 0)
+						break;
+					status = Write16(state, FE_AG_REG_EGC_SLO_INC__A, slowIncrDec, 0);
+					if (status < 0)
+						break;
+					status = Write16(state, FE_AG_REG_EGC_SLO_DEC__A, slowIncrDec, 0);
+					if (status < 0)
+						break;
+				}
+			}
+		} while (0);
+
+	} else {
+		/* No OFF mode for IF control */
+		return -1;
+	}
+	return status;
+}
+
+static int SetCfgRfAgc(struct drxd_state *state, struct SCfgAgc *cfg)
+{
+	int status = 0;
+
+	if (cfg->outputLevel > DRXD_FE_CTRL_MAX)
+		return -1;
+
+	if (cfg->ctrlMode == AGC_CTRL_USER) {
+		do {
+			u16 AgModeLop = 0;
+			u16 level = (cfg->outputLevel);
+
+			if (level == DRXD_FE_CTRL_MAX)
+				level++;
+
+			status = Write16(state, FE_AG_REG_PM2_AGC_WRI__A, level, 0x0000);
+			if (status < 0)
+				break;
+
+			/*==== Mode ====*/
+
+			/* Powerdown PD2, WRI source */
+			state->m_FeAgRegAgPwd &= ~(FE_AG_REG_AG_PWD_PWD_PD2__M);
+			state->m_FeAgRegAgPwd |=
+			    FE_AG_REG_AG_PWD_PWD_PD2_DISABLE;
+			status = Write16(state, FE_AG_REG_AG_PWD__A, state->m_FeAgRegAgPwd, 0x0000);
+			if (status < 0)
+				break;
+
+			status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+			AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M |
+					FE_AG_REG_AG_MODE_LOP_MODE_E__M));
+			AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC |
+				      FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC);
+			status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+
+			/* enable AGC2 pin */
+			{
+				u16 FeAgRegAgAgcSio = 0;
+				status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000);
+				if (status < 0)
+					break;
+				FeAgRegAgAgcSio &=
+				    ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M);
+				FeAgRegAgAgcSio |=
+				    FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT;
+				status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000);
+				if (status < 0)
+					break;
+			}
+
+		} while (0);
+	} else if (cfg->ctrlMode == AGC_CTRL_AUTO) {
+		u16 AgModeLop = 0;
+
+		do {
+			u16 level;
+			/* Automatic control */
+			/* Powerup PD2, AGC2 as output, TGC source */
+			(state->m_FeAgRegAgPwd) &=
+			    ~(FE_AG_REG_AG_PWD_PWD_PD2__M);
+			(state->m_FeAgRegAgPwd) |=
+			    FE_AG_REG_AG_PWD_PWD_PD2_DISABLE;
+			status = Write16(state, FE_AG_REG_AG_PWD__A, (state->m_FeAgRegAgPwd), 0x0000);
+			if (status < 0)
+				break;
+
+			status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+			AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M |
+					FE_AG_REG_AG_MODE_LOP_MODE_E__M));
+			AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC |
+				      FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC);
+			status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+			/* Settle level */
+			level = (((cfg->settleLevel) >> 4) &
+				 FE_AG_REG_TGC_SET_LVL__M);
+			status = Write16(state, FE_AG_REG_TGC_SET_LVL__A, level, 0x0000);
+			if (status < 0)
+				break;
+
+			/* Min/max: don't care */
+
+			/* Speed: TODO */
+
+			/* enable AGC2 pin */
+			{
+				u16 FeAgRegAgAgcSio = 0;
+				status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000);
+				if (status < 0)
+					break;
+				FeAgRegAgAgcSio &=
+				    ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M);
+				FeAgRegAgAgcSio |=
+				    FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT;
+				status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000);
+				if (status < 0)
+					break;
+			}
+
+		} while (0);
+	} else {
+		u16 AgModeLop = 0;
+
+		do {
+			/* No RF AGC control */
+			/* Powerdown PD2, AGC2 as output, WRI source */
+			(state->m_FeAgRegAgPwd) &=
+			    ~(FE_AG_REG_AG_PWD_PWD_PD2__M);
+			(state->m_FeAgRegAgPwd) |=
+			    FE_AG_REG_AG_PWD_PWD_PD2_ENABLE;
+			status = Write16(state, FE_AG_REG_AG_PWD__A, (state->m_FeAgRegAgPwd), 0x0000);
+			if (status < 0)
+				break;
+
+			status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+			AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M |
+					FE_AG_REG_AG_MODE_LOP_MODE_E__M));
+			AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC |
+				      FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC);
+			status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+
+			/* set FeAgRegAgAgcSio AGC2 (RF) as input */
+			{
+				u16 FeAgRegAgAgcSio = 0;
+				status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000);
+				if (status < 0)
+					break;
+				FeAgRegAgAgcSio &=
+				    ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M);
+				FeAgRegAgAgcSio |=
+				    FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT;
+				status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000);
+				if (status < 0)
+					break;
+			}
+		} while (0);
+	}
+	return status;
+}
+
+static int ReadIFAgc(struct drxd_state *state, u32 * pValue)
+{
+	int status = 0;
+
+	*pValue = 0;
+	if (state->if_agc_cfg.ctrlMode != AGC_CTRL_OFF) {
+		u16 Value;
+		status = Read16(state, FE_AG_REG_GC1_AGC_DAT__A, &Value, 0);
+		Value &= FE_AG_REG_GC1_AGC_DAT__M;
+		if (status >= 0) {
+			/*           3.3V
+			   |
+			   R1
+			   |
+			   Vin - R3 - * -- Vout
+			   |
+			   R2
+			   |
+			   GND
+			 */
+			u32 R1 = state->if_agc_cfg.R1;
+			u32 R2 = state->if_agc_cfg.R2;
+			u32 R3 = state->if_agc_cfg.R3;
+
+			u32 Vmax = (3300 * R2) / (R1 + R2);
+			u32 Rpar = (R2 * R3) / (R3 + R2);
+			u32 Vmin = (3300 * Rpar) / (R1 + Rpar);
+			u32 Vout = Vmin + ((Vmax - Vmin) * Value) / 1024;
+
+			*pValue = Vout;
+		}
+	}
+	return status;
+}
+
+static int load_firmware(struct drxd_state *state, const char *fw_name)
+{
+	const struct firmware *fw;
+
+	if (request_firmware(&fw, fw_name, state->dev) < 0) {
+		printk(KERN_ERR "drxd: firmware load failure [%s]\n", fw_name);
+		return -EIO;
+	}
+
+	state->microcode = kzalloc(fw->size, GFP_KERNEL);
+	if (state->microcode == NULL) {
+		printk(KERN_ERR "drxd: firmware load failure: nomemory\n");
+		return -ENOMEM;
+	}
+
+	memcpy(state->microcode, fw->data, fw->size);
+	state->microcode_length = fw->size;
+	return 0;
+}
+
+static int DownloadMicrocode(struct drxd_state *state,
+			     const u8 *pMCImage, u32 Length)
+{
+	u8 *pSrc;
+	u16 Flags;
+	u32 Address;
+	u16 nBlocks;
+	u16 BlockSize;
+	u16 BlockCRC;
+	u32 offset = 0;
+	int i, status = 0;
+
+	pSrc = (u8 *) pMCImage;
+	Flags = (pSrc[0] << 8) | pSrc[1];
+	pSrc += sizeof(u16);
+	offset += sizeof(u16);
+	nBlocks = (pSrc[0] << 8) | pSrc[1];
+	pSrc += sizeof(u16);
+	offset += sizeof(u16);
+
+	for (i = 0; i < nBlocks; i++) {
+		Address = (pSrc[0] << 24) | (pSrc[1] << 16) |
+		    (pSrc[2] << 8) | pSrc[3];
+		pSrc += sizeof(u32);
+		offset += sizeof(u32);
+
+		BlockSize = ((pSrc[0] << 8) | pSrc[1]) * sizeof(u16);
+		pSrc += sizeof(u16);
+		offset += sizeof(u16);
+
+		Flags = (pSrc[0] << 8) | pSrc[1];
+		pSrc += sizeof(u16);
+		offset += sizeof(u16);
+
+		BlockCRC = (pSrc[0] << 8) | pSrc[1];
+		pSrc += sizeof(u16);
+		offset += sizeof(u16);
+
+		status = WriteBlock(state, Address, BlockSize,
+				    pSrc, DRX_I2C_CLEARCRC);
+		if (status < 0)
+			break;
+		pSrc += BlockSize;
+		offset += BlockSize;
+	}
+
+	return status;
+}
+
+static int HI_Command(struct drxd_state *state, u16 cmd, u16 * pResult)
+{
+	u32 nrRetries = 0;
+	u16 waitCmd;
+	int status;
+
+	status = Write16(state, HI_RA_RAM_SRV_CMD__A, cmd, 0);
+	if (status < 0)
+		return status;
+
+	do {
+		nrRetries += 1;
+		if (nrRetries > DRXD_MAX_RETRIES) {
+			status = -1;
+			break;
+		};
+		status = Read16(state, HI_RA_RAM_SRV_CMD__A, &waitCmd, 0);
+	} while (waitCmd != 0);
+
+	if (status >= 0)
+		status = Read16(state, HI_RA_RAM_SRV_RES__A, pResult, 0);
+	return status;
+}
+
+static int HI_CfgCommand(struct drxd_state *state)
+{
+	int status = 0;
+
+	mutex_lock(&state->mutex);
+	Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, HI_RA_RAM_SRV_RST_KEY_ACT, 0);
+	Write16(state, HI_RA_RAM_SRV_CFG_DIV__A, state->hi_cfg_timing_div, 0);
+	Write16(state, HI_RA_RAM_SRV_CFG_BDL__A, state->hi_cfg_bridge_delay, 0);
+	Write16(state, HI_RA_RAM_SRV_CFG_WUP__A, state->hi_cfg_wakeup_key, 0);
+	Write16(state, HI_RA_RAM_SRV_CFG_ACT__A, state->hi_cfg_ctrl, 0);
+
+	Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, HI_RA_RAM_SRV_RST_KEY_ACT, 0);
+
+	if ((state->hi_cfg_ctrl & HI_RA_RAM_SRV_CFG_ACT_PWD_EXE) ==
+	    HI_RA_RAM_SRV_CFG_ACT_PWD_EXE)
+		status = Write16(state, HI_RA_RAM_SRV_CMD__A,
+				 HI_RA_RAM_SRV_CMD_CONFIG, 0);
+	else
+		status = HI_Command(state, HI_RA_RAM_SRV_CMD_CONFIG, 0);
+	mutex_unlock(&state->mutex);
+	return status;
+}
+
+static int InitHI(struct drxd_state *state)
+{
+	state->hi_cfg_wakeup_key = (state->chip_adr);
+	/* port/bridge/power down ctrl */
+	state->hi_cfg_ctrl = HI_RA_RAM_SRV_CFG_ACT_SLV0_ON;
+	return HI_CfgCommand(state);
+}
+
+static int HI_ResetCommand(struct drxd_state *state)
+{
+	int status;
+
+	mutex_lock(&state->mutex);
+	status = Write16(state, HI_RA_RAM_SRV_RST_KEY__A,
+			 HI_RA_RAM_SRV_RST_KEY_ACT, 0);
+	if (status == 0)
+		status = HI_Command(state, HI_RA_RAM_SRV_CMD_RESET, 0);
+	mutex_unlock(&state->mutex);
+	msleep(1);
+	return status;
+}
+
+static int DRX_ConfigureI2CBridge(struct drxd_state *state, int bEnableBridge)
+{
+	state->hi_cfg_ctrl &= (~HI_RA_RAM_SRV_CFG_ACT_BRD__M);
+	if (bEnableBridge)
+		state->hi_cfg_ctrl |= HI_RA_RAM_SRV_CFG_ACT_BRD_ON;
+	else
+		state->hi_cfg_ctrl |= HI_RA_RAM_SRV_CFG_ACT_BRD_OFF;
+
+	return HI_CfgCommand(state);
+}
+
+#define HI_TR_WRITE      0x9
+#define HI_TR_READ       0xA
+#define HI_TR_READ_WRITE 0xB
+#define HI_TR_BROADCAST  0x4
+
+#if 0
+static int AtomicReadBlock(struct drxd_state *state,
+			   u32 Addr, u16 DataSize, u8 *pData, u8 Flags)
+{
+	int status;
+	int i = 0;
+
+	/* Parameter check */
+	if ((!pData) || ((DataSize & 1) != 0))
+		return -1;
+
+	mutex_lock(&state->mutex);
+
+	do {
+		/* Instruct HI to read n bytes */
+		/* TODO use proper names forthese egisters */
+		status = Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, (HI_TR_FUNC_ADDR & 0xFFFF), 0);
+		if (status < 0)
+			break;
+		status = Write16(state, HI_RA_RAM_SRV_CFG_DIV__A, (u16) (Addr >> 16), 0);
+		if (status < 0)
+			break;
+		status = Write16(state, HI_RA_RAM_SRV_CFG_BDL__A, (u16) (Addr & 0xFFFF), 0);
+		if (status < 0)
+			break;
+		status = Write16(state, HI_RA_RAM_SRV_CFG_WUP__A, (u16) ((DataSize / 2) - 1), 0);
+		if (status < 0)
+			break;
+		status = Write16(state, HI_RA_RAM_SRV_CFG_ACT__A, HI_TR_READ, 0);
+		if (status < 0)
+			break;
+
+		status = HI_Command(state, HI_RA_RAM_SRV_CMD_EXECUTE, 0);
+		if (status < 0)
+			break;
+
+	} while (0);
+
+	if (status >= 0) {
+		for (i = 0; i < (DataSize / 2); i += 1) {
+			u16 word;
+
+			status = Read16(state, (HI_RA_RAM_USR_BEGIN__A + i),
+					&word, 0);
+			if (status < 0)
+				break;
+			pData[2 * i] = (u8) (word & 0xFF);
+			pData[(2 * i) + 1] = (u8) (word >> 8);
+		}
+	}
+	mutex_unlock(&state->mutex);
+	return status;
+}
+
+static int AtomicReadReg32(struct drxd_state *state,
+			   u32 Addr, u32 *pData, u8 Flags)
+{
+	u8 buf[sizeof(u32)];
+	int status;
+
+	if (!pData)
+		return -1;
+	status = AtomicReadBlock(state, Addr, sizeof(u32), buf, Flags);
+	*pData = (((u32) buf[0]) << 0) +
+	    (((u32) buf[1]) << 8) +
+	    (((u32) buf[2]) << 16) + (((u32) buf[3]) << 24);
+	return status;
+}
+#endif
+
+static int StopAllProcessors(struct drxd_state *state)
+{
+	return Write16(state, HI_COMM_EXEC__A,
+		       SC_COMM_EXEC_CTL_STOP, DRX_I2C_BROADCAST);
+}
+
+static int EnableAndResetMB(struct drxd_state *state)
+{
+	if (state->type_A) {
+		/* disable? monitor bus observe @ EC_OC */
+		Write16(state, EC_OC_REG_OC_MON_SIO__A, 0x0000, 0x0000);
+	}
+
+	/* do inverse broadcast, followed by explicit write to HI */
+	Write16(state, HI_COMM_MB__A, 0x0000, DRX_I2C_BROADCAST);
+	Write16(state, HI_COMM_MB__A, 0x0000, 0x0000);
+	return 0;
+}
+
+static int InitCC(struct drxd_state *state)
+{
+	if (state->osc_clock_freq == 0 ||
+	    state->osc_clock_freq > 20000 ||
+	    (state->osc_clock_freq % 4000) != 0) {
+		printk(KERN_ERR "invalid osc frequency %d\n", state->osc_clock_freq);
+		return -1;
+	}
+
+	Write16(state, CC_REG_OSC_MODE__A, CC_REG_OSC_MODE_M20, 0);
+	Write16(state, CC_REG_PLL_MODE__A, CC_REG_PLL_MODE_BYPASS_PLL |
+		CC_REG_PLL_MODE_PUMP_CUR_12, 0);
+	Write16(state, CC_REG_REF_DIVIDE__A, state->osc_clock_freq / 4000, 0);
+	Write16(state, CC_REG_PWD_MODE__A, CC_REG_PWD_MODE_DOWN_PLL, 0);
+	Write16(state, CC_REG_UPDATE__A, CC_REG_UPDATE_KEY, 0);
+
+	return 0;
+}
+
+static int ResetECOD(struct drxd_state *state)
+{
+	int status = 0;
+
+	if (state->type_A)
+		status = Write16(state, EC_OD_REG_SYNC__A, 0x0664, 0);
+	else
+		status = Write16(state, B_EC_OD_REG_SYNC__A, 0x0664, 0);
+
+	if (!(status < 0))
+		status = WriteTable(state, state->m_ResetECRAM);
+	if (!(status < 0))
+		status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0001, 0);
+	return status;
+}
+
+/* Configure PGA switch */
+
+static int SetCfgPga(struct drxd_state *state, int pgaSwitch)
+{
+	int status;
+	u16 AgModeLop = 0;
+	u16 AgModeHip = 0;
+	do {
+		if (pgaSwitch) {
+			/* PGA on */
+			/* fine gain */
+			status = Read16(state, B_FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+			AgModeLop &= (~(B_FE_AG_REG_AG_MODE_LOP_MODE_C__M));
+			AgModeLop |= B_FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC;
+			status = Write16(state, B_FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+
+			/* coarse gain */
+			status = Read16(state, B_FE_AG_REG_AG_MODE_HIP__A, &AgModeHip, 0x0000);
+			if (status < 0)
+				break;
+			AgModeHip &= (~(B_FE_AG_REG_AG_MODE_HIP_MODE_J__M));
+			AgModeHip |= B_FE_AG_REG_AG_MODE_HIP_MODE_J_DYNAMIC;
+			status = Write16(state, B_FE_AG_REG_AG_MODE_HIP__A, AgModeHip, 0x0000);
+			if (status < 0)
+				break;
+
+			/* enable fine and coarse gain, enable AAF,
+			   no ext resistor */
+			status = Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, B_FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN, 0x0000);
+			if (status < 0)
+				break;
+		} else {
+			/* PGA off, bypass */
+
+			/* fine gain */
+			status = Read16(state, B_FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+			AgModeLop &= (~(B_FE_AG_REG_AG_MODE_LOP_MODE_C__M));
+			AgModeLop |= B_FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC;
+			status = Write16(state, B_FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+
+			/* coarse gain */
+			status = Read16(state, B_FE_AG_REG_AG_MODE_HIP__A, &AgModeHip, 0x0000);
+			if (status < 0)
+				break;
+			AgModeHip &= (~(B_FE_AG_REG_AG_MODE_HIP_MODE_J__M));
+			AgModeHip |= B_FE_AG_REG_AG_MODE_HIP_MODE_J_STATIC;
+			status = Write16(state, B_FE_AG_REG_AG_MODE_HIP__A, AgModeHip, 0x0000);
+			if (status < 0)
+				break;
+
+			/* disable fine and coarse gain, enable AAF,
+			   no ext resistor */
+			status = Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 0x0000);
+			if (status < 0)
+				break;
+		}
+	} while (0);
+	return status;
+}
+
+static int InitFE(struct drxd_state *state)
+{
+	int status;
+
+	do {
+		status = WriteTable(state, state->m_InitFE_1);
+		if (status < 0)
+			break;
+
+		if (state->type_A) {
+			status = Write16(state, FE_AG_REG_AG_PGA_MODE__A,
+					 FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN,
+					 0);
+		} else {
+			if (state->PGA)
+				status = SetCfgPga(state, 0);
+			else
+				status =
+				    Write16(state, B_FE_AG_REG_AG_PGA_MODE__A,
+					    B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN,
+					    0);
+		}
+
+		if (status < 0)
+			break;
+		status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, state->m_FeAgRegAgAgcSio, 0x0000);
+		if (status < 0)
+			break;
+		status = Write16(state, FE_AG_REG_AG_PWD__A, state->m_FeAgRegAgPwd, 0x0000);
+		if (status < 0)
+			break;
+
+		status = WriteTable(state, state->m_InitFE_2);
+		if (status < 0)
+			break;
+
+	} while (0);
+
+	return status;
+}
+
+static int InitFT(struct drxd_state *state)
+{
+	/*
+	   norm OFFSET,  MB says =2 voor 8K en =3 voor 2K waarschijnlijk
+	   SC stuff
+	 */
+	return Write16(state, FT_REG_COMM_EXEC__A, 0x0001, 0x0000);
+}
+
+static int SC_WaitForReady(struct drxd_state *state)
+{
+	u16 curCmd;
+	int i;
+
+	for (i = 0; i < DRXD_MAX_RETRIES; i += 1) {
+		int status = Read16(state, SC_RA_RAM_CMD__A, &curCmd, 0);
+		if (status == 0 || curCmd == 0)
+			return status;
+	}
+	return -1;
+}
+
+static int SC_SendCommand(struct drxd_state *state, u16 cmd)
+{
+	int status = 0;
+	u16 errCode;
+
+	Write16(state, SC_RA_RAM_CMD__A, cmd, 0);
+	SC_WaitForReady(state);
+
+	Read16(state, SC_RA_RAM_CMD_ADDR__A, &errCode, 0);
+
+	if (errCode == 0xFFFF) {
+		printk(KERN_ERR "Command Error\n");
+		status = -1;
+	}
+
+	return status;
+}
+
+static int SC_ProcStartCommand(struct drxd_state *state,
+			       u16 subCmd, u16 param0, u16 param1)
+{
+	int status = 0;
+	u16 scExec;
+
+	mutex_lock(&state->mutex);
+	do {
+		Read16(state, SC_COMM_EXEC__A, &scExec, 0);
+		if (scExec != 1) {
+			status = -1;
+			break;
+		}
+		SC_WaitForReady(state);
+		Write16(state, SC_RA_RAM_CMD_ADDR__A, subCmd, 0);
+		Write16(state, SC_RA_RAM_PARAM1__A, param1, 0);
+		Write16(state, SC_RA_RAM_PARAM0__A, param0, 0);
+
+		SC_SendCommand(state, SC_RA_RAM_CMD_PROC_START);
+	} while (0);
+	mutex_unlock(&state->mutex);
+	return status;
+}
+
+static int SC_SetPrefParamCommand(struct drxd_state *state,
+				  u16 subCmd, u16 param0, u16 param1)
+{
+	int status;
+
+	mutex_lock(&state->mutex);
+	do {
+		status = SC_WaitForReady(state);
+		if (status < 0)
+			break;
+		status = Write16(state, SC_RA_RAM_CMD_ADDR__A, subCmd, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, SC_RA_RAM_PARAM1__A, param1, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, SC_RA_RAM_PARAM0__A, param0, 0);
+		if (status < 0)
+			break;
+
+		status = SC_SendCommand(state, SC_RA_RAM_CMD_SET_PREF_PARAM);
+		if (status < 0)
+			break;
+	} while (0);
+	mutex_unlock(&state->mutex);
+	return status;
+}
+
+#if 0
+static int SC_GetOpParamCommand(struct drxd_state *state, u16 * result)
+{
+	int status = 0;
+
+	mutex_lock(&state->mutex);
+	do {
+		status = SC_WaitForReady(state);
+		if (status < 0)
+			break;
+		status = SC_SendCommand(state, SC_RA_RAM_CMD_GET_OP_PARAM);
+		if (status < 0)
+			break;
+		status = Read16(state, SC_RA_RAM_PARAM0__A, result, 0);
+		if (status < 0)
+			break;
+	} while (0);
+	mutex_unlock(&state->mutex);
+	return status;
+}
+#endif
+
+static int ConfigureMPEGOutput(struct drxd_state *state, int bEnableOutput)
+{
+	int status;
+
+	do {
+		u16 EcOcRegIprInvMpg = 0;
+		u16 EcOcRegOcModeLop = 0;
+		u16 EcOcRegOcModeHip = 0;
+		u16 EcOcRegOcMpgSio = 0;
+
+		/*CHK_ERROR(Read16(state, EC_OC_REG_OC_MODE_LOP__A, &EcOcRegOcModeLop, 0)); */
+
+		if (state->operation_mode == OM_DVBT_Diversity_Front) {
+			if (bEnableOutput) {
+				EcOcRegOcModeHip |=
+				    B_EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR;
+			} else
+				EcOcRegOcMpgSio |= EC_OC_REG_OC_MPG_SIO__M;
+			EcOcRegOcModeLop |=
+			    EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE;
+		} else {
+			EcOcRegOcModeLop = state->m_EcOcRegOcModeLop;
+
+			if (bEnableOutput)
+				EcOcRegOcMpgSio &= (~(EC_OC_REG_OC_MPG_SIO__M));
+			else
+				EcOcRegOcMpgSio |= EC_OC_REG_OC_MPG_SIO__M;
+
+			/* Don't Insert RS Byte */
+			if (state->insert_rs_byte) {
+				EcOcRegOcModeLop &=
+				    (~(EC_OC_REG_OC_MODE_LOP_PAR_ENA__M));
+				EcOcRegOcModeHip &=
+				    (~EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M);
+				EcOcRegOcModeHip |=
+				    EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE;
+			} else {
+				EcOcRegOcModeLop |=
+				    EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE;
+				EcOcRegOcModeHip &=
+				    (~EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M);
+				EcOcRegOcModeHip |=
+				    EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE;
+			}
+
+			/* Mode = Parallel */
+			if (state->enable_parallel)
+				EcOcRegOcModeLop &=
+				    (~(EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M));
+			else
+				EcOcRegOcModeLop |=
+				    EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL;
+		}
+		/* Invert Data */
+		/* EcOcRegIprInvMpg |= 0x00FF; */
+		EcOcRegIprInvMpg &= (~(0x00FF));
+
+		/* Invert Error ( we don't use the pin ) */
+		/*  EcOcRegIprInvMpg |= 0x0100; */
+		EcOcRegIprInvMpg &= (~(0x0100));
+
+		/* Invert Start ( we don't use the pin ) */
+		/* EcOcRegIprInvMpg |= 0x0200; */
+		EcOcRegIprInvMpg &= (~(0x0200));
+
+		/* Invert Valid ( we don't use the pin ) */
+		/* EcOcRegIprInvMpg |= 0x0400; */
+		EcOcRegIprInvMpg &= (~(0x0400));
+
+		/* Invert Clock */
+		/* EcOcRegIprInvMpg |= 0x0800; */
+		EcOcRegIprInvMpg &= (~(0x0800));
+
+		/* EcOcRegOcModeLop =0x05; */
+		status = Write16(state, EC_OC_REG_IPR_INV_MPG__A, EcOcRegIprInvMpg, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, EcOcRegOcModeLop, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_OC_MODE_HIP__A, EcOcRegOcModeHip, 0x0000);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_OC_MPG_SIO__A, EcOcRegOcMpgSio, 0);
+		if (status < 0)
+			break;
+	} while (0);
+	return status;
+}
+
+static int SetDeviceTypeId(struct drxd_state *state)
+{
+	int status = 0;
+	u16 deviceId = 0;
+
+	do {
+		status = Read16(state, CC_REG_JTAGID_L__A, &deviceId, 0);
+		if (status < 0)
+			break;
+		/* TODO: why twice? */
+		status = Read16(state, CC_REG_JTAGID_L__A, &deviceId, 0);
+		if (status < 0)
+			break;
+		printk(KERN_INFO "drxd: deviceId = %04x\n", deviceId);
+
+		state->type_A = 0;
+		state->PGA = 0;
+		state->diversity = 0;
+		if (deviceId == 0) {	/* on A2 only 3975 available */
+			state->type_A = 1;
+			printk(KERN_INFO "DRX3975D-A2\n");
+		} else {
+			deviceId >>= 12;
+			printk(KERN_INFO "DRX397%dD-B1\n", deviceId);
+			switch (deviceId) {
+			case 4:
+				state->diversity = 1;
+			case 3:
+			case 7:
+				state->PGA = 1;
+				break;
+			case 6:
+				state->diversity = 1;
+			case 5:
+			case 8:
+				break;
+			default:
+				status = -1;
+				break;
+			}
+		}
+	} while (0);
+
+	if (status < 0)
+		return status;
+
+	/* Init Table selection */
+	state->m_InitAtomicRead = DRXD_InitAtomicRead;
+	state->m_InitSC = DRXD_InitSC;
+	state->m_ResetECRAM = DRXD_ResetECRAM;
+	if (state->type_A) {
+		state->m_ResetCEFR = DRXD_ResetCEFR;
+		state->m_InitFE_1 = DRXD_InitFEA2_1;
+		state->m_InitFE_2 = DRXD_InitFEA2_2;
+		state->m_InitCP = DRXD_InitCPA2;
+		state->m_InitCE = DRXD_InitCEA2;
+		state->m_InitEQ = DRXD_InitEQA2;
+		state->m_InitEC = DRXD_InitECA2;
+		if (load_firmware(state, DRX_FW_FILENAME_A2))
+			return -EIO;
+	} else {
+		state->m_ResetCEFR = NULL;
+		state->m_InitFE_1 = DRXD_InitFEB1_1;
+		state->m_InitFE_2 = DRXD_InitFEB1_2;
+		state->m_InitCP = DRXD_InitCPB1;
+		state->m_InitCE = DRXD_InitCEB1;
+		state->m_InitEQ = DRXD_InitEQB1;
+		state->m_InitEC = DRXD_InitECB1;
+		if (load_firmware(state, DRX_FW_FILENAME_B1))
+			return -EIO;
+	}
+	if (state->diversity) {
+		state->m_InitDiversityFront = DRXD_InitDiversityFront;
+		state->m_InitDiversityEnd = DRXD_InitDiversityEnd;
+		state->m_DisableDiversity = DRXD_DisableDiversity;
+		state->m_StartDiversityFront = DRXD_StartDiversityFront;
+		state->m_StartDiversityEnd = DRXD_StartDiversityEnd;
+		state->m_DiversityDelay8MHZ = DRXD_DiversityDelay8MHZ;
+		state->m_DiversityDelay6MHZ = DRXD_DiversityDelay6MHZ;
+	} else {
+		state->m_InitDiversityFront = NULL;
+		state->m_InitDiversityEnd = NULL;
+		state->m_DisableDiversity = NULL;
+		state->m_StartDiversityFront = NULL;
+		state->m_StartDiversityEnd = NULL;
+		state->m_DiversityDelay8MHZ = NULL;
+		state->m_DiversityDelay6MHZ = NULL;
+	}
+
+	return status;
+}
+
+static int CorrectSysClockDeviation(struct drxd_state *state)
+{
+	int status;
+	s32 incr = 0;
+	s32 nomincr = 0;
+	u32 bandwidth = 0;
+	u32 sysClockInHz = 0;
+	u32 sysClockFreq = 0;	/* in kHz */
+	s16 oscClockDeviation;
+	s16 Diff;
+
+	do {
+		/* Retrieve bandwidth and incr, sanity check */
+
+		/* These accesses should be AtomicReadReg32, but that
+		   causes trouble (at least for diversity */
+		status = Read32(state, LC_RA_RAM_IFINCR_NOM_L__A, ((u32 *) &nomincr), 0);
+		if (status < 0)
+			break;
+		status = Read32(state, FE_IF_REG_INCR0__A, (u32 *) &incr, 0);
+		if (status < 0)
+			break;
+
+		if (state->type_A) {
+			if ((nomincr - incr < -500) || (nomincr - incr > 500))
+				break;
+		} else {
+			if ((nomincr - incr < -2000) || (nomincr - incr > 2000))
+				break;
+		}
+
+		switch (state->param.u.ofdm.bandwidth) {
+		case BANDWIDTH_8_MHZ:
+			bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ;
+			break;
+		case BANDWIDTH_7_MHZ:
+			bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ;
+			break;
+		case BANDWIDTH_6_MHZ:
+			bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ;
+			break;
+		default:
+			return -1;
+			break;
+		}
+
+		/* Compute new sysclock value
+		   sysClockFreq = (((incr + 2^23)*bandwidth)/2^21)/1000 */
+		incr += (1 << 23);
+		sysClockInHz = MulDiv32(incr, bandwidth, 1 << 21);
+		sysClockFreq = (u32) (sysClockInHz / 1000);
+		/* rounding */
+		if ((sysClockInHz % 1000) > 500)
+			sysClockFreq++;
+
+		/* Compute clock deviation in ppm */
+		oscClockDeviation = (u16) ((((s32) (sysClockFreq) -
+					     (s32)
+					     (state->expected_sys_clock_freq)) *
+					    1000000L) /
+					   (s32)
+					   (state->expected_sys_clock_freq));
+
+		Diff = oscClockDeviation - state->osc_clock_deviation;
+		/*printk(KERN_INFO "sysclockdiff=%d\n", Diff); */
+		if (Diff >= -200 && Diff <= 200) {
+			state->sys_clock_freq = (u16) sysClockFreq;
+			if (oscClockDeviation != state->osc_clock_deviation) {
+				if (state->config.osc_deviation) {
+					state->config.osc_deviation(state->priv,
+								    oscClockDeviation,
+								    1);
+					state->osc_clock_deviation =
+					    oscClockDeviation;
+				}
+			}
+			/* switch OFF SRMM scan in SC */
+			status = Write16(state, SC_RA_RAM_SAMPLE_RATE_COUNT__A, DRXD_OSCDEV_DONT_SCAN, 0);
+			if (status < 0)
+				break;
+			/* overrule FE_IF internal value for
+			   proper re-locking */
+			status = Write16(state, SC_RA_RAM_IF_SAVE__AX, state->current_fe_if_incr, 0);
+			if (status < 0)
+				break;
+			state->cscd_state = CSCD_SAVED;
+		}
+	} while (0);
+
+	return status;
+}
+
+static int DRX_Stop(struct drxd_state *state)
+{
+	int status;
+
+	if (state->drxd_state != DRXD_STARTED)
+		return 0;
+
+	do {
+		if (state->cscd_state != CSCD_SAVED) {
+			u32 lock;
+			status = DRX_GetLockStatus(state, &lock);
+			if (status < 0)
+				break;
+		}
+
+		status = StopOC(state);
+		if (status < 0)
+			break;
+
+		state->drxd_state = DRXD_STOPPED;
+
+		status = ConfigureMPEGOutput(state, 0);
+		if (status < 0)
+			break;
+
+		if (state->type_A) {
+			/* Stop relevant processors off the device */
+			status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0000, 0x0000);
+			if (status < 0)
+				break;
+
+			status = Write16(state, SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+			if (status < 0)
+				break;
+		} else {
+			/* Stop all processors except HI & CC & FE */
+			status = Write16(state, B_SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, B_LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, B_FT_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, B_CP_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, B_CE_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, B_EQ_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0000, 0);
+			if (status < 0)
+				break;
+		}
+
+	} while (0);
+	return status;
+}
+
+int SetOperationMode(struct drxd_state *state, int oMode)
+{
+	int status;
+
+	do {
+		if (state->drxd_state != DRXD_STOPPED) {
+			status = -1;
+			break;
+		}
+
+		if (oMode == state->operation_mode) {
+			status = 0;
+			break;
+		}
+
+		if (oMode != OM_Default && !state->diversity) {
+			status = -1;
+			break;
+		}
+
+		switch (oMode) {
+		case OM_DVBT_Diversity_Front:
+			status = WriteTable(state, state->m_InitDiversityFront);
+			break;
+		case OM_DVBT_Diversity_End:
+			status = WriteTable(state, state->m_InitDiversityEnd);
+			break;
+		case OM_Default:
+			/* We need to check how to
+			   get DRXD out of diversity */
+		default:
+			status = WriteTable(state, state->m_DisableDiversity);
+			break;
+		}
+	} while (0);
+
+	if (!status)
+		state->operation_mode = oMode;
+	return status;
+}
+
+static int StartDiversity(struct drxd_state *state)
+{
+	int status = 0;
+	u16 rcControl;
+
+	do {
+		if (state->operation_mode == OM_DVBT_Diversity_Front) {
+			status = WriteTable(state, state->m_StartDiversityFront);
+			if (status < 0)
+				break;
+		} else if (state->operation_mode == OM_DVBT_Diversity_End) {
+			status = WriteTable(state, state->m_StartDiversityEnd);
+			if (status < 0)
+				break;
+			if (state->param.u.ofdm.bandwidth == BANDWIDTH_8_MHZ) {
+				status = WriteTable(state, state->m_DiversityDelay8MHZ);
+				if (status < 0)
+					break;
+			} else {
+				status = WriteTable(state, state->m_DiversityDelay6MHZ);
+				if (status < 0)
+					break;
+			}
+
+			status = Read16(state, B_EQ_REG_RC_SEL_CAR__A, &rcControl, 0);
+			if (status < 0)
+				break;
+			rcControl &= ~(B_EQ_REG_RC_SEL_CAR_FFTMODE__M);
+			rcControl |= B_EQ_REG_RC_SEL_CAR_DIV_ON |
+			    /*  combining enabled */
+			    B_EQ_REG_RC_SEL_CAR_MEAS_A_CC |
+			    B_EQ_REG_RC_SEL_CAR_PASS_A_CC |
+			    B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC;
+			status = Write16(state, B_EQ_REG_RC_SEL_CAR__A, rcControl, 0);
+			if (status < 0)
+				break;
+		}
+	} while (0);
+	return status;
+}
+
+static int SetFrequencyShift(struct drxd_state *state,
+			     u32 offsetFreq, int channelMirrored)
+{
+	int negativeShift = (state->tuner_mirrors == channelMirrored);
+
+	/* Handle all mirroring
+	 *
+	 * Note: ADC mirroring (aliasing) is implictly handled by limiting
+	 * feFsRegAddInc to 28 bits below
+	 * (if the result before masking is more than 28 bits, this means
+	 *  that the ADC is mirroring.
+	 * The masking is in fact the aliasing of the ADC)
+	 *
+	 */
+
+	/* Compute register value, unsigned computation */
+	state->fe_fs_add_incr = MulDiv32(state->intermediate_freq +
+					 offsetFreq,
+					 1 << 28, state->sys_clock_freq);
+	/* Remove integer part */
+	state->fe_fs_add_incr &= 0x0FFFFFFFL;
+	if (negativeShift)
+		state->fe_fs_add_incr = ((1 << 28) - state->fe_fs_add_incr);
+
+	/* Save the frequency shift without tunerOffset compensation
+	   for CtrlGetChannel. */
+	state->org_fe_fs_add_incr = MulDiv32(state->intermediate_freq,
+					     1 << 28, state->sys_clock_freq);
+	/* Remove integer part */
+	state->org_fe_fs_add_incr &= 0x0FFFFFFFL;
+	if (negativeShift)
+		state->org_fe_fs_add_incr = ((1L << 28) -
+					     state->org_fe_fs_add_incr);
+
+	return Write32(state, FE_FS_REG_ADD_INC_LOP__A,
+		       state->fe_fs_add_incr, 0);
+}
+
+static int SetCfgNoiseCalibration(struct drxd_state *state,
+				  struct SNoiseCal *noiseCal)
+{
+	u16 beOptEna;
+	int status = 0;
+
+	do {
+		status = Read16(state, SC_RA_RAM_BE_OPT_ENA__A, &beOptEna, 0);
+		if (status < 0)
+			break;
+		if (noiseCal->cpOpt) {
+			beOptEna |= (1 << SC_RA_RAM_BE_OPT_ENA_CP_OPT);
+		} else {
+			beOptEna &= ~(1 << SC_RA_RAM_BE_OPT_ENA_CP_OPT);
+			status = Write16(state, CP_REG_AC_NEXP_OFFS__A, noiseCal->cpNexpOfs, 0);
+			if (status < 0)
+				break;
+		}
+		status = Write16(state, SC_RA_RAM_BE_OPT_ENA__A, beOptEna, 0);
+		if (status < 0)
+			break;
+
+		if (!state->type_A) {
+			status = Write16(state, B_SC_RA_RAM_CO_TD_CAL_2K__A, noiseCal->tdCal2k, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, B_SC_RA_RAM_CO_TD_CAL_8K__A, noiseCal->tdCal8k, 0);
+			if (status < 0)
+				break;
+		}
+	} while (0);
+
+	return status;
+}
+
+static int DRX_Start(struct drxd_state *state, s32 off)
+{
+	struct dvb_ofdm_parameters *p = &state->param.u.ofdm;
+	int status;
+
+	u16 transmissionParams = 0;
+	u16 operationMode = 0;
+	u16 qpskTdTpsPwr = 0;
+	u16 qam16TdTpsPwr = 0;
+	u16 qam64TdTpsPwr = 0;
+	u32 feIfIncr = 0;
+	u32 bandwidth = 0;
+	int mirrorFreqSpect;
+
+	u16 qpskSnCeGain = 0;
+	u16 qam16SnCeGain = 0;
+	u16 qam64SnCeGain = 0;
+	u16 qpskIsGainMan = 0;
+	u16 qam16IsGainMan = 0;
+	u16 qam64IsGainMan = 0;
+	u16 qpskIsGainExp = 0;
+	u16 qam16IsGainExp = 0;
+	u16 qam64IsGainExp = 0;
+	u16 bandwidthParam = 0;
+
+	if (off < 0)
+		off = (off - 500) / 1000;
+	else
+		off = (off + 500) / 1000;
+
+	do {
+		if (state->drxd_state != DRXD_STOPPED)
+			return -1;
+		status = ResetECOD(state);
+		if (status < 0)
+			break;
+		if (state->type_A) {
+			status = InitSC(state);
+			if (status < 0)
+				break;
+		} else {
+			status = InitFT(state);
+			if (status < 0)
+				break;
+			status = InitCP(state);
+			if (status < 0)
+				break;
+			status = InitCE(state);
+			if (status < 0)
+				break;
+			status = InitEQ(state);
+			if (status < 0)
+				break;
+			status = InitSC(state);
+			if (status < 0)
+				break;
+		}
+
+		/* Restore current IF & RF AGC settings */
+
+		status = SetCfgIfAgc(state, &state->if_agc_cfg);
+		if (status < 0)
+			break;
+		status = SetCfgRfAgc(state, &state->rf_agc_cfg);
+		if (status < 0)
+			break;
+
+		mirrorFreqSpect = (state->param.inversion == INVERSION_ON);
+
+		switch (p->transmission_mode) {
+		default:	/* Not set, detect it automatically */
+			operationMode |= SC_RA_RAM_OP_AUTO_MODE__M;
+			/* fall through , try first guess DRX_FFTMODE_8K */
+		case TRANSMISSION_MODE_8K:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_MODE_8K;
+			if (state->type_A) {
+				status = Write16(state, EC_SB_REG_TR_MODE__A, EC_SB_REG_TR_MODE_8K, 0x0000);
+				if (status < 0)
+					break;
+				qpskSnCeGain = 99;
+				qam16SnCeGain = 83;
+				qam64SnCeGain = 67;
+			}
+			break;
+		case TRANSMISSION_MODE_2K:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_MODE_2K;
+			if (state->type_A) {
+				status = Write16(state, EC_SB_REG_TR_MODE__A, EC_SB_REG_TR_MODE_2K, 0x0000);
+				if (status < 0)
+					break;
+				qpskSnCeGain = 97;
+				qam16SnCeGain = 71;
+				qam64SnCeGain = 65;
+			}
+			break;
+		}
+
+		switch (p->guard_interval) {
+		case GUARD_INTERVAL_1_4:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_4;
+			break;
+		case GUARD_INTERVAL_1_8:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_8;
+			break;
+		case GUARD_INTERVAL_1_16:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_16;
+			break;
+		case GUARD_INTERVAL_1_32:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_32;
+			break;
+		default:	/* Not set, detect it automatically */
+			operationMode |= SC_RA_RAM_OP_AUTO_GUARD__M;
+			/* try first guess 1/4 */
+			transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_4;
+			break;
+		}
+
+		switch (p->hierarchy_information) {
+		case HIERARCHY_1:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A1;
+			if (state->type_A) {
+				status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0001, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_ALPHA__A, 0x0001, 0x0000);
+				if (status < 0)
+					break;
+
+				qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN;
+				qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA1;
+				qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA1;
+
+				qpskIsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE;
+				qam16IsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE;
+				qam64IsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE;
+
+				qpskIsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE;
+				qam16IsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE;
+				qam64IsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE;
+			}
+			break;
+
+		case HIERARCHY_2:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A2;
+			if (state->type_A) {
+				status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0002, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_ALPHA__A, 0x0002, 0x0000);
+				if (status < 0)
+					break;
+
+				qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN;
+				qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA2;
+				qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA2;
+
+				qpskIsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE;
+				qam16IsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE;
+				qam64IsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE;
+
+				qpskIsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE;
+				qam16IsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE;
+				qam64IsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE;
+			}
+			break;
+		case HIERARCHY_4:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A4;
+			if (state->type_A) {
+				status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0003, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_ALPHA__A, 0x0003, 0x0000);
+				if (status < 0)
+					break;
+
+				qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN;
+				qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA4;
+				qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA4;
+
+				qpskIsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE;
+				qam16IsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE;
+				qam64IsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE;
+
+				qpskIsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE;
+				qam16IsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE;
+				qam64IsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE;
+			}
+			break;
+		case HIERARCHY_AUTO:
+		default:
+			/* Not set, detect it automatically, start with none */
+			operationMode |= SC_RA_RAM_OP_AUTO_HIER__M;
+			transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_NO;
+			if (state->type_A) {
+				status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0000, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_ALPHA__A, 0x0000, 0x0000);
+				if (status < 0)
+					break;
+
+				qpskTdTpsPwr = EQ_TD_TPS_PWR_QPSK;
+				qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHAN;
+				qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHAN;
+
+				qpskIsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE;
+				qam16IsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE;
+				qam64IsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE;
+
+				qpskIsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE;
+				qam16IsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE;
+				qam64IsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE;
+			}
+			break;
+		}
+		status = status;
+		if (status < 0)
+			break;
+
+		switch (p->constellation) {
+		default:
+			operationMode |= SC_RA_RAM_OP_AUTO_CONST__M;
+			/* fall through , try first guess
+			   DRX_CONSTELLATION_QAM64 */
+		case QAM_64:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QAM64;
+			if (state->type_A) {
+				status = Write16(state, EQ_REG_OT_CONST__A, 0x0002, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_64QAM, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0020, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0008, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0002, 0x0000);
+				if (status < 0)
+					break;
+
+				status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qam64TdTpsPwr, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_SN_CEGAIN__A, qam64SnCeGain, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qam64IsGainMan, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qam64IsGainExp, 0x0000);
+				if (status < 0)
+					break;
+			}
+			break;
+		case QPSK:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QPSK;
+			if (state->type_A) {
+				status = Write16(state, EQ_REG_OT_CONST__A, 0x0000, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_QPSK, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0010, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0000, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0000, 0x0000);
+				if (status < 0)
+					break;
+
+				status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qpskTdTpsPwr, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_SN_CEGAIN__A, qpskSnCeGain, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qpskIsGainMan, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qpskIsGainExp, 0x0000);
+				if (status < 0)
+					break;
+			}
+			break;
+
+		case QAM_16:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QAM16;
+			if (state->type_A) {
+				status = Write16(state, EQ_REG_OT_CONST__A, 0x0001, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_16QAM, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0010, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0004, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0000, 0x0000);
+				if (status < 0)
+					break;
+
+				status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qam16TdTpsPwr, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_SN_CEGAIN__A, qam16SnCeGain, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qam16IsGainMan, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qam16IsGainExp, 0x0000);
+				if (status < 0)
+					break;
+			}
+			break;
+
+		}
+		status = status;
+		if (status < 0)
+			break;
+
+		switch (DRX_CHANNEL_HIGH) {
+		default:
+		case DRX_CHANNEL_AUTO:
+		case DRX_CHANNEL_LOW:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_PRIO_LO;
+			status = Write16(state, EC_SB_REG_PRIOR__A, EC_SB_REG_PRIOR_LO, 0x0000);
+			if (status < 0)
+				break;
+			break;
+		case DRX_CHANNEL_HIGH:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_PRIO_HI;
+			status = Write16(state, EC_SB_REG_PRIOR__A, EC_SB_REG_PRIOR_HI, 0x0000);
+			if (status < 0)
+				break;
+			break;
+
+		}
+
+		switch (p->code_rate_HP) {
+		case FEC_1_2:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_1_2;
+			if (state->type_A) {
+				status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C1_2, 0x0000);
+				if (status < 0)
+					break;
+			}
+			break;
+		default:
+			operationMode |= SC_RA_RAM_OP_AUTO_RATE__M;
+		case FEC_2_3:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_2_3;
+			if (state->type_A) {
+				status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C2_3, 0x0000);
+				if (status < 0)
+					break;
+			}
+			break;
+		case FEC_3_4:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_3_4;
+			if (state->type_A) {
+				status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C3_4, 0x0000);
+				if (status < 0)
+					break;
+			}
+			break;
+		case FEC_5_6:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_5_6;
+			if (state->type_A) {
+				status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C5_6, 0x0000);
+				if (status < 0)
+					break;
+			}
+			break;
+		case FEC_7_8:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_7_8;
+			if (state->type_A) {
+				status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C7_8, 0x0000);
+				if (status < 0)
+					break;
+			}
+			break;
+		}
+		status = status;
+		if (status < 0)
+			break;
+
+		/* First determine real bandwidth (Hz) */
+		/* Also set delay for impulse noise cruncher (only A2) */
+		/* Also set parameters for EC_OC fix, note
+		   EC_OC_REG_TMD_HIL_MAR is changed
+		   by SC for fix for some 8K,1/8 guard but is restored by
+		   InitEC and ResetEC
+		   functions */
+		switch (p->bandwidth) {
+		case BANDWIDTH_AUTO:
+		case BANDWIDTH_8_MHZ:
+			/* (64/7)*(8/8)*1000000 */
+			bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ;
+
+			bandwidthParam = 0;
+			status = Write16(state,
+					 FE_AG_REG_IND_DEL__A, 50, 0x0000);
+			break;
+		case BANDWIDTH_7_MHZ:
+			/* (64/7)*(7/8)*1000000 */
+			bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ;
+			bandwidthParam = 0x4807;	/*binary:0100 1000 0000 0111 */
+			status = Write16(state,
+					 FE_AG_REG_IND_DEL__A, 59, 0x0000);
+			break;
+		case BANDWIDTH_6_MHZ:
+			/* (64/7)*(6/8)*1000000 */
+			bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ;
+			bandwidthParam = 0x0F07;	/*binary: 0000 1111 0000 0111 */
+			status = Write16(state,
+					 FE_AG_REG_IND_DEL__A, 71, 0x0000);
+			break;
+		default:
+			status = -EINVAL;
+		}
+		if (status < 0)
+			break;
+
+		status = Write16(state, SC_RA_RAM_BAND__A, bandwidthParam, 0x0000);
+		if (status < 0)
+			break;
+
+		{
+			u16 sc_config;
+			status = Read16(state, SC_RA_RAM_CONFIG__A, &sc_config, 0);
+			if (status < 0)
+				break;
+
+			/* enable SLAVE mode in 2k 1/32 to
+			   prevent timing change glitches */
+			if ((p->transmission_mode == TRANSMISSION_MODE_2K) &&
+			    (p->guard_interval == GUARD_INTERVAL_1_32)) {
+				/* enable slave */
+				sc_config |= SC_RA_RAM_CONFIG_SLAVE__M;
+			} else {
+				/* disable slave */
+				sc_config &= ~SC_RA_RAM_CONFIG_SLAVE__M;
+			}
+			status = Write16(state, SC_RA_RAM_CONFIG__A, sc_config, 0);
+			if (status < 0)
+				break;
+		}
+
+		status = SetCfgNoiseCalibration(state, &state->noise_cal);
+		if (status < 0)
+			break;
+
+		if (state->cscd_state == CSCD_INIT) {
+			/* switch on SRMM scan in SC */
+			status = Write16(state, SC_RA_RAM_SAMPLE_RATE_COUNT__A, DRXD_OSCDEV_DO_SCAN, 0x0000);
+			if (status < 0)
+				break;
+/*            CHK_ERROR(Write16(SC_RA_RAM_SAMPLE_RATE_STEP__A, DRXD_OSCDEV_STEP, 0x0000));*/
+			state->cscd_state = CSCD_SET;
+		}
+
+		/* Now compute FE_IF_REG_INCR */
+		/*((( SysFreq/BandWidth)/2)/2) -1) * 2^23) =>
+		   ((SysFreq / BandWidth) * (2^21) ) - (2^23) */
+		feIfIncr = MulDiv32(state->sys_clock_freq * 1000,
+				    (1ULL << 21), bandwidth) - (1 << 23);
+		status = Write16(state, FE_IF_REG_INCR0__A, (u16) (feIfIncr & FE_IF_REG_INCR0__M), 0x0000);
+		if (status < 0)
+			break;
+		status = Write16(state, FE_IF_REG_INCR1__A, (u16) ((feIfIncr >> FE_IF_REG_INCR0__W) & FE_IF_REG_INCR1__M), 0x0000);
+		if (status < 0)
+			break;
+		/* Bandwidth setting done */
+
+		/* Mirror & frequency offset */
+		SetFrequencyShift(state, off, mirrorFreqSpect);
+
+		/* Start SC, write channel settings to SC */
+
+		/* Enable SC after setting all other parameters */
+		status = Write16(state, SC_COMM_STATE__A, 0, 0x0000);
+		if (status < 0)
+			break;
+		status = Write16(state, SC_COMM_EXEC__A, 1, 0x0000);
+		if (status < 0)
+			break;
+
+		/* Write SC parameter registers, operation mode */
+#if 1
+		operationMode = (SC_RA_RAM_OP_AUTO_MODE__M |
+				 SC_RA_RAM_OP_AUTO_GUARD__M |
+				 SC_RA_RAM_OP_AUTO_CONST__M |
+				 SC_RA_RAM_OP_AUTO_HIER__M |
+				 SC_RA_RAM_OP_AUTO_RATE__M);
+#endif
+		status = SC_SetPrefParamCommand(state, 0x0000, transmissionParams, operationMode);
+		if (status < 0)
+			break;
+
+		/* Start correct processes to get in lock */
+		status = SC_ProcStartCommand(state, SC_RA_RAM_PROC_LOCKTRACK, SC_RA_RAM_SW_EVENT_RUN_NMASK__M, SC_RA_RAM_LOCKTRACK_MIN);
+		if (status < 0)
+			break;
+
+		status = StartOC(state);
+		if (status < 0)
+			break;
+
+		if (state->operation_mode != OM_Default) {
+			status = StartDiversity(state);
+			if (status < 0)
+				break;
+		}
+
+		state->drxd_state = DRXD_STARTED;
+	} while (0);
+
+	return status;
+}
+
+static int CDRXD(struct drxd_state *state, u32 IntermediateFrequency)
+{
+	u32 ulRfAgcOutputLevel = 0xffffffff;
+	u32 ulRfAgcSettleLevel = 528;	/* Optimum value for MT2060 */
+	u32 ulRfAgcMinLevel = 0;	/* Currently unused */
+	u32 ulRfAgcMaxLevel = DRXD_FE_CTRL_MAX;	/* Currently unused */
+	u32 ulRfAgcSpeed = 0;	/* Currently unused */
+	u32 ulRfAgcMode = 0;	/*2;   Off */
+	u32 ulRfAgcR1 = 820;
+	u32 ulRfAgcR2 = 2200;
+	u32 ulRfAgcR3 = 150;
+	u32 ulIfAgcMode = 0;	/* Auto */
+	u32 ulIfAgcOutputLevel = 0xffffffff;
+	u32 ulIfAgcSettleLevel = 0xffffffff;
+	u32 ulIfAgcMinLevel = 0xffffffff;
+	u32 ulIfAgcMaxLevel = 0xffffffff;
+	u32 ulIfAgcSpeed = 0xffffffff;
+	u32 ulIfAgcR1 = 820;
+	u32 ulIfAgcR2 = 2200;
+	u32 ulIfAgcR3 = 150;
+	u32 ulClock = state->config.clock;
+	u32 ulSerialMode = 0;
+	u32 ulEcOcRegOcModeLop = 4;	/* Dynamic DTO source */
+	u32 ulHiI2cDelay = HI_I2C_DELAY;
+	u32 ulHiI2cBridgeDelay = HI_I2C_BRIDGE_DELAY;
+	u32 ulHiI2cPatch = 0;
+	u32 ulEnvironment = APPENV_PORTABLE;
+	u32 ulEnvironmentDiversity = APPENV_MOBILE;
+	u32 ulIFFilter = IFFILTER_SAW;
+
+	state->if_agc_cfg.ctrlMode = AGC_CTRL_AUTO;
+	state->if_agc_cfg.outputLevel = 0;
+	state->if_agc_cfg.settleLevel = 140;
+	state->if_agc_cfg.minOutputLevel = 0;
+	state->if_agc_cfg.maxOutputLevel = 1023;
+	state->if_agc_cfg.speed = 904;
+
+	if (ulIfAgcMode == 1 && ulIfAgcOutputLevel <= DRXD_FE_CTRL_MAX) {
+		state->if_agc_cfg.ctrlMode = AGC_CTRL_USER;
+		state->if_agc_cfg.outputLevel = (u16) (ulIfAgcOutputLevel);
+	}
+
+	if (ulIfAgcMode == 0 &&
+	    ulIfAgcSettleLevel <= DRXD_FE_CTRL_MAX &&
+	    ulIfAgcMinLevel <= DRXD_FE_CTRL_MAX &&
+	    ulIfAgcMaxLevel <= DRXD_FE_CTRL_MAX &&
+	    ulIfAgcSpeed <= DRXD_FE_CTRL_MAX) {
+		state->if_agc_cfg.ctrlMode = AGC_CTRL_AUTO;
+		state->if_agc_cfg.settleLevel = (u16) (ulIfAgcSettleLevel);
+		state->if_agc_cfg.minOutputLevel = (u16) (ulIfAgcMinLevel);
+		state->if_agc_cfg.maxOutputLevel = (u16) (ulIfAgcMaxLevel);
+		state->if_agc_cfg.speed = (u16) (ulIfAgcSpeed);
+	}
+
+	state->if_agc_cfg.R1 = (u16) (ulIfAgcR1);
+	state->if_agc_cfg.R2 = (u16) (ulIfAgcR2);
+	state->if_agc_cfg.R3 = (u16) (ulIfAgcR3);
+
+	state->rf_agc_cfg.R1 = (u16) (ulRfAgcR1);
+	state->rf_agc_cfg.R2 = (u16) (ulRfAgcR2);
+	state->rf_agc_cfg.R3 = (u16) (ulRfAgcR3);
+
+	state->rf_agc_cfg.ctrlMode = AGC_CTRL_AUTO;
+	/* rest of the RFAgcCfg structure currently unused */
+	if (ulRfAgcMode == 1 && ulRfAgcOutputLevel <= DRXD_FE_CTRL_MAX) {
+		state->rf_agc_cfg.ctrlMode = AGC_CTRL_USER;
+		state->rf_agc_cfg.outputLevel = (u16) (ulRfAgcOutputLevel);
+	}
+
+	if (ulRfAgcMode == 0 &&
+	    ulRfAgcSettleLevel <= DRXD_FE_CTRL_MAX &&
+	    ulRfAgcMinLevel <= DRXD_FE_CTRL_MAX &&
+	    ulRfAgcMaxLevel <= DRXD_FE_CTRL_MAX &&
+	    ulRfAgcSpeed <= DRXD_FE_CTRL_MAX) {
+		state->rf_agc_cfg.ctrlMode = AGC_CTRL_AUTO;
+		state->rf_agc_cfg.settleLevel = (u16) (ulRfAgcSettleLevel);
+		state->rf_agc_cfg.minOutputLevel = (u16) (ulRfAgcMinLevel);
+		state->rf_agc_cfg.maxOutputLevel = (u16) (ulRfAgcMaxLevel);
+		state->rf_agc_cfg.speed = (u16) (ulRfAgcSpeed);
+	}
+
+	if (ulRfAgcMode == 2)
+		state->rf_agc_cfg.ctrlMode = AGC_CTRL_OFF;
+
+	if (ulEnvironment <= 2)
+		state->app_env_default = (enum app_env)
+		    (ulEnvironment);
+	if (ulEnvironmentDiversity <= 2)
+		state->app_env_diversity = (enum app_env)
+		    (ulEnvironmentDiversity);
+
+	if (ulIFFilter == IFFILTER_DISCRETE) {
+		/* discrete filter */
+		state->noise_cal.cpOpt = 0;
+		state->noise_cal.cpNexpOfs = 40;
+		state->noise_cal.tdCal2k = -40;
+		state->noise_cal.tdCal8k = -24;
+	} else {
+		/* SAW filter */
+		state->noise_cal.cpOpt = 1;
+		state->noise_cal.cpNexpOfs = 0;
+		state->noise_cal.tdCal2k = -21;
+		state->noise_cal.tdCal8k = -24;
+	}
+	state->m_EcOcRegOcModeLop = (u16) (ulEcOcRegOcModeLop);
+
+	state->chip_adr = (state->config.demod_address << 1) | 1;
+	switch (ulHiI2cPatch) {
+	case 1:
+		state->m_HiI2cPatch = DRXD_HiI2cPatch_1;
+		break;
+	case 3:
+		state->m_HiI2cPatch = DRXD_HiI2cPatch_3;
+		break;
+	default:
+		state->m_HiI2cPatch = NULL;
+	}
+
+	/* modify tuner and clock attributes */
+	state->intermediate_freq = (u16) (IntermediateFrequency / 1000);
+	/* expected system clock frequency in kHz */
+	state->expected_sys_clock_freq = 48000;
+	/* real system clock frequency in kHz */
+	state->sys_clock_freq = 48000;
+	state->osc_clock_freq = (u16) ulClock;
+	state->osc_clock_deviation = 0;
+	state->cscd_state = CSCD_INIT;
+	state->drxd_state = DRXD_UNINITIALIZED;
+
+	state->PGA = 0;
+	state->type_A = 0;
+	state->tuner_mirrors = 0;
+
+	/* modify MPEG output attributes */
+	state->insert_rs_byte = state->config.insert_rs_byte;
+	state->enable_parallel = (ulSerialMode != 1);
+
+	/* Timing div, 250ns/Psys */
+	/* Timing div, = ( delay (nano seconds) * sysclk (kHz) )/ 1000 */
+
+	state->hi_cfg_timing_div = (u16) ((state->sys_clock_freq / 1000) *
+					  ulHiI2cDelay) / 1000;
+	/* Bridge delay, uses oscilator clock */
+	/* Delay = ( delay (nano seconds) * oscclk (kHz) )/ 1000 */
+	state->hi_cfg_bridge_delay = (u16) ((state->osc_clock_freq / 1000) *
+					    ulHiI2cBridgeDelay) / 1000;
+
+	state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_CONSUMER;
+	/* state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_PRO; */
+	state->m_FeAgRegAgAgcSio = DRXD_DEF_AG_AGC_SIO;
+	return 0;
+}
+
+int DRXD_init(struct drxd_state *state, const u8 * fw, u32 fw_size)
+{
+	int status = 0;
+	u32 driverVersion;
+
+	if (state->init_done)
+		return 0;
+
+	CDRXD(state, state->config.IF ? state->config.IF : 36000000);
+
+	do {
+		state->operation_mode = OM_Default;
+
+		status = SetDeviceTypeId(state);
+		if (status < 0)
+			break;
+
+		/* Apply I2c address patch to B1 */
+		if (!state->type_A && state->m_HiI2cPatch != NULL)
+			status = WriteTable(state, state->m_HiI2cPatch);
+			if (status < 0)
+				break;
+
+		if (state->type_A) {
+			/* HI firmware patch for UIO readout,
+			   avoid clearing of result register */
+			status = Write16(state, 0x43012D, 0x047f, 0);
+			if (status < 0)
+				break;
+		}
+
+		status = HI_ResetCommand(state);
+		if (status < 0)
+			break;
+
+		status = StopAllProcessors(state);
+		if (status < 0)
+			break;
+		status = InitCC(state);
+		if (status < 0)
+			break;
+
+		state->osc_clock_deviation = 0;
+
+		if (state->config.osc_deviation)
+			state->osc_clock_deviation =
+			    state->config.osc_deviation(state->priv, 0, 0);
+		{
+			/* Handle clock deviation */
+			s32 devB;
+			s32 devA = (s32) (state->osc_clock_deviation) *
+			    (s32) (state->expected_sys_clock_freq);
+			/* deviation in kHz */
+			s32 deviation = (devA / (1000000L));
+			/* rounding, signed */
+			if (devA > 0)
+				devB = (2);
+			else
+				devB = (-2);
+			if ((devB * (devA % 1000000L) > 1000000L)) {
+				/* add +1 or -1 */
+				deviation += (devB / 2);
+			}
+
+			state->sys_clock_freq =
+			    (u16) ((state->expected_sys_clock_freq) +
+				   deviation);
+		}
+		status = InitHI(state);
+		if (status < 0)
+			break;
+		status = InitAtomicRead(state);
+		if (status < 0)
+			break;
+
+		status = EnableAndResetMB(state);
+		if (status < 0)
+			break;
+		if (state->type_A)
+			status = ResetCEFR(state);
+			if (status < 0)
+				break;
+
+		if (fw) {
+			status = DownloadMicrocode(state, fw, fw_size);
+			if (status < 0)
+				break;
+		} else {
+			status = DownloadMicrocode(state, state->microcode, state->microcode_length);
+			if (status < 0)
+				break;
+		}
+
+		if (state->PGA) {
+			state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_PRO;
+			SetCfgPga(state, 0);	/* PGA = 0 dB */
+		} else {
+			state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_CONSUMER;
+		}
+
+		state->m_FeAgRegAgAgcSio = DRXD_DEF_AG_AGC_SIO;
+
+		status = InitFE(state);
+		if (status < 0)
+			break;
+		status = InitFT(state);
+		if (status < 0)
+			break;
+		status = InitCP(state);
+		if (status < 0)
+			break;
+		status = InitCE(state);
+		if (status < 0)
+			break;
+		status = InitEQ(state);
+		if (status < 0)
+			break;
+		status = InitEC(state);
+		if (status < 0)
+			break;
+		status = InitSC(state);
+		if (status < 0)
+			break;
+
+		status = SetCfgIfAgc(state, &state->if_agc_cfg);
+		if (status < 0)
+			break;
+		status = SetCfgRfAgc(state, &state->rf_agc_cfg);
+		if (status < 0)
+			break;
+
+		state->cscd_state = CSCD_INIT;
+		status = Write16(state, SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+		if (status < 0)
+			break;
+
+		driverVersion = (((VERSION_MAJOR / 10) << 4) +
+				 (VERSION_MAJOR % 10)) << 24;
+		driverVersion += (((VERSION_MINOR / 10) << 4) +
+				  (VERSION_MINOR % 10)) << 16;
+		driverVersion += ((VERSION_PATCH / 1000) << 12) +
+		    ((VERSION_PATCH / 100) << 8) +
+		    ((VERSION_PATCH / 10) << 4) + (VERSION_PATCH % 10);
+
+		status = Write32(state, SC_RA_RAM_DRIVER_VERSION__AX, driverVersion, 0);
+		if (status < 0)
+			break;
+
+		status = StopOC(state);
+		if (status < 0)
+			break;
+
+		state->drxd_state = DRXD_STOPPED;
+		state->init_done = 1;
+		status = 0;
+	} while (0);
+	return status;
+}
+
+int DRXD_status(struct drxd_state *state, u32 * pLockStatus)
+{
+	DRX_GetLockStatus(state, pLockStatus);
+
+	/*if (*pLockStatus&DRX_LOCK_MPEG) */
+	if (*pLockStatus & DRX_LOCK_FEC) {
+		ConfigureMPEGOutput(state, 1);
+		/* Get status again, in case we have MPEG lock now */
+		/*DRX_GetLockStatus(state, pLockStatus); */
+	}
+
+	return 0;
+}
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static int drxd_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+{
+	struct drxd_state *state = fe->demodulator_priv;
+	u32 value;
+	int res;
+
+	res = ReadIFAgc(state, &value);
+	if (res < 0)
+		*strength = 0;
+	else
+		*strength = 0xffff - (value << 4);
+	return 0;
+}
+
+static int drxd_read_status(struct dvb_frontend *fe, fe_status_t * status)
+{
+	struct drxd_state *state = fe->demodulator_priv;
+	u32 lock;
+
+	DRXD_status(state, &lock);
+	*status = 0;
+	/* No MPEG lock in V255 firmware, bug ? */
+#if 1
+	if (lock & DRX_LOCK_MPEG)
+		*status |= FE_HAS_LOCK;
+#else
+	if (lock & DRX_LOCK_FEC)
+		*status |= FE_HAS_LOCK;
+#endif
+	if (lock & DRX_LOCK_FEC)
+		*status |= FE_HAS_VITERBI | FE_HAS_SYNC;
+	if (lock & DRX_LOCK_DEMOD)
+		*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+
+	return 0;
+}
+
+static int drxd_init(struct dvb_frontend *fe)
+{
+	struct drxd_state *state = fe->demodulator_priv;
+	int err = 0;
+
+/*	if (request_firmware(&state->fw, "drxd.fw", state->dev)<0) */
+	return DRXD_init(state, 0, 0);
+
+	err = DRXD_init(state, state->fw->data, state->fw->size);
+	release_firmware(state->fw);
+	return err;
+}
+
+int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
+{
+	struct drxd_state *state = fe->demodulator_priv;
+
+	if (state->config.disable_i2c_gate_ctrl == 1)
+		return 0;
+
+	return DRX_ConfigureI2CBridge(state, onoff);
+}
+EXPORT_SYMBOL(drxd_config_i2c);
+
+static int drxd_get_tune_settings(struct dvb_frontend *fe,
+				  struct dvb_frontend_tune_settings *sets)
+{
+	sets->min_delay_ms = 10000;
+	sets->max_drift = 0;
+	sets->step_size = 0;
+	return 0;
+}
+
+static int drxd_read_ber(struct dvb_frontend *fe, u32 * ber)
+{
+	*ber = 0;
+	return 0;
+}
+
+static int drxd_read_snr(struct dvb_frontend *fe, u16 * snr)
+{
+	*snr = 0;
+	return 0;
+}
+
+static int drxd_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
+{
+	*ucblocks = 0;
+	return 0;
+}
+
+static int drxd_sleep(struct dvb_frontend *fe)
+{
+	struct drxd_state *state = fe->demodulator_priv;
+
+	ConfigureMPEGOutput(state, 0);
+	return 0;
+}
+
+static int drxd_get_frontend(struct dvb_frontend *fe,
+			     struct dvb_frontend_parameters *param)
+{
+	return 0;
+}
+
+static int drxd_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	return drxd_config_i2c(fe, enable);
+}
+
+static int drxd_set_frontend(struct dvb_frontend *fe,
+			     struct dvb_frontend_parameters *param)
+{
+	struct drxd_state *state = fe->demodulator_priv;
+	s32 off = 0;
+
+	state->param = *param;
+	DRX_Stop(state);
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, param);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	/* FIXME: move PLL drivers */
+	if (state->config.pll_set &&
+	    state->config.pll_set(state->priv, param,
+				  state->config.pll_address,
+				  state->config.demoda_address, &off) < 0) {
+		printk(KERN_ERR "Error in pll_set\n");
+		return -1;
+	}
+
+	msleep(200);
+
+	return DRX_Start(state, off);
+}
+
+static void drxd_release(struct dvb_frontend *fe)
+{
+	struct drxd_state *state = fe->demodulator_priv;
+
+	kfree(state);
+}
+
+static struct dvb_frontend_ops drxd_ops = {
+
+	.info = {
+		 .name = "Micronas DRXD DVB-T",
+		 .type = FE_OFDM,
+		 .frequency_min = 47125000,
+		 .frequency_max = 855250000,
+		 .frequency_stepsize = 166667,
+		 .frequency_tolerance = 0,
+		 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
+		 FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
+		 FE_CAN_FEC_AUTO |
+		 FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+		 FE_CAN_QAM_AUTO |
+		 FE_CAN_TRANSMISSION_MODE_AUTO |
+		 FE_CAN_GUARD_INTERVAL_AUTO |
+		 FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS},
+
+	.release = drxd_release,
+	.init = drxd_init,
+	.sleep = drxd_sleep,
+	.i2c_gate_ctrl = drxd_i2c_gate_ctrl,
+
+	.set_frontend = drxd_set_frontend,
+	.get_frontend = drxd_get_frontend,
+	.get_tune_settings = drxd_get_tune_settings,
+
+	.read_status = drxd_read_status,
+	.read_ber = drxd_read_ber,
+	.read_signal_strength = drxd_read_signal_strength,
+	.read_snr = drxd_read_snr,
+	.read_ucblocks = drxd_read_ucblocks,
+};
+
+struct dvb_frontend *drxd_attach(const struct drxd_config *config,
+				 void *priv, struct i2c_adapter *i2c,
+				 struct device *dev)
+{
+	struct drxd_state *state = NULL;
+
+	state = kmalloc(sizeof(struct drxd_state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+	memset(state, 0, sizeof(*state));
+
+	memcpy(&state->ops, &drxd_ops, sizeof(struct dvb_frontend_ops));
+	state->dev = dev;
+	state->config = *config;
+	state->i2c = i2c;
+	state->priv = priv;
+
+	mutex_init(&state->mutex);
+
+	if (Read16(state, 0, 0, 0) < 0)
+		goto error;
+
+	memcpy(&state->frontend.ops, &drxd_ops,
+	       sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	ConfigureMPEGOutput(state, 0);
+	return &state->frontend;
+
+error:
+	printk(KERN_ERR "drxd: not found\n");
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(drxd_attach);
+
+MODULE_DESCRIPTION("DRXD driver");
+MODULE_AUTHOR("Micronas");
+MODULE_LICENSE("GPL");

+ 1013 - 0
drivers/media/dvb/frontends/drxd_map_firm.h

@@ -0,0 +1,1013 @@
+/*
+ * drx3973d_map_firm.h
+ *
+ * Copyright (C) 2006-2007 Micronas
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __DRX3973D_MAP__H__
+#define __DRX3973D_MAP__H__
+
+/*
+ * Note: originally, this file contained 12000+ lines of data
+ * Probably a few lines for every firwmare assembler instruction. However,
+ * only a few defines were actually used. So, removed all uneeded lines.
+ * If ever needed, the other lines can be easily obtained via git history.
+ */
+
+#define HI_COMM_EXEC__A                                              0x400000
+#define HI_COMM_MB__A                                                0x400002
+#define HI_CT_REG_COMM_STATE__A                                      0x410001
+#define HI_RA_RAM_SRV_RES__A                                         0x420031
+#define HI_RA_RAM_SRV_CMD__A                                         0x420032
+#define   HI_RA_RAM_SRV_CMD_RESET                                    0x2
+#define   HI_RA_RAM_SRV_CMD_CONFIG                                   0x3
+#define   HI_RA_RAM_SRV_CMD_EXECUTE                                  0x6
+#define HI_RA_RAM_SRV_RST_KEY__A                                     0x420033
+#define   HI_RA_RAM_SRV_RST_KEY_ACT                                  0x3973
+#define HI_RA_RAM_SRV_CFG_KEY__A                                     0x420033
+#define HI_RA_RAM_SRV_CFG_DIV__A                                     0x420034
+#define HI_RA_RAM_SRV_CFG_BDL__A                                     0x420035
+#define HI_RA_RAM_SRV_CFG_WUP__A                                     0x420036
+#define HI_RA_RAM_SRV_CFG_ACT__A                                     0x420037
+#define     HI_RA_RAM_SRV_CFG_ACT_SLV0_ON                            0x1
+#define   HI_RA_RAM_SRV_CFG_ACT_BRD__M                               0x4
+#define     HI_RA_RAM_SRV_CFG_ACT_BRD_OFF                            0x0
+#define     HI_RA_RAM_SRV_CFG_ACT_BRD_ON                             0x4
+#define     HI_RA_RAM_SRV_CFG_ACT_PWD_EXE                            0x8
+#define HI_RA_RAM_USR_BEGIN__A                                       0x420040
+#define HI_IF_RAM_TRP_BPT0__AX                                       0x430000
+#define HI_IF_RAM_USR_BEGIN__A                                       0x430200
+#define SC_COMM_EXEC__A                                              0x800000
+#define     SC_COMM_EXEC_CTL_STOP                                    0x0
+#define SC_COMM_STATE__A                                             0x800001
+#define SC_RA_RAM_PARAM0__A                                          0x820040
+#define SC_RA_RAM_PARAM1__A                                          0x820041
+#define SC_RA_RAM_CMD_ADDR__A                                        0x820042
+#define SC_RA_RAM_CMD__A                                             0x820043
+#define   SC_RA_RAM_CMD_PROC_START                                   0x1
+#define   SC_RA_RAM_CMD_SET_PREF_PARAM                               0x3
+#define   SC_RA_RAM_CMD_GET_OP_PARAM                                 0x5
+#define   SC_RA_RAM_SW_EVENT_RUN_NMASK__M                            0x1
+#define   SC_RA_RAM_LOCKTRACK_MIN                                    0x1
+#define     SC_RA_RAM_OP_PARAM_MODE_2K                               0x0
+#define     SC_RA_RAM_OP_PARAM_MODE_8K                               0x1
+#define     SC_RA_RAM_OP_PARAM_GUARD_32                              0x0
+#define     SC_RA_RAM_OP_PARAM_GUARD_16                              0x4
+#define     SC_RA_RAM_OP_PARAM_GUARD_8                               0x8
+#define     SC_RA_RAM_OP_PARAM_GUARD_4                               0xC
+#define     SC_RA_RAM_OP_PARAM_CONST_QPSK                            0x0
+#define     SC_RA_RAM_OP_PARAM_CONST_QAM16                           0x10
+#define     SC_RA_RAM_OP_PARAM_CONST_QAM64                           0x20
+#define     SC_RA_RAM_OP_PARAM_HIER_NO                               0x0
+#define     SC_RA_RAM_OP_PARAM_HIER_A1                               0x40
+#define     SC_RA_RAM_OP_PARAM_HIER_A2                               0x80
+#define     SC_RA_RAM_OP_PARAM_HIER_A4                               0xC0
+#define     SC_RA_RAM_OP_PARAM_RATE_1_2                              0x0
+#define     SC_RA_RAM_OP_PARAM_RATE_2_3                              0x200
+#define     SC_RA_RAM_OP_PARAM_RATE_3_4                              0x400
+#define     SC_RA_RAM_OP_PARAM_RATE_5_6                              0x600
+#define     SC_RA_RAM_OP_PARAM_RATE_7_8                              0x800
+#define     SC_RA_RAM_OP_PARAM_PRIO_HI                               0x0
+#define     SC_RA_RAM_OP_PARAM_PRIO_LO                               0x1000
+#define   SC_RA_RAM_OP_AUTO_MODE__M                                  0x1
+#define   SC_RA_RAM_OP_AUTO_GUARD__M                                 0x2
+#define   SC_RA_RAM_OP_AUTO_CONST__M                                 0x4
+#define   SC_RA_RAM_OP_AUTO_HIER__M                                  0x8
+#define   SC_RA_RAM_OP_AUTO_RATE__M                                  0x10
+#define SC_RA_RAM_LOCK__A                                            0x82004B
+#define   SC_RA_RAM_LOCK_DEMOD__M                                    0x1
+#define   SC_RA_RAM_LOCK_FEC__M                                      0x2
+#define   SC_RA_RAM_LOCK_MPEG__M                                     0x4
+#define SC_RA_RAM_BE_OPT_ENA__A                                      0x82004C
+#define   SC_RA_RAM_BE_OPT_ENA_CP_OPT                                0x1
+#define SC_RA_RAM_BE_OPT_DELAY__A                                    0x82004D
+#define SC_RA_RAM_CONFIG__A                                          0x820050
+#define   SC_RA_RAM_CONFIG_FR_ENABLE__M                              0x4
+#define   SC_RA_RAM_CONFIG_FREQSCAN__M                               0x10
+#define   SC_RA_RAM_CONFIG_SLAVE__M                                  0x20
+#define SC_RA_RAM_IF_SAVE__AX                                        0x82008E
+#define SC_RA_RAM_IR_COARSE_2K_LENGTH__A                             0x8200D1
+#define SC_RA_RAM_IR_COARSE_2K_LENGTH__PRE                           0x9
+#define SC_RA_RAM_IR_COARSE_2K_FREQINC__A                            0x8200D2
+#define SC_RA_RAM_IR_COARSE_2K_FREQINC__PRE                          0x4
+#define SC_RA_RAM_IR_COARSE_2K_KAISINC__A                            0x8200D3
+#define SC_RA_RAM_IR_COARSE_2K_KAISINC__PRE                          0x100
+#define SC_RA_RAM_IR_COARSE_8K_LENGTH__A                             0x8200D4
+#define SC_RA_RAM_IR_COARSE_8K_LENGTH__PRE                           0x8
+#define SC_RA_RAM_IR_COARSE_8K_FREQINC__A                            0x8200D5
+#define SC_RA_RAM_IR_COARSE_8K_FREQINC__PRE                          0x8
+#define SC_RA_RAM_IR_COARSE_8K_KAISINC__A                            0x8200D6
+#define SC_RA_RAM_IR_COARSE_8K_KAISINC__PRE                          0x200
+#define SC_RA_RAM_IR_FINE_2K_LENGTH__A                               0x8200D7
+#define SC_RA_RAM_IR_FINE_2K_LENGTH__PRE                             0x9
+#define SC_RA_RAM_IR_FINE_2K_FREQINC__A                              0x8200D8
+#define SC_RA_RAM_IR_FINE_2K_FREQINC__PRE                            0x4
+#define SC_RA_RAM_IR_FINE_2K_KAISINC__A                              0x8200D9
+#define SC_RA_RAM_IR_FINE_2K_KAISINC__PRE                            0x100
+#define SC_RA_RAM_IR_FINE_8K_LENGTH__A                               0x8200DA
+#define SC_RA_RAM_IR_FINE_8K_LENGTH__PRE                             0xB
+#define SC_RA_RAM_IR_FINE_8K_FREQINC__A                              0x8200DB
+#define SC_RA_RAM_IR_FINE_8K_FREQINC__PRE                            0x1
+#define SC_RA_RAM_IR_FINE_8K_KAISINC__A                              0x8200DC
+#define SC_RA_RAM_IR_FINE_8K_KAISINC__PRE                            0x40
+#define SC_RA_RAM_ECHO_SHIFT_LIM__A                                  0x8200DD
+#define SC_RA_RAM_SAMPLE_RATE_COUNT__A                               0x8200E8
+#define SC_RA_RAM_SAMPLE_RATE_STEP__A                                0x8200E9
+#define SC_RA_RAM_BAND__A                                            0x8200EC
+#define SC_RA_RAM_LC_ABS_2K__A                                       0x8200F4
+#define SC_RA_RAM_LC_ABS_2K__PRE                                     0x1F
+#define SC_RA_RAM_LC_ABS_8K__A                                       0x8200F5
+#define SC_RA_RAM_LC_ABS_8K__PRE                                     0x1F
+#define SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE                        0x1D6
+#define SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE                        0x4
+#define SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE                           0x1BB
+#define SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE                           0x5
+#define SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE                          0x1EF
+#define SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE                          0x5
+#define SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE                       0x15E
+#define SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE                       0x5
+#define SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE                       0x11A
+#define SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE                       0x6
+#define SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE                          0x1FB
+#define SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE                          0x5
+#define SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE                       0x12F
+#define SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE                       0x5
+#define SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE                       0x197
+#define SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE                       0x5
+#define SC_RA_RAM_DRIVER_VERSION__AX                                 0x8201FE
+#define   SC_RA_RAM_PROC_LOCKTRACK                                   0x0
+#define FE_COMM_EXEC__A                                              0xC00000
+#define FE_AD_REG_COMM_EXEC__A                                       0xC10000
+#define FE_AD_REG_FDB_IN__A                                          0xC10012
+#define FE_AD_REG_PD__A                                              0xC10013
+#define FE_AD_REG_INVEXT__A                                          0xC10014
+#define FE_AD_REG_CLKNEG__A                                          0xC10015
+#define FE_AG_REG_COMM_EXEC__A                                       0xC20000
+#define FE_AG_REG_AG_MODE_LOP__A                                     0xC20010
+#define   FE_AG_REG_AG_MODE_LOP_MODE_4__M                            0x10
+#define     FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC                      0x0
+#define     FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC                     0x10
+#define   FE_AG_REG_AG_MODE_LOP_MODE_5__M                            0x20
+#define     FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC                      0x0
+#define   FE_AG_REG_AG_MODE_LOP_MODE_C__M                            0x1000
+#define     FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC                      0x0
+#define     FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC                     0x1000
+#define   FE_AG_REG_AG_MODE_LOP_MODE_E__M                            0x4000
+#define     FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC                      0x0
+#define     FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC                     0x4000
+#define FE_AG_REG_AG_MODE_HIP__A                                     0xC20011
+#define FE_AG_REG_AG_PGA_MODE__A                                     0xC20012
+#define   FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN                      0x0
+#define   FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN                      0x1
+#define FE_AG_REG_AG_AGC_SIO__A                                      0xC20013
+#define   FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M                          0x2
+#define     FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT                    0x0
+#define     FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT                     0x2
+#define FE_AG_REG_AG_PWD__A                                          0xC20015
+#define   FE_AG_REG_AG_PWD_PWD_PD2__M                                0x2
+#define     FE_AG_REG_AG_PWD_PWD_PD2_DISABLE                         0x0
+#define     FE_AG_REG_AG_PWD_PWD_PD2_ENABLE                          0x2
+#define FE_AG_REG_DCE_AUR_CNT__A                                     0xC20016
+#define FE_AG_REG_DCE_RUR_CNT__A                                     0xC20017
+#define FE_AG_REG_ACE_AUR_CNT__A                                     0xC2001A
+#define FE_AG_REG_ACE_RUR_CNT__A                                     0xC2001B
+#define FE_AG_REG_CDR_RUR_CNT__A                                     0xC20020
+#define FE_AG_REG_EGC_RUR_CNT__A                                     0xC20024
+#define FE_AG_REG_EGC_SET_LVL__A                                     0xC20025
+#define FE_AG_REG_EGC_SET_LVL__M                                     0x1FF
+#define FE_AG_REG_EGC_FLA_RGN__A                                     0xC20026
+#define FE_AG_REG_EGC_SLO_RGN__A                                     0xC20027
+#define FE_AG_REG_EGC_JMP_PSN__A                                     0xC20028
+#define FE_AG_REG_EGC_FLA_INC__A                                     0xC20029
+#define FE_AG_REG_EGC_FLA_DEC__A                                     0xC2002A
+#define FE_AG_REG_EGC_SLO_INC__A                                     0xC2002B
+#define FE_AG_REG_EGC_SLO_DEC__A                                     0xC2002C
+#define FE_AG_REG_EGC_FAS_INC__A                                     0xC2002D
+#define FE_AG_REG_EGC_FAS_DEC__A                                     0xC2002E
+#define FE_AG_REG_PM1_AGC_WRI__A                                     0xC20030
+#define FE_AG_REG_PM1_AGC_WRI__M                                     0x7FF
+#define FE_AG_REG_GC1_AGC_RIC__A                                     0xC20031
+#define FE_AG_REG_GC1_AGC_OFF__A                                     0xC20032
+#define FE_AG_REG_GC1_AGC_MAX__A                                     0xC20033
+#define FE_AG_REG_GC1_AGC_MIN__A                                     0xC20034
+#define FE_AG_REG_GC1_AGC_DAT__A                                     0xC20035
+#define FE_AG_REG_GC1_AGC_DAT__M                                     0x3FF
+#define FE_AG_REG_PM2_AGC_WRI__A                                     0xC20036
+#define FE_AG_REG_IND_WIN__A                                         0xC2003C
+#define FE_AG_REG_IND_THD_LOL__A                                     0xC2003D
+#define FE_AG_REG_IND_THD_HIL__A                                     0xC2003E
+#define FE_AG_REG_IND_DEL__A                                         0xC2003F
+#define FE_AG_REG_IND_PD1_WRI__A                                     0xC20040
+#define FE_AG_REG_PDA_AUR_CNT__A                                     0xC20041
+#define FE_AG_REG_PDA_RUR_CNT__A                                     0xC20042
+#define FE_AG_REG_PDA_AVE_DAT__A                                     0xC20043
+#define FE_AG_REG_PDC_RUR_CNT__A                                     0xC20044
+#define FE_AG_REG_PDC_SET_LVL__A                                     0xC20045
+#define FE_AG_REG_PDC_FLA_RGN__A                                     0xC20046
+#define FE_AG_REG_PDC_JMP_PSN__A                                     0xC20047
+#define FE_AG_REG_PDC_FLA_STP__A                                     0xC20048
+#define FE_AG_REG_PDC_SLO_STP__A                                     0xC20049
+#define FE_AG_REG_PDC_PD2_WRI__A                                     0xC2004A
+#define FE_AG_REG_PDC_MAP_DAT__A                                     0xC2004B
+#define FE_AG_REG_PDC_MAX__A                                         0xC2004C
+#define FE_AG_REG_TGA_AUR_CNT__A                                     0xC2004D
+#define FE_AG_REG_TGA_RUR_CNT__A                                     0xC2004E
+#define FE_AG_REG_TGA_AVE_DAT__A                                     0xC2004F
+#define FE_AG_REG_TGC_RUR_CNT__A                                     0xC20050
+#define FE_AG_REG_TGC_SET_LVL__A                                     0xC20051
+#define FE_AG_REG_TGC_SET_LVL__M                                     0x3F
+#define FE_AG_REG_TGC_FLA_RGN__A                                     0xC20052
+#define FE_AG_REG_TGC_JMP_PSN__A                                     0xC20053
+#define FE_AG_REG_TGC_FLA_STP__A                                     0xC20054
+#define FE_AG_REG_TGC_SLO_STP__A                                     0xC20055
+#define FE_AG_REG_TGC_MAP_DAT__A                                     0xC20056
+#define FE_AG_REG_FGA_AUR_CNT__A                                     0xC20057
+#define FE_AG_REG_FGA_RUR_CNT__A                                     0xC20058
+#define FE_AG_REG_FGM_WRI__A                                         0xC20061
+#define FE_AG_REG_BGC_FGC_WRI__A                                     0xC20068
+#define FE_AG_REG_BGC_CGC_WRI__A                                     0xC20069
+#define FE_FS_REG_COMM_EXEC__A                                       0xC30000
+#define FE_FS_REG_ADD_INC_LOP__A                                     0xC30010
+#define FE_FD_REG_COMM_EXEC__A                                       0xC40000
+#define FE_FD_REG_SCL__A                                             0xC40010
+#define FE_FD_REG_MAX_LEV__A                                         0xC40011
+#define FE_FD_REG_NR__A                                              0xC40012
+#define FE_FD_REG_MEAS_VAL__A                                        0xC40014
+#define FE_IF_REG_COMM_EXEC__A                                       0xC50000
+#define FE_IF_REG_INCR0__A                                           0xC50010
+#define FE_IF_REG_INCR0__W                                           16
+#define FE_IF_REG_INCR0__M                                           0xFFFF
+#define FE_IF_REG_INCR1__A                                           0xC50011
+#define FE_IF_REG_INCR1__M                                           0xFF
+#define FE_CF_REG_COMM_EXEC__A                                       0xC60000
+#define FE_CF_REG_SCL__A                                             0xC60010
+#define FE_CF_REG_MAX_LEV__A                                         0xC60011
+#define FE_CF_REG_NR__A                                              0xC60012
+#define FE_CF_REG_IMP_VAL__A                                         0xC60013
+#define FE_CF_REG_MEAS_VAL__A                                        0xC60014
+#define FE_CU_REG_COMM_EXEC__A                                       0xC70000
+#define FE_CU_REG_FRM_CNT_RST__A                                     0xC70011
+#define FE_CU_REG_FRM_CNT_STR__A                                     0xC70012
+#define FT_COMM_EXEC__A                                              0x1000000
+#define FT_REG_COMM_EXEC__A                                          0x1010000
+#define CP_COMM_EXEC__A                                              0x1400000
+#define CP_REG_COMM_EXEC__A                                          0x1410000
+#define CP_REG_INTERVAL__A                                           0x1410011
+#define CP_REG_BR_SPL_OFFSET__A                                      0x1410023
+#define CP_REG_BR_STR_DEL__A                                         0x1410024
+#define CP_REG_RT_ANG_INC0__A                                        0x1410030
+#define CP_REG_RT_ANG_INC1__A                                        0x1410031
+#define CP_REG_RT_DETECT_ENA__A                                      0x1410032
+#define CP_REG_RT_DETECT_TRH__A                                      0x1410033
+#define CP_REG_RT_EXP_MARG__A                                        0x141003E
+#define CP_REG_AC_NEXP_OFFS__A                                       0x1410040
+#define CP_REG_AC_AVER_POW__A                                        0x1410041
+#define CP_REG_AC_MAX_POW__A                                         0x1410042
+#define CP_REG_AC_WEIGHT_MAN__A                                      0x1410043
+#define CP_REG_AC_WEIGHT_EXP__A                                      0x1410044
+#define CP_REG_AC_AMP_MODE__A                                        0x1410047
+#define CP_REG_AC_AMP_FIX__A                                         0x1410048
+#define CP_REG_AC_ANG_MODE__A                                        0x141004A
+#define CE_COMM_EXEC__A                                              0x1800000
+#define CE_REG_COMM_EXEC__A                                          0x1810000
+#define CE_REG_TAPSET__A                                             0x1810011
+#define CE_REG_AVG_POW__A                                            0x1810012
+#define CE_REG_MAX_POW__A                                            0x1810013
+#define CE_REG_ATT__A                                                0x1810014
+#define CE_REG_NRED__A                                               0x1810015
+#define CE_REG_NE_ERR_SELECT__A                                      0x1810043
+#define CE_REG_NE_TD_CAL__A                                          0x1810044
+#define CE_REG_NE_MIXAVG__A                                          0x1810046
+#define CE_REG_NE_NUPD_OFS__A                                        0x1810047
+#define CE_REG_PE_NEXP_OFFS__A                                       0x1810050
+#define CE_REG_PE_TIMESHIFT__A                                       0x1810051
+#define CE_REG_TP_A0_TAP_NEW__A                                      0x1810064
+#define CE_REG_TP_A0_TAP_NEW_VALID__A                                0x1810065
+#define CE_REG_TP_A0_MU_LMS_STEP__A                                  0x1810066
+#define CE_REG_TP_A1_TAP_NEW__A                                      0x1810068
+#define CE_REG_TP_A1_TAP_NEW_VALID__A                                0x1810069
+#define CE_REG_TP_A1_MU_LMS_STEP__A                                  0x181006A
+#define CE_REG_TI_NEXP_OFFS__A                                       0x1810070
+#define CE_REG_FI_SHT_INCR__A                                        0x1810090
+#define CE_REG_FI_EXP_NORM__A                                        0x1810091
+#define CE_REG_IR_INPUTSEL__A                                        0x18100A0
+#define CE_REG_IR_STARTPOS__A                                        0x18100A1
+#define CE_REG_IR_NEXP_THRES__A                                      0x18100A2
+#define CE_REG_FR_TREAL00__A                                         0x1820010
+#define CE_REG_FR_TIMAG00__A                                         0x1820011
+#define CE_REG_FR_TREAL01__A                                         0x1820012
+#define CE_REG_FR_TIMAG01__A                                         0x1820013
+#define CE_REG_FR_TREAL02__A                                         0x1820014
+#define CE_REG_FR_TIMAG02__A                                         0x1820015
+#define CE_REG_FR_TREAL03__A                                         0x1820016
+#define CE_REG_FR_TIMAG03__A                                         0x1820017
+#define CE_REG_FR_TREAL04__A                                         0x1820018
+#define CE_REG_FR_TIMAG04__A                                         0x1820019
+#define CE_REG_FR_TREAL05__A                                         0x182001A
+#define CE_REG_FR_TIMAG05__A                                         0x182001B
+#define CE_REG_FR_TREAL06__A                                         0x182001C
+#define CE_REG_FR_TIMAG06__A                                         0x182001D
+#define CE_REG_FR_TREAL07__A                                         0x182001E
+#define CE_REG_FR_TIMAG07__A                                         0x182001F
+#define CE_REG_FR_TREAL08__A                                         0x1820020
+#define CE_REG_FR_TIMAG08__A                                         0x1820021
+#define CE_REG_FR_TREAL09__A                                         0x1820022
+#define CE_REG_FR_TIMAG09__A                                         0x1820023
+#define CE_REG_FR_TREAL10__A                                         0x1820024
+#define CE_REG_FR_TIMAG10__A                                         0x1820025
+#define CE_REG_FR_TREAL11__A                                         0x1820026
+#define CE_REG_FR_TIMAG11__A                                         0x1820027
+#define CE_REG_FR_MID_TAP__A                                         0x1820028
+#define CE_REG_FR_SQS_G00__A                                         0x1820029
+#define CE_REG_FR_SQS_G01__A                                         0x182002A
+#define CE_REG_FR_SQS_G02__A                                         0x182002B
+#define CE_REG_FR_SQS_G03__A                                         0x182002C
+#define CE_REG_FR_SQS_G04__A                                         0x182002D
+#define CE_REG_FR_SQS_G05__A                                         0x182002E
+#define CE_REG_FR_SQS_G06__A                                         0x182002F
+#define CE_REG_FR_SQS_G07__A                                         0x1820030
+#define CE_REG_FR_SQS_G08__A                                         0x1820031
+#define CE_REG_FR_SQS_G09__A                                         0x1820032
+#define CE_REG_FR_SQS_G10__A                                         0x1820033
+#define CE_REG_FR_SQS_G11__A                                         0x1820034
+#define CE_REG_FR_SQS_G12__A                                         0x1820035
+#define CE_REG_FR_RIO_G00__A                                         0x1820036
+#define CE_REG_FR_RIO_G01__A                                         0x1820037
+#define CE_REG_FR_RIO_G02__A                                         0x1820038
+#define CE_REG_FR_RIO_G03__A                                         0x1820039
+#define CE_REG_FR_RIO_G04__A                                         0x182003A
+#define CE_REG_FR_RIO_G05__A                                         0x182003B
+#define CE_REG_FR_RIO_G06__A                                         0x182003C
+#define CE_REG_FR_RIO_G07__A                                         0x182003D
+#define CE_REG_FR_RIO_G08__A                                         0x182003E
+#define CE_REG_FR_RIO_G09__A                                         0x182003F
+#define CE_REG_FR_RIO_G10__A                                         0x1820040
+#define CE_REG_FR_MODE__A                                            0x1820041
+#define CE_REG_FR_SQS_TRH__A                                         0x1820042
+#define CE_REG_FR_RIO_GAIN__A                                        0x1820043
+#define CE_REG_FR_BYPASS__A                                          0x1820044
+#define CE_REG_FR_PM_SET__A                                          0x1820045
+#define CE_REG_FR_ERR_SH__A                                          0x1820046
+#define CE_REG_FR_MAN_SH__A                                          0x1820047
+#define CE_REG_FR_TAP_SH__A                                          0x1820048
+#define EQ_COMM_EXEC__A                                              0x1C00000
+#define EQ_REG_COMM_EXEC__A                                          0x1C10000
+#define EQ_REG_COMM_MB__A                                            0x1C10002
+#define EQ_REG_IS_GAIN_MAN__A                                        0x1C10015
+#define EQ_REG_IS_GAIN_EXP__A                                        0x1C10016
+#define EQ_REG_IS_CLIP_EXP__A                                        0x1C10017
+#define EQ_REG_SN_CEGAIN__A                                          0x1C1002A
+#define EQ_REG_SN_OFFSET__A                                          0x1C1002B
+#define EQ_REG_RC_SEL_CAR__A                                         0x1C10032
+#define   EQ_REG_RC_SEL_CAR_INIT                                     0x0
+#define     EQ_REG_RC_SEL_CAR_DIV_ON                                 0x1
+#define     EQ_REG_RC_SEL_CAR_PASS_A_CC                              0x0
+#define     EQ_REG_RC_SEL_CAR_PASS_B_CE                              0x2
+#define     EQ_REG_RC_SEL_CAR_LOCAL_A_CC                             0x0
+#define     EQ_REG_RC_SEL_CAR_LOCAL_B_CE                             0x8
+#define     EQ_REG_RC_SEL_CAR_MEAS_A_CC                              0x0
+#define     EQ_REG_RC_SEL_CAR_MEAS_B_CE                              0x20
+#define EQ_REG_OT_CONST__A                                           0x1C10046
+#define EQ_REG_OT_ALPHA__A                                           0x1C10047
+#define EQ_REG_OT_QNT_THRES0__A                                      0x1C10048
+#define EQ_REG_OT_QNT_THRES1__A                                      0x1C10049
+#define EQ_REG_OT_CSI_STEP__A                                        0x1C1004A
+#define EQ_REG_OT_CSI_OFFSET__A                                      0x1C1004B
+#define EQ_REG_TD_REQ_SMB_CNT__A                                     0x1C10061
+#define EQ_REG_TD_TPS_PWR_OFS__A                                     0x1C10062
+#define EC_SB_REG_COMM_EXEC__A                                       0x2010000
+#define EC_SB_REG_TR_MODE__A                                         0x2010010
+#define   EC_SB_REG_TR_MODE_8K                                       0x0
+#define   EC_SB_REG_TR_MODE_2K                                       0x1
+#define EC_SB_REG_CONST__A                                           0x2010011
+#define   EC_SB_REG_CONST_QPSK                                       0x0
+#define   EC_SB_REG_CONST_16QAM                                      0x1
+#define   EC_SB_REG_CONST_64QAM                                      0x2
+#define EC_SB_REG_ALPHA__A                                           0x2010012
+#define EC_SB_REG_PRIOR__A                                           0x2010013
+#define   EC_SB_REG_PRIOR_HI                                         0x0
+#define   EC_SB_REG_PRIOR_LO                                         0x1
+#define EC_SB_REG_CSI_HI__A                                          0x2010014
+#define EC_SB_REG_CSI_LO__A                                          0x2010015
+#define EC_SB_REG_SMB_TGL__A                                         0x2010016
+#define EC_SB_REG_SNR_HI__A                                          0x2010017
+#define EC_SB_REG_SNR_MID__A                                         0x2010018
+#define EC_SB_REG_SNR_LO__A                                          0x2010019
+#define EC_SB_REG_SCALE_MSB__A                                       0x201001A
+#define EC_SB_REG_SCALE_BIT2__A                                      0x201001B
+#define EC_SB_REG_SCALE_LSB__A                                       0x201001C
+#define EC_SB_REG_CSI_OFS__A                                         0x201001D
+#define EC_VD_REG_COMM_EXEC__A                                       0x2090000
+#define EC_VD_REG_FORCE__A                                           0x2090010
+#define EC_VD_REG_SET_CODERATE__A                                    0x2090011
+#define   EC_VD_REG_SET_CODERATE_C1_2                                0x0
+#define   EC_VD_REG_SET_CODERATE_C2_3                                0x1
+#define   EC_VD_REG_SET_CODERATE_C3_4                                0x2
+#define   EC_VD_REG_SET_CODERATE_C5_6                                0x3
+#define   EC_VD_REG_SET_CODERATE_C7_8                                0x4
+#define EC_VD_REG_REQ_SMB_CNT__A                                     0x2090012
+#define EC_VD_REG_RLK_ENA__A                                         0x2090014
+#define EC_OD_REG_COMM_EXEC__A                                       0x2110000
+#define EC_OD_REG_SYNC__A                                            0x2110010
+#define EC_OD_DEINT_RAM__A                                           0x2120000
+#define EC_RS_REG_COMM_EXEC__A                                       0x2130000
+#define EC_RS_REG_REQ_PCK_CNT__A                                     0x2130010
+#define EC_RS_REG_VAL__A                                             0x2130011
+#define   EC_RS_REG_VAL_PCK                                          0x1
+#define EC_RS_EC_RAM__A                                              0x2140000
+#define EC_OC_REG_COMM_EXEC__A                                       0x2150000
+#define     EC_OC_REG_COMM_EXEC_CTL_ACTIVE                           0x1
+#define     EC_OC_REG_COMM_EXEC_CTL_HOLD                             0x2
+#define EC_OC_REG_COMM_INT_STA__A                                    0x2150007
+#define EC_OC_REG_OC_MODE_LOP__A                                     0x2150010
+#define   EC_OC_REG_OC_MODE_LOP_PAR_ENA__M                           0x1
+#define     EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE                     0x0
+#define     EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE                    0x1
+#define   EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M                       0x4
+#define     EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC                 0x0
+#define   EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M                       0x80
+#define     EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL                 0x80
+#define EC_OC_REG_OC_MODE_HIP__A                                     0x2150011
+#define     EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR                0x10
+#define   EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M                       0x200
+#define     EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE                0x0
+#define     EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE                 0x200
+#define EC_OC_REG_OC_MPG_SIO__A                                      0x2150012
+#define EC_OC_REG_OC_MPG_SIO__M                                      0xFFF
+#define EC_OC_REG_OC_MON_SIO__A                                      0x2150013
+#define EC_OC_REG_DTO_INC_LOP__A                                     0x2150014
+#define EC_OC_REG_DTO_INC_HIP__A                                     0x2150015
+#define EC_OC_REG_SNC_ISC_LVL__A                                     0x2150016
+#define   EC_OC_REG_SNC_ISC_LVL_OSC__M                               0xF0
+#define EC_OC_REG_TMD_TOP_MODE__A                                    0x215001D
+#define EC_OC_REG_TMD_TOP_CNT__A                                     0x215001E
+#define EC_OC_REG_TMD_HIL_MAR__A                                     0x215001F
+#define EC_OC_REG_TMD_LOL_MAR__A                                     0x2150020
+#define EC_OC_REG_TMD_CUR_CNT__A                                     0x2150021
+#define EC_OC_REG_AVR_ASH_CNT__A                                     0x2150023
+#define EC_OC_REG_AVR_BSH_CNT__A                                     0x2150024
+#define EC_OC_REG_RCN_MODE__A                                        0x2150027
+#define EC_OC_REG_RCN_CRA_LOP__A                                     0x2150028
+#define EC_OC_REG_RCN_CRA_HIP__A                                     0x2150029
+#define EC_OC_REG_RCN_CST_LOP__A                                     0x215002A
+#define EC_OC_REG_RCN_CST_HIP__A                                     0x215002B
+#define EC_OC_REG_RCN_SET_LVL__A                                     0x215002C
+#define EC_OC_REG_RCN_GAI_LVL__A                                     0x215002D
+#define EC_OC_REG_RCN_CLP_LOP__A                                     0x2150032
+#define EC_OC_REG_RCN_CLP_HIP__A                                     0x2150033
+#define EC_OC_REG_RCN_MAP_LOP__A                                     0x2150034
+#define EC_OC_REG_RCN_MAP_HIP__A                                     0x2150035
+#define EC_OC_REG_OCR_MPG_UOS__A                                     0x2150036
+#define EC_OC_REG_OCR_MPG_UOS__M                                     0xFFF
+#define   EC_OC_REG_OCR_MPG_UOS_INIT                                 0x0
+#define EC_OC_REG_OCR_MPG_USR_DAT__A                                 0x2150038
+#define EC_OC_REG_OCR_MON_UOS__A                                     0x2150039
+#define     EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE                       0x1
+#define     EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE                       0x2
+#define     EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE                       0x4
+#define     EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE                       0x8
+#define     EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE                       0x10
+#define     EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE                       0x20
+#define     EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE                       0x40
+#define     EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE                       0x80
+#define     EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE                       0x100
+#define     EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE                       0x200
+#define     EC_OC_REG_OCR_MON_UOS_VAL_ENABLE                         0x400
+#define     EC_OC_REG_OCR_MON_UOS_CLK_ENABLE                         0x800
+#define EC_OC_REG_OCR_MON_WRI__A                                     0x215003A
+#define   EC_OC_REG_OCR_MON_WRI_INIT                                 0x0
+#define EC_OC_REG_IPR_INV_MPG__A                                     0x2150045
+#define CC_REG_OSC_MODE__A                                           0x2410010
+#define   CC_REG_OSC_MODE_M20                                        0x1
+#define CC_REG_PLL_MODE__A                                           0x2410011
+#define     CC_REG_PLL_MODE_BYPASS_PLL                               0x1
+#define     CC_REG_PLL_MODE_PUMP_CUR_12                              0x14
+#define CC_REG_REF_DIVIDE__A                                         0x2410012
+#define CC_REG_PWD_MODE__A                                           0x2410015
+#define   CC_REG_PWD_MODE_DOWN_PLL                                   0x2
+#define CC_REG_UPDATE__A                                             0x2410017
+#define   CC_REG_UPDATE_KEY                                          0x3973
+#define CC_REG_JTAGID_L__A                                           0x2410019
+#define LC_COMM_EXEC__A                                              0x2800000
+#define LC_RA_RAM_IFINCR_NOM_L__A                                    0x282000C
+#define LC_RA_RAM_FILTER_SYM_SET__A                                  0x282001A
+#define LC_RA_RAM_FILTER_SYM_SET__PRE                                0x3E8
+#define LC_RA_RAM_FILTER_CRMM_A__A                                   0x2820060
+#define LC_RA_RAM_FILTER_CRMM_A__PRE                                 0x4
+#define LC_RA_RAM_FILTER_CRMM_B__A                                   0x2820061
+#define LC_RA_RAM_FILTER_CRMM_B__PRE                                 0x1
+#define LC_RA_RAM_FILTER_SRMM_A__A                                   0x2820068
+#define LC_RA_RAM_FILTER_SRMM_A__PRE                                 0x4
+#define LC_RA_RAM_FILTER_SRMM_B__A                                   0x2820069
+#define LC_RA_RAM_FILTER_SRMM_B__PRE                                 0x1
+#define B_HI_COMM_EXEC__A                                            0x400000
+#define B_HI_COMM_MB__A                                              0x400002
+#define B_HI_CT_REG_COMM_STATE__A                                    0x410001
+#define B_HI_RA_RAM_SRV_RES__A                                       0x420031
+#define B_HI_RA_RAM_SRV_CMD__A                                       0x420032
+#define   B_HI_RA_RAM_SRV_CMD_RESET                                  0x2
+#define   B_HI_RA_RAM_SRV_CMD_CONFIG                                 0x3
+#define   B_HI_RA_RAM_SRV_CMD_EXECUTE                                0x6
+#define B_HI_RA_RAM_SRV_RST_KEY__A                                   0x420033
+#define   B_HI_RA_RAM_SRV_RST_KEY_ACT                                0x3973
+#define B_HI_RA_RAM_SRV_CFG_KEY__A                                   0x420033
+#define B_HI_RA_RAM_SRV_CFG_DIV__A                                   0x420034
+#define B_HI_RA_RAM_SRV_CFG_BDL__A                                   0x420035
+#define B_HI_RA_RAM_SRV_CFG_WUP__A                                   0x420036
+#define B_HI_RA_RAM_SRV_CFG_ACT__A                                   0x420037
+#define     B_HI_RA_RAM_SRV_CFG_ACT_SLV0_ON                          0x1
+#define   B_HI_RA_RAM_SRV_CFG_ACT_BRD__M                             0x4
+#define     B_HI_RA_RAM_SRV_CFG_ACT_BRD_OFF                          0x0
+#define     B_HI_RA_RAM_SRV_CFG_ACT_BRD_ON                           0x4
+#define     B_HI_RA_RAM_SRV_CFG_ACT_PWD_EXE                          0x8
+#define B_HI_RA_RAM_USR_BEGIN__A                                     0x420040
+#define B_HI_IF_RAM_TRP_BPT0__AX                                     0x430000
+#define B_HI_IF_RAM_USR_BEGIN__A                                     0x430200
+#define B_SC_COMM_EXEC__A                                            0x800000
+#define     B_SC_COMM_EXEC_CTL_STOP                                  0x0
+#define B_SC_COMM_STATE__A                                           0x800001
+#define B_SC_RA_RAM_PARAM0__A                                        0x820040
+#define B_SC_RA_RAM_PARAM1__A                                        0x820041
+#define B_SC_RA_RAM_CMD_ADDR__A                                      0x820042
+#define B_SC_RA_RAM_CMD__A                                           0x820043
+#define   B_SC_RA_RAM_CMD_PROC_START                                 0x1
+#define   B_SC_RA_RAM_CMD_SET_PREF_PARAM                             0x3
+#define   B_SC_RA_RAM_CMD_GET_OP_PARAM                               0x5
+#define   B_SC_RA_RAM_SW_EVENT_RUN_NMASK__M                          0x1
+#define   B_SC_RA_RAM_LOCKTRACK_MIN                                  0x1
+#define     B_SC_RA_RAM_OP_PARAM_MODE_2K                             0x0
+#define     B_SC_RA_RAM_OP_PARAM_MODE_8K                             0x1
+#define     B_SC_RA_RAM_OP_PARAM_GUARD_32                            0x0
+#define     B_SC_RA_RAM_OP_PARAM_GUARD_16                            0x4
+#define     B_SC_RA_RAM_OP_PARAM_GUARD_8                             0x8
+#define     B_SC_RA_RAM_OP_PARAM_GUARD_4                             0xC
+#define     B_SC_RA_RAM_OP_PARAM_CONST_QPSK                          0x0
+#define     B_SC_RA_RAM_OP_PARAM_CONST_QAM16                         0x10
+#define     B_SC_RA_RAM_OP_PARAM_CONST_QAM64                         0x20
+#define     B_SC_RA_RAM_OP_PARAM_HIER_NO                             0x0
+#define     B_SC_RA_RAM_OP_PARAM_HIER_A1                             0x40
+#define     B_SC_RA_RAM_OP_PARAM_HIER_A2                             0x80
+#define     B_SC_RA_RAM_OP_PARAM_HIER_A4                             0xC0
+#define     B_SC_RA_RAM_OP_PARAM_RATE_1_2                            0x0
+#define     B_SC_RA_RAM_OP_PARAM_RATE_2_3                            0x200
+#define     B_SC_RA_RAM_OP_PARAM_RATE_3_4                            0x400
+#define     B_SC_RA_RAM_OP_PARAM_RATE_5_6                            0x600
+#define     B_SC_RA_RAM_OP_PARAM_RATE_7_8                            0x800
+#define     B_SC_RA_RAM_OP_PARAM_PRIO_HI                             0x0
+#define     B_SC_RA_RAM_OP_PARAM_PRIO_LO                             0x1000
+#define   B_SC_RA_RAM_OP_AUTO_MODE__M                                0x1
+#define   B_SC_RA_RAM_OP_AUTO_GUARD__M                               0x2
+#define   B_SC_RA_RAM_OP_AUTO_CONST__M                               0x4
+#define   B_SC_RA_RAM_OP_AUTO_HIER__M                                0x8
+#define   B_SC_RA_RAM_OP_AUTO_RATE__M                                0x10
+#define B_SC_RA_RAM_LOCK__A                                          0x82004B
+#define   B_SC_RA_RAM_LOCK_DEMOD__M                                  0x1
+#define   B_SC_RA_RAM_LOCK_FEC__M                                    0x2
+#define   B_SC_RA_RAM_LOCK_MPEG__M                                   0x4
+#define B_SC_RA_RAM_BE_OPT_ENA__A                                    0x82004C
+#define   B_SC_RA_RAM_BE_OPT_ENA_CP_OPT                              0x1
+#define B_SC_RA_RAM_BE_OPT_DELAY__A                                  0x82004D
+#define B_SC_RA_RAM_CONFIG__A                                        0x820050
+#define   B_SC_RA_RAM_CONFIG_FR_ENABLE__M                            0x4
+#define   B_SC_RA_RAM_CONFIG_FREQSCAN__M                             0x10
+#define   B_SC_RA_RAM_CONFIG_SLAVE__M                                0x20
+#define   B_SC_RA_RAM_CONFIG_DIV_BLANK_ENABLE__M                     0x200
+#define   B_SC_RA_RAM_CONFIG_DIV_ECHO_ENABLE__M                      0x400
+#define B_SC_RA_RAM_CO_TD_CAL_2K__A                                  0x82005D
+#define B_SC_RA_RAM_CO_TD_CAL_8K__A                                  0x82005E
+#define B_SC_RA_RAM_IF_SAVE__AX                                      0x82008E
+#define B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A                         0x820098
+#define B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A                         0x820099
+#define B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A                          0x82009A
+#define B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A                          0x82009B
+#define B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A                         0x82009C
+#define B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A                         0x82009D
+#define B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A                          0x82009E
+#define B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A                          0x82009F
+#define B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A                           0x8200D1
+#define B_SC_RA_RAM_IR_COARSE_2K_LENGTH__PRE                         0x9
+#define B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A                          0x8200D2
+#define B_SC_RA_RAM_IR_COARSE_2K_FREQINC__PRE                        0x4
+#define B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A                          0x8200D3
+#define B_SC_RA_RAM_IR_COARSE_2K_KAISINC__PRE                        0x100
+#define B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A                           0x8200D4
+#define B_SC_RA_RAM_IR_COARSE_8K_LENGTH__PRE                         0x8
+#define B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A                          0x8200D5
+#define B_SC_RA_RAM_IR_COARSE_8K_FREQINC__PRE                        0x8
+#define B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A                          0x8200D6
+#define B_SC_RA_RAM_IR_COARSE_8K_KAISINC__PRE                        0x200
+#define B_SC_RA_RAM_IR_FINE_2K_LENGTH__A                             0x8200D7
+#define B_SC_RA_RAM_IR_FINE_2K_LENGTH__PRE                           0x9
+#define B_SC_RA_RAM_IR_FINE_2K_FREQINC__A                            0x8200D8
+#define B_SC_RA_RAM_IR_FINE_2K_FREQINC__PRE                          0x4
+#define B_SC_RA_RAM_IR_FINE_2K_KAISINC__A                            0x8200D9
+#define B_SC_RA_RAM_IR_FINE_2K_KAISINC__PRE                          0x100
+#define B_SC_RA_RAM_IR_FINE_8K_LENGTH__A                             0x8200DA
+#define B_SC_RA_RAM_IR_FINE_8K_LENGTH__PRE                           0xB
+#define B_SC_RA_RAM_IR_FINE_8K_FREQINC__A                            0x8200DB
+#define B_SC_RA_RAM_IR_FINE_8K_FREQINC__PRE                          0x1
+#define B_SC_RA_RAM_IR_FINE_8K_KAISINC__A                            0x8200DC
+#define B_SC_RA_RAM_IR_FINE_8K_KAISINC__PRE                          0x40
+#define B_SC_RA_RAM_ECHO_SHIFT_LIM__A                                0x8200DD
+#define B_SC_RA_RAM_SAMPLE_RATE_COUNT__A                             0x8200E8
+#define B_SC_RA_RAM_SAMPLE_RATE_STEP__A                              0x8200E9
+#define B_SC_RA_RAM_BAND__A                                          0x8200EC
+#define B_SC_RA_RAM_LC_ABS_2K__A                                     0x8200F4
+#define B_SC_RA_RAM_LC_ABS_2K__PRE                                   0x1F
+#define B_SC_RA_RAM_LC_ABS_8K__A                                     0x8200F5
+#define B_SC_RA_RAM_LC_ABS_8K__PRE                                   0x1F
+#define B_SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE                      0x100
+#define B_SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE                      0x4
+#define B_SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE                         0x1E2
+#define B_SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE                         0x4
+#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE                        0x10D
+#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE                        0x5
+#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE                     0x17D
+#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE                     0x4
+#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE                     0x133
+#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE                     0x5
+#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE                        0x114
+#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE                        0x5
+#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE                     0x14A
+#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE                     0x4
+#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE                     0x1BB
+#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE                     0x4
+#define B_SC_RA_RAM_DRIVER_VERSION__AX                               0x8201FE
+#define   B_SC_RA_RAM_PROC_LOCKTRACK                                 0x0
+#define B_FE_COMM_EXEC__A                                            0xC00000
+#define B_FE_AD_REG_COMM_EXEC__A                                     0xC10000
+#define B_FE_AD_REG_FDB_IN__A                                        0xC10012
+#define B_FE_AD_REG_PD__A                                            0xC10013
+#define B_FE_AD_REG_INVEXT__A                                        0xC10014
+#define B_FE_AD_REG_CLKNEG__A                                        0xC10015
+#define B_FE_AG_REG_COMM_EXEC__A                                     0xC20000
+#define B_FE_AG_REG_AG_MODE_LOP__A                                   0xC20010
+#define   B_FE_AG_REG_AG_MODE_LOP_MODE_4__M                          0x10
+#define     B_FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC                    0x0
+#define     B_FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC                   0x10
+#define   B_FE_AG_REG_AG_MODE_LOP_MODE_5__M                          0x20
+#define     B_FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC                    0x0
+#define   B_FE_AG_REG_AG_MODE_LOP_MODE_C__M                          0x1000
+#define     B_FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC                    0x0
+#define     B_FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC                   0x1000
+#define   B_FE_AG_REG_AG_MODE_LOP_MODE_E__M                          0x4000
+#define     B_FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC                    0x0
+#define     B_FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC                   0x4000
+#define B_FE_AG_REG_AG_MODE_HIP__A                                   0xC20011
+#define   B_FE_AG_REG_AG_MODE_HIP_MODE_J__M                          0x8
+#define     B_FE_AG_REG_AG_MODE_HIP_MODE_J_STATIC                    0x0
+#define     B_FE_AG_REG_AG_MODE_HIP_MODE_J_DYNAMIC                   0x8
+#define B_FE_AG_REG_AG_PGA_MODE__A                                   0xC20012
+#define   B_FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN                    0x0
+#define   B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN                    0x1
+#define B_FE_AG_REG_AG_AGC_SIO__A                                    0xC20013
+#define   B_FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M                        0x2
+#define     B_FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT                  0x0
+#define     B_FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT                   0x2
+#define B_FE_AG_REG_AG_PWD__A                                        0xC20015
+#define   B_FE_AG_REG_AG_PWD_PWD_PD2__M                              0x2
+#define     B_FE_AG_REG_AG_PWD_PWD_PD2_DISABLE                       0x0
+#define     B_FE_AG_REG_AG_PWD_PWD_PD2_ENABLE                        0x2
+#define B_FE_AG_REG_DCE_AUR_CNT__A                                   0xC20016
+#define B_FE_AG_REG_DCE_RUR_CNT__A                                   0xC20017
+#define B_FE_AG_REG_ACE_AUR_CNT__A                                   0xC2001A
+#define B_FE_AG_REG_ACE_RUR_CNT__A                                   0xC2001B
+#define B_FE_AG_REG_CDR_RUR_CNT__A                                   0xC20020
+#define B_FE_AG_REG_EGC_RUR_CNT__A                                   0xC20024
+#define B_FE_AG_REG_EGC_SET_LVL__A                                   0xC20025
+#define B_FE_AG_REG_EGC_SET_LVL__M                                   0x1FF
+#define B_FE_AG_REG_EGC_FLA_RGN__A                                   0xC20026
+#define B_FE_AG_REG_EGC_SLO_RGN__A                                   0xC20027
+#define B_FE_AG_REG_EGC_JMP_PSN__A                                   0xC20028
+#define B_FE_AG_REG_EGC_FLA_INC__A                                   0xC20029
+#define B_FE_AG_REG_EGC_FLA_DEC__A                                   0xC2002A
+#define B_FE_AG_REG_EGC_SLO_INC__A                                   0xC2002B
+#define B_FE_AG_REG_EGC_SLO_DEC__A                                   0xC2002C
+#define B_FE_AG_REG_EGC_FAS_INC__A                                   0xC2002D
+#define B_FE_AG_REG_EGC_FAS_DEC__A                                   0xC2002E
+#define B_FE_AG_REG_PM1_AGC_WRI__A                                   0xC20030
+#define B_FE_AG_REG_PM1_AGC_WRI__M                                   0x7FF
+#define B_FE_AG_REG_GC1_AGC_RIC__A                                   0xC20031
+#define B_FE_AG_REG_GC1_AGC_OFF__A                                   0xC20032
+#define B_FE_AG_REG_GC1_AGC_MAX__A                                   0xC20033
+#define B_FE_AG_REG_GC1_AGC_MIN__A                                   0xC20034
+#define B_FE_AG_REG_GC1_AGC_DAT__A                                   0xC20035
+#define B_FE_AG_REG_GC1_AGC_DAT__M                                   0x3FF
+#define B_FE_AG_REG_PM2_AGC_WRI__A                                   0xC20036
+#define B_FE_AG_REG_IND_WIN__A                                       0xC2003C
+#define B_FE_AG_REG_IND_THD_LOL__A                                   0xC2003D
+#define B_FE_AG_REG_IND_THD_HIL__A                                   0xC2003E
+#define B_FE_AG_REG_IND_DEL__A                                       0xC2003F
+#define B_FE_AG_REG_IND_PD1_WRI__A                                   0xC20040
+#define B_FE_AG_REG_PDA_AUR_CNT__A                                   0xC20041
+#define B_FE_AG_REG_PDA_RUR_CNT__A                                   0xC20042
+#define B_FE_AG_REG_PDA_AVE_DAT__A                                   0xC20043
+#define B_FE_AG_REG_PDC_RUR_CNT__A                                   0xC20044
+#define B_FE_AG_REG_PDC_SET_LVL__A                                   0xC20045
+#define B_FE_AG_REG_PDC_FLA_RGN__A                                   0xC20046
+#define B_FE_AG_REG_PDC_JMP_PSN__A                                   0xC20047
+#define B_FE_AG_REG_PDC_FLA_STP__A                                   0xC20048
+#define B_FE_AG_REG_PDC_SLO_STP__A                                   0xC20049
+#define B_FE_AG_REG_PDC_PD2_WRI__A                                   0xC2004A
+#define B_FE_AG_REG_PDC_MAP_DAT__A                                   0xC2004B
+#define B_FE_AG_REG_PDC_MAX__A                                       0xC2004C
+#define B_FE_AG_REG_TGA_AUR_CNT__A                                   0xC2004D
+#define B_FE_AG_REG_TGA_RUR_CNT__A                                   0xC2004E
+#define B_FE_AG_REG_TGA_AVE_DAT__A                                   0xC2004F
+#define B_FE_AG_REG_TGC_RUR_CNT__A                                   0xC20050
+#define B_FE_AG_REG_TGC_SET_LVL__A                                   0xC20051
+#define B_FE_AG_REG_TGC_SET_LVL__M                                   0x3F
+#define B_FE_AG_REG_TGC_FLA_RGN__A                                   0xC20052
+#define B_FE_AG_REG_TGC_JMP_PSN__A                                   0xC20053
+#define B_FE_AG_REG_TGC_FLA_STP__A                                   0xC20054
+#define B_FE_AG_REG_TGC_SLO_STP__A                                   0xC20055
+#define B_FE_AG_REG_TGC_MAP_DAT__A                                   0xC20056
+#define B_FE_AG_REG_FGM_WRI__A                                       0xC20061
+#define B_FE_AG_REG_BGC_FGC_WRI__A                                   0xC20068
+#define B_FE_AG_REG_BGC_CGC_WRI__A                                   0xC20069
+#define B_FE_FS_REG_COMM_EXEC__A                                     0xC30000
+#define B_FE_FS_REG_ADD_INC_LOP__A                                   0xC30010
+#define B_FE_FD_REG_COMM_EXEC__A                                     0xC40000
+#define B_FE_FD_REG_SCL__A                                           0xC40010
+#define B_FE_FD_REG_MAX_LEV__A                                       0xC40011
+#define B_FE_FD_REG_NR__A                                            0xC40012
+#define B_FE_FD_REG_MEAS_VAL__A                                      0xC40014
+#define B_FE_IF_REG_COMM_EXEC__A                                     0xC50000
+#define B_FE_IF_REG_INCR0__A                                         0xC50010
+#define B_FE_IF_REG_INCR0__W                                         16
+#define B_FE_IF_REG_INCR0__M                                         0xFFFF
+#define B_FE_IF_REG_INCR1__A                                         0xC50011
+#define B_FE_IF_REG_INCR1__M                                         0xFF
+#define B_FE_CF_REG_COMM_EXEC__A                                     0xC60000
+#define B_FE_CF_REG_SCL__A                                           0xC60010
+#define B_FE_CF_REG_MAX_LEV__A                                       0xC60011
+#define B_FE_CF_REG_NR__A                                            0xC60012
+#define B_FE_CF_REG_IMP_VAL__A                                       0xC60013
+#define B_FE_CF_REG_MEAS_VAL__A                                      0xC60014
+#define B_FE_CU_REG_COMM_EXEC__A                                     0xC70000
+#define B_FE_CU_REG_FRM_CNT_RST__A                                   0xC70011
+#define B_FE_CU_REG_FRM_CNT_STR__A                                   0xC70012
+#define B_FE_CU_REG_CTR_NFC_ICR__A                                   0xC70020
+#define B_FE_CU_REG_CTR_NFC_OCR__A                                   0xC70021
+#define B_FE_CU_REG_DIV_NFC_CLP__A                                   0xC70027
+#define B_FT_COMM_EXEC__A                                            0x1000000
+#define B_FT_REG_COMM_EXEC__A                                        0x1010000
+#define B_CP_COMM_EXEC__A                                            0x1400000
+#define B_CP_REG_COMM_EXEC__A                                        0x1410000
+#define B_CP_REG_INTERVAL__A                                         0x1410011
+#define B_CP_REG_BR_SPL_OFFSET__A                                    0x1410023
+#define B_CP_REG_BR_STR_DEL__A                                       0x1410024
+#define B_CP_REG_RT_ANG_INC0__A                                      0x1410030
+#define B_CP_REG_RT_ANG_INC1__A                                      0x1410031
+#define B_CP_REG_RT_DETECT_TRH__A                                    0x1410033
+#define B_CP_REG_AC_NEXP_OFFS__A                                     0x1410040
+#define B_CP_REG_AC_AVER_POW__A                                      0x1410041
+#define B_CP_REG_AC_MAX_POW__A                                       0x1410042
+#define B_CP_REG_AC_WEIGHT_MAN__A                                    0x1410043
+#define B_CP_REG_AC_WEIGHT_EXP__A                                    0x1410044
+#define B_CP_REG_AC_AMP_MODE__A                                      0x1410047
+#define B_CP_REG_AC_AMP_FIX__A                                       0x1410048
+#define B_CP_REG_AC_ANG_MODE__A                                      0x141004A
+#define B_CE_COMM_EXEC__A                                            0x1800000
+#define B_CE_REG_COMM_EXEC__A                                        0x1810000
+#define B_CE_REG_TAPSET__A                                           0x1810011
+#define B_CE_REG_AVG_POW__A                                          0x1810012
+#define B_CE_REG_MAX_POW__A                                          0x1810013
+#define B_CE_REG_ATT__A                                              0x1810014
+#define B_CE_REG_NRED__A                                             0x1810015
+#define B_CE_REG_NE_ERR_SELECT__A                                    0x1810043
+#define B_CE_REG_NE_TD_CAL__A                                        0x1810044
+#define B_CE_REG_NE_MIXAVG__A                                        0x1810046
+#define B_CE_REG_NE_NUPD_OFS__A                                      0x1810047
+#define B_CE_REG_PE_NEXP_OFFS__A                                     0x1810050
+#define B_CE_REG_PE_TIMESHIFT__A                                     0x1810051
+#define B_CE_REG_TP_A0_TAP_NEW__A                                    0x1810064
+#define B_CE_REG_TP_A0_TAP_NEW_VALID__A                              0x1810065
+#define B_CE_REG_TP_A0_MU_LMS_STEP__A                                0x1810066
+#define B_CE_REG_TP_A1_TAP_NEW__A                                    0x1810068
+#define B_CE_REG_TP_A1_TAP_NEW_VALID__A                              0x1810069
+#define B_CE_REG_TP_A1_MU_LMS_STEP__A                                0x181006A
+#define B_CE_REG_TI_PHN_ENABLE__A                                    0x1810073
+#define B_CE_REG_FI_SHT_INCR__A                                      0x1810090
+#define B_CE_REG_FI_EXP_NORM__A                                      0x1810091
+#define B_CE_REG_IR_INPUTSEL__A                                      0x18100A0
+#define B_CE_REG_IR_STARTPOS__A                                      0x18100A1
+#define B_CE_REG_IR_NEXP_THRES__A                                    0x18100A2
+#define B_CE_REG_FR_TREAL00__A                                       0x1820010
+#define B_CE_REG_FR_TIMAG00__A                                       0x1820011
+#define B_CE_REG_FR_TREAL01__A                                       0x1820012
+#define B_CE_REG_FR_TIMAG01__A                                       0x1820013
+#define B_CE_REG_FR_TREAL02__A                                       0x1820014
+#define B_CE_REG_FR_TIMAG02__A                                       0x1820015
+#define B_CE_REG_FR_TREAL03__A                                       0x1820016
+#define B_CE_REG_FR_TIMAG03__A                                       0x1820017
+#define B_CE_REG_FR_TREAL04__A                                       0x1820018
+#define B_CE_REG_FR_TIMAG04__A                                       0x1820019
+#define B_CE_REG_FR_TREAL05__A                                       0x182001A
+#define B_CE_REG_FR_TIMAG05__A                                       0x182001B
+#define B_CE_REG_FR_TREAL06__A                                       0x182001C
+#define B_CE_REG_FR_TIMAG06__A                                       0x182001D
+#define B_CE_REG_FR_TREAL07__A                                       0x182001E
+#define B_CE_REG_FR_TIMAG07__A                                       0x182001F
+#define B_CE_REG_FR_TREAL08__A                                       0x1820020
+#define B_CE_REG_FR_TIMAG08__A                                       0x1820021
+#define B_CE_REG_FR_TREAL09__A                                       0x1820022
+#define B_CE_REG_FR_TIMAG09__A                                       0x1820023
+#define B_CE_REG_FR_TREAL10__A                                       0x1820024
+#define B_CE_REG_FR_TIMAG10__A                                       0x1820025
+#define B_CE_REG_FR_TREAL11__A                                       0x1820026
+#define B_CE_REG_FR_TIMAG11__A                                       0x1820027
+#define B_CE_REG_FR_MID_TAP__A                                       0x1820028
+#define B_CE_REG_FR_SQS_G00__A                                       0x1820029
+#define B_CE_REG_FR_SQS_G01__A                                       0x182002A
+#define B_CE_REG_FR_SQS_G02__A                                       0x182002B
+#define B_CE_REG_FR_SQS_G03__A                                       0x182002C
+#define B_CE_REG_FR_SQS_G04__A                                       0x182002D
+#define B_CE_REG_FR_SQS_G05__A                                       0x182002E
+#define B_CE_REG_FR_SQS_G06__A                                       0x182002F
+#define B_CE_REG_FR_SQS_G07__A                                       0x1820030
+#define B_CE_REG_FR_SQS_G08__A                                       0x1820031
+#define B_CE_REG_FR_SQS_G09__A                                       0x1820032
+#define B_CE_REG_FR_SQS_G10__A                                       0x1820033
+#define B_CE_REG_FR_SQS_G11__A                                       0x1820034
+#define B_CE_REG_FR_SQS_G12__A                                       0x1820035
+#define B_CE_REG_FR_RIO_G00__A                                       0x1820036
+#define B_CE_REG_FR_RIO_G01__A                                       0x1820037
+#define B_CE_REG_FR_RIO_G02__A                                       0x1820038
+#define B_CE_REG_FR_RIO_G03__A                                       0x1820039
+#define B_CE_REG_FR_RIO_G04__A                                       0x182003A
+#define B_CE_REG_FR_RIO_G05__A                                       0x182003B
+#define B_CE_REG_FR_RIO_G06__A                                       0x182003C
+#define B_CE_REG_FR_RIO_G07__A                                       0x182003D
+#define B_CE_REG_FR_RIO_G08__A                                       0x182003E
+#define B_CE_REG_FR_RIO_G09__A                                       0x182003F
+#define B_CE_REG_FR_RIO_G10__A                                       0x1820040
+#define B_CE_REG_FR_MODE__A                                          0x1820041
+#define B_CE_REG_FR_SQS_TRH__A                                       0x1820042
+#define B_CE_REG_FR_RIO_GAIN__A                                      0x1820043
+#define B_CE_REG_FR_BYPASS__A                                        0x1820044
+#define B_CE_REG_FR_PM_SET__A                                        0x1820045
+#define B_CE_REG_FR_ERR_SH__A                                        0x1820046
+#define B_CE_REG_FR_MAN_SH__A                                        0x1820047
+#define B_CE_REG_FR_TAP_SH__A                                        0x1820048
+#define B_EQ_COMM_EXEC__A                                            0x1C00000
+#define B_EQ_REG_COMM_EXEC__A                                        0x1C10000
+#define B_EQ_REG_COMM_MB__A                                          0x1C10002
+#define B_EQ_REG_IS_GAIN_MAN__A                                      0x1C10015
+#define B_EQ_REG_IS_GAIN_EXP__A                                      0x1C10016
+#define B_EQ_REG_IS_CLIP_EXP__A                                      0x1C10017
+#define B_EQ_REG_SN_CEGAIN__A                                        0x1C1002A
+#define B_EQ_REG_SN_OFFSET__A                                        0x1C1002B
+#define B_EQ_REG_RC_SEL_CAR__A                                       0x1C10032
+#define   B_EQ_REG_RC_SEL_CAR_INIT                                   0x2
+#define     B_EQ_REG_RC_SEL_CAR_DIV_ON                               0x1
+#define     B_EQ_REG_RC_SEL_CAR_PASS_A_CC                            0x0
+#define     B_EQ_REG_RC_SEL_CAR_PASS_B_CE                            0x2
+#define     B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC                           0x0
+#define     B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE                           0x8
+#define     B_EQ_REG_RC_SEL_CAR_MEAS_A_CC                            0x0
+#define     B_EQ_REG_RC_SEL_CAR_MEAS_B_CE                            0x20
+#define   B_EQ_REG_RC_SEL_CAR_FFTMODE__M                             0x80
+#define B_EQ_REG_OT_CONST__A                                         0x1C10046
+#define B_EQ_REG_OT_ALPHA__A                                         0x1C10047
+#define B_EQ_REG_OT_QNT_THRES0__A                                    0x1C10048
+#define B_EQ_REG_OT_QNT_THRES1__A                                    0x1C10049
+#define B_EQ_REG_OT_CSI_STEP__A                                      0x1C1004A
+#define B_EQ_REG_OT_CSI_OFFSET__A                                    0x1C1004B
+#define B_EQ_REG_TD_REQ_SMB_CNT__A                                   0x1C10061
+#define B_EQ_REG_TD_TPS_PWR_OFS__A                                   0x1C10062
+#define B_EC_SB_REG_COMM_EXEC__A                                     0x2010000
+#define B_EC_SB_REG_TR_MODE__A                                       0x2010010
+#define   B_EC_SB_REG_TR_MODE_8K                                     0x0
+#define   B_EC_SB_REG_TR_MODE_2K                                     0x1
+#define B_EC_SB_REG_CONST__A                                         0x2010011
+#define   B_EC_SB_REG_CONST_QPSK                                     0x0
+#define   B_EC_SB_REG_CONST_16QAM                                    0x1
+#define   B_EC_SB_REG_CONST_64QAM                                    0x2
+#define B_EC_SB_REG_ALPHA__A                                         0x2010012
+#define B_EC_SB_REG_PRIOR__A                                         0x2010013
+#define   B_EC_SB_REG_PRIOR_HI                                       0x0
+#define   B_EC_SB_REG_PRIOR_LO                                       0x1
+#define B_EC_SB_REG_CSI_HI__A                                        0x2010014
+#define B_EC_SB_REG_CSI_LO__A                                        0x2010015
+#define B_EC_SB_REG_SMB_TGL__A                                       0x2010016
+#define B_EC_SB_REG_SNR_HI__A                                        0x2010017
+#define B_EC_SB_REG_SNR_MID__A                                       0x2010018
+#define B_EC_SB_REG_SNR_LO__A                                        0x2010019
+#define B_EC_SB_REG_SCALE_MSB__A                                     0x201001A
+#define B_EC_SB_REG_SCALE_BIT2__A                                    0x201001B
+#define B_EC_SB_REG_SCALE_LSB__A                                     0x201001C
+#define B_EC_SB_REG_CSI_OFS0__A                                      0x201001D
+#define B_EC_SB_REG_CSI_OFS1__A                                      0x201001E
+#define B_EC_SB_REG_CSI_OFS2__A                                      0x201001F
+#define B_EC_VD_REG_COMM_EXEC__A                                     0x2090000
+#define B_EC_VD_REG_FORCE__A                                         0x2090010
+#define B_EC_VD_REG_SET_CODERATE__A                                  0x2090011
+#define   B_EC_VD_REG_SET_CODERATE_C1_2                              0x0
+#define   B_EC_VD_REG_SET_CODERATE_C2_3                              0x1
+#define   B_EC_VD_REG_SET_CODERATE_C3_4                              0x2
+#define   B_EC_VD_REG_SET_CODERATE_C5_6                              0x3
+#define   B_EC_VD_REG_SET_CODERATE_C7_8                              0x4
+#define B_EC_VD_REG_REQ_SMB_CNT__A                                   0x2090012
+#define B_EC_VD_REG_RLK_ENA__A                                       0x2090014
+#define B_EC_OD_REG_COMM_EXEC__A                                     0x2110000
+#define B_EC_OD_REG_SYNC__A                                          0x2110664
+#define B_EC_OD_DEINT_RAM__A                                         0x2120000
+#define B_EC_RS_REG_COMM_EXEC__A                                     0x2130000
+#define B_EC_RS_REG_REQ_PCK_CNT__A                                   0x2130010
+#define B_EC_RS_REG_VAL__A                                           0x2130011
+#define   B_EC_RS_REG_VAL_PCK                                        0x1
+#define B_EC_RS_EC_RAM__A                                            0x2140000
+#define B_EC_OC_REG_COMM_EXEC__A                                     0x2150000
+#define     B_EC_OC_REG_COMM_EXEC_CTL_ACTIVE                         0x1
+#define     B_EC_OC_REG_COMM_EXEC_CTL_HOLD                           0x2
+#define B_EC_OC_REG_COMM_INT_STA__A                                  0x2150007
+#define B_EC_OC_REG_OC_MODE_LOP__A                                   0x2150010
+#define   B_EC_OC_REG_OC_MODE_LOP_PAR_ENA__M                         0x1
+#define     B_EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE                   0x0
+#define     B_EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE                  0x1
+#define   B_EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M                     0x4
+#define     B_EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC               0x0
+#define   B_EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M                     0x80
+#define     B_EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL               0x80
+#define B_EC_OC_REG_OC_MODE_HIP__A                                   0x2150011
+#define     B_EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR              0x10
+#define   B_EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M                     0x200
+#define     B_EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE              0x0
+#define     B_EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE               0x200
+#define B_EC_OC_REG_OC_MPG_SIO__A                                    0x2150012
+#define B_EC_OC_REG_OC_MPG_SIO__M                                    0xFFF
+#define B_EC_OC_REG_DTO_INC_LOP__A                                   0x2150014
+#define B_EC_OC_REG_DTO_INC_HIP__A                                   0x2150015
+#define B_EC_OC_REG_SNC_ISC_LVL__A                                   0x2150016
+#define   B_EC_OC_REG_SNC_ISC_LVL_OSC__M                             0xF0
+#define B_EC_OC_REG_TMD_TOP_MODE__A                                  0x215001D
+#define B_EC_OC_REG_TMD_TOP_CNT__A                                   0x215001E
+#define B_EC_OC_REG_TMD_HIL_MAR__A                                   0x215001F
+#define B_EC_OC_REG_TMD_LOL_MAR__A                                   0x2150020
+#define B_EC_OC_REG_TMD_CUR_CNT__A                                   0x2150021
+#define B_EC_OC_REG_AVR_ASH_CNT__A                                   0x2150023
+#define B_EC_OC_REG_AVR_BSH_CNT__A                                   0x2150024
+#define B_EC_OC_REG_RCN_MODE__A                                      0x2150027
+#define B_EC_OC_REG_RCN_CRA_LOP__A                                   0x2150028
+#define B_EC_OC_REG_RCN_CRA_HIP__A                                   0x2150029
+#define B_EC_OC_REG_RCN_CST_LOP__A                                   0x215002A
+#define B_EC_OC_REG_RCN_CST_HIP__A                                   0x215002B
+#define B_EC_OC_REG_RCN_SET_LVL__A                                   0x215002C
+#define B_EC_OC_REG_RCN_GAI_LVL__A                                   0x215002D
+#define B_EC_OC_REG_RCN_CLP_LOP__A                                   0x2150032
+#define B_EC_OC_REG_RCN_CLP_HIP__A                                   0x2150033
+#define B_EC_OC_REG_RCN_MAP_LOP__A                                   0x2150034
+#define B_EC_OC_REG_RCN_MAP_HIP__A                                   0x2150035
+#define B_EC_OC_REG_OCR_MPG_UOS__A                                   0x2150036
+#define B_EC_OC_REG_OCR_MPG_UOS__M                                   0xFFF
+#define   B_EC_OC_REG_OCR_MPG_UOS_INIT                               0x0
+#define B_EC_OC_REG_OCR_MPG_USR_DAT__A                               0x2150038
+#define B_EC_OC_REG_IPR_INV_MPG__A                                   0x2150045
+#define B_EC_OC_REG_DTO_CLKMODE__A                                   0x2150047
+#define B_EC_OC_REG_DTO_PER__A                                       0x2150048
+#define B_EC_OC_REG_DTO_BUR__A                                       0x2150049
+#define B_EC_OC_REG_RCR_CLKMODE__A                                   0x215004A
+#define B_CC_REG_OSC_MODE__A                                         0x2410010
+#define   B_CC_REG_OSC_MODE_M20                                      0x1
+#define B_CC_REG_PLL_MODE__A                                         0x2410011
+#define     B_CC_REG_PLL_MODE_BYPASS_PLL                             0x1
+#define     B_CC_REG_PLL_MODE_PUMP_CUR_12                            0x14
+#define B_CC_REG_REF_DIVIDE__A                                       0x2410012
+#define B_CC_REG_PWD_MODE__A                                         0x2410015
+#define   B_CC_REG_PWD_MODE_DOWN_PLL                                 0x2
+#define B_CC_REG_UPDATE__A                                           0x2410017
+#define   B_CC_REG_UPDATE_KEY                                        0x3973
+#define B_CC_REG_JTAGID_L__A                                         0x2410019
+#define B_CC_REG_DIVERSITY__A                                        0x241001B
+#define B_LC_COMM_EXEC__A                                            0x2800000
+#define B_LC_RA_RAM_IFINCR_NOM_L__A                                  0x282000C
+#define B_LC_RA_RAM_FILTER_SYM_SET__A                                0x282001A
+#define B_LC_RA_RAM_FILTER_SYM_SET__PRE                              0x3E8
+#define B_LC_RA_RAM_FILTER_CRMM_A__A                                 0x2820060
+#define B_LC_RA_RAM_FILTER_CRMM_A__PRE                               0x4
+#define B_LC_RA_RAM_FILTER_CRMM_B__A                                 0x2820061
+#define B_LC_RA_RAM_FILTER_CRMM_B__PRE                               0x1
+#define B_LC_RA_RAM_FILTER_SRMM_A__A                                 0x2820068
+#define B_LC_RA_RAM_FILTER_SRMM_A__PRE                               0x4
+#define B_LC_RA_RAM_FILTER_SRMM_B__A                                 0x2820069
+#define B_LC_RA_RAM_FILTER_SRMM_B__PRE                               0x1
+
+#endif

+ 1 - 1
drivers/media/dvb/frontends/eds1547.h

@@ -61,7 +61,7 @@ static u8 stv0288_earda_inittab[] = {
 	0x3d, 0x30,
 	0x40, 0x63,
 	0x41, 0x04,
-	0x42, 0x60,
+	0x42, 0x20,
 	0x43, 0x00,
 	0x44, 0x00,
 	0x45, 0x00,

+ 6 - 4
drivers/media/dvb/frontends/ix2505v.c

@@ -218,11 +218,13 @@ static int ix2505v_set_params(struct dvb_frontend *fe,
 		fe->ops.i2c_gate_ctrl(fe, 1);
 
 	len = sizeof(data);
-
 	ret |= ix2505v_write(state, data, len);
 
 	data[2] |= 0x4; /* set TM = 1 other bits same */
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
 	len = 1;
 	ret |= ix2505v_write(state, &data[2], len); /* write byte 4 only */
 
@@ -233,12 +235,12 @@ static int ix2505v_set_params(struct dvb_frontend *fe,
 
 	deb_info("Data 2=[%x%x]\n", data[2], data[3]);
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
 	len = 2;
 	ret |= ix2505v_write(state, &data[2], len); /* write byte 4 & 5 */
 
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
 	if (state->config->min_delay_ms)
 		msleep(state->config->min_delay_ms);
 

+ 1 - 1
drivers/media/dvb/frontends/stv0288.c

@@ -253,7 +253,7 @@ static u8 stv0288_inittab[] = {
 	0x3d, 0x30,
 	0x40, 0x63,
 	0x41, 0x04,
-	0x42, 0x60,
+	0x42, 0x20,
 	0x43, 0x00,
 	0x44, 0x00,
 	0x45, 0x00,

+ 8 - 2
drivers/media/dvb/frontends/stv0299.c

@@ -64,6 +64,7 @@ struct stv0299_state {
 	fe_code_rate_t fec_inner;
 	int errmode;
 	u32 ucblocks;
+	u8 mcr_reg;
 };
 
 #define STATUS_BER 0
@@ -457,6 +458,9 @@ static int stv0299_init (struct dvb_frontend* fe)
 
 	dprintk("stv0299: init chip\n");
 
+	stv0299_writeregI(state, 0x02, 0x30 | state->mcr_reg);
+	msleep(50);
+
 	for (i = 0; ; i += 2)  {
 		reg = state->config->inittab[i];
 		val = state->config->inittab[i+1];
@@ -464,6 +468,8 @@ static int stv0299_init (struct dvb_frontend* fe)
 			break;
 		if (reg == 0x0c && state->config->op0_off)
 			val &= ~0x10;
+		if (reg == 0x2)
+			state->mcr_reg = val & 0xf;
 		stv0299_writeregI(state, reg, val);
 	}
 
@@ -618,7 +624,7 @@ static int stv0299_sleep(struct dvb_frontend* fe)
 {
 	struct stv0299_state* state = fe->demodulator_priv;
 
-	stv0299_writeregI(state, 0x02, 0x80);
+	stv0299_writeregI(state, 0x02, 0xb0 | state->mcr_reg);
 	state->initialised = 0;
 
 	return 0;
@@ -680,7 +686,7 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
 	state->errmode = STATUS_BER;
 
 	/* check if the demod is there */
-	stv0299_writeregI(state, 0x02, 0x34); /* standby off */
+	stv0299_writeregI(state, 0x02, 0x30); /* standby off */
 	msleep(200);
 	id = stv0299_readreg(state, 0x00);
 

+ 1 - 1
drivers/media/dvb/frontends/z0194a.h

@@ -42,7 +42,7 @@ static int sharp_z0194a_set_symbol_rate(struct dvb_frontend *fe,
 
 static u8 sharp_z0194a_inittab[] = {
 	0x01, 0x15,
-	0x02, 0x00,
+	0x02, 0x30,
 	0x03, 0x00,
 	0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
 	0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1 */

+ 1 - 1
drivers/media/dvb/mantis/hopper_cards.c

@@ -44,7 +44,7 @@
 
 static unsigned int verbose;
 module_param(verbose, int, 0644);
-MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 0 (no)");
 
 #define DRIVER_NAME	"Hopper"
 

+ 1 - 1
drivers/media/dvb/mantis/mantis_cards.c

@@ -52,7 +52,7 @@
 
 static unsigned int verbose;
 module_param(verbose, int, 0644);
-MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 0 (no)");
 
 static int devs;
 

+ 2 - 3
drivers/media/dvb/mantis/mantis_pci.c

@@ -48,7 +48,7 @@
 
 int __devinit mantis_pci_init(struct mantis_pci *mantis)
 {
-	u8 revision, latency;
+	u8 latency;
 	struct mantis_hwconfig *config	= mantis->hwconfig;
 	struct pci_dev *pdev		= mantis->pdev;
 	int err, ret = 0;
@@ -95,9 +95,8 @@ int __devinit mantis_pci_init(struct mantis_pci *mantis)
 	}
 
 	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
-	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
 	mantis->latency = latency;
-	mantis->revision = revision;
+	mantis->revision = pdev->revision;
 
 	dprintk(MANTIS_ERROR, 0, "    Mantis Rev %d [%04x:%04x], ",
 		mantis->revision,

+ 1 - 1
drivers/media/dvb/mantis/mantis_vp1033.c

@@ -37,7 +37,7 @@
 
 u8 lgtdqcs001f_inittab[] = {
 	0x01, 0x15,
-	0x02, 0x00,
+	0x02, 0x30,
 	0x03, 0x00,
 	0x04, 0x2a,
 	0x05, 0x85,

+ 3 - 2
drivers/media/dvb/pt1/pt1.c

@@ -1090,6 +1090,7 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	i2c_adap->algo = &pt1_i2c_algo;
 	i2c_adap->algo_data = NULL;
 	i2c_adap->dev.parent = &pdev->dev;
+	strcpy(i2c_adap->name, DRIVER_NAME);
 	i2c_set_adapdata(i2c_adap, pt1);
 	ret = i2c_add_adapter(i2c_adap);
 	if (ret < 0)
@@ -1156,10 +1157,10 @@ err_pt1_disable_ram:
 	pt1->power = 0;
 	pt1->reset = 1;
 	pt1_update_power(pt1);
-err_pt1_cleanup_adapters:
-	pt1_cleanup_adapters(pt1);
 err_i2c_del_adapter:
 	i2c_del_adapter(i2c_adap);
+err_pt1_cleanup_adapters:
+	pt1_cleanup_adapters(pt1);
 err_kfree:
 	pci_set_drvdata(pdev, NULL);
 	kfree(pt1);

+ 1 - 2
drivers/media/dvb/siano/smsusb.c

@@ -297,9 +297,8 @@ static void smsusb_term_device(struct usb_interface *intf)
 		if (dev->coredev)
 			smscore_unregister_device(dev->coredev);
 
-		kfree(dev);
-
 		sms_info("device %p destroyed", dev);
+		kfree(dev);
 	}
 
 	usb_set_intfdata(intf, NULL);

+ 2 - 0
drivers/media/dvb/ttpci/Kconfig

@@ -95,6 +95,8 @@ config DVB_BUDGET_CI
 	select DVB_STB0899 if !DVB_FE_CUSTOMISE
 	select DVB_STB6100 if !DVB_FE_CUSTOMISE
 	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+	select DVB_STV0288 if !DVB_FE_CUSTOMISE
+	select DVB_STB6000 if !DVB_FE_CUSTOMISE
 	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
 	select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
 	depends on RC_CORE

+ 21 - 0
drivers/media/dvb/ttpci/budget-ci.c

@@ -52,6 +52,7 @@
 #include "bsru6.h"
 #include "tda1002x.h"
 #include "tda827x.h"
+#include "bsbe1-d01a.h"
 
 #define MODULE_NAME "budget_ci"
 
@@ -224,6 +225,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
 	case 0x1017:
 	case 0x1019:
 	case 0x101a:
+	case 0x101b:
 		/* for the Technotrend 1500 bundled remote */
 		dev->map_name = RC_MAP_TT_1500;
 		break;
@@ -1388,6 +1390,23 @@ static void frontend_init(struct budget_ci *budget_ci)
 		}
 		break;
 
+	case 0x101b: /* TT S-1500B (BSBE1-D01A - STV0288/STB6000/LNBP21) */
+		budget_ci->budget.dvb_frontend = dvb_attach(stv0288_attach, &stv0288_bsbe1_d01a_config, &budget_ci->budget.i2c_adap);
+		if (budget_ci->budget.dvb_frontend) {
+			if (dvb_attach(stb6000_attach, budget_ci->budget.dvb_frontend, 0x63, &budget_ci->budget.i2c_adap)) {
+				if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
+					printk(KERN_ERR "%s: No LNBP21 found!\n", __func__);
+					dvb_frontend_detach(budget_ci->budget.dvb_frontend);
+					budget_ci->budget.dvb_frontend = NULL;
+				}
+			} else {
+				printk(KERN_ERR "%s: No STB6000 found!\n", __func__);
+				dvb_frontend_detach(budget_ci->budget.dvb_frontend);
+				budget_ci->budget.dvb_frontend = NULL;
+			}
+		}
+		break;
+
 	case 0x1019:		// TT S2-3200 PCI
 		/*
 		 * NOTE! on some STB0899 versions, the internal PLL takes a longer time
@@ -1518,6 +1537,7 @@ MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
 MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
 MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
 MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);
+MAKE_BUDGET_INFO(ttbs1500b, "TT-Budget S-1500B PCI", BUDGET_TT);
 
 static struct pci_device_id pci_tbl[] = {
 	MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
@@ -1528,6 +1548,7 @@ static struct pci_device_id pci_tbl[] = {
 	MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
 	MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
 	MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
+	MAKE_EXTENSION_PCI(ttbs1500b, 0x13c2, 0x101b),
 	{
 	 .vendor = 0,
 	 }

+ 27 - 33
drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c

@@ -52,7 +52,7 @@
     my TTUSB, so let it undef'd unless you want to implement another
     frontend. never tested.
 
-  DEBUG:
+  debug:
     define it to > 3 for really hardcore debugging. you probably don't want
     this unless the device doesn't load at all. > 2 for bandwidth statistics.
 */
@@ -134,20 +134,19 @@ struct ttusb {
 /* ugly workaround ... don't know why it's necessary to read */
 /* all result codes. */
 
-#define DEBUG 0
 static int ttusb_cmd(struct ttusb *ttusb,
 	      const u8 * data, int len, int needresult)
 {
 	int actual_len;
 	int err;
-#if DEBUG >= 3
 	int i;
 
-	printk(">");
-	for (i = 0; i < len; ++i)
-		printk(" %02x", data[i]);
-	printk("\n");
-#endif
+	if (debug >= 3) {
+		printk(KERN_DEBUG ">");
+		for (i = 0; i < len; ++i)
+			printk(KERN_CONT " %02x", data[i]);
+		printk(KERN_CONT "\n");
+	}
 
 	if (mutex_lock_interruptible(&ttusb->semusb) < 0)
 		return -EAGAIN;
@@ -176,13 +175,15 @@ static int ttusb_cmd(struct ttusb *ttusb,
 		mutex_unlock(&ttusb->semusb);
 		return err;
 	}
-#if DEBUG >= 3
-	actual_len = ttusb->last_result[3] + 4;
-	printk("<");
-	for (i = 0; i < actual_len; ++i)
-		printk(" %02x", ttusb->last_result[i]);
-	printk("\n");
-#endif
+
+	if (debug >= 3) {
+		actual_len = ttusb->last_result[3] + 4;
+		printk(KERN_DEBUG "<");
+		for (i = 0; i < actual_len; ++i)
+			printk(KERN_CONT " %02x", ttusb->last_result[i]);
+		printk(KERN_CONT "\n");
+	}
+
 	if (!needresult)
 		mutex_unlock(&ttusb->semusb);
 	return 0;
@@ -636,16 +637,13 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
 				++ttusb->mux_state;
 			else {
 				ttusb->mux_state = 0;
-#if DEBUG > 3
-				if (ttusb->insync)
-					printk("%02x ", data[-1]);
-#else
 				if (ttusb->insync) {
-					printk("%s: lost sync.\n",
+					dprintk("%s: %02x\n",
+						__func__, data[-1]);
+					printk(KERN_INFO "%s: lost sync.\n",
 					       __func__);
 					ttusb->insync = 0;
 				}
-#endif
 			}
 			break;
 		case 3:
@@ -744,6 +742,9 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
 static void ttusb_iso_irq(struct urb *urb)
 {
 	struct ttusb *ttusb = urb->context;
+	struct usb_iso_packet_descriptor *d;
+	u8 *data;
+	int len, i;
 
 	if (!ttusb->iso_streaming)
 		return;
@@ -755,21 +756,14 @@ static void ttusb_iso_irq(struct urb *urb)
 #endif
 
 	if (!urb->status) {
-		int i;
 		for (i = 0; i < urb->number_of_packets; ++i) {
-			struct usb_iso_packet_descriptor *d;
-			u8 *data;
-			int len;
 			numpkt++;
 			if (time_after_eq(jiffies, lastj + HZ)) {
-#if DEBUG > 2
-				printk
-				    ("frames/s: %d (ts: %d, stuff %d, sec: %d, invalid: %d, all: %d)\n",
-				     numpkt * HZ / (jiffies - lastj),
-				     numts, numstuff, numsec, numinvalid,
-				     numts + numstuff + numsec +
-				     numinvalid);
-#endif
+				dprintk("frames/s: %lu (ts: %d, stuff %d, "
+					"sec: %d, invalid: %d, all: %d)\n",
+					numpkt * HZ / (jiffies - lastj),
+					numts, numstuff, numsec, numinvalid,
+					numts + numstuff + numsec + numinvalid);
 				numts = numstuff = numsec = numinvalid = 0;
 				lastj = jiffies;
 				numpkt = 0;

+ 42 - 18
drivers/media/radio/si470x/radio-si470x-common.c

@@ -174,15 +174,27 @@ static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
 	if (retval < 0)
 		goto done;
 
-	/* wait till tune operation has completed */
-	timeout = jiffies + msecs_to_jiffies(tune_timeout);
-	do {
-		retval = si470x_get_register(radio, STATUSRSSI);
-		if (retval < 0)
-			goto stop;
-		timed_out = time_after(jiffies, timeout);
-	} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
-		(!timed_out));
+	/* currently I2C driver only uses interrupt way to tune */
+	if (radio->stci_enabled) {
+		INIT_COMPLETION(radio->completion);
+
+		/* wait till tune operation has completed */
+		retval = wait_for_completion_timeout(&radio->completion,
+				msecs_to_jiffies(tune_timeout));
+		if (!retval)
+			timed_out = true;
+	} else {
+		/* wait till tune operation has completed */
+		timeout = jiffies + msecs_to_jiffies(tune_timeout);
+		do {
+			retval = si470x_get_register(radio, STATUSRSSI);
+			if (retval < 0)
+				goto stop;
+			timed_out = time_after(jiffies, timeout);
+		} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
+				&& (!timed_out));
+	}
+
 	if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
 		dev_warn(&radio->videodev->dev, "tune does not complete\n");
 	if (timed_out)
@@ -310,15 +322,27 @@ static int si470x_set_seek(struct si470x_device *radio,
 	if (retval < 0)
 		goto done;
 
-	/* wait till seek operation has completed */
-	timeout = jiffies + msecs_to_jiffies(seek_timeout);
-	do {
-		retval = si470x_get_register(radio, STATUSRSSI);
-		if (retval < 0)
-			goto stop;
-		timed_out = time_after(jiffies, timeout);
-	} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
-		(!timed_out));
+	/* currently I2C driver only uses interrupt way to seek */
+	if (radio->stci_enabled) {
+		INIT_COMPLETION(radio->completion);
+
+		/* wait till seek operation has completed */
+		retval = wait_for_completion_timeout(&radio->completion,
+				msecs_to_jiffies(seek_timeout));
+		if (!retval)
+			timed_out = true;
+	} else {
+		/* wait till seek operation has completed */
+		timeout = jiffies + msecs_to_jiffies(seek_timeout);
+		do {
+			retval = si470x_get_register(radio, STATUSRSSI);
+			if (retval < 0)
+				goto stop;
+			timed_out = time_after(jiffies, timeout);
+		} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
+				&& (!timed_out));
+	}
+
 	if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
 		dev_warn(&radio->videodev->dev, "seek does not complete\n");
 	if (radio->registers[STATUSRSSI] & STATUSRSSI_SF)

+ 32 - 31
drivers/media/radio/si470x/radio-si470x-i2c.c

@@ -197,8 +197,9 @@ int si470x_fops_open(struct file *file)
 		if (retval < 0)
 			goto done;
 
-		/* enable RDS interrupt */
+		/* enable RDS / STC interrupt */
 		radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN;
+		radio->registers[SYSCONFIG1] |= SYSCONFIG1_STCIEN;
 		radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_GPIO2;
 		radio->registers[SYSCONFIG1] |= 0x1 << 2;
 		retval = si470x_set_register(radio, SYSCONFIG1);
@@ -261,12 +262,11 @@ int si470x_vidioc_querycap(struct file *file, void *priv,
  **************************************************************************/
 
 /*
- * si470x_i2c_interrupt_work - rds processing function
+ * si470x_i2c_interrupt - interrupt handler
  */
-static void si470x_i2c_interrupt_work(struct work_struct *work)
+static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id)
 {
-	struct si470x_device *radio = container_of(work,
-			struct si470x_device, radio_work);
+	struct si470x_device *radio = dev_id;
 	unsigned char regnr;
 	unsigned char blocknum;
 	unsigned short bler; /* rds block errors */
@@ -274,21 +274,29 @@ static void si470x_i2c_interrupt_work(struct work_struct *work)
 	unsigned char tmpbuf[3];
 	int retval = 0;
 
+	/* check Seek/Tune Complete */
+	retval = si470x_get_register(radio, STATUSRSSI);
+	if (retval < 0)
+		goto end;
+
+	if (radio->registers[STATUSRSSI] & STATUSRSSI_STC)
+		complete(&radio->completion);
+
 	/* safety checks */
 	if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
-		return;
+		goto end;
 
 	/* Update RDS registers */
-	for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) {
+	for (regnr = 1; regnr < RDS_REGISTER_NUM; regnr++) {
 		retval = si470x_get_register(radio, STATUSRSSI + regnr);
 		if (retval < 0)
-			return;
+			goto end;
 	}
 
 	/* get rds blocks */
 	if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0)
 		/* No RDS group ready, better luck next time */
-		return;
+		goto end;
 
 	for (blocknum = 0; blocknum < 4; blocknum++) {
 		switch (blocknum) {
@@ -342,19 +350,8 @@ static void si470x_i2c_interrupt_work(struct work_struct *work)
 
 	if (radio->wr_index != radio->rd_index)
 		wake_up_interruptible(&radio->read_queue);
-}
-
-
-/*
- * si470x_i2c_interrupt - interrupt handler
- */
-static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id)
-{
-	struct si470x_device *radio = dev_id;
-
-	if (!work_pending(&radio->radio_work))
-		schedule_work(&radio->radio_work);
 
+end:
 	return IRQ_HANDLED;
 }
 
@@ -376,7 +373,6 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client,
 		goto err_initial;
 	}
 
-	INIT_WORK(&radio->radio_work, si470x_i2c_interrupt_work);
 	radio->users = 0;
 	radio->client = client;
 	mutex_init(&radio->lock);
@@ -441,7 +437,11 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client,
 	radio->rd_index = 0;
 	init_waitqueue_head(&radio->read_queue);
 
-	retval = request_irq(client->irq, si470x_i2c_interrupt,
+	/* mark Seek/Tune Complete Interrupt enabled */
+	radio->stci_enabled = true;
+	init_completion(&radio->completion);
+
+	retval = request_threaded_irq(client->irq, NULL, si470x_i2c_interrupt,
 			IRQF_TRIGGER_FALLING, DRIVER_NAME, radio);
 	if (retval) {
 		dev_err(&client->dev, "Failed to register interrupt\n");
@@ -479,7 +479,6 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client)
 	struct si470x_device *radio = i2c_get_clientdata(client);
 
 	free_irq(client->irq, radio);
-	cancel_work_sync(&radio->radio_work);
 	video_unregister_device(radio->videodev);
 	kfree(radio);
 
@@ -491,8 +490,9 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client)
 /*
  * si470x_i2c_suspend - suspend the device
  */
-static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+static int si470x_i2c_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct si470x_device *radio = i2c_get_clientdata(client);
 
 	/* power down */
@@ -507,8 +507,9 @@ static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
 /*
  * si470x_i2c_resume - resume the device
  */
-static int si470x_i2c_resume(struct i2c_client *client)
+static int si470x_i2c_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct si470x_device *radio = i2c_get_clientdata(client);
 
 	/* power up : need 110ms */
@@ -519,9 +520,8 @@ static int si470x_i2c_resume(struct i2c_client *client)
 
 	return 0;
 }
-#else
-#define si470x_i2c_suspend	NULL
-#define si470x_i2c_resume	NULL
+
+static SIMPLE_DEV_PM_OPS(si470x_i2c_pm, si470x_i2c_suspend, si470x_i2c_resume);
 #endif
 
 
@@ -532,11 +532,12 @@ static struct i2c_driver si470x_i2c_driver = {
 	.driver = {
 		.name		= "si470x",
 		.owner		= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm		= &si470x_i2c_pm,
+#endif
 	},
 	.probe			= si470x_i2c_probe,
 	.remove			= __devexit_p(si470x_i2c_remove),
-	.suspend		= si470x_i2c_suspend,
-	.resume			= si470x_i2c_resume,
 	.id_table		= si470x_i2c_id,
 };
 

+ 3 - 1
drivers/media/radio/si470x/radio-si470x.h

@@ -158,6 +158,9 @@ struct si470x_device {
 	unsigned int rd_index;
 	unsigned int wr_index;
 
+	struct completion completion;
+	bool stci_enabled;		/* Seek/Tune Complete Interrupt */
+
 #if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE)
 	/* reference to USB and video device */
 	struct usb_device *usbdev;
@@ -179,7 +182,6 @@ struct si470x_device {
 
 #if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE)
 	struct i2c_client *client;
-	struct work_struct radio_work;
 #endif
 };
 

+ 0 - 2
drivers/media/radio/wl128x/fmdrv.h

@@ -55,8 +55,6 @@
 #define FM_DRV_TX_TIMEOUT      (5*HZ)	/* 5 seconds */
 #define FM_DRV_RX_SEEK_TIMEOUT (20*HZ)	/* 20 seconds */
 
-#define NO_OF_ENTRIES_IN_ARRAY(array) (sizeof(array) / sizeof(array[0]))
-
 #define fmerr(format, ...) \
 	printk(KERN_ERR "fmdrv: " format, ## __VA_ARGS__)
 #define fmwarn(format, ...) \

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно