* '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 ...
Unified · Split
| @@ -8,3 +8,4 @@ · 7 unmodified lines | ||
| 8 | 8 | *.dvi |
| 9 | 9 | *.log |
| 10 | 10 | *.out |
| 11 | +media/ | |
| @@ -34,6 +34,14 @@ · 33 unmodified lines | ||
| 34 | 34 | |
| 35 | 35 | <revhistory> |
| 36 | 36 | <!-- Put document revisions here, newest first. --> |
| 37 | +<revision> | |
| 38 | + <revnumber>2.0.4</revnumber> | |
| 39 | + <date>2011-05-06</date> | |
| 40 | + <authorinitials>mcc</authorinitials> | |
| 41 | + <revremark> | |
| 42 | + Add more information about DVB APIv5, better describing the frontend GET/SET props ioctl's. | |
| 43 | + </revremark> | |
| 44 | +</revision> | |
| 37 | 45 | <revision> |
| 38 | 46 | <revnumber>2.0.3</revnumber> |
| 39 | 47 | <date>2010-07-03</date> |
| @@ -1,6 +1,327 @@ | ||
| 1 | −<section id="FE_GET_PROPERTY"> | |
| 1 | +<section id="FE_GET_SET_PROPERTY"> | |
| 2 | 2 | <title>FE_GET_PROPERTY/FE_SET_PROPERTY</title> |
| 3 | 3 | |
| 4 | +<programlisting> | |
| 5 | +/* Reserved fields should be set to 0 */ | |
| 6 | +struct dtv_property { | |
| 7 | + __u32 cmd; | |
| 8 | + union { | |
| 9 | + __u32 data; | |
| 10 | + struct { | |
| 11 | + __u8 data[32]; | |
| 12 | + __u32 len; | |
| 13 | + __u32 reserved1[3]; | |
| 14 | + void *reserved2; | |
| 15 | + } buffer; | |
| 16 | + } u; | |
| 17 | + int result; | |
| 18 | +} __attribute__ ((packed)); | |
| 19 | + | |
| 20 | +/* num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl */ | |
| 21 | +#define DTV_IOCTL_MAX_MSGS 64 | |
| 22 | + | |
| 23 | +struct dtv_properties { | |
| 24 | + __u32 num; | |
| 25 | + struct dtv_property *props; | |
| 26 | +}; | |
| 27 | +</programlisting> | |
| 28 | + | |
| 29 | +<section id="FE_GET_PROPERTY"> | |
| 30 | +<title>FE_GET_PROPERTY</title> | |
| 31 | +<para>DESCRIPTION | |
| 32 | +</para> | |
| 33 | +<informaltable><tgroup cols="1"><tbody><row><entry | |
| 34 | + align="char"> | |
| 35 | +<para>This ioctl call returns one or more frontend properties. This call only | |
| 36 | + requires read-only access to the device.</para> | |
| 37 | +</entry> | |
| 38 | + </row></tbody></tgroup></informaltable> | |
| 39 | +<para>SYNOPSIS | |
| 40 | +</para> | |
| 41 | +<informaltable><tgroup cols="1"><tbody><row><entry | |
| 42 | + align="char"> | |
| 43 | +<para>int ioctl(int fd, int request = <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>, | |
| 44 | + dtv_properties ⋆props);</para> | |
| 45 | +</entry> | |
| 46 | + </row></tbody></tgroup></informaltable> | |
| 47 | +<para>PARAMETERS | |
| 48 | +</para> | |
| 49 | +<informaltable><tgroup cols="2"><tbody><row><entry align="char"> | |
| 50 | +<para>int fd</para> | |
| 51 | +</entry><entry | |
| 52 | + align="char"> | |
| 53 | +<para>File descriptor returned by a previous call to open().</para> | |
| 54 | +</entry> | |
| 55 | + </row><row><entry | |
| 56 | + align="char"> | |
| 57 | +<para>int num</para> | |
| 58 | +</entry><entry | |
| 59 | + align="char"> | |
| 60 | +<para>Equals <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link> for this command.</para> | |
| 61 | +</entry> | |
| 62 | + </row><row><entry | |
| 63 | + align="char"> | |
| 64 | +<para>struct dtv_property *props</para> | |
| 65 | +</entry><entry | |
| 66 | + align="char"> | |
| 67 | +<para>Points to the location where the front-end property commands are stored.</para> | |
| 68 | +</entry> | |
| 69 | + </row></tbody></tgroup></informaltable> | |
| 70 | +<para>ERRORS</para> | |
| 71 | +<informaltable><tgroup cols="2"><tbody><row> | |
| 72 | + <entry align="char"><para>EINVAL</para></entry> | |
| 73 | + <entry align="char"><para>Invalid parameter(s) received or number of parameters out of the range.</para></entry> | |
| 74 | + </row><row> | |
| 75 | + <entry align="char"><para>ENOMEM</para></entry> | |
| 76 | + <entry align="char"><para>Out of memory.</para></entry> | |
| 77 | + </row><row> | |
| 78 | + <entry align="char"><para>EFAULT</para></entry> | |
| 79 | + <entry align="char"><para>Failure while copying data from/to userspace.</para></entry> | |
| 80 | + </row><row> | |
| 81 | + <entry align="char"><para>EOPNOTSUPP</para></entry> | |
| 82 | + <entry align="char"><para>Property type not supported.</para></entry> | |
| 83 | + </row></tbody></tgroup></informaltable> | |
| 84 | +</section> | |
| 85 | + | |
| 86 | +<section id="FE_SET_PROPERTY"> | |
| 87 | +<title>FE_SET_PROPERTY</title> | |
| 88 | +<para>DESCRIPTION | |
| 89 | +</para> | |
| 90 | +<informaltable><tgroup cols="1"><tbody><row><entry | |
| 91 | + align="char"> | |
| 92 | +<para>This ioctl call sets one or more frontend properties. This call only | |
| 93 | + requires read-only access to the device.</para> | |
| 94 | +</entry> | |
| 95 | + </row></tbody></tgroup></informaltable> | |
| 96 | +<para>SYNOPSIS | |
| 97 | +</para> | |
| 98 | +<informaltable><tgroup cols="1"><tbody><row><entry | |
| 99 | + align="char"> | |
| 100 | +<para>int ioctl(int fd, int request = <link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link>, | |
| 101 | + dtv_properties ⋆props);</para> | |
| 102 | +</entry> | |
| 103 | + </row></tbody></tgroup></informaltable> | |
| 104 | +<para>PARAMETERS | |
| 105 | +</para> | |
| 106 | +<informaltable><tgroup cols="2"><tbody><row><entry align="char"> | |
| 107 | +<para>int fd</para> | |
| 108 | +</entry><entry | |
| 109 | + align="char"> | |
| 110 | +<para>File descriptor returned by a previous call to open().</para> | |
| 111 | +</entry> | |
| 112 | + </row><row><entry | |
| 113 | + align="char"> | |
| 114 | +<para>int num</para> | |
| 115 | +</entry><entry | |
| 116 | + align="char"> | |
| 117 | +<para>Equals <link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link> for this command.</para> | |
| 118 | +</entry> | |
| 119 | + </row><row><entry | |
| 120 | + align="char"> | |
| 121 | +<para>struct dtv_property *props</para> | |
| 122 | +</entry><entry | |
| 123 | + align="char"> | |
| 124 | +<para>Points to the location where the front-end property commands are stored.</para> | |
| 125 | +</entry> | |
| 126 | + </row></tbody></tgroup></informaltable> | |
| 127 | +<para>ERRORS | |
| 128 | +</para> | |
| 129 | +<informaltable><tgroup cols="2"><tbody><row> | |
| 130 | + <entry align="char"><para>EINVAL</para></entry> | |
| 131 | + <entry align="char"><para>Invalid parameter(s) received or number of parameters out of the range.</para></entry> | |
| 132 | + </row><row> | |
| 133 | + <entry align="char"><para>ENOMEM</para></entry> | |
| 134 | + <entry align="char"><para>Out of memory.</para></entry> | |
| 135 | + </row><row> | |
| 136 | + <entry align="char"><para>EFAULT</para></entry> | |
| 137 | + <entry align="char"><para>Failure while copying data from/to userspace.</para></entry> | |
| 138 | + </row><row> | |
| 139 | + <entry align="char"><para>EOPNOTSUPP</para></entry> | |
| 140 | + <entry align="char"><para>Property type not supported.</para></entry> | |
| 141 | + </row></tbody></tgroup></informaltable> | |
| 142 | +</section> | |
| 143 | + | |
| 144 | +<para> | |
| 145 | +On <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>/<link linkend="FE_SET_PROPERTY">FE_SET_PROPERTY</link>, | |
| 146 | +the actual action is determined by the dtv_property cmd/data pairs. With one single ioctl, is possible to | |
| 147 | +get/set up to 64 properties. The actual meaning of each property is described on the next sections. | |
| 148 | +</para> | |
| 149 | + | |
| 150 | +<para>The Available frontend property types are:</para> | |
| 151 | +<programlisting> | |
| 152 | +#define DTV_UNDEFINED 0 | |
| 153 | +#define DTV_TUNE 1 | |
| 154 | +#define DTV_CLEAR 2 | |
| 155 | +#define DTV_FREQUENCY 3 | |
| 156 | +#define DTV_MODULATION 4 | |
| 157 | +#define DTV_BANDWIDTH_HZ 5 | |
| 158 | +#define DTV_INVERSION 6 | |
| 159 | +#define DTV_DISEQC_MASTER 7 | |
| 160 | +#define DTV_SYMBOL_RATE 8 | |
| 161 | +#define DTV_INNER_FEC 9 | |
| 162 | +#define DTV_VOLTAGE 10 | |
| 163 | +#define DTV_TONE 11 | |
| 164 | +#define DTV_PILOT 12 | |
| 165 | +#define DTV_ROLLOFF 13 | |
| 166 | +#define DTV_DISEQC_SLAVE_REPLY 14 | |
| 167 | +#define DTV_FE_CAPABILITY_COUNT 15 | |
| 168 | +#define DTV_FE_CAPABILITY 16 | |
| 169 | +#define DTV_DELIVERY_SYSTEM 17 | |
| 170 | +#define DTV_ISDBT_PARTIAL_RECEPTION 18 | |
| 171 | +#define DTV_ISDBT_SOUND_BROADCASTING 19 | |
| 172 | +#define DTV_ISDBT_SB_SUBCHANNEL_ID 20 | |
| 173 | +#define DTV_ISDBT_SB_SEGMENT_IDX 21 | |
| 174 | +#define DTV_ISDBT_SB_SEGMENT_COUNT 22 | |
| 175 | +#define DTV_ISDBT_LAYERA_FEC 23 | |
| 176 | +#define DTV_ISDBT_LAYERA_MODULATION 24 | |
| 177 | +#define DTV_ISDBT_LAYERA_SEGMENT_COUNT 25 | |
| 178 | +#define DTV_ISDBT_LAYERA_TIME_INTERLEAVING 26 | |
| 179 | +#define DTV_ISDBT_LAYERB_FEC 27 | |
| 180 | +#define DTV_ISDBT_LAYERB_MODULATION 28 | |
| 181 | +#define DTV_ISDBT_LAYERB_SEGMENT_COUNT 29 | |
| 182 | +#define DTV_ISDBT_LAYERB_TIME_INTERLEAVING 30 | |
| 183 | +#define DTV_ISDBT_LAYERC_FEC 31 | |
| 184 | +#define DTV_ISDBT_LAYERC_MODULATION 32 | |
| 185 | +#define DTV_ISDBT_LAYERC_SEGMENT_COUNT 33 | |
| 186 | +#define DTV_ISDBT_LAYERC_TIME_INTERLEAVING 34 | |
| 187 | +#define DTV_API_VERSION 35 | |
| 188 | +#define DTV_CODE_RATE_HP 36 | |
| 189 | +#define DTV_CODE_RATE_LP 37 | |
| 190 | +#define DTV_GUARD_INTERVAL 38 | |
| 191 | +#define DTV_TRANSMISSION_MODE 39 | |
| 192 | +#define DTV_HIERARCHY 40 | |
| 193 | +#define DTV_ISDBT_LAYER_ENABLED 41 | |
| 194 | +#define DTV_ISDBS_TS_ID 42 | |
| 195 | +</programlisting> | |
| 196 | + | |
| 197 | +<section id="fe_property_common"> | |
| 198 | + <title>Parameters that are common to all Digital TV standards</title> | |
| 199 | + <section id="DTV_FREQUENCY"> | |
| 200 | + <title><constant>DTV_FREQUENCY</constant></title> | |
| 201 | + | |
| 202 | + <para>Central frequency of the channel, in HZ.</para> | |
| 203 | + | |
| 204 | + <para>Notes:</para> | |
| 205 | + <para>1)For ISDB-T, the channels are usually transmitted with an offset of 143kHz. | |
| 206 | + E.g. a valid frequncy could be 474143 kHz. The stepping is bound to the bandwidth of | |
| 207 | + the channel which is 6MHz.</para> | |
| 208 | + | |
| 209 | + <para>2)As in ISDB-Tsb the channel consists of only one or three segments the | |
| 210 | + frequency step is 429kHz, 3*429 respectively. As for ISDB-T the | |
| 211 | + central frequency of the channel is expected.</para> | |
| 212 | + </section> | |
| 213 | + | |
| 214 | + <section id="DTV_BANDWIDTH_HZ"> | |
| 215 | + <title><constant>DTV_BANDWIDTH_HZ</constant></title> | |
| 216 | + | |
| 217 | + <para>Bandwidth for the channel, in HZ.</para> | |
| 218 | + | |
| 219 | + <para>Possible values: | |
| 220 | + <constant>1712000</constant>, | |
| 221 | + <constant>5000000</constant>, | |
| 222 | + <constant>6000000</constant>, | |
| 223 | + <constant>7000000</constant>, | |
| 224 | + <constant>8000000</constant>, | |
| 225 | + <constant>10000000</constant>. | |
| 226 | + </para> | |
| 227 | + | |
| 228 | + <para>Notes:</para> | |
| 229 | + | |
| 230 | + <para>1) For ISDB-T it should be always 6000000Hz (6MHz)</para> | |
| 231 | + <para>2) For ISDB-Tsb it can vary depending on the number of connected segments</para> | |
| 232 | + <para>3) Bandwidth doesn't apply for DVB-C transmissions, as the bandwidth | |
| 233 | + for DVB-C depends on the symbol rate</para> | |
| 234 | + <para>4) Bandwidth in ISDB-T is fixed (6MHz) or can be easily derived from | |
| 235 | + other parameters (DTV_ISDBT_SB_SEGMENT_IDX, | |
| 236 | + DTV_ISDBT_SB_SEGMENT_COUNT).</para> | |
| 237 | + <para>5) DVB-T supports 6, 7 and 8MHz.</para> | |
| 238 | + <para>6) In addition, DVB-T2 supports 1.172, 5 and 10MHz.</para> | |
| 239 | + </section> | |
| 240 | + | |
| 241 | + <section id="DTV_DELIVERY_SYSTEM"> | |
| 242 | + <title><constant>DTV_DELIVERY_SYSTEM</constant></title> | |
| 243 | + | |
| 244 | + <para>Specifies the type of Delivery system</para> | |
| 245 | + | |
| 246 | + <para>Possible values: </para> | |
| 247 | +<programlisting> | |
| 248 | +typedef enum fe_delivery_system { | |
| 249 | + SYS_UNDEFINED, | |
| 250 | + SYS_DVBC_ANNEX_AC, | |
| 251 | + SYS_DVBC_ANNEX_B, | |
| 252 | + SYS_DVBT, | |
| 253 | + SYS_DSS, | |
| 254 | + SYS_DVBS, | |
| 255 | + SYS_DVBS2, | |
| 256 | + SYS_DVBH, | |
| 257 | + SYS_ISDBT, | |
| 258 | + SYS_ISDBS, | |
| 259 | + SYS_ISDBC, | |
| 260 | + SYS_ATSC, | |
| 261 | + SYS_ATSCMH, | |
| 262 | + SYS_DMBTH, | |
| 263 | + SYS_CMMB, | |
| 264 | + SYS_DAB, | |
| 265 | + SYS_DVBT2, | |
| 266 | +} fe_delivery_system_t; | |
| 267 | +</programlisting> | |
| 268 | + | |
| 269 | + </section> | |
| 270 | + | |
| 271 | + <section id="DTV_TRANSMISSION_MODE"> | |
| 272 | + <title><constant>DTV_TRANSMISSION_MODE</constant></title> | |
| 273 | + | |
| 274 | + <para>Specifies the number of carriers used by the standard</para> | |
| 275 | + | |
| 276 | + <para>Possible values are:</para> | |
| 277 | +<programlisting> | |
| 278 | +typedef enum fe_transmit_mode { | |
| 279 | + TRANSMISSION_MODE_2K, | |
| 280 | + TRANSMISSION_MODE_8K, | |
| 281 | + TRANSMISSION_MODE_AUTO, | |
| 282 | + TRANSMISSION_MODE_4K, | |
| 283 | + TRANSMISSION_MODE_1K, | |
| 284 | + TRANSMISSION_MODE_16K, | |
| 285 | + TRANSMISSION_MODE_32K, | |
| 286 | +} fe_transmit_mode_t; | |
| 287 | +</programlisting> | |
| 288 | + | |
| 289 | + <para>Notes:</para> | |
| 290 | + <para>1) ISDB-T supports three carrier/symbol-size: 8K, 4K, 2K. It is called | |
| 291 | + 'mode' in the standard: Mode 1 is 2K, mode 2 is 4K, mode 3 is 8K</para> | |
| 292 | + | |
| 293 | + <para>2) If <constant>DTV_TRANSMISSION_MODE</constant> is set the <constant>TRANSMISSION_MODE_AUTO</constant> the | |
| 294 | + hardware will try to find the correct FFT-size (if capable) and will | |
| 295 | + use TMCC to fill in the missing parameters.</para> | |
| 296 | + <para>3) DVB-T specifies 2K and 8K as valid sizes.</para> | |
| 297 | + <para>4) DVB-T2 specifies 1K, 2K, 4K, 8K, 16K and 32K.</para> | |
| 298 | + </section> | |
| 299 | + | |
| 300 | + <section id="DTV_GUARD_INTERVAL"> | |
| 301 | + <title><constant>DTV_GUARD_INTERVAL</constant></title> | |
| 302 | + | |
| 303 | + <para>Possible values are:</para> | |
| 304 | +<programlisting> | |
| 305 | +typedef enum fe_guard_interval { | |
| 306 | + GUARD_INTERVAL_1_32, | |
| 307 | + GUARD_INTERVAL_1_16, | |
| 308 | + GUARD_INTERVAL_1_8, | |
| 309 | + GUARD_INTERVAL_1_4, | |
| 310 | + GUARD_INTERVAL_AUTO, | |
| 311 | + GUARD_INTERVAL_1_128, | |
| 312 | + GUARD_INTERVAL_19_128, | |
| 313 | + GUARD_INTERVAL_19_256, | |
| 314 | +} fe_guard_interval_t; | |
| 315 | +</programlisting> | |
| 316 | + | |
| 317 | + <para>Notes:</para> | |
| 318 | + <para>1) If <constant>DTV_GUARD_INTERVAL</constant> is set the <constant>GUARD_INTERVAL_AUTO</constant> the hardware will | |
| 319 | + try to find the correct guard interval (if capable) and will use TMCC to fill | |
| 320 | + in the missing parameters.</para> | |
| 321 | + <para>2) Intervals 1/128, 19/128 and 19/256 are used only for DVB-T2 at present</para> | |
| 322 | + </section> | |
| 323 | +</section> | |
| 324 | + | |
| 4 | 325 | <section id="isdbt"> |
| 5 | 326 | <title>ISDB-T frontend</title> |
| 6 | 327 | <para>This section describes shortly what are the possible parameters in the Linux |
| @@ -32,73 +353,6 @@ · 25 unmodified lines | ||
| 32 | 353 | |
| 33 | 354 | <para>Parameters used by ISDB-T and ISDB-Tsb.</para> |
| 34 | 355 | |
| 35 | − <section id="isdbt-parms"> | |
| 36 | − <title>Parameters that are common with DVB-T and ATSC</title> | |
| 37 | − | |
| 38 | − <section id="isdbt-freq"> | |
| 39 | − <title><constant>DTV_FREQUENCY</constant></title> | |
| 40 | − | |
| 41 | − <para>Central frequency of the channel.</para> | |
| 42 | − | |
| 43 | − <para>For ISDB-T the channels are usually transmitted with an offset of 143kHz. E.g. a | |
| 44 | − valid frequncy could be 474143 kHz. The stepping is bound to the bandwidth of | |
| 45 | − the channel which is 6MHz.</para> | |
| 46 | − | |
| 47 | − <para>As in ISDB-Tsb the channel consists of only one or three segments the | |
| 48 | − frequency step is 429kHz, 3*429 respectively. As for ISDB-T the | |
| 49 | − central frequency of the channel is expected.</para> | |
| 50 | − </section> | |
| 51 | − | |
| 52 | − <section id="isdbt-bw"> | |
| 53 | − <title><constant>DTV_BANDWIDTH_HZ</constant> (optional)</title> | |
| 54 | − | |
| 55 | − <para>Possible values:</para> | |
| 56 | − | |
| 57 | − <para>For ISDB-T it should be always 6000000Hz (6MHz)</para> | |
| 58 | − <para>For ISDB-Tsb it can vary depending on the number of connected segments</para> | |
| 59 | − | |
| 60 | − <para>Note: Hardware specific values might be given here, but standard | |
| 61 | − applications should not bother to set a value to this field as | |
| 62 | − standard demods are ignoring it anyway.</para> | |
| 63 | − | |
| 64 | − <para>Bandwidth in ISDB-T is fixed (6MHz) or can be easily derived from | |
| 65 | − other parameters (DTV_ISDBT_SB_SEGMENT_IDX, | |
| 66 | − DTV_ISDBT_SB_SEGMENT_COUNT).</para> | |
| 67 | − </section> | |
| 68 | − | |
| 69 | − <section id="isdbt-delivery-sys"> | |
| 70 | − <title><constant>DTV_DELIVERY_SYSTEM</constant></title> | |
| 71 | − | |
| 72 | − <para>Possible values: <constant>SYS_ISDBT</constant></para> | |
| 73 | − </section> | |
| 74 | − | |
| 75 | − <section id="isdbt-tx-mode"> | |
| 76 | − <title><constant>DTV_TRANSMISSION_MODE</constant></title> | |
| 77 | − | |
| 78 | − <para>ISDB-T supports three carrier/symbol-size: 8K, 4K, 2K. It is called | |
| 79 | − 'mode' in the standard: Mode 1 is 2K, mode 2 is 4K, mode 3 is 8K</para> | |
| 80 | − | |
| 81 | − <para>Possible values: <constant>TRANSMISSION_MODE_2K</constant>, <constant>TRANSMISSION_MODE_8K</constant>, | |
| 82 | − <constant>TRANSMISSION_MODE_AUTO</constant>, <constant>TRANSMISSION_MODE_4K</constant></para> | |
| 83 | − | |
| 84 | − <para>If <constant>DTV_TRANSMISSION_MODE</constant> is set the <constant>TRANSMISSION_MODE_AUTO</constant> the | |
| 85 | − hardware will try to find the correct FFT-size (if capable) and will | |
| 86 | − use TMCC to fill in the missing parameters.</para> | |
| 87 | − | |
| 88 | − <para><constant>TRANSMISSION_MODE_4K</constant> is added at the same time as the other new parameters.</para> | |
| 89 | − </section> | |
| 90 | − | |
| 91 | − <section id="isdbt-guard-interval"> | |
| 92 | − <title><constant>DTV_GUARD_INTERVAL</constant></title> | |
| 93 | − | |
| 94 | − <para>Possible values: <constant>GUARD_INTERVAL_1_32</constant>, <constant>GUARD_INTERVAL_1_16</constant>, <constant>GUARD_INTERVAL_1_8</constant>, | |
| 95 | − <constant>GUARD_INTERVAL_1_4</constant>, <constant>GUARD_INTERVAL_AUTO</constant></para> | |
| 96 | − | |
| 97 | − <para>If <constant>DTV_GUARD_INTERVAL</constant> is set the <constant>GUARD_INTERVAL_AUTO</constant> the hardware will | |
| 98 | − try to find the correct guard interval (if capable) and will use TMCC to fill | |
| 99 | − in the missing parameters.</para> | |
| 100 | − </section> | |
| 101 | − </section> | |
| 102 | 356 | <section id="isdbt-new-parms"> |
| 103 | 357 | <title>ISDB-T only parameters</title> |
| 104 | 358 | |
| @@ -314,5 +568,20 @@ · 209 unmodified lines | ||
| 314 | 568 | </section> |
| 315 | 569 | </section> |
| 316 | 570 | </section> |
| 571 | + <section id="dvbt2-params"> | |
| 572 | + <title>DVB-T2 parameters</title> | |
| 573 | + | |
| 574 | + <para>This section covers parameters that apply only to the DVB-T2 delivery method. DVB-T2 | |
| 575 | + support is currently in the early stages development so expect this section to grow | |
| 576 | + and become more detailed with time.</para> | |
| 577 | + | |
| 578 | + <section id="dvbt2-plp-id"> | |
| 579 | + <title><constant>DTV_DVBT2_PLP_ID</constant></title> | |
| 580 | + | |
| 581 | + <para>DVB-T2 supports Physical Layer Pipes (PLP) to allow transmission of | |
| 582 | + many data types via a single multiplex. The API will soon support this | |
| 583 | + at which point this section will be expanded.</para> | |
| 584 | + </section> | |
| 585 | + </section> | |
| 317 | 586 | </section> |
| 318 | 587 | </section> |
| @@ -176,14 +176,20 @@ typedef enum fe_transmit_mode { · 175 unmodified lines | ||
| 176 | 176 | TRANSMISSION_MODE_2K, |
| 177 | 177 | TRANSMISSION_MODE_8K, |
| 178 | 178 | TRANSMISSION_MODE_AUTO, |
| 179 | − TRANSMISSION_MODE_4K | |
| 179 | + TRANSMISSION_MODE_4K, | |
| 180 | + TRANSMISSION_MODE_1K, | |
| 181 | + TRANSMISSION_MODE_16K, | |
| 182 | + TRANSMISSION_MODE_32K, | |
| 180 | 183 | } fe_transmit_mode_t; |
| 181 | 184 | |
| 182 | 185 | typedef enum fe_bandwidth { |
| 183 | 186 | BANDWIDTH_8_MHZ, |
| 184 | 187 | BANDWIDTH_7_MHZ, |
| 185 | 188 | BANDWIDTH_6_MHZ, |
| 186 | − BANDWIDTH_AUTO | |
| 189 | + BANDWIDTH_AUTO, | |
| 190 | + BANDWIDTH_5_MHZ, | |
| 191 | + BANDWIDTH_10_MHZ, | |
| 192 | + BANDWIDTH_1_712_MHZ, | |
| 187 | 193 | } fe_bandwidth_t; |
| 188 | 194 | |
| 189 | 195 | |
| @@ -192,7 +198,10 @@ typedef enum fe_guard_interval { · 2 unmodified lines | ||
| 192 | 198 | GUARD_INTERVAL_1_16, |
| 193 | 199 | GUARD_INTERVAL_1_8, |
| 194 | 200 | GUARD_INTERVAL_1_4, |
| 195 | − GUARD_INTERVAL_AUTO | |
| 201 | + GUARD_INTERVAL_AUTO, | |
| 202 | + GUARD_INTERVAL_1_128, | |
| 203 | + GUARD_INTERVAL_19_128, | |
| 204 | + GUARD_INTERVAL_19_256, | |
| 196 | 205 | } fe_guard_interval_t; |
| 197 | 206 | |
| 198 | 207 | |
| @@ -306,7 +315,9 @@ struct dvb_frontend_event { · 107 unmodified lines | ||
| 306 | 315 | |
| 307 | 316 | #define DTV_ISDBS_TS_ID 42 |
| 308 | 317 | |
| 309 | −#define DTV_MAX_COMMAND DTV_ISDBS_TS_ID | |
| 318 | +#define DTV_DVBT2_PLP_ID 43 | |
| 319 | + | |
| 320 | +#define DTV_MAX_COMMAND DTV_DVBT2_PLP_ID | |
| 310 | 321 | |
| 311 | 322 | typedef enum fe_pilot { |
| 312 | 323 | PILOT_ON, |
| @@ -338,6 +349,7 @@ typedef enum fe_delivery_system { · 25 unmodified lines | ||
| 338 | 349 | SYS_DMBTH, |
| 339 | 350 | SYS_CMMB, |
| 340 | 351 | SYS_DAB, |
| 352 | + SYS_DVBT2, | |
| 341 | 353 | } fe_delivery_system_t; |
| 342 | 354 | |
| 343 | 355 | struct dtv_cmds_h { |
| @@ -270,6 +270,7 @@ · 269 unmodified lines | ||
| 270 | 270 | <!ENTITY sub-write SYSTEM "v4l/func-write.xml"> |
| 271 | 271 | <!ENTITY sub-io SYSTEM "v4l/io.xml"> |
| 272 | 272 | <!ENTITY sub-grey SYSTEM "v4l/pixfmt-grey.xml"> |
| 273 | +<!ENTITY sub-m420 SYSTEM "v4l/pixfmt-m420.xml"> | |
| 273 | 274 | <!ENTITY sub-nv12 SYSTEM "v4l/pixfmt-nv12.xml"> |
| 274 | 275 | <!ENTITY sub-nv12m SYSTEM "v4l/pixfmt-nv12m.xml"> |
| 275 | 276 | <!ENTITY sub-nv12mt SYSTEM "v4l/pixfmt-nv12mt.xml"> |
| @@ -295,6 +296,7 @@ · 19 unmodified lines | ||
| 295 | 296 | <!ENTITY sub-srggb8 SYSTEM "v4l/pixfmt-srggb8.xml"> |
| 296 | 297 | <!ENTITY sub-y10 SYSTEM "v4l/pixfmt-y10.xml"> |
| 297 | 298 | <!ENTITY sub-y12 SYSTEM "v4l/pixfmt-y12.xml"> |
| 299 | +<!ENTITY sub-y10b SYSTEM "v4l/pixfmt-y10b.xml"> | |
| 298 | 300 | <!ENTITY sub-pixfmt SYSTEM "v4l/pixfmt.xml"> |
| 299 | 301 | <!ENTITY sub-cropcap SYSTEM "v4l/vidioc-cropcap.xml"> |
| 300 | 302 | <!ENTITY sub-dbg-g-register SYSTEM "v4l/vidioc-dbg-g-register.xml"> |
| @@ -0,0 +1,147 @@ | ||
| 1 | + <refentry id="V4L2-PIX-FMT-M420"> | |
| 2 | + <refmeta> | |
| 3 | + <refentrytitle>V4L2_PIX_FMT_M420 ('M420')</refentrytitle> | |
| 4 | + &manvol; | |
| 5 | + </refmeta> | |
| 6 | + <refnamediv> | |
| 7 | + <refname><constant>V4L2_PIX_FMT_M420</constant></refname> | |
| 8 | + <refpurpose>Format with ½ horizontal and vertical chroma | |
| 9 | + resolution, also known as YUV 4:2:0. Hybrid plane line-interleaved | |
| 10 | + layout.</refpurpose> | |
| 11 | + </refnamediv> | |
| 12 | + <refsect1> | |
| 13 | + <title>Description</title> | |
| 14 | + | |
| 15 | + <para>M420 is a YUV format with ½ horizontal and vertical chroma | |
| 16 | + subsampling (YUV 4:2:0). Pixels are organized as interleaved luma and | |
| 17 | + chroma planes. Two lines of luma data are followed by one line of chroma | |
| 18 | + data.</para> | |
| 19 | + <para>The luma plane has one byte per pixel. The chroma plane contains | |
| 20 | + interleaved CbCr pixels subsampled by ½ in the horizontal and | |
| 21 | + vertical directions. Each CbCr pair belongs to four pixels. For example, | |
| 22 | +Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to | |
| 23 | +Y'<subscript>00</subscript>, Y'<subscript>01</subscript>, | |
| 24 | +Y'<subscript>10</subscript>, Y'<subscript>11</subscript>.</para> | |
| 25 | + | |
| 26 | + <para>All line lengths are identical: if the Y lines include pad bytes | |
| 27 | + so do the CbCr lines.</para> | |
| 28 | + | |
| 29 | + <example> | |
| 30 | + <title><constant>V4L2_PIX_FMT_M420</constant> 4 × 4 | |
| 31 | +pixel image</title> | |
| 32 | + | |
| 33 | + <formalpara> | |
| 34 | + <title>Byte Order.</title> | |
| 35 | + <para>Each cell is one byte. | |
| 36 | + <informaltable frame="none"> | |
| 37 | + <tgroup cols="5" align="center"> | |
| 38 | + <colspec align="left" colwidth="2*" /> | |
| 39 | + <tbody valign="top"> | |
| 40 | + <row> | |
| 41 | + <entry>start + 0:</entry> | |
| 42 | + <entry>Y'<subscript>00</subscript></entry> | |
| 43 | + <entry>Y'<subscript>01</subscript></entry> | |
| 44 | + <entry>Y'<subscript>02</subscript></entry> | |
| 45 | + <entry>Y'<subscript>03</subscript></entry> | |
| 46 | + </row> | |
| 47 | + <row> | |
| 48 | + <entry>start + 4:</entry> | |
| 49 | + <entry>Y'<subscript>10</subscript></entry> | |
| 50 | + <entry>Y'<subscript>11</subscript></entry> | |
| 51 | + <entry>Y'<subscript>12</subscript></entry> | |
| 52 | + <entry>Y'<subscript>13</subscript></entry> | |
| 53 | + </row> | |
| 54 | + <row> | |
| 55 | + <entry>start + 8:</entry> | |
| 56 | + <entry>Cb<subscript>00</subscript></entry> | |
| 57 | + <entry>Cr<subscript>00</subscript></entry> | |
| 58 | + <entry>Cb<subscript>01</subscript></entry> | |
| 59 | + <entry>Cr<subscript>01</subscript></entry> | |
| 60 | + </row> | |
| 61 | + <row> | |
| 62 | + <entry>start + 16:</entry> | |
| 63 | + <entry>Y'<subscript>20</subscript></entry> | |
| 64 | + <entry>Y'<subscript>21</subscript></entry> | |
| 65 | + <entry>Y'<subscript>22</subscript></entry> | |
| 66 | + <entry>Y'<subscript>23</subscript></entry> | |
| 67 | + </row> | |
| 68 | + <row> | |
| 69 | + <entry>start + 20:</entry> | |
| 70 | + <entry>Y'<subscript>30</subscript></entry> | |
| 71 | + <entry>Y'<subscript>31</subscript></entry> | |
| 72 | + <entry>Y'<subscript>32</subscript></entry> | |
| 73 | + <entry>Y'<subscript>33</subscript></entry> | |
| 74 | + </row> | |
| 75 | + <row> | |
| 76 | + <entry>start + 24:</entry> | |
| 77 | + <entry>Cb<subscript>10</subscript></entry> | |
| 78 | + <entry>Cr<subscript>10</subscript></entry> | |
| 79 | + <entry>Cb<subscript>11</subscript></entry> | |
| 80 | + <entry>Cr<subscript>11</subscript></entry> | |
| 81 | + </row> | |
| 82 | + </tbody> | |
| 83 | + </tgroup> | |
| 84 | + </informaltable> | |
| 85 | + </para> | |
| 86 | + </formalpara> | |
| 87 | + | |
| 88 | + <formalpara> | |
| 89 | + <title>Color Sample Location.</title> | |
| 90 | + <para> | |
| 91 | + <informaltable frame="none"> | |
| 92 | + <tgroup cols="7" align="center"> | |
| 93 | + <tbody valign="top"> | |
| 94 | + <row> | |
| 95 | + <entry></entry> | |
| 96 | + <entry>0</entry><entry></entry><entry>1</entry><entry></entry> | |
| 97 | + <entry>2</entry><entry></entry><entry>3</entry> | |
| 98 | + </row> | |
| 99 | + <row> | |
| 100 | + <entry>0</entry> | |
| 101 | + <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry> | |
| 102 | + <entry>Y</entry><entry></entry><entry>Y</entry> | |
| 103 | + </row> | |
| 104 | + <row> | |
| 105 | + <entry></entry> | |
| 106 | + <entry></entry><entry>C</entry><entry></entry><entry></entry> | |
| 107 | + <entry></entry><entry>C</entry><entry></entry> | |
| 108 | + </row> | |
| 109 | + <row> | |
| 110 | + <entry>1</entry> | |
| 111 | + <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry> | |
| 112 | + <entry>Y</entry><entry></entry><entry>Y</entry> | |
| 113 | + </row> | |
| 114 | + <row> | |
| 115 | + <entry></entry> | |
| 116 | + </row> | |
| 117 | + <row> | |
| 118 | + <entry>2</entry> | |
| 119 | + <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry> | |
| 120 | + <entry>Y</entry><entry></entry><entry>Y</entry> | |
| 121 | + </row> | |
| 122 | + <row> | |
| 123 | + <entry></entry> | |
| 124 | + <entry></entry><entry>C</entry><entry></entry><entry></entry> | |
| 125 | + <entry></entry><entry>C</entry><entry></entry> | |
| 126 | + </row> | |
| 127 | + <row> | |
| 128 | + <entry>3</entry> | |
| 129 | + <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry> | |
| 130 | + <entry>Y</entry><entry></entry><entry>Y</entry> | |
| 131 | + </row> | |
| 132 | + </tbody> | |
| 133 | + </tgroup> | |
| 134 | + </informaltable> | |
| 135 | + </para> | |
| 136 | + </formalpara> | |
| 137 | + </example> | |
| 138 | + </refsect1> | |
| 139 | + </refentry> | |
| 140 | + | |
| 141 | + <!-- | |
| 142 | +Local Variables: | |
| 143 | +mode: sgml | |
| 144 | +sgml-parent-document: "pixfmt.sgml" | |
| 145 | +indent-tabs-mode: nil | |
| 146 | +End: | |
| 147 | + --> | |
| @@ -0,0 +1,43 @@ | ||
| 1 | +<refentry id="V4L2-PIX-FMT-Y10BPACK"> | |
| 2 | + <refmeta> | |
| 3 | + <refentrytitle>V4L2_PIX_FMT_Y10BPACK ('Y10B')</refentrytitle> | |
| 4 | + &manvol; | |
| 5 | + </refmeta> | |
| 6 | + <refnamediv> | |
| 7 | + <refname><constant>V4L2_PIX_FMT_Y10BPACK</constant></refname> | |
| 8 | + <refpurpose>Grey-scale image as a bit-packed array</refpurpose> | |
| 9 | + </refnamediv> | |
| 10 | + <refsect1> | |
| 11 | + <title>Description</title> | |
| 12 | + | |
| 13 | + <para>This is a packed grey-scale image format with a depth of 10 bits per | |
| 14 | + pixel. Pixels are stored in a bit-packed array of 10bit bits per pixel, | |
| 15 | + with no padding between them and with the most significant bits coming | |
| 16 | + first from the left.</para> | |
| 17 | + | |
| 18 | + <example> | |
| 19 | + <title><constant>V4L2_PIX_FMT_Y10BPACK</constant> 4 pixel data stream taking 5 bytes</title> | |
| 20 | + | |
| 21 | + <formalpara> | |
| 22 | + <title>Bit-packed representation</title> | |
| 23 | + <para>pixels cross the byte boundary and have a ratio of 5 bytes for each 4 | |
| 24 | + pixels. | |
| 25 | + <informaltable frame="all"> | |
| 26 | + <tgroup cols="5" align="center"> | |
| 27 | + <colspec align="left" colwidth="2*" /> | |
| 28 | + <tbody valign="top"> | |
| 29 | + <row> | |
| 30 | + <entry>Y'<subscript>00[9:2]</subscript></entry> | |
| 31 | + <entry>Y'<subscript>00[1:0]</subscript>Y'<subscript>01[9:4]</subscript></entry> | |
| 32 | + <entry>Y'<subscript>01[3:0]</subscript>Y'<subscript>02[9:6]</subscript></entry> | |
| 33 | + <entry>Y'<subscript>02[5:0]</subscript>Y'<subscript>03[9:8]</subscript></entry> | |
| 34 | + <entry>Y'<subscript>03[7:0]</subscript></entry> | |
| 35 | + </row> | |
| 36 | + </tbody> | |
| 37 | + </tgroup> | |
| 38 | + </informaltable> | |
| 39 | + </para> | |
| 40 | + </formalpara> | |
| 41 | + </example> | |
| 42 | + </refsect1> | |
| 43 | +</refentry> | |
| @@ -697,6 +697,7 @@ information.</para> · 696 unmodified lines | ||
| 697 | 697 | &sub-grey; |
| 698 | 698 | &sub-y10; |
| 699 | 699 | &sub-y12; |
| 700 | + &sub-y10b; | |
| 700 | 701 | &sub-y16; |
| 701 | 702 | &sub-yuyv; |
| 702 | 703 | &sub-uyvy; |
| @@ -712,6 +713,7 @@ information.</para> · 9 unmodified lines | ||
| 712 | 713 | &sub-nv12m; |
| 713 | 714 | &sub-nv12mt; |
| 714 | 715 | &sub-nv16; |
| 716 | + &sub-m420; | |
| 715 | 717 | </section> |
| 716 | 718 | |
| 717 | 719 | <section> |
| @@ -2522,5 +2522,51 @@ · 2521 unmodified lines | ||
| 2522 | 2522 | </tgroup> |
| 2523 | 2523 | </table> |
| 2524 | 2524 | </section> |
| 2525 | + | |
| 2526 | + <section> | |
| 2527 | + <title>JPEG Compressed Formats</title> | |
| 2528 | + | |
| 2529 | + <para>Those data formats consist of an ordered sequence of 8-bit bytes | |
| 2530 | + obtained from JPEG compression process. Additionally to the | |
| 2531 | + <constant>_JPEG</constant> prefix the format code is made of | |
| 2532 | + the following information. | |
| 2533 | + <itemizedlist> | |
| 2534 | + <listitem>The number of bus samples per entropy encoded byte.</listitem> | |
| 2535 | + <listitem>The bus width.</listitem> | |
| 2536 | + </itemizedlist> | |
| 2537 | + | |
| 2538 | + <para>For instance, for a JPEG baseline process and an 8-bit bus width | |
| 2539 | + the format will be named <constant>V4L2_MBUS_FMT_JPEG_1X8</constant>. | |
| 2540 | + </para> | |
| 2541 | + </para> | |
| 2542 | + | |
| 2543 | + <para>The following table lists existing JPEG compressed formats.</para> | |
| 2544 | + | |
| 2545 | + <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-jpeg"> | |
| 2546 | + <title>JPEG Formats</title> | |
| 2547 | + <tgroup cols="3"> | |
| 2548 | + <colspec colname="id" align="left" /> | |
| 2549 | + <colspec colname="code" align="left"/> | |
| 2550 | + <colspec colname="remarks" align="left"/> | |
| 2551 | + <thead> | |
| 2552 | + <row> | |
| 2553 | + <entry>Identifier</entry> | |
| 2554 | + <entry>Code</entry> | |
| 2555 | + <entry>Remarks</entry> | |
| 2556 | + </row> | |
| 2557 | + </thead> | |
| 2558 | + <tbody valign="top"> | |
| 2559 | + <row id="V4L2-MBUS-FMT-JPEG-1X8"> | |
| 2560 | + <entry>V4L2_MBUS_FMT_JPEG_1X8</entry> | |
| 2561 | + <entry>0x4001</entry> | |
| 2562 | + <entry>Besides of its usage for the parallel bus this format is | |
| 2563 | + recommended for transmission of JPEG data over MIPI CSI bus | |
| 2564 | + using the User Defined 8-bit Data types. | |
| 2565 | + </entry> | |
| 2566 | + </row> | |
| 2567 | + </tbody> | |
| 2568 | + </tgroup> | |
| 2569 | + </table> | |
| 2570 | + </section> | |
| 2525 | 2571 | </section> |
| 2526 | 2572 | </section> |
| @@ -311,6 +311,9 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> { · 310 unmodified lines | ||
| 311 | 311 | #define <link linkend="V4L2-PIX-FMT-Y10">V4L2_PIX_FMT_Y10</link> v4l2_fourcc('Y', '1', '0', ' ') /* 10 Greyscale */ |
| 312 | 312 | #define <link linkend="V4L2-PIX-FMT-Y16">V4L2_PIX_FMT_Y16</link> v4l2_fourcc('Y', '1', '6', ' ') /* 16 Greyscale */ |
| 313 | 313 | |
| 314 | +/* Grey bit-packed formats */ | |
| 315 | +#define <link linkend="V4L2-PIX-FMT-Y10BPACK">V4L2_PIX_FMT_Y10BPACK</link> v4l2_fourcc('Y', '1', '0', 'B') /* 10 Greyscale bit-packed */ | |
| 316 | + | |
| 314 | 317 | /* Palette formats */ |
| 315 | 318 | #define <link linkend="V4L2-PIX-FMT-PAL8">V4L2_PIX_FMT_PAL8</link> v4l2_fourcc('P', 'A', 'L', '8') /* 8 8-bit palette */ |
| 316 | 319 | |
| @@ -333,6 +336,7 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> { · 16 unmodified lines | ||
| 333 | 336 | #define <link linkend="V4L2-PIX-FMT-YUV420">V4L2_PIX_FMT_YUV420</link> v4l2_fourcc('Y', 'U', '1', '2') /* 12 YUV 4:2:0 */ |
| 334 | 337 | #define <link linkend="V4L2-PIX-FMT-HI240">V4L2_PIX_FMT_HI240</link> v4l2_fourcc('H', 'I', '2', '4') /* 8 8-bit color */ |
| 335 | 338 | #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 */ |
| 339 | +#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 */ | |
| 336 | 340 | |
| 337 | 341 | /* two planes -- one Y, one Cr + Cb interleaved */ |
| 338 | 342 | #define <link linkend="V4L2-PIX-FMT-NV12">V4L2_PIX_FMT_NV12</link> v4l2_fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */ |
| @@ -551,3 +551,26 @@ Why: These legacy callbacks should no longer be used as i2c-core offers · 550 unmodified lines | ||
| 551 | 551 | Who: Jean Delvare <khali@linux-fr.org> |
| 552 | 552 | |
| 553 | 553 | ---------------------------- |
| 554 | + | |
| 555 | +What: Support for UVCIOC_CTRL_ADD in the uvcvideo driver | |
| 556 | +When: 2.6.42 | |
| 557 | +Why: The information passed to the driver by this ioctl is now queried | |
| 558 | + dynamically from the device. | |
| 559 | +Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | |
| 560 | + | |
| 561 | +---------------------------- | |
| 562 | + | |
| 563 | +What: Support for UVCIOC_CTRL_MAP_OLD in the uvcvideo driver | |
| 564 | +When: 2.6.42 | |
| 565 | +Why: Used only by applications compiled against older driver versions. | |
| 566 | + Superseded by UVCIOC_CTRL_MAP which supports V4L2 menu controls. | |
| 567 | +Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | |
| 568 | + | |
| 569 | +---------------------------- | |
| 570 | + | |
| 571 | +What: Support for UVCIOC_CTRL_GET and UVCIOC_CTRL_SET in the uvcvideo driver | |
| 572 | +When: 2.6.42 | |
| 573 | +Why: Superseded by the UVCIOC_CTRL_QUERY ioctl. | |
| 574 | +Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | |
| 575 | + | |
| 576 | +---------------------------- | |
| @@ -166,7 +166,6 @@ Code Seq#(hex) Include File Comments · 165 unmodified lines | ||
| 166 | 166 | 'T' all arch/x86/include/asm/ioctls.h conflict! |
| 167 | 167 | 'T' C0-DF linux/if_tun.h conflict! |
| 168 | 168 | 'U' all sound/asound.h conflict! |
| 169 | −'U' 00-0F drivers/media/video/uvc/uvcvideo.h conflict! | |
| 170 | 169 | 'U' 00-CF linux/uinput.h conflict! |
| 171 | 170 | 'U' 00-EF linux/usbdevice_fs.h |
| 172 | 171 | 'U' C0-CF drivers/bluetooth/hci_uart.h |
| @@ -259,6 +258,7 @@ Code Seq#(hex) Include File Comments · 86 unmodified lines | ||
| 259 | 258 | 't' 80-8F linux/isdn_ppp.h |
| 260 | 259 | 't' 90 linux/toshiba.h |
| 261 | 260 | 'u' 00-1F linux/smb_fs.h gone |
| 261 | +'u' 20-3F linux/uvcvideo.h USB video class host driver | |
| 262 | 262 | 'v' 00-1F linux/ext2_fs.h conflict! |
| 263 | 263 | 'v' 00-1F linux/fs.h conflict! |
| 264 | 264 | 'v' 00-0F linux/sonypi.h conflict! |
| @@ -54,7 +54,7 @@ · 53 unmodified lines | ||
| 54 | 54 | 53 -> Pinnacle Hybrid Pro (em2881) |
| 55 | 55 | 54 -> Kworld VS-DVB-T 323UR (em2882) [eb1a:e323] |
| 56 | 56 | 55 -> Terratec Cinnergy Hybrid T USB XS (em2882) (em2882) [0ccd:005e,0ccd:0042] |
| 57 | − 56 -> Pinnacle Hybrid Pro (2) (em2882) [2304:0226] | |
| 57 | + 56 -> Pinnacle Hybrid Pro (330e) (em2882) [2304:0226] | |
| 58 | 58 | 57 -> Kworld PlusTV HD Hybrid 330 (em2883) [eb1a:a316] |
| 59 | 59 | 58 -> Compro VideoMate ForYou/Stereo (em2820/em2840) [185b:2041] |
| 60 | 60 | 60 -> Hauppauge WinTV HVR 850 (em2883) [2040:651f] |
| @@ -130,7 +130,6 @@ Card number: 4 · 129 unmodified lines | ||
| 130 | 130 | |
| 131 | 131 | Note: No module for the mse3000 is available yet |
| 132 | 132 | Note: No module for the vpx3224 is available yet |
| 133 | −Note: use encoder=X or decoder=X for non-default i2c chips | |
| 134 | 133 | |
| 135 | 134 | =========================== |
| 136 | 135 | |
| @@ -275,6 +275,7 @@ pac7302 093a:2629 Genious iSlim 300 · 274 unmodified lines | ||
| 275 | 275 | pac7302 093a:262a Webcam 300k |
| 276 | 276 | pac7302 093a:262c Philips SPC 230 NC |
| 277 | 277 | jeilinj 0979:0280 Sakar 57379 |
| 278 | +jeilinj 0979:0280 Sportscam DV15 | |
| 278 | 279 | zc3xx 0ac8:0302 Z-star Vimicro zc0302 |
| 279 | 280 | vc032x 0ac8:0321 Vimicro generic vc0321 |
| 280 | 281 | vc032x 0ac8:0323 Vimicro Vc0323 |
| @@ -0,0 +1,239 @@ | ||
| 1 | +Linux USB Video Class (UVC) driver | |
| 2 | +================================== | |
| 3 | + | |
| 4 | +This file documents some driver-specific aspects of the UVC driver, such as | |
| 5 | +driver-specific ioctls and implementation notes. | |
| 6 | + | |
| 7 | +Questions and remarks can be sent to the Linux UVC development mailing list at | |
| 8 | +linux-uvc-devel@lists.berlios.de. | |
| 9 | + | |
| 10 | + | |
| 11 | +Extension Unit (XU) support | |
| 12 | +--------------------------- | |
| 13 | + | |
| 14 | +1. Introduction | |
| 15 | + | |
| 16 | +The UVC specification allows for vendor-specific extensions through extension | |
| 17 | +units (XUs). The Linux UVC driver supports extension unit controls (XU controls) | |
| 18 | +through two separate mechanisms: | |
| 19 | + | |
| 20 | + - through mappings of XU controls to V4L2 controls | |
| 21 | + - through a driver-specific ioctl interface | |
| 22 | + | |
| 23 | +The first one allows generic V4L2 applications to use XU controls by mapping | |
| 24 | +certain XU controls onto V4L2 controls, which then show up during ordinary | |
| 25 | +control enumeration. | |
| 26 | + | |
| 27 | +The second mechanism requires uvcvideo-specific knowledge for the application to | |
| 28 | +access XU controls but exposes the entire UVC XU concept to user space for | |
| 29 | +maximum flexibility. | |
| 30 | + | |
| 31 | +Both mechanisms complement each other and are described in more detail below. | |
| 32 | + | |
| 33 | + | |
| 34 | +2. Control mappings | |
| 35 | + | |
| 36 | +The UVC driver provides an API for user space applications to define so-called | |
| 37 | +control mappings at runtime. These allow for individual XU controls or byte | |
| 38 | +ranges thereof to be mapped to new V4L2 controls. Such controls appear and | |
| 39 | +function exactly like normal V4L2 controls (i.e. the stock controls, such as | |
| 40 | +brightness, contrast, etc.). However, reading or writing of such a V4L2 controls | |
| 41 | +triggers a read or write of the associated XU control. | |
| 42 | + | |
| 43 | +The ioctl used to create these control mappings is called UVCIOC_CTRL_MAP. | |
| 44 | +Previous driver versions (before 0.2.0) required another ioctl to be used | |
| 45 | +beforehand (UVCIOC_CTRL_ADD) to pass XU control information to the UVC driver. | |
| 46 | +This is no longer necessary as newer uvcvideo versions query the information | |
| 47 | +directly from the device. | |
| 48 | + | |
| 49 | +For details on the UVCIOC_CTRL_MAP ioctl please refer to the section titled | |
| 50 | +"IOCTL reference" below. | |
| 51 | + | |
| 52 | + | |
| 53 | +3. Driver specific XU control interface | |
| 54 | + | |
| 55 | +For applications that need to access XU controls directly, e.g. for testing | |
| 56 | +purposes, firmware upload, or accessing binary controls, a second mechanism to | |
| 57 | +access XU controls is provided in the form of a driver-specific ioctl, namely | |
| 58 | +UVCIOC_CTRL_QUERY. | |
| 59 | + | |
| 60 | +A call to this ioctl allows applications to send queries to the UVC driver that | |
| 61 | +directly map to the low-level UVC control requests. | |
| 62 | + | |
| 63 | +In order to make such a request the UVC unit ID of the control's extension unit | |
| 64 | +and the control selector need to be known. This information either needs to be | |
| 65 | +hardcoded in the application or queried using other ways such as by parsing the | |
| 66 | +UVC descriptor or, if available, using the media controller API to enumerate a | |
| 67 | +device's entities. | |
| 68 | + | |
| 69 | +Unless the control size is already known it is necessary to first make a | |
| 70 | +UVC_GET_LEN requests in order to be able to allocate a sufficiently large buffer | |
| 71 | +and set the buffer size to the correct value. Similarly, to find out whether | |
| 72 | +UVC_GET_CUR or UVC_SET_CUR are valid requests for a given control, a | |
| 73 | +UVC_GET_INFO request should be made. The bits 0 (GET supported) and 1 (SET | |
| 74 | +supported) of the resulting byte indicate which requests are valid. | |
| 75 | + | |
| 76 | +With the addition of the UVCIOC_CTRL_QUERY ioctl the UVCIOC_CTRL_GET and | |
| 77 | +UVCIOC_CTRL_SET ioctls have become obsolete since their functionality is a | |
| 78 | +subset of the former ioctl. For the time being they are still supported but | |
| 79 | +application developers are encouraged to use UVCIOC_CTRL_QUERY instead. | |
| 80 | + | |
| 81 | +For details on the UVCIOC_CTRL_QUERY ioctl please refer to the section titled | |
| 82 | +"IOCTL reference" below. | |
| 83 | + | |
| 84 | + | |
| 85 | +4. Security | |
| 86 | + | |
| 87 | +The API doesn't currently provide a fine-grained access control facility. The | |
| 88 | +UVCIOC_CTRL_ADD and UVCIOC_CTRL_MAP ioctls require super user permissions. | |
| 89 | + | |
| 90 | +Suggestions on how to improve this are welcome. | |
| 91 | + | |
| 92 | + | |
| 93 | +5. Debugging | |
| 94 | + | |
| 95 | +In order to debug problems related to XU controls or controls in general it is | |
| 96 | +recommended to enable the UVC_TRACE_CONTROL bit in the module parameter 'trace'. | |
| 97 | +This causes extra output to be written into the system log. | |
| 98 | + | |
| 99 | + | |
| 100 | +6. IOCTL reference | |
| 101 | + | |
| 102 | +---- UVCIOC_CTRL_MAP - Map a UVC control to a V4L2 control ---- | |
| 103 | + | |
| 104 | +Argument: struct uvc_xu_control_mapping | |
| 105 | + | |
| 106 | +Description: | |
| 107 | + This ioctl creates a mapping between a UVC control or part of a UVC | |
| 108 | + control and a V4L2 control. Once mappings are defined, userspace | |
| 109 | + applications can access vendor-defined UVC control through the V4L2 | |
| 110 | + control API. | |
| 111 | + | |
| 112 | + To create a mapping, applications fill the uvc_xu_control_mapping | |
| 113 | + structure with information about an existing UVC control defined with | |
| 114 | + UVCIOC_CTRL_ADD and a new V4L2 control. | |
| 115 | + | |
| 116 | + A UVC control can be mapped to several V4L2 controls. For instance, | |
| 117 | + a UVC pan/tilt control could be mapped to separate pan and tilt V4L2 | |
| 118 | + controls. The UVC control is divided into non overlapping fields using | |
| 119 | + the 'size' and 'offset' fields and are then independantly mapped to | |
| 120 | + V4L2 control. | |
| 121 | + | |
| 122 | + For signed integer V4L2 controls the data_type field should be set to | |
| 123 | + UVC_CTRL_DATA_TYPE_SIGNED. Other values are currently ignored. | |
| 124 | + | |
| 125 | +Return value: | |
| 126 | + On success 0 is returned. On error -1 is returned and errno is set | |
| 127 | + appropriately. | |
| 128 | + | |
| 129 | + ENOMEM | |
| 130 | + Not enough memory to perform the operation. | |
| 131 | + EPERM | |
| 132 | + Insufficient privileges (super user privileges are required). | |
| 133 | + EINVAL | |
| 134 | + No such UVC control. | |
| 135 | + EOVERFLOW | |
| 136 | + The requested offset and size would overflow the UVC control. | |
| 137 | + EEXIST | |
| 138 | + Mapping already exists. | |
| 139 | + | |
| 140 | +Data types: | |
| 141 | + * struct uvc_xu_control_mapping | |
| 142 | + | |
| 143 | + __u32 id V4L2 control identifier | |
| 144 | + __u8 name[32] V4L2 control name | |
| 145 | + __u8 entity[16] UVC extension unit GUID | |
| 146 | + __u8 selector UVC control selector | |
| 147 | + __u8 size V4L2 control size (in bits) | |
| 148 | + __u8 offset V4L2 control offset (in bits) | |
| 149 | + enum v4l2_ctrl_type | |
| 150 | + v4l2_type V4L2 control type | |
| 151 | + enum uvc_control_data_type | |
| 152 | + data_type UVC control data type | |
| 153 | + struct uvc_menu_info | |
| 154 | + *menu_info Array of menu entries (for menu controls only) | |
| 155 | + __u32 menu_count Number of menu entries (for menu controls only) | |
| 156 | + | |
| 157 | + * struct uvc_menu_info | |
| 158 | + | |
| 159 | + __u32 value Menu entry value used by the device | |
| 160 | + __u8 name[32] Menu entry name | |
| 161 | + | |
| 162 | + | |
| 163 | + * enum uvc_control_data_type | |
| 164 | + | |
| 165 | + UVC_CTRL_DATA_TYPE_RAW Raw control (byte array) | |
| 166 | + UVC_CTRL_DATA_TYPE_SIGNED Signed integer | |
| 167 | + UVC_CTRL_DATA_TYPE_UNSIGNED Unsigned integer | |
| 168 | + UVC_CTRL_DATA_TYPE_BOOLEAN Boolean | |
| 169 | + UVC_CTRL_DATA_TYPE_ENUM Enumeration | |
| 170 | + UVC_CTRL_DATA_TYPE_BITMASK Bitmask | |
| 171 | + | |
| 172 | + | |
| 173 | +---- UVCIOC_CTRL_QUERY - Query a UVC XU control ---- | |
| 174 | + | |
| 175 | +Argument: struct uvc_xu_control_query | |
| 176 | + | |
| 177 | +Description: | |
| 178 | + This ioctl queries a UVC XU control identified by its extension unit ID | |
| 179 | + and control selector. | |
| 180 | + | |
| 181 | + There are a number of different queries available that closely | |
| 182 | + correspond to the low-level control requests described in the UVC | |
| 183 | + specification. These requests are: | |
| 184 | + | |
| 185 | + UVC_GET_CUR | |
| 186 | + Obtain the current value of the control. | |
| 187 | + UVC_GET_MIN | |
| 188 | + Obtain the minimum value of the control. | |
| 189 | + UVC_GET_MAX | |
| 190 | + Obtain the maximum value of the control. | |
| 191 | + UVC_GET_DEF | |
| 192 | + Obtain the default value of the control. | |
| 193 | + UVC_GET_RES | |
| 194 | + Query the resolution of the control, i.e. the step size of the | |
| 195 | + allowed control values. | |
| 196 | + UVC_GET_LEN | |
| 197 | + Query the size of the control in bytes. | |
| 198 | + UVC_GET_INFO | |
| 199 | + Query the control information bitmap, which indicates whether | |
| 200 | + get/set requests are supported. | |
| 201 | + UVC_SET_CUR | |
| 202 | + Update the value of the control. | |
| 203 | + | |
| 204 | + Applications must set the 'size' field to the correct length for the | |
| 205 | + control. Exceptions are the UVC_GET_LEN and UVC_GET_INFO queries, for | |
| 206 | + which the size must be set to 2 and 1, respectively. The 'data' field | |
| 207 | + must point to a valid writable buffer big enough to hold the indicated | |
| 208 | + number of data bytes. | |
| 209 | + | |
| 210 | + Data is copied directly from the device without any driver-side | |
| 211 | + processing. Applications are responsible for data buffer formatting, | |
| 212 | + including little-endian/big-endian conversion. This is particularly | |
| 213 | + important for the result of the UVC_GET_LEN requests, which is always | |
| 214 | + returned as a little-endian 16-bit integer by the device. | |
| 215 | + | |
| 216 | +Return value: | |
| 217 | + On success 0 is returned. On error -1 is returned and errno is set | |
| 218 | + appropriately. | |
| 219 | + | |
| 220 | + ENOENT | |
| 221 | + The device does not support the given control or the specified | |
| 222 | + extension unit could not be found. | |
| 223 | + ENOBUFS | |
| 224 | + The specified buffer size is incorrect (too big or too small). | |
| 225 | + EINVAL | |
| 226 | + An invalid request code was passed. | |
| 227 | + EBADRQC | |
| 228 | + The given request is not supported by the given control. | |
| 229 | + EFAULT | |
| 230 | + The data pointer references an inaccessible memory area. | |
| 231 | + | |
| 232 | +Data types: | |
| 233 | + * struct uvc_xu_control_query | |
| 234 | + | |
| 235 | + __u8 unit Extension unit ID | |
| 236 | + __u8 selector Control selector | |
| 237 | + __u8 query Request code to send to the device | |
| 238 | + __u16 size Control data size (in bytes) | |
| 239 | + __u8 *data Control value | |
| @@ -378,12 +378,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent · 377 unmodified lines | ||
| 378 | 378 | dev->pci = pci; |
| 379 | 379 | |
| 380 | 380 | /* get chip-revision; this is needed to enable bug-fixes */ |
| 381 | − err = pci_read_config_dword(pci, PCI_CLASS_REVISION, &dev->revision); | |
| 382 | − if (err < 0) { | |
| 383 | − ERR(("pci_read_config_dword() failed.\n")); | |
| 384 | − goto err_disable; | |
| 385 | − } | |
| 386 | − dev->revision &= 0xf; | |
| 381 | + dev->revision = pci->revision; | |
| 387 | 382 | |
| 388 | 383 | /* remap the memory from virtual to physical address */ |
| 389 | 384 | |
| @@ -186,4 +186,12 @@ config MEDIA_TUNER_TDA18218 · 185 unmodified lines | ||
| 186 | 186 | default m if MEDIA_TUNER_CUSTOMISE |
| 187 | 187 | help |
| 188 | 188 | NXP TDA18218 silicon tuner driver. |
| 189 | + | |
| 190 | +config MEDIA_TUNER_TDA18212 | |
| 191 | + tristate "NXP TDA18212 silicon tuner" | |
| 192 | + depends on VIDEO_MEDIA && I2C | |
| 193 | + default m if MEDIA_TUNER_CUSTOMISE | |
| 194 | + help | |
| 195 | + NXP TDA18212 silicon tuner driver. | |
| 196 | + | |
| 189 | 197 | endmenu |
| @@ -25,6 +25,7 @@ obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o · 24 unmodified lines | ||
| 25 | 25 | obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o |
| 26 | 26 | obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o |
| 27 | 27 | obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o |
| 28 | +obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o | |
| 28 | 29 | |
| 29 | 30 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core |
| 30 | 31 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends |
| @@ -4024,6 +4024,8 @@ static int mxl5005s_set_params(struct dvb_frontend *fe, · 4023 unmodified lines | ||
| 4024 | 4024 | case BANDWIDTH_8_MHZ: |
| 4025 | 4025 | req_bw = MXL5005S_BANDWIDTH_8MHZ; |
| 4026 | 4026 | break; |
| 4027 | + default: | |
| 4028 | + return -EINVAL; | |
| 4027 | 4029 | } |
| 4028 | 4030 | } |
| 4029 | 4031 | |
| @@ -0,0 +1,265 @@ | ||
| 1 | +/* | |
| 2 | + * NXP TDA18212HN silicon tuner driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2011 Antti Palosaari <crope@iki.fi> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License along | |
| 17 | + * with this program; if not, write to the Free Software Foundation, Inc., | |
| 18 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + */ | |
| 20 | + | |
| 21 | +#include "tda18212_priv.h" | |
| 22 | + | |
| 23 | +static int debug; | |
| 24 | +module_param(debug, int, 0644); | |
| 25 | +MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); | |
| 26 | + | |
| 27 | +/* write multiple registers */ | |
| 28 | +static int tda18212_wr_regs(struct tda18212_priv *priv, u8 reg, u8 *val, | |
| 29 | + int len) | |
| 30 | +{ | |
| 31 | + int ret; | |
| 32 | + u8 buf[len+1]; | |
| 33 | + struct i2c_msg msg[1] = { | |
| 34 | + { | |
| 35 | + .addr = priv->cfg->i2c_address, | |
| 36 | + .flags = 0, | |
| 37 | + .len = sizeof(buf), | |
| 38 | + .buf = buf, | |
| 39 | + } | |
| 40 | + }; | |
| 41 | + | |
| 42 | + buf[0] = reg; | |
| 43 | + memcpy(&buf[1], val, len); | |
| 44 | + | |
| 45 | + ret = i2c_transfer(priv->i2c, msg, 1); | |
| 46 | + if (ret == 1) { | |
| 47 | + ret = 0; | |
| 48 | + } else { | |
| 49 | + warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len); | |
| 50 | + ret = -EREMOTEIO; | |
| 51 | + } | |
| 52 | + return ret; | |
| 53 | +} | |
| 54 | + | |
| 55 | +/* read multiple registers */ | |
| 56 | +static int tda18212_rd_regs(struct tda18212_priv *priv, u8 reg, u8 *val, | |
| 57 | + int len) | |
| 58 | +{ | |
| 59 | + int ret; | |
| 60 | + u8 buf[len]; | |
| 61 | + struct i2c_msg msg[2] = { | |
| 62 | + { | |
| 63 | + .addr = priv->cfg->i2c_address, | |
| 64 | + .flags = 0, | |
| 65 | + .len = 1, | |
| 66 | + .buf = ®, | |
| 67 | + }, { | |
| 68 | + .addr = priv->cfg->i2c_address, | |
| 69 | + .flags = I2C_M_RD, | |
| 70 | + .len = sizeof(buf), | |
| 71 | + .buf = buf, | |
| 72 | + } | |
| 73 | + }; | |
| 74 | + | |
| 75 | + ret = i2c_transfer(priv->i2c, msg, 2); | |
| 76 | + if (ret == 2) { | |
| 77 | + memcpy(val, buf, len); | |
| 78 | + ret = 0; | |
| 79 | + } else { | |
| 80 | + warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len); | |
| 81 | + ret = -EREMOTEIO; | |
| 82 | + } | |
| 83 | + | |
| 84 | + return ret; | |
| 85 | +} | |
| 86 | + | |
| 87 | +/* write single register */ | |
| 88 | +static int tda18212_wr_reg(struct tda18212_priv *priv, u8 reg, u8 val) | |
| 89 | +{ | |
| 90 | + return tda18212_wr_regs(priv, reg, &val, 1); | |
| 91 | +} | |
| 92 | + | |
| 93 | +/* read single register */ | |
| 94 | +static int tda18212_rd_reg(struct tda18212_priv *priv, u8 reg, u8 *val) | |
| 95 | +{ | |
| 96 | + return tda18212_rd_regs(priv, reg, val, 1); | |
| 97 | +} | |
| 98 | + | |
| 99 | +#if 0 /* keep, useful when developing driver */ | |
| 100 | +static void tda18212_dump_regs(struct tda18212_priv *priv) | |
| 101 | +{ | |
| 102 | + int i; | |
| 103 | + u8 buf[256]; | |
| 104 | + | |
| 105 | + #define TDA18212_RD_LEN 32 | |
| 106 | + for (i = 0; i < sizeof(buf); i += TDA18212_RD_LEN) | |
| 107 | + tda18212_rd_regs(priv, i, &buf[i], TDA18212_RD_LEN); | |
| 108 | + | |
| 109 | + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 32, 1, buf, | |
| 110 | + sizeof(buf), true); | |
| 111 | + | |
| 112 | + return; | |
| 113 | +} | |
| 114 | +#endif | |
| 115 | + | |
| 116 | +static int tda18212_set_params(struct dvb_frontend *fe, | |
| 117 | + struct dvb_frontend_parameters *p) | |
| 118 | +{ | |
| 119 | + struct tda18212_priv *priv = fe->tuner_priv; | |
| 120 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 121 | + int ret, i; | |
| 122 | + u32 if_khz; | |
| 123 | + u8 buf[9]; | |
| 124 | + static const u8 bw_params[][3] = { | |
| 125 | + /* 0f 13 23 */ | |
| 126 | + { 0xb3, 0x20, 0x03 }, /* DVB-T 6 MHz */ | |
| 127 | + { 0xb3, 0x31, 0x01 }, /* DVB-T 7 MHz */ | |
| 128 | + { 0xb3, 0x22, 0x01 }, /* DVB-T 8 MHz */ | |
| 129 | + { 0x92, 0x53, 0x03 }, /* DVB-C */ | |
| 130 | + }; | |
| 131 | + | |
| 132 | + dbg("%s: delsys=%d RF=%d BW=%d", __func__, | |
| 133 | + c->delivery_system, c->frequency, c->bandwidth_hz); | |
| 134 | + | |
| 135 | + if (fe->ops.i2c_gate_ctrl) | |
| 136 | + fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ | |
| 137 | + | |
| 138 | + switch (c->delivery_system) { | |
| 139 | + case SYS_DVBT: | |
| 140 | + switch (c->bandwidth_hz) { | |
| 141 | + case 6000000: | |
| 142 | + if_khz = priv->cfg->if_dvbt_6; | |
| 143 | + i = 0; | |
| 144 | + break; | |
| 145 | + case 7000000: | |
| 146 | + if_khz = priv->cfg->if_dvbt_7; | |
| 147 | + i = 1; | |
| 148 | + break; | |
| 149 | + case 8000000: | |
| 150 | + if_khz = priv->cfg->if_dvbt_8; | |
| 151 | + i = 2; | |
| 152 | + break; | |
| 153 | + default: | |
| 154 | + ret = -EINVAL; | |
| 155 | + goto error; | |
| 156 | + } | |
| 157 | + break; | |
| 158 | + case SYS_DVBC_ANNEX_AC: | |
| 159 | + if_khz = priv->cfg->if_dvbc; | |
| 160 | + i = 3; | |
| 161 | + break; | |
| 162 | + default: | |
| 163 | + ret = -EINVAL; | |
| 164 | + goto error; | |
| 165 | + } | |
| 166 | + | |
| 167 | + ret = tda18212_wr_reg(priv, 0x23, bw_params[i][2]); | |
| 168 | + if (ret) | |
| 169 | + goto error; | |
| 170 | + | |
| 171 | + ret = tda18212_wr_reg(priv, 0x06, 0x00); | |
| 172 | + if (ret) | |
| 173 | + goto error; | |
| 174 | + | |
| 175 | + ret = tda18212_wr_reg(priv, 0x0f, bw_params[i][0]); | |
| 176 | + if (ret) | |
| 177 | + goto error; | |
| 178 | + | |
| 179 | + buf[0] = 0x02; | |
| 180 | + buf[1] = bw_params[i][1]; | |
| 181 | + buf[2] = 0x03; /* default value */ | |
| 182 | + buf[3] = if_khz / 50; | |
| 183 | + buf[4] = ((c->frequency / 1000) >> 16) & 0xff; | |
| 184 | + buf[5] = ((c->frequency / 1000) >> 8) & 0xff; | |
| 185 | + buf[6] = ((c->frequency / 1000) >> 0) & 0xff; | |
| 186 | + buf[7] = 0xc1; | |
| 187 | + buf[8] = 0x01; | |
| 188 | + ret = tda18212_wr_regs(priv, 0x12, buf, sizeof(buf)); | |
| 189 | + if (ret) | |
| 190 | + goto error; | |
| 191 | + | |
| 192 | +exit: | |
| 193 | + if (fe->ops.i2c_gate_ctrl) | |
| 194 | + fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ | |
| 195 | + | |
| 196 | + return ret; | |
| 197 | + | |
| 198 | +error: | |
| 199 | + dbg("%s: failed:%d", __func__, ret); | |
| 200 | + goto exit; | |
| 201 | +} | |
| 202 | + | |
| 203 | +static int tda18212_release(struct dvb_frontend *fe) | |
| 204 | +{ | |
| 205 | + kfree(fe->tuner_priv); | |
| 206 | + fe->tuner_priv = NULL; | |
| 207 | + return 0; | |
| 208 | +} | |
| 209 | + | |
| 210 | +static const struct dvb_tuner_ops tda18212_tuner_ops = { | |
| 211 | + .info = { | |
| 212 | + .name = "NXP TDA18212", | |
| 213 | + | |
| 214 | + .frequency_min = 48000000, | |
| 215 | + .frequency_max = 864000000, | |
| 216 | + .frequency_step = 1000, | |
| 217 | + }, | |
| 218 | + | |
| 219 | + .release = tda18212_release, | |
| 220 | + | |
| 221 | + .set_params = tda18212_set_params, | |
| 222 | +}; | |
| 223 | + | |
| 224 | +struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe, | |
| 225 | + struct i2c_adapter *i2c, struct tda18212_config *cfg) | |
| 226 | +{ | |
| 227 | + struct tda18212_priv *priv = NULL; | |
| 228 | + int ret; | |
| 229 | + u8 val; | |
| 230 | + | |
| 231 | + priv = kzalloc(sizeof(struct tda18212_priv), GFP_KERNEL); | |
| 232 | + if (priv == NULL) | |
| 233 | + return NULL; | |
| 234 | + | |
| 235 | + priv->cfg = cfg; | |
| 236 | + priv->i2c = i2c; | |
| 237 | + fe->tuner_priv = priv; | |
| 238 | + | |
| 239 | + if (fe->ops.i2c_gate_ctrl) | |
| 240 | + fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ | |
| 241 | + | |
| 242 | + /* check if the tuner is there */ | |
| 243 | + ret = tda18212_rd_reg(priv, 0x00, &val); | |
| 244 | + | |
| 245 | + if (fe->ops.i2c_gate_ctrl) | |
| 246 | + fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ | |
| 247 | + | |
| 248 | + dbg("%s: ret:%d chip ID:%02x", __func__, ret, val); | |
| 249 | + if (ret || val != 0xc7) { | |
| 250 | + kfree(priv); | |
| 251 | + return NULL; | |
| 252 | + } | |
| 253 | + | |
| 254 | + info("NXP TDA18212HN successfully identified."); | |
| 255 | + | |
| 256 | + memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops, | |
| 257 | + sizeof(struct dvb_tuner_ops)); | |
| 258 | + | |
| 259 | + return fe; | |
| 260 | +} | |
| 261 | +EXPORT_SYMBOL(tda18212_attach); | |
| 262 | + | |
| 263 | +MODULE_DESCRIPTION("NXP TDA18212HN silicon tuner driver"); | |
| 264 | +MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | |
| 265 | +MODULE_LICENSE("GPL"); | |
| @@ -0,0 +1,48 @@ | ||
| 1 | +/* | |
| 2 | + * NXP TDA18212HN silicon tuner driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2011 Antti Palosaari <crope@iki.fi> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License along | |
| 17 | + * with this program; if not, write to the Free Software Foundation, Inc., | |
| 18 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + */ | |
| 20 | + | |
| 21 | +#ifndef TDA18212_H | |
| 22 | +#define TDA18212_H | |
| 23 | + | |
| 24 | +#include "dvb_frontend.h" | |
| 25 | + | |
| 26 | +struct tda18212_config { | |
| 27 | + u8 i2c_address; | |
| 28 | + | |
| 29 | + u16 if_dvbt_6; | |
| 30 | + u16 if_dvbt_7; | |
| 31 | + u16 if_dvbt_8; | |
| 32 | + u16 if_dvbc; | |
| 33 | +}; | |
| 34 | + | |
| 35 | +#if defined(CONFIG_MEDIA_TUNER_TDA18212) || \ | |
| 36 | + (defined(CONFIG_MEDIA_TUNER_TDA18212_MODULE) && defined(MODULE)) | |
| 37 | +extern struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe, | |
| 38 | + struct i2c_adapter *i2c, struct tda18212_config *cfg); | |
| 39 | +#else | |
| 40 | +static inline struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe, | |
| 41 | + struct i2c_adapter *i2c, struct tda18212_config *cfg) | |
| 42 | +{ | |
| 43 | + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | |
| 44 | + return NULL; | |
| 45 | +} | |
| 46 | +#endif | |
| 47 | + | |
| 48 | +#endif | |
| @@ -0,0 +1,44 @@ | ||
| 1 | +/* | |
| 2 | + * NXP TDA18212HN silicon tuner driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2011 Antti Palosaari <crope@iki.fi> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License along | |
| 17 | + * with this program; if not, write to the Free Software Foundation, Inc., | |
| 18 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + */ | |
| 20 | + | |
| 21 | +#ifndef TDA18212_PRIV_H | |
| 22 | +#define TDA18212_PRIV_H | |
| 23 | + | |
| 24 | +#include "tda18212.h" | |
| 25 | + | |
| 26 | +#define LOG_PREFIX "tda18212" | |
| 27 | + | |
| 28 | +#undef dbg | |
| 29 | +#define dbg(f, arg...) \ | |
| 30 | + if (debug) \ | |
| 31 | + printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) | |
| 32 | +#undef err | |
| 33 | +#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) | |
| 34 | +#undef info | |
| 35 | +#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) | |
| 36 | +#undef warn | |
| 37 | +#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) | |
| 38 | + | |
| 39 | +struct tda18212_priv { | |
| 40 | + struct tda18212_config *cfg; | |
| 41 | + struct i2c_adapter *i2c; | |
| 42 | +}; | |
| 43 | + | |
| 44 | +#endif | |
| @@ -976,6 +976,10 @@ static int tda18271_set_params(struct dvb_frontend *fe, · 975 unmodified lines | ||
| 976 | 976 | tda_warn("bandwidth not set!\n"); |
| 977 | 977 | return -EINVAL; |
| 978 | 978 | } |
| 979 | + } else if (fe->ops.info.type == FE_QAM) { | |
| 980 | + /* DVB-C */ | |
| 981 | + map = &std_map->qam_8; | |
| 982 | + bw = 8000000; | |
| 979 | 983 | } else { |
| 980 | 984 | tda_warn("modulation type not supported!\n"); |
| 981 | 985 | return -EINVAL; |
| @@ -628,6 +628,15 @@ static void xc_debug_dump(struct xc5000_priv *priv) · 627 unmodified lines | ||
| 628 | 628 | dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality); |
| 629 | 629 | } |
| 630 | 630 | |
| 631 | +/* | |
| 632 | + * As defined on EN 300 429, the DVB-C roll-off factor is 0.15. | |
| 633 | + * So, the amount of the needed bandwith is given by: | |
| 634 | + * Bw = Symbol_rate * (1 + 0.15) | |
| 635 | + * As such, the maximum symbol rate supported by 6 MHz is given by: | |
| 636 | + * max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds | |
| 637 | + */ | |
| 638 | +#define MAX_SYMBOL_RATE_6MHz 5217391 | |
| 639 | + | |
| 631 | 640 | static int xc5000_set_params(struct dvb_frontend *fe, |
| 632 | 641 | struct dvb_frontend_parameters *params) |
| 633 | 642 | { |
| @@ -688,21 +697,32 @@ static int xc5000_set_params(struct dvb_frontend *fe, · 54 unmodified lines | ||
| 688 | 697 | } |
| 689 | 698 | priv->rf_mode = XC_RF_MODE_AIR; |
| 690 | 699 | } else if (fe->ops.info.type == FE_QAM) { |
| 691 | − dprintk(1, "%s() QAM\n", __func__); | |
| 692 | 700 | switch (params->u.qam.modulation) { |
| 701 | + case QAM_256: | |
| 702 | + case QAM_AUTO: | |
| 693 | 703 | case QAM_16: |
| 694 | 704 | case QAM_32: |
| 695 | 705 | case QAM_64: |
| 696 | 706 | case QAM_128: |
| 697 | − case QAM_256: | |
| 698 | − case QAM_AUTO: | |
| 699 | 707 | dprintk(1, "%s() QAM modulation\n", __func__); |
| 700 | − priv->bandwidth = BANDWIDTH_8_MHZ; | |
| 701 | − priv->video_standard = DTV7_8; | |
| 702 | − priv->freq_hz = params->frequency - 2750000; | |
| 703 | 708 | priv->rf_mode = XC_RF_MODE_CABLE; |
| 709 | + /* | |
| 710 | + * Using a 8MHz bandwidth sometimes fail | |
| 711 | + * with 6MHz-spaced channels, due to inter-carrier | |
| 712 | + * interference. So, use DTV6 firmware | |
| 713 | + */ | |
| 714 | + if (params->u.qam.symbol_rate <= MAX_SYMBOL_RATE_6MHz) { | |
| 715 | + priv->bandwidth = BANDWIDTH_6_MHZ; | |
| 716 | + priv->video_standard = DTV6; | |
| 717 | + priv->freq_hz = params->frequency - 1750000; | |
| 718 | + } else { | |
| 719 | + priv->bandwidth = BANDWIDTH_8_MHZ; | |
| 720 | + priv->video_standard = DTV7_8; | |
| 721 | + priv->freq_hz = params->frequency - 2750000; | |
| 722 | + } | |
| 704 | 723 | break; |
| 705 | 724 | default: |
| 725 | + dprintk(1, "%s() Unsupported QAM type\n", __func__); | |
| 706 | 726 | return -EINVAL; |
| 707 | 727 | } |
| 708 | 728 | } else { |
| @@ -290,10 +290,8 @@ static void flexcop_pci_dma_exit(struct flexcop_pci *fc_pci) · 289 unmodified lines | ||
| 290 | 290 | static int flexcop_pci_init(struct flexcop_pci *fc_pci) |
| 291 | 291 | { |
| 292 | 292 | int ret; |
| 293 | − u8 card_rev; | |
| 294 | 293 | |
| 295 | − pci_read_config_byte(fc_pci->pdev, PCI_CLASS_REVISION, &card_rev); | |
| 296 | − info("card revision %x", card_rev); | |
| 294 | + info("card revision %x", fc_pci->pdev->revision); | |
| 297 | 295 | |
| 298 | 296 | if ((ret = pci_enable_device(fc_pci->pdev)) != 0) |
| 299 | 297 | return ret; |
| @@ -460,7 +460,7 @@ static int __devinit bt878_probe(struct pci_dev *dev, · 459 unmodified lines | ||
| 460 | 460 | goto fail0; |
| 461 | 461 | } |
| 462 | 462 | |
| 463 | − pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision); | |
| 463 | + bt->revision = dev->revision; | |
| 464 | 464 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); |
| 465 | 465 | |
| 466 | 466 | |
| @@ -478,97 +478,94 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, · 477 unmodified lines | ||
| 478 | 478 | |
| 479 | 479 | EXPORT_SYMBOL(dvb_dmx_swfilter_packets); |
| 480 | 480 | |
| 481 | −void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) | |
| 481 | +static inline int find_next_packet(const u8 *buf, int pos, size_t count, | |
| 482 | + const int pktsize) | |
| 482 | 483 | { |
| 483 | − int p = 0, i, j; | |
| 484 | + int start = pos, lost; | |
| 484 | 485 | |
| 485 | − spin_lock(&demux->lock); | |
| 486 | − | |
| 487 | − if (demux->tsbufp) { | |
| 488 | − i = demux->tsbufp; | |
| 489 | − j = 188 - i; | |
| 490 | − if (count < j) { | |
| 491 | − memcpy(&demux->tsbuf[i], buf, count); | |
| 492 | − demux->tsbufp += count; | |
| 493 | − goto bailout; | |
| 494 | − } | |
| 495 | − memcpy(&demux->tsbuf[i], buf, j); | |
| 496 | − if (demux->tsbuf[0] == 0x47) | |
| 497 | − dvb_dmx_swfilter_packet(demux, demux->tsbuf); | |
| 498 | − demux->tsbufp = 0; | |
| 499 | − p += j; | |
| 486 | + while (pos < count) { | |
| 487 | + if (buf[pos] == 0x47 || | |
| 488 | + (pktsize == 204 && buf[pos] == 0xB8)) | |
| 489 | + break; | |
| 490 | + pos++; | |
| 500 | 491 | } |
| 501 | 492 | |
| 502 | − while (p < count) { | |
| 503 | − if (buf[p] == 0x47) { | |
| 504 | − if (count - p >= 188) { | |
| 505 | − dvb_dmx_swfilter_packet(demux, &buf[p]); | |
| 506 | − p += 188; | |
| 507 | − } else { | |
| 508 | − i = count - p; | |
| 509 | − memcpy(demux->tsbuf, &buf[p], i); | |
| 510 | − demux->tsbufp = i; | |
| 511 | − goto bailout; | |
| 512 | − } | |
| 513 | − } else | |
| 514 | − p++; | |
| 493 | + lost = pos - start; | |
| 494 | + if (lost) { | |
| 495 | + /* This garbage is part of a valid packet? */ | |
| 496 | + int backtrack = pos - pktsize; | |
| 497 | + if (backtrack >= 0 && (buf[backtrack] == 0x47 || | |
| 498 | + (pktsize == 204 && buf[backtrack] == 0xB8))) | |
| 499 | + return backtrack; | |
| 515 | 500 | } |
| 516 | 501 | |
| 517 | −bailout: | |
| 518 | − spin_unlock(&demux->lock); | |
| 502 | + return pos; | |
| 519 | 503 | } |
| 520 | 504 | |
| 521 | −EXPORT_SYMBOL(dvb_dmx_swfilter); | |
| 522 | − | |
| 523 | −void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) | |
| 505 | +/* Filter all pktsize= 188 or 204 sized packets and skip garbage. */ | |
| 506 | +static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, | |
| 507 | + size_t count, const int pktsize) | |
| 524 | 508 | { |
| 525 | 509 | int p = 0, i, j; |
| 526 | − u8 tmppack[188]; | |
| 510 | + const u8 *q; | |
| 527 | 511 | |
| 528 | 512 | spin_lock(&demux->lock); |
| 529 | 513 | |
| 530 | − if (demux->tsbufp) { | |
| 514 | + if (demux->tsbufp) { /* tsbuf[0] is now 0x47. */ | |
| 531 | 515 | i = demux->tsbufp; |
| 532 | − j = 204 - i; | |
| 516 | + j = pktsize - i; | |
| 533 | 517 | if (count < j) { |
| 534 | 518 | memcpy(&demux->tsbuf[i], buf, count); |
| 535 | 519 | demux->tsbufp += count; |
| 536 | 520 | goto bailout; |
| 537 | 521 | } |
| 538 | 522 | memcpy(&demux->tsbuf[i], buf, j); |
| 539 | − if ((demux->tsbuf[0] == 0x47) || (demux->tsbuf[0] == 0xB8)) { | |
| 540 | − memcpy(tmppack, demux->tsbuf, 188); | |
| 541 | − if (tmppack[0] == 0xB8) | |
| 542 | − tmppack[0] = 0x47; | |
| 543 | − dvb_dmx_swfilter_packet(demux, tmppack); | |
| 544 | − } | |
| 523 | + if (demux->tsbuf[0] == 0x47) /* double check */ | |
| 524 | + dvb_dmx_swfilter_packet(demux, demux->tsbuf); | |
| 545 | 525 | demux->tsbufp = 0; |
| 546 | 526 | p += j; |
| 547 | 527 | } |
| 548 | 528 | |
| 549 | − while (p < count) { | |
| 550 | − if ((buf[p] == 0x47) || (buf[p] == 0xB8)) { | |
| 551 | − if (count - p >= 204) { | |
| 552 | − memcpy(tmppack, &buf[p], 188); | |
| 553 | − if (tmppack[0] == 0xB8) | |
| 554 | − tmppack[0] = 0x47; | |
| 555 | − dvb_dmx_swfilter_packet(demux, tmppack); | |
| 556 | − p += 204; | |
| 557 | − } else { | |
| 558 | − i = count - p; | |
| 559 | − memcpy(demux->tsbuf, &buf[p], i); | |
| 560 | − demux->tsbufp = i; | |
| 561 | − goto bailout; | |
| 562 | − } | |
| 563 | − } else { | |
| 564 | − p++; | |
| 529 | + while (1) { | |
| 530 | + p = find_next_packet(buf, p, count, pktsize); | |
| 531 | + if (p >= count) | |
| 532 | + break; | |
| 533 | + if (count - p < pktsize) | |
| 534 | + break; | |
| 535 | + | |
| 536 | + q = &buf[p]; | |
| 537 | + | |
| 538 | + if (pktsize == 204 && (*q == 0xB8)) { | |
| 539 | + memcpy(demux->tsbuf, q, 188); | |
| 540 | + demux->tsbuf[0] = 0x47; | |
| 541 | + q = demux->tsbuf; | |
| 565 | 542 | } |
| 543 | + dvb_dmx_swfilter_packet(demux, q); | |
| 544 | + p += pktsize; | |
| 545 | + } | |
| 546 | + | |
| 547 | + i = count - p; | |
| 548 | + if (i) { | |
| 549 | + memcpy(demux->tsbuf, &buf[p], i); | |
| 550 | + demux->tsbufp = i; | |
| 551 | + if (pktsize == 204 && demux->tsbuf[0] == 0xB8) | |
| 552 | + demux->tsbuf[0] = 0x47; | |
| 566 | 553 | } |
| 567 | 554 | |
| 568 | 555 | bailout: |
| 569 | 556 | spin_unlock(&demux->lock); |
| 570 | 557 | } |
| 571 | 558 | |
| 559 | +void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) | |
| 560 | +{ | |
| 561 | + _dvb_dmx_swfilter(demux, buf, count, 188); | |
| 562 | +} | |
| 563 | +EXPORT_SYMBOL(dvb_dmx_swfilter); | |
| 564 | + | |
| 565 | +void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) | |
| 566 | +{ | |
| 567 | + _dvb_dmx_swfilter(demux, buf, count, 204); | |
| 568 | +} | |
| 572 | 569 | EXPORT_SYMBOL(dvb_dmx_swfilter_204); |
| 573 | 570 | |
| 574 | 571 | static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux) |
| @@ -105,7 +105,8 @@ struct dvb_frontend_private { · 104 unmodified lines | ||
| 105 | 105 | |
| 106 | 106 | /* thread/frontend values */ |
| 107 | 107 | struct dvb_device *dvbdev; |
| 108 | − struct dvb_frontend_parameters parameters; | |
| 108 | + struct dvb_frontend_parameters parameters_in; | |
| 109 | + struct dvb_frontend_parameters parameters_out; | |
| 109 | 110 | struct dvb_fe_events events; |
| 110 | 111 | struct semaphore sem; |
| 111 | 112 | struct list_head list_head; |
| @@ -160,12 +161,11 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) · 48 unmodified lines | ||
| 160 | 161 | |
| 161 | 162 | e = &events->events[events->eventw]; |
| 162 | 163 | |
| 163 | − memcpy (&e->parameters, &fepriv->parameters, | |
| 164 | − sizeof (struct dvb_frontend_parameters)); | |
| 165 | − | |
| 166 | 164 | if (status & FE_HAS_LOCK) |
| 167 | 165 | if (fe->ops.get_frontend) |
| 168 | − fe->ops.get_frontend(fe, &e->parameters); | |
| 166 | + fe->ops.get_frontend(fe, &fepriv->parameters_out); | |
| 167 | + | |
| 168 | + e->parameters = fepriv->parameters_out; | |
| 169 | 169 | |
| 170 | 170 | events->eventw = wp; |
| 171 | 171 | |
| @@ -277,12 +277,12 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra · 105 unmodified lines | ||
| 277 | 277 | int ready = 0; |
| 278 | 278 | int fe_set_err = 0; |
| 279 | 279 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
| 280 | − int original_inversion = fepriv->parameters.inversion; | |
| 281 | − u32 original_frequency = fepriv->parameters.frequency; | |
| 280 | + int original_inversion = fepriv->parameters_in.inversion; | |
| 281 | + u32 original_frequency = fepriv->parameters_in.frequency; | |
| 282 | 282 | |
| 283 | 283 | /* are we using autoinversion? */ |
| 284 | 284 | autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && |
| 285 | − (fepriv->parameters.inversion == INVERSION_AUTO)); | |
| 285 | + (fepriv->parameters_in.inversion == INVERSION_AUTO)); | |
| 286 | 286 | |
| 287 | 287 | /* setup parameters correctly */ |
| 288 | 288 | while(!ready) { |
| @@ -348,18 +348,19 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra · 59 unmodified lines | ||
| 348 | 348 | fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step); |
| 349 | 349 | |
| 350 | 350 | /* set the frontend itself */ |
| 351 | − fepriv->parameters.frequency += fepriv->lnb_drift; | |
| 351 | + fepriv->parameters_in.frequency += fepriv->lnb_drift; | |
| 352 | 352 | if (autoinversion) |
| 353 | − fepriv->parameters.inversion = fepriv->inversion; | |
| 353 | + fepriv->parameters_in.inversion = fepriv->inversion; | |
| 354 | 354 | if (fe->ops.set_frontend) |
| 355 | − fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters); | |
| 355 | + fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters_in); | |
| 356 | + fepriv->parameters_out = fepriv->parameters_in; | |
| 356 | 357 | if (fe_set_err < 0) { |
| 357 | 358 | fepriv->state = FESTATE_ERROR; |
| 358 | 359 | return fe_set_err; |
| 359 | 360 | } |
| 360 | 361 | |
| 361 | − fepriv->parameters.frequency = original_frequency; | |
| 362 | − fepriv->parameters.inversion = original_inversion; | |
| 362 | + fepriv->parameters_in.frequency = original_frequency; | |
| 363 | + fepriv->parameters_in.inversion = original_inversion; | |
| 363 | 364 | |
| 364 | 365 | fepriv->auto_sub_step++; |
| 365 | 366 | return 0; |
| @@ -383,7 +384,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) · 17 unmodified lines | ||
| 383 | 384 | if (fepriv->state & FESTATE_RETUNE) { |
| 384 | 385 | if (fe->ops.set_frontend) |
| 385 | 386 | retval = fe->ops.set_frontend(fe, |
| 386 | − &fepriv->parameters); | |
| 387 | + &fepriv->parameters_in); | |
| 388 | + fepriv->parameters_out = fepriv->parameters_in; | |
| 387 | 389 | if (retval < 0) |
| 388 | 390 | fepriv->state = FESTATE_ERROR; |
| 389 | 391 | else |
| @@ -413,8 +415,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) · 23 unmodified lines | ||
| 413 | 415 | |
| 414 | 416 | /* if we're tuned, then we have determined the correct inversion */ |
| 415 | 417 | if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && |
| 416 | − (fepriv->parameters.inversion == INVERSION_AUTO)) { | |
| 417 | − fepriv->parameters.inversion = fepriv->inversion; | |
| 418 | + (fepriv->parameters_in.inversion == INVERSION_AUTO)) { | |
| 419 | + fepriv->parameters_in.inversion = fepriv->inversion; | |
| 418 | 420 | } |
| 419 | 421 | return; |
| 420 | 422 | } |
| @@ -594,12 +596,14 @@ restart: · 173 unmodified lines | ||
| 594 | 596 | |
| 595 | 597 | if (fepriv->state & FESTATE_RETUNE) { |
| 596 | 598 | dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); |
| 597 | − params = &fepriv->parameters; | |
| 599 | + params = &fepriv->parameters_in; | |
| 598 | 600 | fepriv->state = FESTATE_TUNED; |
| 599 | 601 | } |
| 600 | 602 | |
| 601 | 603 | if (fe->ops.tune) |
| 602 | 604 | fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s); |
| 605 | + if (params) | |
| 606 | + fepriv->parameters_out = *params; | |
| 603 | 607 | |
| 604 | 608 | if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) { |
| 605 | 609 | dprintk("%s: state changed, adding current state\n", __func__); |
| @@ -612,11 +616,9 @@ restart: · 6 unmodified lines | ||
| 612 | 616 | dvb_frontend_swzigzag(fe); |
| 613 | 617 | break; |
| 614 | 618 | case DVBFE_ALGO_CUSTOM: |
| 615 | − params = NULL; /* have we been asked to RETUNE ? */ | |
| 616 | 619 | dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state); |
| 617 | 620 | if (fepriv->state & FESTATE_RETUNE) { |
| 618 | 621 | dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__); |
| 619 | − params = &fepriv->parameters; | |
| 620 | 622 | fepriv->state = FESTATE_TUNED; |
| 621 | 623 | } |
| 622 | 624 | /* Case where we are going to search for a carrier |
| @@ -625,7 +627,7 @@ restart: · 2 unmodified lines | ||
| 625 | 627 | */ |
| 626 | 628 | if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) { |
| 627 | 629 | if (fe->ops.search) { |
| 628 | − fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters); | |
| 630 | + fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters_in); | |
| 629 | 631 | /* We did do a search as was requested, the flags are |
| 630 | 632 | * now unset as well and has the flags wrt to search. |
| 631 | 633 | */ |
| @@ -636,11 +638,12 @@ restart: · 4 unmodified lines | ||
| 636 | 638 | /* Track the carrier if the search was successful */ |
| 637 | 639 | if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) { |
| 638 | 640 | if (fe->ops.track) |
| 639 | − fe->ops.track(fe, &fepriv->parameters); | |
| 641 | + fe->ops.track(fe, &fepriv->parameters_in); | |
| 640 | 642 | } else { |
| 641 | 643 | fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; |
| 642 | 644 | fepriv->delay = HZ / 2; |
| 643 | 645 | } |
| 646 | + fepriv->parameters_out = fepriv->parameters_in; | |
| 644 | 647 | fe->ops.read_status(fe, &s); |
| 645 | 648 | if (s != fepriv->status) { |
| 646 | 649 | dvb_frontend_add_event(fe, s); /* update event list */ |
| @@ -860,34 +863,34 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, · 213 unmodified lines | ||
| 860 | 863 | |
| 861 | 864 | static int dvb_frontend_clear_cache(struct dvb_frontend *fe) |
| 862 | 865 | { |
| 866 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 863 | 867 | int i; |
| 864 | 868 | |
| 865 | − memset(&(fe->dtv_property_cache), 0, | |
| 866 | − sizeof(struct dtv_frontend_properties)); | |
| 867 | − | |
| 868 | − fe->dtv_property_cache.state = DTV_CLEAR; | |
| 869 | − fe->dtv_property_cache.delivery_system = SYS_UNDEFINED; | |
| 870 | − fe->dtv_property_cache.inversion = INVERSION_AUTO; | |
| 871 | − fe->dtv_property_cache.fec_inner = FEC_AUTO; | |
| 872 | − fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO; | |
| 873 | − fe->dtv_property_cache.bandwidth_hz = BANDWIDTH_AUTO; | |
| 874 | − fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO; | |
| 875 | − fe->dtv_property_cache.hierarchy = HIERARCHY_AUTO; | |
| 876 | − fe->dtv_property_cache.symbol_rate = QAM_AUTO; | |
| 877 | − fe->dtv_property_cache.code_rate_HP = FEC_AUTO; | |
| 878 | − fe->dtv_property_cache.code_rate_LP = FEC_AUTO; | |
| 879 | − | |
| 880 | − fe->dtv_property_cache.isdbt_partial_reception = -1; | |
| 881 | − fe->dtv_property_cache.isdbt_sb_mode = -1; | |
| 882 | − fe->dtv_property_cache.isdbt_sb_subchannel = -1; | |
| 883 | − fe->dtv_property_cache.isdbt_sb_segment_idx = -1; | |
| 884 | − fe->dtv_property_cache.isdbt_sb_segment_count = -1; | |
| 885 | − fe->dtv_property_cache.isdbt_layer_enabled = 0x7; | |
| 869 | + memset(c, 0, sizeof(struct dtv_frontend_properties)); | |
| 870 | + | |
| 871 | + c->state = DTV_CLEAR; | |
| 872 | + c->delivery_system = SYS_UNDEFINED; | |
| 873 | + c->inversion = INVERSION_AUTO; | |
| 874 | + c->fec_inner = FEC_AUTO; | |
| 875 | + c->transmission_mode = TRANSMISSION_MODE_AUTO; | |
| 876 | + c->bandwidth_hz = BANDWIDTH_AUTO; | |
| 877 | + c->guard_interval = GUARD_INTERVAL_AUTO; | |
| 878 | + c->hierarchy = HIERARCHY_AUTO; | |
| 879 | + c->symbol_rate = QAM_AUTO; | |
| 880 | + c->code_rate_HP = FEC_AUTO; | |
| 881 | + c->code_rate_LP = FEC_AUTO; | |
| 882 | + | |
| 883 | + c->isdbt_partial_reception = -1; | |
| 884 | + c->isdbt_sb_mode = -1; | |
| 885 | + c->isdbt_sb_subchannel = -1; | |
| 886 | + c->isdbt_sb_segment_idx = -1; | |
| 887 | + c->isdbt_sb_segment_count = -1; | |
| 888 | + c->isdbt_layer_enabled = 0x7; | |
| 886 | 889 | for (i = 0; i < 3; i++) { |
| 887 | − fe->dtv_property_cache.layer[i].fec = FEC_AUTO; | |
| 888 | − fe->dtv_property_cache.layer[i].modulation = QAM_AUTO; | |
| 889 | − fe->dtv_property_cache.layer[i].interleaving = -1; | |
| 890 | − fe->dtv_property_cache.layer[i].segment_count = -1; | |
| 890 | + c->layer[i].fec = FEC_AUTO; | |
| 891 | + c->layer[i].modulation = QAM_AUTO; | |
| 892 | + c->layer[i].interleaving = -1; | |
| 893 | + c->layer[i].segment_count = -1; | |
| 891 | 894 | } |
| 892 | 895 | |
| 893 | 896 | return 0; |
| @@ -1020,10 +1023,9 @@ static int is_legacy_delivery_system(fe_delivery_system_t s) · 126 unmodified lines | ||
| 1020 | 1023 | * it's being used for the legacy or new API, reducing code and complexity. |
| 1021 | 1024 | */ |
| 1022 | 1025 | static void dtv_property_cache_sync(struct dvb_frontend *fe, |
| 1023 | − struct dvb_frontend_parameters *p) | |
| 1026 | + struct dtv_frontend_properties *c, | |
| 1027 | + const struct dvb_frontend_parameters *p) | |
| 1024 | 1028 | { |
| 1025 | − struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 1026 | − | |
| 1027 | 1029 | c->frequency = p->frequency; |
| 1028 | 1030 | c->inversion = p->inversion; |
| 1029 | 1031 | |
| @@ -1074,9 +1076,9 @@ static void dtv_property_cache_sync(struct dvb_frontend *fe, · 44 unmodified lines | ||
| 1074 | 1076 | */ |
| 1075 | 1077 | static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) |
| 1076 | 1078 | { |
| 1077 | − struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 1079 | + const struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 1078 | 1080 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
| 1079 | − struct dvb_frontend_parameters *p = &fepriv->parameters; | |
| 1081 | + struct dvb_frontend_parameters *p = &fepriv->parameters_in; | |
| 1080 | 1082 | |
| 1081 | 1083 | p->frequency = c->frequency; |
| 1082 | 1084 | p->inversion = c->inversion; |
| @@ -1086,14 +1088,12 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) · 3 unmodified lines | ||
| 1086 | 1088 | dprintk("%s() Preparing QPSK req\n", __func__); |
| 1087 | 1089 | p->u.qpsk.symbol_rate = c->symbol_rate; |
| 1088 | 1090 | p->u.qpsk.fec_inner = c->fec_inner; |
| 1089 | − c->delivery_system = SYS_DVBS; | |
| 1090 | 1091 | break; |
| 1091 | 1092 | case FE_QAM: |
| 1092 | 1093 | dprintk("%s() Preparing QAM req\n", __func__); |
| 1093 | 1094 | p->u.qam.symbol_rate = c->symbol_rate; |
| 1094 | 1095 | p->u.qam.fec_inner = c->fec_inner; |
| 1095 | 1096 | p->u.qam.modulation = c->modulation; |
| 1096 | − c->delivery_system = SYS_DVBC_ANNEX_AC; | |
| 1097 | 1097 | break; |
| 1098 | 1098 | case FE_OFDM: |
| 1099 | 1099 | dprintk("%s() Preparing OFDM req\n", __func__); |
| @@ -1111,15 +1111,10 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) · 11 unmodified lines | ||
| 1111 | 1111 | p->u.ofdm.transmission_mode = c->transmission_mode; |
| 1112 | 1112 | p->u.ofdm.guard_interval = c->guard_interval; |
| 1113 | 1113 | p->u.ofdm.hierarchy_information = c->hierarchy; |
| 1114 | − c->delivery_system = SYS_DVBT; | |
| 1115 | 1114 | break; |
| 1116 | 1115 | case FE_ATSC: |
| 1117 | 1116 | dprintk("%s() Preparing VSB req\n", __func__); |
| 1118 | 1117 | p->u.vsb.modulation = c->modulation; |
| 1119 | − if ((c->modulation == VSB_8) || (c->modulation == VSB_16)) | |
| 1120 | − c->delivery_system = SYS_ATSC; | |
| 1121 | − else | |
| 1122 | − c->delivery_system = SYS_DVBC_ANNEX_B; | |
| 1123 | 1118 | break; |
| 1124 | 1119 | } |
| 1125 | 1120 | } |
| @@ -1129,9 +1124,9 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) · 3 unmodified lines | ||
| 1129 | 1124 | */ |
| 1130 | 1125 | static void dtv_property_adv_params_sync(struct dvb_frontend *fe) |
| 1131 | 1126 | { |
| 1132 | − struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 1127 | + const struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 1133 | 1128 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
| 1134 | − struct dvb_frontend_parameters *p = &fepriv->parameters; | |
| 1129 | + struct dvb_frontend_parameters *p = &fepriv->parameters_in; | |
| 1135 | 1130 | |
| 1136 | 1131 | p->frequency = c->frequency; |
| 1137 | 1132 | p->inversion = c->inversion; |
| @@ -1148,10 +1143,9 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe) · 10 unmodified lines | ||
| 1148 | 1143 | break; |
| 1149 | 1144 | } |
| 1150 | 1145 | |
| 1151 | − if(c->delivery_system == SYS_ISDBT) { | |
| 1152 | − /* Fake out a generic DVB-T request so we pass validation in the ioctl */ | |
| 1153 | − p->frequency = c->frequency; | |
| 1154 | − p->inversion = c->inversion; | |
| 1146 | + /* Fake out a generic DVB-T request so we pass validation in the ioctl */ | |
| 1147 | + if ((c->delivery_system == SYS_ISDBT) || | |
| 1148 | + (c->delivery_system == SYS_DVBT2)) { | |
| 1155 | 1149 | p->u.ofdm.constellation = QAM_AUTO; |
| 1156 | 1150 | p->u.ofdm.code_rate_HP = FEC_AUTO; |
| 1157 | 1151 | p->u.ofdm.code_rate_LP = FEC_AUTO; |
| @@ -1171,7 +1165,7 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe) · 13 unmodified lines | ||
| 1171 | 1165 | |
| 1172 | 1166 | static void dtv_property_cache_submit(struct dvb_frontend *fe) |
| 1173 | 1167 | { |
| 1174 | − struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 1168 | + const struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 1175 | 1169 | |
| 1176 | 1170 | /* For legacy delivery systems we don't need the delivery_system to |
| 1177 | 1171 | * 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, · 26 unmodified lines | ||
| 1204 | 1198 | struct dtv_property *tvp, |
| 1205 | 1199 | struct file *file) |
| 1206 | 1200 | { |
| 1207 | − int r = 0; | |
| 1208 | − | |
| 1209 | − /* Allow the frontend to validate incoming properties */ | |
| 1210 | − if (fe->ops.get_property) | |
| 1211 | − r = fe->ops.get_property(fe, tvp); | |
| 1201 | + const struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 1202 | + struct dvb_frontend_private *fepriv = fe->frontend_priv; | |
| 1203 | + struct dtv_frontend_properties cdetected; | |
| 1204 | + int r; | |
| 1212 | 1205 | |
| 1213 | − if (r < 0) | |
| 1214 | − return r; | |
| 1206 | + /* | |
| 1207 | + * If the driver implements a get_frontend function, then convert | |
| 1208 | + * detected parameters to S2API properties. | |
| 1209 | + */ | |
| 1210 | + if (fe->ops.get_frontend) { | |
| 1211 | + cdetected = *c; | |
| 1212 | + dtv_property_cache_sync(fe, &cdetected, &fepriv->parameters_out); | |
| 1213 | + c = &cdetected; | |
| 1214 | + } | |
| 1215 | 1215 | |
| 1216 | 1216 | switch(tvp->cmd) { |
| 1217 | 1217 | case DTV_FREQUENCY: |
| 1218 | − tvp->u.data = fe->dtv_property_cache.frequency; | |
| 1218 | + tvp->u.data = c->frequency; | |
| 1219 | 1219 | break; |
| 1220 | 1220 | case DTV_MODULATION: |
| 1221 | − tvp->u.data = fe->dtv_property_cache.modulation; | |
| 1221 | + tvp->u.data = c->modulation; | |
| 1222 | 1222 | break; |
| 1223 | 1223 | case DTV_BANDWIDTH_HZ: |
| 1224 | − tvp->u.data = fe->dtv_property_cache.bandwidth_hz; | |
| 1224 | + tvp->u.data = c->bandwidth_hz; | |
| 1225 | 1225 | break; |
| 1226 | 1226 | case DTV_INVERSION: |
| 1227 | − tvp->u.data = fe->dtv_property_cache.inversion; | |
| 1227 | + tvp->u.data = c->inversion; | |
| 1228 | 1228 | break; |
| 1229 | 1229 | case DTV_SYMBOL_RATE: |
| 1230 | − tvp->u.data = fe->dtv_property_cache.symbol_rate; | |
| 1230 | + tvp->u.data = c->symbol_rate; | |
| 1231 | 1231 | break; |
| 1232 | 1232 | case DTV_INNER_FEC: |
| 1233 | − tvp->u.data = fe->dtv_property_cache.fec_inner; | |
| 1233 | + tvp->u.data = c->fec_inner; | |
| 1234 | 1234 | break; |
| 1235 | 1235 | case DTV_PILOT: |
| 1236 | − tvp->u.data = fe->dtv_property_cache.pilot; | |
| 1236 | + tvp->u.data = c->pilot; | |
| 1237 | 1237 | break; |
| 1238 | 1238 | case DTV_ROLLOFF: |
| 1239 | − tvp->u.data = fe->dtv_property_cache.rolloff; | |
| 1239 | + tvp->u.data = c->rolloff; | |
| 1240 | 1240 | break; |
| 1241 | 1241 | case DTV_DELIVERY_SYSTEM: |
| 1242 | − tvp->u.data = fe->dtv_property_cache.delivery_system; | |
| 1242 | + tvp->u.data = c->delivery_system; | |
| 1243 | 1243 | break; |
| 1244 | 1244 | case DTV_VOLTAGE: |
| 1245 | − tvp->u.data = fe->dtv_property_cache.voltage; | |
| 1245 | + tvp->u.data = c->voltage; | |
| 1246 | 1246 | break; |
| 1247 | 1247 | case DTV_TONE: |
| 1248 | − tvp->u.data = fe->dtv_property_cache.sectone; | |
| 1248 | + tvp->u.data = c->sectone; | |
| 1249 | 1249 | break; |
| 1250 | 1250 | case DTV_API_VERSION: |
| 1251 | 1251 | tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR; |
| 1252 | 1252 | break; |
| 1253 | 1253 | case DTV_CODE_RATE_HP: |
| 1254 | − tvp->u.data = fe->dtv_property_cache.code_rate_HP; | |
| 1254 | + tvp->u.data = c->code_rate_HP; | |
| 1255 | 1255 | break; |
| 1256 | 1256 | case DTV_CODE_RATE_LP: |
| 1257 | − tvp->u.data = fe->dtv_property_cache.code_rate_LP; | |
| 1257 | + tvp->u.data = c->code_rate_LP; | |
| 1258 | 1258 | break; |
| 1259 | 1259 | case DTV_GUARD_INTERVAL: |
| 1260 | − tvp->u.data = fe->dtv_property_cache.guard_interval; | |
| 1260 | + tvp->u.data = c->guard_interval; | |
| 1261 | 1261 | break; |
| 1262 | 1262 | case DTV_TRANSMISSION_MODE: |
| 1263 | − tvp->u.data = fe->dtv_property_cache.transmission_mode; | |
| 1263 | + tvp->u.data = c->transmission_mode; | |
| 1264 | 1264 | break; |
| 1265 | 1265 | case DTV_HIERARCHY: |
| 1266 | − tvp->u.data = fe->dtv_property_cache.hierarchy; | |
| 1266 | + tvp->u.data = c->hierarchy; | |
| 1267 | 1267 | break; |
| 1268 | 1268 | |
| 1269 | 1269 | /* ISDB-T Support here */ |
| 1270 | 1270 | case DTV_ISDBT_PARTIAL_RECEPTION: |
| 1271 | − tvp->u.data = fe->dtv_property_cache.isdbt_partial_reception; | |
| 1271 | + tvp->u.data = c->isdbt_partial_reception; | |
| 1272 | 1272 | break; |
| 1273 | 1273 | case DTV_ISDBT_SOUND_BROADCASTING: |
| 1274 | − tvp->u.data = fe->dtv_property_cache.isdbt_sb_mode; | |
| 1274 | + tvp->u.data = c->isdbt_sb_mode; | |
| 1275 | 1275 | break; |
| 1276 | 1276 | case DTV_ISDBT_SB_SUBCHANNEL_ID: |
| 1277 | − tvp->u.data = fe->dtv_property_cache.isdbt_sb_subchannel; | |
| 1277 | + tvp->u.data = c->isdbt_sb_subchannel; | |
| 1278 | 1278 | break; |
| 1279 | 1279 | case DTV_ISDBT_SB_SEGMENT_IDX: |
| 1280 | − tvp->u.data = fe->dtv_property_cache.isdbt_sb_segment_idx; | |
| 1280 | + tvp->u.data = c->isdbt_sb_segment_idx; | |
| 1281 | 1281 | break; |
| 1282 | 1282 | case DTV_ISDBT_SB_SEGMENT_COUNT: |
| 1283 | − tvp->u.data = fe->dtv_property_cache.isdbt_sb_segment_count; | |
| 1283 | + tvp->u.data = c->isdbt_sb_segment_count; | |
| 1284 | 1284 | break; |
| 1285 | 1285 | case DTV_ISDBT_LAYER_ENABLED: |
| 1286 | − tvp->u.data = fe->dtv_property_cache.isdbt_layer_enabled; | |
| 1286 | + tvp->u.data = c->isdbt_layer_enabled; | |
| 1287 | 1287 | break; |
| 1288 | 1288 | case DTV_ISDBT_LAYERA_FEC: |
| 1289 | − tvp->u.data = fe->dtv_property_cache.layer[0].fec; | |
| 1289 | + tvp->u.data = c->layer[0].fec; | |
| 1290 | 1290 | break; |
| 1291 | 1291 | case DTV_ISDBT_LAYERA_MODULATION: |
| 1292 | − tvp->u.data = fe->dtv_property_cache.layer[0].modulation; | |
| 1292 | + tvp->u.data = c->layer[0].modulation; | |
| 1293 | 1293 | break; |
| 1294 | 1294 | case DTV_ISDBT_LAYERA_SEGMENT_COUNT: |
| 1295 | − tvp->u.data = fe->dtv_property_cache.layer[0].segment_count; | |
| 1295 | + tvp->u.data = c->layer[0].segment_count; | |
| 1296 | 1296 | break; |
| 1297 | 1297 | case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: |
| 1298 | − tvp->u.data = fe->dtv_property_cache.layer[0].interleaving; | |
| 1298 | + tvp->u.data = c->layer[0].interleaving; | |
| 1299 | 1299 | break; |
| 1300 | 1300 | case DTV_ISDBT_LAYERB_FEC: |
| 1301 | − tvp->u.data = fe->dtv_property_cache.layer[1].fec; | |
| 1301 | + tvp->u.data = c->layer[1].fec; | |
| 1302 | 1302 | break; |
| 1303 | 1303 | case DTV_ISDBT_LAYERB_MODULATION: |
| 1304 | − tvp->u.data = fe->dtv_property_cache.layer[1].modulation; | |
| 1304 | + tvp->u.data = c->layer[1].modulation; | |
| 1305 | 1305 | break; |
| 1306 | 1306 | case DTV_ISDBT_LAYERB_SEGMENT_COUNT: |
| 1307 | − tvp->u.data = fe->dtv_property_cache.layer[1].segment_count; | |
| 1307 | + tvp->u.data = c->layer[1].segment_count; | |
| 1308 | 1308 | break; |
| 1309 | 1309 | case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: |
| 1310 | − tvp->u.data = fe->dtv_property_cache.layer[1].interleaving; | |
| 1310 | + tvp->u.data = c->layer[1].interleaving; | |
| 1311 | 1311 | break; |
| 1312 | 1312 | case DTV_ISDBT_LAYERC_FEC: |
| 1313 | − tvp->u.data = fe->dtv_property_cache.layer[2].fec; | |
| 1313 | + tvp->u.data = c->layer[2].fec; | |
| 1314 | 1314 | break; |
| 1315 | 1315 | case DTV_ISDBT_LAYERC_MODULATION: |
| 1316 | − tvp->u.data = fe->dtv_property_cache.layer[2].modulation; | |
| 1316 | + tvp->u.data = c->layer[2].modulation; | |
| 1317 | 1317 | break; |
| 1318 | 1318 | case DTV_ISDBT_LAYERC_SEGMENT_COUNT: |
| 1319 | − tvp->u.data = fe->dtv_property_cache.layer[2].segment_count; | |
| 1319 | + tvp->u.data = c->layer[2].segment_count; | |
| 1320 | 1320 | break; |
| 1321 | 1321 | case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: |
| 1322 | − tvp->u.data = fe->dtv_property_cache.layer[2].interleaving; | |
| 1322 | + tvp->u.data = c->layer[2].interleaving; | |
| 1323 | 1323 | break; |
| 1324 | 1324 | case DTV_ISDBS_TS_ID: |
| 1325 | − tvp->u.data = fe->dtv_property_cache.isdbs_ts_id; | |
| 1325 | + tvp->u.data = c->isdbs_ts_id; | |
| 1326 | + break; | |
| 1327 | + case DTV_DVBT2_PLP_ID: | |
| 1328 | + tvp->u.data = c->dvbt2_plp_id; | |
| 1326 | 1329 | break; |
| 1327 | 1330 | default: |
| 1328 | − r = -1; | |
| 1331 | + return -EINVAL; | |
| 1332 | + } | |
| 1333 | + | |
| 1334 | + /* Allow the frontend to override outgoing properties */ | |
| 1335 | + if (fe->ops.get_property) { | |
| 1336 | + r = fe->ops.get_property(fe, tvp); | |
| 1337 | + if (r < 0) | |
| 1338 | + return r; | |
| 1329 | 1339 | } |
| 1330 | 1340 | |
| 1331 | 1341 | dtv_property_dump(tvp); |
| 1332 | 1342 | |
| 1333 | − return r; | |
| 1343 | + return 0; | |
| 1334 | 1344 | } |
| 1335 | 1345 | |
| 1336 | 1346 | static int dtv_property_process_set(struct dvb_frontend *fe, |
| @@ -1338,15 +1348,16 @@ static int dtv_property_process_set(struct dvb_frontend *fe, · 1 unmodified line | ||
| 1338 | 1348 | struct file *file) |
| 1339 | 1349 | { |
| 1340 | 1350 | int r = 0; |
| 1351 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 1341 | 1352 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
| 1342 | 1353 | dtv_property_dump(tvp); |
| 1343 | 1354 | |
| 1344 | 1355 | /* Allow the frontend to validate incoming properties */ |
| 1345 | − if (fe->ops.set_property) | |
| 1356 | + if (fe->ops.set_property) { | |
| 1346 | 1357 | r = fe->ops.set_property(fe, tvp); |
| 1347 | − | |
| 1348 | − if (r < 0) | |
| 1349 | − return r; | |
| 1358 | + if (r < 0) | |
| 1359 | + return r; | |
| 1360 | + } | |
| 1350 | 1361 | |
| 1351 | 1362 | switch(tvp->cmd) { |
| 1352 | 1363 | case DTV_CLEAR: |
| @@ -1361,126 +1372,129 @@ static int dtv_property_process_set(struct dvb_frontend *fe, · 8 unmodified lines | ||
| 1361 | 1372 | * tunerequest so we can pass validation in the FE_SET_FRONTEND |
| 1362 | 1373 | * ioctl. |
| 1363 | 1374 | */ |
| 1364 | − fe->dtv_property_cache.state = tvp->cmd; | |
| 1375 | + c->state = tvp->cmd; | |
| 1365 | 1376 | dprintk("%s() Finalised property cache\n", __func__); |
| 1366 | 1377 | dtv_property_cache_submit(fe); |
| 1367 | 1378 | |
| 1368 | − r |= dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND, | |
| 1369 | − &fepriv->parameters); | |
| 1379 | + r = dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND, | |
| 1380 | + &fepriv->parameters_in); | |
| 1370 | 1381 | break; |
| 1371 | 1382 | case DTV_FREQUENCY: |
| 1372 | − fe->dtv_property_cache.frequency = tvp->u.data; | |
| 1383 | + c->frequency = tvp->u.data; | |
| 1373 | 1384 | break; |
| 1374 | 1385 | case DTV_MODULATION: |
| 1375 | − fe->dtv_property_cache.modulation = tvp->u.data; | |
| 1386 | + c->modulation = tvp->u.data; | |
| 1376 | 1387 | break; |
| 1377 | 1388 | case DTV_BANDWIDTH_HZ: |
| 1378 | − fe->dtv_property_cache.bandwidth_hz = tvp->u.data; | |
| 1389 | + c->bandwidth_hz = tvp->u.data; | |
| 1379 | 1390 | break; |
| 1380 | 1391 | case DTV_INVERSION: |
| 1381 | − fe->dtv_property_cache.inversion = tvp->u.data; | |
| 1392 | + c->inversion = tvp->u.data; | |
| 1382 | 1393 | break; |
| 1383 | 1394 | case DTV_SYMBOL_RATE: |
| 1384 | − fe->dtv_property_cache.symbol_rate = tvp->u.data; | |
| 1395 | + c->symbol_rate = tvp->u.data; | |
| 1385 | 1396 | break; |
| 1386 | 1397 | case DTV_INNER_FEC: |
| 1387 | − fe->dtv_property_cache.fec_inner = tvp->u.data; | |
| 1398 | + c->fec_inner = tvp->u.data; | |
| 1388 | 1399 | break; |
| 1389 | 1400 | case DTV_PILOT: |
| 1390 | − fe->dtv_property_cache.pilot = tvp->u.data; | |
| 1401 | + c->pilot = tvp->u.data; | |
| 1391 | 1402 | break; |
| 1392 | 1403 | case DTV_ROLLOFF: |
| 1393 | − fe->dtv_property_cache.rolloff = tvp->u.data; | |
| 1404 | + c->rolloff = tvp->u.data; | |
| 1394 | 1405 | break; |
| 1395 | 1406 | case DTV_DELIVERY_SYSTEM: |
| 1396 | − fe->dtv_property_cache.delivery_system = tvp->u.data; | |
| 1407 | + c->delivery_system = tvp->u.data; | |
| 1397 | 1408 | break; |
| 1398 | 1409 | case DTV_VOLTAGE: |
| 1399 | − fe->dtv_property_cache.voltage = tvp->u.data; | |
| 1410 | + c->voltage = tvp->u.data; | |
| 1400 | 1411 | r = dvb_frontend_ioctl_legacy(file, FE_SET_VOLTAGE, |
| 1401 | − (void *)fe->dtv_property_cache.voltage); | |
| 1412 | + (void *)c->voltage); | |
| 1402 | 1413 | break; |
| 1403 | 1414 | case DTV_TONE: |
| 1404 | − fe->dtv_property_cache.sectone = tvp->u.data; | |
| 1415 | + c->sectone = tvp->u.data; | |
| 1405 | 1416 | r = dvb_frontend_ioctl_legacy(file, FE_SET_TONE, |
| 1406 | − (void *)fe->dtv_property_cache.sectone); | |
| 1417 | + (void *)c->sectone); | |
| 1407 | 1418 | break; |
| 1408 | 1419 | case DTV_CODE_RATE_HP: |
| 1409 | − fe->dtv_property_cache.code_rate_HP = tvp->u.data; | |
| 1420 | + c->code_rate_HP = tvp->u.data; | |
| 1410 | 1421 | break; |
| 1411 | 1422 | case DTV_CODE_RATE_LP: |
| 1412 | − fe->dtv_property_cache.code_rate_LP = tvp->u.data; | |
| 1423 | + c->code_rate_LP = tvp->u.data; | |
| 1413 | 1424 | break; |
| 1414 | 1425 | case DTV_GUARD_INTERVAL: |
| 1415 | − fe->dtv_property_cache.guard_interval = tvp->u.data; | |
| 1426 | + c->guard_interval = tvp->u.data; | |
| 1416 | 1427 | break; |
| 1417 | 1428 | case DTV_TRANSMISSION_MODE: |
| 1418 | − fe->dtv_property_cache.transmission_mode = tvp->u.data; | |
| 1429 | + c->transmission_mode = tvp->u.data; | |
| 1419 | 1430 | break; |
| 1420 | 1431 | case DTV_HIERARCHY: |
| 1421 | − fe->dtv_property_cache.hierarchy = tvp->u.data; | |
| 1432 | + c->hierarchy = tvp->u.data; | |
| 1422 | 1433 | break; |
| 1423 | 1434 | |
| 1424 | 1435 | /* ISDB-T Support here */ |
| 1425 | 1436 | case DTV_ISDBT_PARTIAL_RECEPTION: |
| 1426 | − fe->dtv_property_cache.isdbt_partial_reception = tvp->u.data; | |
| 1437 | + c->isdbt_partial_reception = tvp->u.data; | |
| 1427 | 1438 | break; |
| 1428 | 1439 | case DTV_ISDBT_SOUND_BROADCASTING: |
| 1429 | − fe->dtv_property_cache.isdbt_sb_mode = tvp->u.data; | |
| 1440 | + c->isdbt_sb_mode = tvp->u.data; | |
| 1430 | 1441 | break; |
| 1431 | 1442 | case DTV_ISDBT_SB_SUBCHANNEL_ID: |
| 1432 | − fe->dtv_property_cache.isdbt_sb_subchannel = tvp->u.data; | |
| 1443 | + c->isdbt_sb_subchannel = tvp->u.data; | |
| 1433 | 1444 | break; |
| 1434 | 1445 | case DTV_ISDBT_SB_SEGMENT_IDX: |
| 1435 | − fe->dtv_property_cache.isdbt_sb_segment_idx = tvp->u.data; | |
| 1446 | + c->isdbt_sb_segment_idx = tvp->u.data; | |
| 1436 | 1447 | break; |
| 1437 | 1448 | case DTV_ISDBT_SB_SEGMENT_COUNT: |
| 1438 | − fe->dtv_property_cache.isdbt_sb_segment_count = tvp->u.data; | |
| 1449 | + c->isdbt_sb_segment_count = tvp->u.data; | |
| 1439 | 1450 | break; |
| 1440 | 1451 | case DTV_ISDBT_LAYER_ENABLED: |
| 1441 | − fe->dtv_property_cache.isdbt_layer_enabled = tvp->u.data; | |
| 1452 | + c->isdbt_layer_enabled = tvp->u.data; | |
| 1442 | 1453 | break; |
| 1443 | 1454 | case DTV_ISDBT_LAYERA_FEC: |
| 1444 | − fe->dtv_property_cache.layer[0].fec = tvp->u.data; | |
| 1455 | + c->layer[0].fec = tvp->u.data; | |
| 1445 | 1456 | break; |
| 1446 | 1457 | case DTV_ISDBT_LAYERA_MODULATION: |
| 1447 | − fe->dtv_property_cache.layer[0].modulation = tvp->u.data; | |
| 1458 | + c->layer[0].modulation = tvp->u.data; | |
| 1448 | 1459 | break; |
| 1449 | 1460 | case DTV_ISDBT_LAYERA_SEGMENT_COUNT: |
| 1450 | − fe->dtv_property_cache.layer[0].segment_count = tvp->u.data; | |
| 1461 | + c->layer[0].segment_count = tvp->u.data; | |
| 1451 | 1462 | break; |
| 1452 | 1463 | case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: |
| 1453 | − fe->dtv_property_cache.layer[0].interleaving = tvp->u.data; | |
| 1464 | + c->layer[0].interleaving = tvp->u.data; | |
| 1454 | 1465 | break; |
| 1455 | 1466 | case DTV_ISDBT_LAYERB_FEC: |
| 1456 | − fe->dtv_property_cache.layer[1].fec = tvp->u.data; | |
| 1467 | + c->layer[1].fec = tvp->u.data; | |
| 1457 | 1468 | break; |
| 1458 | 1469 | case DTV_ISDBT_LAYERB_MODULATION: |
| 1459 | − fe->dtv_property_cache.layer[1].modulation = tvp->u.data; | |
| 1470 | + c->layer[1].modulation = tvp->u.data; | |
| 1460 | 1471 | break; |
| 1461 | 1472 | case DTV_ISDBT_LAYERB_SEGMENT_COUNT: |
| 1462 | − fe->dtv_property_cache.layer[1].segment_count = tvp->u.data; | |
| 1473 | + c->layer[1].segment_count = tvp->u.data; | |
| 1463 | 1474 | break; |
| 1464 | 1475 | case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: |
| 1465 | − fe->dtv_property_cache.layer[1].interleaving = tvp->u.data; | |
| 1476 | + c->layer[1].interleaving = tvp->u.data; | |
| 1466 | 1477 | break; |
| 1467 | 1478 | case DTV_ISDBT_LAYERC_FEC: |
| 1468 | − fe->dtv_property_cache.layer[2].fec = tvp->u.data; | |
| 1479 | + c->layer[2].fec = tvp->u.data; | |
| 1469 | 1480 | break; |
| 1470 | 1481 | case DTV_ISDBT_LAYERC_MODULATION: |
| 1471 | − fe->dtv_property_cache.layer[2].modulation = tvp->u.data; | |
| 1482 | + c->layer[2].modulation = tvp->u.data; | |
| 1472 | 1483 | break; |
| 1473 | 1484 | case DTV_ISDBT_LAYERC_SEGMENT_COUNT: |
| 1474 | − fe->dtv_property_cache.layer[2].segment_count = tvp->u.data; | |
| 1485 | + c->layer[2].segment_count = tvp->u.data; | |
| 1475 | 1486 | break; |
| 1476 | 1487 | case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: |
| 1477 | − fe->dtv_property_cache.layer[2].interleaving = tvp->u.data; | |
| 1488 | + c->layer[2].interleaving = tvp->u.data; | |
| 1478 | 1489 | break; |
| 1479 | 1490 | case DTV_ISDBS_TS_ID: |
| 1480 | − fe->dtv_property_cache.isdbs_ts_id = tvp->u.data; | |
| 1491 | + c->isdbs_ts_id = tvp->u.data; | |
| 1492 | + break; | |
| 1493 | + case DTV_DVBT2_PLP_ID: | |
| 1494 | + c->dvbt2_plp_id = tvp->u.data; | |
| 1481 | 1495 | break; |
| 1482 | 1496 | default: |
| 1483 | − r = -1; | |
| 1497 | + return -EINVAL; | |
| 1484 | 1498 | } |
| 1485 | 1499 | |
| 1486 | 1500 | return r; |
| @@ -1491,6 +1505,7 @@ static int dvb_frontend_ioctl(struct file *file, · 4 unmodified lines | ||
| 1491 | 1505 | { |
| 1492 | 1506 | struct dvb_device *dvbdev = file->private_data; |
| 1493 | 1507 | struct dvb_frontend *fe = dvbdev->priv; |
| 1508 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 1494 | 1509 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
| 1495 | 1510 | int err = -EOPNOTSUPP; |
| 1496 | 1511 | |
| @@ -1510,7 +1525,7 @@ static int dvb_frontend_ioctl(struct file *file, · 13 unmodified lines | ||
| 1510 | 1525 | if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY)) |
| 1511 | 1526 | err = dvb_frontend_ioctl_properties(file, cmd, parg); |
| 1512 | 1527 | else { |
| 1513 | − fe->dtv_property_cache.state = DTV_UNDEFINED; | |
| 1528 | + c->state = DTV_UNDEFINED; | |
| 1514 | 1529 | err = dvb_frontend_ioctl_legacy(file, cmd, parg); |
| 1515 | 1530 | } |
| 1516 | 1531 | |
| @@ -1523,6 +1538,7 @@ static int dvb_frontend_ioctl_properties(struct file *file, · 6 unmodified lines | ||
| 1523 | 1538 | { |
| 1524 | 1539 | struct dvb_device *dvbdev = file->private_data; |
| 1525 | 1540 | struct dvb_frontend *fe = dvbdev->priv; |
| 1541 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 1526 | 1542 | int err = 0; |
| 1527 | 1543 | |
| 1528 | 1544 | struct dtv_properties *tvps = NULL; |
| @@ -1554,11 +1570,13 @@ static int dvb_frontend_ioctl_properties(struct file *file, · 25 unmodified lines | ||
| 1554 | 1570 | } |
| 1555 | 1571 | |
| 1556 | 1572 | for (i = 0; i < tvps->num; i++) { |
| 1557 | − (tvp + i)->result = dtv_property_process_set(fe, tvp + i, file); | |
| 1558 | − err |= (tvp + i)->result; | |
| 1573 | + err = dtv_property_process_set(fe, tvp + i, file); | |
| 1574 | + if (err < 0) | |
| 1575 | + goto out; | |
| 1576 | + (tvp + i)->result = err; | |
| 1559 | 1577 | } |
| 1560 | 1578 | |
| 1561 | − if(fe->dtv_property_cache.state == DTV_TUNE) | |
| 1579 | + if (c->state == DTV_TUNE) | |
| 1562 | 1580 | dprintk("%s() Property cache is full, tuning\n", __func__); |
| 1563 | 1581 | |
| 1564 | 1582 | } else |
| @@ -1586,8 +1604,10 @@ static int dvb_frontend_ioctl_properties(struct file *file, · 21 unmodified lines | ||
| 1586 | 1604 | } |
| 1587 | 1605 | |
| 1588 | 1606 | for (i = 0; i < tvps->num; i++) { |
| 1589 | − (tvp + i)->result = dtv_property_process_get(fe, tvp + i, file); | |
| 1590 | − err |= (tvp + i)->result; | |
| 1607 | + err = dtv_property_process_get(fe, tvp + i, file); | |
| 1608 | + if (err < 0) | |
| 1609 | + goto out; | |
| 1610 | + (tvp + i)->result = err; | |
| 1591 | 1611 | } |
| 1592 | 1612 | |
| 1593 | 1613 | 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, · 193 unmodified lines | ||
| 1787 | 1807 | break; |
| 1788 | 1808 | |
| 1789 | 1809 | case FE_SET_FRONTEND: { |
| 1810 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 1790 | 1811 | struct dvb_frontend_tune_settings fetunesettings; |
| 1791 | 1812 | |
| 1792 | − if(fe->dtv_property_cache.state == DTV_TUNE) { | |
| 1793 | − if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) { | |
| 1813 | + if (c->state == DTV_TUNE) { | |
| 1814 | + if (dvb_frontend_check_parameters(fe, &fepriv->parameters_in) < 0) { | |
| 1794 | 1815 | err = -EINVAL; |
| 1795 | 1816 | break; |
| 1796 | 1817 | } |
| @@ -1800,9 +1821,9 @@ static int dvb_frontend_ioctl_legacy(struct file *file, · 3 unmodified lines | ||
| 1800 | 1821 | break; |
| 1801 | 1822 | } |
| 1802 | 1823 | |
| 1803 | − memcpy (&fepriv->parameters, parg, | |
| 1824 | + memcpy (&fepriv->parameters_in, parg, | |
| 1804 | 1825 | sizeof (struct dvb_frontend_parameters)); |
| 1805 | − dtv_property_cache_sync(fe, &fepriv->parameters); | |
| 1826 | + dtv_property_cache_sync(fe, c, &fepriv->parameters_in); | |
| 1806 | 1827 | } |
| 1807 | 1828 | |
| 1808 | 1829 | memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings)); |
| @@ -1811,15 +1832,15 @@ static int dvb_frontend_ioctl_legacy(struct file *file, · 2 unmodified lines | ||
| 1811 | 1832 | |
| 1812 | 1833 | /* force auto frequency inversion if requested */ |
| 1813 | 1834 | if (dvb_force_auto_inversion) { |
| 1814 | − fepriv->parameters.inversion = INVERSION_AUTO; | |
| 1835 | + fepriv->parameters_in.inversion = INVERSION_AUTO; | |
| 1815 | 1836 | fetunesettings.parameters.inversion = INVERSION_AUTO; |
| 1816 | 1837 | } |
| 1817 | 1838 | if (fe->ops.info.type == FE_OFDM) { |
| 1818 | 1839 | /* without hierarchical coding code_rate_LP is irrelevant, |
| 1819 | 1840 | * so we tolerate the otherwise invalid FEC_NONE setting */ |
| 1820 | − if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE && | |
| 1821 | − fepriv->parameters.u.ofdm.code_rate_LP == FEC_NONE) | |
| 1822 | − fepriv->parameters.u.ofdm.code_rate_LP = FEC_AUTO; | |
| 1841 | + if (fepriv->parameters_in.u.ofdm.hierarchy_information == HIERARCHY_NONE && | |
| 1842 | + fepriv->parameters_in.u.ofdm.code_rate_LP == FEC_NONE) | |
| 1843 | + fepriv->parameters_in.u.ofdm.code_rate_LP = FEC_AUTO; | |
| 1823 | 1844 | } |
| 1824 | 1845 | |
| 1825 | 1846 | /* get frontend-specific tuning settings */ |
| @@ -1832,8 +1853,8 @@ static int dvb_frontend_ioctl_legacy(struct file *file, · 6 unmodified lines | ||
| 1832 | 1853 | switch(fe->ops.info.type) { |
| 1833 | 1854 | case FE_QPSK: |
| 1834 | 1855 | fepriv->min_delay = HZ/20; |
| 1835 | − fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000; | |
| 1836 | − fepriv->max_drift = fepriv->parameters.u.qpsk.symbol_rate / 2000; | |
| 1856 | + fepriv->step_size = fepriv->parameters_in.u.qpsk.symbol_rate / 16000; | |
| 1857 | + fepriv->max_drift = fepriv->parameters_in.u.qpsk.symbol_rate / 2000; | |
| 1837 | 1858 | break; |
| 1838 | 1859 | |
| 1839 | 1860 | case FE_QAM: |
| @@ -1875,8 +1896,8 @@ static int dvb_frontend_ioctl_legacy(struct file *file, · 35 unmodified lines | ||
| 1875 | 1896 | |
| 1876 | 1897 | case FE_GET_FRONTEND: |
| 1877 | 1898 | if (fe->ops.get_frontend) { |
| 1878 | − memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters)); | |
| 1879 | − err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg); | |
| 1899 | + err = fe->ops.get_frontend(fe, &fepriv->parameters_out); | |
| 1900 | + memcpy(parg, &fepriv->parameters_out, sizeof(struct dvb_frontend_parameters)); | |
| 1880 | 1901 | } |
| 1881 | 1902 | break; |
| 1882 | 1903 | |
| @@ -358,6 +358,9 @@ struct dtv_frontend_properties { · 357 unmodified lines | ||
| 358 | 358 | |
| 359 | 359 | /* ISDB-T specifics */ |
| 360 | 360 | u32 isdbs_ts_id; |
| 361 | + | |
| 362 | + /* DVB-T2 specifics */ | |
| 363 | + u32 dvbt2_plp_id; | |
| 361 | 364 | }; |
| 362 | 365 | |
| 363 | 366 | struct dvb_frontend { |
| @@ -292,6 +292,11 @@ config DVB_USB_ANYSEE · 291 unmodified lines | ||
| 292 | 292 | select DVB_MT352 if !DVB_FE_CUSTOMISE |
| 293 | 293 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE |
| 294 | 294 | select DVB_TDA10023 if !DVB_FE_CUSTOMISE |
| 295 | + select MEDIA_TUNER_TDA18212 if !MEDIA_TUNER_CUSTOMISE | |
| 296 | + select DVB_CX24116 if !DVB_FE_CUSTOMISE | |
| 297 | + select DVB_STV0900 if !DVB_FE_CUSTOMISE | |
| 298 | + select DVB_STV6110 if !DVB_FE_CUSTOMISE | |
| 299 | + select DVB_ISL6423 if !DVB_FE_CUSTOMISE | |
| 295 | 300 | help |
| 296 | 301 | Say Y here to support the Anysee E30, Anysee E30 Plus or |
| 297 | 302 | Anysee E30 C Plus DVB USB2.0 receiver. |
| @@ -78,17 +78,26 @@ static struct rc_map_table rc_map_a800_table[] = { · 77 unmodified lines | ||
| 78 | 78 | |
| 79 | 79 | static int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state) |
| 80 | 80 | { |
| 81 | − u8 key[5]; | |
| 81 | + int ret; | |
| 82 | + u8 *key = kmalloc(5, GFP_KERNEL); | |
| 83 | + if (!key) | |
| 84 | + return -ENOMEM; | |
| 85 | + | |
| 82 | 86 | if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0), |
| 83 | 87 | 0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5, |
| 84 | − 2000) != 5) | |
| 85 | − return -ENODEV; | |
| 88 | + 2000) != 5) { | |
| 89 | + ret = -ENODEV; | |
| 90 | + goto out; | |
| 91 | + } | |
| 86 | 92 | |
| 87 | 93 | /* call the universal NEC remote processor, to find out the key's state and event */ |
| 88 | 94 | dvb_usb_nec_rc_key_to_event(d,key,event,state); |
| 89 | 95 | if (key[0] != 0) |
| 90 | 96 | deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); |
| 91 | − return 0; | |
| 97 | + ret = 0; | |
| 98 | +out: | |
| 99 | + kfree(key); | |
| 100 | + return ret; | |
| 92 | 101 | } |
| 93 | 102 | |
| 94 | 103 | /* USB Driver stuff */ |
| @@ -36,6 +36,11 @@ · 35 unmodified lines | ||
| 36 | 36 | #include "mt352.h" |
| 37 | 37 | #include "mt352_priv.h" |
| 38 | 38 | #include "zl10353.h" |
| 39 | +#include "tda18212.h" | |
| 40 | +#include "cx24116.h" | |
| 41 | +#include "stv0900.h" | |
| 42 | +#include "stv6110.h" | |
| 43 | +#include "isl6423.h" | |
| 39 | 44 | |
| 40 | 45 | /* debug */ |
| 41 | 46 | static int dvb_usb_anysee_debug; |
| @@ -105,6 +110,27 @@ static int anysee_write_reg(struct dvb_usb_device *d, u16 reg, u8 val) · 63 unmodified lines | ||
| 105 | 110 | return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); |
| 106 | 111 | } |
| 107 | 112 | |
| 113 | +/* write single register with mask */ | |
| 114 | +static int anysee_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val, | |
| 115 | + u8 mask) | |
| 116 | +{ | |
| 117 | + int ret; | |
| 118 | + u8 tmp; | |
| 119 | + | |
| 120 | + /* no need for read if whole reg is written */ | |
| 121 | + if (mask != 0xff) { | |
| 122 | + ret = anysee_read_reg(d, reg, &tmp); | |
| 123 | + if (ret) | |
| 124 | + return ret; | |
| 125 | + | |
| 126 | + val &= mask; | |
| 127 | + tmp &= ~mask; | |
| 128 | + val |= tmp; | |
| 129 | + } | |
| 130 | + | |
| 131 | + return anysee_write_reg(d, reg, val); | |
| 132 | +} | |
| 133 | + | |
| 108 | 134 | static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id) |
| 109 | 135 | { |
| 110 | 136 | u8 buf[] = {CMD_GET_HW_INFO}; |
| @@ -162,18 +188,18 @@ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, · 51 unmodified lines | ||
| 162 | 188 | if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { |
| 163 | 189 | u8 buf[6]; |
| 164 | 190 | buf[0] = CMD_I2C_READ; |
| 165 | − buf[1] = msg[i].addr + 1; | |
| 191 | + buf[1] = (msg[i].addr << 1) | 0x01; | |
| 166 | 192 | buf[2] = msg[i].buf[0]; |
| 167 | − buf[3] = 0x00; | |
| 168 | − buf[4] = 0x00; | |
| 169 | − buf[5] = 0x01; | |
| 193 | + buf[3] = msg[i].buf[1]; | |
| 194 | + buf[4] = msg[i].len-1; | |
| 195 | + buf[5] = msg[i+1].len; | |
| 170 | 196 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), msg[i+1].buf, |
| 171 | 197 | msg[i+1].len); |
| 172 | 198 | inc = 2; |
| 173 | 199 | } else { |
| 174 | 200 | u8 buf[4+msg[i].len]; |
| 175 | 201 | buf[0] = CMD_I2C_WRITE; |
| 176 | − buf[1] = msg[i].addr; | |
| 202 | + buf[1] = (msg[i].addr << 1); | |
| 177 | 203 | buf[2] = msg[i].len; |
| 178 | 204 | buf[3] = 0x01; |
| 179 | 205 | memcpy(&buf[4], msg[i].buf, msg[i].len); |
| @@ -224,7 +250,7 @@ static int anysee_mt352_demod_init(struct dvb_frontend *fe) · 44 unmodified lines | ||
| 224 | 250 | |
| 225 | 251 | /* Callbacks for DVB USB */ |
| 226 | 252 | static struct tda10023_config anysee_tda10023_config = { |
| 227 | − .demod_address = 0x1a, | |
| 253 | + .demod_address = (0x1a >> 1), | |
| 228 | 254 | .invert = 0, |
| 229 | 255 | .xtal = 16000000, |
| 230 | 256 | .pll_m = 11, |
| @@ -235,143 +261,539 @@ static struct tda10023_config anysee_tda10023_config = { · 4 unmodified lines | ||
| 235 | 261 | }; |
| 236 | 262 | |
| 237 | 263 | static struct mt352_config anysee_mt352_config = { |
| 238 | − .demod_address = 0x1e, | |
| 264 | + .demod_address = (0x1e >> 1), | |
| 239 | 265 | .demod_init = anysee_mt352_demod_init, |
| 240 | 266 | }; |
| 241 | 267 | |
| 242 | 268 | static struct zl10353_config anysee_zl10353_config = { |
| 243 | − .demod_address = 0x1e, | |
| 269 | + .demod_address = (0x1e >> 1), | |
| 244 | 270 | .parallel_ts = 1, |
| 245 | 271 | }; |
| 246 | 272 | |
| 273 | +static struct zl10353_config anysee_zl10353_tda18212_config2 = { | |
| 274 | + .demod_address = (0x1e >> 1), | |
| 275 | + .parallel_ts = 1, | |
| 276 | + .disable_i2c_gate_ctrl = 1, | |
| 277 | + .no_tuner = 1, | |
| 278 | + .if2 = 41500, | |
| 279 | +}; | |
| 280 | + | |
| 281 | +static struct zl10353_config anysee_zl10353_tda18212_config = { | |
| 282 | + .demod_address = (0x18 >> 1), | |
| 283 | + .parallel_ts = 1, | |
| 284 | + .disable_i2c_gate_ctrl = 1, | |
| 285 | + .no_tuner = 1, | |
| 286 | + .if2 = 41500, | |
| 287 | +}; | |
| 288 | + | |
| 289 | +static struct tda10023_config anysee_tda10023_tda18212_config = { | |
| 290 | + .demod_address = (0x1a >> 1), | |
| 291 | + .xtal = 16000000, | |
| 292 | + .pll_m = 12, | |
| 293 | + .pll_p = 3, | |
| 294 | + .pll_n = 1, | |
| 295 | + .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C, | |
| 296 | + .deltaf = 0xba02, | |
| 297 | +}; | |
| 298 | + | |
| 299 | +static struct tda18212_config anysee_tda18212_config = { | |
| 300 | + .i2c_address = (0xc0 >> 1), | |
| 301 | + .if_dvbt_6 = 4150, | |
| 302 | + .if_dvbt_7 = 4150, | |
| 303 | + .if_dvbt_8 = 4150, | |
| 304 | + .if_dvbc = 5000, | |
| 305 | +}; | |
| 306 | + | |
| 307 | +static struct cx24116_config anysee_cx24116_config = { | |
| 308 | + .demod_address = (0xaa >> 1), | |
| 309 | + .mpg_clk_pos_pol = 0x00, | |
| 310 | + .i2c_wr_max = 48, | |
| 311 | +}; | |
| 312 | + | |
| 313 | +static struct stv0900_config anysee_stv0900_config = { | |
| 314 | + .demod_address = (0xd0 >> 1), | |
| 315 | + .demod_mode = 0, | |
| 316 | + .xtal = 8000000, | |
| 317 | + .clkmode = 3, | |
| 318 | + .diseqc_mode = 2, | |
| 319 | + .tun1_maddress = 0, | |
| 320 | + .tun1_adc = 1, /* 1 Vpp */ | |
| 321 | + .path1_mode = 3, | |
| 322 | +}; | |
| 323 | + | |
| 324 | +static struct stv6110_config anysee_stv6110_config = { | |
| 325 | + .i2c_address = (0xc0 >> 1), | |
| 326 | + .mclk = 16000000, | |
| 327 | + .clk_div = 1, | |
| 328 | +}; | |
| 329 | + | |
| 330 | +static struct isl6423_config anysee_isl6423_config = { | |
| 331 | + .current_max = SEC_CURRENT_800m, | |
| 332 | + .curlim = SEC_CURRENT_LIM_OFF, | |
| 333 | + .mod_extern = 1, | |
| 334 | + .addr = (0x10 >> 1), | |
| 335 | +}; | |
| 336 | + | |
| 337 | +/* | |
| 338 | + * New USB device strings: Mfr=1, Product=2, SerialNumber=0 | |
| 339 | + * Manufacturer: AMT.CO.KR | |
| 340 | + * | |
| 341 | + * E30 VID=04b4 PID=861f HW=2 FW=2.1 Product=???????? | |
| 342 | + * PCB: ? | |
| 343 | + * parts: DNOS404ZH102A(MT352, DTT7579(?)) | |
| 344 | + * | |
| 345 | + * E30 VID=04b4 PID=861f HW=2 FW=2.1 Product=???????? | |
| 346 | + * PCB: ? | |
| 347 | + * parts: DNOS404ZH103A(ZL10353, DTT7579(?)) | |
| 348 | + * | |
| 349 | + * E30 Plus VID=04b4 PID=861f HW=6 FW=1.0 "anysee" | |
| 350 | + * PCB: 507CD (rev1.1) | |
| 351 | + * parts: DNOS404ZH103A(ZL10353, DTT7579(?)), CST56I01 | |
| 352 | + * OEA=80 OEB=00 OEC=00 OED=ff OEF=fe | |
| 353 | + * IOA=4f IOB=ff IOC=00 IOD=06 IOF=01 | |
| 354 | + * IOD[0] ZL10353 1=enabled | |
| 355 | + * IOA[7] TS 0=enabled | |
| 356 | + * tuner is not behind ZL10353 I2C-gate (no care if gate disabled or not) | |
| 357 | + * | |
| 358 | + * E30 C Plus VID=04b4 PID=861f HW=10 FW=1.0 "anysee-DC(LP)" | |
| 359 | + * PCB: 507DC (rev0.2) | |
| 360 | + * parts: TDA10023, DTOS403IH102B TM, CST56I01 | |
| 361 | + * OEA=80 OEB=00 OEC=00 OED=ff OEF=fe | |
| 362 | + * IOA=4f IOB=ff IOC=00 IOD=26 IOF=01 | |
| 363 | + * IOD[0] TDA10023 1=enabled | |
| 364 | + * | |
| 365 | + * E30 S2 Plus VID=04b4 PID=861f HW=11 FW=0.1 "anysee-S2(LP)" | |
| 366 | + * PCB: 507SI (rev2.1) | |
| 367 | + * parts: BS2N10WCC01(CX24116, CX24118), ISL6423, TDA8024 | |
| 368 | + * OEA=80 OEB=00 OEC=ff OED=ff OEF=fe | |
| 369 | + * IOA=4d IOB=ff IOC=00 IOD=26 IOF=01 | |
| 370 | + * IOD[0] CX24116 1=enabled | |
| 371 | + * | |
| 372 | + * E30 C Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)" | |
| 373 | + * PCB: 507FA (rev0.4) | |
| 374 | + * parts: TDA10023, DTOS403IH102B TM, TDA8024 | |
| 375 | + * OEA=80 OEB=00 OEC=ff OED=ff OEF=ff | |
| 376 | + * IOA=4d IOB=ff IOC=00 IOD=00 IOF=c0 | |
| 377 | + * IOD[5] TDA10023 1=enabled | |
| 378 | + * IOE[0] tuner 1=enabled | |
| 379 | + * | |
| 380 | + * E30 Combo Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)" | |
| 381 | + * PCB: 507FA (rev1.1) | |
| 382 | + * parts: ZL10353, TDA10023, DTOS403IH102B TM, TDA8024 | |
| 383 | + * OEA=80 OEB=00 OEC=ff OED=ff OEF=ff | |
| 384 | + * IOA=4d IOB=ff IOC=00 IOD=00 IOF=c0 | |
| 385 | + * DVB-C: | |
| 386 | + * IOD[5] TDA10023 1=enabled | |
| 387 | + * IOE[0] tuner 1=enabled | |
| 388 | + * DVB-T: | |
| 389 | + * IOD[0] ZL10353 1=enabled | |
| 390 | + * IOE[0] tuner 0=enabled | |
| 391 | + * tuner is behind ZL10353 I2C-gate | |
| 392 | + * | |
| 393 | + * E7 TC VID=1c73 PID=861f HW=18 FW=0.7 AMTCI=0.5 "anysee-E7TC(LP)" | |
| 394 | + * PCB: 508TC (rev0.6) | |
| 395 | + * parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212) | |
| 396 | + * OEA=80 OEB=00 OEC=03 OED=f7 OEF=ff | |
| 397 | + * IOA=4d IOB=00 IOC=cc IOD=48 IOF=e4 | |
| 398 | + * IOA[7] TS 1=enabled | |
| 399 | + * IOE[4] TDA18212 1=enabled | |
| 400 | + * DVB-C: | |
| 401 | + * IOD[6] ZL10353 0=disabled | |
| 402 | + * IOD[5] TDA10023 1=enabled | |
| 403 | + * IOE[0] IF 1=enabled | |
| 404 | + * DVB-T: | |
| 405 | + * IOD[5] TDA10023 0=disabled | |
| 406 | + * IOD[6] ZL10353 1=enabled | |
| 407 | + * IOE[0] IF 0=enabled | |
| 408 | + * | |
| 409 | + * E7 S2 VID=1c73 PID=861f HW=19 FW=0.4 AMTCI=0.5 "anysee-E7S2(LP)" | |
| 410 | + * PCB: 508S2 (rev0.7) | |
| 411 | + * parts: DNBU10512IST(STV0903, STV6110), ISL6423 | |
| 412 | + * OEA=80 OEB=00 OEC=03 OED=f7 OEF=ff | |
| 413 | + * IOA=4d IOB=00 IOC=c4 IOD=08 IOF=e4 | |
| 414 | + * IOA[7] TS 1=enabled | |
| 415 | + * IOE[5] STV0903 1=enabled | |
| 416 | + * | |
| 417 | + */ | |
| 418 | + | |
| 247 | 419 | static int anysee_frontend_attach(struct dvb_usb_adapter *adap) |
| 248 | 420 | { |
| 249 | 421 | int ret; |
| 250 | 422 | struct anysee_state *state = adap->dev->priv; |
| 251 | 423 | u8 hw_info[3]; |
| 252 | − u8 io_d; /* IO port D */ | |
| 424 | + u8 tmp; | |
| 425 | + struct i2c_msg msg[2] = { | |
| 426 | + { | |
| 427 | + .addr = anysee_tda18212_config.i2c_address, | |
| 428 | + .flags = 0, | |
| 429 | + .len = 1, | |
| 430 | + .buf = "\x00", | |
| 431 | + }, { | |
| 432 | + .addr = anysee_tda18212_config.i2c_address, | |
| 433 | + .flags = I2C_M_RD, | |
| 434 | + .len = 1, | |
| 435 | + .buf = &tmp, | |
| 436 | + } | |
| 437 | + }; | |
| 253 | 438 | |
| 254 | − /* check which hardware we have | |
| 255 | − We must do this call two times to get reliable values (hw bug). */ | |
| 439 | + /* Check which hardware we have. | |
| 440 | + * We must do this call two times to get reliable values (hw bug). | |
| 441 | + */ | |
| 256 | 442 | ret = anysee_get_hw_info(adap->dev, hw_info); |
| 257 | 443 | if (ret) |
| 258 | − return ret; | |
| 444 | + goto error; | |
| 445 | + | |
| 259 | 446 | ret = anysee_get_hw_info(adap->dev, hw_info); |
| 260 | 447 | if (ret) |
| 261 | − return ret; | |
| 448 | + goto error; | |
| 262 | 449 | |
| 263 | 450 | /* Meaning of these info bytes are guessed. */ |
| 264 | − info("firmware version:%d.%d.%d hardware id:%d", | |
| 265 | − 0, hw_info[1], hw_info[2], hw_info[0]); | |
| 451 | + info("firmware version:%d.%d hardware id:%d", | |
| 452 | + hw_info[1], hw_info[2], hw_info[0]); | |
| 266 | 453 | |
| 267 | − ret = anysee_read_reg(adap->dev, 0xb0, &io_d); /* IO port D */ | |
| 268 | − if (ret) | |
| 269 | − return ret; | |
| 270 | − deb_info("%s: IO port D:%02x\n", __func__, io_d); | |
| 271 | − | |
| 272 | − /* Select demod using trial and error method. */ | |
| 273 | − | |
| 274 | − /* Try to attach demodulator in following order: | |
| 275 | − model demod hw firmware | |
| 276 | − 1. E30 MT352 02 0.2.1 | |
| 277 | − 2. E30 ZL10353 02 0.2.1 | |
| 278 | − 3. E30 Combo ZL10353 0f 0.1.2 DVB-T/C combo | |
| 279 | − 4. E30 Plus ZL10353 06 0.1.0 | |
| 280 | − 5. E30C Plus TDA10023 0a 0.1.0 rev 0.2 | |
| 281 | − E30C Plus TDA10023 0f 0.1.2 rev 0.4 | |
| 282 | − E30 Combo TDA10023 0f 0.1.2 DVB-T/C combo | |
| 283 | − */ | |
| 284 | − | |
| 285 | − /* Zarlink MT352 DVB-T demod inside of Samsung DNOS404ZH102A NIM */ | |
| 286 | − adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config, | |
| 287 | − &adap->dev->i2c_adap); | |
| 288 | − if (adap->fe != NULL) { | |
| 289 | − state->tuner = DVB_PLL_THOMSON_DTT7579; | |
| 290 | − return 0; | |
| 291 | − } | |
| 454 | + state->hw = hw_info[0]; | |
| 292 | 455 | |
| 293 | − /* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */ | |
| 294 | − adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config, | |
| 295 | − &adap->dev->i2c_adap); | |
| 296 | − if (adap->fe != NULL) { | |
| 297 | − state->tuner = DVB_PLL_THOMSON_DTT7579; | |
| 298 | − return 0; | |
| 299 | − } | |
| 456 | + switch (state->hw) { | |
| 457 | + case ANYSEE_HW_02: /* 2 */ | |
| 458 | + /* E30 */ | |
| 459 | + | |
| 460 | + /* attach demod */ | |
| 461 | + adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config, | |
| 462 | + &adap->dev->i2c_adap); | |
| 463 | + if (adap->fe) | |
| 464 | + break; | |
| 465 | + | |
| 466 | + /* attach demod */ | |
| 467 | + adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config, | |
| 468 | + &adap->dev->i2c_adap); | |
| 469 | + | |
| 470 | + break; | |
| 471 | + case ANYSEE_HW_507CD: /* 6 */ | |
| 472 | + /* E30 Plus */ | |
| 300 | 473 | |
| 301 | − /* for E30 Combo Plus DVB-T demodulator */ | |
| 302 | − if (dvb_usb_anysee_delsys) { | |
| 303 | − ret = anysee_write_reg(adap->dev, 0xb0, 0x01); | |
| 474 | + /* enable DVB-T demod on IOD[0] */ | |
| 475 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01); | |
| 304 | 476 | if (ret) |
| 305 | − return ret; | |
| 477 | + goto error; | |
| 478 | + | |
| 479 | + /* enable transport stream on IOA[7] */ | |
| 480 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (0 << 7), 0x80); | |
| 481 | + if (ret) | |
| 482 | + goto error; | |
| 306 | 483 | |
| 307 | − /* Zarlink ZL10353 DVB-T demod */ | |
| 484 | + /* attach demod */ | |
| 308 | 485 | adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config, |
| 309 | − &adap->dev->i2c_adap); | |
| 310 | − if (adap->fe != NULL) { | |
| 311 | − state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A; | |
| 312 | − return 0; | |
| 486 | + &adap->dev->i2c_adap); | |
| 487 | + | |
| 488 | + break; | |
| 489 | + case ANYSEE_HW_507DC: /* 10 */ | |
| 490 | + /* E30 C Plus */ | |
| 491 | + | |
| 492 | + /* enable DVB-C demod on IOD[0] */ | |
| 493 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01); | |
| 494 | + if (ret) | |
| 495 | + goto error; | |
| 496 | + | |
| 497 | + /* attach demod */ | |
| 498 | + adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config, | |
| 499 | + &adap->dev->i2c_adap, 0x48); | |
| 500 | + | |
| 501 | + break; | |
| 502 | + case ANYSEE_HW_507SI: /* 11 */ | |
| 503 | + /* E30 S2 Plus */ | |
| 504 | + | |
| 505 | + /* enable DVB-S/S2 demod on IOD[0] */ | |
| 506 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01); | |
| 507 | + if (ret) | |
| 508 | + goto error; | |
| 509 | + | |
| 510 | + /* attach demod */ | |
| 511 | + adap->fe = dvb_attach(cx24116_attach, &anysee_cx24116_config, | |
| 512 | + &adap->dev->i2c_adap); | |
| 513 | + | |
| 514 | + break; | |
| 515 | + case ANYSEE_HW_507FA: /* 15 */ | |
| 516 | + /* E30 Combo Plus */ | |
| 517 | + /* E30 C Plus */ | |
| 518 | + | |
| 519 | + /* enable tuner on IOE[4] */ | |
| 520 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10); | |
| 521 | + if (ret) | |
| 522 | + goto error; | |
| 523 | + | |
| 524 | + /* probe TDA18212 */ | |
| 525 | + tmp = 0; | |
| 526 | + ret = i2c_transfer(&adap->dev->i2c_adap, msg, 2); | |
| 527 | + if (ret == 2 && tmp == 0xc7) | |
| 528 | + deb_info("%s: TDA18212 found\n", __func__); | |
| 529 | + else | |
| 530 | + tmp = 0; | |
| 531 | + | |
| 532 | + /* disable tuner on IOE[4] */ | |
| 533 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10); | |
| 534 | + if (ret) | |
| 535 | + goto error; | |
| 536 | + | |
| 537 | + if (dvb_usb_anysee_delsys) { | |
| 538 | + /* disable DVB-C demod on IOD[5] */ | |
| 539 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5), | |
| 540 | + 0x20); | |
| 541 | + if (ret) | |
| 542 | + goto error; | |
| 543 | + | |
| 544 | + /* enable DVB-T demod on IOD[0] */ | |
| 545 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), | |
| 546 | + 0x01); | |
| 547 | + if (ret) | |
| 548 | + goto error; | |
| 549 | + | |
| 550 | + /* attach demod */ | |
| 551 | + if (tmp == 0xc7) { | |
| 552 | + /* TDA18212 config */ | |
| 553 | + adap->fe = dvb_attach(zl10353_attach, | |
| 554 | + &anysee_zl10353_tda18212_config2, | |
| 555 | + &adap->dev->i2c_adap); | |
| 556 | + } else { | |
| 557 | + /* PLL config */ | |
| 558 | + adap->fe = dvb_attach(zl10353_attach, | |
| 559 | + &anysee_zl10353_config, | |
| 560 | + &adap->dev->i2c_adap); | |
| 561 | + } | |
| 562 | + } else { | |
| 563 | + /* disable DVB-T demod on IOD[0] */ | |
| 564 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0), | |
| 565 | + 0x01); | |
| 566 | + if (ret) | |
| 567 | + goto error; | |
| 568 | + | |
| 569 | + /* enable DVB-C demod on IOD[5] */ | |
| 570 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5), | |
| 571 | + 0x20); | |
| 572 | + if (ret) | |
| 573 | + goto error; | |
| 574 | + | |
| 575 | + /* attach demod */ | |
| 576 | + if (tmp == 0xc7) { | |
| 577 | + /* TDA18212 config */ | |
| 578 | + adap->fe = dvb_attach(tda10023_attach, | |
| 579 | + &anysee_tda10023_tda18212_config, | |
| 580 | + &adap->dev->i2c_adap, 0x48); | |
| 581 | + } else { | |
| 582 | + /* PLL config */ | |
| 583 | + adap->fe = dvb_attach(tda10023_attach, | |
| 584 | + &anysee_tda10023_config, | |
| 585 | + &adap->dev->i2c_adap, 0x48); | |
| 586 | + } | |
| 313 | 587 | } |
| 314 | − } | |
| 315 | 588 | |
| 316 | − /* connect demod on IO port D for TDA10023 & ZL10353 */ | |
| 317 | − ret = anysee_write_reg(adap->dev, 0xb0, 0x25); | |
| 318 | − if (ret) | |
| 319 | − return ret; | |
| 589 | + break; | |
| 590 | + case ANYSEE_HW_508TC: /* 18 */ | |
| 591 | + /* E7 TC */ | |
| 320 | 592 | |
| 321 | − /* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */ | |
| 322 | − adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config, | |
| 323 | − &adap->dev->i2c_adap); | |
| 324 | − if (adap->fe != NULL) { | |
| 325 | − state->tuner = DVB_PLL_THOMSON_DTT7579; | |
| 326 | − return 0; | |
| 327 | − } | |
| 593 | + /* enable transport stream on IOA[7] */ | |
| 594 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80); | |
| 595 | + if (ret) | |
| 596 | + goto error; | |
| 597 | + | |
| 598 | + if (dvb_usb_anysee_delsys) { | |
| 599 | + /* disable DVB-C demod on IOD[5] */ | |
| 600 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5), | |
| 601 | + 0x20); | |
| 602 | + if (ret) | |
| 603 | + goto error; | |
| 604 | + | |
| 605 | + /* enable DVB-T demod on IOD[6] */ | |
| 606 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6), | |
| 607 | + 0x40); | |
| 608 | + if (ret) | |
| 609 | + goto error; | |
| 610 | + | |
| 611 | + /* enable IF route on IOE[0] */ | |
| 612 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0), | |
| 613 | + 0x01); | |
| 614 | + if (ret) | |
| 615 | + goto error; | |
| 616 | + | |
| 617 | + /* attach demod */ | |
| 618 | + adap->fe = dvb_attach(zl10353_attach, | |
| 619 | + &anysee_zl10353_tda18212_config, | |
| 620 | + &adap->dev->i2c_adap); | |
| 621 | + } else { | |
| 622 | + /* disable DVB-T demod on IOD[6] */ | |
| 623 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6), | |
| 624 | + 0x40); | |
| 625 | + if (ret) | |
| 626 | + goto error; | |
| 627 | + | |
| 628 | + /* enable DVB-C demod on IOD[5] */ | |
| 629 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5), | |
| 630 | + 0x20); | |
| 631 | + if (ret) | |
| 632 | + goto error; | |
| 633 | + | |
| 634 | + /* enable IF route on IOE[0] */ | |
| 635 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0), | |
| 636 | + 0x01); | |
| 637 | + if (ret) | |
| 638 | + goto error; | |
| 639 | + | |
| 640 | + /* attach demod */ | |
| 641 | + adap->fe = dvb_attach(tda10023_attach, | |
| 642 | + &anysee_tda10023_tda18212_config, | |
| 643 | + &adap->dev->i2c_adap, 0x48); | |
| 644 | + } | |
| 328 | 645 | |
| 329 | − /* IO port E - E30C rev 0.4 board requires this */ | |
| 330 | − ret = anysee_write_reg(adap->dev, 0xb1, 0xa7); | |
| 331 | − if (ret) | |
| 332 | − return ret; | |
| 646 | + break; | |
| 647 | + case ANYSEE_HW_508S2: /* 19 */ | |
| 648 | + /* E7 S2 */ | |
| 333 | 649 | |
| 334 | − /* Philips TDA10023 DVB-C demod */ | |
| 335 | − adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config, | |
| 336 | − &adap->dev->i2c_adap, 0x48); | |
| 337 | − if (adap->fe != NULL) { | |
| 338 | − state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A; | |
| 339 | − return 0; | |
| 340 | − } | |
| 650 | + /* enable transport stream on IOA[7] */ | |
| 651 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80); | |
| 652 | + if (ret) | |
| 653 | + goto error; | |
| 341 | 654 | |
| 342 | − /* return IO port D to init value for safe */ | |
| 343 | − ret = anysee_write_reg(adap->dev, 0xb0, io_d); | |
| 344 | − if (ret) | |
| 345 | − return ret; | |
| 655 | + /* enable DVB-S/S2 demod on IOE[5] */ | |
| 656 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20); | |
| 657 | + if (ret) | |
| 658 | + goto error; | |
| 659 | + | |
| 660 | + /* attach demod */ | |
| 661 | + adap->fe = dvb_attach(stv0900_attach, &anysee_stv0900_config, | |
| 662 | + &adap->dev->i2c_adap, 0); | |
| 346 | 663 | |
| 347 | − err("Unknown Anysee version: %02x %02x %02x. "\ | |
| 348 | − "Please report the <linux-dvb@linuxtv.org>.", | |
| 349 | − hw_info[0], hw_info[1], hw_info[2]); | |
| 664 | + break; | |
| 665 | + } | |
| 350 | 666 | |
| 351 | − return -ENODEV; | |
| 667 | + if (!adap->fe) { | |
| 668 | + /* we have no frontend :-( */ | |
| 669 | + ret = -ENODEV; | |
| 670 | + err("Unsupported Anysee version. " \ | |
| 671 | + "Please report the <linux-media@vger.kernel.org>."); | |
| 672 | + } | |
| 673 | +error: | |
| 674 | + return ret; | |
| 352 | 675 | } |
| 353 | 676 | |
| 354 | 677 | static int anysee_tuner_attach(struct dvb_usb_adapter *adap) |
| 355 | 678 | { |
| 356 | 679 | struct anysee_state *state = adap->dev->priv; |
| 680 | + struct dvb_frontend *fe; | |
| 681 | + int ret; | |
| 357 | 682 | deb_info("%s:\n", __func__); |
| 358 | 683 | |
| 359 | − switch (state->tuner) { | |
| 360 | − case DVB_PLL_THOMSON_DTT7579: | |
| 361 | − /* Thomson dtt7579 (not sure) PLL inside of: | |
| 362 | − Samsung DNOS404ZH102A NIM | |
| 363 | − Samsung DNOS404ZH103A NIM */ | |
| 364 | − dvb_attach(dvb_pll_attach, adap->fe, 0x61, | |
| 365 | − NULL, DVB_PLL_THOMSON_DTT7579); | |
| 684 | + switch (state->hw) { | |
| 685 | + case ANYSEE_HW_02: /* 2 */ | |
| 686 | + /* E30 */ | |
| 687 | + | |
| 688 | + /* attach tuner */ | |
| 689 | + fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1), | |
| 690 | + NULL, DVB_PLL_THOMSON_DTT7579); | |
| 691 | + | |
| 692 | + break; | |
| 693 | + case ANYSEE_HW_507CD: /* 6 */ | |
| 694 | + /* E30 Plus */ | |
| 695 | + | |
| 696 | + /* attach tuner */ | |
| 697 | + fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1), | |
| 698 | + &adap->dev->i2c_adap, DVB_PLL_THOMSON_DTT7579); | |
| 699 | + | |
| 700 | + break; | |
| 701 | + case ANYSEE_HW_507DC: /* 10 */ | |
| 702 | + /* E30 C Plus */ | |
| 703 | + | |
| 704 | + /* attach tuner */ | |
| 705 | + fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1), | |
| 706 | + &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); | |
| 707 | + | |
| 708 | + break; | |
| 709 | + case ANYSEE_HW_507SI: /* 11 */ | |
| 710 | + /* E30 S2 Plus */ | |
| 711 | + | |
| 712 | + /* attach LNB controller */ | |
| 713 | + fe = dvb_attach(isl6423_attach, adap->fe, &adap->dev->i2c_adap, | |
| 714 | + &anysee_isl6423_config); | |
| 715 | + | |
| 716 | + break; | |
| 717 | + case ANYSEE_HW_507FA: /* 15 */ | |
| 718 | + /* E30 Combo Plus */ | |
| 719 | + /* E30 C Plus */ | |
| 720 | + | |
| 721 | + if (dvb_usb_anysee_delsys) { | |
| 722 | + /* enable DVB-T tuner on IOE[0] */ | |
| 723 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0), | |
| 724 | + 0x01); | |
| 725 | + if (ret) | |
| 726 | + goto error; | |
| 727 | + } else { | |
| 728 | + /* enable DVB-C tuner on IOE[0] */ | |
| 729 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0), | |
| 730 | + 0x01); | |
| 731 | + if (ret) | |
| 732 | + goto error; | |
| 733 | + } | |
| 734 | + | |
| 735 | + /* Try first attach TDA18212 silicon tuner on IOE[4], if that | |
| 736 | + * fails attach old simple PLL. */ | |
| 737 | + | |
| 738 | + /* enable tuner on IOE[4] */ | |
| 739 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10); | |
| 740 | + if (ret) | |
| 741 | + goto error; | |
| 742 | + | |
| 743 | + /* attach tuner */ | |
| 744 | + fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap, | |
| 745 | + &anysee_tda18212_config); | |
| 746 | + if (fe) | |
| 747 | + break; | |
| 748 | + | |
| 749 | + /* disable tuner on IOE[4] */ | |
| 750 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10); | |
| 751 | + if (ret) | |
| 752 | + goto error; | |
| 753 | + | |
| 754 | + /* attach tuner */ | |
| 755 | + fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1), | |
| 756 | + &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); | |
| 757 | + | |
| 366 | 758 | break; |
| 367 | − case DVB_PLL_SAMSUNG_DTOS403IH102A: | |
| 368 | − /* Unknown PLL inside of Samsung DTOS403IH102A tuner module */ | |
| 369 | − dvb_attach(dvb_pll_attach, adap->fe, 0xc0, | |
| 370 | − &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); | |
| 759 | + case ANYSEE_HW_508TC: /* 18 */ | |
| 760 | + /* E7 TC */ | |
| 761 | + | |
| 762 | + /* enable tuner on IOE[4] */ | |
| 763 | + ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10); | |
| 764 | + if (ret) | |
| 765 | + goto error; | |
| 766 | + | |
| 767 | + /* attach tuner */ | |
| 768 | + fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap, | |
| 769 | + &anysee_tda18212_config); | |
| 770 | + | |
| 371 | 771 | break; |
| 772 | + case ANYSEE_HW_508S2: /* 19 */ | |
| 773 | + /* E7 S2 */ | |
| 774 | + | |
| 775 | + /* attach tuner */ | |
| 776 | + fe = dvb_attach(stv6110_attach, adap->fe, | |
| 777 | + &anysee_stv6110_config, &adap->dev->i2c_adap); | |
| 778 | + | |
| 779 | + if (fe) { | |
| 780 | + /* attach LNB controller */ | |
| 781 | + fe = dvb_attach(isl6423_attach, adap->fe, | |
| 782 | + &adap->dev->i2c_adap, &anysee_isl6423_config); | |
| 783 | + } | |
| 784 | + | |
| 785 | + break; | |
| 786 | + default: | |
| 787 | + fe = NULL; | |
| 372 | 788 | } |
| 373 | 789 | |
| 374 | − return 0; | |
| 790 | + if (fe) | |
| 791 | + ret = 0; | |
| 792 | + else | |
| 793 | + ret = -ENODEV; | |
| 794 | + | |
| 795 | +error: | |
| 796 | + return ret; | |
| 375 | 797 | } |
| 376 | 798 | |
| 377 | 799 | static int anysee_rc_query(struct dvb_usb_device *d) |
| @@ -57,10 +57,29 @@ enum cmd { · 56 unmodified lines | ||
| 57 | 57 | }; |
| 58 | 58 | |
| 59 | 59 | struct anysee_state { |
| 60 | − u8 tuner; | |
| 60 | + u8 hw; /* PCB ID */ | |
| 61 | 61 | u8 seq; |
| 62 | 62 | }; |
| 63 | 63 | |
| 64 | +#define ANYSEE_HW_02 2 /* E30 */ | |
| 65 | +#define ANYSEE_HW_507CD 6 /* E30 Plus */ | |
| 66 | +#define ANYSEE_HW_507DC 10 /* E30 C Plus */ | |
| 67 | +#define ANYSEE_HW_507SI 11 /* E30 S2 Plus */ | |
| 68 | +#define ANYSEE_HW_507FA 15 /* E30 Combo Plus / E30 C Plus */ | |
| 69 | +#define ANYSEE_HW_508TC 18 /* E7 TC */ | |
| 70 | +#define ANYSEE_HW_508S2 19 /* E7 S2 */ | |
| 71 | + | |
| 72 | +#define REG_IOA 0x80 /* Port A (bit addressable) */ | |
| 73 | +#define REG_IOB 0x90 /* Port B (bit addressable) */ | |
| 74 | +#define REG_IOC 0xa0 /* Port C (bit addressable) */ | |
| 75 | +#define REG_IOD 0xb0 /* Port D (bit addressable) */ | |
| 76 | +#define REG_IOE 0xb1 /* Port E (NOT bit addressable) */ | |
| 77 | +#define REG_OEA 0xb2 /* Port A Output Enable */ | |
| 78 | +#define REG_OEB 0xb3 /* Port B Output Enable */ | |
| 79 | +#define REG_OEC 0xb4 /* Port C Output Enable */ | |
| 80 | +#define REG_OED 0xb5 /* Port D Output Enable */ | |
| 81 | +#define REG_OEE 0xb6 /* Port E Output Enable */ | |
| 82 | + | |
| 64 | 83 | #endif |
| 65 | 84 | |
| 66 | 85 | /*************************************************************************** |
| @@ -136,7 +155,7 @@ General reply packet(s) are always used if not own reply defined. · 69 unmodified lines | ||
| 136 | 155 | ---------------------------------------------------------------------------- |
| 137 | 156 | | 04 | 0x00 |
| 138 | 157 | ---------------------------------------------------------------------------- |
| 139 | −| 05 | 0x01 | |
| 158 | +| 05 | data length | |
| 140 | 159 | ---------------------------------------------------------------------------- |
| 141 | 160 | | 06-59 | don't care |
| 142 | 161 | ---------------------------------------------------------------------------- |
| @@ -33,8 +33,16 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, · 32 unmodified lines | ||
| 33 | 33 | { |
| 34 | 34 | int ret; |
| 35 | 35 | u16 index; |
| 36 | − u8 usb_buf[6]; /* enough for all known requests, | |
| 37 | − read returns 5 and write 6 bytes */ | |
| 36 | + u8 *usb_buf; | |
| 37 | + | |
| 38 | + /* | |
| 39 | + * allocate enough for all known requests, | |
| 40 | + * read returns 5 and write 6 bytes | |
| 41 | + */ | |
| 42 | + usb_buf = kmalloc(6, GFP_KERNEL); | |
| 43 | + if (!usb_buf) | |
| 44 | + return -ENOMEM; | |
| 45 | + | |
| 38 | 46 | switch (wlen) { |
| 39 | 47 | case 1: |
| 40 | 48 | index = wbuf[0] << 8; |
| @@ -45,14 +53,15 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, · 4 unmodified lines | ||
| 45 | 53 | break; |
| 46 | 54 | default: |
| 47 | 55 | warn("wlen = %x, aborting.", wlen); |
| 48 | − return -EINVAL; | |
| 56 | + ret = -EINVAL; | |
| 57 | + goto error; | |
| 49 | 58 | } |
| 50 | 59 | |
| 51 | 60 | ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation, |
| 52 | 61 | USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index, |
| 53 | − usb_buf, sizeof(usb_buf), AU6610_USB_TIMEOUT); | |
| 62 | + usb_buf, 6, AU6610_USB_TIMEOUT); | |
| 54 | 63 | if (ret < 0) |
| 55 | − return ret; | |
| 64 | + goto error; | |
| 56 | 65 | |
| 57 | 66 | switch (operation) { |
| 58 | 67 | case AU6610_REQ_I2C_READ: |
| @@ -60,7 +69,8 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, · 1 unmodified line | ||
| 60 | 69 | /* requested value is always 5th byte in buffer */ |
| 61 | 70 | rbuf[0] = usb_buf[4]; |
| 62 | 71 | } |
| 63 | − | |
| 72 | +error: | |
| 73 | + kfree(usb_buf); | |
| 64 | 74 | return ret; |
| 65 | 75 | } |
| 66 | 76 | |
| @@ -39,7 +39,7 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req) · 38 unmodified lines | ||
| 39 | 39 | u8 requesttype; |
| 40 | 40 | u16 value; |
| 41 | 41 | u16 index; |
| 42 | − u8 buf[req->data_len]; | |
| 42 | + u8 *buf; | |
| 43 | 43 | |
| 44 | 44 | request = req->cmd; |
| 45 | 45 | value = req->value; |
| @@ -62,6 +62,12 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req) · 16 unmodified lines | ||
| 62 | 62 | goto error; |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | + buf = kmalloc(req->data_len, GFP_KERNEL); | |
| 66 | + if (!buf) { | |
| 67 | + ret = -ENOMEM; | |
| 68 | + goto error; | |
| 69 | + } | |
| 70 | + | |
| 65 | 71 | if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) { |
| 66 | 72 | /* write */ |
| 67 | 73 | memcpy(buf, req->data, req->data_len); |
| @@ -74,7 +80,7 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req) · 6 unmodified lines | ||
| 74 | 80 | msleep(1); /* avoid I2C errors */ |
| 75 | 81 | |
| 76 | 82 | ret = usb_control_msg(udev, pipe, request, requesttype, value, index, |
| 77 | − buf, sizeof(buf), CE6230_USB_TIMEOUT); | |
| 83 | + buf, req->data_len, CE6230_USB_TIMEOUT); | |
| 78 | 84 | |
| 79 | 85 | ce6230_debug_dump(request, requesttype, value, index, buf, |
| 80 | 86 | req->data_len, deb_xfer); |
| @@ -88,6 +94,7 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req) · 7 unmodified lines | ||
| 88 | 94 | if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) |
| 89 | 95 | memcpy(req->data, buf, req->data_len); |
| 90 | 96 | |
| 97 | + kfree(buf); | |
| 91 | 98 | error: |
| 92 | 99 | return ret; |
| 93 | 100 | } |
| @@ -46,8 +46,9 @@ struct dib0700_state { · 45 unmodified lines | ||
| 46 | 46 | u8 is_dib7000pc; |
| 47 | 47 | u8 fw_use_new_i2c_api; |
| 48 | 48 | u8 disable_streaming_master_mode; |
| 49 | − u32 fw_version; | |
| 50 | − u32 nb_packet_buffer_size; | |
| 49 | + u32 fw_version; | |
| 50 | + u32 nb_packet_buffer_size; | |
| 51 | + u8 buf[255]; | |
| 51 | 52 | }; |
| 52 | 53 | |
| 53 | 54 | extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, |
| @@ -27,19 +27,25 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); · 26 unmodified lines | ||
| 27 | 27 | int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, |
| 28 | 28 | u32 *romversion, u32 *ramversion, u32 *fwtype) |
| 29 | 29 | { |
| 30 | − u8 b[16]; | |
| 31 | − int ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), | |
| 30 | + struct dib0700_state *st = d->priv; | |
| 31 | + int ret; | |
| 32 | + | |
| 33 | + ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), | |
| 32 | 34 | REQUEST_GET_VERSION, |
| 33 | 35 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, |
| 34 | − b, sizeof(b), USB_CTRL_GET_TIMEOUT); | |
| 36 | + st->buf, 16, USB_CTRL_GET_TIMEOUT); | |
| 35 | 37 | if (hwversion != NULL) |
| 36 | − *hwversion = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; | |
| 38 | + *hwversion = (st->buf[0] << 24) | (st->buf[1] << 16) | | |
| 39 | + (st->buf[2] << 8) | st->buf[3]; | |
| 37 | 40 | if (romversion != NULL) |
| 38 | − *romversion = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | b[7]; | |
| 41 | + *romversion = (st->buf[4] << 24) | (st->buf[5] << 16) | | |
| 42 | + (st->buf[6] << 8) | st->buf[7]; | |
| 39 | 43 | if (ramversion != NULL) |
| 40 | − *ramversion = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11]; | |
| 44 | + *ramversion = (st->buf[8] << 24) | (st->buf[9] << 16) | | |
| 45 | + (st->buf[10] << 8) | st->buf[11]; | |
| 41 | 46 | if (fwtype != NULL) |
| 42 | − *fwtype = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15]; | |
| 47 | + *fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) | | |
| 48 | + (st->buf[14] << 8) | st->buf[15]; | |
| 43 | 49 | return ret; |
| 44 | 50 | } |
| 45 | 51 | |
| @@ -101,24 +107,31 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen · 55 unmodified lines | ||
| 101 | 107 | |
| 102 | 108 | int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val) |
| 103 | 109 | { |
| 104 | − u8 buf[3] = { REQUEST_SET_GPIO, gpio, ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6) }; | |
| 105 | − return dib0700_ctrl_wr(d, buf, sizeof(buf)); | |
| 110 | + struct dib0700_state *st = d->priv; | |
| 111 | + s16 ret; | |
| 112 | + | |
| 113 | + st->buf[0] = REQUEST_SET_GPIO; | |
| 114 | + st->buf[1] = gpio; | |
| 115 | + st->buf[2] = ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6); | |
| 116 | + | |
| 117 | + ret = dib0700_ctrl_wr(d, st->buf, 3); | |
| 118 | + | |
| 119 | + return ret; | |
| 106 | 120 | } |
| 107 | 121 | |
| 108 | 122 | static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) |
| 109 | 123 | { |
| 110 | 124 | struct dib0700_state *st = d->priv; |
| 111 | − u8 b[3]; | |
| 112 | 125 | int ret; |
| 113 | 126 | |
| 114 | 127 | if (st->fw_version >= 0x10201) { |
| 115 | − b[0] = REQUEST_SET_USB_XFER_LEN; | |
| 116 | − b[1] = (nb_ts_packets >> 8) & 0xff; | |
| 117 | − b[2] = nb_ts_packets & 0xff; | |
| 128 | + st->buf[0] = REQUEST_SET_USB_XFER_LEN; | |
| 129 | + st->buf[1] = (nb_ts_packets >> 8) & 0xff; | |
| 130 | + st->buf[2] = nb_ts_packets & 0xff; | |
| 118 | 131 | |
| 119 | 132 | deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets); |
| 120 | 133 | |
| 121 | − ret = dib0700_ctrl_wr(d, b, sizeof(b)); | |
| 134 | + ret = dib0700_ctrl_wr(d, st->buf, 3); | |
| 122 | 135 | } else { |
| 123 | 136 | deb_info("this firmware does not allow to change the USB xfer len\n"); |
| 124 | 137 | ret = -EIO; |
| @@ -137,11 +150,11 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, · 12 unmodified lines | ||
| 137 | 150 | properly support i2c read calls not preceded by a write */ |
| 138 | 151 | |
| 139 | 152 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
| 153 | + struct dib0700_state *st = d->priv; | |
| 140 | 154 | uint8_t bus_mode = 1; /* 0=eeprom bus, 1=frontend bus */ |
| 141 | 155 | uint8_t gen_mode = 0; /* 0=master i2c, 1=gpio i2c */ |
| 142 | 156 | uint8_t en_start = 0; |
| 143 | 157 | uint8_t en_stop = 0; |
| 144 | − uint8_t buf[255]; /* TBV: malloc ? */ | |
| 145 | 158 | int result, i; |
| 146 | 159 | |
| 147 | 160 | /* 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, · 47 unmodified lines | ||
| 195 | 208 | |
| 196 | 209 | } else { |
| 197 | 210 | /* Write request */ |
| 198 | − buf[0] = REQUEST_NEW_I2C_WRITE; | |
| 199 | − buf[1] = msg[i].addr << 1; | |
| 200 | − buf[2] = (en_start << 7) | (en_stop << 6) | | |
| 211 | + st->buf[0] = REQUEST_NEW_I2C_WRITE; | |
| 212 | + st->buf[1] = msg[i].addr << 1; | |
| 213 | + st->buf[2] = (en_start << 7) | (en_stop << 6) | | |
| 201 | 214 | (msg[i].len & 0x3F); |
| 202 | 215 | /* I2C ctrl + FE bus; */ |
| 203 | − buf[3] = ((gen_mode << 6) & 0xC0) | | |
| 216 | + st->buf[3] = ((gen_mode << 6) & 0xC0) | | |
| 204 | 217 | ((bus_mode << 4) & 0x30); |
| 205 | 218 | /* The Actual i2c payload */ |
| 206 | − memcpy(&buf[4], msg[i].buf, msg[i].len); | |
| 219 | + memcpy(&st->buf[4], msg[i].buf, msg[i].len); | |
| 207 | 220 | |
| 208 | 221 | deb_data(">>> "); |
| 209 | − debug_dump(buf, msg[i].len + 4, deb_data); | |
| 222 | + debug_dump(st->buf, msg[i].len + 4, deb_data); | |
| 210 | 223 | |
| 211 | 224 | result = usb_control_msg(d->udev, |
| 212 | 225 | usb_sndctrlpipe(d->udev, 0), |
| 213 | 226 | REQUEST_NEW_I2C_WRITE, |
| 214 | 227 | USB_TYPE_VENDOR | USB_DIR_OUT, |
| 215 | − 0, 0, buf, msg[i].len + 4, | |
| 228 | + 0, 0, st->buf, msg[i].len + 4, | |
| 216 | 229 | USB_CTRL_GET_TIMEOUT); |
| 217 | 230 | if (result < 0) { |
| 218 | 231 | deb_info("i2c write error (status = %d)\n", result); |
| @@ -231,27 +244,29 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, · 12 unmodified lines | ||
| 231 | 244 | struct i2c_msg *msg, int num) |
| 232 | 245 | { |
| 233 | 246 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
| 247 | + struct dib0700_state *st = d->priv; | |
| 234 | 248 | int i,len; |
| 235 | − u8 buf[255]; | |
| 236 | 249 | |
| 237 | 250 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) |
| 238 | 251 | return -EAGAIN; |
| 239 | 252 | |
| 240 | 253 | for (i = 0; i < num; i++) { |
| 241 | 254 | /* fill in the address */ |
| 242 | − buf[1] = msg[i].addr << 1; | |
| 255 | + st->buf[1] = msg[i].addr << 1; | |
| 243 | 256 | /* fill the buffer */ |
| 244 | − memcpy(&buf[2], msg[i].buf, msg[i].len); | |
| 257 | + memcpy(&st->buf[2], msg[i].buf, msg[i].len); | |
| 245 | 258 | |
| 246 | 259 | /* write/read request */ |
| 247 | 260 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { |
| 248 | − buf[0] = REQUEST_I2C_READ; | |
| 249 | − buf[1] |= 1; | |
| 261 | + st->buf[0] = REQUEST_I2C_READ; | |
| 262 | + st->buf[1] |= 1; | |
| 250 | 263 | |
| 251 | 264 | /* special thing in the current firmware: when length is zero the read-failed */ |
| 252 | − if ((len = dib0700_ctrl_rd(d, buf, msg[i].len + 2, msg[i+1].buf, msg[i+1].len)) <= 0) { | |
| 265 | + len = dib0700_ctrl_rd(d, st->buf, msg[i].len + 2, | |
| 266 | + msg[i+1].buf, msg[i+1].len); | |
| 267 | + if (len <= 0) { | |
| 253 | 268 | deb_info("I2C read failed on address 0x%02x\n", |
| 254 | − msg[i].addr); | |
| 269 | + msg[i].addr); | |
| 255 | 270 | break; |
| 256 | 271 | } |
| 257 | 272 | |
| @@ -259,13 +274,13 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, · 1 unmodified line | ||
| 259 | 274 | |
| 260 | 275 | i++; |
| 261 | 276 | } else { |
| 262 | − buf[0] = REQUEST_I2C_WRITE; | |
| 263 | − if (dib0700_ctrl_wr(d, buf, msg[i].len + 2) < 0) | |
| 277 | + st->buf[0] = REQUEST_I2C_WRITE; | |
| 278 | + if (dib0700_ctrl_wr(d, st->buf, msg[i].len + 2) < 0) | |
| 264 | 279 | break; |
| 265 | 280 | } |
| 266 | 281 | } |
| 267 | − | |
| 268 | 282 | mutex_unlock(&d->i2c_mutex); |
| 283 | + | |
| 269 | 284 | return i; |
| 270 | 285 | } |
| 271 | 286 | |
| @@ -297,15 +312,23 @@ struct i2c_algorithm dib0700_i2c_algo = { · 25 unmodified lines | ||
| 297 | 312 | int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, |
| 298 | 313 | struct dvb_usb_device_description **desc, int *cold) |
| 299 | 314 | { |
| 300 | − u8 b[16]; | |
| 301 | − s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0), | |
| 315 | + s16 ret; | |
| 316 | + u8 *b; | |
| 317 | + | |
| 318 | + b = kmalloc(16, GFP_KERNEL); | |
| 319 | + if (!b) | |
| 320 | + return -ENOMEM; | |
| 321 | + | |
| 322 | + | |
| 323 | + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | |
| 302 | 324 | REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT); |
| 303 | 325 | |
| 304 | 326 | deb_info("FW GET_VERSION length: %d\n",ret); |
| 305 | 327 | |
| 306 | 328 | *cold = ret <= 0; |
| 307 | − | |
| 308 | 329 | deb_info("cold: %d\n", *cold); |
| 330 | + | |
| 331 | + kfree(b); | |
| 309 | 332 | return 0; |
| 310 | 333 | } |
| 311 | 334 | |
| @@ -313,43 +336,50 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, · 1 unmodified line | ||
| 313 | 336 | u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv, |
| 314 | 337 | u16 pll_loopdiv, u16 free_div, u16 dsuScaler) |
| 315 | 338 | { |
| 316 | − u8 b[10]; | |
| 317 | − b[0] = REQUEST_SET_CLOCK; | |
| 318 | − b[1] = (en_pll << 7) | (pll_src << 6) | (pll_range << 5) | (clock_gpio3 << 4); | |
| 319 | − b[2] = (pll_prediv >> 8) & 0xff; // MSB | |
| 320 | − b[3] = pll_prediv & 0xff; // LSB | |
| 321 | − b[4] = (pll_loopdiv >> 8) & 0xff; // MSB | |
| 322 | − b[5] = pll_loopdiv & 0xff; // LSB | |
| 323 | − b[6] = (free_div >> 8) & 0xff; // MSB | |
| 324 | − b[7] = free_div & 0xff; // LSB | |
| 325 | − b[8] = (dsuScaler >> 8) & 0xff; // MSB | |
| 326 | − b[9] = dsuScaler & 0xff; // LSB | |
| 327 | − | |
| 328 | − return dib0700_ctrl_wr(d, b, 10); | |
| 339 | + struct dib0700_state *st = d->priv; | |
| 340 | + s16 ret; | |
| 341 | + | |
| 342 | + st->buf[0] = REQUEST_SET_CLOCK; | |
| 343 | + st->buf[1] = (en_pll << 7) | (pll_src << 6) | | |
| 344 | + (pll_range << 5) | (clock_gpio3 << 4); | |
| 345 | + st->buf[2] = (pll_prediv >> 8) & 0xff; /* MSB */ | |
| 346 | + st->buf[3] = pll_prediv & 0xff; /* LSB */ | |
| 347 | + st->buf[4] = (pll_loopdiv >> 8) & 0xff; /* MSB */ | |
| 348 | + st->buf[5] = pll_loopdiv & 0xff; /* LSB */ | |
| 349 | + st->buf[6] = (free_div >> 8) & 0xff; /* MSB */ | |
| 350 | + st->buf[7] = free_div & 0xff; /* LSB */ | |
| 351 | + st->buf[8] = (dsuScaler >> 8) & 0xff; /* MSB */ | |
| 352 | + st->buf[9] = dsuScaler & 0xff; /* LSB */ | |
| 353 | + | |
| 354 | + ret = dib0700_ctrl_wr(d, st->buf, 10); | |
| 355 | + | |
| 356 | + return ret; | |
| 329 | 357 | } |
| 330 | 358 | |
| 331 | 359 | int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) |
| 332 | 360 | { |
| 361 | + struct dib0700_state *st = d->priv; | |
| 333 | 362 | u16 divider; |
| 334 | − u8 b[8]; | |
| 335 | 363 | |
| 336 | 364 | if (scl_kHz == 0) |
| 337 | 365 | return -EINVAL; |
| 338 | 366 | |
| 339 | − b[0] = REQUEST_SET_I2C_PARAM; | |
| 367 | + st->buf[0] = REQUEST_SET_I2C_PARAM; | |
| 340 | 368 | divider = (u16) (30000 / scl_kHz); |
| 341 | − b[2] = (u8) (divider >> 8); | |
| 342 | − b[3] = (u8) (divider & 0xff); | |
| 369 | + st->buf[1] = 0; | |
| 370 | + st->buf[2] = (u8) (divider >> 8); | |
| 371 | + st->buf[3] = (u8) (divider & 0xff); | |
| 343 | 372 | divider = (u16) (72000 / scl_kHz); |
| 344 | − b[4] = (u8) (divider >> 8); | |
| 345 | − b[5] = (u8) (divider & 0xff); | |
| 373 | + st->buf[4] = (u8) (divider >> 8); | |
| 374 | + st->buf[5] = (u8) (divider & 0xff); | |
| 346 | 375 | divider = (u16) (72000 / scl_kHz); /* clock: 72MHz */ |
| 347 | − b[6] = (u8) (divider >> 8); | |
| 348 | − b[7] = (u8) (divider & 0xff); | |
| 376 | + st->buf[6] = (u8) (divider >> 8); | |
| 377 | + st->buf[7] = (u8) (divider & 0xff); | |
| 349 | 378 | |
| 350 | 379 | deb_info("setting I2C speed: %04x %04x %04x (%d kHz).", |
| 351 | − (b[2] << 8) | (b[3]), (b[4] << 8) | b[5], (b[6] << 8) | b[7], scl_kHz); | |
| 352 | − return dib0700_ctrl_wr(d, b, 8); | |
| 380 | + (st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) | | |
| 381 | + st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz); | |
| 382 | + return dib0700_ctrl_wr(d, st->buf, 8); | |
| 353 | 383 | } |
| 354 | 384 | |
| 355 | 385 | |
| @@ -364,32 +394,45 @@ int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3) · 8 unmodified lines | ||
| 364 | 394 | |
| 365 | 395 | static int dib0700_jumpram(struct usb_device *udev, u32 address) |
| 366 | 396 | { |
| 367 | − int ret, actlen; | |
| 368 | − u8 buf[8] = { REQUEST_JUMPRAM, 0, 0, 0, | |
| 369 | − (address >> 24) & 0xff, | |
| 370 | − (address >> 16) & 0xff, | |
| 371 | − (address >> 8) & 0xff, | |
| 372 | − address & 0xff }; | |
| 397 | + int ret = 0, actlen; | |
| 398 | + u8 *buf; | |
| 399 | + | |
| 400 | + buf = kmalloc(8, GFP_KERNEL); | |
| 401 | + if (!buf) | |
| 402 | + return -ENOMEM; | |
| 403 | + buf[0] = REQUEST_JUMPRAM; | |
| 404 | + buf[1] = 0; | |
| 405 | + buf[2] = 0; | |
| 406 | + buf[3] = 0; | |
| 407 | + buf[4] = (address >> 24) & 0xff; | |
| 408 | + buf[5] = (address >> 16) & 0xff; | |
| 409 | + buf[6] = (address >> 8) & 0xff; | |
| 410 | + buf[7] = address & 0xff; | |
| 373 | 411 | |
| 374 | 412 | if ((ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x01),buf,8,&actlen,1000)) < 0) { |
| 375 | 413 | deb_fw("jumpram to 0x%x failed\n",address); |
| 376 | − return ret; | |
| 414 | + goto out; | |
| 377 | 415 | } |
| 378 | 416 | if (actlen != 8) { |
| 379 | 417 | deb_fw("jumpram to 0x%x failed\n",address); |
| 380 | − return -EIO; | |
| 418 | + ret = -EIO; | |
| 419 | + goto out; | |
| 381 | 420 | } |
| 382 | − return 0; | |
| 421 | +out: | |
| 422 | + kfree(buf); | |
| 423 | + return ret; | |
| 383 | 424 | } |
| 384 | 425 | |
| 385 | 426 | int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw) |
| 386 | 427 | { |
| 387 | 428 | struct hexline hx; |
| 388 | 429 | int pos = 0, ret, act_len, i, adap_num; |
| 389 | − u8 b[16]; | |
| 430 | + u8 *buf; | |
| 390 | 431 | u32 fw_version; |
| 391 | 432 | |
| 392 | − u8 buf[260]; | |
| 433 | + buf = kmalloc(260, GFP_KERNEL); | |
| 434 | + if (!buf) | |
| 435 | + return -ENOMEM; | |
| 393 | 436 | |
| 394 | 437 | while ((ret = dvb_usb_get_hexline(fw, &hx, &pos)) > 0) { |
| 395 | 438 | 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 · 15 unmodified lines | ||
| 411 | 454 | |
| 412 | 455 | if (ret < 0) { |
| 413 | 456 | err("firmware download failed at %d with %d",pos,ret); |
| 414 | − return ret; | |
| 457 | + goto out; | |
| 415 | 458 | } |
| 416 | 459 | } |
| 417 | 460 | |
| @@ -432,8 +475,8 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw · 14 unmodified lines | ||
| 432 | 475 | usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), |
| 433 | 476 | REQUEST_GET_VERSION, |
| 434 | 477 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, |
| 435 | − b, sizeof(b), USB_CTRL_GET_TIMEOUT); | |
| 436 | − fw_version = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11]; | |
| 478 | + buf, 16, USB_CTRL_GET_TIMEOUT); | |
| 479 | + fw_version = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11]; | |
| 437 | 480 | |
| 438 | 481 | /* set the buffer size - DVB-USB is allocating URB buffers |
| 439 | 482 | * only after the firwmare download was successful */ |
| @@ -451,14 +494,14 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw · 11 unmodified lines | ||
| 451 | 494 | } |
| 452 | 495 | } |
| 453 | 496 | } |
| 454 | − | |
| 497 | +out: | |
| 498 | + kfree(buf); | |
| 455 | 499 | return ret; |
| 456 | 500 | } |
| 457 | 501 | |
| 458 | 502 | int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) |
| 459 | 503 | { |
| 460 | 504 | struct dib0700_state *st = adap->dev->priv; |
| 461 | − u8 b[4]; | |
| 462 | 505 | int ret; |
| 463 | 506 | |
| 464 | 507 | if ((onoff != 0) && (st->fw_version >= 0x10201)) { |
| @@ -472,15 +515,17 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) · 7 unmodified lines | ||
| 472 | 515 | } |
| 473 | 516 | } |
| 474 | 517 | |
| 475 | − b[0] = REQUEST_ENABLE_VIDEO; | |
| 476 | − b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */ | |
| 518 | + st->buf[0] = REQUEST_ENABLE_VIDEO; | |
| 519 | + /* this bit gives a kind of command, | |
| 520 | + * rather than enabling something or not */ | |
| 521 | + st->buf[1] = (onoff << 4) | 0x00; | |
| 477 | 522 | |
| 478 | 523 | if (st->disable_streaming_master_mode == 1) |
| 479 | − b[2] = 0x00; | |
| 524 | + st->buf[2] = 0x00; | |
| 480 | 525 | else |
| 481 | − b[2] = 0x01 << 4; /* Master mode */ | |
| 526 | + st->buf[2] = 0x01 << 4; /* Master mode */ | |
| 482 | 527 | |
| 483 | − b[3] = 0x00; | |
| 528 | + st->buf[3] = 0x00; | |
| 484 | 529 | |
| 485 | 530 | deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id); |
| 486 | 531 | |
| @@ -499,20 +544,23 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) · 12 unmodified lines | ||
| 499 | 544 | st->channel_state |= 1 << (3-adap->stream.props.endpoint); |
| 500 | 545 | } |
| 501 | 546 | |
| 502 | − b[2] |= st->channel_state; | |
| 547 | + st->buf[2] |= st->channel_state; | |
| 503 | 548 | |
| 504 | − deb_info("data for streaming: %x %x\n", b[1], b[2]); | |
| 549 | + deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]); | |
| 505 | 550 | |
| 506 | − return dib0700_ctrl_wr(adap->dev, b, 4); | |
| 551 | + return dib0700_ctrl_wr(adap->dev, st->buf, 4); | |
| 507 | 552 | } |
| 508 | 553 | |
| 509 | 554 | int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) |
| 510 | 555 | { |
| 511 | 556 | struct dvb_usb_device *d = rc->priv; |
| 512 | 557 | struct dib0700_state *st = d->priv; |
| 513 | − u8 rc_setup[3] = { REQUEST_SET_RC, 0, 0 }; | |
| 514 | 558 | int new_proto, ret; |
| 515 | 559 | |
| 560 | + st->buf[0] = REQUEST_SET_RC; | |
| 561 | + st->buf[1] = 0; | |
| 562 | + st->buf[2] = 0; | |
| 563 | + | |
| 516 | 564 | /* Set the IR mode */ |
| 517 | 565 | if (rc_type == RC_TYPE_RC5) |
| 518 | 566 | new_proto = 1; |
| @@ -526,9 +574,9 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) · 7 unmodified lines | ||
| 526 | 574 | } else |
| 527 | 575 | return -EINVAL; |
| 528 | 576 | |
| 529 | − rc_setup[1] = new_proto; | |
| 577 | + st->buf[1] = new_proto; | |
| 530 | 578 | |
| 531 | − ret = dib0700_ctrl_wr(d, rc_setup, sizeof(rc_setup)); | |
| 579 | + ret = dib0700_ctrl_wr(d, st->buf, 3); | |
| 532 | 580 | if (ret < 0) { |
| 533 | 581 | err("ir protocol setup failed"); |
| 534 | 582 | return ret; |
| @@ -561,7 +609,6 @@ struct dib0700_rc_response { · 26 unmodified lines | ||
| 561 | 609 | static void dib0700_rc_urb_completion(struct urb *purb) |
| 562 | 610 | { |
| 563 | 611 | struct dvb_usb_device *d = purb->context; |
| 564 | − struct dib0700_state *st; | |
| 565 | 612 | struct dib0700_rc_response *poll_reply; |
| 566 | 613 | u32 uninitialized_var(keycode); |
| 567 | 614 | u8 toggle; |
| @@ -576,7 +623,6 @@ static void dib0700_rc_urb_completion(struct urb *purb) · 8 unmodified lines | ||
| 576 | 623 | return; |
| 577 | 624 | } |
| 578 | 625 | |
| 579 | − st = d->priv; | |
| 580 | 626 | poll_reply = purb->transfer_buffer; |
| 581 | 627 | |
| 582 | 628 | if (purb->status < 0) { |
| @@ -2439,7 +2439,6 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap) · 2438 unmodified lines | ||
| 2439 | 2439 | |
| 2440 | 2440 | dib0700_set_i2c_speed(adap->dev, 340); |
| 2441 | 2441 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]); |
| 2442 | − | |
| 2443 | 2442 | if (adap->fe == NULL) |
| 2444 | 2443 | return -ENODEV; |
| 2445 | 2444 | |
| @@ -2802,6 +2801,7 @@ struct usb_device_id dib0700_usb_id_table[] = { · 356 unmodified lines | ||
| 2802 | 2801 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_NIM7090) }, |
| 2803 | 2802 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7090PVR) }, |
| 2804 | 2803 | { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2) }, |
| 2804 | +/* 75 */{ USB_DEVICE(USB_VID_MEDION, USB_PID_CREATIX_CTX1921) }, | |
| 2805 | 2805 | { 0 } /* Terminating entry */ |
| 2806 | 2806 | }; |
| 2807 | 2807 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); |
| @@ -3411,7 +3411,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { · 603 unmodified lines | ||
| 3411 | 3411 | }, |
| 3412 | 3412 | }, |
| 3413 | 3413 | |
| 3414 | − .num_device_descs = 3, | |
| 3414 | + .num_device_descs = 4, | |
| 3415 | 3415 | .devices = { |
| 3416 | 3416 | { "DiBcom STK7770P reference design", |
| 3417 | 3417 | { &dib0700_usb_id_table[59], NULL }, |
| @@ -3427,6 +3427,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { · 9 unmodified lines | ||
| 3427 | 3427 | { &dib0700_usb_id_table[74], NULL }, |
| 3428 | 3428 | { NULL }, |
| 3429 | 3429 | }, |
| 3430 | + { "Medion CTX1921 DVB-T USB", | |
| 3431 | + { &dib0700_usb_id_table[75], NULL }, | |
| 3432 | + { NULL }, | |
| 3433 | + }, | |
| 3430 | 3434 | }, |
| 3431 | 3435 | |
| 3432 | 3436 | .rc.core = { |
| @@ -408,7 +408,7 @@ struct rc_map_table rc_map_dibusb_table[] = { · 407 unmodified lines | ||
| 408 | 408 | |
| 409 | 409 | { 0x8008, KEY_DVD }, |
| 410 | 410 | { 0x8009, KEY_AUDIO }, |
| 411 | − { 0x800a, KEY_MEDIA }, /* Pictures */ | |
| 411 | + { 0x800a, KEY_IMAGES }, /* Pictures */ | |
| 412 | 412 | { 0x800b, KEY_VIDEO }, |
| 413 | 413 | |
| 414 | 414 | { 0x800c, KEY_BACK }, |
| @@ -12,7 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) |
| 13 | 13 | { |
| 14 | 14 | struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv; |
| 15 | − int newfeedcount,ret; | |
| 15 | + int newfeedcount, ret; | |
| 16 | 16 | |
| 17 | 17 | if (adap == NULL) |
| 18 | 18 | return -ENODEV; |
| @@ -24,9 +24,13 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) · 5 unmodified lines | ||
| 24 | 24 | deb_ts("stop feeding\n"); |
| 25 | 25 | usb_urb_kill(&adap->stream); |
| 26 | 26 | |
| 27 | − if (adap->props.streaming_ctrl != NULL) | |
| 28 | − if ((ret = adap->props.streaming_ctrl(adap,0))) | |
| 27 | + if (adap->props.streaming_ctrl != NULL) { | |
| 28 | + ret = adap->props.streaming_ctrl(adap, 0); | |
| 29 | + if (ret < 0) { | |
| 29 | 30 | err("error while stopping stream."); |
| 31 | + return ret; | |
| 32 | + } | |
| 33 | + } | |
| 30 | 34 | } |
| 31 | 35 | |
| 32 | 36 | adap->feedcount = newfeedcount; |
| @@ -49,17 +53,24 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) · 16 unmodified lines | ||
| 49 | 53 | |
| 50 | 54 | deb_ts("controlling pid parser\n"); |
| 51 | 55 | if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER && |
| 52 | − adap->props.caps & DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF && | |
| 53 | − adap->props.pid_filter_ctrl != NULL) | |
| 54 | − if (adap->props.pid_filter_ctrl(adap,adap->pid_filtering) < 0) | |
| 56 | + adap->props.caps & | |
| 57 | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF && | |
| 58 | + adap->props.pid_filter_ctrl != NULL) { | |
| 59 | + ret = adap->props.pid_filter_ctrl(adap, | |
| 60 | + adap->pid_filtering); | |
| 61 | + if (ret < 0) { | |
| 55 | 62 | err("could not handle pid_parser"); |
| 56 | − | |
| 63 | + return ret; | |
| 64 | + } | |
| 65 | + } | |
| 57 | 66 | deb_ts("start feeding\n"); |
| 58 | − if (adap->props.streaming_ctrl != NULL) | |
| 59 | − if (adap->props.streaming_ctrl(adap,1)) { | |
| 67 | + if (adap->props.streaming_ctrl != NULL) { | |
| 68 | + ret = adap->props.streaming_ctrl(adap, 1); | |
| 69 | + if (ret < 0) { | |
| 60 | 70 | err("error while enabling fifo."); |
| 61 | − return -ENODEV; | |
| 71 | + return ret; | |
| 62 | 72 | } |
| 73 | + } | |
| 63 | 74 | |
| 64 | 75 | } |
| 65 | 76 | return 0; |
| @@ -91,6 +91,7 @@ · 90 unmodified lines | ||
| 91 | 91 | #define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80 |
| 92 | 92 | #define USB_PID_CONCEPTRONIC_CTVDIGRCU 0xe397 |
| 93 | 93 | #define USB_PID_CONEXANT_D680_DMB 0x86d6 |
| 94 | +#define USB_PID_CREATIX_CTX1921 0x1921 | |
| 94 | 95 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 |
| 95 | 96 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 |
| 96 | 97 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 |
| @@ -121,12 +121,16 @@ static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value, · 120 unmodified lines | ||
| 121 | 121 | u16 index, u8 * data, u16 len, int flags) |
| 122 | 122 | { |
| 123 | 123 | int ret; |
| 124 | − u8 u8buf[len]; | |
| 125 | − | |
| 124 | + u8 *u8buf; | |
| 126 | 125 | unsigned int pipe = (flags == DW210X_READ_MSG) ? |
| 127 | 126 | usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); |
| 128 | 127 | u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; |
| 129 | 128 | |
| 129 | + u8buf = kmalloc(len, GFP_KERNEL); | |
| 130 | + if (!u8buf) | |
| 131 | + return -ENOMEM; | |
| 132 | + | |
| 133 | + | |
| 130 | 134 | if (flags == DW210X_WRITE_MSG) |
| 131 | 135 | memcpy(u8buf, data, len); |
| 132 | 136 | 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, · 1 unmodified line | ||
| 134 | 138 | |
| 135 | 139 | if (flags == DW210X_READ_MSG) |
| 136 | 140 | memcpy(data, u8buf, len); |
| 141 | + | |
| 142 | + kfree(u8buf); | |
| 137 | 143 | return ret; |
| 138 | 144 | } |
| 139 | 145 | |
| @@ -36,7 +36,9 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req) · 35 unmodified lines | ||
| 36 | 36 | int ret; |
| 37 | 37 | unsigned int pipe; |
| 38 | 38 | u8 request, requesttype; |
| 39 | − u8 buf[req->size]; | |
| 39 | + u8 *buf; | |
| 40 | + | |
| 41 | + | |
| 40 | 42 | |
| 41 | 43 | switch (req->cmd) { |
| 42 | 44 | case DOWNLOAD_FIRMWARE: |
| @@ -72,6 +74,12 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req) · 29 unmodified lines | ||
| 72 | 74 | goto error; |
| 73 | 75 | } |
| 74 | 76 | |
| 77 | + buf = kmalloc(req->size, GFP_KERNEL); | |
| 78 | + if (!buf) { | |
| 79 | + ret = -ENOMEM; | |
| 80 | + goto error; | |
| 81 | + } | |
| 82 | + | |
| 75 | 83 | if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) { |
| 76 | 84 | /* write */ |
| 77 | 85 | memcpy(buf, req->data, req->size); |
| @@ -84,13 +92,13 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req) · 6 unmodified lines | ||
| 84 | 92 | msleep(1); /* avoid I2C errors */ |
| 85 | 93 | |
| 86 | 94 | ret = usb_control_msg(udev, pipe, request, requesttype, req->value, |
| 87 | − req->index, buf, sizeof(buf), EC168_USB_TIMEOUT); | |
| 95 | + req->index, buf, req->size, EC168_USB_TIMEOUT); | |
| 88 | 96 | |
| 89 | 97 | ec168_debug_dump(request, requesttype, req->value, req->index, buf, |
| 90 | 98 | req->size, deb_xfer); |
| 91 | 99 | |
| 92 | 100 | if (ret < 0) |
| 93 | − goto error; | |
| 101 | + goto err_dealloc; | |
| 94 | 102 | else |
| 95 | 103 | ret = 0; |
| 96 | 104 | |
| @@ -98,7 +106,11 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req) · 1 unmodified line | ||
| 98 | 106 | if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) |
| 99 | 107 | memcpy(req->data, buf, req->size); |
| 100 | 108 | |
| 109 | + kfree(buf); | |
| 101 | 110 | return ret; |
| 111 | + | |
| 112 | +err_dealloc: | |
| 113 | + kfree(buf); | |
| 102 | 114 | error: |
| 103 | 115 | deb_info("%s: failed:%d\n", __func__, ret); |
| 104 | 116 | return ret; |
| @@ -142,17 +142,20 @@ static u32 gl861_i2c_func(struct i2c_adapter *adapter) · 141 unmodified lines | ||
| 142 | 142 | return I2C_FUNC_I2C; |
| 143 | 143 | } |
| 144 | 144 | |
| 145 | − | |
| 146 | 145 | static int friio_ext_ctl(struct dvb_usb_adapter *adap, |
| 147 | 146 | u32 sat_color, int lnb_on) |
| 148 | 147 | { |
| 149 | 148 | int i; |
| 150 | 149 | int ret; |
| 151 | 150 | struct i2c_msg msg; |
| 152 | − u8 buf[2]; | |
| 151 | + u8 *buf; | |
| 153 | 152 | u32 mask; |
| 154 | 153 | u8 lnb = (lnb_on) ? FRIIO_CTL_LNB : 0; |
| 155 | 154 | |
| 155 | + buf = kmalloc(2, GFP_KERNEL); | |
| 156 | + if (!buf) | |
| 157 | + return -ENOMEM; | |
| 158 | + | |
| 156 | 159 | msg.addr = 0x00; |
| 157 | 160 | msg.flags = 0; |
| 158 | 161 | msg.len = 2; |
| @@ -189,6 +192,7 @@ static int friio_ext_ctl(struct dvb_usb_adapter *adap, · 30 unmodified lines | ||
| 189 | 192 | buf[1] |= FRIIO_CTL_CLK; |
| 190 | 193 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); |
| 191 | 194 | |
| 195 | + kfree(buf); | |
| 192 | 196 | return (ret == 70); |
| 193 | 197 | } |
| 194 | 198 | |
| @@ -219,11 +223,20 @@ static int friio_initialize(struct dvb_usb_device *d) · 24 unmodified lines | ||
| 219 | 223 | int ret; |
| 220 | 224 | int i; |
| 221 | 225 | int retry = 0; |
| 222 | − u8 rbuf[2]; | |
| 223 | − u8 wbuf[3]; | |
| 226 | + u8 *rbuf, *wbuf; | |
| 224 | 227 | |
| 225 | 228 | deb_info("%s called.\n", __func__); |
| 226 | 229 | |
| 230 | + wbuf = kmalloc(3, GFP_KERNEL); | |
| 231 | + if (!wbuf) | |
| 232 | + return -ENOMEM; | |
| 233 | + | |
| 234 | + rbuf = kmalloc(2, GFP_KERNEL); | |
| 235 | + if (!rbuf) { | |
| 236 | + kfree(wbuf); | |
| 237 | + return -ENOMEM; | |
| 238 | + } | |
| 239 | + | |
| 227 | 240 | /* use gl861_i2c_msg instead of gl861_i2c_xfer(), */ |
| 228 | 241 | /* because the i2c device is not set up yet. */ |
| 229 | 242 | wbuf[0] = 0x11; |
| @@ -358,6 +371,8 @@ restart: · 128 unmodified lines | ||
| 358 | 371 | return 0; |
| 359 | 372 | |
| 360 | 373 | error: |
| 374 | + kfree(wbuf); | |
| 375 | + kfree(rbuf); | |
| 361 | 376 | deb_info("%s:ret == %d\n", __func__, ret); |
| 362 | 377 | return -EIO; |
| 363 | 378 | } |
| @@ -62,8 +62,6 @@ · 61 unmodified lines | ||
| 62 | 62 | * LME2510: SHARP:BS2F7HZ0194(MV0194) cannot cold reset and share system |
| 63 | 63 | * with other tuners. After a cold reset streaming will not start. |
| 64 | 64 | * |
| 65 | − * PID functions have been removed from this driver version due to | |
| 66 | − * problems with different firmware and application versions. | |
| 67 | 65 | */ |
| 68 | 66 | #define DVB_USB_LOG_PREFIX "LME2510(C)" |
| 69 | 67 | #include <linux/usb.h> |
| @@ -104,6 +102,10 @@ static int dvb_usb_lme2510_firmware; · 34 unmodified lines | ||
| 104 | 102 | module_param_named(firmware, dvb_usb_lme2510_firmware, int, 0644); |
| 105 | 103 | MODULE_PARM_DESC(firmware, "set default firmware 0=Sharp7395 1=LG"); |
| 106 | 104 | |
| 105 | +static int pid_filter; | |
| 106 | +module_param_named(pid, pid_filter, int, 0644); | |
| 107 | +MODULE_PARM_DESC(pid, "set default 0=on 1=off"); | |
| 108 | + | |
| 107 | 109 | |
| 108 | 110 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
| 109 | 111 | |
| @@ -125,6 +127,7 @@ struct lme2510_state { · 15 unmodified lines | ||
| 125 | 127 | u8 i2c_tuner_gate_r; |
| 126 | 128 | u8 i2c_tuner_addr; |
| 127 | 129 | u8 stream_on; |
| 130 | + u8 pid_size; | |
| 128 | 131 | void *buffer; |
| 129 | 132 | struct urb *lme_urb; |
| 130 | 133 | void *usb_buffer; |
| @@ -167,14 +170,14 @@ static int lme2510_usb_talk(struct dvb_usb_device *d, · 36 unmodified lines | ||
| 167 | 170 | } |
| 168 | 171 | buff = st->usb_buffer; |
| 169 | 172 | |
| 170 | − /* the read/write capped at 512 */ | |
| 171 | − memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen); | |
| 172 | − | |
| 173 | 173 | ret = mutex_lock_interruptible(&d->usb_mutex); |
| 174 | 174 | |
| 175 | 175 | if (ret < 0) |
| 176 | 176 | return -EAGAIN; |
| 177 | 177 | |
| 178 | + /* the read/write capped at 512 */ | |
| 179 | + memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen); | |
| 180 | + | |
| 178 | 181 | ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01)); |
| 179 | 182 | |
| 180 | 183 | 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) · 35 unmodified lines | ||
| 216 | 219 | return 0; |
| 217 | 220 | } |
| 218 | 221 | |
| 222 | +static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out) | |
| 223 | +{ | |
| 224 | + struct lme2510_state *st = d->priv; | |
| 225 | + static u8 pid_buff[] = LME_ZERO_PID; | |
| 226 | + static u8 rbuf[1]; | |
| 227 | + u8 pid_no = index * 2; | |
| 228 | + u8 pid_len = pid_no + 2; | |
| 229 | + int ret = 0; | |
| 230 | + deb_info(1, "PID Setting Pid %04x", pid_out); | |
| 231 | + | |
| 232 | + if (st->pid_size == 0) | |
| 233 | + ret |= lme2510_stream_restart(d); | |
| 234 | + | |
| 235 | + pid_buff[2] = pid_no; | |
| 236 | + pid_buff[3] = (u8)pid_out & 0xff; | |
| 237 | + pid_buff[4] = pid_no + 1; | |
| 238 | + pid_buff[5] = (u8)(pid_out >> 8); | |
| 239 | + | |
| 240 | + if (pid_len > st->pid_size) | |
| 241 | + st->pid_size = pid_len; | |
| 242 | + pid_buff[7] = 0x80 + st->pid_size; | |
| 243 | + | |
| 244 | + ret |= lme2510_usb_talk(d, pid_buff , | |
| 245 | + sizeof(pid_buff) , rbuf, sizeof(rbuf)); | |
| 246 | + | |
| 247 | + if (st->stream_on) | |
| 248 | + ret |= lme2510_stream_restart(d); | |
| 249 | + | |
| 250 | + return ret; | |
| 251 | +} | |
| 252 | + | |
| 219 | 253 | static void lme2510_int_response(struct urb *lme_urb) |
| 220 | 254 | { |
| 221 | 255 | struct dvb_usb_adapter *adap = lme_urb->context; |
| @@ -326,16 +360,68 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap) · 104 unmodified lines | ||
| 326 | 360 | return 0; |
| 327 | 361 | } |
| 328 | 362 | |
| 363 | +static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) | |
| 364 | +{ | |
| 365 | + struct lme2510_state *st = adap->dev->priv; | |
| 366 | + static u8 clear_pid_reg[] = LME_CLEAR_PID; | |
| 367 | + static u8 rbuf[1]; | |
| 368 | + int ret; | |
| 369 | + | |
| 370 | + deb_info(1, "PID Clearing Filter"); | |
| 371 | + | |
| 372 | + ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); | |
| 373 | + if (ret < 0) | |
| 374 | + return -EAGAIN; | |
| 375 | + | |
| 376 | + if (!onoff) | |
| 377 | + ret |= lme2510_usb_talk(adap->dev, clear_pid_reg, | |
| 378 | + sizeof(clear_pid_reg), rbuf, sizeof(rbuf)); | |
| 379 | + | |
| 380 | + st->pid_size = 0; | |
| 381 | + | |
| 382 | + mutex_unlock(&adap->dev->i2c_mutex); | |
| 383 | + | |
| 384 | + return 0; | |
| 385 | +} | |
| 386 | + | |
| 387 | +static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, | |
| 388 | + int onoff) | |
| 389 | +{ | |
| 390 | + int ret = 0; | |
| 391 | + | |
| 392 | + deb_info(3, "%s PID=%04x Index=%04x onoff=%02x", __func__, | |
| 393 | + pid, index, onoff); | |
| 394 | + | |
| 395 | + if (onoff) | |
| 396 | + if (!pid_filter) { | |
| 397 | + ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); | |
| 398 | + if (ret < 0) | |
| 399 | + return -EAGAIN; | |
| 400 | + ret |= lme2510_enable_pid(adap->dev, index, pid); | |
| 401 | + mutex_unlock(&adap->dev->i2c_mutex); | |
| 402 | + } | |
| 403 | + | |
| 404 | + | |
| 405 | + return ret; | |
| 406 | +} | |
| 407 | + | |
| 408 | + | |
| 329 | 409 | static int lme2510_return_status(struct usb_device *dev) |
| 330 | 410 | { |
| 331 | 411 | int ret = 0; |
| 332 | − u8 data[10] = {0}; | |
| 412 | + u8 *data; | |
| 413 | + | |
| 414 | + data = kzalloc(10, GFP_KERNEL); | |
| 415 | + if (!data) | |
| 416 | + return -ENOMEM; | |
| 333 | 417 | |
| 334 | 418 | ret |= usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), |
| 335 | 419 | 0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200); |
| 336 | 420 | info("Firmware Status: %x (%x)", ret , data[2]); |
| 337 | 421 | |
| 338 | − return (ret < 0) ? -ENODEV : data[2]; | |
| 422 | + ret = (ret < 0) ? -ENODEV : data[2]; | |
| 423 | + kfree(data); | |
| 424 | + return ret; | |
| 339 | 425 | } |
| 340 | 426 | |
| 341 | 427 | 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) · 249 unmodified lines | ||
| 591 | 677 | else { |
| 592 | 678 | deb_info(1, "STM Steam Off"); |
| 593 | 679 | /* mutex is here only to avoid collision with I2C */ |
| 594 | − ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); | |
| 680 | + if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) | |
| 681 | + return -EAGAIN; | |
| 595 | 682 | |
| 596 | − ret |= lme2510_usb_talk(adap->dev, clear_reg_3, | |
| 683 | + ret = lme2510_usb_talk(adap->dev, clear_reg_3, | |
| 597 | 684 | sizeof(clear_reg_3), rbuf, rlen); |
| 598 | 685 | st->stream_on = 0; |
| 599 | 686 | st->i2c_talk_onoff = 1; |
| @@ -655,7 +742,7 @@ static int lme2510_download_firmware(struct usb_device *dev, · 55 unmodified lines | ||
| 655 | 742 | const struct firmware *fw) |
| 656 | 743 | { |
| 657 | 744 | int ret = 0; |
| 658 | − u8 data[512] = {0}; | |
| 745 | + u8 *data; | |
| 659 | 746 | u16 j, wlen, len_in, start, end; |
| 660 | 747 | u8 packet_size, dlen, i; |
| 661 | 748 | u8 *fw_data; |
| @@ -663,6 +750,11 @@ static int lme2510_download_firmware(struct usb_device *dev, · 1 unmodified line | ||
| 663 | 750 | packet_size = 0x31; |
| 664 | 751 | len_in = 1; |
| 665 | 752 | |
| 753 | + data = kzalloc(512, GFP_KERNEL); | |
| 754 | + if (!data) { | |
| 755 | + info("FRM Could not start Firmware Download (Buffer allocation failed)"); | |
| 756 | + return -ENOMEM; | |
| 757 | + } | |
| 666 | 758 | |
| 667 | 759 | info("FRM Starting Firmware Download"); |
| 668 | 760 | |
| @@ -678,15 +770,15 @@ static int lme2510_download_firmware(struct usb_device *dev, · 9 unmodified lines | ||
| 678 | 770 | data[0] = i | 0x80; |
| 679 | 771 | dlen = (u8)(end - j)-1; |
| 680 | 772 | } |
| 681 | − data[1] = dlen; | |
| 682 | − memcpy(&data[2], fw_data, dlen+1); | |
| 683 | − wlen = (u8) dlen + 4; | |
| 684 | − data[wlen-1] = check_sum(fw_data, dlen+1); | |
| 685 | − deb_info(1, "Data S=%02x:E=%02x CS= %02x", data[3], | |
| 773 | + data[1] = dlen; | |
| 774 | + memcpy(&data[2], fw_data, dlen+1); | |
| 775 | + wlen = (u8) dlen + 4; | |
| 776 | + data[wlen-1] = check_sum(fw_data, dlen+1); | |
| 777 | + deb_info(1, "Data S=%02x:E=%02x CS= %02x", data[3], | |
| 686 | 778 | data[dlen+2], data[dlen+3]); |
| 687 | − ret |= lme2510_bulk_write(dev, data, wlen, 1); | |
| 688 | − ret |= lme2510_bulk_read(dev, data, len_in , 1); | |
| 689 | − ret |= (data[0] == 0x88) ? 0 : -1; | |
| 779 | + ret |= lme2510_bulk_write(dev, data, wlen, 1); | |
| 780 | + ret |= lme2510_bulk_read(dev, data, len_in , 1); | |
| 781 | + ret |= (data[0] == 0x88) ? 0 : -1; | |
| 690 | 782 | } |
| 691 | 783 | } |
| 692 | 784 | |
| @@ -706,7 +798,7 @@ static int lme2510_download_firmware(struct usb_device *dev, · 13 unmodified lines | ||
| 706 | 798 | else |
| 707 | 799 | info("FRM Firmware Download Completed - Resetting Device"); |
| 708 | 800 | |
| 709 | − | |
| 801 | + kfree(data); | |
| 710 | 802 | return (ret < 0) ? -ENODEV : 0; |
| 711 | 803 | } |
| 712 | 804 | |
| @@ -747,7 +839,7 @@ static int lme_firmware_switch(struct usb_device *udev, int cold) · 34 unmodified lines | ||
| 747 | 839 | fw_lme = fw_s0194; |
| 748 | 840 | ret = request_firmware(&fw, fw_lme, &udev->dev); |
| 749 | 841 | if (ret == 0) { |
| 750 | − cold = 0;/*lme2510-s0194 cannot cold reset*/ | |
| 842 | + cold = 0; | |
| 751 | 843 | break; |
| 752 | 844 | } |
| 753 | 845 | dvb_usb_lme2510_firmware = TUNER_LG; |
| @@ -769,8 +861,10 @@ static int lme_firmware_switch(struct usb_device *udev, int cold) · 15 unmodified lines | ||
| 769 | 861 | case TUNER_S7395: |
| 770 | 862 | fw_lme = fw_c_s7395; |
| 771 | 863 | ret = request_firmware(&fw, fw_lme, &udev->dev); |
| 772 | − if (ret == 0) | |
| 864 | + if (ret == 0) { | |
| 865 | + cold = 0; | |
| 773 | 866 | break; |
| 867 | + } | |
| 774 | 868 | dvb_usb_lme2510_firmware = TUNER_LG; |
| 775 | 869 | case TUNER_LG: |
| 776 | 870 | fw_lme = fw_c_lg; |
| @@ -796,14 +890,14 @@ static int lme_firmware_switch(struct usb_device *udev, int cold) · 19 unmodified lines | ||
| 796 | 890 | ret = lme2510_download_firmware(udev, fw); |
| 797 | 891 | } |
| 798 | 892 | |
| 893 | + release_firmware(fw); | |
| 894 | + | |
| 799 | 895 | if (cold) { |
| 800 | 896 | info("FRM Changing to %s firmware", fw_lme); |
| 801 | 897 | lme_coldreset(udev); |
| 802 | 898 | return -ENODEV; |
| 803 | 899 | } |
| 804 | 900 | |
| 805 | − release_firmware(fw); | |
| 806 | − | |
| 807 | 901 | return ret; |
| 808 | 902 | } |
| 809 | 903 | |
| @@ -1017,12 +1111,13 @@ static int lme2510_powerup(struct dvb_usb_device *d, int onoff) · 207 unmodified lines | ||
| 1017 | 1111 | static u8 rbuf[1]; |
| 1018 | 1112 | int ret, len = 3, rlen = 1; |
| 1019 | 1113 | |
| 1020 | − ret = mutex_lock_interruptible(&d->i2c_mutex); | |
| 1114 | + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | |
| 1115 | + return -EAGAIN; | |
| 1021 | 1116 | |
| 1022 | 1117 | if (onoff) |
| 1023 | − ret |= lme2510_usb_talk(d, lnb_on, len, rbuf, rlen); | |
| 1118 | + ret = lme2510_usb_talk(d, lnb_on, len, rbuf, rlen); | |
| 1024 | 1119 | else |
| 1025 | − ret |= lme2510_usb_talk(d, lnb_off, len, rbuf, rlen); | |
| 1120 | + ret = lme2510_usb_talk(d, lnb_off, len, rbuf, rlen); | |
| 1026 | 1121 | |
| 1027 | 1122 | st->i2c_talk_onoff = 1; |
| 1028 | 1123 | |
| @@ -1086,7 +1181,13 @@ static struct dvb_usb_device_properties lme2510_properties = { · 57 unmodified lines | ||
| 1086 | 1181 | .num_adapters = 1, |
| 1087 | 1182 | .adapter = { |
| 1088 | 1183 | { |
| 1184 | + .caps = DVB_USB_ADAP_HAS_PID_FILTER| | |
| 1185 | + DVB_USB_ADAP_NEED_PID_FILTERING| | |
| 1186 | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | |
| 1089 | 1187 | .streaming_ctrl = lme2510_streaming_ctrl, |
| 1188 | + .pid_filter_count = 15, | |
| 1189 | + .pid_filter = lme2510_pid_filter, | |
| 1190 | + .pid_filter_ctrl = lme2510_pid_filter_ctrl, | |
| 1090 | 1191 | .frontend_attach = dm04_lme2510_frontend_attach, |
| 1091 | 1192 | .tuner_attach = dm04_lme2510_tuner, |
| 1092 | 1193 | /* parameter for the MPEG2-data transfer */ |
| @@ -1122,7 +1223,13 @@ static struct dvb_usb_device_properties lme2510c_properties = { · 29 unmodified lines | ||
| 1122 | 1223 | .num_adapters = 1, |
| 1123 | 1224 | .adapter = { |
| 1124 | 1225 | { |
| 1226 | + .caps = DVB_USB_ADAP_HAS_PID_FILTER| | |
| 1227 | + DVB_USB_ADAP_NEED_PID_FILTERING| | |
| 1228 | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | |
| 1125 | 1229 | .streaming_ctrl = lme2510_streaming_ctrl, |
| 1230 | + .pid_filter_count = 15, | |
| 1231 | + .pid_filter = lme2510_pid_filter, | |
| 1232 | + .pid_filter_ctrl = lme2510_pid_filter_ctrl, | |
| 1126 | 1233 | .frontend_attach = dm04_lme2510_frontend_attach, |
| 1127 | 1234 | .tuner_attach = dm04_lme2510_tuner, |
| 1128 | 1235 | /* parameter for the MPEG2-data transfer */ |
| @@ -1151,7 +1258,7 @@ static struct dvb_usb_device_properties lme2510c_properties = { · 22 unmodified lines | ||
| 1151 | 1258 | } |
| 1152 | 1259 | }; |
| 1153 | 1260 | |
| 1154 | −void *lme2510_exit_int(struct dvb_usb_device *d) | |
| 1261 | +static void *lme2510_exit_int(struct dvb_usb_device *d) | |
| 1155 | 1262 | { |
| 1156 | 1263 | struct lme2510_state *st = d->priv; |
| 1157 | 1264 | struct dvb_usb_adapter *adap = &d->adapter[0]; |
| @@ -1178,7 +1285,7 @@ void *lme2510_exit_int(struct dvb_usb_device *d) · 20 unmodified lines | ||
| 1178 | 1285 | return buffer; |
| 1179 | 1286 | } |
| 1180 | 1287 | |
| 1181 | −void lme2510_exit(struct usb_interface *intf) | |
| 1288 | +static void lme2510_exit(struct usb_interface *intf) | |
| 1182 | 1289 | { |
| 1183 | 1290 | struct dvb_usb_device *d = usb_get_intfdata(intf); |
| 1184 | 1291 | void *usb_buffer; |
| @@ -1220,5 +1327,5 @@ module_exit(lme2510_module_exit); · 35 unmodified lines | ||
| 1220 | 1327 | |
| 1221 | 1328 | MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); |
| 1222 | 1329 | MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); |
| 1223 | −MODULE_VERSION("1.80"); | |
| 1330 | +MODULE_VERSION("1.86"); | |
| 1224 | 1331 | MODULE_LICENSE("GPL"); |
| @@ -40,6 +40,7 @@ · 39 unmodified lines | ||
| 40 | 40 | */ |
| 41 | 41 | #define LME_ST_ON_W {0x06, 0x00} |
| 42 | 42 | #define LME_CLEAR_PID {0x03, 0x02, 0x20, 0xa0} |
| 43 | +#define LME_ZERO_PID {0x03, 0x06, 0x00, 0x00, 0x01, 0x00, 0x20, 0x9c} | |
| 43 | 44 | |
| 44 | 45 | /* LNB Voltage |
| 45 | 46 | * 07 XX XX |
| @@ -108,14 +109,14 @@ static u8 s7395_inittab[] = { · 62 unmodified lines | ||
| 108 | 109 | 0x3d, 0x30, |
| 109 | 110 | 0x40, 0x63, |
| 110 | 111 | 0x41, 0x04, |
| 111 | − 0x42, 0x60, | |
| 112 | + 0x42, 0x20, | |
| 112 | 113 | 0x43, 0x00, |
| 113 | 114 | 0x44, 0x00, |
| 114 | 115 | 0x45, 0x00, |
| 115 | 116 | 0x46, 0x00, |
| 116 | 117 | 0x47, 0x00, |
| 117 | 118 | 0x4a, 0x00, |
| 118 | − 0x50, 0x12, | |
| 119 | + 0x50, 0x10, | |
| 119 | 120 | 0x51, 0x36, |
| 120 | 121 | 0x52, 0x21, |
| 121 | 122 | 0x53, 0x94, |
| @@ -134,13 +134,17 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) · 133 unmodified lines | ||
| 134 | 134 | { |
| 135 | 135 | struct m920x_state *m = d->priv; |
| 136 | 136 | int i, ret = 0; |
| 137 | − u8 rc_state[2]; | |
| 137 | + u8 *rc_state; | |
| 138 | + | |
| 139 | + rc_state = kmalloc(2, GFP_KERNEL); | |
| 140 | + if (!rc_state) | |
| 141 | + return -ENOMEM; | |
| 138 | 142 | |
| 139 | 143 | if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0) |
| 140 | − goto unlock; | |
| 144 | + goto out; | |
| 141 | 145 | |
| 142 | 146 | if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0) |
| 143 | − goto unlock; | |
| 147 | + goto out; | |
| 144 | 148 | |
| 145 | 149 | for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) |
| 146 | 150 | 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) · 2 unmodified lines | ||
| 149 | 153 | switch(rc_state[0]) { |
| 150 | 154 | case 0x80: |
| 151 | 155 | *state = REMOTE_NO_KEY_PRESSED; |
| 152 | − goto unlock; | |
| 156 | + goto out; | |
| 153 | 157 | |
| 154 | 158 | case 0x88: /* framing error or "invalid code" */ |
| 155 | 159 | case 0x99: |
| @@ -157,7 +161,7 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) · 1 unmodified line | ||
| 157 | 161 | case 0xd8: |
| 158 | 162 | *state = REMOTE_NO_KEY_PRESSED; |
| 159 | 163 | m->rep_count = 0; |
| 160 | − goto unlock; | |
| 164 | + goto out; | |
| 161 | 165 | |
| 162 | 166 | case 0x93: |
| 163 | 167 | case 0x92: |
| @@ -165,7 +169,7 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) · 1 unmodified line | ||
| 165 | 169 | case 0x82: |
| 166 | 170 | m->rep_count = 0; |
| 167 | 171 | *state = REMOTE_KEY_PRESSED; |
| 168 | − goto unlock; | |
| 172 | + goto out; | |
| 169 | 173 | |
| 170 | 174 | case 0x91: |
| 171 | 175 | case 0x81: /* pinnacle PCTV310e */ |
| @@ -174,12 +178,12 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) · 2 unmodified lines | ||
| 174 | 178 | *state = REMOTE_KEY_REPEAT; |
| 175 | 179 | else |
| 176 | 180 | *state = REMOTE_NO_KEY_PRESSED; |
| 177 | − goto unlock; | |
| 181 | + goto out; | |
| 178 | 182 | |
| 179 | 183 | default: |
| 180 | 184 | deb("Unexpected rc state %02x\n", rc_state[0]); |
| 181 | 185 | *state = REMOTE_NO_KEY_PRESSED; |
| 182 | − goto unlock; | |
| 186 | + goto out; | |
| 183 | 187 | } |
| 184 | 188 | } |
| 185 | 189 | |
| @@ -188,8 +192,8 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) · 2 unmodified lines | ||
| 188 | 192 | |
| 189 | 193 | *state = REMOTE_NO_KEY_PRESSED; |
| 190 | 194 | |
| 191 | − unlock: | |
| 192 | − | |
| 195 | + out: | |
| 196 | + kfree(rc_state); | |
| 193 | 197 | return ret; |
| 194 | 198 | } |
| 195 | 199 | |
| @@ -339,13 +343,19 @@ static int m920x_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, in · 143 unmodified lines | ||
| 339 | 343 | static int m920x_firmware_download(struct usb_device *udev, const struct firmware *fw) |
| 340 | 344 | { |
| 341 | 345 | u16 value, index, size; |
| 342 | − u8 read[4], *buff; | |
| 346 | + u8 *read, *buff; | |
| 343 | 347 | int i, pass, ret = 0; |
| 344 | 348 | |
| 345 | 349 | buff = kmalloc(65536, GFP_KERNEL); |
| 346 | 350 | if (buff == NULL) |
| 347 | 351 | return -ENOMEM; |
| 348 | 352 | |
| 353 | + read = kmalloc(4, GFP_KERNEL); | |
| 354 | + if (!read) { | |
| 355 | + kfree(buff); | |
| 356 | + return -ENOMEM; | |
| 357 | + } | |
| 358 | + | |
| 349 | 359 | if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0) |
| 350 | 360 | goto done; |
| 351 | 361 | 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 · 44 unmodified lines | ||
| 396 | 406 | deb("firmware uploaded!\n"); |
| 397 | 407 | |
| 398 | 408 | done: |
| 409 | + kfree(read); | |
| 399 | 410 | kfree(buff); |
| 400 | 411 | |
| 401 | 412 | return ret; |
| @@ -632,9 +643,9 @@ static struct rc_map_table rc_map_pinnacle310e_table[] = { · 230 unmodified lines | ||
| 632 | 643 | { 0x16, KEY_POWER }, |
| 633 | 644 | { 0x17, KEY_FAVORITES }, |
| 634 | 645 | { 0x0f, KEY_TEXT }, |
| 635 | − { 0x48, KEY_MEDIA }, /* preview */ | |
| 646 | + { 0x48, KEY_PROGRAM }, /* preview */ | |
| 636 | 647 | { 0x1c, KEY_EPG }, |
| 637 | − { 0x04, KEY_LIST }, /* record list */ | |
| 648 | + { 0x04, KEY_LIST }, /* record list */ | |
| 638 | 649 | { 0x03, KEY_1 }, |
| 639 | 650 | { 0x01, KEY_2 }, |
| 640 | 651 | { 0x06, KEY_3 }, |
| @@ -674,14 +685,14 @@ static struct rc_map_table rc_map_pinnacle310e_table[] = { · 33 unmodified lines | ||
| 674 | 685 | { 0x0e, KEY_MUTE }, |
| 675 | 686 | /* { 0x49, KEY_LR }, */ /* L/R */ |
| 676 | 687 | { 0x07, KEY_SLEEP }, /* Hibernate */ |
| 677 | − { 0x08, KEY_MEDIA }, /* A/V */ | |
| 678 | − { 0x0e, KEY_MENU }, /* Recall */ | |
| 688 | + { 0x08, KEY_VIDEO }, /* A/V */ | |
| 689 | + { 0x0e, KEY_MENU }, /* Recall */ | |
| 679 | 690 | { 0x45, KEY_ZOOMIN }, |
| 680 | 691 | { 0x46, KEY_ZOOMOUT }, |
| 681 | − { 0x18, KEY_TV }, /* Red */ | |
| 682 | − { 0x53, KEY_VCR }, /* Green */ | |
| 683 | − { 0x5e, KEY_SAT }, /* Yellow */ | |
| 684 | − { 0x5f, KEY_PLAYER }, /* Blue */ | |
| 692 | + { 0x18, KEY_RED }, /* Red */ | |
| 693 | + { 0x53, KEY_GREEN }, /* Green */ | |
| 694 | + { 0x5e, KEY_YELLOW }, /* Yellow */ | |
| 695 | + { 0x5f, KEY_BLUE }, /* Blue */ | |
| 685 | 696 | }; |
| 686 | 697 | |
| 687 | 698 | /* DVB USB Driver stuff */ |
| @@ -47,7 +47,7 @@ static struct rc_map_table rc_map_haupp_table[] = { · 46 unmodified lines | ||
| 47 | 47 | { 0x1e17, KEY_RIGHT }, |
| 48 | 48 | { 0x1e18, KEY_VIDEO }, |
| 49 | 49 | { 0x1e19, KEY_AUDIO }, |
| 50 | − { 0x1e1a, KEY_MEDIA }, | |
| 50 | + { 0x1e1a, KEY_IMAGES }, | |
| 51 | 51 | { 0x1e1b, KEY_EPG }, |
| 52 | 52 | { 0x1e1c, KEY_TV }, |
| 53 | 53 | { 0x1e1e, KEY_NEXT }, |
| @@ -53,27 +53,36 @@ static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value, · 52 unmodified lines | ||
| 53 | 53 | u8 * data, u16 len, int flags) |
| 54 | 54 | { |
| 55 | 55 | int ret; |
| 56 | − u8 r; | |
| 57 | − u8 u8buf[len]; | |
| 58 | − | |
| 56 | + u8 tmp; | |
| 57 | + u8 *buf; | |
| 59 | 58 | unsigned int pipe = (flags == OPERA_READ_MSG) ? |
| 60 | 59 | usb_rcvctrlpipe(dev,0) : usb_sndctrlpipe(dev, 0); |
| 61 | 60 | u8 request_type = (flags == OPERA_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; |
| 62 | 61 | |
| 62 | + buf = kmalloc(len, GFP_KERNEL); | |
| 63 | + if (!buf) | |
| 64 | + return -ENOMEM; | |
| 65 | + | |
| 63 | 66 | if (flags == OPERA_WRITE_MSG) |
| 64 | − memcpy(u8buf, data, len); | |
| 65 | − ret = | |
| 66 | − usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, | |
| 67 | − value, 0x0, u8buf, len, 2000); | |
| 67 | + memcpy(buf, data, len); | |
| 68 | + ret = usb_control_msg(dev, pipe, request, | |
| 69 | + request_type | USB_TYPE_VENDOR, value, 0x0, | |
| 70 | + buf, len, 2000); | |
| 68 | 71 | |
| 69 | 72 | if (request == OPERA_TUNER_REQ) { |
| 73 | + tmp = buf[0]; | |
| 70 | 74 | if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), |
| 71 | − OPERA_TUNER_REQ, USB_DIR_IN | USB_TYPE_VENDOR, | |
| 72 | − 0x01, 0x0, &r, 1, 2000)<1 || r!=0x08) | |
| 73 | − return 0; | |
| 75 | + OPERA_TUNER_REQ, USB_DIR_IN | USB_TYPE_VENDOR, | |
| 76 | + 0x01, 0x0, buf, 1, 2000) < 1 || buf[0] != 0x08) { | |
| 77 | + ret = 0; | |
| 78 | + goto out; | |
| 79 | + } | |
| 80 | + buf[0] = tmp; | |
| 74 | 81 | } |
| 75 | 82 | if (flags == OPERA_READ_MSG) |
| 76 | − memcpy(data, u8buf, len); | |
| 83 | + memcpy(data, buf, len); | |
| 84 | +out: | |
| 85 | + kfree(buf); | |
| 77 | 86 | return ret; |
| 78 | 87 | } |
| 79 | 88 | |
| @@ -189,7 +198,7 @@ static int opera1_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate, · 109 unmodified lines | ||
| 189 | 198 | static u8 opera1_inittab[] = { |
| 190 | 199 | 0x00, 0xa1, |
| 191 | 200 | 0x01, 0x15, |
| 192 | − 0x02, 0x00, | |
| 201 | + 0x02, 0x30, | |
| 193 | 202 | 0x03, 0x00, |
| 194 | 203 | 0x04, 0x7d, |
| 195 | 204 | 0x05, 0x05, |
| @@ -41,14 +41,23 @@ struct vp702x_fe_state { · 40 unmodified lines | ||
| 41 | 41 | |
| 42 | 42 | static int vp702x_fe_refresh_state(struct vp702x_fe_state *st) |
| 43 | 43 | { |
| 44 | − u8 buf[10]; | |
| 45 | − if (time_after(jiffies,st->next_status_check)) { | |
| 46 | − vp702x_usb_in_op(st->d,READ_STATUS,0,0,buf,10); | |
| 44 | + struct vp702x_device_state *dst = st->d->priv; | |
| 45 | + u8 *buf; | |
| 47 | 46 | |
| 47 | + if (time_after(jiffies, st->next_status_check)) { | |
| 48 | + mutex_lock(&dst->buf_mutex); | |
| 49 | + buf = dst->buf; | |
| 50 | + | |
| 51 | + vp702x_usb_in_op(st->d, READ_STATUS, 0, 0, buf, 10); | |
| 48 | 52 | st->lock = buf[4]; |
| 49 | − vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x11,0,&st->snr,1); | |
| 50 | − vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x15,0,&st->sig,1); | |
| 51 | 53 | |
| 54 | + vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x11, 0, buf, 1); | |
| 55 | + st->snr = buf[0]; | |
| 56 | + | |
| 57 | + vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x15, 0, buf, 1); | |
| 58 | + st->sig = buf[0]; | |
| 59 | + | |
| 60 | + mutex_unlock(&dst->buf_mutex); | |
| 52 | 61 | st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000; |
| 53 | 62 | } |
| 54 | 63 | return 0; |
| @@ -130,11 +139,17 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe, · 75 unmodified lines | ||
| 130 | 139 | struct dvb_frontend_parameters *fep) |
| 131 | 140 | { |
| 132 | 141 | struct vp702x_fe_state *st = fe->demodulator_priv; |
| 142 | + struct vp702x_device_state *dst = st->d->priv; | |
| 133 | 143 | u32 freq = fep->frequency/1000; |
| 134 | 144 | /*CalFrequency*/ |
| 135 | 145 | /* u16 frequencyRef[16] = { 2, 4, 8, 16, 32, 64, 128, 256, 24, 5, 10, 20, 40, 80, 160, 320 }; */ |
| 136 | 146 | u64 sr; |
| 137 | − u8 cmd[8] = { 0 },ibuf[10]; | |
| 147 | + u8 *cmd; | |
| 148 | + | |
| 149 | + mutex_lock(&dst->buf_mutex); | |
| 150 | + | |
| 151 | + cmd = dst->buf; | |
| 152 | + memset(cmd, 0, 10); | |
| 138 | 153 | |
| 139 | 154 | cmd[0] = (freq >> 8) & 0x7f; |
| 140 | 155 | cmd[1] = freq & 0xff; |
| @@ -170,13 +185,15 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe, · 29 unmodified lines | ||
| 170 | 185 | st->status_check_interval = 250; |
| 171 | 186 | st->next_status_check = jiffies; |
| 172 | 187 | |
| 173 | − vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100); | |
| 188 | + vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100); | |
| 174 | 189 | |
| 175 | − if (ibuf[2] == 0 && ibuf[3] == 0) | |
| 190 | + if (cmd[2] == 0 && cmd[3] == 0) | |
| 176 | 191 | deb_fe("tuning failed.\n"); |
| 177 | 192 | else |
| 178 | 193 | deb_fe("tuning succeeded.\n"); |
| 179 | 194 | |
| 195 | + mutex_unlock(&dst->buf_mutex); | |
| 196 | + | |
| 180 | 197 | return 0; |
| 181 | 198 | } |
| 182 | 199 | |
| @@ -204,27 +221,32 @@ static int vp702x_fe_get_frontend(struct dvb_frontend* fe, · 21 unmodified lines | ||
| 204 | 221 | static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe, |
| 205 | 222 | struct dvb_diseqc_master_cmd *m) |
| 206 | 223 | { |
| 224 | + u8 *cmd; | |
| 207 | 225 | struct vp702x_fe_state *st = fe->demodulator_priv; |
| 208 | − u8 cmd[8],ibuf[10]; | |
| 209 | − memset(cmd,0,8); | |
| 226 | + struct vp702x_device_state *dst = st->d->priv; | |
| 210 | 227 | |
| 211 | 228 | deb_fe("%s\n",__func__); |
| 212 | 229 | |
| 213 | 230 | if (m->msg_len > 4) |
| 214 | 231 | return -EINVAL; |
| 215 | 232 | |
| 233 | + mutex_lock(&dst->buf_mutex); | |
| 234 | + | |
| 235 | + cmd = dst->buf; | |
| 216 | 236 | cmd[1] = SET_DISEQC_CMD; |
| 217 | 237 | cmd[2] = m->msg_len; |
| 218 | 238 | memcpy(&cmd[3], m->msg, m->msg_len); |
| 219 | − cmd[7] = vp702x_chksum(cmd,0,7); | |
| 239 | + cmd[7] = vp702x_chksum(cmd, 0, 7); | |
| 220 | 240 | |
| 221 | − vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100); | |
| 241 | + vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100); | |
| 222 | 242 | |
| 223 | − if (ibuf[2] == 0 && ibuf[3] == 0) | |
| 243 | + if (cmd[2] == 0 && cmd[3] == 0) | |
| 224 | 244 | deb_fe("diseqc cmd failed.\n"); |
| 225 | 245 | else |
| 226 | 246 | deb_fe("diseqc cmd succeeded.\n"); |
| 227 | 247 | |
| 248 | + mutex_unlock(&dst->buf_mutex); | |
| 249 | + | |
| 228 | 250 | return 0; |
| 229 | 251 | } |
| 230 | 252 | |
| @@ -237,7 +259,9 @@ static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd · 6 unmodified lines | ||
| 237 | 259 | static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) |
| 238 | 260 | { |
| 239 | 261 | struct vp702x_fe_state *st = fe->demodulator_priv; |
| 240 | − u8 ibuf[10]; | |
| 262 | + struct vp702x_device_state *dst = st->d->priv; | |
| 263 | + u8 *buf; | |
| 264 | + | |
| 241 | 265 | deb_fe("%s\n",__func__); |
| 242 | 266 | |
| 243 | 267 | st->tone_mode = tone; |
| @@ -247,14 +271,21 @@ static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) · 3 unmodified lines | ||
| 247 | 271 | else |
| 248 | 272 | st->lnb_buf[2] = 0x00; |
| 249 | 273 | |
| 250 | − st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7); | |
| 274 | + st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7); | |
| 275 | + | |
| 276 | + mutex_lock(&dst->buf_mutex); | |
| 277 | + | |
| 278 | + buf = dst->buf; | |
| 279 | + memcpy(buf, st->lnb_buf, 8); | |
| 251 | 280 | |
| 252 | − vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100); | |
| 253 | − if (ibuf[2] == 0 && ibuf[3] == 0) | |
| 281 | + vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100); | |
| 282 | + if (buf[2] == 0 && buf[3] == 0) | |
| 254 | 283 | deb_fe("set_tone cmd failed.\n"); |
| 255 | 284 | else |
| 256 | 285 | deb_fe("set_tone cmd succeeded.\n"); |
| 257 | 286 | |
| 287 | + mutex_unlock(&dst->buf_mutex); | |
| 288 | + | |
| 258 | 289 | return 0; |
| 259 | 290 | } |
| 260 | 291 | |
| @@ -262,7 +293,8 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t · 1 unmodified line | ||
| 262 | 293 | voltage) |
| 263 | 294 | { |
| 264 | 295 | struct vp702x_fe_state *st = fe->demodulator_priv; |
| 265 | − u8 ibuf[10]; | |
| 296 | + struct vp702x_device_state *dst = st->d->priv; | |
| 297 | + u8 *buf; | |
| 266 | 298 | deb_fe("%s\n",__func__); |
| 267 | 299 | |
| 268 | 300 | st->voltage = voltage; |
| @@ -272,14 +304,20 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t · 3 unmodified lines | ||
| 272 | 304 | else |
| 273 | 305 | st->lnb_buf[4] = 0x00; |
| 274 | 306 | |
| 275 | − st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7); | |
| 307 | + st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7); | |
| 308 | + | |
| 309 | + mutex_lock(&dst->buf_mutex); | |
| 310 | + | |
| 311 | + buf = dst->buf; | |
| 312 | + memcpy(buf, st->lnb_buf, 8); | |
| 276 | 313 | |
| 277 | − vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100); | |
| 278 | − if (ibuf[2] == 0 && ibuf[3] == 0) | |
| 314 | + vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100); | |
| 315 | + if (buf[2] == 0 && buf[3] == 0) | |
| 279 | 316 | deb_fe("set_voltage cmd failed.\n"); |
| 280 | 317 | else |
| 281 | 318 | deb_fe("set_voltage cmd succeeded.\n"); |
| 282 | 319 | |
| 320 | + mutex_unlock(&dst->buf_mutex); | |
| 283 | 321 | return 0; |
| 284 | 322 | } |
| 285 | 323 | |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | * see Documentation/dvb/README.dvb-usb for more information |
| 16 | 16 | */ |
| 17 | 17 | #include "vp702x.h" |
| 18 | +#include <linux/mutex.h> | |
| 18 | 19 | |
| 19 | 20 | /* debug */ |
| 20 | 21 | 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 · 2 unmodified lines | ||
| 23 | 24 | |
| 24 | 25 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
| 25 | 26 | |
| 26 | −struct vp702x_state { | |
| 27 | +struct vp702x_adapter_state { | |
| 27 | 28 | int pid_filter_count; |
| 28 | 29 | int pid_filter_can_bypass; |
| 29 | 30 | u8 pid_filter_state; |
| 30 | 31 | }; |
| 31 | 32 | |
| 32 | −struct vp702x_device_state { | |
| 33 | − u8 power_state; | |
| 34 | −}; | |
| 35 | − | |
| 36 | −/* check for mutex FIXME */ | |
| 37 | −int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) | |
| 33 | +static int vp702x_usb_in_op_unlocked(struct dvb_usb_device *d, u8 req, | |
| 34 | + u16 value, u16 index, u8 *b, int blen) | |
| 38 | 35 | { |
| 39 | − int ret = -1; | |
| 36 | + int ret; | |
| 40 | 37 | |
| 41 | − ret = usb_control_msg(d->udev, | |
| 42 | − usb_rcvctrlpipe(d->udev,0), | |
| 43 | − req, | |
| 44 | − USB_TYPE_VENDOR | USB_DIR_IN, | |
| 45 | − value,index,b,blen, | |
| 46 | − 2000); | |
| 38 | + ret = usb_control_msg(d->udev, | |
| 39 | + usb_rcvctrlpipe(d->udev, 0), | |
| 40 | + req, | |
| 41 | + USB_TYPE_VENDOR | USB_DIR_IN, | |
| 42 | + value, index, b, blen, | |
| 43 | + 2000); | |
| 47 | 44 | |
| 48 | 45 | if (ret < 0) { |
| 49 | 46 | 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 · 8 unmodified lines | ||
| 58 | 55 | return ret; |
| 59 | 56 | } |
| 60 | 57 | |
| 61 | −static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, | |
| 62 | − u16 index, u8 *b, int blen) | |
| 58 | +int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, | |
| 59 | + u16 index, u8 *b, int blen) | |
| 60 | +{ | |
| 61 | + int ret; | |
| 62 | + | |
| 63 | + mutex_lock(&d->usb_mutex); | |
| 64 | + ret = vp702x_usb_in_op_unlocked(d, req, value, index, b, blen); | |
| 65 | + mutex_unlock(&d->usb_mutex); | |
| 66 | + | |
| 67 | + return ret; | |
| 68 | +} | |
| 69 | + | |
| 70 | +int vp702x_usb_out_op_unlocked(struct dvb_usb_device *d, u8 req, u16 value, | |
| 71 | + u16 index, u8 *b, int blen) | |
| 63 | 72 | { |
| 64 | 73 | int ret; |
| 65 | 74 | 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, · 11 unmodified lines | ||
| 77 | 86 | return 0; |
| 78 | 87 | } |
| 79 | 88 | |
| 89 | +int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, | |
| 90 | + u16 index, u8 *b, int blen) | |
| 91 | +{ | |
| 92 | + int ret; | |
| 93 | + | |
| 94 | + mutex_lock(&d->usb_mutex); | |
| 95 | + ret = vp702x_usb_out_op_unlocked(d, req, value, index, b, blen); | |
| 96 | + mutex_unlock(&d->usb_mutex); | |
| 97 | + | |
| 98 | + return ret; | |
| 99 | +} | |
| 100 | + | |
| 80 | 101 | int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec) |
| 81 | 102 | { |
| 82 | 103 | int ret; |
| @@ -84,50 +105,93 @@ int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int il · 1 unmodified line | ||
| 84 | 105 | if ((ret = mutex_lock_interruptible(&d->usb_mutex))) |
| 85 | 106 | return ret; |
| 86 | 107 | |
| 87 | − ret = vp702x_usb_out_op(d,REQUEST_OUT,0,0,o,olen); | |
| 108 | + ret = vp702x_usb_out_op_unlocked(d, REQUEST_OUT, 0, 0, o, olen); | |
| 88 | 109 | msleep(msec); |
| 89 | − ret = vp702x_usb_in_op(d,REQUEST_IN,0,0,i,ilen); | |
| 110 | + ret = vp702x_usb_in_op_unlocked(d, REQUEST_IN, 0, 0, i, ilen); | |
| 90 | 111 | |
| 91 | 112 | mutex_unlock(&d->usb_mutex); |
| 92 | − | |
| 93 | 113 | return ret; |
| 94 | 114 | } |
| 95 | 115 | |
| 96 | 116 | static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, |
| 97 | 117 | int olen, u8 *i, int ilen, int msec) |
| 98 | 118 | { |
| 99 | − u8 bout[olen+2]; | |
| 100 | − u8 bin[ilen+1]; | |
| 119 | + struct vp702x_device_state *st = d->priv; | |
| 101 | 120 | int ret = 0; |
| 121 | + u8 *buf; | |
| 122 | + int buflen = max(olen + 2, ilen + 1); | |
| 123 | + | |
| 124 | + ret = mutex_lock_interruptible(&st->buf_mutex); | |
| 125 | + if (ret < 0) | |
| 126 | + return ret; | |
| 127 | + | |
| 128 | + if (buflen > st->buf_len) { | |
| 129 | + buf = kmalloc(buflen, GFP_KERNEL); | |
| 130 | + if (!buf) { | |
| 131 | + mutex_unlock(&st->buf_mutex); | |
| 132 | + return -ENOMEM; | |
| 133 | + } | |
| 134 | + info("successfully reallocated a bigger buffer"); | |
| 135 | + kfree(st->buf); | |
| 136 | + st->buf = buf; | |
| 137 | + st->buf_len = buflen; | |
| 138 | + } else { | |
| 139 | + buf = st->buf; | |
| 140 | + } | |
| 102 | 141 | |
| 103 | − bout[0] = 0x00; | |
| 104 | − bout[1] = cmd; | |
| 105 | − memcpy(&bout[2],o,olen); | |
| 142 | + buf[0] = 0x00; | |
| 143 | + buf[1] = cmd; | |
| 144 | + memcpy(&buf[2], o, olen); | |
| 106 | 145 | |
| 107 | − ret = vp702x_usb_inout_op(d, bout, olen+2, bin, ilen+1,msec); | |
| 146 | + ret = vp702x_usb_inout_op(d, buf, olen+2, buf, ilen+1, msec); | |
| 108 | 147 | |
| 109 | 148 | if (ret == 0) |
| 110 | − memcpy(i,&bin[1],ilen); | |
| 149 | + memcpy(i, &buf[1], ilen); | |
| 150 | + mutex_unlock(&st->buf_mutex); | |
| 111 | 151 | |
| 112 | 152 | return ret; |
| 113 | 153 | } |
| 114 | 154 | |
| 115 | 155 | static int vp702x_set_pld_mode(struct dvb_usb_adapter *adap, u8 bypass) |
| 116 | 156 | { |
| 117 | − u8 buf[16] = { 0 }; | |
| 118 | − return vp702x_usb_in_op(adap->dev, 0xe0, (bypass << 8) | 0x0e, 0, buf, 16); | |
| 157 | + int ret; | |
| 158 | + struct vp702x_device_state *st = adap->dev->priv; | |
| 159 | + u8 *buf; | |
| 160 | + | |
| 161 | + mutex_lock(&st->buf_mutex); | |
| 162 | + | |
| 163 | + buf = st->buf; | |
| 164 | + memset(buf, 0, 16); | |
| 165 | + | |
| 166 | + ret = vp702x_usb_in_op(adap->dev, 0xe0, (bypass << 8) | 0x0e, | |
| 167 | + 0, buf, 16); | |
| 168 | + mutex_unlock(&st->buf_mutex); | |
| 169 | + return ret; | |
| 119 | 170 | } |
| 120 | 171 | |
| 121 | 172 | static int vp702x_set_pld_state(struct dvb_usb_adapter *adap, u8 state) |
| 122 | 173 | { |
| 123 | − u8 buf[16] = { 0 }; | |
| 124 | − return vp702x_usb_in_op(adap->dev, 0xe0, (state << 8) | 0x0f, 0, buf, 16); | |
| 174 | + int ret; | |
| 175 | + struct vp702x_device_state *st = adap->dev->priv; | |
| 176 | + u8 *buf; | |
| 177 | + | |
| 178 | + mutex_lock(&st->buf_mutex); | |
| 179 | + | |
| 180 | + buf = st->buf; | |
| 181 | + memset(buf, 0, 16); | |
| 182 | + ret = vp702x_usb_in_op(adap->dev, 0xe0, (state << 8) | 0x0f, | |
| 183 | + 0, buf, 16); | |
| 184 | + | |
| 185 | + mutex_unlock(&st->buf_mutex); | |
| 186 | + | |
| 187 | + return ret; | |
| 125 | 188 | } |
| 126 | 189 | |
| 127 | 190 | static int vp702x_set_pid(struct dvb_usb_adapter *adap, u16 pid, u8 id, int onoff) |
| 128 | 191 | { |
| 129 | − struct vp702x_state *st = adap->priv; | |
| 130 | − u8 buf[16] = { 0 }; | |
| 192 | + struct vp702x_adapter_state *st = adap->priv; | |
| 193 | + struct vp702x_device_state *dst = adap->dev->priv; | |
| 194 | + u8 *buf; | |
| 131 | 195 | |
| 132 | 196 | if (onoff) |
| 133 | 197 | 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 · 5 unmodified lines | ||
| 139 | 203 | id = 0x10 + id*2; |
| 140 | 204 | |
| 141 | 205 | vp702x_set_pld_state(adap, st->pid_filter_state); |
| 206 | + | |
| 207 | + mutex_lock(&dst->buf_mutex); | |
| 208 | + | |
| 209 | + buf = dst->buf; | |
| 210 | + memset(buf, 0, 16); | |
| 142 | 211 | vp702x_usb_in_op(adap->dev, 0xe0, (((pid >> 8) & 0xff) << 8) | (id), 0, buf, 16); |
| 143 | 212 | vp702x_usb_in_op(adap->dev, 0xe0, (((pid ) & 0xff) << 8) | (id+1), 0, buf, 16); |
| 213 | + | |
| 214 | + mutex_unlock(&dst->buf_mutex); | |
| 215 | + | |
| 144 | 216 | return 0; |
| 145 | 217 | } |
| 146 | 218 | |
| 147 | 219 | |
| 148 | 220 | static int vp702x_init_pid_filter(struct dvb_usb_adapter *adap) |
| 149 | 221 | { |
| 150 | − struct vp702x_state *st = adap->priv; | |
| 222 | + struct vp702x_adapter_state *st = adap->priv; | |
| 223 | + struct vp702x_device_state *dst = adap->dev->priv; | |
| 151 | 224 | int i; |
| 152 | − u8 b[10] = { 0 }; | |
| 225 | + u8 *b; | |
| 153 | 226 | |
| 154 | 227 | st->pid_filter_count = 8; |
| 155 | 228 | st->pid_filter_can_bypass = 1; |
| 156 | 229 | st->pid_filter_state = 0x00; |
| 157 | 230 | |
| 158 | − vp702x_set_pld_mode(adap, 1); // bypass | |
| 231 | + vp702x_set_pld_mode(adap, 1); /* bypass */ | |
| 159 | 232 | |
| 160 | 233 | for (i = 0; i < st->pid_filter_count; i++) |
| 161 | 234 | vp702x_set_pid(adap, 0xffff, i, 1); |
| 162 | 235 | |
| 236 | + mutex_lock(&dst->buf_mutex); | |
| 237 | + b = dst->buf; | |
| 238 | + memset(b, 0, 10); | |
| 163 | 239 | vp702x_usb_in_op(adap->dev, 0xb5, 3, 0, b, 10); |
| 164 | 240 | vp702x_usb_in_op(adap->dev, 0xb5, 0, 0, b, 10); |
| 165 | 241 | vp702x_usb_in_op(adap->dev, 0xb5, 1, 0, b, 10); |
| 242 | + mutex_unlock(&dst->buf_mutex); | |
| 243 | + /*vp702x_set_pld_mode(d, 0); // filter */ | |
| 166 | 244 | |
| 167 | − //vp702x_set_pld_mode(d, 0); // filter | |
| 168 | 245 | return 0; |
| 169 | 246 | } |
| 170 | 247 | |
| @@ -182,18 +259,23 @@ static struct rc_map_table rc_map_vp702x_table[] = { · 11 unmodified lines | ||
| 182 | 259 | /* remote control stuff (does not work with my box) */ |
| 183 | 260 | static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) |
| 184 | 261 | { |
| 185 | − u8 key[10]; | |
| 262 | + u8 *key; | |
| 186 | 263 | int i; |
| 187 | 264 | |
| 188 | 265 | /* remove the following return to enabled remote querying */ |
| 189 | 266 | return 0; |
| 190 | 267 | |
| 268 | + key = kmalloc(10, GFP_KERNEL); | |
| 269 | + if (!key) | |
| 270 | + return -ENOMEM; | |
| 271 | + | |
| 191 | 272 | vp702x_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10); |
| 192 | 273 | |
| 193 | 274 | deb_rc("remote query key: %x %d\n",key[1],key[1]); |
| 194 | 275 | |
| 195 | 276 | if (key[1] == 0x44) { |
| 196 | 277 | *state = REMOTE_NO_KEY_PRESSED; |
| 278 | + kfree(key); | |
| 197 | 279 | return 0; |
| 198 | 280 | } |
| 199 | 281 | |
| @@ -203,15 +285,23 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) · 3 unmodified lines | ||
| 203 | 285 | *event = rc_map_vp702x_table[i].keycode; |
| 204 | 286 | break; |
| 205 | 287 | } |
| 288 | + kfree(key); | |
| 206 | 289 | return 0; |
| 207 | 290 | } |
| 208 | 291 | |
| 209 | 292 | |
| 210 | 293 | static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6]) |
| 211 | 294 | { |
| 212 | − u8 i; | |
| 295 | + u8 i, *buf; | |
| 296 | + struct vp702x_device_state *st = d->priv; | |
| 297 | + | |
| 298 | + mutex_lock(&st->buf_mutex); | |
| 299 | + buf = st->buf; | |
| 213 | 300 | for (i = 6; i < 12; i++) |
| 214 | − vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &mac[i - 6], 1); | |
| 301 | + vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &buf[i - 6], 1); | |
| 302 | + | |
| 303 | + memcpy(mac, buf, 6); | |
| 304 | + mutex_unlock(&st->buf_mutex); | |
| 215 | 305 | return 0; |
| 216 | 306 | } |
| 217 | 307 | |
| @@ -221,7 +311,8 @@ static int vp702x_frontend_attach(struct dvb_usb_adapter *adap) · 3 unmodified lines | ||
| 221 | 311 | |
| 222 | 312 | vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 0, 7, NULL, 0); |
| 223 | 313 | |
| 224 | − if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0, buf, 10, 10)) | |
| 314 | + if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0, | |
| 315 | + buf, 10, 10)) | |
| 225 | 316 | return -EIO; |
| 226 | 317 | |
| 227 | 318 | buf[9] = '\0'; |
| @@ -240,8 +331,38 @@ static struct dvb_usb_device_properties vp702x_properties; · 12 unmodified lines | ||
| 240 | 331 | static int vp702x_usb_probe(struct usb_interface *intf, |
| 241 | 332 | const struct usb_device_id *id) |
| 242 | 333 | { |
| 243 | − return dvb_usb_device_init(intf, &vp702x_properties, | |
| 244 | − THIS_MODULE, NULL, adapter_nr); | |
| 334 | + struct dvb_usb_device *d; | |
| 335 | + struct vp702x_device_state *st; | |
| 336 | + int ret; | |
| 337 | + | |
| 338 | + ret = dvb_usb_device_init(intf, &vp702x_properties, | |
| 339 | + THIS_MODULE, &d, adapter_nr); | |
| 340 | + if (ret) | |
| 341 | + goto out; | |
| 342 | + | |
| 343 | + st = d->priv; | |
| 344 | + st->buf_len = 16; | |
| 345 | + st->buf = kmalloc(st->buf_len, GFP_KERNEL); | |
| 346 | + if (!st->buf) { | |
| 347 | + ret = -ENOMEM; | |
| 348 | + dvb_usb_device_exit(intf); | |
| 349 | + goto out; | |
| 350 | + } | |
| 351 | + mutex_init(&st->buf_mutex); | |
| 352 | + | |
| 353 | +out: | |
| 354 | + return ret; | |
| 355 | + | |
| 356 | +} | |
| 357 | + | |
| 358 | +static void vp702x_usb_disconnect(struct usb_interface *intf) | |
| 359 | +{ | |
| 360 | + struct dvb_usb_device *d = usb_get_intfdata(intf); | |
| 361 | + struct vp702x_device_state *st = d->priv; | |
| 362 | + mutex_lock(&st->buf_mutex); | |
| 363 | + kfree(st->buf); | |
| 364 | + mutex_unlock(&st->buf_mutex); | |
| 365 | + dvb_usb_device_exit(intf); | |
| 245 | 366 | } |
| 246 | 367 | |
| 247 | 368 | static struct usb_device_id vp702x_usb_table [] = { |
| @@ -278,7 +399,7 @@ static struct dvb_usb_device_properties vp702x_properties = { · 30 unmodified lines | ||
| 278 | 399 | } |
| 279 | 400 | } |
| 280 | 401 | }, |
| 281 | − .size_of_priv = sizeof(struct vp702x_state), | |
| 402 | + .size_of_priv = sizeof(struct vp702x_adapter_state), | |
| 282 | 403 | } |
| 283 | 404 | }, |
| 284 | 405 | .read_mac_address = vp702x_read_mac_addr, |
| @@ -307,9 +428,9 @@ static struct dvb_usb_device_properties vp702x_properties = { · 22 unmodified lines | ||
| 307 | 428 | /* usb specific object needed to register this driver with the usb subsystem */ |
| 308 | 429 | static struct usb_driver vp702x_usb_driver = { |
| 309 | 430 | .name = "dvb_usb_vp702x", |
| 310 | − .probe = vp702x_usb_probe, | |
| 311 | − .disconnect = dvb_usb_device_exit, | |
| 312 | − .id_table = vp702x_usb_table, | |
| 431 | + .probe = vp702x_usb_probe, | |
| 432 | + .disconnect = vp702x_usb_disconnect, | |
| 433 | + .id_table = vp702x_usb_table, | |
| 313 | 434 | }; |
| 314 | 435 | |
| 315 | 436 | /* module stuff */ |
| @@ -98,6 +98,13 @@ extern int dvb_usb_vp702x_debug; · 97 unmodified lines | ||
| 98 | 98 | #define RESET_TUNER 0xBE |
| 99 | 99 | /* IN i: 0, v: 0, no extra buffer */ |
| 100 | 100 | |
| 101 | +struct vp702x_device_state { | |
| 102 | + struct mutex buf_mutex; | |
| 103 | + int buf_len; | |
| 104 | + u8 *buf; | |
| 105 | +}; | |
| 106 | + | |
| 107 | + | |
| 101 | 108 | extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d); |
| 102 | 109 | |
| 103 | 110 | extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec); |
| @@ -28,9 +28,9 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); · 27 unmodified lines | ||
| 28 | 28 | int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec) |
| 29 | 29 | { |
| 30 | 30 | int ret = 0; |
| 31 | − u8 inbuf[12] = { 0 }, outbuf[20] = { 0 }; | |
| 31 | + u8 *buf = d->priv; | |
| 32 | 32 | |
| 33 | − outbuf[0] = cmd; | |
| 33 | + buf[0] = cmd; | |
| 34 | 34 | |
| 35 | 35 | if (outlen > 19) |
| 36 | 36 | outlen = 19; |
| @@ -38,19 +38,21 @@ int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, · 1 unmodified line | ||
| 38 | 38 | if (inlen > 11) |
| 39 | 39 | inlen = 11; |
| 40 | 40 | |
| 41 | + ret = mutex_lock_interruptible(&d->usb_mutex); | |
| 42 | + if (ret) | |
| 43 | + return ret; | |
| 44 | + | |
| 41 | 45 | if (out != NULL && outlen > 0) |
| 42 | − memcpy(&outbuf[1], out, outlen); | |
| 46 | + memcpy(&buf[1], out, outlen); | |
| 43 | 47 | |
| 44 | 48 | deb_xfer("out buffer: "); |
| 45 | − debug_dump(outbuf,outlen+1,deb_xfer); | |
| 49 | + debug_dump(buf, outlen+1, deb_xfer); | |
| 46 | 50 | |
| 47 | − if ((ret = mutex_lock_interruptible(&d->usb_mutex))) | |
| 48 | − return ret; | |
| 49 | 51 | |
| 50 | 52 | if (usb_control_msg(d->udev, |
| 51 | 53 | usb_sndctrlpipe(d->udev,0), |
| 52 | 54 | TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, |
| 53 | − outbuf, 20, 2000) != 20) { | |
| 55 | + buf, 20, 2000) != 20) { | |
| 54 | 56 | err("USB control message 'out' went wrong."); |
| 55 | 57 | ret = -EIO; |
| 56 | 58 | goto unlock; |
| @@ -61,17 +63,17 @@ int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, · 4 unmodified lines | ||
| 61 | 63 | if (usb_control_msg(d->udev, |
| 62 | 64 | usb_rcvctrlpipe(d->udev,0), |
| 63 | 65 | TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, |
| 64 | − inbuf, 12, 2000) != 12) { | |
| 66 | + buf, 12, 2000) != 12) { | |
| 65 | 67 | err("USB control message 'in' went wrong."); |
| 66 | 68 | ret = -EIO; |
| 67 | 69 | goto unlock; |
| 68 | 70 | } |
| 69 | 71 | |
| 70 | 72 | deb_xfer("in buffer: "); |
| 71 | − debug_dump(inbuf,12,deb_xfer); | |
| 73 | + debug_dump(buf, 12, deb_xfer); | |
| 72 | 74 | |
| 73 | 75 | if (in != NULL && inlen > 0) |
| 74 | − memcpy(in,&inbuf[1],inlen); | |
| 76 | + memcpy(in, &buf[1], inlen); | |
| 75 | 77 | |
| 76 | 78 | unlock: |
| 77 | 79 | mutex_unlock(&d->usb_mutex); |
| @@ -222,8 +224,26 @@ static struct dvb_usb_device_properties vp7045_properties; · 144 unmodified lines | ||
| 222 | 224 | static int vp7045_usb_probe(struct usb_interface *intf, |
| 223 | 225 | const struct usb_device_id *id) |
| 224 | 226 | { |
| 225 | − return dvb_usb_device_init(intf, &vp7045_properties, | |
| 226 | − THIS_MODULE, NULL, adapter_nr); | |
| 227 | + struct dvb_usb_device *d; | |
| 228 | + int ret = dvb_usb_device_init(intf, &vp7045_properties, | |
| 229 | + THIS_MODULE, &d, adapter_nr); | |
| 230 | + if (ret) | |
| 231 | + return ret; | |
| 232 | + | |
| 233 | + d->priv = kmalloc(20, GFP_KERNEL); | |
| 234 | + if (!d->priv) { | |
| 235 | + dvb_usb_device_exit(intf); | |
| 236 | + return -ENOMEM; | |
| 237 | + } | |
| 238 | + | |
| 239 | + return ret; | |
| 240 | +} | |
| 241 | + | |
| 242 | +static void vp7045_usb_disconnect(struct usb_interface *intf) | |
| 243 | +{ | |
| 244 | + struct dvb_usb_device *d = usb_get_intfdata(intf); | |
| 245 | + kfree(d->priv); | |
| 246 | + dvb_usb_device_exit(intf); | |
| 227 | 247 | } |
| 228 | 248 | |
| 229 | 249 | static struct usb_device_id vp7045_usb_table [] = { |
| @@ -238,6 +258,7 @@ MODULE_DEVICE_TABLE(usb, vp7045_usb_table); · 8 unmodified lines | ||
| 238 | 258 | static struct dvb_usb_device_properties vp7045_properties = { |
| 239 | 259 | .usb_ctrl = CYPRESS_FX2, |
| 240 | 260 | .firmware = "dvb-usb-vp7045-01.fw", |
| 261 | + .size_of_priv = sizeof(u8 *), | |
| 241 | 262 | |
| 242 | 263 | .num_adapters = 1, |
| 243 | 264 | .adapter = { |
| @@ -284,7 +305,7 @@ static struct dvb_usb_device_properties vp7045_properties = { · 40 unmodified lines | ||
| 284 | 305 | static struct usb_driver vp7045_usb_driver = { |
| 285 | 306 | .name = "dvb_usb_vp7045", |
| 286 | 307 | .probe = vp7045_usb_probe, |
| 287 | − .disconnect = dvb_usb_device_exit, | |
| 308 | + .disconnect = vp7045_usb_disconnect, | |
| 288 | 309 | .id_table = vp7045_usb_table, |
| 289 | 310 | }; |
| 290 | 311 | |
| @@ -263,18 +263,16 @@ config DVB_S5H1432 · 262 unmodified lines | ||
| 263 | 263 | help |
| 264 | 264 | A DVB-T tuner module. Say Y when you want to support this frontend. |
| 265 | 265 | |
| 266 | −config DVB_DRX397XD | |
| 267 | − tristate "Micronas DRX3975D/DRX3977D based" | |
| 266 | +config DVB_DRXD | |
| 267 | + tristate "Micronas DRXD driver" | |
| 268 | 268 | depends on DVB_CORE && I2C |
| 269 | 269 | default m if DVB_FE_CUSTOMISE |
| 270 | 270 | help |
| 271 | 271 | A DVB-T tuner module. Say Y when you want to support this frontend. |
| 272 | 272 | |
| 273 | − TODO: | |
| 274 | − This driver needs external firmware. Please use the command | |
| 275 | − "<kerneldir>/Documentation/dvb/get_dvb_firmware drx397xD" to | |
| 276 | − download/extract them, and then copy them to /usr/lib/hotplug/firmware | |
| 277 | − or /lib/firmware (depending on configuration of firmware hotplug). | |
| 273 | + Note: this driver was based on vendor driver reference code (released | |
| 274 | + under the GPL) as opposed to the existing drx397xd driver, which | |
| 275 | + was written via reverse engineering. | |
| 278 | 276 | |
| 279 | 277 | config DVB_L64781 |
| 280 | 278 | tristate "LSI L64781" |
| @@ -385,6 +383,13 @@ config DVB_STV0367 · 104 unmodified lines | ||
| 385 | 383 | help |
| 386 | 384 | A DVB-T/C tuner module. Say Y when you want to support this frontend. |
| 387 | 385 | |
| 386 | +config DVB_CXD2820R | |
| 387 | + tristate "Sony CXD2820R" | |
| 388 | + depends on DVB_CORE && I2C | |
| 389 | + default m if DVB_FE_CUSTOMISE | |
| 390 | + help | |
| 391 | + Say Y when you want to support this frontend. | |
| 392 | + | |
| 388 | 393 | comment "DVB-C (cable) frontends" |
| 389 | 394 | depends on DVB_CORE |
| 390 | 395 | |
| @@ -8,6 +8,8 @@ EXTRA_CFLAGS += -Idrivers/media/common/tuners/ · 7 unmodified lines | ||
| 8 | 8 | stb0899-objs = stb0899_drv.o stb0899_algo.o |
| 9 | 9 | stv0900-objs = stv0900_core.o stv0900_sw.o |
| 10 | 10 | au8522-objs = au8522_dig.o au8522_decoder.o |
| 11 | +drxd-objs = drxd_firm.o drxd_hard.o | |
| 12 | +cxd2820r-objs = cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o | |
| 11 | 13 | |
| 12 | 14 | obj-$(CONFIG_DVB_PLL) += dvb-pll.o |
| 13 | 15 | obj-$(CONFIG_DVB_STV0299) += stv0299.o |
| @@ -36,7 +38,7 @@ obj-$(CONFIG_DVB_ZL10036) += zl10036.o · 22 unmodified lines | ||
| 36 | 38 | obj-$(CONFIG_DVB_ZL10039) += zl10039.o |
| 37 | 39 | obj-$(CONFIG_DVB_ZL10353) += zl10353.o |
| 38 | 40 | obj-$(CONFIG_DVB_CX22702) += cx22702.o |
| 39 | −obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o | |
| 41 | +obj-$(CONFIG_DVB_DRXD) += drxd.o | |
| 40 | 42 | obj-$(CONFIG_DVB_TDA10021) += tda10021.o |
| 41 | 43 | obj-$(CONFIG_DVB_TDA10023) += tda10023.o |
| 42 | 44 | obj-$(CONFIG_DVB_STV0297) += stv0297.o |
| @@ -85,3 +87,5 @@ obj-$(CONFIG_DVB_MB86A16) += mb86a16.o · 42 unmodified lines | ||
| 85 | 87 | obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o |
| 86 | 88 | obj-$(CONFIG_DVB_IX2505V) += ix2505v.o |
| 87 | 89 | obj-$(CONFIG_DVB_STV0367) += stv0367.o |
| 90 | +obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o | |
| 91 | + | |
| @@ -0,0 +1,146 @@ | ||
| 1 | +/* | |
| 2 | + * bsbe1-d01a.h - ALPS BSBE1-D01A tuner support | |
| 3 | + * | |
| 4 | + * Copyright (C) 2011 Oliver Endriss <o.endriss@gmx.de> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or | |
| 7 | + * modify it under the terms of the GNU General Public License | |
| 8 | + * as published by the Free Software Foundation; either version 2 | |
| 9 | + * of the License, or (at your option) any later version. | |
| 10 | + * | |
| 11 | + * | |
| 12 | + * This program is distributed in the hope that it will be useful, | |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | + * GNU General Public License for more details. | |
| 16 | + * | |
| 17 | + * | |
| 18 | + * You should have received a copy of the GNU General Public License | |
| 19 | + * along with this program; if not, write to the Free Software | |
| 20 | + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
| 21 | + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | |
| 22 | + * | |
| 23 | + * | |
| 24 | + * the project's page is at http://www.linuxtv.org | |
| 25 | + */ | |
| 26 | + | |
| 27 | +#ifndef BSBE1_D01A_H | |
| 28 | +#define BSBE1_D01A_H | |
| 29 | + | |
| 30 | +#include "stb6000.h" | |
| 31 | +#include "stv0288.h" | |
| 32 | + | |
| 33 | +static u8 stv0288_bsbe1_d01a_inittab[] = { | |
| 34 | + 0x01, 0x15, | |
| 35 | + 0x02, 0x20, | |
| 36 | + 0x09, 0x0, | |
| 37 | + 0x0a, 0x4, | |
| 38 | + 0x0b, 0x0, | |
| 39 | + 0x0c, 0x0, | |
| 40 | + 0x0d, 0x0, | |
| 41 | + 0x0e, 0xd4, | |
| 42 | + 0x0f, 0x30, | |
| 43 | + 0x11, 0x80, | |
| 44 | + 0x12, 0x03, | |
| 45 | + 0x13, 0x48, | |
| 46 | + 0x14, 0x84, | |
| 47 | + 0x15, 0x45, | |
| 48 | + 0x16, 0xb7, | |
| 49 | + 0x17, 0x9c, | |
| 50 | + 0x18, 0x0, | |
| 51 | + 0x19, 0xa6, | |
| 52 | + 0x1a, 0x88, | |
| 53 | + 0x1b, 0x8f, | |
| 54 | + 0x1c, 0xf0, | |
| 55 | + 0x20, 0x0b, | |
| 56 | + 0x21, 0x54, | |
| 57 | + 0x22, 0x0, | |
| 58 | + 0x23, 0x0, | |
| 59 | + 0x2b, 0xff, | |
| 60 | + 0x2c, 0xf7, | |
| 61 | + 0x30, 0x0, | |
| 62 | + 0x31, 0x1e, | |
| 63 | + 0x32, 0x14, | |
| 64 | + 0x33, 0x0f, | |
| 65 | + 0x34, 0x09, | |
| 66 | + 0x35, 0x0c, | |
| 67 | + 0x36, 0x05, | |
| 68 | + 0x37, 0x2f, | |
| 69 | + 0x38, 0x16, | |
| 70 | + 0x39, 0xbd, | |
| 71 | + 0x3a, 0x03, | |
| 72 | + 0x3b, 0x13, | |
| 73 | + 0x3c, 0x11, | |
| 74 | + 0x3d, 0x30, | |
| 75 | + 0x40, 0x63, | |
| 76 | + 0x41, 0x04, | |
| 77 | + 0x42, 0x60, | |
| 78 | + 0x43, 0x00, | |
| 79 | + 0x44, 0x00, | |
| 80 | + 0x45, 0x00, | |
| 81 | + 0x46, 0x00, | |
| 82 | + 0x47, 0x00, | |
| 83 | + 0x4a, 0x00, | |
| 84 | + 0x50, 0x10, | |
| 85 | + 0x51, 0x36, | |
| 86 | + 0x52, 0x09, | |
| 87 | + 0x53, 0x94, | |
| 88 | + 0x54, 0x62, | |
| 89 | + 0x55, 0x29, | |
| 90 | + 0x56, 0x64, | |
| 91 | + 0x57, 0x2b, | |
| 92 | + 0x58, 0x54, | |
| 93 | + 0x59, 0x86, | |
| 94 | + 0x5a, 0x0, | |
| 95 | + 0x5b, 0x9b, | |
| 96 | + 0x5c, 0x08, | |
| 97 | + 0x5d, 0x7f, | |
| 98 | + 0x5e, 0x0, | |
| 99 | + 0x5f, 0xff, | |
| 100 | + 0x70, 0x0, | |
| 101 | + 0x71, 0x0, | |
| 102 | + 0x72, 0x0, | |
| 103 | + 0x74, 0x0, | |
| 104 | + 0x75, 0x0, | |
| 105 | + 0x76, 0x0, | |
| 106 | + 0x81, 0x0, | |
| 107 | + 0x82, 0x3f, | |
| 108 | + 0x83, 0x3f, | |
| 109 | + 0x84, 0x0, | |
| 110 | + 0x85, 0x0, | |
| 111 | + 0x88, 0x0, | |
| 112 | + 0x89, 0x0, | |
| 113 | + 0x8a, 0x0, | |
| 114 | + 0x8b, 0x0, | |
| 115 | + 0x8c, 0x0, | |
| 116 | + 0x90, 0x0, | |
| 117 | + 0x91, 0x0, | |
| 118 | + 0x92, 0x0, | |
| 119 | + 0x93, 0x0, | |
| 120 | + 0x94, 0x1c, | |
| 121 | + 0x97, 0x0, | |
| 122 | + 0xa0, 0x48, | |
| 123 | + 0xa1, 0x0, | |
| 124 | + 0xb0, 0xb8, | |
| 125 | + 0xb1, 0x3a, | |
| 126 | + 0xb2, 0x10, | |
| 127 | + 0xb3, 0x82, | |
| 128 | + 0xb4, 0x80, | |
| 129 | + 0xb5, 0x82, | |
| 130 | + 0xb6, 0x82, | |
| 131 | + 0xb7, 0x82, | |
| 132 | + 0xb8, 0x20, | |
| 133 | + 0xb9, 0x0, | |
| 134 | + 0xf0, 0x0, | |
| 135 | + 0xf1, 0x0, | |
| 136 | + 0xf2, 0xc0, | |
| 137 | + 0xff, 0xff, | |
| 138 | +}; | |
| 139 | + | |
| 140 | +static struct stv0288_config stv0288_bsbe1_d01a_config = { | |
| 141 | + .demod_address = 0x68, | |
| 142 | + .min_delay_ms = 100, | |
| 143 | + .inittab = stv0288_bsbe1_d01a_inittab, | |
| 144 | +}; | |
| 145 | + | |
| 146 | +#endif | |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | static u8 alps_bsru6_inittab[] = { |
| 29 | 29 | 0x01, 0x15, |
| 30 | − 0x02, 0x00, | |
| 30 | + 0x02, 0x30, | |
| 31 | 31 | 0x03, 0x00, |
| 32 | 32 | 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ |
| 33 | 33 | 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ |
| @@ -137,7 +137,7 @@ MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, "\ · 136 unmodified lines | ||
| 137 | 137 | /* SNR measurements */ |
| 138 | 138 | static int esno_snr; |
| 139 | 139 | module_param(esno_snr, int, 0644); |
| 140 | −MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, "\ | |
| 140 | +MODULE_PARM_DESC(esno_snr, "SNR return units, 0=PERCENTAGE 0-100, "\ | |
| 141 | 141 | "1=ESNO(db * 10) (default:0)"); |
| 142 | 142 | |
| 143 | 143 | enum cmds { |
| @@ -566,7 +566,7 @@ static int cx24116_load_firmware(struct dvb_frontend *fe, · 422 unmodified lines | ||
| 566 | 566 | { |
| 567 | 567 | struct cx24116_state *state = fe->demodulator_priv; |
| 568 | 568 | struct cx24116_cmd cmd; |
| 569 | − int i, ret; | |
| 569 | + int i, ret, len, max, remaining; | |
| 570 | 570 | unsigned char vers[4]; |
| 571 | 571 | |
| 572 | 572 | dprintk("%s\n", __func__); |
| @@ -603,8 +603,21 @@ static int cx24116_load_firmware(struct dvb_frontend *fe, · 30 unmodified lines | ||
| 603 | 603 | cx24116_writereg(state, 0xF5, 0x00); |
| 604 | 604 | cx24116_writereg(state, 0xF6, 0x00); |
| 605 | 605 | |
| 606 | − /* write the entire firmware as one transaction */ | |
| 607 | − cx24116_writeregN(state, 0xF7, fw->data, fw->size); | |
| 606 | + /* Split firmware to the max I2C write len and write. | |
| 607 | + * Writes whole firmware as one write when i2c_wr_max is set to 0. */ | |
| 608 | + if (state->config->i2c_wr_max) | |
| 609 | + max = state->config->i2c_wr_max; | |
| 610 | + else | |
| 611 | + max = INT_MAX; /* enough for 32k firmware */ | |
| 612 | + | |
| 613 | + for (remaining = fw->size; remaining > 0; remaining -= max - 1) { | |
| 614 | + len = remaining; | |
| 615 | + if (len > max - 1) | |
| 616 | + len = max - 1; | |
| 617 | + | |
| 618 | + cx24116_writeregN(state, 0xF7, &fw->data[fw->size - remaining], | |
| 619 | + len); | |
| 620 | + } | |
| 608 | 621 | |
| 609 | 622 | cx24116_writereg(state, 0xF4, 0x10); |
| 610 | 623 | cx24116_writereg(state, 0xF0, 0x00); |
| @@ -35,6 +35,9 @@ struct cx24116_config { · 34 unmodified lines | ||
| 35 | 35 | |
| 36 | 36 | /* Need to set MPEG parameters */ |
| 37 | 37 | u8 mpg_clk_pos_pol:0x02; |
| 38 | + | |
| 39 | + /* max bytes I2C provider can write at once */ | |
| 40 | + u16 i2c_wr_max; | |
| 38 | 41 | }; |
| 39 | 42 | |
| 40 | 43 | #if defined(CONFIG_DVB_CX24116) || \ |
| @@ -0,0 +1,118 @@ | ||
| 1 | +/* | |
| 2 | + * Sony CXD2820R demodulator driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License along | |
| 17 | + * with this program; if not, write to the Free Software Foundation, Inc., | |
| 18 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + */ | |
| 20 | + | |
| 21 | + | |
| 22 | +#ifndef CXD2820R_H | |
| 23 | +#define CXD2820R_H | |
| 24 | + | |
| 25 | +#include <linux/dvb/frontend.h> | |
| 26 | + | |
| 27 | +#define CXD2820R_GPIO_D (0 << 0) /* disable */ | |
| 28 | +#define CXD2820R_GPIO_E (1 << 0) /* enable */ | |
| 29 | +#define CXD2820R_GPIO_O (0 << 1) /* output */ | |
| 30 | +#define CXD2820R_GPIO_I (1 << 1) /* input */ | |
| 31 | +#define CXD2820R_GPIO_L (0 << 2) /* output low */ | |
| 32 | +#define CXD2820R_GPIO_H (1 << 2) /* output high */ | |
| 33 | + | |
| 34 | +#define CXD2820R_TS_SERIAL 0x08 | |
| 35 | +#define CXD2820R_TS_SERIAL_MSB 0x28 | |
| 36 | +#define CXD2820R_TS_PARALLEL 0x30 | |
| 37 | +#define CXD2820R_TS_PARALLEL_MSB 0x70 | |
| 38 | + | |
| 39 | +struct cxd2820r_config { | |
| 40 | + /* Demodulator I2C address. | |
| 41 | + * Driver determines DVB-C slave I2C address automatically from master | |
| 42 | + * address. | |
| 43 | + * Default: none, must set | |
| 44 | + * Values: 0x6c, 0x6d | |
| 45 | + */ | |
| 46 | + u8 i2c_address; | |
| 47 | + | |
| 48 | + /* TS output mode. | |
| 49 | + * Default: none, must set. | |
| 50 | + * Values: | |
| 51 | + */ | |
| 52 | + u8 ts_mode; | |
| 53 | + | |
| 54 | + /* IF AGC polarity. | |
| 55 | + * Default: 0 | |
| 56 | + * Values: 0, 1 | |
| 57 | + */ | |
| 58 | + int if_agc_polarity:1; | |
| 59 | + | |
| 60 | + /* Spectrum inversion. | |
| 61 | + * Default: 0 | |
| 62 | + * Values: 0, 1 | |
| 63 | + */ | |
| 64 | + int spec_inv:1; | |
| 65 | + | |
| 66 | + /* IFs for all used modes. | |
| 67 | + * Default: none, must set | |
| 68 | + * Values: <kHz> | |
| 69 | + */ | |
| 70 | + u16 if_dvbt_6; | |
| 71 | + u16 if_dvbt_7; | |
| 72 | + u16 if_dvbt_8; | |
| 73 | + u16 if_dvbt2_5; | |
| 74 | + u16 if_dvbt2_6; | |
| 75 | + u16 if_dvbt2_7; | |
| 76 | + u16 if_dvbt2_8; | |
| 77 | + u16 if_dvbc; | |
| 78 | + | |
| 79 | + /* GPIOs for all used modes. | |
| 80 | + * Default: none, disabled | |
| 81 | + * Values: <see above> | |
| 82 | + */ | |
| 83 | + u8 gpio_dvbt[3]; | |
| 84 | + u8 gpio_dvbt2[3]; | |
| 85 | + u8 gpio_dvbc[3]; | |
| 86 | +}; | |
| 87 | + | |
| 88 | + | |
| 89 | +#if defined(CONFIG_DVB_CXD2820R) || \ | |
| 90 | + (defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE)) | |
| 91 | +extern struct dvb_frontend *cxd2820r_attach( | |
| 92 | + const struct cxd2820r_config *config, | |
| 93 | + struct i2c_adapter *i2c, | |
| 94 | + struct dvb_frontend *fe | |
| 95 | +); | |
| 96 | +extern struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter( | |
| 97 | + struct dvb_frontend *fe | |
| 98 | +); | |
| 99 | +#else | |
| 100 | +static inline struct dvb_frontend *cxd2820r_attach( | |
| 101 | + const struct cxd2820r_config *config, | |
| 102 | + struct i2c_adapter *i2c, | |
| 103 | + struct dvb_frontend *fe | |
| 104 | +) | |
| 105 | +{ | |
| 106 | + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | |
| 107 | + return NULL; | |
| 108 | +} | |
| 109 | +static inline struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter( | |
| 110 | + struct dvb_frontend *fe | |
| 111 | +) | |
| 112 | +{ | |
| 113 | + return NULL; | |
| 114 | +} | |
| 115 | + | |
| 116 | +#endif | |
| 117 | + | |
| 118 | +#endif /* CXD2820R_H */ | |
| @@ -0,0 +1,338 @@ | ||
| 1 | +/* | |
| 2 | + * Sony CXD2820R demodulator driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License along | |
| 17 | + * with this program; if not, write to the Free Software Foundation, Inc., | |
| 18 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + */ | |
| 20 | + | |
| 21 | + | |
| 22 | +#include "cxd2820r_priv.h" | |
| 23 | + | |
| 24 | +int cxd2820r_set_frontend_c(struct dvb_frontend *fe, | |
| 25 | + struct dvb_frontend_parameters *params) | |
| 26 | +{ | |
| 27 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 28 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 29 | + int ret, i; | |
| 30 | + u8 buf[2]; | |
| 31 | + u16 if_ctl; | |
| 32 | + u64 num; | |
| 33 | + struct reg_val_mask tab[] = { | |
| 34 | + { 0x00080, 0x01, 0xff }, | |
| 35 | + { 0x00081, 0x05, 0xff }, | |
| 36 | + { 0x00085, 0x07, 0xff }, | |
| 37 | + { 0x00088, 0x01, 0xff }, | |
| 38 | + | |
| 39 | + { 0x00082, 0x20, 0x60 }, | |
| 40 | + { 0x1016a, 0x48, 0xff }, | |
| 41 | + { 0x100a5, 0x00, 0x01 }, | |
| 42 | + { 0x10020, 0x06, 0x07 }, | |
| 43 | + { 0x10059, 0x50, 0xff }, | |
| 44 | + { 0x10087, 0x0c, 0x3c }, | |
| 45 | + { 0x1008b, 0x07, 0xff }, | |
| 46 | + { 0x1001f, priv->cfg.if_agc_polarity << 7, 0x80 }, | |
| 47 | + { 0x10070, priv->cfg.ts_mode, 0xff }, | |
| 48 | + }; | |
| 49 | + | |
| 50 | + dbg("%s: RF=%d SR=%d", __func__, c->frequency, c->symbol_rate); | |
| 51 | + | |
| 52 | + /* update GPIOs */ | |
| 53 | + ret = cxd2820r_gpio(fe); | |
| 54 | + if (ret) | |
| 55 | + goto error; | |
| 56 | + | |
| 57 | + /* program tuner */ | |
| 58 | + if (fe->ops.tuner_ops.set_params) | |
| 59 | + fe->ops.tuner_ops.set_params(fe, params); | |
| 60 | + | |
| 61 | + if (priv->delivery_system != SYS_DVBC_ANNEX_AC) { | |
| 62 | + for (i = 0; i < ARRAY_SIZE(tab); i++) { | |
| 63 | + ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, | |
| 64 | + tab[i].val, tab[i].mask); | |
| 65 | + if (ret) | |
| 66 | + goto error; | |
| 67 | + } | |
| 68 | + } | |
| 69 | + | |
| 70 | + priv->delivery_system = SYS_DVBC_ANNEX_AC; | |
| 71 | + priv->ber_running = 0; /* tune stops BER counter */ | |
| 72 | + | |
| 73 | + num = priv->cfg.if_dvbc; | |
| 74 | + num *= 0x4000; | |
| 75 | + if_ctl = cxd2820r_div_u64_round_closest(num, 41000); | |
| 76 | + buf[0] = (if_ctl >> 8) & 0x3f; | |
| 77 | + buf[1] = (if_ctl >> 0) & 0xff; | |
| 78 | + | |
| 79 | + ret = cxd2820r_wr_regs(priv, 0x10042, buf, 2); | |
| 80 | + if (ret) | |
| 81 | + goto error; | |
| 82 | + | |
| 83 | + ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08); | |
| 84 | + if (ret) | |
| 85 | + goto error; | |
| 86 | + | |
| 87 | + ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01); | |
| 88 | + if (ret) | |
| 89 | + goto error; | |
| 90 | + | |
| 91 | + return ret; | |
| 92 | +error: | |
| 93 | + dbg("%s: failed:%d", __func__, ret); | |
| 94 | + return ret; | |
| 95 | +} | |
| 96 | + | |
| 97 | +int cxd2820r_get_frontend_c(struct dvb_frontend *fe, | |
| 98 | + struct dvb_frontend_parameters *p) | |
| 99 | +{ | |
| 100 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 101 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 102 | + int ret; | |
| 103 | + u8 buf[2]; | |
| 104 | + | |
| 105 | + ret = cxd2820r_rd_regs(priv, 0x1001a, buf, 2); | |
| 106 | + if (ret) | |
| 107 | + goto error; | |
| 108 | + | |
| 109 | + c->symbol_rate = 2500 * ((buf[0] & 0x0f) << 8 | buf[1]); | |
| 110 | + | |
| 111 | + ret = cxd2820r_rd_reg(priv, 0x10019, &buf[0]); | |
| 112 | + if (ret) | |
| 113 | + goto error; | |
| 114 | + | |
| 115 | + switch ((buf[0] >> 0) & 0x03) { | |
| 116 | + case 0: | |
| 117 | + c->modulation = QAM_16; | |
| 118 | + break; | |
| 119 | + case 1: | |
| 120 | + c->modulation = QAM_32; | |
| 121 | + break; | |
| 122 | + case 2: | |
| 123 | + c->modulation = QAM_64; | |
| 124 | + break; | |
| 125 | + case 3: | |
| 126 | + c->modulation = QAM_128; | |
| 127 | + break; | |
| 128 | + case 4: | |
| 129 | + c->modulation = QAM_256; | |
| 130 | + break; | |
| 131 | + } | |
| 132 | + | |
| 133 | + switch ((buf[0] >> 7) & 0x01) { | |
| 134 | + case 0: | |
| 135 | + c->inversion = INVERSION_OFF; | |
| 136 | + break; | |
| 137 | + case 1: | |
| 138 | + c->inversion = INVERSION_ON; | |
| 139 | + break; | |
| 140 | + } | |
| 141 | + | |
| 142 | + return ret; | |
| 143 | +error: | |
| 144 | + dbg("%s: failed:%d", __func__, ret); | |
| 145 | + return ret; | |
| 146 | +} | |
| 147 | + | |
| 148 | +int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber) | |
| 149 | +{ | |
| 150 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 151 | + int ret; | |
| 152 | + u8 buf[3], start_ber = 0; | |
| 153 | + *ber = 0; | |
| 154 | + | |
| 155 | + if (priv->ber_running) { | |
| 156 | + ret = cxd2820r_rd_regs(priv, 0x10076, buf, sizeof(buf)); | |
| 157 | + if (ret) | |
| 158 | + goto error; | |
| 159 | + | |
| 160 | + if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) { | |
| 161 | + *ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0]; | |
| 162 | + start_ber = 1; | |
| 163 | + } | |
| 164 | + } else { | |
| 165 | + priv->ber_running = 1; | |
| 166 | + start_ber = 1; | |
| 167 | + } | |
| 168 | + | |
| 169 | + if (start_ber) { | |
| 170 | + /* (re)start BER */ | |
| 171 | + ret = cxd2820r_wr_reg(priv, 0x10079, 0x01); | |
| 172 | + if (ret) | |
| 173 | + goto error; | |
| 174 | + } | |
| 175 | + | |
| 176 | + return ret; | |
| 177 | +error: | |
| 178 | + dbg("%s: failed:%d", __func__, ret); | |
| 179 | + return ret; | |
| 180 | +} | |
| 181 | + | |
| 182 | +int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe, | |
| 183 | + u16 *strength) | |
| 184 | +{ | |
| 185 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 186 | + int ret; | |
| 187 | + u8 buf[2]; | |
| 188 | + u16 tmp; | |
| 189 | + | |
| 190 | + ret = cxd2820r_rd_regs(priv, 0x10049, buf, sizeof(buf)); | |
| 191 | + if (ret) | |
| 192 | + goto error; | |
| 193 | + | |
| 194 | + tmp = (buf[0] & 0x03) << 8 | buf[1]; | |
| 195 | + tmp = (~tmp & 0x03ff); | |
| 196 | + | |
| 197 | + if (tmp == 512) | |
| 198 | + /* ~no signal */ | |
| 199 | + tmp = 0; | |
| 200 | + else if (tmp > 350) | |
| 201 | + tmp = 350; | |
| 202 | + | |
| 203 | + /* scale value to 0x0000-0xffff */ | |
| 204 | + *strength = tmp * 0xffff / (350-0); | |
| 205 | + | |
| 206 | + return ret; | |
| 207 | +error: | |
| 208 | + dbg("%s: failed:%d", __func__, ret); | |
| 209 | + return ret; | |
| 210 | +} | |
| 211 | + | |
| 212 | +int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr) | |
| 213 | +{ | |
| 214 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 215 | + int ret; | |
| 216 | + u8 tmp; | |
| 217 | + unsigned int A, B; | |
| 218 | + /* report SNR in dB * 10 */ | |
| 219 | + | |
| 220 | + ret = cxd2820r_rd_reg(priv, 0x10019, &tmp); | |
| 221 | + if (ret) | |
| 222 | + goto error; | |
| 223 | + | |
| 224 | + if (((tmp >> 0) & 0x03) % 2) { | |
| 225 | + A = 875; | |
| 226 | + B = 650; | |
| 227 | + } else { | |
| 228 | + A = 950; | |
| 229 | + B = 760; | |
| 230 | + } | |
| 231 | + | |
| 232 | + ret = cxd2820r_rd_reg(priv, 0x1004d, &tmp); | |
| 233 | + if (ret) | |
| 234 | + goto error; | |
| 235 | + | |
| 236 | + #define CXD2820R_LOG2_E_24 24204406 /* log2(e) << 24 */ | |
| 237 | + if (tmp) | |
| 238 | + *snr = A * (intlog2(B / tmp) >> 5) / (CXD2820R_LOG2_E_24 >> 5) | |
| 239 | + / 10; | |
| 240 | + else | |
| 241 | + *snr = 0; | |
| 242 | + | |
| 243 | + return ret; | |
| 244 | +error: | |
| 245 | + dbg("%s: failed:%d", __func__, ret); | |
| 246 | + return ret; | |
| 247 | +} | |
| 248 | + | |
| 249 | +int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks) | |
| 250 | +{ | |
| 251 | + *ucblocks = 0; | |
| 252 | + /* no way to read ? */ | |
| 253 | + return 0; | |
| 254 | +} | |
| 255 | + | |
| 256 | +int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status) | |
| 257 | +{ | |
| 258 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 259 | + int ret; | |
| 260 | + u8 buf[2]; | |
| 261 | + *status = 0; | |
| 262 | + | |
| 263 | + ret = cxd2820r_rd_regs(priv, 0x10088, buf, sizeof(buf)); | |
| 264 | + if (ret) | |
| 265 | + goto error; | |
| 266 | + | |
| 267 | + if (((buf[0] >> 0) & 0x01) == 1) { | |
| 268 | + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | | |
| 269 | + FE_HAS_VITERBI | FE_HAS_SYNC; | |
| 270 | + | |
| 271 | + if (((buf[1] >> 3) & 0x01) == 1) { | |
| 272 | + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | | |
| 273 | + FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | |
| 274 | + } | |
| 275 | + } | |
| 276 | + | |
| 277 | + dbg("%s: lock=%02x %02x", __func__, buf[0], buf[1]); | |
| 278 | + | |
| 279 | + return ret; | |
| 280 | +error: | |
| 281 | + dbg("%s: failed:%d", __func__, ret); | |
| 282 | + return ret; | |
| 283 | +} | |
| 284 | + | |
| 285 | +int cxd2820r_init_c(struct dvb_frontend *fe) | |
| 286 | +{ | |
| 287 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 288 | + int ret; | |
| 289 | + | |
| 290 | + ret = cxd2820r_wr_reg(priv, 0x00085, 0x07); | |
| 291 | + if (ret) | |
| 292 | + goto error; | |
| 293 | + | |
| 294 | + return ret; | |
| 295 | +error: | |
| 296 | + dbg("%s: failed:%d", __func__, ret); | |
| 297 | + return ret; | |
| 298 | +} | |
| 299 | + | |
| 300 | +int cxd2820r_sleep_c(struct dvb_frontend *fe) | |
| 301 | +{ | |
| 302 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 303 | + int ret, i; | |
| 304 | + struct reg_val_mask tab[] = { | |
| 305 | + { 0x000ff, 0x1f, 0xff }, | |
| 306 | + { 0x00085, 0x00, 0xff }, | |
| 307 | + { 0x00088, 0x01, 0xff }, | |
| 308 | + { 0x00081, 0x00, 0xff }, | |
| 309 | + { 0x00080, 0x00, 0xff }, | |
| 310 | + }; | |
| 311 | + | |
| 312 | + dbg("%s", __func__); | |
| 313 | + | |
| 314 | + priv->delivery_system = SYS_UNDEFINED; | |
| 315 | + | |
| 316 | + for (i = 0; i < ARRAY_SIZE(tab); i++) { | |
| 317 | + ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val, | |
| 318 | + tab[i].mask); | |
| 319 | + if (ret) | |
| 320 | + goto error; | |
| 321 | + } | |
| 322 | + | |
| 323 | + return ret; | |
| 324 | +error: | |
| 325 | + dbg("%s: failed:%d", __func__, ret); | |
| 326 | + return ret; | |
| 327 | +} | |
| 328 | + | |
| 329 | +int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe, | |
| 330 | + struct dvb_frontend_tune_settings *s) | |
| 331 | +{ | |
| 332 | + s->min_delay_ms = 500; | |
| 333 | + s->step_size = 0; /* no zigzag */ | |
| 334 | + s->max_drift = 0; | |
| 335 | + | |
| 336 | + return 0; | |
| 337 | +} | |
| 338 | + | |
| @@ -0,0 +1,915 @@ | ||
| 1 | +/* | |
| 2 | + * Sony CXD2820R demodulator driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License along | |
| 17 | + * with this program; if not, write to the Free Software Foundation, Inc., | |
| 18 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + */ | |
| 20 | + | |
| 21 | + | |
| 22 | +#include "cxd2820r_priv.h" | |
| 23 | + | |
| 24 | +int cxd2820r_debug; | |
| 25 | +module_param_named(debug, cxd2820r_debug, int, 0644); | |
| 26 | +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | |
| 27 | + | |
| 28 | +/* write multiple registers */ | |
| 29 | +static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg, | |
| 30 | + u8 *val, int len) | |
| 31 | +{ | |
| 32 | + int ret; | |
| 33 | + u8 buf[len+1]; | |
| 34 | + struct i2c_msg msg[1] = { | |
| 35 | + { | |
| 36 | + .addr = i2c, | |
| 37 | + .flags = 0, | |
| 38 | + .len = sizeof(buf), | |
| 39 | + .buf = buf, | |
| 40 | + } | |
| 41 | + }; | |
| 42 | + | |
| 43 | + buf[0] = reg; | |
| 44 | + memcpy(&buf[1], val, len); | |
| 45 | + | |
| 46 | + ret = i2c_transfer(priv->i2c, msg, 1); | |
| 47 | + if (ret == 1) { | |
| 48 | + ret = 0; | |
| 49 | + } else { | |
| 50 | + warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len); | |
| 51 | + ret = -EREMOTEIO; | |
| 52 | + } | |
| 53 | + return ret; | |
| 54 | +} | |
| 55 | + | |
| 56 | +/* read multiple registers */ | |
| 57 | +static int cxd2820r_rd_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg, | |
| 58 | + u8 *val, int len) | |
| 59 | +{ | |
| 60 | + int ret; | |
| 61 | + u8 buf[len]; | |
| 62 | + struct i2c_msg msg[2] = { | |
| 63 | + { | |
| 64 | + .addr = i2c, | |
| 65 | + .flags = 0, | |
| 66 | + .len = 1, | |
| 67 | + .buf = ®, | |
| 68 | + }, { | |
| 69 | + .addr = i2c, | |
| 70 | + .flags = I2C_M_RD, | |
| 71 | + .len = sizeof(buf), | |
| 72 | + .buf = buf, | |
| 73 | + } | |
| 74 | + }; | |
| 75 | + | |
| 76 | + ret = i2c_transfer(priv->i2c, msg, 2); | |
| 77 | + if (ret == 2) { | |
| 78 | + memcpy(val, buf, len); | |
| 79 | + ret = 0; | |
| 80 | + } else { | |
| 81 | + warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len); | |
| 82 | + ret = -EREMOTEIO; | |
| 83 | + } | |
| 84 | + | |
| 85 | + return ret; | |
| 86 | +} | |
| 87 | + | |
| 88 | +/* write multiple registers */ | |
| 89 | +int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val, | |
| 90 | + int len) | |
| 91 | +{ | |
| 92 | + int ret; | |
| 93 | + u8 i2c_addr; | |
| 94 | + u8 reg = (reginfo >> 0) & 0xff; | |
| 95 | + u8 bank = (reginfo >> 8) & 0xff; | |
| 96 | + u8 i2c = (reginfo >> 16) & 0x01; | |
| 97 | + | |
| 98 | + /* select I2C */ | |
| 99 | + if (i2c) | |
| 100 | + i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */ | |
| 101 | + else | |
| 102 | + i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */ | |
| 103 | + | |
| 104 | + /* switch bank if needed */ | |
| 105 | + if (bank != priv->bank[i2c]) { | |
| 106 | + ret = cxd2820r_wr_regs_i2c(priv, i2c_addr, 0x00, &bank, 1); | |
| 107 | + if (ret) | |
| 108 | + return ret; | |
| 109 | + priv->bank[i2c] = bank; | |
| 110 | + } | |
| 111 | + return cxd2820r_wr_regs_i2c(priv, i2c_addr, reg, val, len); | |
| 112 | +} | |
| 113 | + | |
| 114 | +/* read multiple registers */ | |
| 115 | +int cxd2820r_rd_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val, | |
| 116 | + int len) | |
| 117 | +{ | |
| 118 | + int ret; | |
| 119 | + u8 i2c_addr; | |
| 120 | + u8 reg = (reginfo >> 0) & 0xff; | |
| 121 | + u8 bank = (reginfo >> 8) & 0xff; | |
| 122 | + u8 i2c = (reginfo >> 16) & 0x01; | |
| 123 | + | |
| 124 | + /* select I2C */ | |
| 125 | + if (i2c) | |
| 126 | + i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */ | |
| 127 | + else | |
| 128 | + i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */ | |
| 129 | + | |
| 130 | + /* switch bank if needed */ | |
| 131 | + if (bank != priv->bank[i2c]) { | |
| 132 | + ret = cxd2820r_wr_regs_i2c(priv, i2c_addr, 0x00, &bank, 1); | |
| 133 | + if (ret) | |
| 134 | + return ret; | |
| 135 | + priv->bank[i2c] = bank; | |
| 136 | + } | |
| 137 | + return cxd2820r_rd_regs_i2c(priv, i2c_addr, reg, val, len); | |
| 138 | +} | |
| 139 | + | |
| 140 | +/* write single register */ | |
| 141 | +int cxd2820r_wr_reg(struct cxd2820r_priv *priv, u32 reg, u8 val) | |
| 142 | +{ | |
| 143 | + return cxd2820r_wr_regs(priv, reg, &val, 1); | |
| 144 | +} | |
| 145 | + | |
| 146 | +/* read single register */ | |
| 147 | +int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val) | |
| 148 | +{ | |
| 149 | + return cxd2820r_rd_regs(priv, reg, val, 1); | |
| 150 | +} | |
| 151 | + | |
| 152 | +/* write single register with mask */ | |
| 153 | +int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val, | |
| 154 | + u8 mask) | |
| 155 | +{ | |
| 156 | + int ret; | |
| 157 | + u8 tmp; | |
| 158 | + | |
| 159 | + /* no need for read if whole reg is written */ | |
| 160 | + if (mask != 0xff) { | |
| 161 | + ret = cxd2820r_rd_reg(priv, reg, &tmp); | |
| 162 | + if (ret) | |
| 163 | + return ret; | |
| 164 | + | |
| 165 | + val &= mask; | |
| 166 | + tmp &= ~mask; | |
| 167 | + val |= tmp; | |
| 168 | + } | |
| 169 | + | |
| 170 | + return cxd2820r_wr_reg(priv, reg, val); | |
| 171 | +} | |
| 172 | + | |
| 173 | +int cxd2820r_gpio(struct dvb_frontend *fe) | |
| 174 | +{ | |
| 175 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 176 | + int ret, i; | |
| 177 | + u8 *gpio, tmp0, tmp1; | |
| 178 | + dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | |
| 179 | + | |
| 180 | + switch (fe->dtv_property_cache.delivery_system) { | |
| 181 | + case SYS_DVBT: | |
| 182 | + gpio = priv->cfg.gpio_dvbt; | |
| 183 | + break; | |
| 184 | + case SYS_DVBT2: | |
| 185 | + gpio = priv->cfg.gpio_dvbt2; | |
| 186 | + break; | |
| 187 | + case SYS_DVBC_ANNEX_AC: | |
| 188 | + gpio = priv->cfg.gpio_dvbc; | |
| 189 | + break; | |
| 190 | + default: | |
| 191 | + ret = -EINVAL; | |
| 192 | + goto error; | |
| 193 | + } | |
| 194 | + | |
| 195 | + /* update GPIOs only when needed */ | |
| 196 | + if (!memcmp(gpio, priv->gpio, sizeof(priv->gpio))) | |
| 197 | + return 0; | |
| 198 | + | |
| 199 | + tmp0 = 0x00; | |
| 200 | + tmp1 = 0x00; | |
| 201 | + for (i = 0; i < sizeof(priv->gpio); i++) { | |
| 202 | + /* enable / disable */ | |
| 203 | + if (gpio[i] & CXD2820R_GPIO_E) | |
| 204 | + tmp0 |= (2 << 6) >> (2 * i); | |
| 205 | + else | |
| 206 | + tmp0 |= (1 << 6) >> (2 * i); | |
| 207 | + | |
| 208 | + /* input / output */ | |
| 209 | + if (gpio[i] & CXD2820R_GPIO_I) | |
| 210 | + tmp1 |= (1 << (3 + i)); | |
| 211 | + else | |
| 212 | + tmp1 |= (0 << (3 + i)); | |
| 213 | + | |
| 214 | + /* high / low */ | |
| 215 | + if (gpio[i] & CXD2820R_GPIO_H) | |
| 216 | + tmp1 |= (1 << (0 + i)); | |
| 217 | + else | |
| 218 | + tmp1 |= (0 << (0 + i)); | |
| 219 | + | |
| 220 | + dbg("%s: GPIO i=%d %02x %02x", __func__, i, tmp0, tmp1); | |
| 221 | + } | |
| 222 | + | |
| 223 | + dbg("%s: wr gpio=%02x %02x", __func__, tmp0, tmp1); | |
| 224 | + | |
| 225 | + /* write bits [7:2] */ | |
| 226 | + ret = cxd2820r_wr_reg_mask(priv, 0x00089, tmp0, 0xfc); | |
| 227 | + if (ret) | |
| 228 | + goto error; | |
| 229 | + | |
| 230 | + /* write bits [5:0] */ | |
| 231 | + ret = cxd2820r_wr_reg_mask(priv, 0x0008e, tmp1, 0x3f); | |
| 232 | + if (ret) | |
| 233 | + goto error; | |
| 234 | + | |
| 235 | + memcpy(priv->gpio, gpio, sizeof(priv->gpio)); | |
| 236 | + | |
| 237 | + return ret; | |
| 238 | +error: | |
| 239 | + dbg("%s: failed:%d", __func__, ret); | |
| 240 | + return ret; | |
| 241 | +} | |
| 242 | + | |
| 243 | +/* lock FE */ | |
| 244 | +static int cxd2820r_lock(struct cxd2820r_priv *priv, int active_fe) | |
| 245 | +{ | |
| 246 | + int ret = 0; | |
| 247 | + dbg("%s: active_fe=%d", __func__, active_fe); | |
| 248 | + | |
| 249 | + mutex_lock(&priv->fe_lock); | |
| 250 | + | |
| 251 | + /* -1=NONE, 0=DVB-T/T2, 1=DVB-C */ | |
| 252 | + if (priv->active_fe == active_fe) | |
| 253 | + ; | |
| 254 | + else if (priv->active_fe == -1) | |
| 255 | + priv->active_fe = active_fe; | |
| 256 | + else | |
| 257 | + ret = -EBUSY; | |
| 258 | + | |
| 259 | + mutex_unlock(&priv->fe_lock); | |
| 260 | + | |
| 261 | + return ret; | |
| 262 | +} | |
| 263 | + | |
| 264 | +/* unlock FE */ | |
| 265 | +static void cxd2820r_unlock(struct cxd2820r_priv *priv, int active_fe) | |
| 266 | +{ | |
| 267 | + dbg("%s: active_fe=%d", __func__, active_fe); | |
| 268 | + | |
| 269 | + mutex_lock(&priv->fe_lock); | |
| 270 | + | |
| 271 | + /* -1=NONE, 0=DVB-T/T2, 1=DVB-C */ | |
| 272 | + if (priv->active_fe == active_fe) | |
| 273 | + priv->active_fe = -1; | |
| 274 | + | |
| 275 | + mutex_unlock(&priv->fe_lock); | |
| 276 | + | |
| 277 | + return; | |
| 278 | +} | |
| 279 | + | |
| 280 | +/* 64 bit div with round closest, like DIV_ROUND_CLOSEST but 64 bit */ | |
| 281 | +u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor) | |
| 282 | +{ | |
| 283 | + return div_u64(dividend + (divisor / 2), divisor); | |
| 284 | +} | |
| 285 | + | |
| 286 | +static int cxd2820r_set_frontend(struct dvb_frontend *fe, | |
| 287 | + struct dvb_frontend_parameters *p) | |
| 288 | +{ | |
| 289 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 290 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 291 | + int ret; | |
| 292 | + dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | |
| 293 | + | |
| 294 | + if (fe->ops.info.type == FE_OFDM) { | |
| 295 | + /* DVB-T/T2 */ | |
| 296 | + ret = cxd2820r_lock(priv, 0); | |
| 297 | + if (ret) | |
| 298 | + return ret; | |
| 299 | + | |
| 300 | + switch (priv->delivery_system) { | |
| 301 | + case SYS_UNDEFINED: | |
| 302 | + if (c->delivery_system == SYS_DVBT) { | |
| 303 | + /* SLEEP => DVB-T */ | |
| 304 | + ret = cxd2820r_set_frontend_t(fe, p); | |
| 305 | + } else { | |
| 306 | + /* SLEEP => DVB-T2 */ | |
| 307 | + ret = cxd2820r_set_frontend_t2(fe, p); | |
| 308 | + } | |
| 309 | + break; | |
| 310 | + case SYS_DVBT: | |
| 311 | + if (c->delivery_system == SYS_DVBT) { | |
| 312 | + /* DVB-T => DVB-T */ | |
| 313 | + ret = cxd2820r_set_frontend_t(fe, p); | |
| 314 | + } else if (c->delivery_system == SYS_DVBT2) { | |
| 315 | + /* DVB-T => DVB-T2 */ | |
| 316 | + ret = cxd2820r_sleep_t(fe); | |
| 317 | + ret = cxd2820r_set_frontend_t2(fe, p); | |
| 318 | + } | |
| 319 | + break; | |
| 320 | + case SYS_DVBT2: | |
| 321 | + if (c->delivery_system == SYS_DVBT2) { | |
| 322 | + /* DVB-T2 => DVB-T2 */ | |
| 323 | + ret = cxd2820r_set_frontend_t2(fe, p); | |
| 324 | + } else if (c->delivery_system == SYS_DVBT) { | |
| 325 | + /* DVB-T2 => DVB-T */ | |
| 326 | + ret = cxd2820r_sleep_t2(fe); | |
| 327 | + ret = cxd2820r_set_frontend_t(fe, p); | |
| 328 | + } | |
| 329 | + break; | |
| 330 | + default: | |
| 331 | + dbg("%s: error state=%d", __func__, | |
| 332 | + priv->delivery_system); | |
| 333 | + ret = -EINVAL; | |
| 334 | + } | |
| 335 | + } else { | |
| 336 | + /* DVB-C */ | |
| 337 | + ret = cxd2820r_lock(priv, 1); | |
| 338 | + if (ret) | |
| 339 | + return ret; | |
| 340 | + | |
| 341 | + ret = cxd2820r_set_frontend_c(fe, p); | |
| 342 | + } | |
| 343 | + | |
| 344 | + return ret; | |
| 345 | +} | |
| 346 | + | |
| 347 | +static int cxd2820r_read_status(struct dvb_frontend *fe, fe_status_t *status) | |
| 348 | +{ | |
| 349 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 350 | + int ret; | |
| 351 | + dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | |
| 352 | + | |
| 353 | + if (fe->ops.info.type == FE_OFDM) { | |
| 354 | + /* DVB-T/T2 */ | |
| 355 | + ret = cxd2820r_lock(priv, 0); | |
| 356 | + if (ret) | |
| 357 | + return ret; | |
| 358 | + | |
| 359 | + switch (fe->dtv_property_cache.delivery_system) { | |
| 360 | + case SYS_DVBT: | |
| 361 | + ret = cxd2820r_read_status_t(fe, status); | |
| 362 | + break; | |
| 363 | + case SYS_DVBT2: | |
| 364 | + ret = cxd2820r_read_status_t2(fe, status); | |
| 365 | + break; | |
| 366 | + default: | |
| 367 | + ret = -EINVAL; | |
| 368 | + } | |
| 369 | + } else { | |
| 370 | + /* DVB-C */ | |
| 371 | + ret = cxd2820r_lock(priv, 1); | |
| 372 | + if (ret) | |
| 373 | + return ret; | |
| 374 | + | |
| 375 | + ret = cxd2820r_read_status_c(fe, status); | |
| 376 | + } | |
| 377 | + | |
| 378 | + return ret; | |
| 379 | +} | |
| 380 | + | |
| 381 | +static int cxd2820r_get_frontend(struct dvb_frontend *fe, | |
| 382 | + struct dvb_frontend_parameters *p) | |
| 383 | +{ | |
| 384 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 385 | + int ret; | |
| 386 | + dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | |
| 387 | + | |
| 388 | + if (fe->ops.info.type == FE_OFDM) { | |
| 389 | + /* DVB-T/T2 */ | |
| 390 | + ret = cxd2820r_lock(priv, 0); | |
| 391 | + if (ret) | |
| 392 | + return ret; | |
| 393 | + | |
| 394 | + switch (fe->dtv_property_cache.delivery_system) { | |
| 395 | + case SYS_DVBT: | |
| 396 | + ret = cxd2820r_get_frontend_t(fe, p); | |
| 397 | + break; | |
| 398 | + case SYS_DVBT2: | |
| 399 | + ret = cxd2820r_get_frontend_t2(fe, p); | |
| 400 | + break; | |
| 401 | + default: | |
| 402 | + ret = -EINVAL; | |
| 403 | + } | |
| 404 | + } else { | |
| 405 | + /* DVB-C */ | |
| 406 | + ret = cxd2820r_lock(priv, 1); | |
| 407 | + if (ret) | |
| 408 | + return ret; | |
| 409 | + | |
| 410 | + ret = cxd2820r_get_frontend_c(fe, p); | |
| 411 | + } | |
| 412 | + | |
| 413 | + return ret; | |
| 414 | +} | |
| 415 | + | |
| 416 | +static int cxd2820r_read_ber(struct dvb_frontend *fe, u32 *ber) | |
| 417 | +{ | |
| 418 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 419 | + int ret; | |
| 420 | + dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | |
| 421 | + | |
| 422 | + if (fe->ops.info.type == FE_OFDM) { | |
| 423 | + /* DVB-T/T2 */ | |
| 424 | + ret = cxd2820r_lock(priv, 0); | |
| 425 | + if (ret) | |
| 426 | + return ret; | |
| 427 | + | |
| 428 | + switch (fe->dtv_property_cache.delivery_system) { | |
| 429 | + case SYS_DVBT: | |
| 430 | + ret = cxd2820r_read_ber_t(fe, ber); | |
| 431 | + break; | |
| 432 | + case SYS_DVBT2: | |
| 433 | + ret = cxd2820r_read_ber_t2(fe, ber); | |
| 434 | + break; | |
| 435 | + default: | |
| 436 | + ret = -EINVAL; | |
| 437 | + } | |
| 438 | + } else { | |
| 439 | + /* DVB-C */ | |
| 440 | + ret = cxd2820r_lock(priv, 1); | |
| 441 | + if (ret) | |
| 442 | + return ret; | |
| 443 | + | |
| 444 | + ret = cxd2820r_read_ber_c(fe, ber); | |
| 445 | + } | |
| 446 | + | |
| 447 | + return ret; | |
| 448 | +} | |
| 449 | + | |
| 450 | +static int cxd2820r_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | |
| 451 | +{ | |
| 452 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 453 | + int ret; | |
| 454 | + dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | |
| 455 | + | |
| 456 | + if (fe->ops.info.type == FE_OFDM) { | |
| 457 | + /* DVB-T/T2 */ | |
| 458 | + ret = cxd2820r_lock(priv, 0); | |
| 459 | + if (ret) | |
| 460 | + return ret; | |
| 461 | + | |
| 462 | + switch (fe->dtv_property_cache.delivery_system) { | |
| 463 | + case SYS_DVBT: | |
| 464 | + ret = cxd2820r_read_signal_strength_t(fe, strength); | |
| 465 | + break; | |
| 466 | + case SYS_DVBT2: | |
| 467 | + ret = cxd2820r_read_signal_strength_t2(fe, strength); | |
| 468 | + break; | |
| 469 | + default: | |
| 470 | + ret = -EINVAL; | |
| 471 | + } | |
| 472 | + } else { | |
| 473 | + /* DVB-C */ | |
| 474 | + ret = cxd2820r_lock(priv, 1); | |
| 475 | + if (ret) | |
| 476 | + return ret; | |
| 477 | + | |
| 478 | + ret = cxd2820r_read_signal_strength_c(fe, strength); | |
| 479 | + } | |
| 480 | + | |
| 481 | + return ret; | |
| 482 | +} | |
| 483 | + | |
| 484 | +static int cxd2820r_read_snr(struct dvb_frontend *fe, u16 *snr) | |
| 485 | +{ | |
| 486 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 487 | + int ret; | |
| 488 | + dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | |
| 489 | + | |
| 490 | + if (fe->ops.info.type == FE_OFDM) { | |
| 491 | + /* DVB-T/T2 */ | |
| 492 | + ret = cxd2820r_lock(priv, 0); | |
| 493 | + if (ret) | |
| 494 | + return ret; | |
| 495 | + | |
| 496 | + switch (fe->dtv_property_cache.delivery_system) { | |
| 497 | + case SYS_DVBT: | |
| 498 | + ret = cxd2820r_read_snr_t(fe, snr); | |
| 499 | + break; | |
| 500 | + case SYS_DVBT2: | |
| 501 | + ret = cxd2820r_read_snr_t2(fe, snr); | |
| 502 | + break; | |
| 503 | + default: | |
| 504 | + ret = -EINVAL; | |
| 505 | + } | |
| 506 | + } else { | |
| 507 | + /* DVB-C */ | |
| 508 | + ret = cxd2820r_lock(priv, 1); | |
| 509 | + if (ret) | |
| 510 | + return ret; | |
| 511 | + | |
| 512 | + ret = cxd2820r_read_snr_c(fe, snr); | |
| 513 | + } | |
| 514 | + | |
| 515 | + return ret; | |
| 516 | +} | |
| 517 | + | |
| 518 | +static int cxd2820r_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | |
| 519 | +{ | |
| 520 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 521 | + int ret; | |
| 522 | + dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | |
| 523 | + | |
| 524 | + if (fe->ops.info.type == FE_OFDM) { | |
| 525 | + /* DVB-T/T2 */ | |
| 526 | + ret = cxd2820r_lock(priv, 0); | |
| 527 | + if (ret) | |
| 528 | + return ret; | |
| 529 | + | |
| 530 | + switch (fe->dtv_property_cache.delivery_system) { | |
| 531 | + case SYS_DVBT: | |
| 532 | + ret = cxd2820r_read_ucblocks_t(fe, ucblocks); | |
| 533 | + break; | |
| 534 | + case SYS_DVBT2: | |
| 535 | + ret = cxd2820r_read_ucblocks_t2(fe, ucblocks); | |
| 536 | + break; | |
| 537 | + default: | |
| 538 | + ret = -EINVAL; | |
| 539 | + } | |
| 540 | + } else { | |
| 541 | + /* DVB-C */ | |
| 542 | + ret = cxd2820r_lock(priv, 1); | |
| 543 | + if (ret) | |
| 544 | + return ret; | |
| 545 | + | |
| 546 | + ret = cxd2820r_read_ucblocks_c(fe, ucblocks); | |
| 547 | + } | |
| 548 | + | |
| 549 | + return ret; | |
| 550 | +} | |
| 551 | + | |
| 552 | +static int cxd2820r_init(struct dvb_frontend *fe) | |
| 553 | +{ | |
| 554 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 555 | + int ret; | |
| 556 | + dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | |
| 557 | + | |
| 558 | + priv->delivery_system = SYS_UNDEFINED; | |
| 559 | + /* delivery system is unknown at that (init) phase */ | |
| 560 | + | |
| 561 | + if (fe->ops.info.type == FE_OFDM) { | |
| 562 | + /* DVB-T/T2 */ | |
| 563 | + ret = cxd2820r_lock(priv, 0); | |
| 564 | + if (ret) | |
| 565 | + return ret; | |
| 566 | + | |
| 567 | + ret = cxd2820r_init_t(fe); | |
| 568 | + } else { | |
| 569 | + /* DVB-C */ | |
| 570 | + ret = cxd2820r_lock(priv, 1); | |
| 571 | + if (ret) | |
| 572 | + return ret; | |
| 573 | + | |
| 574 | + ret = cxd2820r_init_c(fe); | |
| 575 | + } | |
| 576 | + | |
| 577 | + return ret; | |
| 578 | +} | |
| 579 | + | |
| 580 | +static int cxd2820r_sleep(struct dvb_frontend *fe) | |
| 581 | +{ | |
| 582 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 583 | + int ret; | |
| 584 | + dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | |
| 585 | + | |
| 586 | + if (fe->ops.info.type == FE_OFDM) { | |
| 587 | + /* DVB-T/T2 */ | |
| 588 | + ret = cxd2820r_lock(priv, 0); | |
| 589 | + if (ret) | |
| 590 | + return ret; | |
| 591 | + | |
| 592 | + switch (fe->dtv_property_cache.delivery_system) { | |
| 593 | + case SYS_DVBT: | |
| 594 | + ret = cxd2820r_sleep_t(fe); | |
| 595 | + break; | |
| 596 | + case SYS_DVBT2: | |
| 597 | + ret = cxd2820r_sleep_t2(fe); | |
| 598 | + break; | |
| 599 | + default: | |
| 600 | + ret = -EINVAL; | |
| 601 | + } | |
| 602 | + | |
| 603 | + cxd2820r_unlock(priv, 0); | |
| 604 | + } else { | |
| 605 | + /* DVB-C */ | |
| 606 | + ret = cxd2820r_lock(priv, 1); | |
| 607 | + if (ret) | |
| 608 | + return ret; | |
| 609 | + | |
| 610 | + ret = cxd2820r_sleep_c(fe); | |
| 611 | + | |
| 612 | + cxd2820r_unlock(priv, 1); | |
| 613 | + } | |
| 614 | + | |
| 615 | + return ret; | |
| 616 | +} | |
| 617 | + | |
| 618 | +static int cxd2820r_get_tune_settings(struct dvb_frontend *fe, | |
| 619 | + struct dvb_frontend_tune_settings *s) | |
| 620 | +{ | |
| 621 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 622 | + int ret; | |
| 623 | + dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | |
| 624 | + | |
| 625 | + if (fe->ops.info.type == FE_OFDM) { | |
| 626 | + /* DVB-T/T2 */ | |
| 627 | + ret = cxd2820r_lock(priv, 0); | |
| 628 | + if (ret) | |
| 629 | + return ret; | |
| 630 | + | |
| 631 | + switch (fe->dtv_property_cache.delivery_system) { | |
| 632 | + case SYS_DVBT: | |
| 633 | + ret = cxd2820r_get_tune_settings_t(fe, s); | |
| 634 | + break; | |
| 635 | + case SYS_DVBT2: | |
| 636 | + ret = cxd2820r_get_tune_settings_t2(fe, s); | |
| 637 | + break; | |
| 638 | + default: | |
| 639 | + ret = -EINVAL; | |
| 640 | + } | |
| 641 | + } else { | |
| 642 | + /* DVB-C */ | |
| 643 | + ret = cxd2820r_lock(priv, 1); | |
| 644 | + if (ret) | |
| 645 | + return ret; | |
| 646 | + | |
| 647 | + ret = cxd2820r_get_tune_settings_c(fe, s); | |
| 648 | + } | |
| 649 | + | |
| 650 | + return ret; | |
| 651 | +} | |
| 652 | + | |
| 653 | +static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe, | |
| 654 | + struct dvb_frontend_parameters *p) | |
| 655 | +{ | |
| 656 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 657 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 658 | + int ret, i; | |
| 659 | + fe_status_t status = 0; | |
| 660 | + dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); | |
| 661 | + | |
| 662 | + /* switch between DVB-T and DVB-T2 when tune fails */ | |
| 663 | + if (priv->last_tune_failed) { | |
| 664 | + if (priv->delivery_system == SYS_DVBT) | |
| 665 | + c->delivery_system = SYS_DVBT2; | |
| 666 | + else | |
| 667 | + c->delivery_system = SYS_DVBT; | |
| 668 | + } | |
| 669 | + | |
| 670 | + /* set frontend */ | |
| 671 | + ret = cxd2820r_set_frontend(fe, p); | |
| 672 | + if (ret) | |
| 673 | + goto error; | |
| 674 | + | |
| 675 | + | |
| 676 | + /* frontend lock wait loop count */ | |
| 677 | + switch (priv->delivery_system) { | |
| 678 | + case SYS_DVBT: | |
| 679 | + i = 20; | |
| 680 | + break; | |
| 681 | + case SYS_DVBT2: | |
| 682 | + i = 40; | |
| 683 | + break; | |
| 684 | + case SYS_UNDEFINED: | |
| 685 | + default: | |
| 686 | + i = 0; | |
| 687 | + break; | |
| 688 | + } | |
| 689 | + | |
| 690 | + /* wait frontend lock */ | |
| 691 | + for (; i > 0; i--) { | |
| 692 | + dbg("%s: LOOP=%d", __func__, i); | |
| 693 | + msleep(50); | |
| 694 | + ret = cxd2820r_read_status(fe, &status); | |
| 695 | + if (ret) | |
| 696 | + goto error; | |
| 697 | + | |
| 698 | + if (status & FE_HAS_SIGNAL) | |
| 699 | + break; | |
| 700 | + } | |
| 701 | + | |
| 702 | + /* check if we have a valid signal */ | |
| 703 | + if (status) { | |
| 704 | + priv->last_tune_failed = 0; | |
| 705 | + return DVBFE_ALGO_SEARCH_SUCCESS; | |
| 706 | + } else { | |
| 707 | + priv->last_tune_failed = 1; | |
| 708 | + return DVBFE_ALGO_SEARCH_AGAIN; | |
| 709 | + } | |
| 710 | + | |
| 711 | +error: | |
| 712 | + dbg("%s: failed:%d", __func__, ret); | |
| 713 | + return DVBFE_ALGO_SEARCH_ERROR; | |
| 714 | +} | |
| 715 | + | |
| 716 | +static int cxd2820r_get_frontend_algo(struct dvb_frontend *fe) | |
| 717 | +{ | |
| 718 | + return DVBFE_ALGO_CUSTOM; | |
| 719 | +} | |
| 720 | + | |
| 721 | +static void cxd2820r_release(struct dvb_frontend *fe) | |
| 722 | +{ | |
| 723 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 724 | + dbg("%s", __func__); | |
| 725 | + | |
| 726 | + if (fe->ops.info.type == FE_OFDM) { | |
| 727 | + i2c_del_adapter(&priv->tuner_i2c_adapter); | |
| 728 | + kfree(priv); | |
| 729 | + } | |
| 730 | + | |
| 731 | + return; | |
| 732 | +} | |
| 733 | + | |
| 734 | +static u32 cxd2820r_tuner_i2c_func(struct i2c_adapter *adapter) | |
| 735 | +{ | |
| 736 | + return I2C_FUNC_I2C; | |
| 737 | +} | |
| 738 | + | |
| 739 | +static int cxd2820r_tuner_i2c_xfer(struct i2c_adapter *i2c_adap, | |
| 740 | + struct i2c_msg msg[], int num) | |
| 741 | +{ | |
| 742 | + struct cxd2820r_priv *priv = i2c_get_adapdata(i2c_adap); | |
| 743 | + u8 obuf[msg[0].len + 2]; | |
| 744 | + struct i2c_msg msg2[2] = { | |
| 745 | + { | |
| 746 | + .addr = priv->cfg.i2c_address, | |
| 747 | + .flags = 0, | |
| 748 | + .len = sizeof(obuf), | |
| 749 | + .buf = obuf, | |
| 750 | + }, { | |
| 751 | + .addr = priv->cfg.i2c_address, | |
| 752 | + .flags = I2C_M_RD, | |
| 753 | + .len = msg[1].len, | |
| 754 | + .buf = msg[1].buf, | |
| 755 | + } | |
| 756 | + }; | |
| 757 | + | |
| 758 | + obuf[0] = 0x09; | |
| 759 | + obuf[1] = (msg[0].addr << 1); | |
| 760 | + if (num == 2) { /* I2C read */ | |
| 761 | + obuf[1] = (msg[0].addr << 1) | I2C_M_RD; /* I2C RD flag */ | |
| 762 | + msg2[0].len = sizeof(obuf) - 1; /* maybe HW bug ? */ | |
| 763 | + } | |
| 764 | + memcpy(&obuf[2], msg[0].buf, msg[0].len); | |
| 765 | + | |
| 766 | + return i2c_transfer(priv->i2c, msg2, num); | |
| 767 | +} | |
| 768 | + | |
| 769 | +static struct i2c_algorithm cxd2820r_tuner_i2c_algo = { | |
| 770 | + .master_xfer = cxd2820r_tuner_i2c_xfer, | |
| 771 | + .functionality = cxd2820r_tuner_i2c_func, | |
| 772 | +}; | |
| 773 | + | |
| 774 | +struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(struct dvb_frontend *fe) | |
| 775 | +{ | |
| 776 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 777 | + return &priv->tuner_i2c_adapter; | |
| 778 | +} | |
| 779 | +EXPORT_SYMBOL(cxd2820r_get_tuner_i2c_adapter); | |
| 780 | + | |
| 781 | +static struct dvb_frontend_ops cxd2820r_ops[2]; | |
| 782 | + | |
| 783 | +struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg, | |
| 784 | + struct i2c_adapter *i2c, struct dvb_frontend *fe) | |
| 785 | +{ | |
| 786 | + int ret; | |
| 787 | + struct cxd2820r_priv *priv = NULL; | |
| 788 | + u8 tmp; | |
| 789 | + | |
| 790 | + if (fe == NULL) { | |
| 791 | + /* FE0 */ | |
| 792 | + /* allocate memory for the internal priv */ | |
| 793 | + priv = kzalloc(sizeof(struct cxd2820r_priv), GFP_KERNEL); | |
| 794 | + if (priv == NULL) | |
| 795 | + goto error; | |
| 796 | + | |
| 797 | + /* setup the priv */ | |
| 798 | + priv->i2c = i2c; | |
| 799 | + memcpy(&priv->cfg, cfg, sizeof(struct cxd2820r_config)); | |
| 800 | + mutex_init(&priv->fe_lock); | |
| 801 | + | |
| 802 | + priv->active_fe = -1; /* NONE */ | |
| 803 | + | |
| 804 | + /* check if the demod is there */ | |
| 805 | + priv->bank[0] = priv->bank[1] = 0xff; | |
| 806 | + ret = cxd2820r_rd_reg(priv, 0x000fd, &tmp); | |
| 807 | + dbg("%s: chip id=%02x", __func__, tmp); | |
| 808 | + if (ret || tmp != 0xe1) | |
| 809 | + goto error; | |
| 810 | + | |
| 811 | + /* create frontends */ | |
| 812 | + memcpy(&priv->fe[0].ops, &cxd2820r_ops[0], | |
| 813 | + sizeof(struct dvb_frontend_ops)); | |
| 814 | + memcpy(&priv->fe[1].ops, &cxd2820r_ops[1], | |
| 815 | + sizeof(struct dvb_frontend_ops)); | |
| 816 | + | |
| 817 | + priv->fe[0].demodulator_priv = priv; | |
| 818 | + priv->fe[1].demodulator_priv = priv; | |
| 819 | + | |
| 820 | + /* create tuner i2c adapter */ | |
| 821 | + strlcpy(priv->tuner_i2c_adapter.name, | |
| 822 | + "CXD2820R tuner I2C adapter", | |
| 823 | + sizeof(priv->tuner_i2c_adapter.name)); | |
| 824 | + priv->tuner_i2c_adapter.algo = &cxd2820r_tuner_i2c_algo; | |
| 825 | + priv->tuner_i2c_adapter.algo_data = NULL; | |
| 826 | + i2c_set_adapdata(&priv->tuner_i2c_adapter, priv); | |
| 827 | + if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) { | |
| 828 | + err("tuner I2C bus could not be initialized"); | |
| 829 | + goto error; | |
| 830 | + } | |
| 831 | + | |
| 832 | + return &priv->fe[0]; | |
| 833 | + | |
| 834 | + } else { | |
| 835 | + /* FE1: FE0 given as pointer, just return FE1 we have | |
| 836 | + * already created */ | |
| 837 | + priv = fe->demodulator_priv; | |
| 838 | + return &priv->fe[1]; | |
| 839 | + } | |
| 840 | + | |
| 841 | +error: | |
| 842 | + kfree(priv); | |
| 843 | + return NULL; | |
| 844 | +} | |
| 845 | +EXPORT_SYMBOL(cxd2820r_attach); | |
| 846 | + | |
| 847 | +static struct dvb_frontend_ops cxd2820r_ops[2] = { | |
| 848 | + { | |
| 849 | + /* DVB-T/T2 */ | |
| 850 | + .info = { | |
| 851 | + .name = "Sony CXD2820R (DVB-T/T2)", | |
| 852 | + .type = FE_OFDM, | |
| 853 | + .caps = | |
| 854 | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | | |
| 855 | + FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | | |
| 856 | + FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | |
| 857 | + FE_CAN_QPSK | FE_CAN_QAM_16 | | |
| 858 | + FE_CAN_QAM_64 | FE_CAN_QAM_256 | | |
| 859 | + FE_CAN_QAM_AUTO | | |
| 860 | + FE_CAN_TRANSMISSION_MODE_AUTO | | |
| 861 | + FE_CAN_GUARD_INTERVAL_AUTO | | |
| 862 | + FE_CAN_HIERARCHY_AUTO | | |
| 863 | + FE_CAN_MUTE_TS | | |
| 864 | + FE_CAN_2G_MODULATION | |
| 865 | + }, | |
| 866 | + | |
| 867 | + .release = cxd2820r_release, | |
| 868 | + .init = cxd2820r_init, | |
| 869 | + .sleep = cxd2820r_sleep, | |
| 870 | + | |
| 871 | + .get_tune_settings = cxd2820r_get_tune_settings, | |
| 872 | + | |
| 873 | + .get_frontend = cxd2820r_get_frontend, | |
| 874 | + | |
| 875 | + .get_frontend_algo = cxd2820r_get_frontend_algo, | |
| 876 | + .search = cxd2820r_search, | |
| 877 | + | |
| 878 | + .read_status = cxd2820r_read_status, | |
| 879 | + .read_snr = cxd2820r_read_snr, | |
| 880 | + .read_ber = cxd2820r_read_ber, | |
| 881 | + .read_ucblocks = cxd2820r_read_ucblocks, | |
| 882 | + .read_signal_strength = cxd2820r_read_signal_strength, | |
| 883 | + }, | |
| 884 | + { | |
| 885 | + /* DVB-C */ | |
| 886 | + .info = { | |
| 887 | + .name = "Sony CXD2820R (DVB-C)", | |
| 888 | + .type = FE_QAM, | |
| 889 | + .caps = | |
| 890 | + FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | | |
| 891 | + FE_CAN_QAM_128 | FE_CAN_QAM_256 | | |
| 892 | + FE_CAN_FEC_AUTO | |
| 893 | + }, | |
| 894 | + | |
| 895 | + .release = cxd2820r_release, | |
| 896 | + .init = cxd2820r_init, | |
| 897 | + .sleep = cxd2820r_sleep, | |
| 898 | + | |
| 899 | + .get_tune_settings = cxd2820r_get_tune_settings, | |
| 900 | + | |
| 901 | + .set_frontend = cxd2820r_set_frontend, | |
| 902 | + .get_frontend = cxd2820r_get_frontend, | |
| 903 | + | |
| 904 | + .read_status = cxd2820r_read_status, | |
| 905 | + .read_snr = cxd2820r_read_snr, | |
| 906 | + .read_ber = cxd2820r_read_ber, | |
| 907 | + .read_ucblocks = cxd2820r_read_ucblocks, | |
| 908 | + .read_signal_strength = cxd2820r_read_signal_strength, | |
| 909 | + }, | |
| 910 | +}; | |
| 911 | + | |
| 912 | + | |
| 913 | +MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | |
| 914 | +MODULE_DESCRIPTION("Sony CXD2820R demodulator driver"); | |
| 915 | +MODULE_LICENSE("GPL"); | |
| @@ -0,0 +1,166 @@ | ||
| 1 | +/* | |
| 2 | + * Sony CXD2820R demodulator driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License along | |
| 17 | + * with this program; if not, write to the Free Software Foundation, Inc., | |
| 18 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + */ | |
| 20 | + | |
| 21 | + | |
| 22 | +#ifndef CXD2820R_PRIV_H | |
| 23 | +#define CXD2820R_PRIV_H | |
| 24 | + | |
| 25 | +#include <linux/dvb/version.h> | |
| 26 | +#include "dvb_frontend.h" | |
| 27 | +#include "dvb_math.h" | |
| 28 | +#include "cxd2820r.h" | |
| 29 | + | |
| 30 | +#define LOG_PREFIX "cxd2820r" | |
| 31 | + | |
| 32 | +#undef dbg | |
| 33 | +#define dbg(f, arg...) \ | |
| 34 | + if (cxd2820r_debug) \ | |
| 35 | + printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) | |
| 36 | +#undef err | |
| 37 | +#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) | |
| 38 | +#undef info | |
| 39 | +#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) | |
| 40 | +#undef warn | |
| 41 | +#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) | |
| 42 | + | |
| 43 | +struct reg_val_mask { | |
| 44 | + u32 reg; | |
| 45 | + u8 val; | |
| 46 | + u8 mask; | |
| 47 | +}; | |
| 48 | + | |
| 49 | +struct cxd2820r_priv { | |
| 50 | + struct i2c_adapter *i2c; | |
| 51 | + struct dvb_frontend fe[2]; | |
| 52 | + struct cxd2820r_config cfg; | |
| 53 | + struct i2c_adapter tuner_i2c_adapter; | |
| 54 | + | |
| 55 | + struct mutex fe_lock; /* FE lock */ | |
| 56 | + int active_fe:2; /* FE lock, -1=NONE, 0=DVB-T/T2, 1=DVB-C */ | |
| 57 | + | |
| 58 | + int ber_running:1; | |
| 59 | + | |
| 60 | + u8 bank[2]; | |
| 61 | + u8 gpio[3]; | |
| 62 | + | |
| 63 | + fe_delivery_system_t delivery_system; | |
| 64 | + int last_tune_failed:1; /* for switch between T and T2 tune */ | |
| 65 | +}; | |
| 66 | + | |
| 67 | +/* cxd2820r_core.c */ | |
| 68 | + | |
| 69 | +extern int cxd2820r_debug; | |
| 70 | + | |
| 71 | +int cxd2820r_gpio(struct dvb_frontend *fe); | |
| 72 | + | |
| 73 | +int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val, | |
| 74 | + u8 mask); | |
| 75 | + | |
| 76 | +int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val, | |
| 77 | + int len); | |
| 78 | + | |
| 79 | +u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor); | |
| 80 | + | |
| 81 | +int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val, | |
| 82 | + int len); | |
| 83 | + | |
| 84 | +int cxd2820r_rd_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val, | |
| 85 | + int len); | |
| 86 | + | |
| 87 | +int cxd2820r_wr_reg(struct cxd2820r_priv *priv, u32 reg, u8 val); | |
| 88 | + | |
| 89 | +int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val); | |
| 90 | + | |
| 91 | +/* cxd2820r_c.c */ | |
| 92 | + | |
| 93 | +int cxd2820r_get_frontend_c(struct dvb_frontend *fe, | |
| 94 | + struct dvb_frontend_parameters *p); | |
| 95 | + | |
| 96 | +int cxd2820r_set_frontend_c(struct dvb_frontend *fe, | |
| 97 | + struct dvb_frontend_parameters *params); | |
| 98 | + | |
| 99 | +int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status); | |
| 100 | + | |
| 101 | +int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber); | |
| 102 | + | |
| 103 | +int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe, u16 *strength); | |
| 104 | + | |
| 105 | +int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr); | |
| 106 | + | |
| 107 | +int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks); | |
| 108 | + | |
| 109 | +int cxd2820r_init_c(struct dvb_frontend *fe); | |
| 110 | + | |
| 111 | +int cxd2820r_sleep_c(struct dvb_frontend *fe); | |
| 112 | + | |
| 113 | +int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe, | |
| 114 | + struct dvb_frontend_tune_settings *s); | |
| 115 | + | |
| 116 | +/* cxd2820r_t.c */ | |
| 117 | + | |
| 118 | +int cxd2820r_get_frontend_t(struct dvb_frontend *fe, | |
| 119 | + struct dvb_frontend_parameters *p); | |
| 120 | + | |
| 121 | +int cxd2820r_set_frontend_t(struct dvb_frontend *fe, | |
| 122 | + struct dvb_frontend_parameters *params); | |
| 123 | + | |
| 124 | +int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status); | |
| 125 | + | |
| 126 | +int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber); | |
| 127 | + | |
| 128 | +int cxd2820r_read_signal_strength_t(struct dvb_frontend *fe, u16 *strength); | |
| 129 | + | |
| 130 | +int cxd2820r_read_snr_t(struct dvb_frontend *fe, u16 *snr); | |
| 131 | + | |
| 132 | +int cxd2820r_read_ucblocks_t(struct dvb_frontend *fe, u32 *ucblocks); | |
| 133 | + | |
| 134 | +int cxd2820r_init_t(struct dvb_frontend *fe); | |
| 135 | + | |
| 136 | +int cxd2820r_sleep_t(struct dvb_frontend *fe); | |
| 137 | + | |
| 138 | +int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe, | |
| 139 | + struct dvb_frontend_tune_settings *s); | |
| 140 | + | |
| 141 | +/* cxd2820r_t2.c */ | |
| 142 | + | |
| 143 | +int cxd2820r_get_frontend_t2(struct dvb_frontend *fe, | |
| 144 | + struct dvb_frontend_parameters *p); | |
| 145 | + | |
| 146 | +int cxd2820r_set_frontend_t2(struct dvb_frontend *fe, | |
| 147 | + struct dvb_frontend_parameters *params); | |
| 148 | + | |
| 149 | +int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status); | |
| 150 | + | |
| 151 | +int cxd2820r_read_ber_t2(struct dvb_frontend *fe, u32 *ber); | |
| 152 | + | |
| 153 | +int cxd2820r_read_signal_strength_t2(struct dvb_frontend *fe, u16 *strength); | |
| 154 | + | |
| 155 | +int cxd2820r_read_snr_t2(struct dvb_frontend *fe, u16 *snr); | |
| 156 | + | |
| 157 | +int cxd2820r_read_ucblocks_t2(struct dvb_frontend *fe, u32 *ucblocks); | |
| 158 | + | |
| 159 | +int cxd2820r_init_t2(struct dvb_frontend *fe); | |
| 160 | + | |
| 161 | +int cxd2820r_sleep_t2(struct dvb_frontend *fe); | |
| 162 | + | |
| 163 | +int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe, | |
| 164 | + struct dvb_frontend_tune_settings *s); | |
| 165 | + | |
| 166 | +#endif /* CXD2820R_PRIV_H */ | |
| @@ -0,0 +1,449 @@ | ||
| 1 | +/* | |
| 2 | + * Sony CXD2820R demodulator driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License along | |
| 17 | + * with this program; if not, write to the Free Software Foundation, Inc., | |
| 18 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + */ | |
| 20 | + | |
| 21 | + | |
| 22 | +#include "cxd2820r_priv.h" | |
| 23 | + | |
| 24 | +int cxd2820r_set_frontend_t(struct dvb_frontend *fe, | |
| 25 | + struct dvb_frontend_parameters *p) | |
| 26 | +{ | |
| 27 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 28 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 29 | + int ret, i; | |
| 30 | + u32 if_khz, if_ctl; | |
| 31 | + u64 num; | |
| 32 | + u8 buf[3], bw_param; | |
| 33 | + u8 bw_params1[][5] = { | |
| 34 | + { 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */ | |
| 35 | + { 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */ | |
| 36 | + { 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */ | |
| 37 | + }; | |
| 38 | + u8 bw_params2[][2] = { | |
| 39 | + { 0x1f, 0xdc }, /* 6 MHz */ | |
| 40 | + { 0x12, 0xf8 }, /* 7 MHz */ | |
| 41 | + { 0x01, 0xe0 }, /* 8 MHz */ | |
| 42 | + }; | |
| 43 | + struct reg_val_mask tab[] = { | |
| 44 | + { 0x00080, 0x00, 0xff }, | |
| 45 | + { 0x00081, 0x03, 0xff }, | |
| 46 | + { 0x00085, 0x07, 0xff }, | |
| 47 | + { 0x00088, 0x01, 0xff }, | |
| 48 | + | |
| 49 | + { 0x00070, priv->cfg.ts_mode, 0xff }, | |
| 50 | + { 0x000cb, priv->cfg.if_agc_polarity << 6, 0x40 }, | |
| 51 | + { 0x000a5, 0x00, 0x01 }, | |
| 52 | + { 0x00082, 0x20, 0x60 }, | |
| 53 | + { 0x000c2, 0xc3, 0xff }, | |
| 54 | + { 0x0016a, 0x50, 0xff }, | |
| 55 | + { 0x00427, 0x41, 0xff }, | |
| 56 | + }; | |
| 57 | + | |
| 58 | + dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz); | |
| 59 | + | |
| 60 | + /* update GPIOs */ | |
| 61 | + ret = cxd2820r_gpio(fe); | |
| 62 | + if (ret) | |
| 63 | + goto error; | |
| 64 | + | |
| 65 | + /* program tuner */ | |
| 66 | + if (fe->ops.tuner_ops.set_params) | |
| 67 | + fe->ops.tuner_ops.set_params(fe, p); | |
| 68 | + | |
| 69 | + if (priv->delivery_system != SYS_DVBT) { | |
| 70 | + for (i = 0; i < ARRAY_SIZE(tab); i++) { | |
| 71 | + ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, | |
| 72 | + tab[i].val, tab[i].mask); | |
| 73 | + if (ret) | |
| 74 | + goto error; | |
| 75 | + } | |
| 76 | + } | |
| 77 | + | |
| 78 | + priv->delivery_system = SYS_DVBT; | |
| 79 | + priv->ber_running = 0; /* tune stops BER counter */ | |
| 80 | + | |
| 81 | + switch (c->bandwidth_hz) { | |
| 82 | + case 6000000: | |
| 83 | + if_khz = priv->cfg.if_dvbt_6; | |
| 84 | + i = 0; | |
| 85 | + bw_param = 2; | |
| 86 | + break; | |
| 87 | + case 7000000: | |
| 88 | + if_khz = priv->cfg.if_dvbt_7; | |
| 89 | + i = 1; | |
| 90 | + bw_param = 1; | |
| 91 | + break; | |
| 92 | + case 8000000: | |
| 93 | + if_khz = priv->cfg.if_dvbt_8; | |
| 94 | + i = 2; | |
| 95 | + bw_param = 0; | |
| 96 | + break; | |
| 97 | + default: | |
| 98 | + return -EINVAL; | |
| 99 | + } | |
| 100 | + | |
| 101 | + num = if_khz; | |
| 102 | + num *= 0x1000000; | |
| 103 | + if_ctl = cxd2820r_div_u64_round_closest(num, 41000); | |
| 104 | + buf[0] = ((if_ctl >> 16) & 0xff); | |
| 105 | + buf[1] = ((if_ctl >> 8) & 0xff); | |
| 106 | + buf[2] = ((if_ctl >> 0) & 0xff); | |
| 107 | + | |
| 108 | + ret = cxd2820r_wr_regs(priv, 0x000b6, buf, 3); | |
| 109 | + if (ret) | |
| 110 | + goto error; | |
| 111 | + | |
| 112 | + ret = cxd2820r_wr_regs(priv, 0x0009f, bw_params1[i], 5); | |
| 113 | + if (ret) | |
| 114 | + goto error; | |
| 115 | + | |
| 116 | + ret = cxd2820r_wr_reg_mask(priv, 0x000d7, bw_param << 6, 0xc0); | |
| 117 | + if (ret) | |
| 118 | + goto error; | |
| 119 | + | |
| 120 | + ret = cxd2820r_wr_regs(priv, 0x000d9, bw_params2[i], 2); | |
| 121 | + if (ret) | |
| 122 | + goto error; | |
| 123 | + | |
| 124 | + ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08); | |
| 125 | + if (ret) | |
| 126 | + goto error; | |
| 127 | + | |
| 128 | + ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01); | |
| 129 | + if (ret) | |
| 130 | + goto error; | |
| 131 | + | |
| 132 | + return ret; | |
| 133 | +error: | |
| 134 | + dbg("%s: failed:%d", __func__, ret); | |
| 135 | + return ret; | |
| 136 | +} | |
| 137 | + | |
| 138 | +int cxd2820r_get_frontend_t(struct dvb_frontend *fe, | |
| 139 | + struct dvb_frontend_parameters *p) | |
| 140 | +{ | |
| 141 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 142 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 143 | + int ret; | |
| 144 | + u8 buf[2]; | |
| 145 | + | |
| 146 | + ret = cxd2820r_rd_regs(priv, 0x0002f, buf, sizeof(buf)); | |
| 147 | + if (ret) | |
| 148 | + goto error; | |
| 149 | + | |
| 150 | + switch ((buf[0] >> 6) & 0x03) { | |
| 151 | + case 0: | |
| 152 | + c->modulation = QPSK; | |
| 153 | + break; | |
| 154 | + case 1: | |
| 155 | + c->modulation = QAM_16; | |
| 156 | + break; | |
| 157 | + case 2: | |
| 158 | + c->modulation = QAM_64; | |
| 159 | + break; | |
| 160 | + } | |
| 161 | + | |
| 162 | + switch ((buf[1] >> 1) & 0x03) { | |
| 163 | + case 0: | |
| 164 | + c->transmission_mode = TRANSMISSION_MODE_2K; | |
| 165 | + break; | |
| 166 | + case 1: | |
| 167 | + c->transmission_mode = TRANSMISSION_MODE_8K; | |
| 168 | + break; | |
| 169 | + } | |
| 170 | + | |
| 171 | + switch ((buf[1] >> 3) & 0x03) { | |
| 172 | + case 0: | |
| 173 | + c->guard_interval = GUARD_INTERVAL_1_32; | |
| 174 | + break; | |
| 175 | + case 1: | |
| 176 | + c->guard_interval = GUARD_INTERVAL_1_16; | |
| 177 | + break; | |
| 178 | + case 2: | |
| 179 | + c->guard_interval = GUARD_INTERVAL_1_8; | |
| 180 | + break; | |
| 181 | + case 3: | |
| 182 | + c->guard_interval = GUARD_INTERVAL_1_4; | |
| 183 | + break; | |
| 184 | + } | |
| 185 | + | |
| 186 | + switch ((buf[0] >> 3) & 0x07) { | |
| 187 | + case 0: | |
| 188 | + c->hierarchy = HIERARCHY_NONE; | |
| 189 | + break; | |
| 190 | + case 1: | |
| 191 | + c->hierarchy = HIERARCHY_1; | |
| 192 | + break; | |
| 193 | + case 2: | |
| 194 | + c->hierarchy = HIERARCHY_2; | |
| 195 | + break; | |
| 196 | + case 3: | |
| 197 | + c->hierarchy = HIERARCHY_4; | |
| 198 | + break; | |
| 199 | + } | |
| 200 | + | |
| 201 | + switch ((buf[0] >> 0) & 0x07) { | |
| 202 | + case 0: | |
| 203 | + c->code_rate_HP = FEC_1_2; | |
| 204 | + break; | |
| 205 | + case 1: | |
| 206 | + c->code_rate_HP = FEC_2_3; | |
| 207 | + break; | |
| 208 | + case 2: | |
| 209 | + c->code_rate_HP = FEC_3_4; | |
| 210 | + break; | |
| 211 | + case 3: | |
| 212 | + c->code_rate_HP = FEC_5_6; | |
| 213 | + break; | |
| 214 | + case 4: | |
| 215 | + c->code_rate_HP = FEC_7_8; | |
| 216 | + break; | |
| 217 | + } | |
| 218 | + | |
| 219 | + switch ((buf[1] >> 5) & 0x07) { | |
| 220 | + case 0: | |
| 221 | + c->code_rate_LP = FEC_1_2; | |
| 222 | + break; | |
| 223 | + case 1: | |
| 224 | + c->code_rate_LP = FEC_2_3; | |
| 225 | + break; | |
| 226 | + case 2: | |
| 227 | + c->code_rate_LP = FEC_3_4; | |
| 228 | + break; | |
| 229 | + case 3: | |
| 230 | + c->code_rate_LP = FEC_5_6; | |
| 231 | + break; | |
| 232 | + case 4: | |
| 233 | + c->code_rate_LP = FEC_7_8; | |
| 234 | + break; | |
| 235 | + } | |
| 236 | + | |
| 237 | + ret = cxd2820r_rd_reg(priv, 0x007c6, &buf[0]); | |
| 238 | + if (ret) | |
| 239 | + goto error; | |
| 240 | + | |
| 241 | + switch ((buf[0] >> 0) & 0x01) { | |
| 242 | + case 0: | |
| 243 | + c->inversion = INVERSION_OFF; | |
| 244 | + break; | |
| 245 | + case 1: | |
| 246 | + c->inversion = INVERSION_ON; | |
| 247 | + break; | |
| 248 | + } | |
| 249 | + | |
| 250 | + return ret; | |
| 251 | +error: | |
| 252 | + dbg("%s: failed:%d", __func__, ret); | |
| 253 | + return ret; | |
| 254 | +} | |
| 255 | + | |
| 256 | +int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber) | |
| 257 | +{ | |
| 258 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 259 | + int ret; | |
| 260 | + u8 buf[3], start_ber = 0; | |
| 261 | + *ber = 0; | |
| 262 | + | |
| 263 | + if (priv->ber_running) { | |
| 264 | + ret = cxd2820r_rd_regs(priv, 0x00076, buf, sizeof(buf)); | |
| 265 | + if (ret) | |
| 266 | + goto error; | |
| 267 | + | |
| 268 | + if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) { | |
| 269 | + *ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0]; | |
| 270 | + start_ber = 1; | |
| 271 | + } | |
| 272 | + } else { | |
| 273 | + priv->ber_running = 1; | |
| 274 | + start_ber = 1; | |
| 275 | + } | |
| 276 | + | |
| 277 | + if (start_ber) { | |
| 278 | + /* (re)start BER */ | |
| 279 | + ret = cxd2820r_wr_reg(priv, 0x00079, 0x01); | |
| 280 | + if (ret) | |
| 281 | + goto error; | |
| 282 | + } | |
| 283 | + | |
| 284 | + return ret; | |
| 285 | +error: | |
| 286 | + dbg("%s: failed:%d", __func__, ret); | |
| 287 | + return ret; | |
| 288 | +} | |
| 289 | + | |
| 290 | +int cxd2820r_read_signal_strength_t(struct dvb_frontend *fe, | |
| 291 | + u16 *strength) | |
| 292 | +{ | |
| 293 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 294 | + int ret; | |
| 295 | + u8 buf[2]; | |
| 296 | + u16 tmp; | |
| 297 | + | |
| 298 | + ret = cxd2820r_rd_regs(priv, 0x00026, buf, sizeof(buf)); | |
| 299 | + if (ret) | |
| 300 | + goto error; | |
| 301 | + | |
| 302 | + tmp = (buf[0] & 0x0f) << 8 | buf[1]; | |
| 303 | + tmp = ~tmp & 0x0fff; | |
| 304 | + | |
| 305 | + /* scale value to 0x0000-0xffff from 0x0000-0x0fff */ | |
| 306 | + *strength = tmp * 0xffff / 0x0fff; | |
| 307 | + | |
| 308 | + return ret; | |
| 309 | +error: | |
| 310 | + dbg("%s: failed:%d", __func__, ret); | |
| 311 | + return ret; | |
| 312 | +} | |
| 313 | + | |
| 314 | +int cxd2820r_read_snr_t(struct dvb_frontend *fe, u16 *snr) | |
| 315 | +{ | |
| 316 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 317 | + int ret; | |
| 318 | + u8 buf[2]; | |
| 319 | + u16 tmp; | |
| 320 | + /* report SNR in dB * 10 */ | |
| 321 | + | |
| 322 | + ret = cxd2820r_rd_regs(priv, 0x00028, buf, sizeof(buf)); | |
| 323 | + if (ret) | |
| 324 | + goto error; | |
| 325 | + | |
| 326 | + tmp = (buf[0] & 0x1f) << 8 | buf[1]; | |
| 327 | + #define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */ | |
| 328 | + if (tmp) | |
| 329 | + *snr = (intlog10(tmp) - CXD2820R_LOG10_8_24) / ((1 << 24) | |
| 330 | + / 100); | |
| 331 | + else | |
| 332 | + *snr = 0; | |
| 333 | + | |
| 334 | + dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp); | |
| 335 | + | |
| 336 | + return ret; | |
| 337 | +error: | |
| 338 | + dbg("%s: failed:%d", __func__, ret); | |
| 339 | + return ret; | |
| 340 | +} | |
| 341 | + | |
| 342 | +int cxd2820r_read_ucblocks_t(struct dvb_frontend *fe, u32 *ucblocks) | |
| 343 | +{ | |
| 344 | + *ucblocks = 0; | |
| 345 | + /* no way to read ? */ | |
| 346 | + return 0; | |
| 347 | +} | |
| 348 | + | |
| 349 | +int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status) | |
| 350 | +{ | |
| 351 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 352 | + int ret; | |
| 353 | + u8 buf[4]; | |
| 354 | + *status = 0; | |
| 355 | + | |
| 356 | + ret = cxd2820r_rd_reg(priv, 0x00010, &buf[0]); | |
| 357 | + if (ret) | |
| 358 | + goto error; | |
| 359 | + | |
| 360 | + if ((buf[0] & 0x07) == 6) { | |
| 361 | + ret = cxd2820r_rd_reg(priv, 0x00073, &buf[1]); | |
| 362 | + if (ret) | |
| 363 | + goto error; | |
| 364 | + | |
| 365 | + if (((buf[1] >> 3) & 0x01) == 1) { | |
| 366 | + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | | |
| 367 | + FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | |
| 368 | + } else { | |
| 369 | + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | | |
| 370 | + FE_HAS_VITERBI | FE_HAS_SYNC; | |
| 371 | + } | |
| 372 | + } else { | |
| 373 | + ret = cxd2820r_rd_reg(priv, 0x00014, &buf[2]); | |
| 374 | + if (ret) | |
| 375 | + goto error; | |
| 376 | + | |
| 377 | + if ((buf[2] & 0x0f) >= 4) { | |
| 378 | + ret = cxd2820r_rd_reg(priv, 0x00a14, &buf[3]); | |
| 379 | + if (ret) | |
| 380 | + goto error; | |
| 381 | + | |
| 382 | + if (((buf[3] >> 4) & 0x01) == 1) | |
| 383 | + *status |= FE_HAS_SIGNAL; | |
| 384 | + } | |
| 385 | + } | |
| 386 | + | |
| 387 | + dbg("%s: lock=%02x %02x %02x %02x", __func__, | |
| 388 | + buf[0], buf[1], buf[2], buf[3]); | |
| 389 | + | |
| 390 | + return ret; | |
| 391 | +error: | |
| 392 | + dbg("%s: failed:%d", __func__, ret); | |
| 393 | + return ret; | |
| 394 | +} | |
| 395 | + | |
| 396 | +int cxd2820r_init_t(struct dvb_frontend *fe) | |
| 397 | +{ | |
| 398 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 399 | + int ret; | |
| 400 | + | |
| 401 | + ret = cxd2820r_wr_reg(priv, 0x00085, 0x07); | |
| 402 | + if (ret) | |
| 403 | + goto error; | |
| 404 | + | |
| 405 | + return ret; | |
| 406 | +error: | |
| 407 | + dbg("%s: failed:%d", __func__, ret); | |
| 408 | + return ret; | |
| 409 | +} | |
| 410 | + | |
| 411 | +int cxd2820r_sleep_t(struct dvb_frontend *fe) | |
| 412 | +{ | |
| 413 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 414 | + int ret, i; | |
| 415 | + struct reg_val_mask tab[] = { | |
| 416 | + { 0x000ff, 0x1f, 0xff }, | |
| 417 | + { 0x00085, 0x00, 0xff }, | |
| 418 | + { 0x00088, 0x01, 0xff }, | |
| 419 | + { 0x00081, 0x00, 0xff }, | |
| 420 | + { 0x00080, 0x00, 0xff }, | |
| 421 | + }; | |
| 422 | + | |
| 423 | + dbg("%s", __func__); | |
| 424 | + | |
| 425 | + priv->delivery_system = SYS_UNDEFINED; | |
| 426 | + | |
| 427 | + for (i = 0; i < ARRAY_SIZE(tab); i++) { | |
| 428 | + ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val, | |
| 429 | + tab[i].mask); | |
| 430 | + if (ret) | |
| 431 | + goto error; | |
| 432 | + } | |
| 433 | + | |
| 434 | + return ret; | |
| 435 | +error: | |
| 436 | + dbg("%s: failed:%d", __func__, ret); | |
| 437 | + return ret; | |
| 438 | +} | |
| 439 | + | |
| 440 | +int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe, | |
| 441 | + struct dvb_frontend_tune_settings *s) | |
| 442 | +{ | |
| 443 | + s->min_delay_ms = 500; | |
| 444 | + s->step_size = fe->ops.info.frequency_stepsize * 2; | |
| 445 | + s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; | |
| 446 | + | |
| 447 | + return 0; | |
| 448 | +} | |
| 449 | + | |
| @@ -0,0 +1,423 @@ | ||
| 1 | +/* | |
| 2 | + * Sony CXD2820R demodulator driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License along | |
| 17 | + * with this program; if not, write to the Free Software Foundation, Inc., | |
| 18 | + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + */ | |
| 20 | + | |
| 21 | + | |
| 22 | +#include "cxd2820r_priv.h" | |
| 23 | + | |
| 24 | +int cxd2820r_set_frontend_t2(struct dvb_frontend *fe, | |
| 25 | + struct dvb_frontend_parameters *params) | |
| 26 | +{ | |
| 27 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 28 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 29 | + int ret, i; | |
| 30 | + u32 if_khz, if_ctl; | |
| 31 | + u64 num; | |
| 32 | + u8 buf[3], bw_param; | |
| 33 | + u8 bw_params1[][5] = { | |
| 34 | + { 0x1c, 0xb3, 0x33, 0x33, 0x33 }, /* 5 MHz */ | |
| 35 | + { 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */ | |
| 36 | + { 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */ | |
| 37 | + { 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */ | |
| 38 | + }; | |
| 39 | + struct reg_val_mask tab[] = { | |
| 40 | + { 0x00080, 0x02, 0xff }, | |
| 41 | + { 0x00081, 0x20, 0xff }, | |
| 42 | + { 0x00085, 0x07, 0xff }, | |
| 43 | + { 0x00088, 0x01, 0xff }, | |
| 44 | + { 0x02069, 0x01, 0xff }, | |
| 45 | + | |
| 46 | + { 0x0207f, 0x2a, 0xff }, | |
| 47 | + { 0x02082, 0x0a, 0xff }, | |
| 48 | + { 0x02083, 0x0a, 0xff }, | |
| 49 | + { 0x020cb, priv->cfg.if_agc_polarity << 6, 0x40 }, | |
| 50 | + { 0x02070, priv->cfg.ts_mode, 0xff }, | |
| 51 | + { 0x020b5, priv->cfg.spec_inv << 4, 0x10 }, | |
| 52 | + { 0x02567, 0x07, 0x0f }, | |
| 53 | + { 0x02569, 0x03, 0x03 }, | |
| 54 | + { 0x02595, 0x1a, 0xff }, | |
| 55 | + { 0x02596, 0x50, 0xff }, | |
| 56 | + { 0x02a8c, 0x00, 0xff }, | |
| 57 | + { 0x02a8d, 0x34, 0xff }, | |
| 58 | + { 0x02a45, 0x06, 0x07 }, | |
| 59 | + { 0x03f10, 0x0d, 0xff }, | |
| 60 | + { 0x03f11, 0x02, 0xff }, | |
| 61 | + { 0x03f12, 0x01, 0xff }, | |
| 62 | + { 0x03f23, 0x2c, 0xff }, | |
| 63 | + { 0x03f51, 0x13, 0xff }, | |
| 64 | + { 0x03f52, 0x01, 0xff }, | |
| 65 | + { 0x03f53, 0x00, 0xff }, | |
| 66 | + { 0x027e6, 0x14, 0xff }, | |
| 67 | + { 0x02786, 0x02, 0x07 }, | |
| 68 | + { 0x02787, 0x40, 0xe0 }, | |
| 69 | + { 0x027ef, 0x10, 0x18 }, | |
| 70 | + }; | |
| 71 | + | |
| 72 | + dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz); | |
| 73 | + | |
| 74 | + /* update GPIOs */ | |
| 75 | + ret = cxd2820r_gpio(fe); | |
| 76 | + if (ret) | |
| 77 | + goto error; | |
| 78 | + | |
| 79 | + /* program tuner */ | |
| 80 | + if (fe->ops.tuner_ops.set_params) | |
| 81 | + fe->ops.tuner_ops.set_params(fe, params); | |
| 82 | + | |
| 83 | + if (priv->delivery_system != SYS_DVBT2) { | |
| 84 | + for (i = 0; i < ARRAY_SIZE(tab); i++) { | |
| 85 | + ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, | |
| 86 | + tab[i].val, tab[i].mask); | |
| 87 | + if (ret) | |
| 88 | + goto error; | |
| 89 | + } | |
| 90 | + } | |
| 91 | + | |
| 92 | + priv->delivery_system = SYS_DVBT2; | |
| 93 | + | |
| 94 | + switch (c->bandwidth_hz) { | |
| 95 | + case 5000000: | |
| 96 | + if_khz = priv->cfg.if_dvbt2_5; | |
| 97 | + i = 0; | |
| 98 | + bw_param = 3; | |
| 99 | + break; | |
| 100 | + case 6000000: | |
| 101 | + if_khz = priv->cfg.if_dvbt2_6; | |
| 102 | + i = 1; | |
| 103 | + bw_param = 2; | |
| 104 | + break; | |
| 105 | + case 7000000: | |
| 106 | + if_khz = priv->cfg.if_dvbt2_7; | |
| 107 | + i = 2; | |
| 108 | + bw_param = 1; | |
| 109 | + break; | |
| 110 | + case 8000000: | |
| 111 | + if_khz = priv->cfg.if_dvbt2_8; | |
| 112 | + i = 3; | |
| 113 | + bw_param = 0; | |
| 114 | + break; | |
| 115 | + default: | |
| 116 | + return -EINVAL; | |
| 117 | + } | |
| 118 | + | |
| 119 | + num = if_khz; | |
| 120 | + num *= 0x1000000; | |
| 121 | + if_ctl = cxd2820r_div_u64_round_closest(num, 41000); | |
| 122 | + buf[0] = ((if_ctl >> 16) & 0xff); | |
| 123 | + buf[1] = ((if_ctl >> 8) & 0xff); | |
| 124 | + buf[2] = ((if_ctl >> 0) & 0xff); | |
| 125 | + | |
| 126 | + ret = cxd2820r_wr_regs(priv, 0x020b6, buf, 3); | |
| 127 | + if (ret) | |
| 128 | + goto error; | |
| 129 | + | |
| 130 | + ret = cxd2820r_wr_regs(priv, 0x0209f, bw_params1[i], 5); | |
| 131 | + if (ret) | |
| 132 | + goto error; | |
| 133 | + | |
| 134 | + ret = cxd2820r_wr_reg_mask(priv, 0x020d7, bw_param << 6, 0xc0); | |
| 135 | + if (ret) | |
| 136 | + goto error; | |
| 137 | + | |
| 138 | + ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08); | |
| 139 | + if (ret) | |
| 140 | + goto error; | |
| 141 | + | |
| 142 | + ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01); | |
| 143 | + if (ret) | |
| 144 | + goto error; | |
| 145 | + | |
| 146 | + return ret; | |
| 147 | +error: | |
| 148 | + dbg("%s: failed:%d", __func__, ret); | |
| 149 | + return ret; | |
| 150 | + | |
| 151 | +} | |
| 152 | + | |
| 153 | +int cxd2820r_get_frontend_t2(struct dvb_frontend *fe, | |
| 154 | + struct dvb_frontend_parameters *p) | |
| 155 | +{ | |
| 156 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 157 | + struct dtv_frontend_properties *c = &fe->dtv_property_cache; | |
| 158 | + int ret; | |
| 159 | + u8 buf[2]; | |
| 160 | + | |
| 161 | + ret = cxd2820r_rd_regs(priv, 0x0205c, buf, 2); | |
| 162 | + if (ret) | |
| 163 | + goto error; | |
| 164 | + | |
| 165 | + switch ((buf[0] >> 0) & 0x07) { | |
| 166 | + case 0: | |
| 167 | + c->transmission_mode = TRANSMISSION_MODE_2K; | |
| 168 | + break; | |
| 169 | + case 1: | |
| 170 | + c->transmission_mode = TRANSMISSION_MODE_8K; | |
| 171 | + break; | |
| 172 | + case 2: | |
| 173 | + c->transmission_mode = TRANSMISSION_MODE_4K; | |
| 174 | + break; | |
| 175 | + case 3: | |
| 176 | + c->transmission_mode = TRANSMISSION_MODE_1K; | |
| 177 | + break; | |
| 178 | + case 4: | |
| 179 | + c->transmission_mode = TRANSMISSION_MODE_16K; | |
| 180 | + break; | |
| 181 | + case 5: | |
| 182 | + c->transmission_mode = TRANSMISSION_MODE_32K; | |
| 183 | + break; | |
| 184 | + } | |
| 185 | + | |
| 186 | + switch ((buf[1] >> 4) & 0x07) { | |
| 187 | + case 0: | |
| 188 | + c->guard_interval = GUARD_INTERVAL_1_32; | |
| 189 | + break; | |
| 190 | + case 1: | |
| 191 | + c->guard_interval = GUARD_INTERVAL_1_16; | |
| 192 | + break; | |
| 193 | + case 2: | |
| 194 | + c->guard_interval = GUARD_INTERVAL_1_8; | |
| 195 | + break; | |
| 196 | + case 3: | |
| 197 | + c->guard_interval = GUARD_INTERVAL_1_4; | |
| 198 | + break; | |
| 199 | + case 4: | |
| 200 | + c->guard_interval = GUARD_INTERVAL_1_128; | |
| 201 | + break; | |
| 202 | + case 5: | |
| 203 | + c->guard_interval = GUARD_INTERVAL_19_128; | |
| 204 | + break; | |
| 205 | + case 6: | |
| 206 | + c->guard_interval = GUARD_INTERVAL_19_256; | |
| 207 | + break; | |
| 208 | + } | |
| 209 | + | |
| 210 | + ret = cxd2820r_rd_regs(priv, 0x0225b, buf, 2); | |
| 211 | + if (ret) | |
| 212 | + goto error; | |
| 213 | + | |
| 214 | + switch ((buf[0] >> 0) & 0x07) { | |
| 215 | + case 0: | |
| 216 | + c->fec_inner = FEC_1_2; | |
| 217 | + break; | |
| 218 | + case 1: | |
| 219 | + c->fec_inner = FEC_3_5; | |
| 220 | + break; | |
| 221 | + case 2: | |
| 222 | + c->fec_inner = FEC_2_3; | |
| 223 | + break; | |
| 224 | + case 3: | |
| 225 | + c->fec_inner = FEC_3_4; | |
| 226 | + break; | |
| 227 | + case 4: | |
| 228 | + c->fec_inner = FEC_4_5; | |
| 229 | + break; | |
| 230 | + case 5: | |
| 231 | + c->fec_inner = FEC_5_6; | |
| 232 | + break; | |
| 233 | + } | |
| 234 | + | |
| 235 | + switch ((buf[1] >> 0) & 0x07) { | |
| 236 | + case 0: | |
| 237 | + c->modulation = QPSK; | |
| 238 | + break; | |
| 239 | + case 1: | |
| 240 | + c->modulation = QAM_16; | |
| 241 | + break; | |
| 242 | + case 2: | |
| 243 | + c->modulation = QAM_64; | |
| 244 | + break; | |
| 245 | + case 3: | |
| 246 | + c->modulation = QAM_256; | |
| 247 | + break; | |
| 248 | + } | |
| 249 | + | |
| 250 | + ret = cxd2820r_rd_reg(priv, 0x020b5, &buf[0]); | |
| 251 | + if (ret) | |
| 252 | + goto error; | |
| 253 | + | |
| 254 | + switch ((buf[0] >> 4) & 0x01) { | |
| 255 | + case 0: | |
| 256 | + c->inversion = INVERSION_OFF; | |
| 257 | + break; | |
| 258 | + case 1: | |
| 259 | + c->inversion = INVERSION_ON; | |
| 260 | + break; | |
| 261 | + } | |
| 262 | + | |
| 263 | + return ret; | |
| 264 | +error: | |
| 265 | + dbg("%s: failed:%d", __func__, ret); | |
| 266 | + return ret; | |
| 267 | +} | |
| 268 | + | |
| 269 | +int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status) | |
| 270 | +{ | |
| 271 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 272 | + int ret; | |
| 273 | + u8 buf[1]; | |
| 274 | + *status = 0; | |
| 275 | + | |
| 276 | + ret = cxd2820r_rd_reg(priv, 0x02010 , &buf[0]); | |
| 277 | + if (ret) | |
| 278 | + goto error; | |
| 279 | + | |
| 280 | + if ((buf[0] & 0x07) == 6) { | |
| 281 | + if (((buf[0] >> 5) & 0x01) == 1) { | |
| 282 | + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | | |
| 283 | + FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | |
| 284 | + } else { | |
| 285 | + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | | |
| 286 | + FE_HAS_VITERBI | FE_HAS_SYNC; | |
| 287 | + } | |
| 288 | + } | |
| 289 | + | |
| 290 | + dbg("%s: lock=%02x", __func__, buf[0]); | |
| 291 | + | |
| 292 | + return ret; | |
| 293 | +error: | |
| 294 | + dbg("%s: failed:%d", __func__, ret); | |
| 295 | + return ret; | |
| 296 | +} | |
| 297 | + | |
| 298 | +int cxd2820r_read_ber_t2(struct dvb_frontend *fe, u32 *ber) | |
| 299 | +{ | |
| 300 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 301 | + int ret; | |
| 302 | + u8 buf[4]; | |
| 303 | + unsigned int errbits; | |
| 304 | + *ber = 0; | |
| 305 | + /* FIXME: correct calculation */ | |
| 306 | + | |
| 307 | + ret = cxd2820r_rd_regs(priv, 0x02039, buf, sizeof(buf)); | |
| 308 | + if (ret) | |
| 309 | + goto error; | |
| 310 | + | |
| 311 | + if ((buf[0] >> 4) & 0x01) { | |
| 312 | + errbits = (buf[0] & 0x0f) << 24 | buf[1] << 16 | | |
| 313 | + buf[2] << 8 | buf[3]; | |
| 314 | + | |
| 315 | + if (errbits) | |
| 316 | + *ber = errbits * 64 / 16588800; | |
| 317 | + } | |
| 318 | + | |
| 319 | + return ret; | |
| 320 | +error: | |
| 321 | + dbg("%s: failed:%d", __func__, ret); | |
| 322 | + return ret; | |
| 323 | +} | |
| 324 | + | |
| 325 | +int cxd2820r_read_signal_strength_t2(struct dvb_frontend *fe, | |
| 326 | + u16 *strength) | |
| 327 | +{ | |
| 328 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 329 | + int ret; | |
| 330 | + u8 buf[2]; | |
| 331 | + u16 tmp; | |
| 332 | + | |
| 333 | + ret = cxd2820r_rd_regs(priv, 0x02026, buf, sizeof(buf)); | |
| 334 | + if (ret) | |
| 335 | + goto error; | |
| 336 | + | |
| 337 | + tmp = (buf[0] & 0x0f) << 8 | buf[1]; | |
| 338 | + tmp = ~tmp & 0x0fff; | |
| 339 | + | |
| 340 | + /* scale value to 0x0000-0xffff from 0x0000-0x0fff */ | |
| 341 | + *strength = tmp * 0xffff / 0x0fff; | |
| 342 | + | |
| 343 | + return ret; | |
| 344 | +error: | |
| 345 | + dbg("%s: failed:%d", __func__, ret); | |
| 346 | + return ret; | |
| 347 | +} | |
| 348 | + | |
| 349 | +int cxd2820r_read_snr_t2(struct dvb_frontend *fe, u16 *snr) | |
| 350 | +{ | |
| 351 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 352 | + int ret; | |
| 353 | + u8 buf[2]; | |
| 354 | + u16 tmp; | |
| 355 | + /* report SNR in dB * 10 */ | |
| 356 | + | |
| 357 | + ret = cxd2820r_rd_regs(priv, 0x02028, buf, sizeof(buf)); | |
| 358 | + if (ret) | |
| 359 | + goto error; | |
| 360 | + | |
| 361 | + tmp = (buf[0] & 0x0f) << 8 | buf[1]; | |
| 362 | + #define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */ | |
| 363 | + if (tmp) | |
| 364 | + *snr = (intlog10(tmp) - CXD2820R_LOG10_8_24) / ((1 << 24) | |
| 365 | + / 100); | |
| 366 | + else | |
| 367 | + *snr = 0; | |
| 368 | + | |
| 369 | + dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp); | |
| 370 | + | |
| 371 | + return ret; | |
| 372 | +error: | |
| 373 | + dbg("%s: failed:%d", __func__, ret); | |
| 374 | + return ret; | |
| 375 | +} | |
| 376 | + | |
| 377 | +int cxd2820r_read_ucblocks_t2(struct dvb_frontend *fe, u32 *ucblocks) | |
| 378 | +{ | |
| 379 | + *ucblocks = 0; | |
| 380 | + /* no way to read ? */ | |
| 381 | + return 0; | |
| 382 | +} | |
| 383 | + | |
| 384 | +int cxd2820r_sleep_t2(struct dvb_frontend *fe) | |
| 385 | +{ | |
| 386 | + struct cxd2820r_priv *priv = fe->demodulator_priv; | |
| 387 | + int ret, i; | |
| 388 | + struct reg_val_mask tab[] = { | |
| 389 | + { 0x000ff, 0x1f, 0xff }, | |
| 390 | + { 0x00085, 0x00, 0xff }, | |
| 391 | + { 0x00088, 0x01, 0xff }, | |
| 392 | + { 0x02069, 0x00, 0xff }, | |
| 393 | + { 0x00081, 0x00, 0xff }, | |
| 394 | + { 0x00080, 0x00, 0xff }, | |
| 395 | + }; | |
| 396 | + | |
| 397 | + dbg("%s", __func__); | |
| 398 | + | |
| 399 | + for (i = 0; i < ARRAY_SIZE(tab); i++) { | |
| 400 | + ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val, | |
| 401 | + tab[i].mask); | |
| 402 | + if (ret) | |
| 403 | + goto error; | |
| 404 | + } | |
| 405 | + | |
| 406 | + priv->delivery_system = SYS_UNDEFINED; | |
| 407 | + | |
| 408 | + return ret; | |
| 409 | +error: | |
| 410 | + dbg("%s: failed:%d", __func__, ret); | |
| 411 | + return ret; | |
| 412 | +} | |
| 413 | + | |
| 414 | +int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe, | |
| 415 | + struct dvb_frontend_tune_settings *s) | |
| 416 | +{ | |
| 417 | + s->min_delay_ms = 1500; | |
| 418 | + s->step_size = fe->ops.info.frequency_stepsize * 2; | |
| 419 | + s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; | |
| 420 | + | |
| 421 | + return 0; | |
| 422 | +} | |
| 423 | + | |
| @@ -73,27 +73,47 @@ struct dib0070_state { · 72 unmodified lines | ||
| 73 | 73 | |
| 74 | 74 | u8 wbd_gain_current; |
| 75 | 75 | u16 wbd_offset_3_3[2]; |
| 76 | + | |
| 77 | + /* for the I2C transfer */ | |
| 78 | + struct i2c_msg msg[2]; | |
| 79 | + u8 i2c_write_buffer[3]; | |
| 80 | + u8 i2c_read_buffer[2]; | |
| 76 | 81 | }; |
| 77 | 82 | |
| 78 | 83 | static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) |
| 79 | 84 | { |
| 80 | − u8 b[2]; | |
| 81 | − struct i2c_msg msg[2] = { | |
| 82 | − { .addr = state->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 }, | |
| 83 | − { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 }, | |
| 84 | − }; | |
| 85 | − if (i2c_transfer(state->i2c, msg, 2) != 2) { | |
| 85 | + state->i2c_write_buffer[0] = reg; | |
| 86 | + | |
| 87 | + memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); | |
| 88 | + state->msg[0].addr = state->cfg->i2c_address; | |
| 89 | + state->msg[0].flags = 0; | |
| 90 | + state->msg[0].buf = state->i2c_write_buffer; | |
| 91 | + state->msg[0].len = 1; | |
| 92 | + state->msg[1].addr = state->cfg->i2c_address; | |
| 93 | + state->msg[1].flags = I2C_M_RD; | |
| 94 | + state->msg[1].buf = state->i2c_read_buffer; | |
| 95 | + state->msg[1].len = 2; | |
| 96 | + | |
| 97 | + if (i2c_transfer(state->i2c, state->msg, 2) != 2) { | |
| 86 | 98 | printk(KERN_WARNING "DiB0070 I2C read failed\n"); |
| 87 | 99 | return 0; |
| 88 | 100 | } |
| 89 | − return (b[0] << 8) | b[1]; | |
| 101 | + return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; | |
| 90 | 102 | } |
| 91 | 103 | |
| 92 | 104 | static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) |
| 93 | 105 | { |
| 94 | − u8 b[3] = { reg, val >> 8, val & 0xff }; | |
| 95 | − struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 }; | |
| 96 | − if (i2c_transfer(state->i2c, &msg, 1) != 1) { | |
| 106 | + state->i2c_write_buffer[0] = reg; | |
| 107 | + state->i2c_write_buffer[1] = val >> 8; | |
| 108 | + state->i2c_write_buffer[2] = val & 0xff; | |
| 109 | + | |
| 110 | + memset(state->msg, 0, sizeof(struct i2c_msg)); | |
| 111 | + state->msg[0].addr = state->cfg->i2c_address; | |
| 112 | + state->msg[0].flags = 0; | |
| 113 | + state->msg[0].buf = state->i2c_write_buffer; | |
| 114 | + state->msg[0].len = 3; | |
| 115 | + | |
| 116 | + if (i2c_transfer(state->i2c, state->msg, 1) != 1) { | |
| 97 | 117 | printk(KERN_WARNING "DiB0070 I2C write failed\n"); |
| 98 | 118 | return -EREMOTEIO; |
| 99 | 119 | } |
| @@ -191,6 +191,11 @@ struct dib0090_state { · 190 unmodified lines | ||
| 191 | 191 | u8 wbd_calibration_gain; |
| 192 | 192 | const struct dib0090_wbd_slope *current_wbd_table; |
| 193 | 193 | u16 wbdmux; |
| 194 | + | |
| 195 | + /* for the I2C transfer */ | |
| 196 | + struct i2c_msg msg[2]; | |
| 197 | + u8 i2c_write_buffer[3]; | |
| 198 | + u8 i2c_read_buffer[2]; | |
| 194 | 199 | }; |
| 195 | 200 | |
| 196 | 201 | struct dib0090_fw_state { |
| @@ -198,27 +203,48 @@ struct dib0090_fw_state { · 1 unmodified line | ||
| 198 | 203 | struct dvb_frontend *fe; |
| 199 | 204 | struct dib0090_identity identity; |
| 200 | 205 | const struct dib0090_config *config; |
| 206 | + | |
| 207 | + /* for the I2C transfer */ | |
| 208 | + struct i2c_msg msg; | |
| 209 | + u8 i2c_write_buffer[2]; | |
| 210 | + u8 i2c_read_buffer[2]; | |
| 201 | 211 | }; |
| 202 | 212 | |
| 203 | 213 | static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) |
| 204 | 214 | { |
| 205 | − u8 b[2]; | |
| 206 | − struct i2c_msg msg[2] = { | |
| 207 | − {.addr = state->config->i2c_address, .flags = 0, .buf = ®, .len = 1}, | |
| 208 | − {.addr = state->config->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2}, | |
| 209 | − }; | |
| 210 | − if (i2c_transfer(state->i2c, msg, 2) != 2) { | |
| 215 | + state->i2c_write_buffer[0] = reg; | |
| 216 | + | |
| 217 | + memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); | |
| 218 | + state->msg[0].addr = state->config->i2c_address; | |
| 219 | + state->msg[0].flags = 0; | |
| 220 | + state->msg[0].buf = state->i2c_write_buffer; | |
| 221 | + state->msg[0].len = 1; | |
| 222 | + state->msg[1].addr = state->config->i2c_address; | |
| 223 | + state->msg[1].flags = I2C_M_RD; | |
| 224 | + state->msg[1].buf = state->i2c_read_buffer; | |
| 225 | + state->msg[1].len = 2; | |
| 226 | + | |
| 227 | + if (i2c_transfer(state->i2c, state->msg, 2) != 2) { | |
| 211 | 228 | printk(KERN_WARNING "DiB0090 I2C read failed\n"); |
| 212 | 229 | return 0; |
| 213 | 230 | } |
| 214 | − return (b[0] << 8) | b[1]; | |
| 231 | + | |
| 232 | + return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; | |
| 215 | 233 | } |
| 216 | 234 | |
| 217 | 235 | static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) |
| 218 | 236 | { |
| 219 | − u8 b[3] = { reg & 0xff, val >> 8, val & 0xff }; | |
| 220 | − struct i2c_msg msg = {.addr = state->config->i2c_address, .flags = 0, .buf = b, .len = 3 }; | |
| 221 | − if (i2c_transfer(state->i2c, &msg, 1) != 1) { | |
| 237 | + state->i2c_write_buffer[0] = reg & 0xff; | |
| 238 | + state->i2c_write_buffer[1] = val >> 8; | |
| 239 | + state->i2c_write_buffer[2] = val & 0xff; | |
| 240 | + | |
| 241 | + memset(state->msg, 0, sizeof(struct i2c_msg)); | |
| 242 | + state->msg[0].addr = state->config->i2c_address; | |
| 243 | + state->msg[0].flags = 0; | |
| 244 | + state->msg[0].buf = state->i2c_write_buffer; | |
| 245 | + state->msg[0].len = 3; | |
| 246 | + | |
| 247 | + if (i2c_transfer(state->i2c, state->msg, 1) != 1) { | |
| 222 | 248 | printk(KERN_WARNING "DiB0090 I2C write failed\n"); |
| 223 | 249 | return -EREMOTEIO; |
| 224 | 250 | } |
| @@ -227,20 +253,31 @@ static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) · 2 unmodified lines | ||
| 227 | 253 | |
| 228 | 254 | static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg) |
| 229 | 255 | { |
| 230 | − u8 b[2]; | |
| 231 | − struct i2c_msg msg = {.addr = reg, .flags = I2C_M_RD, .buf = b, .len = 2 }; | |
| 232 | − if (i2c_transfer(state->i2c, &msg, 1) != 1) { | |
| 256 | + state->i2c_write_buffer[0] = reg; | |
| 257 | + | |
| 258 | + memset(&state->msg, 0, sizeof(struct i2c_msg)); | |
| 259 | + state->msg.addr = reg; | |
| 260 | + state->msg.flags = I2C_M_RD; | |
| 261 | + state->msg.buf = state->i2c_read_buffer; | |
| 262 | + state->msg.len = 2; | |
| 263 | + if (i2c_transfer(state->i2c, &state->msg, 1) != 1) { | |
| 233 | 264 | printk(KERN_WARNING "DiB0090 I2C read failed\n"); |
| 234 | 265 | return 0; |
| 235 | 266 | } |
| 236 | − return (b[0] << 8) | b[1]; | |
| 267 | + return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; | |
| 237 | 268 | } |
| 238 | 269 | |
| 239 | 270 | static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val) |
| 240 | 271 | { |
| 241 | − u8 b[2] = { val >> 8, val & 0xff }; | |
| 242 | − struct i2c_msg msg = {.addr = reg, .flags = 0, .buf = b, .len = 2 }; | |
| 243 | − if (i2c_transfer(state->i2c, &msg, 1) != 1) { | |
| 272 | + state->i2c_write_buffer[0] = val >> 8; | |
| 273 | + state->i2c_write_buffer[1] = val & 0xff; | |
| 274 | + | |
| 275 | + memset(&state->msg, 0, sizeof(struct i2c_msg)); | |
| 276 | + state->msg.addr = reg; | |
| 277 | + state->msg.flags = 0; | |
| 278 | + state->msg.buf = state->i2c_write_buffer; | |
| 279 | + state->msg.len = 2; | |
| 280 | + if (i2c_transfer(state->i2c, &state->msg, 1) != 1) { | |
| 244 | 281 | printk(KERN_WARNING "DiB0090 I2C write failed\n"); |
| 245 | 282 | return -EREMOTEIO; |
| 246 | 283 | } |
| @@ -50,6 +50,11 @@ struct dib7000m_state { · 49 unmodified lines | ||
| 50 | 50 | u16 revision; |
| 51 | 51 | |
| 52 | 52 | u8 agc_state; |
| 53 | + | |
| 54 | + /* for the I2C transfer */ | |
| 55 | + struct i2c_msg msg[2]; | |
| 56 | + u8 i2c_write_buffer[4]; | |
| 57 | + u8 i2c_read_buffer[2]; | |
| 53 | 58 | }; |
| 54 | 59 | |
| 55 | 60 | enum dib7000m_power_mode { |
| @@ -64,29 +69,39 @@ enum dib7000m_power_mode { · 8 unmodified lines | ||
| 64 | 69 | |
| 65 | 70 | static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) |
| 66 | 71 | { |
| 67 | − u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff }; | |
| 68 | − u8 rb[2]; | |
| 69 | − struct i2c_msg msg[2] = { | |
| 70 | − { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 }, | |
| 71 | − { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 }, | |
| 72 | − }; | |
| 73 | − | |
| 74 | − if (i2c_transfer(state->i2c_adap, msg, 2) != 2) | |
| 72 | + state->i2c_write_buffer[0] = (reg >> 8) | 0x80; | |
| 73 | + state->i2c_write_buffer[1] = reg & 0xff; | |
| 74 | + | |
| 75 | + memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); | |
| 76 | + state->msg[0].addr = state->i2c_addr >> 1; | |
| 77 | + state->msg[0].flags = 0; | |
| 78 | + state->msg[0].buf = state->i2c_write_buffer; | |
| 79 | + state->msg[0].len = 2; | |
| 80 | + state->msg[1].addr = state->i2c_addr >> 1; | |
| 81 | + state->msg[1].flags = I2C_M_RD; | |
| 82 | + state->msg[1].buf = state->i2c_read_buffer; | |
| 83 | + state->msg[1].len = 2; | |
| 84 | + | |
| 85 | + if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2) | |
| 75 | 86 | dprintk("i2c read error on %d",reg); |
| 76 | 87 | |
| 77 | − return (rb[0] << 8) | rb[1]; | |
| 88 | + return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; | |
| 78 | 89 | } |
| 79 | 90 | |
| 80 | 91 | static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) |
| 81 | 92 | { |
| 82 | − u8 b[4] = { | |
| 83 | − (reg >> 8) & 0xff, reg & 0xff, | |
| 84 | − (val >> 8) & 0xff, val & 0xff, | |
| 85 | − }; | |
| 86 | − struct i2c_msg msg = { | |
| 87 | − .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 | |
| 88 | − }; | |
| 89 | − return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | |
| 93 | + state->i2c_write_buffer[0] = (reg >> 8) & 0xff; | |
| 94 | + state->i2c_write_buffer[1] = reg & 0xff; | |
| 95 | + state->i2c_write_buffer[2] = (val >> 8) & 0xff; | |
| 96 | + state->i2c_write_buffer[3] = val & 0xff; | |
| 97 | + | |
| 98 | + memset(&state->msg[0], 0, sizeof(struct i2c_msg)); | |
| 99 | + state->msg[0].addr = state->i2c_addr >> 1; | |
| 100 | + state->msg[0].flags = 0; | |
| 101 | + state->msg[0].buf = state->i2c_write_buffer; | |
| 102 | + state->msg[0].len = 4; | |
| 103 | + | |
| 104 | + return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; | |
| 90 | 105 | } |
| 91 | 106 | static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf) |
| 92 | 107 | { |
| @@ -63,6 +63,11 @@ struct dib7000p_state { · 62 unmodified lines | ||
| 63 | 63 | |
| 64 | 64 | u16 tuner_enable; |
| 65 | 65 | struct i2c_adapter dib7090_tuner_adap; |
| 66 | + | |
| 67 | + /* for the I2C transfer */ | |
| 68 | + struct i2c_msg msg[2]; | |
| 69 | + u8 i2c_write_buffer[4]; | |
| 70 | + u8 i2c_read_buffer[2]; | |
| 66 | 71 | }; |
| 67 | 72 | |
| 68 | 73 | enum dib7000p_power_mode { |
| @@ -76,29 +81,39 @@ static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff); · 7 unmodified lines | ||
| 76 | 81 | |
| 77 | 82 | static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) |
| 78 | 83 | { |
| 79 | − u8 wb[2] = { reg >> 8, reg & 0xff }; | |
| 80 | − u8 rb[2]; | |
| 81 | − struct i2c_msg msg[2] = { | |
| 82 | − {.addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2}, | |
| 83 | − {.addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2}, | |
| 84 | − }; | |
| 84 | + state->i2c_write_buffer[0] = reg >> 8; | |
| 85 | + state->i2c_write_buffer[1] = reg & 0xff; | |
| 86 | + | |
| 87 | + memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); | |
| 88 | + state->msg[0].addr = state->i2c_addr >> 1; | |
| 89 | + state->msg[0].flags = 0; | |
| 90 | + state->msg[0].buf = state->i2c_write_buffer; | |
| 91 | + state->msg[0].len = 2; | |
| 92 | + state->msg[1].addr = state->i2c_addr >> 1; | |
| 93 | + state->msg[1].flags = I2C_M_RD; | |
| 94 | + state->msg[1].buf = state->i2c_read_buffer; | |
| 95 | + state->msg[1].len = 2; | |
| 85 | 96 | |
| 86 | − if (i2c_transfer(state->i2c_adap, msg, 2) != 2) | |
| 97 | + if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2) | |
| 87 | 98 | dprintk("i2c read error on %d", reg); |
| 88 | 99 | |
| 89 | − return (rb[0] << 8) | rb[1]; | |
| 100 | + return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; | |
| 90 | 101 | } |
| 91 | 102 | |
| 92 | 103 | static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) |
| 93 | 104 | { |
| 94 | − u8 b[4] = { | |
| 95 | − (reg >> 8) & 0xff, reg & 0xff, | |
| 96 | − (val >> 8) & 0xff, val & 0xff, | |
| 97 | − }; | |
| 98 | − struct i2c_msg msg = { | |
| 99 | − .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 | |
| 100 | − }; | |
| 101 | − return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | |
| 105 | + state->i2c_write_buffer[0] = (reg >> 8) & 0xff; | |
| 106 | + state->i2c_write_buffer[1] = reg & 0xff; | |
| 107 | + state->i2c_write_buffer[2] = (val >> 8) & 0xff; | |
| 108 | + state->i2c_write_buffer[3] = val & 0xff; | |
| 109 | + | |
| 110 | + memset(&state->msg[0], 0, sizeof(struct i2c_msg)); | |
| 111 | + state->msg[0].addr = state->i2c_addr >> 1; | |
| 112 | + state->msg[0].flags = 0; | |
| 113 | + state->msg[0].buf = state->i2c_write_buffer; | |
| 114 | + state->msg[0].len = 4; | |
| 115 | + | |
| 116 | + return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; | |
| 102 | 117 | } |
| 103 | 118 | |
| 104 | 119 | static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf) |
| @@ -1550,11 +1565,24 @@ static void dib7000p_release(struct dvb_frontend *demod) · 1445 unmodified lines | ||
| 1550 | 1565 | |
| 1551 | 1566 | int dib7000pc_detection(struct i2c_adapter *i2c_adap) |
| 1552 | 1567 | { |
| 1553 | − u8 tx[2], rx[2]; | |
| 1568 | + u8 *tx, *rx; | |
| 1554 | 1569 | struct i2c_msg msg[2] = { |
| 1555 | − {.addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2}, | |
| 1556 | − {.addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2}, | |
| 1570 | + {.addr = 18 >> 1, .flags = 0, .len = 2}, | |
| 1571 | + {.addr = 18 >> 1, .flags = I2C_M_RD, .len = 2}, | |
| 1557 | 1572 | }; |
| 1573 | + int ret = 0; | |
| 1574 | + | |
| 1575 | + tx = kzalloc(2*sizeof(u8), GFP_KERNEL); | |
| 1576 | + if (!tx) | |
| 1577 | + return -ENOMEM; | |
| 1578 | + rx = kzalloc(2*sizeof(u8), GFP_KERNEL); | |
| 1579 | + if (!rx) { | |
| 1580 | + goto rx_memory_error; | |
| 1581 | + ret = -ENOMEM; | |
| 1582 | + } | |
| 1583 | + | |
| 1584 | + msg[0].buf = tx; | |
| 1585 | + msg[1].buf = rx; | |
| 1558 | 1586 | |
| 1559 | 1587 | tx[0] = 0x03; |
| 1560 | 1588 | tx[1] = 0x00; |
| @@ -1574,7 +1602,11 @@ int dib7000pc_detection(struct i2c_adapter *i2c_adap) · 13 unmodified lines | ||
| 1574 | 1602 | } |
| 1575 | 1603 | |
| 1576 | 1604 | dprintk("-D- DiB7000PC not detected"); |
| 1577 | − return 0; | |
| 1605 | + | |
| 1606 | + kfree(rx); | |
| 1607 | +rx_memory_error: | |
| 1608 | + kfree(tx); | |
| 1609 | + return ret; | |
| 1578 | 1610 | } |
| 1579 | 1611 | EXPORT_SYMBOL(dib7000pc_detection); |
| 1580 | 1612 | |
| @@ -35,6 +35,8 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); · 34 unmodified lines | ||
| 35 | 35 | struct i2c_device { |
| 36 | 36 | struct i2c_adapter *adap; |
| 37 | 37 | u8 addr; |
| 38 | + u8 *i2c_write_buffer; | |
| 39 | + u8 *i2c_read_buffer; | |
| 38 | 40 | }; |
| 39 | 41 | |
| 40 | 42 | struct dib8000_state { |
| @@ -70,6 +72,11 @@ struct dib8000_state { · 29 unmodified lines | ||
| 70 | 72 | u32 status; |
| 71 | 73 | |
| 72 | 74 | struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS]; |
| 75 | + | |
| 76 | + /* for the I2C transfer */ | |
| 77 | + struct i2c_msg msg[2]; | |
| 78 | + u8 i2c_write_buffer[4]; | |
| 79 | + u8 i2c_read_buffer[2]; | |
| 73 | 80 | }; |
| 74 | 81 | |
| 75 | 82 | enum dib8000_power_mode { |
| @@ -79,22 +86,41 @@ enum dib8000_power_mode { · 3 unmodified lines | ||
| 79 | 86 | |
| 80 | 87 | static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg) |
| 81 | 88 | { |
| 82 | − u8 wb[2] = { reg >> 8, reg & 0xff }; | |
| 83 | − u8 rb[2]; | |
| 84 | 89 | struct i2c_msg msg[2] = { |
| 85 | − {.addr = i2c->addr >> 1,.flags = 0,.buf = wb,.len = 2}, | |
| 86 | − {.addr = i2c->addr >> 1,.flags = I2C_M_RD,.buf = rb,.len = 2}, | |
| 90 | + {.addr = i2c->addr >> 1, .flags = 0, | |
| 91 | + .buf = i2c->i2c_write_buffer, .len = 2}, | |
| 92 | + {.addr = i2c->addr >> 1, .flags = I2C_M_RD, | |
| 93 | + .buf = i2c->i2c_read_buffer, .len = 2}, | |
| 87 | 94 | }; |
| 88 | 95 | |
| 96 | + msg[0].buf[0] = reg >> 8; | |
| 97 | + msg[0].buf[1] = reg & 0xff; | |
| 98 | + | |
| 89 | 99 | if (i2c_transfer(i2c->adap, msg, 2) != 2) |
| 90 | 100 | dprintk("i2c read error on %d", reg); |
| 91 | 101 | |
| 92 | − return (rb[0] << 8) | rb[1]; | |
| 102 | + return (msg[1].buf[0] << 8) | msg[1].buf[1]; | |
| 93 | 103 | } |
| 94 | 104 | |
| 95 | 105 | static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) |
| 96 | 106 | { |
| 97 | − return dib8000_i2c_read16(&state->i2c, reg); | |
| 107 | + state->i2c_write_buffer[0] = reg >> 8; | |
| 108 | + state->i2c_write_buffer[1] = reg & 0xff; | |
| 109 | + | |
| 110 | + memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); | |
| 111 | + state->msg[0].addr = state->i2c.addr >> 1; | |
| 112 | + state->msg[0].flags = 0; | |
| 113 | + state->msg[0].buf = state->i2c_write_buffer; | |
| 114 | + state->msg[0].len = 2; | |
| 115 | + state->msg[1].addr = state->i2c.addr >> 1; | |
| 116 | + state->msg[1].flags = I2C_M_RD; | |
| 117 | + state->msg[1].buf = state->i2c_read_buffer; | |
| 118 | + state->msg[1].len = 2; | |
| 119 | + | |
| 120 | + if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2) | |
| 121 | + dprintk("i2c read error on %d", reg); | |
| 122 | + | |
| 123 | + return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; | |
| 98 | 124 | } |
| 99 | 125 | |
| 100 | 126 | static u32 dib8000_read32(struct dib8000_state *state, u16 reg) |
| @@ -109,19 +135,34 @@ static u32 dib8000_read32(struct dib8000_state *state, u16 reg) · 8 unmodified lines | ||
| 109 | 135 | |
| 110 | 136 | static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val) |
| 111 | 137 | { |
| 112 | − u8 b[4] = { | |
| 113 | − (reg >> 8) & 0xff, reg & 0xff, | |
| 114 | − (val >> 8) & 0xff, val & 0xff, | |
| 115 | − }; | |
| 116 | − struct i2c_msg msg = { | |
| 117 | − .addr = i2c->addr >> 1,.flags = 0,.buf = b,.len = 4 | |
| 118 | − }; | |
| 119 | − return i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | |
| 138 | + struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, | |
| 139 | + .buf = i2c->i2c_write_buffer, .len = 4}; | |
| 140 | + int ret = 0; | |
| 141 | + | |
| 142 | + msg.buf[0] = (reg >> 8) & 0xff; | |
| 143 | + msg.buf[1] = reg & 0xff; | |
| 144 | + msg.buf[2] = (val >> 8) & 0xff; | |
| 145 | + msg.buf[3] = val & 0xff; | |
| 146 | + | |
| 147 | + ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | |
| 148 | + | |
| 149 | + return ret; | |
| 120 | 150 | } |
| 121 | 151 | |
| 122 | 152 | static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) |
| 123 | 153 | { |
| 124 | − return dib8000_i2c_write16(&state->i2c, reg, val); | |
| 154 | + state->i2c_write_buffer[0] = (reg >> 8) & 0xff; | |
| 155 | + state->i2c_write_buffer[1] = reg & 0xff; | |
| 156 | + state->i2c_write_buffer[2] = (val >> 8) & 0xff; | |
| 157 | + state->i2c_write_buffer[3] = val & 0xff; | |
| 158 | + | |
| 159 | + memset(&state->msg[0], 0, sizeof(struct i2c_msg)); | |
| 160 | + state->msg[0].addr = state->i2c.addr >> 1; | |
| 161 | + state->msg[0].flags = 0; | |
| 162 | + state->msg[0].buf = state->i2c_write_buffer; | |
| 163 | + state->msg[0].len = 4; | |
| 164 | + | |
| 165 | + return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; | |
| 125 | 166 | } |
| 126 | 167 | |
| 127 | 168 | static const s16 coeff_2k_sb_1seg_dqpsk[8] = { |
| @@ -980,30 +1021,31 @@ static void dib8000_update_timf(struct dib8000_state *state) · 852 unmodified lines | ||
| 980 | 1021 | dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default); |
| 981 | 1022 | } |
| 982 | 1023 | |
| 1024 | +static const u16 adc_target_16dB[11] = { | |
| 1025 | + (1 << 13) - 825 - 117, | |
| 1026 | + (1 << 13) - 837 - 117, | |
| 1027 | + (1 << 13) - 811 - 117, | |
| 1028 | + (1 << 13) - 766 - 117, | |
| 1029 | + (1 << 13) - 737 - 117, | |
| 1030 | + (1 << 13) - 693 - 117, | |
| 1031 | + (1 << 13) - 648 - 117, | |
| 1032 | + (1 << 13) - 619 - 117, | |
| 1033 | + (1 << 13) - 575 - 117, | |
| 1034 | + (1 << 13) - 531 - 117, | |
| 1035 | + (1 << 13) - 501 - 117 | |
| 1036 | +}; | |
| 1037 | +static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 }; | |
| 1038 | + | |
| 983 | 1039 | static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosearching) |
| 984 | 1040 | { |
| 985 | 1041 | u16 mode, max_constellation, seg_diff_mask = 0, nbseg_diff = 0; |
| 986 | 1042 | u8 guard, crate, constellation, timeI; |
| 987 | − u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 }; | |
| 988 | 1043 | u16 i, coeff[4], P_cfr_left_edge = 0, P_cfr_right_edge = 0, seg_mask13 = 0x1fff; // All 13 segments enabled |
| 989 | 1044 | const s16 *ncoeff = NULL, *ana_fe; |
| 990 | 1045 | u16 tmcc_pow = 0; |
| 991 | 1046 | u16 coff_pow = 0x2800; |
| 992 | 1047 | u16 init_prbs = 0xfff; |
| 993 | 1048 | u16 ana_gain = 0; |
| 994 | − u16 adc_target_16dB[11] = { | |
| 995 | − (1 << 13) - 825 - 117, | |
| 996 | − (1 << 13) - 837 - 117, | |
| 997 | − (1 << 13) - 811 - 117, | |
| 998 | − (1 << 13) - 766 - 117, | |
| 999 | − (1 << 13) - 737 - 117, | |
| 1000 | − (1 << 13) - 693 - 117, | |
| 1001 | − (1 << 13) - 648 - 117, | |
| 1002 | − (1 << 13) - 619 - 117, | |
| 1003 | − (1 << 13) - 575 - 117, | |
| 1004 | − (1 << 13) - 531 - 117, | |
| 1005 | − (1 << 13) - 501 - 117 | |
| 1006 | − }; | |
| 1007 | 1049 | |
| 1008 | 1050 | if (state->ber_monitored_layer != LAYER_ALL) |
| 1009 | 1051 | 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); · 1369 unmodified lines | ||
| 2379 | 2421 | |
| 2380 | 2422 | int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr) |
| 2381 | 2423 | { |
| 2382 | − int k = 0; | |
| 2424 | + int k = 0, ret = 0; | |
| 2383 | 2425 | u8 new_addr = 0; |
| 2384 | 2426 | struct i2c_device client = {.adap = host }; |
| 2385 | 2427 | |
| 2428 | + client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL); | |
| 2429 | + if (!client.i2c_write_buffer) { | |
| 2430 | + dprintk("%s: not enough memory", __func__); | |
| 2431 | + return -ENOMEM; | |
| 2432 | + } | |
| 2433 | + client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL); | |
| 2434 | + if (!client.i2c_read_buffer) { | |
| 2435 | + dprintk("%s: not enough memory", __func__); | |
| 2436 | + ret = -ENOMEM; | |
| 2437 | + goto error_memory; | |
| 2438 | + } | |
| 2439 | + | |
| 2386 | 2440 | for (k = no_of_demods - 1; k >= 0; k--) { |
| 2387 | 2441 | /* designated i2c address */ |
| 2388 | 2442 | new_addr = first_addr + (k << 1); |
| @@ -2394,7 +2448,8 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau · 5 unmodified lines | ||
| 2394 | 2448 | client.addr = default_addr; |
| 2395 | 2449 | if (dib8000_identify(&client) == 0) { |
| 2396 | 2450 | dprintk("#%d: not identified", k); |
| 2397 | − return -EINVAL; | |
| 2451 | + ret = -EINVAL; | |
| 2452 | + goto error; | |
| 2398 | 2453 | } |
| 2399 | 2454 | } |
| 2400 | 2455 | |
| @@ -2420,7 +2475,12 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau · 19 unmodified lines | ||
| 2420 | 2475 | dib8000_i2c_write16(&client, 1286, 0); |
| 2421 | 2476 | } |
| 2422 | 2477 | |
| 2423 | − return 0; | |
| 2478 | +error: | |
| 2479 | + kfree(client.i2c_read_buffer); | |
| 2480 | +error_memory: | |
| 2481 | + kfree(client.i2c_write_buffer); | |
| 2482 | + | |
| 2483 | + return ret; | |
| 2424 | 2484 | } |
| 2425 | 2485 | |
| 2426 | 2486 | EXPORT_SYMBOL(dib8000_i2c_enumeration); |
| @@ -2519,6 +2579,8 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s · 92 unmodified lines | ||
| 2519 | 2579 | memcpy(&state->cfg, cfg, sizeof(struct dib8000_config)); |
| 2520 | 2580 | state->i2c.adap = i2c_adap; |
| 2521 | 2581 | state->i2c.addr = i2c_addr; |
| 2582 | + state->i2c.i2c_write_buffer = state->i2c_write_buffer; | |
| 2583 | + state->i2c.i2c_read_buffer = state->i2c_read_buffer; | |
| 2522 | 2584 | state->gpio_val = cfg->gpio_val; |
| 2523 | 2585 | state->gpio_dir = cfg->gpio_dir; |
| 2524 | 2586 | |
| @@ -27,6 +27,8 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); · 26 unmodified lines | ||
| 27 | 27 | struct i2c_device { |
| 28 | 28 | struct i2c_adapter *i2c_adap; |
| 29 | 29 | u8 i2c_addr; |
| 30 | + u8 *i2c_read_buffer; | |
| 31 | + u8 *i2c_write_buffer; | |
| 30 | 32 | }; |
| 31 | 33 | |
| 32 | 34 | /* lock */ |
| @@ -92,11 +94,16 @@ struct dib9000_state { · 59 unmodified lines | ||
| 92 | 94 | |
| 93 | 95 | struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS]; |
| 94 | 96 | u16 component_bus_speed; |
| 97 | + | |
| 98 | + /* for the I2C transfer */ | |
| 99 | + struct i2c_msg msg[2]; | |
| 100 | + u8 i2c_write_buffer[255]; | |
| 101 | + u8 i2c_read_buffer[255]; | |
| 95 | 102 | }; |
| 96 | 103 | |
| 97 | −u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 104 | +static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 98 | 105 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 99 | − 0, 0, 0 | |
| 106 | + 0, 0, 0, 0, 0, 0, 0, 0 | |
| 100 | 107 | }; |
| 101 | 108 | |
| 102 | 109 | enum dib9000_power_mode { |
| @@ -217,25 +224,33 @@ static u16 dib9000_read16_attr(struct dib9000_state *state, u16 reg, u8 * b, u32 · 114 unmodified lines | ||
| 217 | 224 | u32 chunk_size = 126; |
| 218 | 225 | u32 l; |
| 219 | 226 | int ret; |
| 220 | − u8 wb[2] = { reg >> 8, reg & 0xff }; | |
| 221 | − struct i2c_msg msg[2] = { | |
| 222 | − {.addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2}, | |
| 223 | − {.addr = state->i2c.i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = len}, | |
| 224 | − }; | |
| 225 | 227 | |
| 226 | 228 | if (state->platform.risc.fw_is_running && (reg < 1024)) |
| 227 | 229 | return dib9000_risc_apb_access_read(state, reg, attribute, NULL, 0, b, len); |
| 228 | 230 | |
| 231 | + memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); | |
| 232 | + state->msg[0].addr = state->i2c.i2c_addr >> 1; | |
| 233 | + state->msg[0].flags = 0; | |
| 234 | + state->msg[0].buf = state->i2c_write_buffer; | |
| 235 | + state->msg[0].len = 2; | |
| 236 | + state->msg[1].addr = state->i2c.i2c_addr >> 1; | |
| 237 | + state->msg[1].flags = I2C_M_RD; | |
| 238 | + state->msg[1].buf = b; | |
| 239 | + state->msg[1].len = len; | |
| 240 | + | |
| 241 | + state->i2c_write_buffer[0] = reg >> 8; | |
| 242 | + state->i2c_write_buffer[1] = reg & 0xff; | |
| 243 | + | |
| 229 | 244 | if (attribute & DATA_BUS_ACCESS_MODE_8BIT) |
| 230 | − wb[0] |= (1 << 5); | |
| 245 | + state->i2c_write_buffer[0] |= (1 << 5); | |
| 231 | 246 | if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT) |
| 232 | − wb[0] |= (1 << 4); | |
| 247 | + state->i2c_write_buffer[0] |= (1 << 4); | |
| 233 | 248 | |
| 234 | 249 | do { |
| 235 | 250 | l = len < chunk_size ? len : chunk_size; |
| 236 | − msg[1].len = l; | |
| 237 | − msg[1].buf = b; | |
| 238 | − ret = i2c_transfer(state->i2c.i2c_adap, msg, 2) != 2 ? -EREMOTEIO : 0; | |
| 251 | + state->msg[1].len = l; | |
| 252 | + state->msg[1].buf = b; | |
| 253 | + ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 2) != 2 ? -EREMOTEIO : 0; | |
| 239 | 254 | if (ret != 0) { |
| 240 | 255 | dprintk("i2c read error on %d", reg); |
| 241 | 256 | return -EREMOTEIO; |
| @@ -253,50 +268,47 @@ static u16 dib9000_read16_attr(struct dib9000_state *state, u16 reg, u8 * b, u32 · 11 unmodified lines | ||
| 253 | 268 | |
| 254 | 269 | static u16 dib9000_i2c_read16(struct i2c_device *i2c, u16 reg) |
| 255 | 270 | { |
| 256 | − u8 b[2]; | |
| 257 | − u8 wb[2] = { reg >> 8, reg & 0xff }; | |
| 258 | 271 | struct i2c_msg msg[2] = { |
| 259 | − {.addr = i2c->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2}, | |
| 260 | − {.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = 2}, | |
| 272 | + {.addr = i2c->i2c_addr >> 1, .flags = 0, | |
| 273 | + .buf = i2c->i2c_write_buffer, .len = 2}, | |
| 274 | + {.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD, | |
| 275 | + .buf = i2c->i2c_read_buffer, .len = 2}, | |
| 261 | 276 | }; |
| 262 | 277 | |
| 278 | + i2c->i2c_write_buffer[0] = reg >> 8; | |
| 279 | + i2c->i2c_write_buffer[1] = reg & 0xff; | |
| 280 | + | |
| 263 | 281 | if (i2c_transfer(i2c->i2c_adap, msg, 2) != 2) { |
| 264 | 282 | dprintk("read register %x error", reg); |
| 265 | 283 | return 0; |
| 266 | 284 | } |
| 267 | 285 | |
| 268 | − return (b[0] << 8) | b[1]; | |
| 286 | + return (i2c->i2c_read_buffer[0] << 8) | i2c->i2c_read_buffer[1]; | |
| 269 | 287 | } |
| 270 | 288 | |
| 271 | 289 | static inline u16 dib9000_read_word(struct dib9000_state *state, u16 reg) |
| 272 | 290 | { |
| 273 | − u8 b[2]; | |
| 274 | − if (dib9000_read16_attr(state, reg, b, 2, 0) != 0) | |
| 291 | + if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2, 0) != 0) | |
| 275 | 292 | return 0; |
| 276 | − return (b[0] << 8 | b[1]); | |
| 293 | + return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; | |
| 277 | 294 | } |
| 278 | 295 | |
| 279 | 296 | static inline u16 dib9000_read_word_attr(struct dib9000_state *state, u16 reg, u16 attribute) |
| 280 | 297 | { |
| 281 | − u8 b[2]; | |
| 282 | − if (dib9000_read16_attr(state, reg, b, 2, attribute) != 0) | |
| 298 | + if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2, | |
| 299 | + attribute) != 0) | |
| 283 | 300 | return 0; |
| 284 | − return (b[0] << 8 | b[1]); | |
| 301 | + return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; | |
| 285 | 302 | } |
| 286 | 303 | |
| 287 | 304 | #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) |
| 288 | 305 | |
| 289 | 306 | static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * buf, u32 len, u16 attribute) |
| 290 | 307 | { |
| 291 | − u8 b[255]; | |
| 292 | 308 | u32 chunk_size = 126; |
| 293 | 309 | u32 l; |
| 294 | 310 | int ret; |
| 295 | 311 | |
| 296 | − struct i2c_msg msg = { | |
| 297 | − .addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = b, .len = len + 2 | |
| 298 | − }; | |
| 299 | − | |
| 300 | 312 | if (state->platform.risc.fw_is_running && (reg < 1024)) { |
| 301 | 313 | if (dib9000_risc_apb_access_write |
| 302 | 314 | (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 * · 1 unmodified line | ||
| 304 | 316 | return 0; |
| 305 | 317 | } |
| 306 | 318 | |
| 307 | − b[0] = (reg >> 8) & 0xff; | |
| 308 | − b[1] = (reg) & 0xff; | |
| 319 | + memset(&state->msg[0], 0, sizeof(struct i2c_msg)); | |
| 320 | + state->msg[0].addr = state->i2c.i2c_addr >> 1; | |
| 321 | + state->msg[0].flags = 0; | |
| 322 | + state->msg[0].buf = state->i2c_write_buffer; | |
| 323 | + state->msg[0].len = len + 2; | |
| 324 | + | |
| 325 | + state->i2c_write_buffer[0] = (reg >> 8) & 0xff; | |
| 326 | + state->i2c_write_buffer[1] = (reg) & 0xff; | |
| 309 | 327 | |
| 310 | 328 | if (attribute & DATA_BUS_ACCESS_MODE_8BIT) |
| 311 | − b[0] |= (1 << 5); | |
| 329 | + state->i2c_write_buffer[0] |= (1 << 5); | |
| 312 | 330 | if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT) |
| 313 | − b[0] |= (1 << 4); | |
| 331 | + state->i2c_write_buffer[0] |= (1 << 4); | |
| 314 | 332 | |
| 315 | 333 | do { |
| 316 | 334 | l = len < chunk_size ? len : chunk_size; |
| 317 | − msg.len = l + 2; | |
| 318 | − memcpy(&b[2], buf, l); | |
| 335 | + state->msg[0].len = l + 2; | |
| 336 | + memcpy(&state->i2c_write_buffer[2], buf, l); | |
| 319 | 337 | |
| 320 | − ret = i2c_transfer(state->i2c.i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | |
| 338 | + ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0; | |
| 321 | 339 | |
| 322 | 340 | buf += l; |
| 323 | 341 | len -= l; |
| @@ -331,11 +349,16 @@ static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * · 7 unmodified lines | ||
| 331 | 349 | |
| 332 | 350 | static int dib9000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val) |
| 333 | 351 | { |
| 334 | − u8 b[4] = { (reg >> 8) & 0xff, reg & 0xff, (val >> 8) & 0xff, val & 0xff }; | |
| 335 | 352 | struct i2c_msg msg = { |
| 336 | − .addr = i2c->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 | |
| 353 | + .addr = i2c->i2c_addr >> 1, .flags = 0, | |
| 354 | + .buf = i2c->i2c_write_buffer, .len = 4 | |
| 337 | 355 | }; |
| 338 | 356 | |
| 357 | + i2c->i2c_write_buffer[0] = (reg >> 8) & 0xff; | |
| 358 | + i2c->i2c_write_buffer[1] = reg & 0xff; | |
| 359 | + i2c->i2c_write_buffer[2] = (val >> 8) & 0xff; | |
| 360 | + i2c->i2c_write_buffer[3] = val & 0xff; | |
| 361 | + | |
| 339 | 362 | return i2c_transfer(i2c->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; |
| 340 | 363 | } |
| 341 | 364 | |
| @@ -1015,8 +1038,8 @@ static int dib9000_fw_memmbx_sync(struct dib9000_state *state, u8 i) · 673 unmodified lines | ||
| 1015 | 1038 | return 0; |
| 1016 | 1039 | dib9000_risc_mem_write(state, FE_MM_RW_SYNC, &i); |
| 1017 | 1040 | do { |
| 1018 | − dib9000_risc_mem_read(state, FE_MM_RW_SYNC, &i, 1); | |
| 1019 | − } while (i && index_loop--); | |
| 1041 | + dib9000_risc_mem_read(state, FE_MM_RW_SYNC, state->i2c_read_buffer, 1); | |
| 1042 | + } while (state->i2c_read_buffer[0] && index_loop--); | |
| 1020 | 1043 | |
| 1021 | 1044 | if (index_loop > 0) |
| 1022 | 1045 | return 0; |
| @@ -1139,7 +1162,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p · 116 unmodified lines | ||
| 1139 | 1162 | |
| 1140 | 1163 | s8 intlv_native; |
| 1141 | 1164 | }; |
| 1142 | − struct dibDVBTChannel ch; | |
| 1165 | + struct dibDVBTChannel *ch; | |
| 1143 | 1166 | int ret = 0; |
| 1144 | 1167 | |
| 1145 | 1168 | 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 · 2 unmodified lines | ||
| 1148 | 1171 | ret = -EIO; |
| 1149 | 1172 | } |
| 1150 | 1173 | |
| 1151 | − dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION, (u8 *) &ch, sizeof(struct dibDVBTChannel)); | |
| 1174 | + dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION, | |
| 1175 | + state->i2c_read_buffer, sizeof(struct dibDVBTChannel)); | |
| 1176 | + ch = (struct dibDVBTChannel *)state->i2c_read_buffer; | |
| 1177 | + | |
| 1152 | 1178 | |
| 1153 | − switch (ch.spectrum_inversion & 0x7) { | |
| 1179 | + switch (ch->spectrum_inversion & 0x7) { | |
| 1154 | 1180 | case 1: |
| 1155 | 1181 | state->fe[0]->dtv_property_cache.inversion = INVERSION_ON; |
| 1156 | 1182 | break; |
| @@ -1162,7 +1188,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p · 5 unmodified lines | ||
| 1162 | 1188 | state->fe[0]->dtv_property_cache.inversion = INVERSION_AUTO; |
| 1163 | 1189 | break; |
| 1164 | 1190 | } |
| 1165 | − switch (ch.nfft) { | |
| 1191 | + switch (ch->nfft) { | |
| 1166 | 1192 | case 0: |
| 1167 | 1193 | state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K; |
| 1168 | 1194 | break; |
| @@ -1177,7 +1203,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p · 8 unmodified lines | ||
| 1177 | 1203 | state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO; |
| 1178 | 1204 | break; |
| 1179 | 1205 | } |
| 1180 | − switch (ch.guard) { | |
| 1206 | + switch (ch->guard) { | |
| 1181 | 1207 | case 0: |
| 1182 | 1208 | state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32; |
| 1183 | 1209 | break; |
| @@ -1195,7 +1221,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p · 11 unmodified lines | ||
| 1195 | 1221 | state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO; |
| 1196 | 1222 | break; |
| 1197 | 1223 | } |
| 1198 | − switch (ch.constellation) { | |
| 1224 | + switch (ch->constellation) { | |
| 1199 | 1225 | case 2: |
| 1200 | 1226 | state->fe[0]->dtv_property_cache.modulation = QAM_64; |
| 1201 | 1227 | break; |
| @@ -1210,7 +1236,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p · 8 unmodified lines | ||
| 1210 | 1236 | state->fe[0]->dtv_property_cache.modulation = QAM_AUTO; |
| 1211 | 1237 | break; |
| 1212 | 1238 | } |
| 1213 | − switch (ch.hrch) { | |
| 1239 | + switch (ch->hrch) { | |
| 1214 | 1240 | case 0: |
| 1215 | 1241 | state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_NONE; |
| 1216 | 1242 | break; |
| @@ -1222,7 +1248,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p · 5 unmodified lines | ||
| 1222 | 1248 | state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_AUTO; |
| 1223 | 1249 | break; |
| 1224 | 1250 | } |
| 1225 | − switch (ch.code_rate_hp) { | |
| 1251 | + switch (ch->code_rate_hp) { | |
| 1226 | 1252 | case 1: |
| 1227 | 1253 | state->fe[0]->dtv_property_cache.code_rate_HP = FEC_1_2; |
| 1228 | 1254 | break; |
| @@ -1243,7 +1269,7 @@ static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_p · 14 unmodified lines | ||
| 1243 | 1269 | state->fe[0]->dtv_property_cache.code_rate_HP = FEC_AUTO; |
| 1244 | 1270 | break; |
| 1245 | 1271 | } |
| 1246 | − switch (ch.code_rate_lp) { | |
| 1272 | + switch (ch->code_rate_lp) { | |
| 1247 | 1273 | case 1: |
| 1248 | 1274 | state->fe[0]->dtv_property_cache.code_rate_LP = FEC_1_2; |
| 1249 | 1275 | break; |
| @@ -1439,9 +1465,10 @@ static int dib9000_fw_tune(struct dvb_frontend *fe, struct dvb_frontend_paramete · 189 unmodified lines | ||
| 1439 | 1465 | break; |
| 1440 | 1466 | case CT_DEMOD_STEP_1: |
| 1441 | 1467 | if (search) |
| 1442 | − dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, (u8 *) &i, 1); | |
| 1468 | + dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, state->i2c_read_buffer, 1); | |
| 1443 | 1469 | else |
| 1444 | − dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, (u8 *) &i, 1); | |
| 1470 | + dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, state->i2c_read_buffer, 1); | |
| 1471 | + i = (s8)state->i2c_read_buffer[0]; | |
| 1445 | 1472 | switch (i) { /* something happened */ |
| 1446 | 1473 | case 0: |
| 1447 | 1474 | break; |
| @@ -2038,14 +2065,17 @@ static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat) · 590 unmodified lines | ||
| 2038 | 2065 | static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber) |
| 2039 | 2066 | { |
| 2040 | 2067 | struct dib9000_state *state = fe->demodulator_priv; |
| 2041 | − u16 c[16]; | |
| 2068 | + u16 *c; | |
| 2042 | 2069 | |
| 2043 | 2070 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); |
| 2044 | 2071 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) |
| 2045 | 2072 | return -EIO; |
| 2046 | − dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c)); | |
| 2073 | + dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, | |
| 2074 | + state->i2c_read_buffer, 16 * 2); | |
| 2047 | 2075 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); |
| 2048 | 2076 | |
| 2077 | + c = (u16 *)state->i2c_read_buffer; | |
| 2078 | + | |
| 2049 | 2079 | *ber = c[10] << 16 | c[11]; |
| 2050 | 2080 | return 0; |
| 2051 | 2081 | } |
| @@ -2054,7 +2084,7 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) · 2 unmodified lines | ||
| 2054 | 2084 | { |
| 2055 | 2085 | struct dib9000_state *state = fe->demodulator_priv; |
| 2056 | 2086 | u8 index_frontend; |
| 2057 | − u16 c[16]; | |
| 2087 | + u16 *c = (u16 *)state->i2c_read_buffer; | |
| 2058 | 2088 | u16 val; |
| 2059 | 2089 | |
| 2060 | 2090 | *strength = 0; |
| @@ -2069,7 +2099,7 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) · 8 unmodified lines | ||
| 2069 | 2099 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); |
| 2070 | 2100 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) |
| 2071 | 2101 | return -EIO; |
| 2072 | − dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c)); | |
| 2102 | + dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); | |
| 2073 | 2103 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); |
| 2074 | 2104 | |
| 2075 | 2105 | val = 65535 - c[4]; |
| @@ -2083,14 +2113,14 @@ static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) · 7 unmodified lines | ||
| 2083 | 2113 | static u32 dib9000_get_snr(struct dvb_frontend *fe) |
| 2084 | 2114 | { |
| 2085 | 2115 | struct dib9000_state *state = fe->demodulator_priv; |
| 2086 | − u16 c[16]; | |
| 2116 | + u16 *c = (u16 *)state->i2c_read_buffer; | |
| 2087 | 2117 | u32 n, s, exp; |
| 2088 | 2118 | u16 val; |
| 2089 | 2119 | |
| 2090 | 2120 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); |
| 2091 | 2121 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) |
| 2092 | 2122 | return -EIO; |
| 2093 | − dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c)); | |
| 2123 | + dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); | |
| 2094 | 2124 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); |
| 2095 | 2125 | |
| 2096 | 2126 | val = c[7]; |
| @@ -2137,12 +2167,12 @@ static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr) · 40 unmodified lines | ||
| 2137 | 2167 | static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) |
| 2138 | 2168 | { |
| 2139 | 2169 | struct dib9000_state *state = fe->demodulator_priv; |
| 2140 | − u16 c[16]; | |
| 2170 | + u16 *c = (u16 *)state->i2c_read_buffer; | |
| 2141 | 2171 | |
| 2142 | 2172 | DibAcquireLock(&state->platform.risc.mem_mbx_lock); |
| 2143 | 2173 | if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) |
| 2144 | 2174 | return -EIO; |
| 2145 | − dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c)); | |
| 2175 | + dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2); | |
| 2146 | 2176 | DibReleaseLock(&state->platform.risc.mem_mbx_lock); |
| 2147 | 2177 | |
| 2148 | 2178 | *unc = c[12]; |
| @@ -2151,10 +2181,22 @@ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) · 2 unmodified lines | ||
| 2151 | 2181 | |
| 2152 | 2182 | int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr) |
| 2153 | 2183 | { |
| 2154 | − int k = 0; | |
| 2184 | + int k = 0, ret = 0; | |
| 2155 | 2185 | u8 new_addr = 0; |
| 2156 | 2186 | struct i2c_device client = {.i2c_adap = i2c }; |
| 2157 | 2187 | |
| 2188 | + client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL); | |
| 2189 | + if (!client.i2c_write_buffer) { | |
| 2190 | + dprintk("%s: not enough memory", __func__); | |
| 2191 | + return -ENOMEM; | |
| 2192 | + } | |
| 2193 | + client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL); | |
| 2194 | + if (!client.i2c_read_buffer) { | |
| 2195 | + dprintk("%s: not enough memory", __func__); | |
| 2196 | + ret = -ENOMEM; | |
| 2197 | + goto error_memory; | |
| 2198 | + } | |
| 2199 | + | |
| 2158 | 2200 | client.i2c_addr = default_addr + 16; |
| 2159 | 2201 | dib9000_i2c_write16(&client, 1796, 0x0); |
| 2160 | 2202 | |
| @@ -2178,7 +2220,8 @@ int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defaul · 17 unmodified lines | ||
| 2178 | 2220 | client.i2c_addr = default_addr; |
| 2179 | 2221 | if (dib9000_identify(&client) == 0) { |
| 2180 | 2222 | dprintk("DiB9000 #%d: not identified", k); |
| 2181 | − return -EIO; | |
| 2223 | + ret = -EIO; | |
| 2224 | + goto error; | |
| 2182 | 2225 | } |
| 2183 | 2226 | } |
| 2184 | 2227 | |
| @@ -2196,7 +2239,12 @@ int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defaul · 11 unmodified lines | ||
| 2196 | 2239 | dib9000_i2c_write16(&client, 1795, 0); |
| 2197 | 2240 | } |
| 2198 | 2241 | |
| 2199 | − return 0; | |
| 2242 | +error: | |
| 2243 | + kfree(client.i2c_read_buffer); | |
| 2244 | +error_memory: | |
| 2245 | + kfree(client.i2c_write_buffer); | |
| 2246 | + | |
| 2247 | + return ret; | |
| 2200 | 2248 | } |
| 2201 | 2249 | EXPORT_SYMBOL(dib9000_i2c_enumeration); |
| 2202 | 2250 | |
| @@ -2255,12 +2303,16 @@ struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, c · 52 unmodified lines | ||
| 2255 | 2303 | if (st == NULL) |
| 2256 | 2304 | return NULL; |
| 2257 | 2305 | fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL); |
| 2258 | − if (fe == NULL) | |
| 2306 | + if (fe == NULL) { | |
| 2307 | + kfree(st); | |
| 2259 | 2308 | return NULL; |
| 2309 | + } | |
| 2260 | 2310 | |
| 2261 | 2311 | memcpy(&st->chip.d9.cfg, cfg, sizeof(struct dib9000_config)); |
| 2262 | 2312 | st->i2c.i2c_adap = i2c_adap; |
| 2263 | 2313 | st->i2c.i2c_addr = i2c_addr; |
| 2314 | + st->i2c.i2c_write_buffer = st->i2c_write_buffer; | |
| 2315 | + st->i2c.i2c_read_buffer = st->i2c_read_buffer; | |
| 2264 | 2316 | |
| 2265 | 2317 | st->gpio_dir = DIB9000_GPIO_DEFAULT_DIRECTIONS; |
| 2266 | 2318 | st->gpio_val = DIB9000_GPIO_DEFAULT_VALUES; |
| @@ -10,30 +10,39 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) |
| 12 | 12 | { |
| 13 | − u8 b[4] = { | |
| 14 | − (reg >> 8) & 0xff, reg & 0xff, | |
| 15 | − (val >> 8) & 0xff, val & 0xff, | |
| 16 | − }; | |
| 17 | − struct i2c_msg msg = { | |
| 18 | − .addr = mst->i2c_addr,.flags = 0,.buf = b,.len = 4 | |
| 19 | − }; | |
| 20 | − | |
| 21 | − return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | |
| 13 | + mst->i2c_write_buffer[0] = (reg >> 8) & 0xff; | |
| 14 | + mst->i2c_write_buffer[1] = reg & 0xff; | |
| 15 | + mst->i2c_write_buffer[2] = (val >> 8) & 0xff; | |
| 16 | + mst->i2c_write_buffer[3] = val & 0xff; | |
| 17 | + | |
| 18 | + memset(mst->msg, 0, sizeof(struct i2c_msg)); | |
| 19 | + mst->msg[0].addr = mst->i2c_addr; | |
| 20 | + mst->msg[0].flags = 0; | |
| 21 | + mst->msg[0].buf = mst->i2c_write_buffer; | |
| 22 | + mst->msg[0].len = 4; | |
| 23 | + | |
| 24 | + return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0; | |
| 22 | 25 | } |
| 23 | 26 | |
| 24 | 27 | static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg) |
| 25 | 28 | { |
| 26 | − u8 wb[2] = { reg >> 8, reg & 0xff }; | |
| 27 | − u8 rb[2]; | |
| 28 | − struct i2c_msg msg[2] = { | |
| 29 | − {.addr = mst->i2c_addr, .flags = 0, .buf = wb, .len = 2}, | |
| 30 | − {.addr = mst->i2c_addr, .flags = I2C_M_RD, .buf = rb, .len = 2}, | |
| 31 | − }; | |
| 32 | − | |
| 33 | − if (i2c_transfer(mst->i2c_adap, msg, 2) != 2) | |
| 29 | + mst->i2c_write_buffer[0] = reg >> 8; | |
| 30 | + mst->i2c_write_buffer[1] = reg & 0xff; | |
| 31 | + | |
| 32 | + memset(mst->msg, 0, 2 * sizeof(struct i2c_msg)); | |
| 33 | + mst->msg[0].addr = mst->i2c_addr; | |
| 34 | + mst->msg[0].flags = 0; | |
| 35 | + mst->msg[0].buf = mst->i2c_write_buffer; | |
| 36 | + mst->msg[0].len = 2; | |
| 37 | + mst->msg[1].addr = mst->i2c_addr; | |
| 38 | + mst->msg[1].flags = I2C_M_RD; | |
| 39 | + mst->msg[1].buf = mst->i2c_read_buffer; | |
| 40 | + mst->msg[1].len = 2; | |
| 41 | + | |
| 42 | + if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2) | |
| 34 | 43 | dprintk("i2c read error on %d", reg); |
| 35 | 44 | |
| 36 | − return (rb[0] << 8) | rb[1]; | |
| 45 | + return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1]; | |
| 37 | 46 | } |
| 38 | 47 | |
| 39 | 48 | 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, · 208 unmodified lines | ||
| 248 | 257 | struct i2c_msg msg[], int num) |
| 249 | 258 | { |
| 250 | 259 | struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); |
| 251 | − struct i2c_msg m[2 + num]; | |
| 252 | − u8 tx_open[4], tx_close[4]; | |
| 253 | 260 | |
| 254 | − memset(m, 0, sizeof(struct i2c_msg) * (2 + num)); | |
| 261 | + if (num > 32) { | |
| 262 | + dprintk("%s: too much I2C message to be transmitted (%i).\ | |
| 263 | + Maximum is 32", __func__, num); | |
| 264 | + return -ENOMEM; | |
| 265 | + } | |
| 266 | + | |
| 267 | + memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); | |
| 255 | 268 | |
| 256 | 269 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7); |
| 257 | 270 | |
| 258 | − dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1); | |
| 259 | − m[0].addr = mst->i2c_addr; | |
| 260 | − m[0].buf = tx_open; | |
| 261 | − m[0].len = 4; | |
| 271 | + /* open the gate */ | |
| 272 | + dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); | |
| 273 | + mst->msg[0].addr = mst->i2c_addr; | |
| 274 | + mst->msg[0].buf = &mst->i2c_write_buffer[0]; | |
| 275 | + mst->msg[0].len = 4; | |
| 262 | 276 | |
| 263 | − memcpy(&m[1], msg, sizeof(struct i2c_msg) * num); | |
| 277 | + memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num); | |
| 264 | 278 | |
| 265 | − dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0); | |
| 266 | − m[num + 1].addr = mst->i2c_addr; | |
| 267 | − m[num + 1].buf = tx_close; | |
| 268 | − m[num + 1].len = 4; | |
| 279 | + /* close the gate */ | |
| 280 | + dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0); | |
| 281 | + mst->msg[num + 1].addr = mst->i2c_addr; | |
| 282 | + mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; | |
| 283 | + mst->msg[num + 1].len = 4; | |
| 269 | 284 | |
| 270 | − return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO; | |
| 285 | + return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO; | |
| 271 | 286 | } |
| 272 | 287 | |
| 273 | 288 | 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, · 5 unmodified lines | ||
| 279 | 294 | struct i2c_msg msg[], int num) |
| 280 | 295 | { |
| 281 | 296 | struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); |
| 282 | − struct i2c_msg m[2 + num]; | |
| 283 | − u8 tx_open[4], tx_close[4]; | |
| 284 | 297 | |
| 285 | − memset(m, 0, sizeof(struct i2c_msg) * (2 + num)); | |
| 298 | + if (num > 32) { | |
| 299 | + dprintk("%s: too much I2C message to be transmitted (%i).\ | |
| 300 | + Maximum is 32", __func__, num); | |
| 301 | + return -ENOMEM; | |
| 302 | + } | |
| 303 | + | |
| 304 | + memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); | |
| 286 | 305 | |
| 287 | 306 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); |
| 288 | 307 | |
| 289 | − dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1); | |
| 290 | − m[0].addr = mst->i2c_addr; | |
| 291 | − m[0].buf = tx_open; | |
| 292 | − m[0].len = 4; | |
| 308 | + /* open the gate */ | |
| 309 | + dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); | |
| 310 | + mst->msg[0].addr = mst->i2c_addr; | |
| 311 | + mst->msg[0].buf = &mst->i2c_write_buffer[0]; | |
| 312 | + mst->msg[0].len = 4; | |
| 293 | 313 | |
| 294 | − memcpy(&m[1], msg, sizeof(struct i2c_msg) * num); | |
| 314 | + memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num); | |
| 295 | 315 | |
| 296 | − dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0); | |
| 297 | − m[num + 1].addr = mst->i2c_addr; | |
| 298 | − m[num + 1].buf = tx_close; | |
| 299 | − m[num + 1].len = 4; | |
| 316 | + /* close the gate */ | |
| 317 | + dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0); | |
| 318 | + mst->msg[num + 1].addr = mst->i2c_addr; | |
| 319 | + mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; | |
| 320 | + mst->msg[num + 1].len = 4; | |
| 300 | 321 | |
| 301 | − return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO; | |
| 322 | + return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO; | |
| 302 | 323 | } |
| 303 | 324 | |
| 304 | 325 | static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = { |
| @@ -28,6 +28,11 @@ struct dibx000_i2c_master { · 27 unmodified lines | ||
| 28 | 28 | u8 i2c_addr; |
| 29 | 29 | |
| 30 | 30 | u16 base_reg; |
| 31 | + | |
| 32 | + /* for the I2C transfer */ | |
| 33 | + struct i2c_msg msg[34]; | |
| 34 | + u8 i2c_write_buffer[8]; | |
| 35 | + u8 i2c_read_buffer[2]; | |
| 31 | 36 | }; |
| 32 | 37 | |
| 33 | 38 | extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, |
| @@ -1,1511 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * Driver for Micronas drx397xD demodulator | |
| 3 | − * | |
| 4 | − * Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@gmail.com> | |
| 5 | − * | |
| 6 | − * This program is free software; you can redistribute it and/or modify | |
| 7 | − * it under the terms of the GNU General Public License as published by | |
| 8 | − * the Free Software Foundation; either version 2 of the License, or | |
| 9 | − * (at your option) any later version. | |
| 10 | − * | |
| 11 | − * This program is distributed in the hope that it will be useful, | |
| 12 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | − * GNU General Public License for more details. | |
| 15 | − * | |
| 16 | − * You should have received a copy of the GNU General Public License | |
| 17 | − * along with this program; If not, see <http://www.gnu.org/licenses/>. | |
| 18 | − */ | |
| 19 | − | |
| 20 | −#define DEBUG /* uncomment if you want debugging output */ | |
| 21 | −#include <linux/kernel.h> | |
| 22 | −#include <linux/module.h> | |
| 23 | −#include <linux/moduleparam.h> | |
| 24 | −#include <linux/init.h> | |
| 25 | −#include <linux/device.h> | |
| 26 | −#include <linux/delay.h> | |
| 27 | −#include <linux/string.h> | |
| 28 | −#include <linux/firmware.h> | |
| 29 | −#include <linux/slab.h> | |
| 30 | −#include <asm/div64.h> | |
| 31 | − | |
| 32 | −#include "dvb_frontend.h" | |
| 33 | −#include "drx397xD.h" | |
| 34 | − | |
| 35 | −static const char mod_name[] = "drx397xD"; | |
| 36 | − | |
| 37 | −#define MAX_CLOCK_DRIFT 200 /* maximal 200 PPM allowed */ | |
| 38 | − | |
| 39 | −#define F_SET_0D0h 1 | |
| 40 | −#define F_SET_0D4h 2 | |
| 41 | − | |
| 42 | −enum fw_ix { | |
| 43 | −#define _FW_ENTRY(a, b, c) b | |
| 44 | −#include "drx397xD_fw.h" | |
| 45 | −}; | |
| 46 | − | |
| 47 | −/* chip specifics */ | |
| 48 | −struct drx397xD_state { | |
| 49 | − struct i2c_adapter *i2c; | |
| 50 | − struct dvb_frontend frontend; | |
| 51 | − struct drx397xD_config config; | |
| 52 | − enum fw_ix chip_rev; | |
| 53 | − int flags; | |
| 54 | − u32 bandwidth_parm; /* internal bandwidth conversions */ | |
| 55 | − u32 f_osc; /* w90: actual osc frequency [Hz] */ | |
| 56 | −}; | |
| 57 | − | |
| 58 | −/* Firmware */ | |
| 59 | −static const char *blob_name[] = { | |
| 60 | −#define _BLOB_ENTRY(a, b) a | |
| 61 | −#include "drx397xD_fw.h" | |
| 62 | −}; | |
| 63 | − | |
| 64 | −enum blob_ix { | |
| 65 | −#define _BLOB_ENTRY(a, b) b | |
| 66 | −#include "drx397xD_fw.h" | |
| 67 | −}; | |
| 68 | − | |
| 69 | −static struct { | |
| 70 | − const char *name; | |
| 71 | − const struct firmware *file; | |
| 72 | − rwlock_t lock; | |
| 73 | − int refcnt; | |
| 74 | − const u8 *data[ARRAY_SIZE(blob_name)]; | |
| 75 | −} fw[] = { | |
| 76 | −#define _FW_ENTRY(a, b, c) { \ | |
| 77 | − .name = a, \ | |
| 78 | − .file = NULL, \ | |
| 79 | − .lock = __RW_LOCK_UNLOCKED(fw[c].lock), \ | |
| 80 | − .refcnt = 0, \ | |
| 81 | − .data = { } } | |
| 82 | −#include "drx397xD_fw.h" | |
| 83 | −}; | |
| 84 | − | |
| 85 | −/* use only with writer lock acquired */ | |
| 86 | −static void _drx_release_fw(struct drx397xD_state *s, enum fw_ix ix) | |
| 87 | −{ | |
| 88 | − memset(&fw[ix].data[0], 0, sizeof(fw[0].data)); | |
| 89 | − if (fw[ix].file) | |
| 90 | − release_firmware(fw[ix].file); | |
| 91 | −} | |
| 92 | − | |
| 93 | −static void drx_release_fw(struct drx397xD_state *s) | |
| 94 | −{ | |
| 95 | − enum fw_ix ix = s->chip_rev; | |
| 96 | − | |
| 97 | − pr_debug("%s\n", __func__); | |
| 98 | − | |
| 99 | − write_lock(&fw[ix].lock); | |
| 100 | − if (fw[ix].refcnt) { | |
| 101 | − fw[ix].refcnt--; | |
| 102 | − if (fw[ix].refcnt == 0) | |
| 103 | − _drx_release_fw(s, ix); | |
| 104 | − } | |
| 105 | − write_unlock(&fw[ix].lock); | |
| 106 | −} | |
| 107 | − | |
| 108 | −static int drx_load_fw(struct drx397xD_state *s, enum fw_ix ix) | |
| 109 | −{ | |
| 110 | − const u8 *data; | |
| 111 | − size_t size, len; | |
| 112 | − int i = 0, j, rc = -EINVAL; | |
| 113 | − | |
| 114 | − pr_debug("%s\n", __func__); | |
| 115 | − | |
| 116 | − if (ix < 0 || ix >= ARRAY_SIZE(fw)) | |
| 117 | − return -EINVAL; | |
| 118 | − s->chip_rev = ix; | |
| 119 | − | |
| 120 | − write_lock(&fw[ix].lock); | |
| 121 | − if (fw[ix].file) { | |
| 122 | − rc = 0; | |
| 123 | − goto exit_ok; | |
| 124 | − } | |
| 125 | − memset(&fw[ix].data[0], 0, sizeof(fw[0].data)); | |
| 126 | − | |
| 127 | − rc = request_firmware(&fw[ix].file, fw[ix].name, s->i2c->dev.parent); | |
| 128 | − if (rc != 0) { | |
| 129 | − printk(KERN_ERR "%s: Firmware \"%s\" not available\n", | |
| 130 | − mod_name, fw[ix].name); | |
| 131 | − goto exit_err; | |
| 132 | − } | |
| 133 | − | |
| 134 | − if (!fw[ix].file->data || fw[ix].file->size < 10) | |
| 135 | − goto exit_corrupt; | |
| 136 | − | |
| 137 | − data = fw[ix].file->data; | |
| 138 | − size = fw[ix].file->size; | |
| 139 | − | |
| 140 | − if (data[i++] != 2) /* check firmware version */ | |
| 141 | − goto exit_corrupt; | |
| 142 | − | |
| 143 | − do { | |
| 144 | − switch (data[i++]) { | |
| 145 | − case 0x00: /* bytecode */ | |
| 146 | − if (i >= size) | |
| 147 | − break; | |
| 148 | − i += data[i]; | |
| 149 | − case 0x01: /* reset */ | |
| 150 | − case 0x02: /* sleep */ | |
| 151 | − i++; | |
| 152 | − break; | |
| 153 | − case 0xfe: /* name */ | |
| 154 | − len = strnlen(&data[i], size - i); | |
| 155 | − if (i + len + 1 >= size) | |
| 156 | − goto exit_corrupt; | |
| 157 | − if (data[i + len + 1] != 0) | |
| 158 | − goto exit_corrupt; | |
| 159 | − for (j = 0; j < ARRAY_SIZE(blob_name); j++) { | |
| 160 | − if (strcmp(blob_name[j], &data[i]) == 0) { | |
| 161 | − fw[ix].data[j] = &data[i + len + 1]; | |
| 162 | − pr_debug("Loading %s\n", blob_name[j]); | |
| 163 | − } | |
| 164 | − } | |
| 165 | − i += len + 1; | |
| 166 | − break; | |
| 167 | − case 0xff: /* file terminator */ | |
| 168 | − if (i == size) { | |
| 169 | − rc = 0; | |
| 170 | − goto exit_ok; | |
| 171 | − } | |
| 172 | − default: | |
| 173 | − goto exit_corrupt; | |
| 174 | − } | |
| 175 | − } while (i < size); | |
| 176 | − | |
| 177 | −exit_corrupt: | |
| 178 | − printk(KERN_ERR "%s: Firmware is corrupt\n", mod_name); | |
| 179 | −exit_err: | |
| 180 | − _drx_release_fw(s, ix); | |
| 181 | − fw[ix].refcnt--; | |
| 182 | −exit_ok: | |
| 183 | − fw[ix].refcnt++; | |
| 184 | − write_unlock(&fw[ix].lock); | |
| 185 | − | |
| 186 | − return rc; | |
| 187 | −} | |
| 188 | − | |
| 189 | −/* i2c bus IO */ | |
| 190 | −static int write_fw(struct drx397xD_state *s, enum blob_ix ix) | |
| 191 | −{ | |
| 192 | − const u8 *data; | |
| 193 | − int len, rc = 0, i = 0; | |
| 194 | − struct i2c_msg msg = { | |
| 195 | − .addr = s->config.demod_address, | |
| 196 | − .flags = 0 | |
| 197 | − }; | |
| 198 | − | |
| 199 | − if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) { | |
| 200 | − pr_debug("%s drx_fw_ix_t out of range\n", __func__); | |
| 201 | − return -EINVAL; | |
| 202 | − } | |
| 203 | − pr_debug("%s %s\n", __func__, blob_name[ix]); | |
| 204 | − | |
| 205 | − read_lock(&fw[s->chip_rev].lock); | |
| 206 | − data = fw[s->chip_rev].data[ix]; | |
| 207 | − if (!data) { | |
| 208 | − rc = -EINVAL; | |
| 209 | − goto exit_rc; | |
| 210 | − } | |
| 211 | − | |
| 212 | − for (;;) { | |
| 213 | − switch (data[i++]) { | |
| 214 | − case 0: /* bytecode */ | |
| 215 | − len = data[i++]; | |
| 216 | − msg.len = len; | |
| 217 | − msg.buf = (__u8 *) &data[i]; | |
| 218 | − if (i2c_transfer(s->i2c, &msg, 1) != 1) { | |
| 219 | − rc = -EIO; | |
| 220 | − goto exit_rc; | |
| 221 | − } | |
| 222 | − i += len; | |
| 223 | − break; | |
| 224 | − case 1: /* reset */ | |
| 225 | − case 2: /* sleep */ | |
| 226 | − i++; | |
| 227 | − break; | |
| 228 | − default: | |
| 229 | − goto exit_rc; | |
| 230 | − } | |
| 231 | − } | |
| 232 | −exit_rc: | |
| 233 | − read_unlock(&fw[s->chip_rev].lock); | |
| 234 | − | |
| 235 | − return rc; | |
| 236 | −} | |
| 237 | − | |
| 238 | −/* Function is not endian safe, use the RD16 wrapper below */ | |
| 239 | −static int _read16(struct drx397xD_state *s, __le32 i2c_adr) | |
| 240 | −{ | |
| 241 | − int rc; | |
| 242 | − u8 a[4]; | |
| 243 | − __le16 v; | |
| 244 | − struct i2c_msg msg[2] = { | |
| 245 | − { | |
| 246 | − .addr = s->config.demod_address, | |
| 247 | − .flags = 0, | |
| 248 | − .buf = a, | |
| 249 | − .len = sizeof(a) | |
| 250 | − }, { | |
| 251 | − .addr = s->config.demod_address, | |
| 252 | − .flags = I2C_M_RD, | |
| 253 | − .buf = (u8 *)&v, | |
| 254 | − .len = sizeof(v) | |
| 255 | − } | |
| 256 | − }; | |
| 257 | − | |
| 258 | − *(__le32 *) a = i2c_adr; | |
| 259 | − | |
| 260 | − rc = i2c_transfer(s->i2c, msg, 2); | |
| 261 | − if (rc != 2) | |
| 262 | − return -EIO; | |
| 263 | − | |
| 264 | − return le16_to_cpu(v); | |
| 265 | −} | |
| 266 | − | |
| 267 | −/* Function is not endian safe, use the WR16.. wrappers below */ | |
| 268 | −static int _write16(struct drx397xD_state *s, __le32 i2c_adr, __le16 val) | |
| 269 | −{ | |
| 270 | − u8 a[6]; | |
| 271 | − int rc; | |
| 272 | − struct i2c_msg msg = { | |
| 273 | − .addr = s->config.demod_address, | |
| 274 | − .flags = 0, | |
| 275 | − .buf = a, | |
| 276 | − .len = sizeof(a) | |
| 277 | − }; | |
| 278 | − | |
| 279 | − *(__le32 *)a = i2c_adr; | |
| 280 | − *(__le16 *)&a[4] = val; | |
| 281 | − | |
| 282 | − rc = i2c_transfer(s->i2c, &msg, 1); | |
| 283 | − if (rc != 1) | |
| 284 | − return -EIO; | |
| 285 | − | |
| 286 | − return 0; | |
| 287 | −} | |
| 288 | − | |
| 289 | −#define WR16(ss, adr, val) \ | |
| 290 | − _write16(ss, I2C_ADR_C0(adr), cpu_to_le16(val)) | |
| 291 | −#define WR16_E0(ss, adr, val) \ | |
| 292 | − _write16(ss, I2C_ADR_E0(adr), cpu_to_le16(val)) | |
| 293 | −#define RD16(ss, adr) \ | |
| 294 | − _read16(ss, I2C_ADR_C0(adr)) | |
| 295 | − | |
| 296 | −#define EXIT_RC(cmd) \ | |
| 297 | − if ((rc = (cmd)) < 0) \ | |
| 298 | − goto exit_rc | |
| 299 | − | |
| 300 | −/* Tuner callback */ | |
| 301 | −static int PLL_Set(struct drx397xD_state *s, | |
| 302 | − struct dvb_frontend_parameters *fep, int *df_tuner) | |
| 303 | −{ | |
| 304 | − struct dvb_frontend *fe = &s->frontend; | |
| 305 | − u32 f_tuner, f = fep->frequency; | |
| 306 | − int rc; | |
| 307 | − | |
| 308 | − pr_debug("%s\n", __func__); | |
| 309 | − | |
| 310 | − if ((f > s->frontend.ops.tuner_ops.info.frequency_max) || | |
| 311 | − (f < s->frontend.ops.tuner_ops.info.frequency_min)) | |
| 312 | − return -EINVAL; | |
| 313 | − | |
| 314 | − *df_tuner = 0; | |
| 315 | − if (!s->frontend.ops.tuner_ops.set_params || | |
| 316 | − !s->frontend.ops.tuner_ops.get_frequency) | |
| 317 | − return -ENOSYS; | |
| 318 | − | |
| 319 | − rc = s->frontend.ops.tuner_ops.set_params(fe, fep); | |
| 320 | − if (rc < 0) | |
| 321 | − return rc; | |
| 322 | − | |
| 323 | − rc = s->frontend.ops.tuner_ops.get_frequency(fe, &f_tuner); | |
| 324 | − if (rc < 0) | |
| 325 | − return rc; | |
| 326 | − | |
| 327 | − *df_tuner = f_tuner - f; | |
| 328 | − pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __func__, f, | |
| 329 | − f_tuner); | |
| 330 | − | |
| 331 | − return 0; | |
| 332 | −} | |
| 333 | − | |
| 334 | −/* Demodulator helper functions */ | |
| 335 | −static int SC_WaitForReady(struct drx397xD_state *s) | |
| 336 | −{ | |
| 337 | − int cnt = 1000; | |
| 338 | − int rc; | |
| 339 | − | |
| 340 | − pr_debug("%s\n", __func__); | |
| 341 | − | |
| 342 | − while (cnt--) { | |
| 343 | − rc = RD16(s, 0x820043); | |
| 344 | − if (rc == 0) | |
| 345 | − return 0; | |
| 346 | − } | |
| 347 | − | |
| 348 | − return -1; | |
| 349 | −} | |
| 350 | − | |
| 351 | −static int SC_SendCommand(struct drx397xD_state *s, int cmd) | |
| 352 | −{ | |
| 353 | − int rc; | |
| 354 | − | |
| 355 | − pr_debug("%s\n", __func__); | |
| 356 | − | |
| 357 | − WR16(s, 0x820043, cmd); | |
| 358 | − SC_WaitForReady(s); | |
| 359 | − rc = RD16(s, 0x820042); | |
| 360 | − if ((rc & 0xffff) == 0xffff) | |
| 361 | − return -1; | |
| 362 | − | |
| 363 | − return 0; | |
| 364 | −} | |
| 365 | − | |
| 366 | −static int HI_Command(struct drx397xD_state *s, u16 cmd) | |
| 367 | −{ | |
| 368 | − int rc, cnt = 1000; | |
| 369 | − | |
| 370 | − pr_debug("%s\n", __func__); | |
| 371 | − | |
| 372 | − rc = WR16(s, 0x420032, cmd); | |
| 373 | − if (rc < 0) | |
| 374 | − return rc; | |
| 375 | − | |
| 376 | − do { | |
| 377 | − rc = RD16(s, 0x420032); | |
| 378 | − if (rc == 0) { | |
| 379 | − rc = RD16(s, 0x420031); | |
| 380 | − return rc; | |
| 381 | − } | |
| 382 | − if (rc < 0) | |
| 383 | − return rc; | |
| 384 | − } while (--cnt); | |
| 385 | − | |
| 386 | − return rc; | |
| 387 | −} | |
| 388 | − | |
| 389 | −static int HI_CfgCommand(struct drx397xD_state *s) | |
| 390 | −{ | |
| 391 | − | |
| 392 | − pr_debug("%s\n", __func__); | |
| 393 | − | |
| 394 | − WR16(s, 0x420033, 0x3973); | |
| 395 | − WR16(s, 0x420034, s->config.w50); /* code 4, log 4 */ | |
| 396 | − WR16(s, 0x420035, s->config.w52); /* code 15, log 9 */ | |
| 397 | − WR16(s, 0x420036, s->config.demod_address << 1); | |
| 398 | − WR16(s, 0x420037, s->config.w56); /* code (set_i2c ?? initX 1 ), log 1 */ | |
| 399 | − /* WR16(s, 0x420033, 0x3973); */ | |
| 400 | − if ((s->config.w56 & 8) == 0) | |
| 401 | − return HI_Command(s, 3); | |
| 402 | − | |
| 403 | − return WR16(s, 0x420032, 0x3); | |
| 404 | −} | |
| 405 | − | |
| 406 | −static const u8 fastIncrDecLUT_15273[] = { | |
| 407 | − 0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14, | |
| 408 | − 0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f | |
| 409 | −}; | |
| 410 | − | |
| 411 | −static const u8 slowIncrDecLUT_15272[] = { | |
| 412 | − 3, 4, 4, 5, 6 | |
| 413 | −}; | |
| 414 | − | |
| 415 | −static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc) | |
| 416 | −{ | |
| 417 | − u16 w06 = agc->w06; | |
| 418 | − u16 w08 = agc->w08; | |
| 419 | − u16 w0A = agc->w0A; | |
| 420 | − u16 w0C = agc->w0C; | |
| 421 | − int quot, rem, i, rc = -EINVAL; | |
| 422 | − | |
| 423 | − pr_debug("%s\n", __func__); | |
| 424 | − | |
| 425 | − if (agc->w04 > 0x3ff) | |
| 426 | − goto exit_rc; | |
| 427 | − | |
| 428 | − if (agc->d00 == 1) { | |
| 429 | − EXIT_RC(RD16(s, 0x0c20010)); | |
| 430 | − rc &= ~0x10; | |
| 431 | − EXIT_RC(WR16(s, 0x0c20010, rc)); | |
| 432 | − return WR16(s, 0x0c20030, agc->w04 & 0x7ff); | |
| 433 | − } | |
| 434 | − | |
| 435 | − if (agc->d00 != 0) | |
| 436 | − goto exit_rc; | |
| 437 | − if (w0A < w08) | |
| 438 | − goto exit_rc; | |
| 439 | − if (w0A > 0x3ff) | |
| 440 | − goto exit_rc; | |
| 441 | − if (w0C > 0x3ff) | |
| 442 | − goto exit_rc; | |
| 443 | − if (w06 > 0x3ff) | |
| 444 | − goto exit_rc; | |
| 445 | − | |
| 446 | − EXIT_RC(RD16(s, 0x0c20010)); | |
| 447 | − rc |= 0x10; | |
| 448 | − EXIT_RC(WR16(s, 0x0c20010, rc)); | |
| 449 | − | |
| 450 | − EXIT_RC(WR16(s, 0x0c20025, (w06 >> 1) & 0x1ff)); | |
| 451 | − EXIT_RC(WR16(s, 0x0c20031, (w0A - w08) >> 1)); | |
| 452 | − EXIT_RC(WR16(s, 0x0c20032, ((w0A + w08) >> 1) - 0x1ff)); | |
| 453 | − | |
| 454 | − quot = w0C / 113; | |
| 455 | − rem = w0C % 113; | |
| 456 | − if (quot <= 8) { | |
| 457 | − quot = 8 - quot; | |
| 458 | − } else { | |
| 459 | − quot = 0; | |
| 460 | − rem += 113; | |
| 461 | − } | |
| 462 | − | |
| 463 | − EXIT_RC(WR16(s, 0x0c20024, quot)); | |
| 464 | − | |
| 465 | − i = fastIncrDecLUT_15273[rem / 8]; | |
| 466 | − EXIT_RC(WR16(s, 0x0c2002d, i)); | |
| 467 | − EXIT_RC(WR16(s, 0x0c2002e, i)); | |
| 468 | − | |
| 469 | − i = slowIncrDecLUT_15272[rem / 28]; | |
| 470 | − EXIT_RC(WR16(s, 0x0c2002b, i)); | |
| 471 | − rc = WR16(s, 0x0c2002c, i); | |
| 472 | −exit_rc: | |
| 473 | − return rc; | |
| 474 | −} | |
| 475 | − | |
| 476 | −static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc) | |
| 477 | −{ | |
| 478 | − u16 w04 = agc->w04; | |
| 479 | − u16 w06 = agc->w06; | |
| 480 | − int rc = -1; | |
| 481 | − | |
| 482 | − pr_debug("%s %d 0x%x 0x%x\n", __func__, agc->d00, w04, w06); | |
| 483 | − | |
| 484 | − if (w04 > 0x3ff) | |
| 485 | − goto exit_rc; | |
| 486 | − | |
| 487 | − switch (agc->d00) { | |
| 488 | − case 1: | |
| 489 | − if (w04 == 0x3ff) | |
| 490 | − w04 = 0x400; | |
| 491 | − | |
| 492 | − EXIT_RC(WR16(s, 0x0c20036, w04)); | |
| 493 | − s->config.w9C &= ~2; | |
| 494 | − EXIT_RC(WR16(s, 0x0c20015, s->config.w9C)); | |
| 495 | − EXIT_RC(RD16(s, 0x0c20010)); | |
| 496 | − rc &= 0xbfdf; | |
| 497 | − EXIT_RC(WR16(s, 0x0c20010, rc)); | |
| 498 | − EXIT_RC(RD16(s, 0x0c20013)); | |
| 499 | − rc &= ~2; | |
| 500 | − break; | |
| 501 | − case 0: | |
| 502 | − /* loc_8000659 */ | |
| 503 | − s->config.w9C &= ~2; | |
| 504 | − EXIT_RC(WR16(s, 0x0c20015, s->config.w9C)); | |
| 505 | − EXIT_RC(RD16(s, 0x0c20010)); | |
| 506 | − rc &= 0xbfdf; | |
| 507 | − rc |= 0x4000; | |
| 508 | − EXIT_RC(WR16(s, 0x0c20010, rc)); | |
| 509 | − EXIT_RC(WR16(s, 0x0c20051, (w06 >> 4) & 0x3f)); | |
| 510 | − EXIT_RC(RD16(s, 0x0c20013)); | |
| 511 | − rc &= ~2; | |
| 512 | − break; | |
| 513 | − default: | |
| 514 | − s->config.w9C |= 2; | |
| 515 | − EXIT_RC(WR16(s, 0x0c20015, s->config.w9C)); | |
| 516 | − EXIT_RC(RD16(s, 0x0c20010)); | |
| 517 | − rc &= 0xbfdf; | |
| 518 | − EXIT_RC(WR16(s, 0x0c20010, rc)); | |
| 519 | − | |
| 520 | − EXIT_RC(WR16(s, 0x0c20036, 0)); | |
| 521 | − | |
| 522 | − EXIT_RC(RD16(s, 0x0c20013)); | |
| 523 | − rc |= 2; | |
| 524 | − } | |
| 525 | − rc = WR16(s, 0x0c20013, rc); | |
| 526 | − | |
| 527 | −exit_rc: | |
| 528 | − return rc; | |
| 529 | −} | |
| 530 | − | |
| 531 | −static int GetLockStatus(struct drx397xD_state *s, int *lockstat) | |
| 532 | −{ | |
| 533 | − int rc; | |
| 534 | − | |
| 535 | − *lockstat = 0; | |
| 536 | − | |
| 537 | − rc = RD16(s, 0x082004b); | |
| 538 | − if (rc < 0) | |
| 539 | − return rc; | |
| 540 | − | |
| 541 | − if (s->config.d60 != 2) | |
| 542 | − return 0; | |
| 543 | − | |
| 544 | − if ((rc & 7) == 7) | |
| 545 | − *lockstat |= 1; | |
| 546 | − if ((rc & 3) == 3) | |
| 547 | − *lockstat |= 2; | |
| 548 | − if (rc & 1) | |
| 549 | − *lockstat |= 4; | |
| 550 | − return 0; | |
| 551 | −} | |
| 552 | − | |
| 553 | −static int CorrectSysClockDeviation(struct drx397xD_state *s) | |
| 554 | −{ | |
| 555 | − int rc = -EINVAL; | |
| 556 | − int lockstat; | |
| 557 | − u32 clk, clk_limit; | |
| 558 | − | |
| 559 | − pr_debug("%s\n", __func__); | |
| 560 | − | |
| 561 | − if (s->config.d5C == 0) { | |
| 562 | − EXIT_RC(WR16(s, 0x08200e8, 0x010)); | |
| 563 | − EXIT_RC(WR16(s, 0x08200e9, 0x113)); | |
| 564 | − s->config.d5C = 1; | |
| 565 | − return rc; | |
| 566 | − } | |
| 567 | − if (s->config.d5C != 1) | |
| 568 | − goto exit_rc; | |
| 569 | − | |
| 570 | − rc = RD16(s, 0x0820048); | |
| 571 | − | |
| 572 | − rc = GetLockStatus(s, &lockstat); | |
| 573 | − if (rc < 0) | |
| 574 | − goto exit_rc; | |
| 575 | − if ((lockstat & 1) == 0) | |
| 576 | − goto exit_rc; | |
| 577 | − | |
| 578 | − EXIT_RC(WR16(s, 0x0420033, 0x200)); | |
| 579 | − EXIT_RC(WR16(s, 0x0420034, 0xc5)); | |
| 580 | − EXIT_RC(WR16(s, 0x0420035, 0x10)); | |
| 581 | − EXIT_RC(WR16(s, 0x0420036, 0x1)); | |
| 582 | − EXIT_RC(WR16(s, 0x0420037, 0xa)); | |
| 583 | − EXIT_RC(HI_Command(s, 6)); | |
| 584 | − EXIT_RC(RD16(s, 0x0420040)); | |
| 585 | − clk = rc; | |
| 586 | − EXIT_RC(RD16(s, 0x0420041)); | |
| 587 | − clk |= rc << 16; | |
| 588 | − | |
| 589 | − if (clk <= 0x26ffff) | |
| 590 | − goto exit_rc; | |
| 591 | − if (clk > 0x610000) | |
| 592 | − goto exit_rc; | |
| 593 | − | |
| 594 | − if (!s->bandwidth_parm) | |
| 595 | − return -EINVAL; | |
| 596 | − | |
| 597 | − /* round & convert to Hz */ | |
| 598 | − clk = ((u64) (clk + 0x800000) * s->bandwidth_parm + (1 << 20)) >> 21; | |
| 599 | − clk_limit = s->config.f_osc * MAX_CLOCK_DRIFT / 1000; | |
| 600 | − | |
| 601 | − if (clk - s->config.f_osc * 1000 + clk_limit <= 2 * clk_limit) { | |
| 602 | − s->f_osc = clk; | |
| 603 | − pr_debug("%s: osc %d %d [Hz]\n", __func__, | |
| 604 | − s->config.f_osc * 1000, clk - s->config.f_osc * 1000); | |
| 605 | − } | |
| 606 | − rc = WR16(s, 0x08200e8, 0); | |
| 607 | − | |
| 608 | −exit_rc: | |
| 609 | − return rc; | |
| 610 | −} | |
| 611 | − | |
| 612 | −static int ConfigureMPEGOutput(struct drx397xD_state *s, int type) | |
| 613 | −{ | |
| 614 | − int rc, si, bp; | |
| 615 | − | |
| 616 | − pr_debug("%s\n", __func__); | |
| 617 | − | |
| 618 | − si = s->config.wA0; | |
| 619 | − if (s->config.w98 == 0) { | |
| 620 | − si |= 1; | |
| 621 | − bp = 0; | |
| 622 | − } else { | |
| 623 | − si &= ~1; | |
| 624 | − bp = 0x200; | |
| 625 | − } | |
| 626 | − if (s->config.w9A == 0) | |
| 627 | − si |= 0x80; | |
| 628 | − else | |
| 629 | − si &= ~0x80; | |
| 630 | − | |
| 631 | − EXIT_RC(WR16(s, 0x2150045, 0)); | |
| 632 | − EXIT_RC(WR16(s, 0x2150010, si)); | |
| 633 | − EXIT_RC(WR16(s, 0x2150011, bp)); | |
| 634 | − rc = WR16(s, 0x2150012, (type == 0 ? 0xfff : 0)); | |
| 635 | − | |
| 636 | −exit_rc: | |
| 637 | − return rc; | |
| 638 | −} | |
| 639 | − | |
| 640 | −static int drx_tune(struct drx397xD_state *s, | |
| 641 | − struct dvb_frontend_parameters *fep) | |
| 642 | −{ | |
| 643 | − u16 v22 = 0; | |
| 644 | − u16 v1C = 0; | |
| 645 | − u16 v1A = 0; | |
| 646 | − u16 v18 = 0; | |
| 647 | − u32 edi = 0, ebx = 0, ebp = 0, edx = 0; | |
| 648 | − u16 v20 = 0, v1E = 0, v16 = 0, v14 = 0, v12 = 0, v10 = 0, v0E = 0; | |
| 649 | − | |
| 650 | − int rc, df_tuner = 0; | |
| 651 | − int a, b, c, d; | |
| 652 | − pr_debug("%s %d\n", __func__, s->config.d60); | |
| 653 | − | |
| 654 | − if (s->config.d60 != 2) | |
| 655 | − goto set_tuner; | |
| 656 | − rc = CorrectSysClockDeviation(s); | |
| 657 | − if (rc < 0) | |
| 658 | − goto set_tuner; | |
| 659 | − | |
| 660 | − s->config.d60 = 1; | |
| 661 | − rc = ConfigureMPEGOutput(s, 0); | |
| 662 | − if (rc < 0) | |
| 663 | − goto set_tuner; | |
| 664 | −set_tuner: | |
| 665 | − | |
| 666 | − rc = PLL_Set(s, fep, &df_tuner); | |
| 667 | − if (rc < 0) { | |
| 668 | − printk(KERN_ERR "Error in pll_set\n"); | |
| 669 | − goto exit_rc; | |
| 670 | − } | |
| 671 | − msleep(200); | |
| 672 | − | |
| 673 | − a = rc = RD16(s, 0x2150016); | |
| 674 | − if (rc < 0) | |
| 675 | − goto exit_rc; | |
| 676 | − b = rc = RD16(s, 0x2150010); | |
| 677 | − if (rc < 0) | |
| 678 | − goto exit_rc; | |
| 679 | − c = rc = RD16(s, 0x2150034); | |
| 680 | − if (rc < 0) | |
| 681 | − goto exit_rc; | |
| 682 | − d = rc = RD16(s, 0x2150035); | |
| 683 | − if (rc < 0) | |
| 684 | − goto exit_rc; | |
| 685 | − rc = WR16(s, 0x2150014, c); | |
| 686 | − rc = WR16(s, 0x2150015, d); | |
| 687 | − rc = WR16(s, 0x2150010, 0); | |
| 688 | − rc = WR16(s, 0x2150000, 2); | |
| 689 | − rc = WR16(s, 0x2150036, 0x0fff); | |
| 690 | − rc = WR16(s, 0x2150016, a); | |
| 691 | − | |
| 692 | − rc = WR16(s, 0x2150010, 2); | |
| 693 | − rc = WR16(s, 0x2150007, 0); | |
| 694 | − rc = WR16(s, 0x2150000, 1); | |
| 695 | − rc = WR16(s, 0x2110000, 0); | |
| 696 | − rc = WR16(s, 0x0800000, 0); | |
| 697 | − rc = WR16(s, 0x2800000, 0); | |
| 698 | − rc = WR16(s, 0x2110010, 0x664); | |
| 699 | − | |
| 700 | − rc = write_fw(s, DRXD_ResetECRAM); | |
| 701 | − rc = WR16(s, 0x2110000, 1); | |
| 702 | − | |
| 703 | − rc = write_fw(s, DRXD_InitSC); | |
| 704 | − if (rc < 0) | |
| 705 | − goto exit_rc; | |
| 706 | − | |
| 707 | − rc = SetCfgIfAgc(s, &s->config.ifagc); | |
| 708 | − if (rc < 0) | |
| 709 | − goto exit_rc; | |
| 710 | − | |
| 711 | − rc = SetCfgRfAgc(s, &s->config.rfagc); | |
| 712 | − if (rc < 0) | |
| 713 | − goto exit_rc; | |
| 714 | − | |
| 715 | − if (fep->u.ofdm.transmission_mode != TRANSMISSION_MODE_2K) | |
| 716 | − v22 = 1; | |
| 717 | − switch (fep->u.ofdm.transmission_mode) { | |
| 718 | − case TRANSMISSION_MODE_8K: | |
| 719 | − edi = 1; | |
| 720 | − if (s->chip_rev == DRXD_FW_B1) | |
| 721 | − break; | |
| 722 | − | |
| 723 | − rc = WR16(s, 0x2010010, 0); | |
| 724 | − if (rc < 0) | |
| 725 | − break; | |
| 726 | − v1C = 0x63; | |
| 727 | − v1A = 0x53; | |
| 728 | − v18 = 0x43; | |
| 729 | − break; | |
| 730 | − default: | |
| 731 | − edi = 0; | |
| 732 | − if (s->chip_rev == DRXD_FW_B1) | |
| 733 | − break; | |
| 734 | − | |
| 735 | − rc = WR16(s, 0x2010010, 1); | |
| 736 | − if (rc < 0) | |
| 737 | − break; | |
| 738 | − | |
| 739 | − v1C = 0x61; | |
| 740 | − v1A = 0x47; | |
| 741 | − v18 = 0x41; | |
| 742 | − } | |
| 743 | − | |
| 744 | − switch (fep->u.ofdm.guard_interval) { | |
| 745 | − case GUARD_INTERVAL_1_4: | |
| 746 | − edi |= 0x0c; | |
| 747 | − break; | |
| 748 | − case GUARD_INTERVAL_1_8: | |
| 749 | − edi |= 0x08; | |
| 750 | − break; | |
| 751 | − case GUARD_INTERVAL_1_16: | |
| 752 | − edi |= 0x04; | |
| 753 | − break; | |
| 754 | − case GUARD_INTERVAL_1_32: | |
| 755 | − break; | |
| 756 | − default: | |
| 757 | − v22 |= 2; | |
| 758 | − } | |
| 759 | − | |
| 760 | − ebx = 0; | |
| 761 | − ebp = 0; | |
| 762 | − v20 = 0; | |
| 763 | − v1E = 0; | |
| 764 | − v16 = 0; | |
| 765 | − v14 = 0; | |
| 766 | − v12 = 0; | |
| 767 | − v10 = 0; | |
| 768 | − v0E = 0; | |
| 769 | − | |
| 770 | − switch (fep->u.ofdm.hierarchy_information) { | |
| 771 | − case HIERARCHY_1: | |
| 772 | − edi |= 0x40; | |
| 773 | − if (s->chip_rev == DRXD_FW_B1) | |
| 774 | − break; | |
| 775 | − rc = WR16(s, 0x1c10047, 1); | |
| 776 | − if (rc < 0) | |
| 777 | − goto exit_rc; | |
| 778 | − rc = WR16(s, 0x2010012, 1); | |
| 779 | − if (rc < 0) | |
| 780 | − goto exit_rc; | |
| 781 | − ebx = 0x19f; | |
| 782 | − ebp = 0x1fb; | |
| 783 | − v20 = 0x0c0; | |
| 784 | − v1E = 0x195; | |
| 785 | − v16 = 0x1d6; | |
| 786 | − v14 = 0x1ef; | |
| 787 | − v12 = 4; | |
| 788 | − v10 = 5; | |
| 789 | − v0E = 5; | |
| 790 | − break; | |
| 791 | − case HIERARCHY_2: | |
| 792 | − edi |= 0x80; | |
| 793 | − if (s->chip_rev == DRXD_FW_B1) | |
| 794 | − break; | |
| 795 | − rc = WR16(s, 0x1c10047, 2); | |
| 796 | − if (rc < 0) | |
| 797 | − goto exit_rc; | |
| 798 | − rc = WR16(s, 0x2010012, 2); | |
| 799 | − if (rc < 0) | |
| 800 | − goto exit_rc; | |
| 801 | − ebx = 0x08f; | |
| 802 | − ebp = 0x12f; | |
| 803 | − v20 = 0x0c0; | |
| 804 | − v1E = 0x11e; | |
| 805 | − v16 = 0x1d6; | |
| 806 | − v14 = 0x15e; | |
| 807 | − v12 = 4; | |
| 808 | − v10 = 5; | |
| 809 | − v0E = 5; | |
| 810 | − break; | |
| 811 | − case HIERARCHY_4: | |
| 812 | − edi |= 0xc0; | |
| 813 | − if (s->chip_rev == DRXD_FW_B1) | |
| 814 | − break; | |
| 815 | − rc = WR16(s, 0x1c10047, 3); | |
| 816 | − if (rc < 0) | |
| 817 | − goto exit_rc; | |
| 818 | − rc = WR16(s, 0x2010012, 3); | |
| 819 | − if (rc < 0) | |
| 820 | − goto exit_rc; | |
| 821 | − ebx = 0x14d; | |
| 822 | − ebp = 0x197; | |
| 823 | − v20 = 0x0c0; | |
| 824 | − v1E = 0x1ce; | |
| 825 | − v16 = 0x1d6; | |
| 826 | − v14 = 0x11a; | |
| 827 | − v12 = 4; | |
| 828 | − v10 = 6; | |
| 829 | − v0E = 5; | |
| 830 | − break; | |
| 831 | − default: | |
| 832 | − v22 |= 8; | |
| 833 | − if (s->chip_rev == DRXD_FW_B1) | |
| 834 | − break; | |
| 835 | − rc = WR16(s, 0x1c10047, 0); | |
| 836 | − if (rc < 0) | |
| 837 | − goto exit_rc; | |
| 838 | − rc = WR16(s, 0x2010012, 0); | |
| 839 | − if (rc < 0) | |
| 840 | − goto exit_rc; | |
| 841 | − /* QPSK QAM16 QAM64 */ | |
| 842 | − ebx = 0x19f; /* 62 */ | |
| 843 | − ebp = 0x1fb; /* 15 */ | |
| 844 | − v20 = 0x16a; /* 62 */ | |
| 845 | − v1E = 0x195; /* 62 */ | |
| 846 | − v16 = 0x1bb; /* 15 */ | |
| 847 | − v14 = 0x1ef; /* 15 */ | |
| 848 | − v12 = 5; /* 16 */ | |
| 849 | − v10 = 5; /* 16 */ | |
| 850 | − v0E = 5; /* 16 */ | |
| 851 | − } | |
| 852 | − | |
| 853 | − switch (fep->u.ofdm.constellation) { | |
| 854 | − default: | |
| 855 | − v22 |= 4; | |
| 856 | − case QPSK: | |
| 857 | − if (s->chip_rev == DRXD_FW_B1) | |
| 858 | − break; | |
| 859 | − | |
| 860 | − rc = WR16(s, 0x1c10046, 0); | |
| 861 | − if (rc < 0) | |
| 862 | − goto exit_rc; | |
| 863 | − rc = WR16(s, 0x2010011, 0); | |
| 864 | − if (rc < 0) | |
| 865 | − goto exit_rc; | |
| 866 | − rc = WR16(s, 0x201001a, 0x10); | |
| 867 | − if (rc < 0) | |
| 868 | − goto exit_rc; | |
| 869 | − rc = WR16(s, 0x201001b, 0); | |
| 870 | − if (rc < 0) | |
| 871 | − goto exit_rc; | |
| 872 | − rc = WR16(s, 0x201001c, 0); | |
| 873 | − if (rc < 0) | |
| 874 | − goto exit_rc; | |
| 875 | − rc = WR16(s, 0x1c10062, v20); | |
| 876 | − if (rc < 0) | |
| 877 | − goto exit_rc; | |
| 878 | − rc = WR16(s, 0x1c1002a, v1C); | |
| 879 | − if (rc < 0) | |
| 880 | − goto exit_rc; | |
| 881 | − rc = WR16(s, 0x1c10015, v16); | |
| 882 | − if (rc < 0) | |
| 883 | − goto exit_rc; | |
| 884 | − rc = WR16(s, 0x1c10016, v12); | |
| 885 | − if (rc < 0) | |
| 886 | − goto exit_rc; | |
| 887 | − break; | |
| 888 | − case QAM_16: | |
| 889 | − edi |= 0x10; | |
| 890 | − if (s->chip_rev == DRXD_FW_B1) | |
| 891 | − break; | |
| 892 | − | |
| 893 | − rc = WR16(s, 0x1c10046, 1); | |
| 894 | − if (rc < 0) | |
| 895 | − goto exit_rc; | |
| 896 | − rc = WR16(s, 0x2010011, 1); | |
| 897 | − if (rc < 0) | |
| 898 | − goto exit_rc; | |
| 899 | − rc = WR16(s, 0x201001a, 0x10); | |
| 900 | − if (rc < 0) | |
| 901 | − goto exit_rc; | |
| 902 | − rc = WR16(s, 0x201001b, 4); | |
| 903 | − if (rc < 0) | |
| 904 | − goto exit_rc; | |
| 905 | − rc = WR16(s, 0x201001c, 0); | |
| 906 | − if (rc < 0) | |
| 907 | − goto exit_rc; | |
| 908 | − rc = WR16(s, 0x1c10062, v1E); | |
| 909 | − if (rc < 0) | |
| 910 | − goto exit_rc; | |
| 911 | − rc = WR16(s, 0x1c1002a, v1A); | |
| 912 | − if (rc < 0) | |
| 913 | − goto exit_rc; | |
| 914 | − rc = WR16(s, 0x1c10015, v14); | |
| 915 | − if (rc < 0) | |
| 916 | − goto exit_rc; | |
| 917 | − rc = WR16(s, 0x1c10016, v10); | |
| 918 | − if (rc < 0) | |
| 919 | − goto exit_rc; | |
| 920 | − break; | |
| 921 | − case QAM_64: | |
| 922 | − edi |= 0x20; | |
| 923 | − rc = WR16(s, 0x1c10046, 2); | |
| 924 | − if (rc < 0) | |
| 925 | − goto exit_rc; | |
| 926 | − rc = WR16(s, 0x2010011, 2); | |
| 927 | − if (rc < 0) | |
| 928 | − goto exit_rc; | |
| 929 | − rc = WR16(s, 0x201001a, 0x20); | |
| 930 | − if (rc < 0) | |
| 931 | − goto exit_rc; | |
| 932 | − rc = WR16(s, 0x201001b, 8); | |
| 933 | − if (rc < 0) | |
| 934 | − goto exit_rc; | |
| 935 | − rc = WR16(s, 0x201001c, 2); | |
| 936 | − if (rc < 0) | |
| 937 | − goto exit_rc; | |
| 938 | − rc = WR16(s, 0x1c10062, ebx); | |
| 939 | − if (rc < 0) | |
| 940 | − goto exit_rc; | |
| 941 | − rc = WR16(s, 0x1c1002a, v18); | |
| 942 | − if (rc < 0) | |
| 943 | − goto exit_rc; | |
| 944 | − rc = WR16(s, 0x1c10015, ebp); | |
| 945 | − if (rc < 0) | |
| 946 | − goto exit_rc; | |
| 947 | − rc = WR16(s, 0x1c10016, v0E); | |
| 948 | − if (rc < 0) | |
| 949 | − goto exit_rc; | |
| 950 | − break; | |
| 951 | − } | |
| 952 | − | |
| 953 | − if (s->config.s20d24 == 1) { | |
| 954 | − rc = WR16(s, 0x2010013, 0); | |
| 955 | − } else { | |
| 956 | − rc = WR16(s, 0x2010013, 1); | |
| 957 | − edi |= 0x1000; | |
| 958 | − } | |
| 959 | − | |
| 960 | − switch (fep->u.ofdm.code_rate_HP) { | |
| 961 | − default: | |
| 962 | − v22 |= 0x10; | |
| 963 | − case FEC_1_2: | |
| 964 | − if (s->chip_rev == DRXD_FW_B1) | |
| 965 | − break; | |
| 966 | − rc = WR16(s, 0x2090011, 0); | |
| 967 | − break; | |
| 968 | − case FEC_2_3: | |
| 969 | − edi |= 0x200; | |
| 970 | − if (s->chip_rev == DRXD_FW_B1) | |
| 971 | − break; | |
| 972 | − rc = WR16(s, 0x2090011, 1); | |
| 973 | − break; | |
| 974 | − case FEC_3_4: | |
| 975 | − edi |= 0x400; | |
| 976 | − if (s->chip_rev == DRXD_FW_B1) | |
| 977 | − break; | |
| 978 | − rc = WR16(s, 0x2090011, 2); | |
| 979 | − break; | |
| 980 | − case FEC_5_6: /* 5 */ | |
| 981 | − edi |= 0x600; | |
| 982 | − if (s->chip_rev == DRXD_FW_B1) | |
| 983 | − break; | |
| 984 | − rc = WR16(s, 0x2090011, 3); | |
| 985 | − break; | |
| 986 | − case FEC_7_8: /* 7 */ | |
| 987 | − edi |= 0x800; | |
| 988 | − if (s->chip_rev == DRXD_FW_B1) | |
| 989 | − break; | |
| 990 | − rc = WR16(s, 0x2090011, 4); | |
| 991 | − break; | |
| 992 | − }; | |
| 993 | − if (rc < 0) | |
| 994 | − goto exit_rc; | |
| 995 | − | |
| 996 | − switch (fep->u.ofdm.bandwidth) { | |
| 997 | − default: | |
| 998 | − rc = -EINVAL; | |
| 999 | − goto exit_rc; | |
| 1000 | − case BANDWIDTH_8_MHZ: /* 0 */ | |
| 1001 | − case BANDWIDTH_AUTO: | |
| 1002 | − rc = WR16(s, 0x0c2003f, 0x32); | |
| 1003 | − s->bandwidth_parm = ebx = 0x8b8249; | |
| 1004 | − edx = 0; | |
| 1005 | − break; | |
| 1006 | − case BANDWIDTH_7_MHZ: | |
| 1007 | − rc = WR16(s, 0x0c2003f, 0x3b); | |
| 1008 | − s->bandwidth_parm = ebx = 0x7a1200; | |
| 1009 | − edx = 0x4807; | |
| 1010 | − break; | |
| 1011 | − case BANDWIDTH_6_MHZ: | |
| 1012 | − rc = WR16(s, 0x0c2003f, 0x47); | |
| 1013 | − s->bandwidth_parm = ebx = 0x68a1b6; | |
| 1014 | − edx = 0x0f07; | |
| 1015 | − break; | |
| 1016 | − }; | |
| 1017 | − | |
| 1018 | − if (rc < 0) | |
| 1019 | − goto exit_rc; | |
| 1020 | − | |
| 1021 | − rc = WR16(s, 0x08200ec, edx); | |
| 1022 | − if (rc < 0) | |
| 1023 | − goto exit_rc; | |
| 1024 | − | |
| 1025 | − rc = RD16(s, 0x0820050); | |
| 1026 | − if (rc < 0) | |
| 1027 | − goto exit_rc; | |
| 1028 | − rc = WR16(s, 0x0820050, rc); | |
| 1029 | − | |
| 1030 | − { | |
| 1031 | − /* Configure bandwidth specific factor */ | |
| 1032 | − ebx = div64_u64(((u64) (s->f_osc) << 21) + (ebx >> 1), | |
| 1033 | − (u64)ebx) - 0x800000; | |
| 1034 | − EXIT_RC(WR16(s, 0x0c50010, ebx & 0xffff)); | |
| 1035 | − EXIT_RC(WR16(s, 0x0c50011, ebx >> 16)); | |
| 1036 | − | |
| 1037 | − /* drx397xD oscillator calibration */ | |
| 1038 | − ebx = div64_u64(((u64) (s->config.f_if + df_tuner) << 28) + | |
| 1039 | − (s->f_osc >> 1), (u64)s->f_osc); | |
| 1040 | − } | |
| 1041 | − ebx &= 0xfffffff; | |
| 1042 | − if (fep->inversion == INVERSION_ON) | |
| 1043 | − ebx = 0x10000000 - ebx; | |
| 1044 | − | |
| 1045 | − EXIT_RC(WR16(s, 0x0c30010, ebx & 0xffff)); | |
| 1046 | − EXIT_RC(WR16(s, 0x0c30011, ebx >> 16)); | |
| 1047 | − | |
| 1048 | − EXIT_RC(WR16(s, 0x0800000, 1)); | |
| 1049 | − EXIT_RC(RD16(s, 0x0800000)); | |
| 1050 | − | |
| 1051 | − | |
| 1052 | − EXIT_RC(SC_WaitForReady(s)); | |
| 1053 | − EXIT_RC(WR16(s, 0x0820042, 0)); | |
| 1054 | − EXIT_RC(WR16(s, 0x0820041, v22)); | |
| 1055 | − EXIT_RC(WR16(s, 0x0820040, edi)); | |
| 1056 | − EXIT_RC(SC_SendCommand(s, 3)); | |
| 1057 | − | |
| 1058 | − rc = RD16(s, 0x0800000); | |
| 1059 | − | |
| 1060 | − SC_WaitForReady(s); | |
| 1061 | − WR16(s, 0x0820042, 0); | |
| 1062 | − WR16(s, 0x0820041, 1); | |
| 1063 | − WR16(s, 0x0820040, 1); | |
| 1064 | − SC_SendCommand(s, 1); | |
| 1065 | − | |
| 1066 | − | |
| 1067 | − rc = WR16(s, 0x2150000, 2); | |
| 1068 | − rc = WR16(s, 0x2150016, a); | |
| 1069 | − rc = WR16(s, 0x2150010, 4); | |
| 1070 | − rc = WR16(s, 0x2150036, 0); | |
| 1071 | − rc = WR16(s, 0x2150000, 1); | |
| 1072 | − s->config.d60 = 2; | |
| 1073 | − | |
| 1074 | −exit_rc: | |
| 1075 | − return rc; | |
| 1076 | −} | |
| 1077 | − | |
| 1078 | −/******************************************************************************* | |
| 1079 | − * DVB interface | |
| 1080 | − ******************************************************************************/ | |
| 1081 | − | |
| 1082 | −static int drx397x_init(struct dvb_frontend *fe) | |
| 1083 | −{ | |
| 1084 | − struct drx397xD_state *s = fe->demodulator_priv; | |
| 1085 | − int rc; | |
| 1086 | − | |
| 1087 | − pr_debug("%s\n", __func__); | |
| 1088 | − | |
| 1089 | − s->config.rfagc.d00 = 2; /* 0x7c */ | |
| 1090 | − s->config.rfagc.w04 = 0; | |
| 1091 | − s->config.rfagc.w06 = 0x3ff; | |
| 1092 | − | |
| 1093 | − s->config.ifagc.d00 = 0; /* 0x68 */ | |
| 1094 | − s->config.ifagc.w04 = 0; | |
| 1095 | − s->config.ifagc.w06 = 140; | |
| 1096 | − s->config.ifagc.w08 = 0; | |
| 1097 | − s->config.ifagc.w0A = 0x3ff; | |
| 1098 | − s->config.ifagc.w0C = 0x388; | |
| 1099 | − | |
| 1100 | − /* for signal strength calculations */ | |
| 1101 | − s->config.ss76 = 820; | |
| 1102 | − s->config.ss78 = 2200; | |
| 1103 | − s->config.ss7A = 150; | |
| 1104 | − | |
| 1105 | − /* HI_CfgCommand */ | |
| 1106 | − s->config.w50 = 4; | |
| 1107 | − s->config.w52 = 9; | |
| 1108 | − | |
| 1109 | − s->config.f_if = 42800000; /* d14: intermediate frequency [Hz] */ | |
| 1110 | − s->config.f_osc = 48000; /* s66 : oscillator frequency [kHz] */ | |
| 1111 | − s->config.w92 = 12000; | |
| 1112 | − | |
| 1113 | − s->config.w9C = 0x000e; | |
| 1114 | − s->config.w9E = 0x0000; | |
| 1115 | − | |
| 1116 | − /* ConfigureMPEGOutput params */ | |
| 1117 | − s->config.wA0 = 4; | |
| 1118 | − s->config.w98 = 1; | |
| 1119 | − s->config.w9A = 1; | |
| 1120 | − | |
| 1121 | − /* get chip revision */ | |
| 1122 | − rc = RD16(s, 0x2410019); | |
| 1123 | − if (rc < 0) | |
| 1124 | − return -ENODEV; | |
| 1125 | − | |
| 1126 | − if (rc == 0) { | |
| 1127 | − printk(KERN_INFO "%s: chip revision A2\n", mod_name); | |
| 1128 | − rc = drx_load_fw(s, DRXD_FW_A2); | |
| 1129 | − } else { | |
| 1130 | − | |
| 1131 | − rc = (rc >> 12) - 3; | |
| 1132 | − switch (rc) { | |
| 1133 | − case 1: | |
| 1134 | − s->flags |= F_SET_0D4h; | |
| 1135 | − case 0: | |
| 1136 | − case 4: | |
| 1137 | − s->flags |= F_SET_0D0h; | |
| 1138 | − break; | |
| 1139 | − case 2: | |
| 1140 | − case 5: | |
| 1141 | − break; | |
| 1142 | − case 3: | |
| 1143 | − s->flags |= F_SET_0D4h; | |
| 1144 | − break; | |
| 1145 | − default: | |
| 1146 | − return -ENODEV; | |
| 1147 | − }; | |
| 1148 | − printk(KERN_INFO "%s: chip revision B1.%d\n", mod_name, rc); | |
| 1149 | − rc = drx_load_fw(s, DRXD_FW_B1); | |
| 1150 | − } | |
| 1151 | − if (rc < 0) | |
| 1152 | − goto error; | |
| 1153 | − | |
| 1154 | − rc = WR16(s, 0x0420033, 0x3973); | |
| 1155 | − if (rc < 0) | |
| 1156 | − goto error; | |
| 1157 | − | |
| 1158 | − rc = HI_Command(s, 2); | |
| 1159 | − | |
| 1160 | − msleep(1); | |
| 1161 | − | |
| 1162 | − if (s->chip_rev == DRXD_FW_A2) { | |
| 1163 | − rc = WR16(s, 0x043012d, 0x47F); | |
| 1164 | − if (rc < 0) | |
| 1165 | − goto error; | |
| 1166 | − } | |
| 1167 | − rc = WR16_E0(s, 0x0400000, 0); | |
| 1168 | − if (rc < 0) | |
| 1169 | − goto error; | |
| 1170 | − | |
| 1171 | − if (s->config.w92 > 20000 || s->config.w92 % 4000) { | |
| 1172 | − printk(KERN_ERR "%s: invalid osc frequency\n", mod_name); | |
| 1173 | − rc = -1; | |
| 1174 | − goto error; | |
| 1175 | − } | |
| 1176 | − | |
| 1177 | − rc = WR16(s, 0x2410010, 1); | |
| 1178 | − if (rc < 0) | |
| 1179 | − goto error; | |
| 1180 | − rc = WR16(s, 0x2410011, 0x15); | |
| 1181 | − if (rc < 0) | |
| 1182 | − goto error; | |
| 1183 | − rc = WR16(s, 0x2410012, s->config.w92 / 4000); | |
| 1184 | − if (rc < 0) | |
| 1185 | − goto error; | |
| 1186 | −#ifdef ORIG_FW | |
| 1187 | − rc = WR16(s, 0x2410015, 2); | |
| 1188 | − if (rc < 0) | |
| 1189 | − goto error; | |
| 1190 | −#endif | |
| 1191 | − rc = WR16(s, 0x2410017, 0x3973); | |
| 1192 | − if (rc < 0) | |
| 1193 | − goto error; | |
| 1194 | − | |
| 1195 | − s->f_osc = s->config.f_osc * 1000; /* initial estimator */ | |
| 1196 | − | |
| 1197 | − s->config.w56 = 1; | |
| 1198 | − | |
| 1199 | − rc = HI_CfgCommand(s); | |
| 1200 | − if (rc < 0) | |
| 1201 | − goto error; | |
| 1202 | − | |
| 1203 | − rc = write_fw(s, DRXD_InitAtomicRead); | |
| 1204 | − if (rc < 0) | |
| 1205 | − goto error; | |
| 1206 | − | |
| 1207 | − if (s->chip_rev == DRXD_FW_A2) { | |
| 1208 | − rc = WR16(s, 0x2150013, 0); | |
| 1209 | − if (rc < 0) | |
| 1210 | − goto error; | |
| 1211 | − } | |
| 1212 | − | |
| 1213 | − rc = WR16_E0(s, 0x0400002, 0); | |
| 1214 | − if (rc < 0) | |
| 1215 | − goto error; | |
| 1216 | − rc = WR16(s, 0x0400002, 0); | |
| 1217 | − if (rc < 0) | |
| 1218 | − goto error; | |
| 1219 | − | |
| 1220 | − if (s->chip_rev == DRXD_FW_A2) { | |
| 1221 | − rc = write_fw(s, DRXD_ResetCEFR); | |
| 1222 | − if (rc < 0) | |
| 1223 | − goto error; | |
| 1224 | − } | |
| 1225 | − rc = write_fw(s, DRXD_microcode); | |
| 1226 | − if (rc < 0) | |
| 1227 | − goto error; | |
| 1228 | − | |
| 1229 | − s->config.w9C = 0x0e; | |
| 1230 | − if (s->flags & F_SET_0D0h) { | |
| 1231 | − s->config.w9C = 0; | |
| 1232 | − rc = RD16(s, 0x0c20010); | |
| 1233 | − if (rc < 0) | |
| 1234 | − goto write_DRXD_InitFE_1; | |
| 1235 | − | |
| 1236 | − rc &= ~0x1000; | |
| 1237 | − rc = WR16(s, 0x0c20010, rc); | |
| 1238 | − if (rc < 0) | |
| 1239 | − goto write_DRXD_InitFE_1; | |
| 1240 | − | |
| 1241 | − rc = RD16(s, 0x0c20011); | |
| 1242 | − if (rc < 0) | |
| 1243 | − goto write_DRXD_InitFE_1; | |
| 1244 | − | |
| 1245 | − rc &= ~0x8; | |
| 1246 | − rc = WR16(s, 0x0c20011, rc); | |
| 1247 | − if (rc < 0) | |
| 1248 | − goto write_DRXD_InitFE_1; | |
| 1249 | − | |
| 1250 | − rc = WR16(s, 0x0c20012, 1); | |
| 1251 | − } | |
| 1252 | − | |
| 1253 | −write_DRXD_InitFE_1: | |
| 1254 | − | |
| 1255 | − rc = write_fw(s, DRXD_InitFE_1); | |
| 1256 | − if (rc < 0) | |
| 1257 | − goto error; | |
| 1258 | − | |
| 1259 | − rc = 1; | |
| 1260 | − if (s->chip_rev == DRXD_FW_B1) { | |
| 1261 | − if (s->flags & F_SET_0D0h) | |
| 1262 | − rc = 0; | |
| 1263 | − } else { | |
| 1264 | − if (s->flags & F_SET_0D0h) | |
| 1265 | − rc = 4; | |
| 1266 | − } | |
| 1267 | − | |
| 1268 | − rc = WR16(s, 0x0C20012, rc); | |
| 1269 | − if (rc < 0) | |
| 1270 | − goto error; | |
| 1271 | − | |
| 1272 | − rc = WR16(s, 0x0C20013, s->config.w9E); | |
| 1273 | − if (rc < 0) | |
| 1274 | − goto error; | |
| 1275 | − rc = WR16(s, 0x0C20015, s->config.w9C); | |
| 1276 | − if (rc < 0) | |
| 1277 | − goto error; | |
| 1278 | − | |
| 1279 | − rc = write_fw(s, DRXD_InitFE_2); | |
| 1280 | − if (rc < 0) | |
| 1281 | − goto error; | |
| 1282 | − rc = write_fw(s, DRXD_InitFT); | |
| 1283 | − if (rc < 0) | |
| 1284 | − goto error; | |
| 1285 | − rc = write_fw(s, DRXD_InitCP); | |
| 1286 | − if (rc < 0) | |
| 1287 | − goto error; | |
| 1288 | − rc = write_fw(s, DRXD_InitCE); | |
| 1289 | − if (rc < 0) | |
| 1290 | − goto error; | |
| 1291 | − rc = write_fw(s, DRXD_InitEQ); | |
| 1292 | − if (rc < 0) | |
| 1293 | − goto error; | |
| 1294 | − rc = write_fw(s, DRXD_InitEC); | |
| 1295 | − if (rc < 0) | |
| 1296 | − goto error; | |
| 1297 | − rc = write_fw(s, DRXD_InitSC); | |
| 1298 | − if (rc < 0) | |
| 1299 | − goto error; | |
| 1300 | − | |
| 1301 | − rc = SetCfgIfAgc(s, &s->config.ifagc); | |
| 1302 | − if (rc < 0) | |
| 1303 | − goto error; | |
| 1304 | − | |
| 1305 | − rc = SetCfgRfAgc(s, &s->config.rfagc); | |
| 1306 | − if (rc < 0) | |
| 1307 | − goto error; | |
| 1308 | − | |
| 1309 | − rc = ConfigureMPEGOutput(s, 1); | |
| 1310 | − rc = WR16(s, 0x08201fe, 0x0017); | |
| 1311 | − rc = WR16(s, 0x08201ff, 0x0101); | |
| 1312 | − | |
| 1313 | − s->config.d5C = 0; | |
| 1314 | − s->config.d60 = 1; | |
| 1315 | − s->config.d48 = 1; | |
| 1316 | − | |
| 1317 | −error: | |
| 1318 | − return rc; | |
| 1319 | −} | |
| 1320 | − | |
| 1321 | −static int drx397x_get_frontend(struct dvb_frontend *fe, | |
| 1322 | − struct dvb_frontend_parameters *params) | |
| 1323 | −{ | |
| 1324 | − return 0; | |
| 1325 | −} | |
| 1326 | − | |
| 1327 | −static int drx397x_set_frontend(struct dvb_frontend *fe, | |
| 1328 | − struct dvb_frontend_parameters *params) | |
| 1329 | −{ | |
| 1330 | − struct drx397xD_state *s = fe->demodulator_priv; | |
| 1331 | − | |
| 1332 | − s->config.s20d24 = 1; | |
| 1333 | − | |
| 1334 | − return drx_tune(s, params); | |
| 1335 | −} | |
| 1336 | − | |
| 1337 | −static int drx397x_get_tune_settings(struct dvb_frontend *fe, | |
| 1338 | − struct dvb_frontend_tune_settings | |
| 1339 | − *fe_tune_settings) | |
| 1340 | −{ | |
| 1341 | − fe_tune_settings->min_delay_ms = 10000; | |
| 1342 | − fe_tune_settings->step_size = 0; | |
| 1343 | − fe_tune_settings->max_drift = 0; | |
| 1344 | − | |
| 1345 | − return 0; | |
| 1346 | −} | |
| 1347 | − | |
| 1348 | −static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t *status) | |
| 1349 | −{ | |
| 1350 | − struct drx397xD_state *s = fe->demodulator_priv; | |
| 1351 | − int lockstat; | |
| 1352 | − | |
| 1353 | − GetLockStatus(s, &lockstat); | |
| 1354 | − | |
| 1355 | − *status = 0; | |
| 1356 | − if (lockstat & 2) { | |
| 1357 | − CorrectSysClockDeviation(s); | |
| 1358 | − ConfigureMPEGOutput(s, 1); | |
| 1359 | − *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI; | |
| 1360 | − } | |
| 1361 | − if (lockstat & 4) | |
| 1362 | − *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; | |
| 1363 | − | |
| 1364 | − return 0; | |
| 1365 | −} | |
| 1366 | − | |
| 1367 | −static int drx397x_read_ber(struct dvb_frontend *fe, unsigned int *ber) | |
| 1368 | −{ | |
| 1369 | − *ber = 0; | |
| 1370 | − | |
| 1371 | − return 0; | |
| 1372 | −} | |
| 1373 | − | |
| 1374 | −static int drx397x_read_snr(struct dvb_frontend *fe, u16 *snr) | |
| 1375 | −{ | |
| 1376 | − *snr = 0; | |
| 1377 | − | |
| 1378 | − return 0; | |
| 1379 | −} | |
| 1380 | − | |
| 1381 | −static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | |
| 1382 | −{ | |
| 1383 | − struct drx397xD_state *s = fe->demodulator_priv; | |
| 1384 | − int rc; | |
| 1385 | − | |
| 1386 | − if (s->config.ifagc.d00 == 2) { | |
| 1387 | − *strength = 0xffff; | |
| 1388 | − return 0; | |
| 1389 | − } | |
| 1390 | − rc = RD16(s, 0x0c20035); | |
| 1391 | − if (rc < 0) { | |
| 1392 | − *strength = 0; | |
| 1393 | − return 0; | |
| 1394 | − } | |
| 1395 | − rc &= 0x3ff; | |
| 1396 | − /* Signal strength is calculated using the following formula: | |
| 1397 | − * | |
| 1398 | − * a = 2200 * 150 / (2200 + 150); | |
| 1399 | − * a = a * 3300 / (a + 820); | |
| 1400 | − * b = 2200 * 3300 / (2200 + 820); | |
| 1401 | − * c = (((b-a) * rc) >> 10 + a) << 4; | |
| 1402 | − * strength = ~c & 0xffff; | |
| 1403 | − * | |
| 1404 | − * The following does the same but with less rounding errors: | |
| 1405 | − */ | |
| 1406 | − *strength = ~(7720 + (rc * 30744 >> 10)); | |
| 1407 | − | |
| 1408 | − return 0; | |
| 1409 | −} | |
| 1410 | − | |
| 1411 | −static int drx397x_read_ucblocks(struct dvb_frontend *fe, | |
| 1412 | − unsigned int *ucblocks) | |
| 1413 | −{ | |
| 1414 | − *ucblocks = 0; | |
| 1415 | − | |
| 1416 | − return 0; | |
| 1417 | −} | |
| 1418 | − | |
| 1419 | −static int drx397x_sleep(struct dvb_frontend *fe) | |
| 1420 | −{ | |
| 1421 | − return 0; | |
| 1422 | −} | |
| 1423 | − | |
| 1424 | −static void drx397x_release(struct dvb_frontend *fe) | |
| 1425 | −{ | |
| 1426 | − struct drx397xD_state *s = fe->demodulator_priv; | |
| 1427 | − printk(KERN_INFO "%s: release demodulator\n", mod_name); | |
| 1428 | − if (s) { | |
| 1429 | − drx_release_fw(s); | |
| 1430 | − kfree(s); | |
| 1431 | − } | |
| 1432 | − | |
| 1433 | −} | |
| 1434 | − | |
| 1435 | −static struct dvb_frontend_ops drx397x_ops = { | |
| 1436 | − | |
| 1437 | − .info = { | |
| 1438 | − .name = "Micronas DRX397xD DVB-T Frontend", | |
| 1439 | − .type = FE_OFDM, | |
| 1440 | − .frequency_min = 47125000, | |
| 1441 | − .frequency_max = 855250000, | |
| 1442 | − .frequency_stepsize = 166667, | |
| 1443 | − .frequency_tolerance = 0, | |
| 1444 | − .caps = /* 0x0C01B2EAE */ | |
| 1445 | − FE_CAN_FEC_1_2 | /* = 0x2, */ | |
| 1446 | − FE_CAN_FEC_2_3 | /* = 0x4, */ | |
| 1447 | − FE_CAN_FEC_3_4 | /* = 0x8, */ | |
| 1448 | − FE_CAN_FEC_5_6 | /* = 0x20, */ | |
| 1449 | − FE_CAN_FEC_7_8 | /* = 0x80, */ | |
| 1450 | − FE_CAN_FEC_AUTO | /* = 0x200, */ | |
| 1451 | − FE_CAN_QPSK | /* = 0x400, */ | |
| 1452 | − FE_CAN_QAM_16 | /* = 0x800, */ | |
| 1453 | − FE_CAN_QAM_64 | /* = 0x2000, */ | |
| 1454 | − FE_CAN_QAM_AUTO | /* = 0x10000, */ | |
| 1455 | − FE_CAN_TRANSMISSION_MODE_AUTO | /* = 0x20000, */ | |
| 1456 | − FE_CAN_GUARD_INTERVAL_AUTO | /* = 0x80000, */ | |
| 1457 | − FE_CAN_HIERARCHY_AUTO | /* = 0x100000, */ | |
| 1458 | − FE_CAN_RECOVER | /* = 0x40000000, */ | |
| 1459 | − FE_CAN_MUTE_TS /* = 0x80000000 */ | |
| 1460 | − }, | |
| 1461 | − | |
| 1462 | − .release = drx397x_release, | |
| 1463 | − .init = drx397x_init, | |
| 1464 | − .sleep = drx397x_sleep, | |
| 1465 | − | |
| 1466 | − .set_frontend = drx397x_set_frontend, | |
| 1467 | − .get_tune_settings = drx397x_get_tune_settings, | |
| 1468 | − .get_frontend = drx397x_get_frontend, | |
| 1469 | − | |
| 1470 | − .read_status = drx397x_read_status, | |
| 1471 | − .read_snr = drx397x_read_snr, | |
| 1472 | − .read_signal_strength = drx397x_read_signal_strength, | |
| 1473 | − .read_ber = drx397x_read_ber, | |
| 1474 | − .read_ucblocks = drx397x_read_ucblocks, | |
| 1475 | −}; | |
| 1476 | − | |
| 1477 | −struct dvb_frontend *drx397xD_attach(const struct drx397xD_config *config, | |
| 1478 | − struct i2c_adapter *i2c) | |
| 1479 | −{ | |
| 1480 | − struct drx397xD_state *state; | |
| 1481 | − | |
| 1482 | − /* allocate memory for the internal state */ | |
| 1483 | − state = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL); | |
| 1484 | − if (!state) | |
| 1485 | − goto error; | |
| 1486 | − | |
| 1487 | − /* setup the state */ | |
| 1488 | − state->i2c = i2c; | |
| 1489 | − memcpy(&state->config, config, sizeof(struct drx397xD_config)); | |
| 1490 | − | |
| 1491 | − /* check if the demod is there */ | |
| 1492 | − if (RD16(state, 0x2410019) < 0) | |
| 1493 | − goto error; | |
| 1494 | − | |
| 1495 | − /* create dvb_frontend */ | |
| 1496 | − memcpy(&state->frontend.ops, &drx397x_ops, | |
| 1497 | − sizeof(struct dvb_frontend_ops)); | |
| 1498 | − state->frontend.demodulator_priv = state; | |
| 1499 | − | |
| 1500 | − return &state->frontend; | |
| 1501 | −error: | |
| 1502 | − kfree(state); | |
| 1503 | − | |
| 1504 | − return NULL; | |
| 1505 | −} | |
| 1506 | −EXPORT_SYMBOL(drx397xD_attach); | |
| 1507 | − | |
| 1508 | −MODULE_DESCRIPTION("Micronas DRX397xD DVB-T Frontend"); | |
| 1509 | −MODULE_AUTHOR("Henk Vergonet"); | |
| 1510 | −MODULE_LICENSE("GPL"); | |
| 1511 | − | |
| @@ -1,130 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * Driver for Micronas DVB-T drx397xD demodulator | |
| 3 | − * | |
| 4 | − * Copyright (C) 2007 Henk vergonet <Henk.Vergonet@gmail.com> | |
| 5 | − * | |
| 6 | − * This program is free software; you can redistribute it and/or modify | |
| 7 | − * it under the terms of the GNU General Public License as published by | |
| 8 | − * the Free Software Foundation; either version 2 of the License, or | |
| 9 | − * (at your option) any later version. | |
| 10 | − * | |
| 11 | − * This program is distributed in the hope that it will be useful, | |
| 12 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | − * | |
| 15 | − * GNU General Public License for more details. | |
| 16 | − * | |
| 17 | − * You should have received a copy of the GNU General Public License | |
| 18 | − * along with this program; if not, write to the Free Software | |
| 19 | − * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.= | |
| 20 | − */ | |
| 21 | − | |
| 22 | −#ifndef _DRX397XD_H_INCLUDED | |
| 23 | −#define _DRX397XD_H_INCLUDED | |
| 24 | − | |
| 25 | −#include <linux/dvb/frontend.h> | |
| 26 | − | |
| 27 | −#define DRX_F_STEPSIZE 166667 | |
| 28 | −#define DRX_F_OFFSET 36000000 | |
| 29 | − | |
| 30 | −#define I2C_ADR_C0(x) \ | |
| 31 | −( cpu_to_le32( \ | |
| 32 | − (u32)( \ | |
| 33 | − (((u32)(x) & (u32)0x000000ffUL) ) | \ | |
| 34 | − (((u32)(x) & (u32)0x0000ff00UL) << 16) | \ | |
| 35 | − (((u32)(x) & (u32)0x0fff0000UL) >> 8) | \ | |
| 36 | − ( (u32)0x00c00000UL) \ | |
| 37 | − )) \ | |
| 38 | −) | |
| 39 | − | |
| 40 | −#define I2C_ADR_E0(x) \ | |
| 41 | −( cpu_to_le32( \ | |
| 42 | − (u32)( \ | |
| 43 | − (((u32)(x) & (u32)0x000000ffUL) ) | \ | |
| 44 | − (((u32)(x) & (u32)0x0000ff00UL) << 16) | \ | |
| 45 | − (((u32)(x) & (u32)0x0fff0000UL) >> 8) | \ | |
| 46 | − ( (u32)0x00e00000UL) \ | |
| 47 | − )) \ | |
| 48 | −) | |
| 49 | − | |
| 50 | −struct drx397xD_CfgRfAgc /* 0x7c */ | |
| 51 | −{ | |
| 52 | − int d00; /* 2 */ | |
| 53 | − u16 w04; | |
| 54 | − u16 w06; | |
| 55 | −}; | |
| 56 | − | |
| 57 | −struct drx397xD_CfgIfAgc /* 0x68 */ | |
| 58 | −{ | |
| 59 | − int d00; /* 0 */ | |
| 60 | − u16 w04; /* 0 */ | |
| 61 | − u16 w06; | |
| 62 | − u16 w08; | |
| 63 | − u16 w0A; | |
| 64 | − u16 w0C; | |
| 65 | −}; | |
| 66 | − | |
| 67 | −struct drx397xD_s20 { | |
| 68 | − int d04; | |
| 69 | − u32 d18; | |
| 70 | − u32 d1C; | |
| 71 | − u32 d20; | |
| 72 | − u32 d14; | |
| 73 | − u32 d24; | |
| 74 | − u32 d0C; | |
| 75 | − u32 d08; | |
| 76 | −}; | |
| 77 | − | |
| 78 | −struct drx397xD_config | |
| 79 | −{ | |
| 80 | − /* demodulator's I2C address */ | |
| 81 | − u8 demod_address; /* 0x0f */ | |
| 82 | − | |
| 83 | − struct drx397xD_CfgIfAgc ifagc; /* 0x68 */ | |
| 84 | − struct drx397xD_CfgRfAgc rfagc; /* 0x7c */ | |
| 85 | − u32 s20d24; | |
| 86 | − | |
| 87 | − /* HI_CfgCommand parameters */ | |
| 88 | − u16 w50, w52, /* w54, */ w56; | |
| 89 | − | |
| 90 | − int d5C; | |
| 91 | − int d60; | |
| 92 | − int d48; | |
| 93 | − int d28; | |
| 94 | − | |
| 95 | − u32 f_if; /* d14: intermediate frequency [Hz] */ | |
| 96 | − /* 36000000 on Cinergy 2400i DT */ | |
| 97 | − /* 42800000 on Pinnacle Hybrid PRO 330e */ | |
| 98 | − | |
| 99 | − u16 f_osc; /* s66: 48000 oscillator frequency [kHz] */ | |
| 100 | − | |
| 101 | − u16 w92; /* 20000 */ | |
| 102 | − | |
| 103 | − u16 wA0; | |
| 104 | − u16 w98; | |
| 105 | − u16 w9A; | |
| 106 | − | |
| 107 | − u16 w9C; /* 0xe0 */ | |
| 108 | − u16 w9E; /* 0x00 */ | |
| 109 | − | |
| 110 | − /* used for signal strength calculations in | |
| 111 | − drx397x_read_signal_strength | |
| 112 | − */ | |
| 113 | − u16 ss78; // 2200 | |
| 114 | − u16 ss7A; // 150 | |
| 115 | − u16 ss76; // 820 | |
| 116 | −}; | |
| 117 | − | |
| 118 | −#if defined(CONFIG_DVB_DRX397XD) || (defined(CONFIG_DVB_DRX397XD_MODULE) && defined(MODULE)) | |
| 119 | −extern struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config, | |
| 120 | − struct i2c_adapter *i2c); | |
| 121 | −#else | |
| 122 | −static inline struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config, | |
| 123 | − struct i2c_adapter *i2c) | |
| 124 | −{ | |
| 125 | − printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | |
| 126 | − return NULL; | |
| 127 | −} | |
| 128 | −#endif /* CONFIG_DVB_DRX397XD */ | |
| 129 | − | |
| 130 | −#endif /* _DRX397XD_H_INCLUDED */ | |
| @@ -1,40 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * Firmware definitions for Micronas drx397xD | |
| 3 | − * | |
| 4 | − * Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@gmail.com> | |
| 5 | − * | |
| 6 | − * This program is free software; you can redistribute it and/or modify | |
| 7 | − * it under the terms of the GNU General Public License as published by | |
| 8 | − * the Free Software Foundation; either version 2 of the License, or | |
| 9 | − * (at your option) any later version. | |
| 10 | − * | |
| 11 | − * This program is distributed in the hope that it will be useful, | |
| 12 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | − * GNU General Public License for more details. | |
| 15 | − * | |
| 16 | − * You should have received a copy of the GNU General Public License | |
| 17 | − * along with this program; If not, see <http://www.gnu.org/licenses/>. | |
| 18 | − */ | |
| 19 | − | |
| 20 | −#ifdef _FW_ENTRY | |
| 21 | − _FW_ENTRY("drx397xD.A2.fw", DRXD_FW_A2 = 0, DRXD_FW_A2 ), | |
| 22 | − _FW_ENTRY("drx397xD.B1.fw", DRXD_FW_B1, DRXD_FW_B1 ), | |
| 23 | −#undef _FW_ENTRY | |
| 24 | −#endif /* _FW_ENTRY */ | |
| 25 | − | |
| 26 | −#ifdef _BLOB_ENTRY | |
| 27 | − _BLOB_ENTRY("InitAtomicRead", DRXD_InitAtomicRead = 0 ), | |
| 28 | − _BLOB_ENTRY("InitCE", DRXD_InitCE ), | |
| 29 | − _BLOB_ENTRY("InitCP", DRXD_InitCP ), | |
| 30 | − _BLOB_ENTRY("InitEC", DRXD_InitEC ), | |
| 31 | − _BLOB_ENTRY("InitEQ", DRXD_InitEQ ), | |
| 32 | − _BLOB_ENTRY("InitFE_1", DRXD_InitFE_1 ), | |
| 33 | − _BLOB_ENTRY("InitFE_2", DRXD_InitFE_2 ), | |
| 34 | − _BLOB_ENTRY("InitFT", DRXD_InitFT ), | |
| 35 | − _BLOB_ENTRY("InitSC", DRXD_InitSC ), | |
| 36 | − _BLOB_ENTRY("ResetCEFR", DRXD_ResetCEFR ), | |
| 37 | − _BLOB_ENTRY("ResetECRAM", DRXD_ResetECRAM ), | |
| 38 | − _BLOB_ENTRY("microcode", DRXD_microcode ), | |
| 39 | −#undef _BLOB_ENTRY | |
| 40 | −#endif /* _BLOB_ENTRY */ | |
| @@ -0,0 +1,61 @@ | ||
| 1 | +/* | |
| 2 | + * drxd.h: DRXD DVB-T demodulator driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2005-2007 Micronas | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or | |
| 7 | + * modify it under the terms of the GNU General Public License | |
| 8 | + * version 2 only, as published by the Free Software Foundation. | |
| 9 | + * | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License | |
| 18 | + * along with this program; if not, write to the Free Software | |
| 19 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| 20 | + * 02110-1301, USA | |
| 21 | + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | |
| 22 | + */ | |
| 23 | + | |
| 24 | +#ifndef _DRXD_H_ | |
| 25 | +#define _DRXD_H_ | |
| 26 | + | |
| 27 | +#include <linux/types.h> | |
| 28 | +#include <linux/i2c.h> | |
| 29 | + | |
| 30 | +struct drxd_config { | |
| 31 | + u8 index; | |
| 32 | + | |
| 33 | + u8 pll_address; | |
| 34 | + u8 pll_type; | |
| 35 | +#define DRXD_PLL_NONE 0 | |
| 36 | +#define DRXD_PLL_DTT7520X 1 | |
| 37 | +#define DRXD_PLL_MT3X0823 2 | |
| 38 | + | |
| 39 | + u32 clock; | |
| 40 | + u8 insert_rs_byte; | |
| 41 | + | |
| 42 | + u8 demod_address; | |
| 43 | + u8 demoda_address; | |
| 44 | + u8 demod_revision; | |
| 45 | + | |
| 46 | + /* If the tuner is not behind an i2c gate, be sure to flip this bit | |
| 47 | + or else the i2c bus could get wedged */ | |
| 48 | + u8 disable_i2c_gate_ctrl; | |
| 49 | + | |
| 50 | + u32 IF; | |
| 51 | + int (*pll_set) (void *priv, void *priv_params, | |
| 52 | + u8 pll_addr, u8 demoda_addr, s32 *off); | |
| 53 | + s16(*osc_deviation) (void *priv, s16 dev, int flag); | |
| 54 | +}; | |
| 55 | + | |
| 56 | +extern | |
| 57 | +struct dvb_frontend *drxd_attach(const struct drxd_config *config, | |
| 58 | + void *priv, struct i2c_adapter *i2c, | |
| 59 | + struct device *dev); | |
| 60 | +extern int drxd_config_i2c(struct dvb_frontend *, int); | |
| 61 | +#endif | |
| @@ -0,0 +1,929 @@ | ||
| 1 | +/* | |
| 2 | + * drxd_firm.c : DRXD firmware tables | |
| 3 | + * | |
| 4 | + * Copyright (C) 2006-2007 Micronas | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or | |
| 7 | + * modify it under the terms of the GNU General Public License | |
| 8 | + * version 2 only, as published by the Free Software Foundation. | |
| 9 | + * | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License | |
| 18 | + * along with this program; if not, write to the Free Software | |
| 19 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| 20 | + * 02110-1301, USA | |
| 21 | + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | |
| 22 | + */ | |
| 23 | + | |
| 24 | +/* TODO: generate this file with a script from a settings file */ | |
| 25 | + | |
| 26 | +/* Contains A2 firmware version: 1.4.2 | |
| 27 | + * Contains B1 firmware version: 3.3.33 | |
| 28 | + * Contains settings from driver 1.4.23 | |
| 29 | +*/ | |
| 30 | + | |
| 31 | +#include "drxd_firm.h" | |
| 32 | + | |
| 33 | +#define ADDRESS(x) ((x) & 0xFF), (((x)>>8) & 0xFF), (((x)>>16) & 0xFF), (((x)>>24) & 0xFF) | |
| 34 | +#define LENGTH(x) ((x) & 0xFF), (((x)>>8) & 0xFF) | |
| 35 | + | |
| 36 | +/* Is written via block write, must be little endian */ | |
| 37 | +#define DATA16(x) ((x) & 0xFF), (((x)>>8) & 0xFF) | |
| 38 | + | |
| 39 | +#define WRBLOCK(a, l) ADDRESS(a), LENGTH(l) | |
| 40 | +#define WR16(a, d) ADDRESS(a), LENGTH(1), DATA16(d) | |
| 41 | + | |
| 42 | +#define END_OF_TABLE 0xFF, 0xFF, 0xFF, 0xFF | |
| 43 | + | |
| 44 | +/* HI firmware patches */ | |
| 45 | + | |
| 46 | +#define HI_TR_FUNC_ADDR HI_IF_RAM_USR_BEGIN__A | |
| 47 | +#define HI_TR_FUNC_SIZE 9 /* size of this function in instruction words */ | |
| 48 | + | |
| 49 | +u8 DRXD_InitAtomicRead[] = { | |
| 50 | + WRBLOCK(HI_TR_FUNC_ADDR, HI_TR_FUNC_SIZE), | |
| 51 | + 0x26, 0x00, /* 0 -> ring.rdy; */ | |
| 52 | + 0x60, 0x04, /* r0rami.dt -> ring.xba; */ | |
| 53 | + 0x61, 0x04, /* r0rami.dt -> ring.xad; */ | |
| 54 | + 0xE3, 0x07, /* HI_RA_RAM_USR_BEGIN -> ring.iad; */ | |
| 55 | + 0x40, 0x00, /* (long immediate) */ | |
| 56 | + 0x64, 0x04, /* r0rami.dt -> ring.len; */ | |
| 57 | + 0x65, 0x04, /* r0rami.dt -> ring.ctl; */ | |
| 58 | + 0x26, 0x00, /* 0 -> ring.rdy; */ | |
| 59 | + 0x38, 0x00, /* 0 -> jumps.ad; */ | |
| 60 | + END_OF_TABLE | |
| 61 | +}; | |
| 62 | + | |
| 63 | +/* Pins D0 and D1 of the parallel MPEG output can be used | |
| 64 | + to set the I2C address of a device. */ | |
| 65 | + | |
| 66 | +#define HI_RST_FUNC_ADDR (HI_IF_RAM_USR_BEGIN__A + HI_TR_FUNC_SIZE) | |
| 67 | +#define HI_RST_FUNC_SIZE 54 /* size of this function in instruction words */ | |
| 68 | + | |
| 69 | +/* D0 Version */ | |
| 70 | +u8 DRXD_HiI2cPatch_1[] = { | |
| 71 | + WRBLOCK(HI_RST_FUNC_ADDR, HI_RST_FUNC_SIZE), | |
| 72 | + 0xC8, 0x07, 0x01, 0x00, /* MASK -> reg0.dt; */ | |
| 73 | + 0xE0, 0x07, 0x15, 0x02, /* (EC__BLK << 6) + EC_OC_REG__BNK -> ring.xba; */ | |
| 74 | + 0xE1, 0x07, 0x12, 0x00, /* EC_OC_REG_OC_MPG_SIO__A -> ring.xad; */ | |
| 75 | + 0xA2, 0x00, /* M_BNK_ID_DAT -> ring.iba; */ | |
| 76 | + 0x23, 0x00, /* &data -> ring.iad; */ | |
| 77 | + 0x24, 0x00, /* 0 -> ring.len; */ | |
| 78 | + 0xA5, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl; */ | |
| 79 | + 0x26, 0x00, /* 0 -> ring.rdy; */ | |
| 80 | + 0x42, 0x00, /* &data+1 -> w0ram.ad; */ | |
| 81 | + 0xC0, 0x07, 0xFF, 0x0F, /* -1 -> w0ram.dt; */ | |
| 82 | + 0x63, 0x00, /* &data+1 -> ring.iad; */ | |
| 83 | + 0x65, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl; */ | |
| 84 | + 0x26, 0x00, /* 0 -> ring.rdy; */ | |
| 85 | + 0xE1, 0x07, 0x38, 0x00, /* EC_OC_REG_OCR_MPG_USR_DAT__A -> ring.xad; */ | |
| 86 | + 0xA5, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl; */ | |
| 87 | + 0x26, 0x00, /* 0 -> ring.rdy; */ | |
| 88 | + 0xE1, 0x07, 0x12, 0x00, /* EC_OC_REG_OC_MPG_SIO__A -> ring.xad; */ | |
| 89 | + 0x23, 0x00, /* &data -> ring.iad; */ | |
| 90 | + 0x65, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl; */ | |
| 91 | + 0x26, 0x00, /* 0 -> ring.rdy; */ | |
| 92 | + 0x42, 0x00, /* &data+1 -> w0ram.ad; */ | |
| 93 | + 0x0F, 0x04, /* r0ram.dt -> and.op; */ | |
| 94 | + 0x1C, 0x06, /* reg0.dt -> and.tr; */ | |
| 95 | + 0xCF, 0x04, /* and.rs -> add.op; */ | |
| 96 | + 0xD0, 0x07, 0x70, 0x00, /* DEF_DEV_ID -> add.tr; */ | |
| 97 | + 0xD0, 0x04, /* add.rs -> add.tr; */ | |
| 98 | + 0xC8, 0x04, /* add.rs -> reg0.dt; */ | |
| 99 | + 0x60, 0x00, /* reg0.dt -> w0ram.dt; */ | |
| 100 | + 0xC2, 0x07, 0x10, 0x00, /* SLV0_BASE -> w0rami.ad; */ | |
| 101 | + 0x01, 0x00, /* 0 -> w0rami.dt; */ | |
| 102 | + 0x01, 0x06, /* reg0.dt -> w0rami.dt; */ | |
| 103 | + 0xC2, 0x07, 0x20, 0x00, /* SLV1_BASE -> w0rami.ad; */ | |
| 104 | + 0x01, 0x00, /* 0 -> w0rami.dt; */ | |
| 105 | + 0x01, 0x06, /* reg0.dt -> w0rami.dt; */ | |
| 106 | + 0xC2, 0x07, 0x30, 0x00, /* CMD_BASE -> w0rami.ad; */ | |
| 107 | + 0x01, 0x00, /* 0 -> w0rami.dt; */ | |
| 108 | + 0x01, 0x00, /* 0 -> w0rami.dt; */ | |
| 109 | + 0x01, 0x00, /* 0 -> w0rami.dt; */ | |
| 110 | + 0x68, 0x00, /* M_IC_SEL_PT1 -> i2c.sel; */ | |
| 111 | + 0x29, 0x00, /* M_IC_CMD_RESET -> i2c.cmd; */ | |
| 112 | + 0x28, 0x00, /* M_IC_SEL_PT0 -> i2c.sel; */ | |
| 113 | + 0x29, 0x00, /* M_IC_CMD_RESET -> i2c.cmd; */ | |
| 114 | + 0xF8, 0x07, 0x2F, 0x00, /* 0x2F -> jumps.ad; */ | |
| 115 | + | |
| 116 | + WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 0) + 1)), | |
| 117 | + (u16) (HI_RST_FUNC_ADDR & 0x3FF)), | |
| 118 | + WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 1) + 1)), | |
| 119 | + (u16) (HI_RST_FUNC_ADDR & 0x3FF)), | |
| 120 | + WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 2) + 1)), | |
| 121 | + (u16) (HI_RST_FUNC_ADDR & 0x3FF)), | |
| 122 | + WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 3) + 1)), | |
| 123 | + (u16) (HI_RST_FUNC_ADDR & 0x3FF)), | |
| 124 | + | |
| 125 | + /* Force quick and dirty reset */ | |
| 126 | + WR16(B_HI_CT_REG_COMM_STATE__A, 0), | |
| 127 | + END_OF_TABLE | |
| 128 | +}; | |
| 129 | + | |
| 130 | +/* D0,D1 Version */ | |
| 131 | +u8 DRXD_HiI2cPatch_3[] = { | |
| 132 | + WRBLOCK(HI_RST_FUNC_ADDR, HI_RST_FUNC_SIZE), | |
| 133 | + 0xC8, 0x07, 0x03, 0x00, /* MASK -> reg0.dt; */ | |
| 134 | + 0xE0, 0x07, 0x15, 0x02, /* (EC__BLK << 6) + EC_OC_REG__BNK -> ring.xba; */ | |
| 135 | + 0xE1, 0x07, 0x12, 0x00, /* EC_OC_REG_OC_MPG_SIO__A -> ring.xad; */ | |
| 136 | + 0xA2, 0x00, /* M_BNK_ID_DAT -> ring.iba; */ | |
| 137 | + 0x23, 0x00, /* &data -> ring.iad; */ | |
| 138 | + 0x24, 0x00, /* 0 -> ring.len; */ | |
| 139 | + 0xA5, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl; */ | |
| 140 | + 0x26, 0x00, /* 0 -> ring.rdy; */ | |
| 141 | + 0x42, 0x00, /* &data+1 -> w0ram.ad; */ | |
| 142 | + 0xC0, 0x07, 0xFF, 0x0F, /* -1 -> w0ram.dt; */ | |
| 143 | + 0x63, 0x00, /* &data+1 -> ring.iad; */ | |
| 144 | + 0x65, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl; */ | |
| 145 | + 0x26, 0x00, /* 0 -> ring.rdy; */ | |
| 146 | + 0xE1, 0x07, 0x38, 0x00, /* EC_OC_REG_OCR_MPG_USR_DAT__A -> ring.xad; */ | |
| 147 | + 0xA5, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl; */ | |
| 148 | + 0x26, 0x00, /* 0 -> ring.rdy; */ | |
| 149 | + 0xE1, 0x07, 0x12, 0x00, /* EC_OC_REG_OC_MPG_SIO__A -> ring.xad; */ | |
| 150 | + 0x23, 0x00, /* &data -> ring.iad; */ | |
| 151 | + 0x65, 0x02, /* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl; */ | |
| 152 | + 0x26, 0x00, /* 0 -> ring.rdy; */ | |
| 153 | + 0x42, 0x00, /* &data+1 -> w0ram.ad; */ | |
| 154 | + 0x0F, 0x04, /* r0ram.dt -> and.op; */ | |
| 155 | + 0x1C, 0x06, /* reg0.dt -> and.tr; */ | |
| 156 | + 0xCF, 0x04, /* and.rs -> add.op; */ | |
| 157 | + 0xD0, 0x07, 0x70, 0x00, /* DEF_DEV_ID -> add.tr; */ | |
| 158 | + 0xD0, 0x04, /* add.rs -> add.tr; */ | |
| 159 | + 0xC8, 0x04, /* add.rs -> reg0.dt; */ | |
| 160 | + 0x60, 0x00, /* reg0.dt -> w0ram.dt; */ | |
| 161 | + 0xC2, 0x07, 0x10, 0x00, /* SLV0_BASE -> w0rami.ad; */ | |
| 162 | + 0x01, 0x00, /* 0 -> w0rami.dt; */ | |
| 163 | + 0x01, 0x06, /* reg0.dt -> w0rami.dt; */ | |
| 164 | + 0xC2, 0x07, 0x20, 0x00, /* SLV1_BASE -> w0rami.ad; */ | |
| 165 | + 0x01, 0x00, /* 0 -> w0rami.dt; */ | |
| 166 | + 0x01, 0x06, /* reg0.dt -> w0rami.dt; */ | |
| 167 | + 0xC2, 0x07, 0x30, 0x00, /* CMD_BASE -> w0rami.ad; */ | |
| 168 | + 0x01, 0x00, /* 0 -> w0rami.dt; */ | |
| 169 | + 0x01, 0x00, /* 0 -> w0rami.dt; */ | |
| 170 | + 0x01, 0x00, /* 0 -> w0rami.dt; */ | |
| 171 | + 0x68, 0x00, /* M_IC_SEL_PT1 -> i2c.sel; */ | |
| 172 | + 0x29, 0x00, /* M_IC_CMD_RESET -> i2c.cmd; */ | |
| 173 | + 0x28, 0x00, /* M_IC_SEL_PT0 -> i2c.sel; */ | |
| 174 | + 0x29, 0x00, /* M_IC_CMD_RESET -> i2c.cmd; */ | |
| 175 | + 0xF8, 0x07, 0x2F, 0x00, /* 0x2F -> jumps.ad; */ | |
| 176 | + | |
| 177 | + WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 0) + 1)), | |
| 178 | + (u16) (HI_RST_FUNC_ADDR & 0x3FF)), | |
| 179 | + WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 1) + 1)), | |
| 180 | + (u16) (HI_RST_FUNC_ADDR & 0x3FF)), | |
| 181 | + WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 2) + 1)), | |
| 182 | + (u16) (HI_RST_FUNC_ADDR & 0x3FF)), | |
| 183 | + WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 3) + 1)), | |
| 184 | + (u16) (HI_RST_FUNC_ADDR & 0x3FF)), | |
| 185 | + | |
| 186 | + /* Force quick and dirty reset */ | |
| 187 | + WR16(B_HI_CT_REG_COMM_STATE__A, 0), | |
| 188 | + END_OF_TABLE | |
| 189 | +}; | |
| 190 | + | |
| 191 | +u8 DRXD_ResetCEFR[] = { | |
| 192 | + WRBLOCK(CE_REG_FR_TREAL00__A, 57), | |
| 193 | + 0x52, 0x00, /* CE_REG_FR_TREAL00__A */ | |
| 194 | + 0x00, 0x00, /* CE_REG_FR_TIMAG00__A */ | |
| 195 | + 0x52, 0x00, /* CE_REG_FR_TREAL01__A */ | |
| 196 | + 0x00, 0x00, /* CE_REG_FR_TIMAG01__A */ | |
| 197 | + 0x52, 0x00, /* CE_REG_FR_TREAL02__A */ | |
| 198 | + 0x00, 0x00, /* CE_REG_FR_TIMAG02__A */ | |
| 199 | + 0x52, 0x00, /* CE_REG_FR_TREAL03__A */ | |
| 200 | + 0x00, 0x00, /* CE_REG_FR_TIMAG03__A */ | |
| 201 | + 0x52, 0x00, /* CE_REG_FR_TREAL04__A */ | |
| 202 | + 0x00, 0x00, /* CE_REG_FR_TIMAG04__A */ | |
| 203 | + 0x52, 0x00, /* CE_REG_FR_TREAL05__A */ | |
| 204 | + 0x00, 0x00, /* CE_REG_FR_TIMAG05__A */ | |
| 205 | + 0x52, 0x00, /* CE_REG_FR_TREAL06__A */ | |
| 206 | + 0x00, 0x00, /* CE_REG_FR_TIMAG06__A */ | |
| 207 | + 0x52, 0x00, /* CE_REG_FR_TREAL07__A */ | |
| 208 | + 0x00, 0x00, /* CE_REG_FR_TIMAG07__A */ | |
| 209 | + 0x52, 0x00, /* CE_REG_FR_TREAL08__A */ | |
| 210 | + 0x00, 0x00, /* CE_REG_FR_TIMAG08__A */ | |
| 211 | + 0x52, 0x00, /* CE_REG_FR_TREAL09__A */ | |
| 212 | + 0x00, 0x00, /* CE_REG_FR_TIMAG09__A */ | |
| 213 | + 0x52, 0x00, /* CE_REG_FR_TREAL10__A */ | |
| 214 | + 0x00, 0x00, /* CE_REG_FR_TIMAG10__A */ | |
| 215 | + 0x52, 0x00, /* CE_REG_FR_TREAL11__A */ | |
| 216 | + 0x00, 0x00, /* CE_REG_FR_TIMAG11__A */ | |
| 217 | + | |
| 218 | + 0x52, 0x00, /* CE_REG_FR_MID_TAP__A */ | |
| 219 | + | |
| 220 | + 0x0B, 0x00, /* CE_REG_FR_SQS_G00__A */ | |
| 221 | + 0x0B, 0x00, /* CE_REG_FR_SQS_G01__A */ | |
| 222 | + 0x0B, 0x00, /* CE_REG_FR_SQS_G02__A */ | |
| 223 | + 0x0B, 0x00, /* CE_REG_FR_SQS_G03__A */ | |
| 224 | + 0x0B, 0x00, /* CE_REG_FR_SQS_G04__A */ | |
| 225 | + 0x0B, 0x00, /* CE_REG_FR_SQS_G05__A */ | |
| 226 | + 0x0B, 0x00, /* CE_REG_FR_SQS_G06__A */ | |
| 227 | + 0x0B, 0x00, /* CE_REG_FR_SQS_G07__A */ | |
| 228 | + 0x0B, 0x00, /* CE_REG_FR_SQS_G08__A */ | |
| 229 | + 0x0B, 0x00, /* CE_REG_FR_SQS_G09__A */ | |
| 230 | + 0x0B, 0x00, /* CE_REG_FR_SQS_G10__A */ | |
| 231 | + 0x0B, 0x00, /* CE_REG_FR_SQS_G11__A */ | |
| 232 | + 0x0B, 0x00, /* CE_REG_FR_SQS_G12__A */ | |
| 233 | + | |
| 234 | + 0xFF, 0x01, /* CE_REG_FR_RIO_G00__A */ | |
| 235 | + 0x90, 0x01, /* CE_REG_FR_RIO_G01__A */ | |
| 236 | + 0x0B, 0x01, /* CE_REG_FR_RIO_G02__A */ | |
| 237 | + 0xC8, 0x00, /* CE_REG_FR_RIO_G03__A */ | |
| 238 | + 0xA0, 0x00, /* CE_REG_FR_RIO_G04__A */ | |
| 239 | + 0x85, 0x00, /* CE_REG_FR_RIO_G05__A */ | |
| 240 | + 0x72, 0x00, /* CE_REG_FR_RIO_G06__A */ | |
| 241 | + 0x64, 0x00, /* CE_REG_FR_RIO_G07__A */ | |
| 242 | + 0x59, 0x00, /* CE_REG_FR_RIO_G08__A */ | |
| 243 | + 0x50, 0x00, /* CE_REG_FR_RIO_G09__A */ | |
| 244 | + 0x49, 0x00, /* CE_REG_FR_RIO_G10__A */ | |
| 245 | + | |
| 246 | + 0x10, 0x00, /* CE_REG_FR_MODE__A */ | |
| 247 | + 0x78, 0x00, /* CE_REG_FR_SQS_TRH__A */ | |
| 248 | + 0x00, 0x00, /* CE_REG_FR_RIO_GAIN__A */ | |
| 249 | + 0x00, 0x02, /* CE_REG_FR_BYPASS__A */ | |
| 250 | + 0x0D, 0x00, /* CE_REG_FR_PM_SET__A */ | |
| 251 | + 0x07, 0x00, /* CE_REG_FR_ERR_SH__A */ | |
| 252 | + 0x04, 0x00, /* CE_REG_FR_MAN_SH__A */ | |
| 253 | + 0x06, 0x00, /* CE_REG_FR_TAP_SH__A */ | |
| 254 | + | |
| 255 | + END_OF_TABLE | |
| 256 | +}; | |
| 257 | + | |
| 258 | +u8 DRXD_InitFEA2_1[] = { | |
| 259 | + WRBLOCK(FE_AD_REG_PD__A, 3), | |
| 260 | + 0x00, 0x00, /* FE_AD_REG_PD__A */ | |
| 261 | + 0x01, 0x00, /* FE_AD_REG_INVEXT__A */ | |
| 262 | + 0x00, 0x00, /* FE_AD_REG_CLKNEG__A */ | |
| 263 | + | |
| 264 | + WRBLOCK(FE_AG_REG_DCE_AUR_CNT__A, 2), | |
| 265 | + 0x10, 0x00, /* FE_AG_REG_DCE_AUR_CNT__A */ | |
| 266 | + 0x10, 0x00, /* FE_AG_REG_DCE_RUR_CNT__A */ | |
| 267 | + | |
| 268 | + WRBLOCK(FE_AG_REG_ACE_AUR_CNT__A, 2), | |
| 269 | + 0x0E, 0x00, /* FE_AG_REG_ACE_AUR_CNT__A */ | |
| 270 | + 0x00, 0x00, /* FE_AG_REG_ACE_RUR_CNT__A */ | |
| 271 | + | |
| 272 | + WRBLOCK(FE_AG_REG_EGC_FLA_RGN__A, 5), | |
| 273 | + 0x04, 0x00, /* FE_AG_REG_EGC_FLA_RGN__A */ | |
| 274 | + 0x1F, 0x00, /* FE_AG_REG_EGC_SLO_RGN__A */ | |
| 275 | + 0x00, 0x00, /* FE_AG_REG_EGC_JMP_PSN__A */ | |
| 276 | + 0x00, 0x00, /* FE_AG_REG_EGC_FLA_INC__A */ | |
| 277 | + 0x00, 0x00, /* FE_AG_REG_EGC_FLA_DEC__A */ | |
| 278 | + | |
| 279 | + WRBLOCK(FE_AG_REG_GC1_AGC_MAX__A, 2), | |
| 280 | + 0xFF, 0x01, /* FE_AG_REG_GC1_AGC_MAX__A */ | |
| 281 | + 0x00, 0xFE, /* FE_AG_REG_GC1_AGC_MIN__A */ | |
| 282 | + | |
| 283 | + WRBLOCK(FE_AG_REG_IND_WIN__A, 29), | |
| 284 | + 0x00, 0x00, /* FE_AG_REG_IND_WIN__A */ | |
| 285 | + 0x05, 0x00, /* FE_AG_REG_IND_THD_LOL__A */ | |
| 286 | + 0x0F, 0x00, /* FE_AG_REG_IND_THD_HIL__A */ | |
| 287 | + 0x00, 0x00, /* FE_AG_REG_IND_DEL__A don't care */ | |
| 288 | + 0x1E, 0x00, /* FE_AG_REG_IND_PD1_WRI__A */ | |
| 289 | + 0x0C, 0x00, /* FE_AG_REG_PDA_AUR_CNT__A */ | |
| 290 | + 0x00, 0x00, /* FE_AG_REG_PDA_RUR_CNT__A */ | |
| 291 | + 0x00, 0x00, /* FE_AG_REG_PDA_AVE_DAT__A don't care */ | |
| 292 | + 0x00, 0x00, /* FE_AG_REG_PDC_RUR_CNT__A */ | |
| 293 | + 0x01, 0x00, /* FE_AG_REG_PDC_SET_LVL__A */ | |
| 294 | + 0x02, 0x00, /* FE_AG_REG_PDC_FLA_RGN__A */ | |
| 295 | + 0x00, 0x00, /* FE_AG_REG_PDC_JMP_PSN__A don't care */ | |
| 296 | + 0xFF, 0xFF, /* FE_AG_REG_PDC_FLA_STP__A */ | |
| 297 | + 0xFF, 0xFF, /* FE_AG_REG_PDC_SLO_STP__A */ | |
| 298 | + 0x00, 0x1F, /* FE_AG_REG_PDC_PD2_WRI__A don't care */ | |
| 299 | + 0x00, 0x00, /* FE_AG_REG_PDC_MAP_DAT__A don't care */ | |
| 300 | + 0x02, 0x00, /* FE_AG_REG_PDC_MAX__A */ | |
| 301 | + 0x0C, 0x00, /* FE_AG_REG_TGA_AUR_CNT__A */ | |
| 302 | + 0x00, 0x00, /* FE_AG_REG_TGA_RUR_CNT__A */ | |
| 303 | + 0x00, 0x00, /* FE_AG_REG_TGA_AVE_DAT__A don't care */ | |
| 304 | + 0x00, 0x00, /* FE_AG_REG_TGC_RUR_CNT__A */ | |
| 305 | + 0x22, 0x00, /* FE_AG_REG_TGC_SET_LVL__A */ | |
| 306 | + 0x15, 0x00, /* FE_AG_REG_TGC_FLA_RGN__A */ | |
| 307 | + 0x00, 0x00, /* FE_AG_REG_TGC_JMP_PSN__A don't care */ | |
| 308 | + 0x01, 0x00, /* FE_AG_REG_TGC_FLA_STP__A */ | |
| 309 | + 0x0A, 0x00, /* FE_AG_REG_TGC_SLO_STP__A */ | |
| 310 | + 0x00, 0x00, /* FE_AG_REG_TGC_MAP_DAT__A don't care */ | |
| 311 | + 0x10, 0x00, /* FE_AG_REG_FGA_AUR_CNT__A */ | |
| 312 | + 0x10, 0x00, /* FE_AG_REG_FGA_RUR_CNT__A */ | |
| 313 | + | |
| 314 | + WRBLOCK(FE_AG_REG_BGC_FGC_WRI__A, 2), | |
| 315 | + 0x00, 0x00, /* FE_AG_REG_BGC_FGC_WRI__A */ | |
| 316 | + 0x00, 0x00, /* FE_AG_REG_BGC_CGC_WRI__A */ | |
| 317 | + | |
| 318 | + WRBLOCK(FE_FD_REG_SCL__A, 3), | |
| 319 | + 0x05, 0x00, /* FE_FD_REG_SCL__A */ | |
| 320 | + 0x03, 0x00, /* FE_FD_REG_MAX_LEV__A */ | |
| 321 | + 0x05, 0x00, /* FE_FD_REG_NR__A */ | |
| 322 | + | |
| 323 | + WRBLOCK(FE_CF_REG_SCL__A, 5), | |
| 324 | + 0x16, 0x00, /* FE_CF_REG_SCL__A */ | |
| 325 | + 0x04, 0x00, /* FE_CF_REG_MAX_LEV__A */ | |
| 326 | + 0x06, 0x00, /* FE_CF_REG_NR__A */ | |
| 327 | + 0x00, 0x00, /* FE_CF_REG_IMP_VAL__A */ | |
| 328 | + 0x01, 0x00, /* FE_CF_REG_MEAS_VAL__A */ | |
| 329 | + | |
| 330 | + WRBLOCK(FE_CU_REG_FRM_CNT_RST__A, 2), | |
| 331 | + 0x00, 0x08, /* FE_CU_REG_FRM_CNT_RST__A */ | |
| 332 | + 0x00, 0x00, /* FE_CU_REG_FRM_CNT_STR__A */ | |
| 333 | + | |
| 334 | + END_OF_TABLE | |
| 335 | +}; | |
| 336 | + | |
| 337 | + /* with PGA */ | |
| 338 | +/* WR16COND( DRXD_WITH_PGA, FE_AG_REG_AG_PGA_MODE__A , 0x0004), */ | |
| 339 | + /* without PGA */ | |
| 340 | +/* WR16COND( DRXD_WITHOUT_PGA, FE_AG_REG_AG_PGA_MODE__A , 0x0001), */ | |
| 341 | +/* WR16(FE_AG_REG_AG_AGC_SIO__A, (extAttr -> FeAgRegAgAgcSio), 0x0000 );*/ | |
| 342 | +/* WR16(FE_AG_REG_AG_PWD__A ,(extAttr -> FeAgRegAgPwd), 0x0000 );*/ | |
| 343 | + | |
| 344 | +u8 DRXD_InitFEA2_2[] = { | |
| 345 | + WR16(FE_AG_REG_CDR_RUR_CNT__A, 0x0010), | |
| 346 | + WR16(FE_AG_REG_FGM_WRI__A, 48), | |
| 347 | + /* Activate measurement, activate scale */ | |
| 348 | + WR16(FE_FD_REG_MEAS_VAL__A, 0x0001), | |
| 349 | + | |
| 350 | + WR16(FE_CU_REG_COMM_EXEC__A, 0x0001), | |
| 351 | + WR16(FE_CF_REG_COMM_EXEC__A, 0x0001), | |
| 352 | + WR16(FE_IF_REG_COMM_EXEC__A, 0x0001), | |
| 353 | + WR16(FE_FD_REG_COMM_EXEC__A, 0x0001), | |
| 354 | + WR16(FE_FS_REG_COMM_EXEC__A, 0x0001), | |
| 355 | + WR16(FE_AD_REG_COMM_EXEC__A, 0x0001), | |
| 356 | + WR16(FE_AG_REG_COMM_EXEC__A, 0x0001), | |
| 357 | + WR16(FE_AG_REG_AG_MODE_LOP__A, 0x895E), | |
| 358 | + | |
| 359 | + END_OF_TABLE | |
| 360 | +}; | |
| 361 | + | |
| 362 | +u8 DRXD_InitFEB1_1[] = { | |
| 363 | + WR16(B_FE_AD_REG_PD__A, 0x0000), | |
| 364 | + WR16(B_FE_AD_REG_CLKNEG__A, 0x0000), | |
| 365 | + WR16(B_FE_AG_REG_BGC_FGC_WRI__A, 0x0000), | |
| 366 | + WR16(B_FE_AG_REG_BGC_CGC_WRI__A, 0x0000), | |
| 367 | + WR16(B_FE_AG_REG_AG_MODE_LOP__A, 0x000a), | |
| 368 | + WR16(B_FE_AG_REG_IND_PD1_WRI__A, 35), | |
| 369 | + WR16(B_FE_AG_REG_IND_WIN__A, 0), | |
| 370 | + WR16(B_FE_AG_REG_IND_THD_LOL__A, 8), | |
| 371 | + WR16(B_FE_AG_REG_IND_THD_HIL__A, 8), | |
| 372 | + WR16(B_FE_CF_REG_IMP_VAL__A, 1), | |
| 373 | + WR16(B_FE_AG_REG_EGC_FLA_RGN__A, 7), | |
| 374 | + END_OF_TABLE | |
| 375 | +}; | |
| 376 | + | |
| 377 | + /* with PGA */ | |
| 378 | +/* WR16(B_FE_AG_REG_AG_PGA_MODE__A , 0x0000, 0x0000); */ | |
| 379 | + /* without PGA */ | |
| 380 | +/* WR16(B_FE_AG_REG_AG_PGA_MODE__A , | |
| 381 | + B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 0x0000);*/ | |
| 382 | + /* WR16(B_FE_AG_REG_AG_AGC_SIO__A,(extAttr -> FeAgRegAgAgcSio), 0x0000 );*//*added HS 23-05-2005 */ | |
| 383 | +/* WR16(B_FE_AG_REG_AG_PWD__A ,(extAttr -> FeAgRegAgPwd), 0x0000 );*/ | |
| 384 | + | |
| 385 | +u8 DRXD_InitFEB1_2[] = { | |
| 386 | + WR16(B_FE_COMM_EXEC__A, 0x0001), | |
| 387 | + | |
| 388 | + /* RF-AGC setup */ | |
| 389 | + WR16(B_FE_AG_REG_PDA_AUR_CNT__A, 0x0C), | |
| 390 | + WR16(B_FE_AG_REG_PDC_SET_LVL__A, 0x01), | |
| 391 | + WR16(B_FE_AG_REG_PDC_FLA_RGN__A, 0x02), | |
| 392 | + WR16(B_FE_AG_REG_PDC_FLA_STP__A, 0xFFFF), | |
| 393 | + WR16(B_FE_AG_REG_PDC_SLO_STP__A, 0xFFFF), | |
| 394 | + WR16(B_FE_AG_REG_PDC_MAX__A, 0x02), | |
| 395 | + WR16(B_FE_AG_REG_TGA_AUR_CNT__A, 0x0C), | |
| 396 | + WR16(B_FE_AG_REG_TGC_SET_LVL__A, 0x22), | |
| 397 | + WR16(B_FE_AG_REG_TGC_FLA_RGN__A, 0x15), | |
| 398 | + WR16(B_FE_AG_REG_TGC_FLA_STP__A, 0x01), | |
| 399 | + WR16(B_FE_AG_REG_TGC_SLO_STP__A, 0x0A), | |
| 400 | + | |
| 401 | + WR16(B_FE_CU_REG_DIV_NFC_CLP__A, 0), | |
| 402 | + WR16(B_FE_CU_REG_CTR_NFC_OCR__A, 25000), | |
| 403 | + WR16(B_FE_CU_REG_CTR_NFC_ICR__A, 1), | |
| 404 | + END_OF_TABLE | |
| 405 | +}; | |
| 406 | + | |
| 407 | +u8 DRXD_InitCPA2[] = { | |
| 408 | + WRBLOCK(CP_REG_BR_SPL_OFFSET__A, 2), | |
| 409 | + 0x07, 0x00, /* CP_REG_BR_SPL_OFFSET__A */ | |
| 410 | + 0x0A, 0x00, /* CP_REG_BR_STR_DEL__A */ | |
| 411 | + | |
| 412 | + WRBLOCK(CP_REG_RT_ANG_INC0__A, 4), | |
| 413 | + 0x00, 0x00, /* CP_REG_RT_ANG_INC0__A */ | |
| 414 | + 0x00, 0x00, /* CP_REG_RT_ANG_INC1__A */ | |
| 415 | + 0x03, 0x00, /* CP_REG_RT_DETECT_ENA__A */ | |
| 416 | + 0x03, 0x00, /* CP_REG_RT_DETECT_TRH__A */ | |
| 417 | + | |
| 418 | + WRBLOCK(CP_REG_AC_NEXP_OFFS__A, 5), | |
| 419 | + 0x32, 0x00, /* CP_REG_AC_NEXP_OFFS__A */ | |
| 420 | + 0x62, 0x00, /* CP_REG_AC_AVER_POW__A */ | |
| 421 | + 0x82, 0x00, /* CP_REG_AC_MAX_POW__A */ | |
| 422 | + 0x26, 0x00, /* CP_REG_AC_WEIGHT_MAN__A */ | |
| 423 | + 0x0F, 0x00, /* CP_REG_AC_WEIGHT_EXP__A */ | |
| 424 | + | |
| 425 | + WRBLOCK(CP_REG_AC_AMP_MODE__A, 2), | |
| 426 | + 0x02, 0x00, /* CP_REG_AC_AMP_MODE__A */ | |
| 427 | + 0x01, 0x00, /* CP_REG_AC_AMP_FIX__A */ | |
| 428 | + | |
| 429 | + WR16(CP_REG_INTERVAL__A, 0x0005), | |
| 430 | + WR16(CP_REG_RT_EXP_MARG__A, 0x0004), | |
| 431 | + WR16(CP_REG_AC_ANG_MODE__A, 0x0003), | |
| 432 | + | |
| 433 | + WR16(CP_REG_COMM_EXEC__A, 0x0001), | |
| 434 | + END_OF_TABLE | |
| 435 | +}; | |
| 436 | + | |
| 437 | +u8 DRXD_InitCPB1[] = { | |
| 438 | + WR16(B_CP_REG_BR_SPL_OFFSET__A, 0x0008), | |
| 439 | + WR16(B_CP_COMM_EXEC__A, 0x0001), | |
| 440 | + END_OF_TABLE | |
| 441 | +}; | |
| 442 | + | |
| 443 | +u8 DRXD_InitCEA2[] = { | |
| 444 | + WRBLOCK(CE_REG_AVG_POW__A, 4), | |
| 445 | + 0x62, 0x00, /* CE_REG_AVG_POW__A */ | |
| 446 | + 0x78, 0x00, /* CE_REG_MAX_POW__A */ | |
| 447 | + 0x62, 0x00, /* CE_REG_ATT__A */ | |
| 448 | + 0x17, 0x00, /* CE_REG_NRED__A */ | |
| 449 | + | |
| 450 | + WRBLOCK(CE_REG_NE_ERR_SELECT__A, 2), | |
| 451 | + 0x07, 0x00, /* CE_REG_NE_ERR_SELECT__A */ | |
| 452 | + 0xEB, 0xFF, /* CE_REG_NE_TD_CAL__A */ | |
| 453 | + | |
| 454 | + WRBLOCK(CE_REG_NE_MIXAVG__A, 2), | |
| 455 | + 0x06, 0x00, /* CE_REG_NE_MIXAVG__A */ | |
| 456 | + 0x00, 0x00, /* CE_REG_NE_NUPD_OFS__A */ | |
| 457 | + | |
| 458 | + WRBLOCK(CE_REG_PE_NEXP_OFFS__A, 2), | |
| 459 | + 0x00, 0x00, /* CE_REG_PE_NEXP_OFFS__A */ | |
| 460 | + 0x00, 0x00, /* CE_REG_PE_TIMESHIFT__A */ | |
| 461 | + | |
| 462 | + WRBLOCK(CE_REG_TP_A0_TAP_NEW__A, 3), | |
| 463 | + 0x00, 0x01, /* CE_REG_TP_A0_TAP_NEW__A */ | |
| 464 | + 0x01, 0x00, /* CE_REG_TP_A0_TAP_NEW_VALID__A */ | |
| 465 | + 0x0E, 0x00, /* CE_REG_TP_A0_MU_LMS_STEP__A */ | |
| 466 | + | |
| 467 | + WRBLOCK(CE_REG_TP_A1_TAP_NEW__A, 3), | |
| 468 | + 0x00, 0x00, /* CE_REG_TP_A1_TAP_NEW__A */ | |
| 469 | + 0x01, 0x00, /* CE_REG_TP_A1_TAP_NEW_VALID__A */ | |
| 470 | + 0x0A, 0x00, /* CE_REG_TP_A1_MU_LMS_STEP__A */ | |
| 471 | + | |
| 472 | + WRBLOCK(CE_REG_FI_SHT_INCR__A, 2), | |
| 473 | + 0x12, 0x00, /* CE_REG_FI_SHT_INCR__A */ | |
| 474 | + 0x0C, 0x00, /* CE_REG_FI_EXP_NORM__A */ | |
| 475 | + | |
| 476 | + WRBLOCK(CE_REG_IR_INPUTSEL__A, 3), | |
| 477 | + 0x00, 0x00, /* CE_REG_IR_INPUTSEL__A */ | |
| 478 | + 0x00, 0x00, /* CE_REG_IR_STARTPOS__A */ | |
| 479 | + 0xFF, 0x00, /* CE_REG_IR_NEXP_THRES__A */ | |
| 480 | + | |
| 481 | + WR16(CE_REG_TI_NEXP_OFFS__A, 0x0000), | |
| 482 | + | |
| 483 | + END_OF_TABLE | |
| 484 | +}; | |
| 485 | + | |
| 486 | +u8 DRXD_InitCEB1[] = { | |
| 487 | + WR16(B_CE_REG_TI_PHN_ENABLE__A, 0x0001), | |
| 488 | + WR16(B_CE_REG_FR_PM_SET__A, 0x000D), | |
| 489 | + | |
| 490 | + END_OF_TABLE | |
| 491 | +}; | |
| 492 | + | |
| 493 | +u8 DRXD_InitEQA2[] = { | |
| 494 | + WRBLOCK(EQ_REG_OT_QNT_THRES0__A, 4), | |
| 495 | + 0x1E, 0x00, /* EQ_REG_OT_QNT_THRES0__A */ | |
| 496 | + 0x1F, 0x00, /* EQ_REG_OT_QNT_THRES1__A */ | |
| 497 | + 0x06, 0x00, /* EQ_REG_OT_CSI_STEP__A */ | |
| 498 | + 0x02, 0x00, /* EQ_REG_OT_CSI_OFFSET__A */ | |
| 499 | + | |
| 500 | + WR16(EQ_REG_TD_REQ_SMB_CNT__A, 0x0200), | |
| 501 | + WR16(EQ_REG_IS_CLIP_EXP__A, 0x001F), | |
| 502 | + WR16(EQ_REG_SN_OFFSET__A, (u16) (-7)), | |
| 503 | + WR16(EQ_REG_RC_SEL_CAR__A, 0x0002), | |
| 504 | + WR16(EQ_REG_COMM_EXEC__A, 0x0001), | |
| 505 | + END_OF_TABLE | |
| 506 | +}; | |
| 507 | + | |
| 508 | +u8 DRXD_InitEQB1[] = { | |
| 509 | + WR16(B_EQ_REG_COMM_EXEC__A, 0x0001), | |
| 510 | + END_OF_TABLE | |
| 511 | +}; | |
| 512 | + | |
| 513 | +u8 DRXD_ResetECRAM[] = { | |
| 514 | + /* Reset packet sync bytes in EC_VD ram */ | |
| 515 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000), | |
| 516 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000), | |
| 517 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000), | |
| 518 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000), | |
| 519 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000), | |
| 520 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000), | |
| 521 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000), | |
| 522 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000), | |
| 523 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000), | |
| 524 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000), | |
| 525 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000), | |
| 526 | + | |
| 527 | + /* Reset packet sync bytes in EC_RS ram */ | |
| 528 | + WR16(EC_RS_EC_RAM__A, 0x0000), | |
| 529 | + WR16(EC_RS_EC_RAM__A + 204, 0x0000), | |
| 530 | + END_OF_TABLE | |
| 531 | +}; | |
| 532 | + | |
| 533 | +u8 DRXD_InitECA2[] = { | |
| 534 | + WRBLOCK(EC_SB_REG_CSI_HI__A, 6), | |
| 535 | + 0x1F, 0x00, /* EC_SB_REG_CSI_HI__A */ | |
| 536 | + 0x1E, 0x00, /* EC_SB_REG_CSI_LO__A */ | |
| 537 | + 0x01, 0x00, /* EC_SB_REG_SMB_TGL__A */ | |
| 538 | + 0x7F, 0x00, /* EC_SB_REG_SNR_HI__A */ | |
| 539 | + 0x7F, 0x00, /* EC_SB_REG_SNR_MID__A */ | |
| 540 | + 0x7F, 0x00, /* EC_SB_REG_SNR_LO__A */ | |
| 541 | + | |
| 542 | + WRBLOCK(EC_RS_REG_REQ_PCK_CNT__A, 2), | |
| 543 | + 0x00, 0x10, /* EC_RS_REG_REQ_PCK_CNT__A */ | |
| 544 | + DATA16(EC_RS_REG_VAL_PCK), /* EC_RS_REG_VAL__A */ | |
| 545 | + | |
| 546 | + WRBLOCK(EC_OC_REG_TMD_TOP_MODE__A, 5), | |
| 547 | + 0x03, 0x00, /* EC_OC_REG_TMD_TOP_MODE__A */ | |
| 548 | + 0xF4, 0x01, /* EC_OC_REG_TMD_TOP_CNT__A */ | |
| 549 | + 0xC0, 0x03, /* EC_OC_REG_TMD_HIL_MAR__A */ | |
| 550 | + 0x40, 0x00, /* EC_OC_REG_TMD_LOL_MAR__A */ | |
| 551 | + 0x03, 0x00, /* EC_OC_REG_TMD_CUR_CNT__A */ | |
| 552 | + | |
| 553 | + WRBLOCK(EC_OC_REG_AVR_ASH_CNT__A, 2), | |
| 554 | + 0x06, 0x00, /* EC_OC_REG_AVR_ASH_CNT__A */ | |
| 555 | + 0x02, 0x00, /* EC_OC_REG_AVR_BSH_CNT__A */ | |
| 556 | + | |
| 557 | + WRBLOCK(EC_OC_REG_RCN_MODE__A, 7), | |
| 558 | + 0x07, 0x00, /* EC_OC_REG_RCN_MODE__A */ | |
| 559 | + 0x00, 0x00, /* EC_OC_REG_RCN_CRA_LOP__A */ | |
| 560 | + 0xc0, 0x00, /* EC_OC_REG_RCN_CRA_HIP__A */ | |
| 561 | + 0x00, 0x10, /* EC_OC_REG_RCN_CST_LOP__A */ | |
| 562 | + 0x00, 0x00, /* EC_OC_REG_RCN_CST_HIP__A */ | |
| 563 | + 0xFF, 0x01, /* EC_OC_REG_RCN_SET_LVL__A */ | |
| 564 | + 0x0D, 0x00, /* EC_OC_REG_RCN_GAI_LVL__A */ | |
| 565 | + | |
| 566 | + WRBLOCK(EC_OC_REG_RCN_CLP_LOP__A, 2), | |
| 567 | + 0x00, 0x00, /* EC_OC_REG_RCN_CLP_LOP__A */ | |
| 568 | + 0xC0, 0x00, /* EC_OC_REG_RCN_CLP_HIP__A */ | |
| 569 | + | |
| 570 | + WR16(EC_SB_REG_CSI_OFS__A, 0x0001), | |
| 571 | + WR16(EC_VD_REG_FORCE__A, 0x0002), | |
| 572 | + WR16(EC_VD_REG_REQ_SMB_CNT__A, 0x0001), | |
| 573 | + WR16(EC_VD_REG_RLK_ENA__A, 0x0001), | |
| 574 | + WR16(EC_OD_REG_SYNC__A, 0x0664), | |
| 575 | + WR16(EC_OC_REG_OC_MON_SIO__A, 0x0000), | |
| 576 | + WR16(EC_OC_REG_SNC_ISC_LVL__A, 0x0D0C), | |
| 577 | + /* Output zero on monitorbus pads, power saving */ | |
| 578 | + WR16(EC_OC_REG_OCR_MON_UOS__A, | |
| 579 | + (EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE | | |
| 580 | + EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE | | |
| 581 | + EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE | | |
| 582 | + EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE | | |
| 583 | + EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE | | |
| 584 | + EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE | | |
| 585 | + EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE | | |
| 586 | + EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE | | |
| 587 | + EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE | | |
| 588 | + EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE | | |
| 589 | + EC_OC_REG_OCR_MON_UOS_VAL_ENABLE | | |
| 590 | + EC_OC_REG_OCR_MON_UOS_CLK_ENABLE)), | |
| 591 | + WR16(EC_OC_REG_OCR_MON_WRI__A, | |
| 592 | + EC_OC_REG_OCR_MON_WRI_INIT), | |
| 593 | + | |
| 594 | +/* CHK_ERROR(ResetECRAM(demod)); */ | |
| 595 | + /* Reset packet sync bytes in EC_VD ram */ | |
| 596 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000), | |
| 597 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000), | |
| 598 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000), | |
| 599 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000), | |
| 600 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000), | |
| 601 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000), | |
| 602 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000), | |
| 603 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000), | |
| 604 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000), | |
| 605 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000), | |
| 606 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000), | |
| 607 | + | |
| 608 | + /* Reset packet sync bytes in EC_RS ram */ | |
| 609 | + WR16(EC_RS_EC_RAM__A, 0x0000), | |
| 610 | + WR16(EC_RS_EC_RAM__A + 204, 0x0000), | |
| 611 | + | |
| 612 | + WR16(EC_SB_REG_COMM_EXEC__A, 0x0001), | |
| 613 | + WR16(EC_VD_REG_COMM_EXEC__A, 0x0001), | |
| 614 | + WR16(EC_OD_REG_COMM_EXEC__A, 0x0001), | |
| 615 | + WR16(EC_RS_REG_COMM_EXEC__A, 0x0001), | |
| 616 | + END_OF_TABLE | |
| 617 | +}; | |
| 618 | + | |
| 619 | +u8 DRXD_InitECB1[] = { | |
| 620 | + WR16(B_EC_SB_REG_CSI_OFS0__A, 0x0001), | |
| 621 | + WR16(B_EC_SB_REG_CSI_OFS1__A, 0x0001), | |
| 622 | + WR16(B_EC_SB_REG_CSI_OFS2__A, 0x0001), | |
| 623 | + WR16(B_EC_SB_REG_CSI_LO__A, 0x000c), | |
| 624 | + WR16(B_EC_SB_REG_CSI_HI__A, 0x0018), | |
| 625 | + WR16(B_EC_SB_REG_SNR_HI__A, 0x007f), | |
| 626 | + WR16(B_EC_SB_REG_SNR_MID__A, 0x007f), | |
| 627 | + WR16(B_EC_SB_REG_SNR_LO__A, 0x007f), | |
| 628 | + | |
| 629 | + WR16(B_EC_OC_REG_DTO_CLKMODE__A, 0x0002), | |
| 630 | + WR16(B_EC_OC_REG_DTO_PER__A, 0x0006), | |
| 631 | + WR16(B_EC_OC_REG_DTO_BUR__A, 0x0001), | |
| 632 | + WR16(B_EC_OC_REG_RCR_CLKMODE__A, 0x0000), | |
| 633 | + WR16(B_EC_OC_REG_RCN_GAI_LVL__A, 0x000D), | |
| 634 | + WR16(B_EC_OC_REG_OC_MPG_SIO__A, 0x0000), | |
| 635 | + | |
| 636 | + /* Needed because shadow registers do not have correct default value */ | |
| 637 | + WR16(B_EC_OC_REG_RCN_CST_LOP__A, 0x1000), | |
| 638 | + WR16(B_EC_OC_REG_RCN_CST_HIP__A, 0x0000), | |
| 639 | + WR16(B_EC_OC_REG_RCN_CRA_LOP__A, 0x0000), | |
| 640 | + WR16(B_EC_OC_REG_RCN_CRA_HIP__A, 0x00C0), | |
| 641 | + WR16(B_EC_OC_REG_RCN_CLP_LOP__A, 0x0000), | |
| 642 | + WR16(B_EC_OC_REG_RCN_CLP_HIP__A, 0x00C0), | |
| 643 | + WR16(B_EC_OC_REG_DTO_INC_LOP__A, 0x0000), | |
| 644 | + WR16(B_EC_OC_REG_DTO_INC_HIP__A, 0x00C0), | |
| 645 | + | |
| 646 | + WR16(B_EC_OD_REG_SYNC__A, 0x0664), | |
| 647 | + WR16(B_EC_RS_REG_REQ_PCK_CNT__A, 0x1000), | |
| 648 | + | |
| 649 | +/* CHK_ERROR(ResetECRAM(demod)); */ | |
| 650 | + /* Reset packet sync bytes in EC_VD ram */ | |
| 651 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000), | |
| 652 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000), | |
| 653 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000), | |
| 654 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000), | |
| 655 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000), | |
| 656 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000), | |
| 657 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000), | |
| 658 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000), | |
| 659 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000), | |
| 660 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000), | |
| 661 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000), | |
| 662 | + | |
| 663 | + /* Reset packet sync bytes in EC_RS ram */ | |
| 664 | + WR16(EC_RS_EC_RAM__A, 0x0000), | |
| 665 | + WR16(EC_RS_EC_RAM__A + 204, 0x0000), | |
| 666 | + | |
| 667 | + WR16(B_EC_SB_REG_COMM_EXEC__A, 0x0001), | |
| 668 | + WR16(B_EC_VD_REG_COMM_EXEC__A, 0x0001), | |
| 669 | + WR16(B_EC_OD_REG_COMM_EXEC__A, 0x0001), | |
| 670 | + WR16(B_EC_RS_REG_COMM_EXEC__A, 0x0001), | |
| 671 | + END_OF_TABLE | |
| 672 | +}; | |
| 673 | + | |
| 674 | +u8 DRXD_ResetECA2[] = { | |
| 675 | + | |
| 676 | + WR16(EC_OC_REG_COMM_EXEC__A, 0x0000), | |
| 677 | + WR16(EC_OD_REG_COMM_EXEC__A, 0x0000), | |
| 678 | + | |
| 679 | + WRBLOCK(EC_OC_REG_TMD_TOP_MODE__A, 5), | |
| 680 | + 0x03, 0x00, /* EC_OC_REG_TMD_TOP_MODE__A */ | |
| 681 | + 0xF4, 0x01, /* EC_OC_REG_TMD_TOP_CNT__A */ | |
| 682 | + 0xC0, 0x03, /* EC_OC_REG_TMD_HIL_MAR__A */ | |
| 683 | + 0x40, 0x00, /* EC_OC_REG_TMD_LOL_MAR__A */ | |
| 684 | + 0x03, 0x00, /* EC_OC_REG_TMD_CUR_CNT__A */ | |
| 685 | + | |
| 686 | + WRBLOCK(EC_OC_REG_AVR_ASH_CNT__A, 2), | |
| 687 | + 0x06, 0x00, /* EC_OC_REG_AVR_ASH_CNT__A */ | |
| 688 | + 0x02, 0x00, /* EC_OC_REG_AVR_BSH_CNT__A */ | |
| 689 | + | |
| 690 | + WRBLOCK(EC_OC_REG_RCN_MODE__A, 7), | |
| 691 | + 0x07, 0x00, /* EC_OC_REG_RCN_MODE__A */ | |
| 692 | + 0x00, 0x00, /* EC_OC_REG_RCN_CRA_LOP__A */ | |
| 693 | + 0xc0, 0x00, /* EC_OC_REG_RCN_CRA_HIP__A */ | |
| 694 | + 0x00, 0x10, /* EC_OC_REG_RCN_CST_LOP__A */ | |
| 695 | + 0x00, 0x00, /* EC_OC_REG_RCN_CST_HIP__A */ | |
| 696 | + 0xFF, 0x01, /* EC_OC_REG_RCN_SET_LVL__A */ | |
| 697 | + 0x0D, 0x00, /* EC_OC_REG_RCN_GAI_LVL__A */ | |
| 698 | + | |
| 699 | + WRBLOCK(EC_OC_REG_RCN_CLP_LOP__A, 2), | |
| 700 | + 0x00, 0x00, /* EC_OC_REG_RCN_CLP_LOP__A */ | |
| 701 | + 0xC0, 0x00, /* EC_OC_REG_RCN_CLP_HIP__A */ | |
| 702 | + | |
| 703 | + WR16(EC_OD_REG_SYNC__A, 0x0664), | |
| 704 | + WR16(EC_OC_REG_OC_MON_SIO__A, 0x0000), | |
| 705 | + WR16(EC_OC_REG_SNC_ISC_LVL__A, 0x0D0C), | |
| 706 | + /* Output zero on monitorbus pads, power saving */ | |
| 707 | + WR16(EC_OC_REG_OCR_MON_UOS__A, | |
| 708 | + (EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE | | |
| 709 | + EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE | | |
| 710 | + EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE | | |
| 711 | + EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE | | |
| 712 | + EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE | | |
| 713 | + EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE | | |
| 714 | + EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE | | |
| 715 | + EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE | | |
| 716 | + EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE | | |
| 717 | + EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE | | |
| 718 | + EC_OC_REG_OCR_MON_UOS_VAL_ENABLE | | |
| 719 | + EC_OC_REG_OCR_MON_UOS_CLK_ENABLE)), | |
| 720 | + WR16(EC_OC_REG_OCR_MON_WRI__A, | |
| 721 | + EC_OC_REG_OCR_MON_WRI_INIT), | |
| 722 | + | |
| 723 | +/* CHK_ERROR(ResetECRAM(demod)); */ | |
| 724 | + /* Reset packet sync bytes in EC_VD ram */ | |
| 725 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000), | |
| 726 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000), | |
| 727 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000), | |
| 728 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000), | |
| 729 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000), | |
| 730 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000), | |
| 731 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000), | |
| 732 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000), | |
| 733 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000), | |
| 734 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000), | |
| 735 | + WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000), | |
| 736 | + | |
| 737 | + /* Reset packet sync bytes in EC_RS ram */ | |
| 738 | + WR16(EC_RS_EC_RAM__A, 0x0000), | |
| 739 | + WR16(EC_RS_EC_RAM__A + 204, 0x0000), | |
| 740 | + | |
| 741 | + WR16(EC_OD_REG_COMM_EXEC__A, 0x0001), | |
| 742 | + END_OF_TABLE | |
| 743 | +}; | |
| 744 | + | |
| 745 | +u8 DRXD_InitSC[] = { | |
| 746 | + WR16(SC_COMM_EXEC__A, 0), | |
| 747 | + WR16(SC_COMM_STATE__A, 0), | |
| 748 | + | |
| 749 | +#ifdef COMPILE_FOR_QT | |
| 750 | + WR16(SC_RA_RAM_BE_OPT_DELAY__A, 0x100), | |
| 751 | +#endif | |
| 752 | + | |
| 753 | + /* SC is not started, this is done in SetChannels() */ | |
| 754 | + END_OF_TABLE | |
| 755 | +}; | |
| 756 | + | |
| 757 | +/* Diversity settings */ | |
| 758 | + | |
| 759 | +u8 DRXD_InitDiversityFront[] = { | |
| 760 | + /* Start demod ********* RF in , diversity out **************************** */ | |
| 761 | + WR16(B_SC_RA_RAM_CONFIG__A, B_SC_RA_RAM_CONFIG_FR_ENABLE__M | | |
| 762 | + B_SC_RA_RAM_CONFIG_FREQSCAN__M), | |
| 763 | + | |
| 764 | + WR16(B_SC_RA_RAM_LC_ABS_2K__A, 0x7), | |
| 765 | + WR16(B_SC_RA_RAM_LC_ABS_8K__A, 0x7), | |
| 766 | + WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A, IRLEN_COARSE_8K), | |
| 767 | + WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A, 1 << (11 - IRLEN_COARSE_8K)), | |
| 768 | + WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A, 1 << (17 - IRLEN_COARSE_8K)), | |
| 769 | + WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A, IRLEN_FINE_8K), | |
| 770 | + WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A, 1 << (11 - IRLEN_FINE_8K)), | |
| 771 | + WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A, 1 << (17 - IRLEN_FINE_8K)), | |
| 772 | + | |
| 773 | + WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A, IRLEN_COARSE_2K), | |
| 774 | + WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A, 1 << (11 - IRLEN_COARSE_2K)), | |
| 775 | + WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A, 1 << (17 - IRLEN_COARSE_2K)), | |
| 776 | + WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A, IRLEN_FINE_2K), | |
| 777 | + WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A, 1 << (11 - IRLEN_FINE_2K)), | |
| 778 | + WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A, 1 << (17 - IRLEN_FINE_2K)), | |
| 779 | + | |
| 780 | + WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, 7), | |
| 781 | + WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, 4), | |
| 782 | + WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, 7), | |
| 783 | + WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, 4), | |
| 784 | + WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, 500), | |
| 785 | + | |
| 786 | + WR16(B_CC_REG_DIVERSITY__A, 0x0001), | |
| 787 | + WR16(B_EC_OC_REG_OC_MODE_HIP__A, 0x0010), | |
| 788 | + WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_PASS_B_CE | | |
| 789 | + B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE | B_EQ_REG_RC_SEL_CAR_MEAS_B_CE), | |
| 790 | + | |
| 791 | + /* 0x2a ), *//* CE to PASS mux */ | |
| 792 | + | |
| 793 | + END_OF_TABLE | |
| 794 | +}; | |
| 795 | + | |
| 796 | +u8 DRXD_InitDiversityEnd[] = { | |
| 797 | + /* End demod *********** combining RF in and diversity in, MPEG TS out **** */ | |
| 798 | + /* disable near/far; switch on timing slave mode */ | |
| 799 | + WR16(B_SC_RA_RAM_CONFIG__A, B_SC_RA_RAM_CONFIG_FR_ENABLE__M | | |
| 800 | + B_SC_RA_RAM_CONFIG_FREQSCAN__M | | |
| 801 | + B_SC_RA_RAM_CONFIG_DIV_ECHO_ENABLE__M | | |
| 802 | + B_SC_RA_RAM_CONFIG_SLAVE__M | | |
| 803 | + B_SC_RA_RAM_CONFIG_DIV_BLANK_ENABLE__M | |
| 804 | +/* MV from CtrlDiversity */ | |
| 805 | + ), | |
| 806 | +#ifdef DRXDDIV_SRMM_SLAVING | |
| 807 | + WR16(SC_RA_RAM_LC_ABS_2K__A, 0x3c7), | |
| 808 | + WR16(SC_RA_RAM_LC_ABS_8K__A, 0x3c7), | |
| 809 | +#else | |
| 810 | + WR16(SC_RA_RAM_LC_ABS_2K__A, 0x7), | |
| 811 | + WR16(SC_RA_RAM_LC_ABS_8K__A, 0x7), | |
| 812 | +#endif | |
| 813 | + | |
| 814 | + WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A, IRLEN_COARSE_8K), | |
| 815 | + WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A, 1 << (11 - IRLEN_COARSE_8K)), | |
| 816 | + WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A, 1 << (17 - IRLEN_COARSE_8K)), | |
| 817 | + WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A, IRLEN_FINE_8K), | |
| 818 | + WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A, 1 << (11 - IRLEN_FINE_8K)), | |
| 819 | + WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A, 1 << (17 - IRLEN_FINE_8K)), | |
| 820 | + | |
| 821 | + WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A, IRLEN_COARSE_2K), | |
| 822 | + WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A, 1 << (11 - IRLEN_COARSE_2K)), | |
| 823 | + WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A, 1 << (17 - IRLEN_COARSE_2K)), | |
| 824 | + WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A, IRLEN_FINE_2K), | |
| 825 | + WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A, 1 << (11 - IRLEN_FINE_2K)), | |
| 826 | + WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A, 1 << (17 - IRLEN_FINE_2K)), | |
| 827 | + | |
| 828 | + WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, 7), | |
| 829 | + WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, 4), | |
| 830 | + WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, 7), | |
| 831 | + WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, 4), | |
| 832 | + WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, 500), | |
| 833 | + | |
| 834 | + WR16(B_CC_REG_DIVERSITY__A, 0x0001), | |
| 835 | + END_OF_TABLE | |
| 836 | +}; | |
| 837 | + | |
| 838 | +u8 DRXD_DisableDiversity[] = { | |
| 839 | + WR16(B_SC_RA_RAM_LC_ABS_2K__A, B_SC_RA_RAM_LC_ABS_2K__PRE), | |
| 840 | + WR16(B_SC_RA_RAM_LC_ABS_8K__A, B_SC_RA_RAM_LC_ABS_8K__PRE), | |
| 841 | + WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A, | |
| 842 | + B_SC_RA_RAM_IR_COARSE_8K_LENGTH__PRE), | |
| 843 | + WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A, | |
| 844 | + B_SC_RA_RAM_IR_COARSE_8K_FREQINC__PRE), | |
| 845 | + WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A, | |
| 846 | + B_SC_RA_RAM_IR_COARSE_8K_KAISINC__PRE), | |
| 847 | + WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A, | |
| 848 | + B_SC_RA_RAM_IR_FINE_8K_LENGTH__PRE), | |
| 849 | + WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A, | |
| 850 | + B_SC_RA_RAM_IR_FINE_8K_FREQINC__PRE), | |
| 851 | + WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A, | |
| 852 | + B_SC_RA_RAM_IR_FINE_8K_KAISINC__PRE), | |
| 853 | + | |
| 854 | + WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A, | |
| 855 | + B_SC_RA_RAM_IR_COARSE_2K_LENGTH__PRE), | |
| 856 | + WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A, | |
| 857 | + B_SC_RA_RAM_IR_COARSE_2K_FREQINC__PRE), | |
| 858 | + WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A, | |
| 859 | + B_SC_RA_RAM_IR_COARSE_2K_KAISINC__PRE), | |
| 860 | + WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A, | |
| 861 | + B_SC_RA_RAM_IR_FINE_2K_LENGTH__PRE), | |
| 862 | + WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A, | |
| 863 | + B_SC_RA_RAM_IR_FINE_2K_FREQINC__PRE), | |
| 864 | + WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A, | |
| 865 | + B_SC_RA_RAM_IR_FINE_2K_KAISINC__PRE), | |
| 866 | + | |
| 867 | + WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, B_LC_RA_RAM_FILTER_CRMM_A__PRE), | |
| 868 | + WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, B_LC_RA_RAM_FILTER_CRMM_B__PRE), | |
| 869 | + WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, B_LC_RA_RAM_FILTER_SRMM_A__PRE), | |
| 870 | + WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, B_LC_RA_RAM_FILTER_SRMM_B__PRE), | |
| 871 | + WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, B_LC_RA_RAM_FILTER_SYM_SET__PRE), | |
| 872 | + | |
| 873 | + WR16(B_CC_REG_DIVERSITY__A, 0x0000), | |
| 874 | + WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_INIT), /* combining disabled */ | |
| 875 | + | |
| 876 | + END_OF_TABLE | |
| 877 | +}; | |
| 878 | + | |
| 879 | +u8 DRXD_StartDiversityFront[] = { | |
| 880 | + /* Start demod, RF in and diversity out, no combining */ | |
| 881 | + WR16(B_FE_CF_REG_IMP_VAL__A, 0x0), | |
| 882 | + WR16(B_FE_AD_REG_FDB_IN__A, 0x0), | |
| 883 | + WR16(B_FE_AD_REG_INVEXT__A, 0x0), | |
| 884 | + WR16(B_EQ_REG_COMM_MB__A, 0x12), /* EQ to MB out */ | |
| 885 | + WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_PASS_B_CE | /* CE to PASS mux */ | |
| 886 | + B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE | B_EQ_REG_RC_SEL_CAR_MEAS_B_CE), | |
| 887 | + | |
| 888 | + WR16(SC_RA_RAM_ECHO_SHIFT_LIM__A, 2), | |
| 889 | + | |
| 890 | + END_OF_TABLE | |
| 891 | +}; | |
| 892 | + | |
| 893 | +u8 DRXD_StartDiversityEnd[] = { | |
| 894 | + /* End demod, combining RF in and diversity in, MPEG TS out */ | |
| 895 | + WR16(B_FE_CF_REG_IMP_VAL__A, 0x0), /* disable impulse noise cruncher */ | |
| 896 | + WR16(B_FE_AD_REG_INVEXT__A, 0x0), /* clock inversion (for sohard board) */ | |
| 897 | + WR16(B_CP_REG_BR_STR_DEL__A, 10), /* apperently no mb delay matching is best */ | |
| 898 | + | |
| 899 | + WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_DIV_ON | /* org = 0x81 combining enabled */ | |
| 900 | + B_EQ_REG_RC_SEL_CAR_MEAS_A_CC | | |
| 901 | + B_EQ_REG_RC_SEL_CAR_PASS_A_CC | B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC), | |
| 902 | + | |
| 903 | + END_OF_TABLE | |
| 904 | +}; | |
| 905 | + | |
| 906 | +u8 DRXD_DiversityDelay8MHZ[] = { | |
| 907 | + WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A, 1150 - 50), | |
| 908 | + WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A, 1100 - 50), | |
| 909 | + WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A, 1000 - 50), | |
| 910 | + WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A, 800 - 50), | |
| 911 | + WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A, 5420 - 50), | |
| 912 | + WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A, 5200 - 50), | |
| 913 | + WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A, 4800 - 50), | |
| 914 | + WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A, 4000 - 50), | |
| 915 | + END_OF_TABLE | |
| 916 | +}; | |
| 917 | + | |
| 918 | +u8 DRXD_DiversityDelay6MHZ[] = /* also used ok for 7 MHz */ | |
| 919 | +{ | |
| 920 | + WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A, 1100 - 50), | |
| 921 | + WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A, 1000 - 50), | |
| 922 | + WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A, 900 - 50), | |
| 923 | + WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A, 600 - 50), | |
| 924 | + WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A, 5300 - 50), | |
| 925 | + WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A, 5000 - 50), | |
| 926 | + WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A, 4500 - 50), | |
| 927 | + WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A, 3500 - 50), | |
| 928 | + END_OF_TABLE | |
| 929 | +}; | |
| @@ -0,0 +1,115 @@ | ||
| 1 | +/* | |
| 2 | + * drxd_firm.h | |
| 3 | + * | |
| 4 | + * Copyright (C) 2006-2007 Micronas | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or | |
| 7 | + * modify it under the terms of the GNU General Public License | |
| 8 | + * version 2 only, as published by the Free Software Foundation. | |
| 9 | + * | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License | |
| 18 | + * along with this program; if not, write to the Free Software | |
| 19 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| 20 | + * 02110-1301, USA | |
| 21 | + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | |
| 22 | + */ | |
| 23 | + | |
| 24 | +#ifndef _DRXD_FIRM_H_ | |
| 25 | +#define _DRXD_FIRM_H_ | |
| 26 | + | |
| 27 | +#include <linux/types.h> | |
| 28 | +#include "drxd_map_firm.h" | |
| 29 | + | |
| 30 | +#define VERSION_MAJOR 1 | |
| 31 | +#define VERSION_MINOR 4 | |
| 32 | +#define VERSION_PATCH 23 | |
| 33 | + | |
| 34 | +#define HI_TR_FUNC_ADDR HI_IF_RAM_USR_BEGIN__A | |
| 35 | + | |
| 36 | +#define DRXD_MAX_RETRIES (1000) | |
| 37 | +#define HI_I2C_DELAY 84 | |
| 38 | +#define HI_I2C_BRIDGE_DELAY 750 | |
| 39 | + | |
| 40 | +#define EQ_TD_TPS_PWR_UNKNOWN 0x00C0 /* Unknown configurations */ | |
| 41 | +#define EQ_TD_TPS_PWR_QPSK 0x016a | |
| 42 | +#define EQ_TD_TPS_PWR_QAM16_ALPHAN 0x0195 | |
| 43 | +#define EQ_TD_TPS_PWR_QAM16_ALPHA1 0x0195 | |
| 44 | +#define EQ_TD_TPS_PWR_QAM16_ALPHA2 0x011E | |
| 45 | +#define EQ_TD_TPS_PWR_QAM16_ALPHA4 0x01CE | |
| 46 | +#define EQ_TD_TPS_PWR_QAM64_ALPHAN 0x019F | |
| 47 | +#define EQ_TD_TPS_PWR_QAM64_ALPHA1 0x019F | |
| 48 | +#define EQ_TD_TPS_PWR_QAM64_ALPHA2 0x00F8 | |
| 49 | +#define EQ_TD_TPS_PWR_QAM64_ALPHA4 0x014D | |
| 50 | + | |
| 51 | +#define DRXD_DEF_AG_PWD_CONSUMER 0x000E | |
| 52 | +#define DRXD_DEF_AG_PWD_PRO 0x0000 | |
| 53 | +#define DRXD_DEF_AG_AGC_SIO 0x0000 | |
| 54 | + | |
| 55 | +#define DRXD_FE_CTRL_MAX 1023 | |
| 56 | + | |
| 57 | +#define DRXD_OSCDEV_DO_SCAN (16) | |
| 58 | + | |
| 59 | +#define DRXD_OSCDEV_DONT_SCAN (0) | |
| 60 | + | |
| 61 | +#define DRXD_OSCDEV_STEP (275) | |
| 62 | + | |
| 63 | +#define DRXD_SCAN_TIMEOUT (650) | |
| 64 | + | |
| 65 | +#define DRXD_BANDWIDTH_8MHZ_IN_HZ (0x8B8249L) | |
| 66 | +#define DRXD_BANDWIDTH_7MHZ_IN_HZ (0x7A1200L) | |
| 67 | +#define DRXD_BANDWIDTH_6MHZ_IN_HZ (0x68A1B6L) | |
| 68 | + | |
| 69 | +#define IRLEN_COARSE_8K (10) | |
| 70 | +#define IRLEN_FINE_8K (10) | |
| 71 | +#define IRLEN_COARSE_2K (7) | |
| 72 | +#define IRLEN_FINE_2K (9) | |
| 73 | +#define DIFF_INVALID (511) | |
| 74 | +#define DIFF_TARGET (4) | |
| 75 | +#define DIFF_MARGIN (1) | |
| 76 | + | |
| 77 | +extern u8 DRXD_InitAtomicRead[]; | |
| 78 | +extern u8 DRXD_HiI2cPatch_1[]; | |
| 79 | +extern u8 DRXD_HiI2cPatch_3[]; | |
| 80 | + | |
| 81 | +extern u8 DRXD_InitSC[]; | |
| 82 | + | |
| 83 | +extern u8 DRXD_ResetCEFR[]; | |
| 84 | +extern u8 DRXD_InitFEA2_1[]; | |
| 85 | +extern u8 DRXD_InitFEA2_2[]; | |
| 86 | +extern u8 DRXD_InitCPA2[]; | |
| 87 | +extern u8 DRXD_InitCEA2[]; | |
| 88 | +extern u8 DRXD_InitEQA2[]; | |
| 89 | +extern u8 DRXD_InitECA2[]; | |
| 90 | +extern u8 DRXD_ResetECA2[]; | |
| 91 | +extern u8 DRXD_ResetECRAM[]; | |
| 92 | + | |
| 93 | +extern u8 DRXD_A2_microcode[]; | |
| 94 | +extern u32 DRXD_A2_microcode_length; | |
| 95 | + | |
| 96 | +extern u8 DRXD_InitFEB1_1[]; | |
| 97 | +extern u8 DRXD_InitFEB1_2[]; | |
| 98 | +extern u8 DRXD_InitCPB1[]; | |
| 99 | +extern u8 DRXD_InitCEB1[]; | |
| 100 | +extern u8 DRXD_InitEQB1[]; | |
| 101 | +extern u8 DRXD_InitECB1[]; | |
| 102 | + | |
| 103 | +extern u8 DRXD_InitDiversityFront[]; | |
| 104 | +extern u8 DRXD_InitDiversityEnd[]; | |
| 105 | +extern u8 DRXD_DisableDiversity[]; | |
| 106 | +extern u8 DRXD_StartDiversityFront[]; | |
| 107 | +extern u8 DRXD_StartDiversityEnd[]; | |
| 108 | + | |
| 109 | +extern u8 DRXD_DiversityDelay8MHZ[]; | |
| 110 | +extern u8 DRXD_DiversityDelay6MHZ[]; | |
| 111 | + | |
| 112 | +extern u8 DRXD_B1_microcode[]; | |
| 113 | +extern u32 DRXD_B1_microcode_length; | |
| 114 | + | |
| 115 | +#endif | |
| @@ -0,0 +1,3001 @@ | ||
| 1 | +/* | |
| 2 | + * drxd_hard.c: DVB-T Demodulator Micronas DRX3975D-A2,DRX397xD-B1 | |
| 3 | + * | |
| 4 | + * Copyright (C) 2003-2007 Micronas | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or | |
| 7 | + * modify it under the terms of the GNU General Public License | |
| 8 | + * version 2 only, as published by the Free Software Foundation. | |
| 9 | + * | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License | |
| 18 | + * along with this program; if not, write to the Free Software | |
| 19 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| 20 | + * 02110-1301, USA | |
| 21 | + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | |
| 22 | + */ | |
| 23 | + | |
| 24 | +#include <linux/kernel.h> | |
| 25 | +#include <linux/module.h> | |
| 26 | +#include <linux/moduleparam.h> | |
| 27 | +#include <linux/init.h> | |
| 28 | +#include <linux/delay.h> | |
| 29 | +#include <linux/firmware.h> | |
| 30 | +#include <linux/i2c.h> | |
| 31 | +#include <linux/version.h> | |
| 32 | +#include <asm/div64.h> | |
| 33 | + | |
| 34 | +#include "dvb_frontend.h" | |
| 35 | +#include "drxd.h" | |
| 36 | +#include "drxd_firm.h" | |
| 37 | + | |
| 38 | +#define DRX_FW_FILENAME_A2 "drxd-a2-1.1.fw" | |
| 39 | +#define DRX_FW_FILENAME_B1 "drxd-b1-1.1.fw" | |
| 40 | + | |
| 41 | +#define CHUNK_SIZE 48 | |
| 42 | + | |
| 43 | +#define DRX_I2C_RMW 0x10 | |
| 44 | +#define DRX_I2C_BROADCAST 0x20 | |
| 45 | +#define DRX_I2C_CLEARCRC 0x80 | |
| 46 | +#define DRX_I2C_SINGLE_MASTER 0xC0 | |
| 47 | +#define DRX_I2C_MODEFLAGS 0xC0 | |
| 48 | +#define DRX_I2C_FLAGS 0xF0 | |
| 49 | + | |
| 50 | +#ifndef SIZEOF_ARRAY | |
| 51 | +#define SIZEOF_ARRAY(array) (sizeof((array))/sizeof((array)[0])) | |
| 52 | +#endif | |
| 53 | + | |
| 54 | +#define DEFAULT_LOCK_TIMEOUT 1100 | |
| 55 | + | |
| 56 | +#define DRX_CHANNEL_AUTO 0 | |
| 57 | +#define DRX_CHANNEL_HIGH 1 | |
| 58 | +#define DRX_CHANNEL_LOW 2 | |
| 59 | + | |
| 60 | +#define DRX_LOCK_MPEG 1 | |
| 61 | +#define DRX_LOCK_FEC 2 | |
| 62 | +#define DRX_LOCK_DEMOD 4 | |
| 63 | + | |
| 64 | +/****************************************************************************/ | |
| 65 | + | |
| 66 | +enum CSCDState { | |
| 67 | + CSCD_INIT = 0, | |
| 68 | + CSCD_SET, | |
| 69 | + CSCD_SAVED | |
| 70 | +}; | |
| 71 | + | |
| 72 | +enum CDrxdState { | |
| 73 | + DRXD_UNINITIALIZED = 0, | |
| 74 | + DRXD_STOPPED, | |
| 75 | + DRXD_STARTED | |
| 76 | +}; | |
| 77 | + | |
| 78 | +enum AGC_CTRL_MODE { | |
| 79 | + AGC_CTRL_AUTO = 0, | |
| 80 | + AGC_CTRL_USER, | |
| 81 | + AGC_CTRL_OFF | |
| 82 | +}; | |
| 83 | + | |
| 84 | +enum OperationMode { | |
| 85 | + OM_Default, | |
| 86 | + OM_DVBT_Diversity_Front, | |
| 87 | + OM_DVBT_Diversity_End | |
| 88 | +}; | |
| 89 | + | |
| 90 | +struct SCfgAgc { | |
| 91 | + enum AGC_CTRL_MODE ctrlMode; | |
| 92 | + u16 outputLevel; /* range [0, ... , 1023], 1/n of fullscale range */ | |
| 93 | + u16 settleLevel; /* range [0, ... , 1023], 1/n of fullscale range */ | |
| 94 | + u16 minOutputLevel; /* range [0, ... , 1023], 1/n of fullscale range */ | |
| 95 | + u16 maxOutputLevel; /* range [0, ... , 1023], 1/n of fullscale range */ | |
| 96 | + u16 speed; /* range [0, ... , 1023], 1/n of fullscale range */ | |
| 97 | + | |
| 98 | + u16 R1; | |
| 99 | + u16 R2; | |
| 100 | + u16 R3; | |
| 101 | +}; | |
| 102 | + | |
| 103 | +struct SNoiseCal { | |
| 104 | + int cpOpt; | |
| 105 | + u16 cpNexpOfs; | |
| 106 | + u16 tdCal2k; | |
| 107 | + u16 tdCal8k; | |
| 108 | +}; | |
| 109 | + | |
| 110 | +enum app_env { | |
| 111 | + APPENV_STATIC = 0, | |
| 112 | + APPENV_PORTABLE = 1, | |
| 113 | + APPENV_MOBILE = 2 | |
| 114 | +}; | |
| 115 | + | |
| 116 | +enum EIFFilter { | |
| 117 | + IFFILTER_SAW = 0, | |
| 118 | + IFFILTER_DISCRETE = 1 | |
| 119 | +}; | |
| 120 | + | |
| 121 | +struct drxd_state { | |
| 122 | + struct dvb_frontend frontend; | |
| 123 | + struct dvb_frontend_ops ops; | |
| 124 | + struct dvb_frontend_parameters param; | |
| 125 | + | |
| 126 | + const struct firmware *fw; | |
| 127 | + struct device *dev; | |
| 128 | + | |
| 129 | + struct i2c_adapter *i2c; | |
| 130 | + void *priv; | |
| 131 | + struct drxd_config config; | |
| 132 | + | |
| 133 | + int i2c_access; | |
| 134 | + int init_done; | |
| 135 | + struct mutex mutex; | |
| 136 | + | |
| 137 | + u8 chip_adr; | |
| 138 | + u16 hi_cfg_timing_div; | |
| 139 | + u16 hi_cfg_bridge_delay; | |
| 140 | + u16 hi_cfg_wakeup_key; | |
| 141 | + u16 hi_cfg_ctrl; | |
| 142 | + | |
| 143 | + u16 intermediate_freq; | |
| 144 | + u16 osc_clock_freq; | |
| 145 | + | |
| 146 | + enum CSCDState cscd_state; | |
| 147 | + enum CDrxdState drxd_state; | |
| 148 | + | |
| 149 | + u16 sys_clock_freq; | |
| 150 | + s16 osc_clock_deviation; | |
| 151 | + u16 expected_sys_clock_freq; | |
| 152 | + | |
| 153 | + u16 insert_rs_byte; | |
| 154 | + u16 enable_parallel; | |
| 155 | + | |
| 156 | + int operation_mode; | |
| 157 | + | |
| 158 | + struct SCfgAgc if_agc_cfg; | |
| 159 | + struct SCfgAgc rf_agc_cfg; | |
| 160 | + | |
| 161 | + struct SNoiseCal noise_cal; | |
| 162 | + | |
| 163 | + u32 fe_fs_add_incr; | |
| 164 | + u32 org_fe_fs_add_incr; | |
| 165 | + u16 current_fe_if_incr; | |
| 166 | + | |
| 167 | + u16 m_FeAgRegAgPwd; | |
| 168 | + u16 m_FeAgRegAgAgcSio; | |
| 169 | + | |
| 170 | + u16 m_EcOcRegOcModeLop; | |
| 171 | + u16 m_EcOcRegSncSncLvl; | |
| 172 | + u8 *m_InitAtomicRead; | |
| 173 | + u8 *m_HiI2cPatch; | |
| 174 | + | |
| 175 | + u8 *m_ResetCEFR; | |
| 176 | + u8 *m_InitFE_1; | |
| 177 | + u8 *m_InitFE_2; | |
| 178 | + u8 *m_InitCP; | |
| 179 | + u8 *m_InitCE; | |
| 180 | + u8 *m_InitEQ; | |
| 181 | + u8 *m_InitSC; | |
| 182 | + u8 *m_InitEC; | |
| 183 | + u8 *m_ResetECRAM; | |
| 184 | + u8 *m_InitDiversityFront; | |
| 185 | + u8 *m_InitDiversityEnd; | |
| 186 | + u8 *m_DisableDiversity; | |
| 187 | + u8 *m_StartDiversityFront; | |
| 188 | + u8 *m_StartDiversityEnd; | |
| 189 | + | |
| 190 | + u8 *m_DiversityDelay8MHZ; | |
| 191 | + u8 *m_DiversityDelay6MHZ; | |
| 192 | + | |
| 193 | + u8 *microcode; | |
| 194 | + u32 microcode_length; | |
| 195 | + | |
| 196 | + int type_A; | |
| 197 | + int PGA; | |
| 198 | + int diversity; | |
| 199 | + int tuner_mirrors; | |
| 200 | + | |
| 201 | + enum app_env app_env_default; | |
| 202 | + enum app_env app_env_diversity; | |
| 203 | + | |
| 204 | +}; | |
| 205 | + | |
| 206 | +/****************************************************************************/ | |
| 207 | +/* I2C **********************************************************************/ | |
| 208 | +/****************************************************************************/ | |
| 209 | + | |
| 210 | +static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 * data, int len) | |
| 211 | +{ | |
| 212 | + struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len }; | |
| 213 | + | |
| 214 | + if (i2c_transfer(adap, &msg, 1) != 1) | |
| 215 | + return -1; | |
| 216 | + return 0; | |
| 217 | +} | |
| 218 | + | |
| 219 | +static int i2c_read(struct i2c_adapter *adap, | |
| 220 | + u8 adr, u8 *msg, int len, u8 *answ, int alen) | |
| 221 | +{ | |
| 222 | + struct i2c_msg msgs[2] = { | |
| 223 | + { | |
| 224 | + .addr = adr, .flags = 0, | |
| 225 | + .buf = msg, .len = len | |
| 226 | + }, { | |
| 227 | + .addr = adr, .flags = I2C_M_RD, | |
| 228 | + .buf = answ, .len = alen | |
| 229 | + } | |
| 230 | + }; | |
| 231 | + if (i2c_transfer(adap, msgs, 2) != 2) | |
| 232 | + return -1; | |
| 233 | + return 0; | |
| 234 | +} | |
| 235 | + | |
| 236 | +inline u32 MulDiv32(u32 a, u32 b, u32 c) | |
| 237 | +{ | |
| 238 | + u64 tmp64; | |
| 239 | + | |
| 240 | + tmp64 = (u64)a * (u64)b; | |
| 241 | + do_div(tmp64, c); | |
| 242 | + | |
| 243 | + return (u32) tmp64; | |
| 244 | +} | |
| 245 | + | |
| 246 | +static int Read16(struct drxd_state *state, u32 reg, u16 *data, u8 flags) | |
| 247 | +{ | |
| 248 | + u8 adr = state->config.demod_address; | |
| 249 | + u8 mm1[4] = { reg & 0xff, (reg >> 16) & 0xff, | |
| 250 | + flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff | |
| 251 | + }; | |
| 252 | + u8 mm2[2]; | |
| 253 | + if (i2c_read(state->i2c, adr, mm1, 4, mm2, 2) < 0) | |
| 254 | + return -1; | |
| 255 | + if (data) | |
| 256 | + *data = mm2[0] | (mm2[1] << 8); | |
| 257 | + return mm2[0] | (mm2[1] << 8); | |
| 258 | +} | |
| 259 | + | |
| 260 | +static int Read32(struct drxd_state *state, u32 reg, u32 *data, u8 flags) | |
| 261 | +{ | |
| 262 | + u8 adr = state->config.demod_address; | |
| 263 | + u8 mm1[4] = { reg & 0xff, (reg >> 16) & 0xff, | |
| 264 | + flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff | |
| 265 | + }; | |
| 266 | + u8 mm2[4]; | |
| 267 | + | |
| 268 | + if (i2c_read(state->i2c, adr, mm1, 4, mm2, 4) < 0) | |
| 269 | + return -1; | |
| 270 | + if (data) | |
| 271 | + *data = | |
| 272 | + mm2[0] | (mm2[1] << 8) | (mm2[2] << 16) | (mm2[3] << 24); | |
| 273 | + return 0; | |
| 274 | +} | |
| 275 | + | |
| 276 | +static int Write16(struct drxd_state *state, u32 reg, u16 data, u8 flags) | |
| 277 | +{ | |
| 278 | + u8 adr = state->config.demod_address; | |
| 279 | + u8 mm[6] = { reg & 0xff, (reg >> 16) & 0xff, | |
| 280 | + flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff, | |
| 281 | + data & 0xff, (data >> 8) & 0xff | |
| 282 | + }; | |
| 283 | + | |
| 284 | + if (i2c_write(state->i2c, adr, mm, 6) < 0) | |
| 285 | + return -1; | |
| 286 | + return 0; | |
| 287 | +} | |
| 288 | + | |
| 289 | +static int Write32(struct drxd_state *state, u32 reg, u32 data, u8 flags) | |
| 290 | +{ | |
| 291 | + u8 adr = state->config.demod_address; | |
| 292 | + u8 mm[8] = { reg & 0xff, (reg >> 16) & 0xff, | |
| 293 | + flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff, | |
| 294 | + data & 0xff, (data >> 8) & 0xff, | |
| 295 | + (data >> 16) & 0xff, (data >> 24) & 0xff | |
| 296 | + }; | |
| 297 | + | |
| 298 | + if (i2c_write(state->i2c, adr, mm, 8) < 0) | |
| 299 | + return -1; | |
| 300 | + return 0; | |
| 301 | +} | |
| 302 | + | |
| 303 | +static int write_chunk(struct drxd_state *state, | |
| 304 | + u32 reg, u8 *data, u32 len, u8 flags) | |
| 305 | +{ | |
| 306 | + u8 adr = state->config.demod_address; | |
| 307 | + u8 mm[CHUNK_SIZE + 4] = { reg & 0xff, (reg >> 16) & 0xff, | |
| 308 | + flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff | |
| 309 | + }; | |
| 310 | + int i; | |
| 311 | + | |
| 312 | + for (i = 0; i < len; i++) | |
| 313 | + mm[4 + i] = data[i]; | |
| 314 | + if (i2c_write(state->i2c, adr, mm, 4 + len) < 0) { | |
| 315 | + printk(KERN_ERR "error in write_chunk\n"); | |
| 316 | + return -1; | |
| 317 | + } | |
| 318 | + return 0; | |
| 319 | +} | |
| 320 | + | |
| 321 | +static int WriteBlock(struct drxd_state *state, | |
| 322 | + u32 Address, u16 BlockSize, u8 *pBlock, u8 Flags) | |
| 323 | +{ | |
| 324 | + while (BlockSize > 0) { | |
| 325 | + u16 Chunk = BlockSize > CHUNK_SIZE ? CHUNK_SIZE : BlockSize; | |
| 326 | + | |
| 327 | + if (write_chunk(state, Address, pBlock, Chunk, Flags) < 0) | |
| 328 | + return -1; | |
| 329 | + pBlock += Chunk; | |
| 330 | + Address += (Chunk >> 1); | |
| 331 | + BlockSize -= Chunk; | |
| 332 | + } | |
| 333 | + return 0; | |
| 334 | +} | |
| 335 | + | |
| 336 | +static int WriteTable(struct drxd_state *state, u8 * pTable) | |
| 337 | +{ | |
| 338 | + int status = 0; | |
| 339 | + | |
| 340 | + if (pTable == NULL) | |
| 341 | + return 0; | |
| 342 | + | |
| 343 | + while (!status) { | |
| 344 | + u16 Length; | |
| 345 | + u32 Address = pTable[0] | (pTable[1] << 8) | | |
| 346 | + (pTable[2] << 16) | (pTable[3] << 24); | |
| 347 | + | |
| 348 | + if (Address == 0xFFFFFFFF) | |
| 349 | + break; | |
| 350 | + pTable += sizeof(u32); | |
| 351 | + | |
| 352 | + Length = pTable[0] | (pTable[1] << 8); | |
| 353 | + pTable += sizeof(u16); | |
| 354 | + if (!Length) | |
| 355 | + break; | |
| 356 | + status = WriteBlock(state, Address, Length * 2, pTable, 0); | |
| 357 | + pTable += (Length * 2); | |
| 358 | + } | |
| 359 | + return status; | |
| 360 | +} | |
| 361 | + | |
| 362 | +/****************************************************************************/ | |
| 363 | +/****************************************************************************/ | |
| 364 | +/****************************************************************************/ | |
| 365 | + | |
| 366 | +static int ResetCEFR(struct drxd_state *state) | |
| 367 | +{ | |
| 368 | + return WriteTable(state, state->m_ResetCEFR); | |
| 369 | +} | |
| 370 | + | |
| 371 | +static int InitCP(struct drxd_state *state) | |
| 372 | +{ | |
| 373 | + return WriteTable(state, state->m_InitCP); | |
| 374 | +} | |
| 375 | + | |
| 376 | +static int InitCE(struct drxd_state *state) | |
| 377 | +{ | |
| 378 | + int status; | |
| 379 | + enum app_env AppEnv = state->app_env_default; | |
| 380 | + | |
| 381 | + do { | |
| 382 | + status = WriteTable(state, state->m_InitCE); | |
| 383 | + if (status < 0) | |
| 384 | + break; | |
| 385 | + | |
| 386 | + if (state->operation_mode == OM_DVBT_Diversity_Front || | |
| 387 | + state->operation_mode == OM_DVBT_Diversity_End) { | |
| 388 | + AppEnv = state->app_env_diversity; | |
| 389 | + } | |
| 390 | + if (AppEnv == APPENV_STATIC) { | |
| 391 | + status = Write16(state, CE_REG_TAPSET__A, 0x0000, 0); | |
| 392 | + if (status < 0) | |
| 393 | + break; | |
| 394 | + } else if (AppEnv == APPENV_PORTABLE) { | |
| 395 | + status = Write16(state, CE_REG_TAPSET__A, 0x0001, 0); | |
| 396 | + if (status < 0) | |
| 397 | + break; | |
| 398 | + } else if (AppEnv == APPENV_MOBILE && state->type_A) { | |
| 399 | + status = Write16(state, CE_REG_TAPSET__A, 0x0002, 0); | |
| 400 | + if (status < 0) | |
| 401 | + break; | |
| 402 | + } else if (AppEnv == APPENV_MOBILE && !state->type_A) { | |
| 403 | + status = Write16(state, CE_REG_TAPSET__A, 0x0006, 0); | |
| 404 | + if (status < 0) | |
| 405 | + break; | |
| 406 | + } | |
| 407 | + | |
| 408 | + /* start ce */ | |
| 409 | + status = Write16(state, B_CE_REG_COMM_EXEC__A, 0x0001, 0); | |
| 410 | + if (status < 0) | |
| 411 | + break; | |
| 412 | + } while (0); | |
| 413 | + return status; | |
| 414 | +} | |
| 415 | + | |
| 416 | +static int StopOC(struct drxd_state *state) | |
| 417 | +{ | |
| 418 | + int status = 0; | |
| 419 | + u16 ocSyncLvl = 0; | |
| 420 | + u16 ocModeLop = state->m_EcOcRegOcModeLop; | |
| 421 | + u16 dtoIncLop = 0; | |
| 422 | + u16 dtoIncHip = 0; | |
| 423 | + | |
| 424 | + do { | |
| 425 | + /* Store output configuration */ | |
| 426 | + status = Read16(state, EC_OC_REG_SNC_ISC_LVL__A, &ocSyncLvl, 0); | |
| 427 | + if (status < 0) | |
| 428 | + break; | |
| 429 | + /* CHK_ERROR(Read16(EC_OC_REG_OC_MODE_LOP__A, &ocModeLop)); */ | |
| 430 | + state->m_EcOcRegSncSncLvl = ocSyncLvl; | |
| 431 | + /* m_EcOcRegOcModeLop = ocModeLop; */ | |
| 432 | + | |
| 433 | + /* Flush FIFO (byte-boundary) at fixed rate */ | |
| 434 | + status = Read16(state, EC_OC_REG_RCN_MAP_LOP__A, &dtoIncLop, 0); | |
| 435 | + if (status < 0) | |
| 436 | + break; | |
| 437 | + status = Read16(state, EC_OC_REG_RCN_MAP_HIP__A, &dtoIncHip, 0); | |
| 438 | + if (status < 0) | |
| 439 | + break; | |
| 440 | + status = Write16(state, EC_OC_REG_DTO_INC_LOP__A, dtoIncLop, 0); | |
| 441 | + if (status < 0) | |
| 442 | + break; | |
| 443 | + status = Write16(state, EC_OC_REG_DTO_INC_HIP__A, dtoIncHip, 0); | |
| 444 | + if (status < 0) | |
| 445 | + break; | |
| 446 | + ocModeLop &= ~(EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M); | |
| 447 | + ocModeLop |= EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC; | |
| 448 | + status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, ocModeLop, 0); | |
| 449 | + if (status < 0) | |
| 450 | + break; | |
| 451 | + status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_HOLD, 0); | |
| 452 | + if (status < 0) | |
| 453 | + break; | |
| 454 | + | |
| 455 | + msleep(1); | |
| 456 | + /* Output pins to '0' */ | |
| 457 | + status = Write16(state, EC_OC_REG_OCR_MPG_UOS__A, EC_OC_REG_OCR_MPG_UOS__M, 0); | |
| 458 | + if (status < 0) | |
| 459 | + break; | |
| 460 | + | |
| 461 | + /* Force the OC out of sync */ | |
| 462 | + ocSyncLvl &= ~(EC_OC_REG_SNC_ISC_LVL_OSC__M); | |
| 463 | + status = Write16(state, EC_OC_REG_SNC_ISC_LVL__A, ocSyncLvl, 0); | |
| 464 | + if (status < 0) | |
| 465 | + break; | |
| 466 | + ocModeLop &= ~(EC_OC_REG_OC_MODE_LOP_PAR_ENA__M); | |
| 467 | + ocModeLop |= EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE; | |
| 468 | + ocModeLop |= 0x2; /* Magically-out-of-sync */ | |
| 469 | + status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, ocModeLop, 0); | |
| 470 | + if (status < 0) | |
| 471 | + break; | |
| 472 | + status = Write16(state, EC_OC_REG_COMM_INT_STA__A, 0x0, 0); | |
| 473 | + if (status < 0) | |
| 474 | + break; | |
| 475 | + status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_ACTIVE, 0); | |
| 476 | + if (status < 0) | |
| 477 | + break; | |
| 478 | + } while (0); | |
| 479 | + | |
| 480 | + return status; | |
| 481 | +} | |
| 482 | + | |
| 483 | +static int StartOC(struct drxd_state *state) | |
| 484 | +{ | |
| 485 | + int status = 0; | |
| 486 | + | |
| 487 | + do { | |
| 488 | + /* Stop OC */ | |
| 489 | + status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_HOLD, 0); | |
| 490 | + if (status < 0) | |
| 491 | + break; | |
| 492 | + | |
| 493 | + /* Restore output configuration */ | |
| 494 | + status = Write16(state, EC_OC_REG_SNC_ISC_LVL__A, state->m_EcOcRegSncSncLvl, 0); | |
| 495 | + if (status < 0) | |
| 496 | + break; | |
| 497 | + status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, state->m_EcOcRegOcModeLop, 0); | |
| 498 | + if (status < 0) | |
| 499 | + break; | |
| 500 | + | |
| 501 | + /* Output pins active again */ | |
| 502 | + status = Write16(state, EC_OC_REG_OCR_MPG_UOS__A, EC_OC_REG_OCR_MPG_UOS_INIT, 0); | |
| 503 | + if (status < 0) | |
| 504 | + break; | |
| 505 | + | |
| 506 | + /* Start OC */ | |
| 507 | + status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_ACTIVE, 0); | |
| 508 | + if (status < 0) | |
| 509 | + break; | |
| 510 | + } while (0); | |
| 511 | + return status; | |
| 512 | +} | |
| 513 | + | |
| 514 | +static int InitEQ(struct drxd_state *state) | |
| 515 | +{ | |
| 516 | + return WriteTable(state, state->m_InitEQ); | |
| 517 | +} | |
| 518 | + | |
| 519 | +static int InitEC(struct drxd_state *state) | |
| 520 | +{ | |
| 521 | + return WriteTable(state, state->m_InitEC); | |
| 522 | +} | |
| 523 | + | |
| 524 | +static int InitSC(struct drxd_state *state) | |
| 525 | +{ | |
| 526 | + return WriteTable(state, state->m_InitSC); | |
| 527 | +} | |
| 528 | + | |
| 529 | +static int InitAtomicRead(struct drxd_state *state) | |
| 530 | +{ | |
| 531 | + return WriteTable(state, state->m_InitAtomicRead); | |
| 532 | +} | |
| 533 | + | |
| 534 | +static int CorrectSysClockDeviation(struct drxd_state *state); | |
| 535 | + | |
| 536 | +static int DRX_GetLockStatus(struct drxd_state *state, u32 * pLockStatus) | |
| 537 | +{ | |
| 538 | + u16 ScRaRamLock = 0; | |
| 539 | + const u16 mpeg_lock_mask = (SC_RA_RAM_LOCK_MPEG__M | | |
| 540 | + SC_RA_RAM_LOCK_FEC__M | | |
| 541 | + SC_RA_RAM_LOCK_DEMOD__M); | |
| 542 | + const u16 fec_lock_mask = (SC_RA_RAM_LOCK_FEC__M | | |
| 543 | + SC_RA_RAM_LOCK_DEMOD__M); | |
| 544 | + const u16 demod_lock_mask = SC_RA_RAM_LOCK_DEMOD__M; | |
| 545 | + | |
| 546 | + int status; | |
| 547 | + | |
| 548 | + *pLockStatus = 0; | |
| 549 | + | |
| 550 | + status = Read16(state, SC_RA_RAM_LOCK__A, &ScRaRamLock, 0x0000); | |
| 551 | + if (status < 0) { | |
| 552 | + printk(KERN_ERR "Can't read SC_RA_RAM_LOCK__A status = %08x\n", status); | |
| 553 | + return status; | |
| 554 | + } | |
| 555 | + | |
| 556 | + if (state->drxd_state != DRXD_STARTED) | |
| 557 | + return 0; | |
| 558 | + | |
| 559 | + if ((ScRaRamLock & mpeg_lock_mask) == mpeg_lock_mask) { | |
| 560 | + *pLockStatus |= DRX_LOCK_MPEG; | |
| 561 | + CorrectSysClockDeviation(state); | |
| 562 | + } | |
| 563 | + | |
| 564 | + if ((ScRaRamLock & fec_lock_mask) == fec_lock_mask) | |
| 565 | + *pLockStatus |= DRX_LOCK_FEC; | |
| 566 | + | |
| 567 | + if ((ScRaRamLock & demod_lock_mask) == demod_lock_mask) | |
| 568 | + *pLockStatus |= DRX_LOCK_DEMOD; | |
| 569 | + return 0; | |
| 570 | +} | |
| 571 | + | |
| 572 | +/****************************************************************************/ | |
| 573 | + | |
| 574 | +static int SetCfgIfAgc(struct drxd_state *state, struct SCfgAgc *cfg) | |
| 575 | +{ | |
| 576 | + int status; | |
| 577 | + | |
| 578 | + if (cfg->outputLevel > DRXD_FE_CTRL_MAX) | |
| 579 | + return -1; | |
| 580 | + | |
| 581 | + if (cfg->ctrlMode == AGC_CTRL_USER) { | |
| 582 | + do { | |
| 583 | + u16 FeAgRegPm1AgcWri; | |
| 584 | + u16 FeAgRegAgModeLop; | |
| 585 | + | |
| 586 | + status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &FeAgRegAgModeLop, 0); | |
| 587 | + if (status < 0) | |
| 588 | + break; | |
| 589 | + FeAgRegAgModeLop &= (~FE_AG_REG_AG_MODE_LOP_MODE_4__M); | |
| 590 | + FeAgRegAgModeLop |= FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC; | |
| 591 | + status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, FeAgRegAgModeLop, 0); | |
| 592 | + if (status < 0) | |
| 593 | + break; | |
| 594 | + | |
| 595 | + FeAgRegPm1AgcWri = (u16) (cfg->outputLevel & | |
| 596 | + FE_AG_REG_PM1_AGC_WRI__M); | |
| 597 | + status = Write16(state, FE_AG_REG_PM1_AGC_WRI__A, FeAgRegPm1AgcWri, 0); | |
| 598 | + if (status < 0) | |
| 599 | + break; | |
| 600 | + } while (0); | |
| 601 | + } else if (cfg->ctrlMode == AGC_CTRL_AUTO) { | |
| 602 | + if (((cfg->maxOutputLevel) < (cfg->minOutputLevel)) || | |
| 603 | + ((cfg->maxOutputLevel) > DRXD_FE_CTRL_MAX) || | |
| 604 | + ((cfg->speed) > DRXD_FE_CTRL_MAX) || | |
| 605 | + ((cfg->settleLevel) > DRXD_FE_CTRL_MAX) | |
| 606 | + ) | |
| 607 | + return -1; | |
| 608 | + do { | |
| 609 | + u16 FeAgRegAgModeLop; | |
| 610 | + u16 FeAgRegEgcSetLvl; | |
| 611 | + u16 slope, offset; | |
| 612 | + | |
| 613 | + /* == Mode == */ | |
| 614 | + | |
| 615 | + status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &FeAgRegAgModeLop, 0); | |
| 616 | + if (status < 0) | |
| 617 | + break; | |
| 618 | + FeAgRegAgModeLop &= (~FE_AG_REG_AG_MODE_LOP_MODE_4__M); | |
| 619 | + FeAgRegAgModeLop |= | |
| 620 | + FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC; | |
| 621 | + status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, FeAgRegAgModeLop, 0); | |
| 622 | + if (status < 0) | |
| 623 | + break; | |
| 624 | + | |
| 625 | + /* == Settle level == */ | |
| 626 | + | |
| 627 | + FeAgRegEgcSetLvl = (u16) ((cfg->settleLevel >> 1) & | |
| 628 | + FE_AG_REG_EGC_SET_LVL__M); | |
| 629 | + status = Write16(state, FE_AG_REG_EGC_SET_LVL__A, FeAgRegEgcSetLvl, 0); | |
| 630 | + if (status < 0) | |
| 631 | + break; | |
| 632 | + | |
| 633 | + /* == Min/Max == */ | |
| 634 | + | |
| 635 | + slope = (u16) ((cfg->maxOutputLevel - | |
| 636 | + cfg->minOutputLevel) / 2); | |
| 637 | + offset = (u16) ((cfg->maxOutputLevel + | |
| 638 | + cfg->minOutputLevel) / 2 - 511); | |
| 639 | + | |
| 640 | + status = Write16(state, FE_AG_REG_GC1_AGC_RIC__A, slope, 0); | |
| 641 | + if (status < 0) | |
| 642 | + break; | |
| 643 | + status = Write16(state, FE_AG_REG_GC1_AGC_OFF__A, offset, 0); | |
| 644 | + if (status < 0) | |
| 645 | + break; | |
| 646 | + | |
| 647 | + /* == Speed == */ | |
| 648 | + { | |
| 649 | + const u16 maxRur = 8; | |
| 650 | + const u16 slowIncrDecLUT[] = { 3, 4, 4, 5, 6 }; | |
| 651 | + const u16 fastIncrDecLUT[] = { 14, 15, 15, 16, | |
| 652 | + 17, 18, 18, 19, | |
| 653 | + 20, 21, 22, 23, | |
| 654 | + 24, 26, 27, 28, | |
| 655 | + 29, 31 | |
| 656 | + }; | |
| 657 | + | |
| 658 | + u16 fineSteps = (DRXD_FE_CTRL_MAX + 1) / | |
| 659 | + (maxRur + 1); | |
| 660 | + u16 fineSpeed = (u16) (cfg->speed - | |
| 661 | + ((cfg->speed / | |
| 662 | + fineSteps) * | |
| 663 | + fineSteps)); | |
| 664 | + u16 invRurCount = (u16) (cfg->speed / | |
| 665 | + fineSteps); | |
| 666 | + u16 rurCount; | |
| 667 | + if (invRurCount > maxRur) { | |
| 668 | + rurCount = 0; | |
| 669 | + fineSpeed += fineSteps; | |
| 670 | + } else { | |
| 671 | + rurCount = maxRur - invRurCount; | |
| 672 | + } | |
| 673 | + | |
| 674 | + /* | |
| 675 | + fastInc = default * | |
| 676 | + (2^(fineSpeed/fineSteps)) | |
| 677 | + => range[default...2*default> | |
| 678 | + slowInc = default * | |
| 679 | + (2^(fineSpeed/fineSteps)) | |
| 680 | + */ | |
| 681 | + { | |
| 682 | + u16 fastIncrDec = | |
| 683 | + fastIncrDecLUT[fineSpeed / | |
| 684 | + ((fineSteps / | |
| 685 | + (14 + 1)) + 1)]; | |
| 686 | + u16 slowIncrDec = | |
| 687 | + slowIncrDecLUT[fineSpeed / | |
| 688 | + (fineSteps / | |
| 689 | + (3 + 1))]; | |
| 690 | + | |
| 691 | + status = Write16(state, FE_AG_REG_EGC_RUR_CNT__A, rurCount, 0); | |
| 692 | + if (status < 0) | |
| 693 | + break; | |
| 694 | + status = Write16(state, FE_AG_REG_EGC_FAS_INC__A, fastIncrDec, 0); | |
| 695 | + if (status < 0) | |
| 696 | + break; | |
| 697 | + status = Write16(state, FE_AG_REG_EGC_FAS_DEC__A, fastIncrDec, 0); | |
| 698 | + if (status < 0) | |
| 699 | + break; | |
| 700 | + status = Write16(state, FE_AG_REG_EGC_SLO_INC__A, slowIncrDec, 0); | |
| 701 | + if (status < 0) | |
| 702 | + break; | |
| 703 | + status = Write16(state, FE_AG_REG_EGC_SLO_DEC__A, slowIncrDec, 0); | |
| 704 | + if (status < 0) | |
| 705 | + break; | |
| 706 | + } | |
| 707 | + } | |
| 708 | + } while (0); | |
| 709 | + | |
| 710 | + } else { | |
| 711 | + /* No OFF mode for IF control */ | |
| 712 | + return -1; | |
| 713 | + } | |
| 714 | + return status; | |
| 715 | +} | |
| 716 | + | |
| 717 | +static int SetCfgRfAgc(struct drxd_state *state, struct SCfgAgc *cfg) | |
| 718 | +{ | |
| 719 | + int status = 0; | |
| 720 | + | |
| 721 | + if (cfg->outputLevel > DRXD_FE_CTRL_MAX) | |
| 722 | + return -1; | |
| 723 | + | |
| 724 | + if (cfg->ctrlMode == AGC_CTRL_USER) { | |
| 725 | + do { | |
| 726 | + u16 AgModeLop = 0; | |
| 727 | + u16 level = (cfg->outputLevel); | |
| 728 | + | |
| 729 | + if (level == DRXD_FE_CTRL_MAX) | |
| 730 | + level++; | |
| 731 | + | |
| 732 | + status = Write16(state, FE_AG_REG_PM2_AGC_WRI__A, level, 0x0000); | |
| 733 | + if (status < 0) | |
| 734 | + break; | |
| 735 | + | |
| 736 | + /*==== Mode ====*/ | |
| 737 | + | |
| 738 | + /* Powerdown PD2, WRI source */ | |
| 739 | + state->m_FeAgRegAgPwd &= ~(FE_AG_REG_AG_PWD_PWD_PD2__M); | |
| 740 | + state->m_FeAgRegAgPwd |= | |
| 741 | + FE_AG_REG_AG_PWD_PWD_PD2_DISABLE; | |
| 742 | + status = Write16(state, FE_AG_REG_AG_PWD__A, state->m_FeAgRegAgPwd, 0x0000); | |
| 743 | + if (status < 0) | |
| 744 | + break; | |
| 745 | + | |
| 746 | + status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); | |
| 747 | + if (status < 0) | |
| 748 | + break; | |
| 749 | + AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M | | |
| 750 | + FE_AG_REG_AG_MODE_LOP_MODE_E__M)); | |
| 751 | + AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC | | |
| 752 | + FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC); | |
| 753 | + status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); | |
| 754 | + if (status < 0) | |
| 755 | + break; | |
| 756 | + | |
| 757 | + /* enable AGC2 pin */ | |
| 758 | + { | |
| 759 | + u16 FeAgRegAgAgcSio = 0; | |
| 760 | + status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000); | |
| 761 | + if (status < 0) | |
| 762 | + break; | |
| 763 | + FeAgRegAgAgcSio &= | |
| 764 | + ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M); | |
| 765 | + FeAgRegAgAgcSio |= | |
| 766 | + FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT; | |
| 767 | + status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000); | |
| 768 | + if (status < 0) | |
| 769 | + break; | |
| 770 | + } | |
| 771 | + | |
| 772 | + } while (0); | |
| 773 | + } else if (cfg->ctrlMode == AGC_CTRL_AUTO) { | |
| 774 | + u16 AgModeLop = 0; | |
| 775 | + | |
| 776 | + do { | |
| 777 | + u16 level; | |
| 778 | + /* Automatic control */ | |
| 779 | + /* Powerup PD2, AGC2 as output, TGC source */ | |
| 780 | + (state->m_FeAgRegAgPwd) &= | |
| 781 | + ~(FE_AG_REG_AG_PWD_PWD_PD2__M); | |
| 782 | + (state->m_FeAgRegAgPwd) |= | |
| 783 | + FE_AG_REG_AG_PWD_PWD_PD2_DISABLE; | |
| 784 | + status = Write16(state, FE_AG_REG_AG_PWD__A, (state->m_FeAgRegAgPwd), 0x0000); | |
| 785 | + if (status < 0) | |
| 786 | + break; | |
| 787 | + | |
| 788 | + status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); | |
| 789 | + if (status < 0) | |
| 790 | + break; | |
| 791 | + AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M | | |
| 792 | + FE_AG_REG_AG_MODE_LOP_MODE_E__M)); | |
| 793 | + AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC | | |
| 794 | + FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC); | |
| 795 | + status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); | |
| 796 | + if (status < 0) | |
| 797 | + break; | |
| 798 | + /* Settle level */ | |
| 799 | + level = (((cfg->settleLevel) >> 4) & | |
| 800 | + FE_AG_REG_TGC_SET_LVL__M); | |
| 801 | + status = Write16(state, FE_AG_REG_TGC_SET_LVL__A, level, 0x0000); | |
| 802 | + if (status < 0) | |
| 803 | + break; | |
| 804 | + | |
| 805 | + /* Min/max: don't care */ | |
| 806 | + | |
| 807 | + /* Speed: TODO */ | |
| 808 | + | |
| 809 | + /* enable AGC2 pin */ | |
| 810 | + { | |
| 811 | + u16 FeAgRegAgAgcSio = 0; | |
| 812 | + status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000); | |
| 813 | + if (status < 0) | |
| 814 | + break; | |
| 815 | + FeAgRegAgAgcSio &= | |
| 816 | + ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M); | |
| 817 | + FeAgRegAgAgcSio |= | |
| 818 | + FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT; | |
| 819 | + status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000); | |
| 820 | + if (status < 0) | |
| 821 | + break; | |
| 822 | + } | |
| 823 | + | |
| 824 | + } while (0); | |
| 825 | + } else { | |
| 826 | + u16 AgModeLop = 0; | |
| 827 | + | |
| 828 | + do { | |
| 829 | + /* No RF AGC control */ | |
| 830 | + /* Powerdown PD2, AGC2 as output, WRI source */ | |
| 831 | + (state->m_FeAgRegAgPwd) &= | |
| 832 | + ~(FE_AG_REG_AG_PWD_PWD_PD2__M); | |
| 833 | + (state->m_FeAgRegAgPwd) |= | |
| 834 | + FE_AG_REG_AG_PWD_PWD_PD2_ENABLE; | |
| 835 | + status = Write16(state, FE_AG_REG_AG_PWD__A, (state->m_FeAgRegAgPwd), 0x0000); | |
| 836 | + if (status < 0) | |
| 837 | + break; | |
| 838 | + | |
| 839 | + status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); | |
| 840 | + if (status < 0) | |
| 841 | + break; | |
| 842 | + AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M | | |
| 843 | + FE_AG_REG_AG_MODE_LOP_MODE_E__M)); | |
| 844 | + AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC | | |
| 845 | + FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC); | |
| 846 | + status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); | |
| 847 | + if (status < 0) | |
| 848 | + break; | |
| 849 | + | |
| 850 | + /* set FeAgRegAgAgcSio AGC2 (RF) as input */ | |
| 851 | + { | |
| 852 | + u16 FeAgRegAgAgcSio = 0; | |
| 853 | + status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000); | |
| 854 | + if (status < 0) | |
| 855 | + break; | |
| 856 | + FeAgRegAgAgcSio &= | |
| 857 | + ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M); | |
| 858 | + FeAgRegAgAgcSio |= | |
| 859 | + FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT; | |
| 860 | + status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000); | |
| 861 | + if (status < 0) | |
| 862 | + break; | |
| 863 | + } | |
| 864 | + } while (0); | |
| 865 | + } | |
| 866 | + return status; | |
| 867 | +} | |
| 868 | + | |
| 869 | +static int ReadIFAgc(struct drxd_state *state, u32 * pValue) | |
| 870 | +{ | |
| 871 | + int status = 0; | |
| 872 | + | |
| 873 | + *pValue = 0; | |
| 874 | + if (state->if_agc_cfg.ctrlMode != AGC_CTRL_OFF) { | |
| 875 | + u16 Value; | |
| 876 | + status = Read16(state, FE_AG_REG_GC1_AGC_DAT__A, &Value, 0); | |
| 877 | + Value &= FE_AG_REG_GC1_AGC_DAT__M; | |
| 878 | + if (status >= 0) { | |
| 879 | + /* 3.3V | |
| 880 | + | | |
| 881 | + R1 | |
| 882 | + | | |
| 883 | + Vin - R3 - * -- Vout | |
| 884 | + | | |
| 885 | + R2 | |
| 886 | + | | |
| 887 | + GND | |
| 888 | + */ | |
| 889 | + u32 R1 = state->if_agc_cfg.R1; | |
| 890 | + u32 R2 = state->if_agc_cfg.R2; | |
| 891 | + u32 R3 = state->if_agc_cfg.R3; | |
| 892 | + | |
| 893 | + u32 Vmax = (3300 * R2) / (R1 + R2); | |
| 894 | + u32 Rpar = (R2 * R3) / (R3 + R2); | |
| 895 | + u32 Vmin = (3300 * Rpar) / (R1 + Rpar); | |
| 896 | + u32 Vout = Vmin + ((Vmax - Vmin) * Value) / 1024; | |
| 897 | + | |
| 898 | + *pValue = Vout; | |
| 899 | + } | |
| 900 | + } | |
| 901 | + return status; | |
| 902 | +} | |
| 903 | + | |
| 904 | +static int load_firmware(struct drxd_state *state, const char *fw_name) | |
| 905 | +{ | |
| 906 | + const struct firmware *fw; | |
| 907 | + | |
| 908 | + if (request_firmware(&fw, fw_name, state->dev) < 0) { | |
| 909 | + printk(KERN_ERR "drxd: firmware load failure [%s]\n", fw_name); | |
| 910 | + return -EIO; | |
| 911 | + } | |
| 912 | + | |
| 913 | + state->microcode = kzalloc(fw->size, GFP_KERNEL); | |
| 914 | + if (state->microcode == NULL) { | |
| 915 | + printk(KERN_ERR "drxd: firmware load failure: nomemory\n"); | |
| 916 | + return -ENOMEM; | |
| 917 | + } | |
| 918 | + | |
| 919 | + memcpy(state->microcode, fw->data, fw->size); | |
| 920 | + state->microcode_length = fw->size; | |
| 921 | + return 0; | |
| 922 | +} | |
| 923 | + | |
| 924 | +static int DownloadMicrocode(struct drxd_state *state, | |
| 925 | + const u8 *pMCImage, u32 Length) | |
| 926 | +{ | |
| 927 | + u8 *pSrc; | |
| 928 | + u16 Flags; | |
| 929 | + u32 Address; | |
| 930 | + u16 nBlocks; | |
| 931 | + u16 BlockSize; | |
| 932 | + u16 BlockCRC; | |
| 933 | + u32 offset = 0; | |
| 934 | + int i, status = 0; | |
| 935 | + | |
| 936 | + pSrc = (u8 *) pMCImage; | |
| 937 | + Flags = (pSrc[0] << 8) | pSrc[1]; | |
| 938 | + pSrc += sizeof(u16); | |
| 939 | + offset += sizeof(u16); | |
| 940 | + nBlocks = (pSrc[0] << 8) | pSrc[1]; | |
| 941 | + pSrc += sizeof(u16); | |
| 942 | + offset += sizeof(u16); | |
| 943 | + | |
| 944 | + for (i = 0; i < nBlocks; i++) { | |
| 945 | + Address = (pSrc[0] << 24) | (pSrc[1] << 16) | | |
| 946 | + (pSrc[2] << 8) | pSrc[3]; | |
| 947 | + pSrc += sizeof(u32); | |
| 948 | + offset += sizeof(u32); | |
| 949 | + | |
| 950 | + BlockSize = ((pSrc[0] << 8) | pSrc[1]) * sizeof(u16); | |
| 951 | + pSrc += sizeof(u16); | |
| 952 | + offset += sizeof(u16); | |
| 953 | + | |
| 954 | + Flags = (pSrc[0] << 8) | pSrc[1]; | |
| 955 | + pSrc += sizeof(u16); | |
| 956 | + offset += sizeof(u16); | |
| 957 | + | |
| 958 | + BlockCRC = (pSrc[0] << 8) | pSrc[1]; | |
| 959 | + pSrc += sizeof(u16); | |
| 960 | + offset += sizeof(u16); | |
| 961 | + | |
| 962 | + status = WriteBlock(state, Address, BlockSize, | |
| 963 | + pSrc, DRX_I2C_CLEARCRC); | |
| 964 | + if (status < 0) | |
| 965 | + break; | |
| 966 | + pSrc += BlockSize; | |
| 967 | + offset += BlockSize; | |
| 968 | + } | |
| 969 | + | |
| 970 | + return status; | |
| 971 | +} | |
| 972 | + | |
| 973 | +static int HI_Command(struct drxd_state *state, u16 cmd, u16 * pResult) | |
| 974 | +{ | |
| 975 | + u32 nrRetries = 0; | |
| 976 | + u16 waitCmd; | |
| 977 | + int status; | |
| 978 | + | |
| 979 | + status = Write16(state, HI_RA_RAM_SRV_CMD__A, cmd, 0); | |
| 980 | + if (status < 0) | |
| 981 | + return status; | |
| 982 | + | |
| 983 | + do { | |
| 984 | + nrRetries += 1; | |
| 985 | + if (nrRetries > DRXD_MAX_RETRIES) { | |
| 986 | + status = -1; | |
| 987 | + break; | |
| 988 | + }; | |
| 989 | + status = Read16(state, HI_RA_RAM_SRV_CMD__A, &waitCmd, 0); | |
| 990 | + } while (waitCmd != 0); | |
| 991 | + | |
| 992 | + if (status >= 0) | |
| 993 | + status = Read16(state, HI_RA_RAM_SRV_RES__A, pResult, 0); | |
| 994 | + return status; | |
| 995 | +} | |
| 996 | + | |
| 997 | +static int HI_CfgCommand(struct drxd_state *state) | |
| 998 | +{ | |
| 999 | + int status = 0; | |
| 1000 | + | |
| 1001 | + mutex_lock(&state->mutex); | |
| 1002 | + Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, HI_RA_RAM_SRV_RST_KEY_ACT, 0); | |
| 1003 | + Write16(state, HI_RA_RAM_SRV_CFG_DIV__A, state->hi_cfg_timing_div, 0); | |
| 1004 | + Write16(state, HI_RA_RAM_SRV_CFG_BDL__A, state->hi_cfg_bridge_delay, 0); | |
| 1005 | + Write16(state, HI_RA_RAM_SRV_CFG_WUP__A, state->hi_cfg_wakeup_key, 0); | |
| 1006 | + Write16(state, HI_RA_RAM_SRV_CFG_ACT__A, state->hi_cfg_ctrl, 0); | |
| 1007 | + | |
| 1008 | + Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, HI_RA_RAM_SRV_RST_KEY_ACT, 0); | |
| 1009 | + | |
| 1010 | + if ((state->hi_cfg_ctrl & HI_RA_RAM_SRV_CFG_ACT_PWD_EXE) == | |
| 1011 | + HI_RA_RAM_SRV_CFG_ACT_PWD_EXE) | |
| 1012 | + status = Write16(state, HI_RA_RAM_SRV_CMD__A, | |
| 1013 | + HI_RA_RAM_SRV_CMD_CONFIG, 0); | |
| 1014 | + else | |
| 1015 | + status = HI_Command(state, HI_RA_RAM_SRV_CMD_CONFIG, 0); | |
| 1016 | + mutex_unlock(&state->mutex); | |
| 1017 | + return status; | |
| 1018 | +} | |
| 1019 | + | |
| 1020 | +static int InitHI(struct drxd_state *state) | |
| 1021 | +{ | |
| 1022 | + state->hi_cfg_wakeup_key = (state->chip_adr); | |
| 1023 | + /* port/bridge/power down ctrl */ | |
| 1024 | + state->hi_cfg_ctrl = HI_RA_RAM_SRV_CFG_ACT_SLV0_ON; | |
| 1025 | + return HI_CfgCommand(state); | |
| 1026 | +} | |
| 1027 | + | |
| 1028 | +static int HI_ResetCommand(struct drxd_state *state) | |
| 1029 | +{ | |
| 1030 | + int status; | |
| 1031 | + | |
| 1032 | + mutex_lock(&state->mutex); | |
| 1033 | + status = Write16(state, HI_RA_RAM_SRV_RST_KEY__A, | |
| 1034 | + HI_RA_RAM_SRV_RST_KEY_ACT, 0); | |
| 1035 | + if (status == 0) | |
| 1036 | + status = HI_Command(state, HI_RA_RAM_SRV_CMD_RESET, 0); | |
| 1037 | + mutex_unlock(&state->mutex); | |
| 1038 | + msleep(1); | |
| 1039 | + return status; | |
| 1040 | +} | |
| 1041 | + | |
| 1042 | +static int DRX_ConfigureI2CBridge(struct drxd_state *state, int bEnableBridge) | |
| 1043 | +{ | |
| 1044 | + state->hi_cfg_ctrl &= (~HI_RA_RAM_SRV_CFG_ACT_BRD__M); | |
| 1045 | + if (bEnableBridge) | |
| 1046 | + state->hi_cfg_ctrl |= HI_RA_RAM_SRV_CFG_ACT_BRD_ON; | |
| 1047 | + else | |
| 1048 | + state->hi_cfg_ctrl |= HI_RA_RAM_SRV_CFG_ACT_BRD_OFF; | |
| 1049 | + | |
| 1050 | + return HI_CfgCommand(state); | |
| 1051 | +} | |
| 1052 | + | |
| 1053 | +#define HI_TR_WRITE 0x9 | |
| 1054 | +#define HI_TR_READ 0xA | |
| 1055 | +#define HI_TR_READ_WRITE 0xB | |
| 1056 | +#define HI_TR_BROADCAST 0x4 | |
| 1057 | + | |
| 1058 | +#if 0 | |
| 1059 | +static int AtomicReadBlock(struct drxd_state *state, | |
| 1060 | + u32 Addr, u16 DataSize, u8 *pData, u8 Flags) | |
| 1061 | +{ | |
| 1062 | + int status; | |
| 1063 | + int i = 0; | |
| 1064 | + | |
| 1065 | + /* Parameter check */ | |
| 1066 | + if ((!pData) || ((DataSize & 1) != 0)) | |
| 1067 | + return -1; | |
| 1068 | + | |
| 1069 | + mutex_lock(&state->mutex); | |
| 1070 | + | |
| 1071 | + do { | |
| 1072 | + /* Instruct HI to read n bytes */ | |
| 1073 | + /* TODO use proper names forthese egisters */ | |
| 1074 | + status = Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, (HI_TR_FUNC_ADDR & 0xFFFF), 0); | |
| 1075 | + if (status < 0) | |
| 1076 | + break; | |
| 1077 | + status = Write16(state, HI_RA_RAM_SRV_CFG_DIV__A, (u16) (Addr >> 16), 0); | |
| 1078 | + if (status < 0) | |
| 1079 | + break; | |
| 1080 | + status = Write16(state, HI_RA_RAM_SRV_CFG_BDL__A, (u16) (Addr & 0xFFFF), 0); | |
| 1081 | + if (status < 0) | |
| 1082 | + break; | |
| 1083 | + status = Write16(state, HI_RA_RAM_SRV_CFG_WUP__A, (u16) ((DataSize / 2) - 1), 0); | |
| 1084 | + if (status < 0) | |
| 1085 | + break; | |
| 1086 | + status = Write16(state, HI_RA_RAM_SRV_CFG_ACT__A, HI_TR_READ, 0); | |
| 1087 | + if (status < 0) | |
| 1088 | + break; | |
| 1089 | + | |
| 1090 | + status = HI_Command(state, HI_RA_RAM_SRV_CMD_EXECUTE, 0); | |
| 1091 | + if (status < 0) | |
| 1092 | + break; | |
| 1093 | + | |
| 1094 | + } while (0); | |
| 1095 | + | |
| 1096 | + if (status >= 0) { | |
| 1097 | + for (i = 0; i < (DataSize / 2); i += 1) { | |
| 1098 | + u16 word; | |
| 1099 | + | |
| 1100 | + status = Read16(state, (HI_RA_RAM_USR_BEGIN__A + i), | |
| 1101 | + &word, 0); | |
| 1102 | + if (status < 0) | |
| 1103 | + break; | |
| 1104 | + pData[2 * i] = (u8) (word & 0xFF); | |
| 1105 | + pData[(2 * i) + 1] = (u8) (word >> 8); | |
| 1106 | + } | |
| 1107 | + } | |
| 1108 | + mutex_unlock(&state->mutex); | |
| 1109 | + return status; | |
| 1110 | +} | |
| 1111 | + | |
| 1112 | +static int AtomicReadReg32(struct drxd_state *state, | |
| 1113 | + u32 Addr, u32 *pData, u8 Flags) | |
| 1114 | +{ | |
| 1115 | + u8 buf[sizeof(u32)]; | |
| 1116 | + int status; | |
| 1117 | + | |
| 1118 | + if (!pData) | |
| 1119 | + return -1; | |
| 1120 | + status = AtomicReadBlock(state, Addr, sizeof(u32), buf, Flags); | |
| 1121 | + *pData = (((u32) buf[0]) << 0) + | |
| 1122 | + (((u32) buf[1]) << 8) + | |
| 1123 | + (((u32) buf[2]) << 16) + (((u32) buf[3]) << 24); | |
| 1124 | + return status; | |
| 1125 | +} | |
| 1126 | +#endif | |
| 1127 | + | |
| 1128 | +static int StopAllProcessors(struct drxd_state *state) | |
| 1129 | +{ | |
| 1130 | + return Write16(state, HI_COMM_EXEC__A, | |
| 1131 | + SC_COMM_EXEC_CTL_STOP, DRX_I2C_BROADCAST); | |
| 1132 | +} | |
| 1133 | + | |
| 1134 | +static int EnableAndResetMB(struct drxd_state *state) | |
| 1135 | +{ | |
| 1136 | + if (state->type_A) { | |
| 1137 | + /* disable? monitor bus observe @ EC_OC */ | |
| 1138 | + Write16(state, EC_OC_REG_OC_MON_SIO__A, 0x0000, 0x0000); | |
| 1139 | + } | |
| 1140 | + | |
| 1141 | + /* do inverse broadcast, followed by explicit write to HI */ | |
| 1142 | + Write16(state, HI_COMM_MB__A, 0x0000, DRX_I2C_BROADCAST); | |
| 1143 | + Write16(state, HI_COMM_MB__A, 0x0000, 0x0000); | |
| 1144 | + return 0; | |
| 1145 | +} | |
| 1146 | + | |
| 1147 | +static int InitCC(struct drxd_state *state) | |
| 1148 | +{ | |
| 1149 | + if (state->osc_clock_freq == 0 || | |
| 1150 | + state->osc_clock_freq > 20000 || | |
| 1151 | + (state->osc_clock_freq % 4000) != 0) { | |
| 1152 | + printk(KERN_ERR "invalid osc frequency %d\n", state->osc_clock_freq); | |
| 1153 | + return -1; | |
| 1154 | + } | |
| 1155 | + | |
| 1156 | + Write16(state, CC_REG_OSC_MODE__A, CC_REG_OSC_MODE_M20, 0); | |
| 1157 | + Write16(state, CC_REG_PLL_MODE__A, CC_REG_PLL_MODE_BYPASS_PLL | | |
| 1158 | + CC_REG_PLL_MODE_PUMP_CUR_12, 0); | |
| 1159 | + Write16(state, CC_REG_REF_DIVIDE__A, state->osc_clock_freq / 4000, 0); | |
| 1160 | + Write16(state, CC_REG_PWD_MODE__A, CC_REG_PWD_MODE_DOWN_PLL, 0); | |
| 1161 | + Write16(state, CC_REG_UPDATE__A, CC_REG_UPDATE_KEY, 0); | |
| 1162 | + | |
| 1163 | + return 0; | |
| 1164 | +} | |
| 1165 | + | |
| 1166 | +static int ResetECOD(struct drxd_state *state) | |
| 1167 | +{ | |
| 1168 | + int status = 0; | |
| 1169 | + | |
| 1170 | + if (state->type_A) | |
| 1171 | + status = Write16(state, EC_OD_REG_SYNC__A, 0x0664, 0); | |
| 1172 | + else | |
| 1173 | + status = Write16(state, B_EC_OD_REG_SYNC__A, 0x0664, 0); | |
| 1174 | + | |
| 1175 | + if (!(status < 0)) | |
| 1176 | + status = WriteTable(state, state->m_ResetECRAM); | |
| 1177 | + if (!(status < 0)) | |
| 1178 | + status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0001, 0); | |
| 1179 | + return status; | |
| 1180 | +} | |
| 1181 | + | |
| 1182 | +/* Configure PGA switch */ | |
| 1183 | + | |
| 1184 | +static int SetCfgPga(struct drxd_state *state, int pgaSwitch) | |
| 1185 | +{ | |
| 1186 | + int status; | |
| 1187 | + u16 AgModeLop = 0; | |
| 1188 | + u16 AgModeHip = 0; | |
| 1189 | + do { | |
| 1190 | + if (pgaSwitch) { | |
| 1191 | + /* PGA on */ | |
| 1192 | + /* fine gain */ | |
| 1193 | + status = Read16(state, B_FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); | |
| 1194 | + if (status < 0) | |
| 1195 | + break; | |
| 1196 | + AgModeLop &= (~(B_FE_AG_REG_AG_MODE_LOP_MODE_C__M)); | |
| 1197 | + AgModeLop |= B_FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC; | |
| 1198 | + status = Write16(state, B_FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); | |
| 1199 | + if (status < 0) | |
| 1200 | + break; | |
| 1201 | + | |
| 1202 | + /* coarse gain */ | |
| 1203 | + status = Read16(state, B_FE_AG_REG_AG_MODE_HIP__A, &AgModeHip, 0x0000); | |
| 1204 | + if (status < 0) | |
| 1205 | + break; | |
| 1206 | + AgModeHip &= (~(B_FE_AG_REG_AG_MODE_HIP_MODE_J__M)); | |
| 1207 | + AgModeHip |= B_FE_AG_REG_AG_MODE_HIP_MODE_J_DYNAMIC; | |
| 1208 | + status = Write16(state, B_FE_AG_REG_AG_MODE_HIP__A, AgModeHip, 0x0000); | |
| 1209 | + if (status < 0) | |
| 1210 | + break; | |
| 1211 | + | |
| 1212 | + /* enable fine and coarse gain, enable AAF, | |
| 1213 | + no ext resistor */ | |
| 1214 | + status = Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, B_FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN, 0x0000); | |
| 1215 | + if (status < 0) | |
| 1216 | + break; | |
| 1217 | + } else { | |
| 1218 | + /* PGA off, bypass */ | |
| 1219 | + | |
| 1220 | + /* fine gain */ | |
| 1221 | + status = Read16(state, B_FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000); | |
| 1222 | + if (status < 0) | |
| 1223 | + break; | |
| 1224 | + AgModeLop &= (~(B_FE_AG_REG_AG_MODE_LOP_MODE_C__M)); | |
| 1225 | + AgModeLop |= B_FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC; | |
| 1226 | + status = Write16(state, B_FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000); | |
| 1227 | + if (status < 0) | |
| 1228 | + break; | |
| 1229 | + | |
| 1230 | + /* coarse gain */ | |
| 1231 | + status = Read16(state, B_FE_AG_REG_AG_MODE_HIP__A, &AgModeHip, 0x0000); | |
| 1232 | + if (status < 0) | |
| 1233 | + break; | |
| 1234 | + AgModeHip &= (~(B_FE_AG_REG_AG_MODE_HIP_MODE_J__M)); | |
| 1235 | + AgModeHip |= B_FE_AG_REG_AG_MODE_HIP_MODE_J_STATIC; | |
| 1236 | + status = Write16(state, B_FE_AG_REG_AG_MODE_HIP__A, AgModeHip, 0x0000); | |
| 1237 | + if (status < 0) | |
| 1238 | + break; | |
| 1239 | + | |
| 1240 | + /* disable fine and coarse gain, enable AAF, | |
| 1241 | + no ext resistor */ | |
| 1242 | + status = Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 0x0000); | |
| 1243 | + if (status < 0) | |
| 1244 | + break; | |
| 1245 | + } | |
| 1246 | + } while (0); | |
| 1247 | + return status; | |
| 1248 | +} | |
| 1249 | + | |
| 1250 | +static int InitFE(struct drxd_state *state) | |
| 1251 | +{ | |
| 1252 | + int status; | |
| 1253 | + | |
| 1254 | + do { | |
| 1255 | + status = WriteTable(state, state->m_InitFE_1); | |
| 1256 | + if (status < 0) | |
| 1257 | + break; | |
| 1258 | + | |
| 1259 | + if (state->type_A) { | |
| 1260 | + status = Write16(state, FE_AG_REG_AG_PGA_MODE__A, | |
| 1261 | + FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, | |
| 1262 | + 0); | |
| 1263 | + } else { | |
| 1264 | + if (state->PGA) | |
| 1265 | + status = SetCfgPga(state, 0); | |
| 1266 | + else | |
| 1267 | + status = | |
| 1268 | + Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, | |
| 1269 | + B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, | |
| 1270 | + 0); | |
| 1271 | + } | |
| 1272 | + | |
| 1273 | + if (status < 0) | |
| 1274 | + break; | |
| 1275 | + status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, state->m_FeAgRegAgAgcSio, 0x0000); | |
| 1276 | + if (status < 0) | |
| 1277 | + break; | |
| 1278 | + status = Write16(state, FE_AG_REG_AG_PWD__A, state->m_FeAgRegAgPwd, 0x0000); | |
| 1279 | + if (status < 0) | |
| 1280 | + break; | |
| 1281 | + | |
| 1282 | + status = WriteTable(state, state->m_InitFE_2); | |
| 1283 | + if (status < 0) | |
| 1284 | + break; | |
| 1285 | + | |
| 1286 | + } while (0); | |
| 1287 | + | |
| 1288 | + return status; | |
| 1289 | +} | |
| 1290 | + | |
| 1291 | +static int InitFT(struct drxd_state *state) | |
| 1292 | +{ | |
| 1293 | + /* | |
| 1294 | + norm OFFSET, MB says =2 voor 8K en =3 voor 2K waarschijnlijk | |
| 1295 | + SC stuff | |
| 1296 | + */ | |
| 1297 | + return Write16(state, FT_REG_COMM_EXEC__A, 0x0001, 0x0000); | |
| 1298 | +} | |
| 1299 | + | |
| 1300 | +static int SC_WaitForReady(struct drxd_state *state) | |
| 1301 | +{ | |
| 1302 | + u16 curCmd; | |
| 1303 | + int i; | |
| 1304 | + | |
| 1305 | + for (i = 0; i < DRXD_MAX_RETRIES; i += 1) { | |
| 1306 | + int status = Read16(state, SC_RA_RAM_CMD__A, &curCmd, 0); | |
| 1307 | + if (status == 0 || curCmd == 0) | |
| 1308 | + return status; | |
| 1309 | + } | |
| 1310 | + return -1; | |
| 1311 | +} | |
| 1312 | + | |
| 1313 | +static int SC_SendCommand(struct drxd_state *state, u16 cmd) | |
| 1314 | +{ | |
| 1315 | + int status = 0; | |
| 1316 | + u16 errCode; | |
| 1317 | + | |
| 1318 | + Write16(state, SC_RA_RAM_CMD__A, cmd, 0); | |
| 1319 | + SC_WaitForReady(state); | |
| 1320 | + | |
| 1321 | + Read16(state, SC_RA_RAM_CMD_ADDR__A, &errCode, 0); | |
| 1322 | + | |
| 1323 | + if (errCode == 0xFFFF) { | |
| 1324 | + printk(KERN_ERR "Command Error\n"); | |
| 1325 | + status = -1; | |
| 1326 | + } | |
| 1327 | + | |
| 1328 | + return status; | |
| 1329 | +} | |
| 1330 | + | |
| 1331 | +static int SC_ProcStartCommand(struct drxd_state *state, | |
| 1332 | + u16 subCmd, u16 param0, u16 param1) | |
| 1333 | +{ | |
| 1334 | + int status = 0; | |
| 1335 | + u16 scExec; | |
| 1336 | + | |
| 1337 | + mutex_lock(&state->mutex); | |
| 1338 | + do { | |
| 1339 | + Read16(state, SC_COMM_EXEC__A, &scExec, 0); | |
| 1340 | + if (scExec != 1) { | |
| 1341 | + status = -1; | |
| 1342 | + break; | |
| 1343 | + } | |
| 1344 | + SC_WaitForReady(state); | |
| 1345 | + Write16(state, SC_RA_RAM_CMD_ADDR__A, subCmd, 0); | |
| 1346 | + Write16(state, SC_RA_RAM_PARAM1__A, param1, 0); | |
| 1347 | + Write16(state, SC_RA_RAM_PARAM0__A, param0, 0); | |
| 1348 | + | |
| 1349 | + SC_SendCommand(state, SC_RA_RAM_CMD_PROC_START); | |
| 1350 | + } while (0); | |
| 1351 | + mutex_unlock(&state->mutex); | |
| 1352 | + return status; | |
| 1353 | +} | |
| 1354 | + | |
| 1355 | +static int SC_SetPrefParamCommand(struct drxd_state *state, | |
| 1356 | + u16 subCmd, u16 param0, u16 param1) | |
| 1357 | +{ | |
| 1358 | + int status; | |
| 1359 | + | |
| 1360 | + mutex_lock(&state->mutex); | |
| 1361 | + do { | |
| 1362 | + status = SC_WaitForReady(state); | |
| 1363 | + if (status < 0) | |
| 1364 | + break; | |
| 1365 | + status = Write16(state, SC_RA_RAM_CMD_ADDR__A, subCmd, 0); | |
| 1366 | + if (status < 0) | |
| 1367 | + break; | |
| 1368 | + status = Write16(state, SC_RA_RAM_PARAM1__A, param1, 0); | |
| 1369 | + if (status < 0) | |
| 1370 | + break; | |
| 1371 | + status = Write16(state, SC_RA_RAM_PARAM0__A, param0, 0); | |
| 1372 | + if (status < 0) | |
| 1373 | + break; | |
| 1374 | + | |
| 1375 | + status = SC_SendCommand(state, SC_RA_RAM_CMD_SET_PREF_PARAM); | |
| 1376 | + if (status < 0) | |
| 1377 | + break; | |
| 1378 | + } while (0); | |
| 1379 | + mutex_unlock(&state->mutex); | |
| 1380 | + return status; | |
| 1381 | +} | |
| 1382 | + | |
| 1383 | +#if 0 | |
| 1384 | +static int SC_GetOpParamCommand(struct drxd_state *state, u16 * result) | |
| 1385 | +{ | |
| 1386 | + int status = 0; | |
| 1387 | + | |
| 1388 | + mutex_lock(&state->mutex); | |
| 1389 | + do { | |
| 1390 | + status = SC_WaitForReady(state); | |
| 1391 | + if (status < 0) | |
| 1392 | + break; | |
| 1393 | + status = SC_SendCommand(state, SC_RA_RAM_CMD_GET_OP_PARAM); | |
| 1394 | + if (status < 0) | |
| 1395 | + break; | |
| 1396 | + status = Read16(state, SC_RA_RAM_PARAM0__A, result, 0); | |
| 1397 | + if (status < 0) | |
| 1398 | + break; | |
| 1399 | + } while (0); | |
| 1400 | + mutex_unlock(&state->mutex); | |
| 1401 | + return status; | |
| 1402 | +} | |
| 1403 | +#endif | |
| 1404 | + | |
| 1405 | +static int ConfigureMPEGOutput(struct drxd_state *state, int bEnableOutput) | |
| 1406 | +{ | |
| 1407 | + int status; | |
| 1408 | + | |
| 1409 | + do { | |
| 1410 | + u16 EcOcRegIprInvMpg = 0; | |
| 1411 | + u16 EcOcRegOcModeLop = 0; | |
| 1412 | + u16 EcOcRegOcModeHip = 0; | |
| 1413 | + u16 EcOcRegOcMpgSio = 0; | |
| 1414 | + | |
| 1415 | + /*CHK_ERROR(Read16(state, EC_OC_REG_OC_MODE_LOP__A, &EcOcRegOcModeLop, 0)); */ | |
| 1416 | + | |
| 1417 | + if (state->operation_mode == OM_DVBT_Diversity_Front) { | |
| 1418 | + if (bEnableOutput) { | |
| 1419 | + EcOcRegOcModeHip |= | |
| 1420 | + B_EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR; | |
| 1421 | + } else | |
| 1422 | + EcOcRegOcMpgSio |= EC_OC_REG_OC_MPG_SIO__M; | |
| 1423 | + EcOcRegOcModeLop |= | |
| 1424 | + EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE; | |
| 1425 | + } else { | |
| 1426 | + EcOcRegOcModeLop = state->m_EcOcRegOcModeLop; | |
| 1427 | + | |
| 1428 | + if (bEnableOutput) | |
| 1429 | + EcOcRegOcMpgSio &= (~(EC_OC_REG_OC_MPG_SIO__M)); | |
| 1430 | + else | |
| 1431 | + EcOcRegOcMpgSio |= EC_OC_REG_OC_MPG_SIO__M; | |
| 1432 | + | |
| 1433 | + /* Don't Insert RS Byte */ | |
| 1434 | + if (state->insert_rs_byte) { | |
| 1435 | + EcOcRegOcModeLop &= | |
| 1436 | + (~(EC_OC_REG_OC_MODE_LOP_PAR_ENA__M)); | |
| 1437 | + EcOcRegOcModeHip &= | |
| 1438 | + (~EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M); | |
| 1439 | + EcOcRegOcModeHip |= | |
| 1440 | + EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE; | |
| 1441 | + } else { | |
| 1442 | + EcOcRegOcModeLop |= | |
| 1443 | + EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE; | |
| 1444 | + EcOcRegOcModeHip &= | |
| 1445 | + (~EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M); | |
| 1446 | + EcOcRegOcModeHip |= | |
| 1447 | + EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE; | |
| 1448 | + } | |
| 1449 | + | |
| 1450 | + /* Mode = Parallel */ | |
| 1451 | + if (state->enable_parallel) | |
| 1452 | + EcOcRegOcModeLop &= | |
| 1453 | + (~(EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M)); | |
| 1454 | + else | |
| 1455 | + EcOcRegOcModeLop |= | |
| 1456 | + EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL; | |
| 1457 | + } | |
| 1458 | + /* Invert Data */ | |
| 1459 | + /* EcOcRegIprInvMpg |= 0x00FF; */ | |
| 1460 | + EcOcRegIprInvMpg &= (~(0x00FF)); | |
| 1461 | + | |
| 1462 | + /* Invert Error ( we don't use the pin ) */ | |
| 1463 | + /* EcOcRegIprInvMpg |= 0x0100; */ | |
| 1464 | + EcOcRegIprInvMpg &= (~(0x0100)); | |
| 1465 | + | |
| 1466 | + /* Invert Start ( we don't use the pin ) */ | |
| 1467 | + /* EcOcRegIprInvMpg |= 0x0200; */ | |
| 1468 | + EcOcRegIprInvMpg &= (~(0x0200)); | |
| 1469 | + | |
| 1470 | + /* Invert Valid ( we don't use the pin ) */ | |
| 1471 | + /* EcOcRegIprInvMpg |= 0x0400; */ | |
| 1472 | + EcOcRegIprInvMpg &= (~(0x0400)); | |
| 1473 | + | |
| 1474 | + /* Invert Clock */ | |
| 1475 | + /* EcOcRegIprInvMpg |= 0x0800; */ | |
| 1476 | + EcOcRegIprInvMpg &= (~(0x0800)); | |
| 1477 | + | |
| 1478 | + /* EcOcRegOcModeLop =0x05; */ | |
| 1479 | + status = Write16(state, EC_OC_REG_IPR_INV_MPG__A, EcOcRegIprInvMpg, 0); | |
| 1480 | + if (status < 0) | |
| 1481 | + break; | |
| 1482 | + status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, EcOcRegOcModeLop, 0); | |
| 1483 | + if (status < 0) | |
| 1484 | + break; | |
| 1485 | + status = Write16(state, EC_OC_REG_OC_MODE_HIP__A, EcOcRegOcModeHip, 0x0000); | |
| 1486 | + if (status < 0) | |
| 1487 | + break; | |
| 1488 | + status = Write16(state, EC_OC_REG_OC_MPG_SIO__A, EcOcRegOcMpgSio, 0); | |
| 1489 | + if (status < 0) | |
| 1490 | + break; | |
| 1491 | + } while (0); | |
| 1492 | + return status; | |
| 1493 | +} | |
| 1494 | + | |
| 1495 | +static int SetDeviceTypeId(struct drxd_state *state) | |
| 1496 | +{ | |
| 1497 | + int status = 0; | |
| 1498 | + u16 deviceId = 0; | |
| 1499 | + | |
| 1500 | + do { | |
| 1501 | + status = Read16(state, CC_REG_JTAGID_L__A, &deviceId, 0); | |
| 1502 | + if (status < 0) | |
| 1503 | + break; | |
| 1504 | + /* TODO: why twice? */ | |
| 1505 | + status = Read16(state, CC_REG_JTAGID_L__A, &deviceId, 0); | |
| 1506 | + if (status < 0) | |
| 1507 | + break; | |
| 1508 | + printk(KERN_INFO "drxd: deviceId = %04x\n", deviceId); | |
| 1509 | + | |
| 1510 | + state->type_A = 0; | |
| 1511 | + state->PGA = 0; | |
| 1512 | + state->diversity = 0; | |
| 1513 | + if (deviceId == 0) { /* on A2 only 3975 available */ | |
| 1514 | + state->type_A = 1; | |
| 1515 | + printk(KERN_INFO "DRX3975D-A2\n"); | |
| 1516 | + } else { | |
| 1517 | + deviceId >>= 12; | |
| 1518 | + printk(KERN_INFO "DRX397%dD-B1\n", deviceId); | |
| 1519 | + switch (deviceId) { | |
| 1520 | + case 4: | |
| 1521 | + state->diversity = 1; | |
| 1522 | + case 3: | |
| 1523 | + case 7: | |
| 1524 | + state->PGA = 1; | |
| 1525 | + break; | |
| 1526 | + case 6: | |
| 1527 | + state->diversity = 1; | |
| 1528 | + case 5: | |
| 1529 | + case 8: | |
| 1530 | + break; | |
| 1531 | + default: | |
| 1532 | + status = -1; | |
| 1533 | + break; | |
| 1534 | + } | |
| 1535 | + } | |
| 1536 | + } while (0); | |
| 1537 | + | |
| 1538 | + if (status < 0) | |
| 1539 | + return status; | |
| 1540 | + | |
| 1541 | + /* Init Table selection */ | |
| 1542 | + state->m_InitAtomicRead = DRXD_InitAtomicRead; | |
| 1543 | + state->m_InitSC = DRXD_InitSC; | |
| 1544 | + state->m_ResetECRAM = DRXD_ResetECRAM; | |
| 1545 | + if (state->type_A) { | |
| 1546 | + state->m_ResetCEFR = DRXD_ResetCEFR; | |
| 1547 | + state->m_InitFE_1 = DRXD_InitFEA2_1; | |
| 1548 | + state->m_InitFE_2 = DRXD_InitFEA2_2; | |
| 1549 | + state->m_InitCP = DRXD_InitCPA2; | |
| 1550 | + state->m_InitCE = DRXD_InitCEA2; | |
| 1551 | + state->m_InitEQ = DRXD_InitEQA2; | |
| 1552 | + state->m_InitEC = DRXD_InitECA2; | |
| 1553 | + if (load_firmware(state, DRX_FW_FILENAME_A2)) | |
| 1554 | + return -EIO; | |
| 1555 | + } else { | |
| 1556 | + state->m_ResetCEFR = NULL; | |
| 1557 | + state->m_InitFE_1 = DRXD_InitFEB1_1; | |
| 1558 | + state->m_InitFE_2 = DRXD_InitFEB1_2; | |
| 1559 | + state->m_InitCP = DRXD_InitCPB1; | |
| 1560 | + state->m_InitCE = DRXD_InitCEB1; | |
| 1561 | + state->m_InitEQ = DRXD_InitEQB1; | |
| 1562 | + state->m_InitEC = DRXD_InitECB1; | |
| 1563 | + if (load_firmware(state, DRX_FW_FILENAME_B1)) | |
| 1564 | + return -EIO; | |
| 1565 | + } | |
| 1566 | + if (state->diversity) { | |
| 1567 | + state->m_InitDiversityFront = DRXD_InitDiversityFront; | |
| 1568 | + state->m_InitDiversityEnd = DRXD_InitDiversityEnd; | |
| 1569 | + state->m_DisableDiversity = DRXD_DisableDiversity; | |
| 1570 | + state->m_StartDiversityFront = DRXD_StartDiversityFront; | |
| 1571 | + state->m_StartDiversityEnd = DRXD_StartDiversityEnd; | |
| 1572 | + state->m_DiversityDelay8MHZ = DRXD_DiversityDelay8MHZ; | |
| 1573 | + state->m_DiversityDelay6MHZ = DRXD_DiversityDelay6MHZ; | |
| 1574 | + } else { | |
| 1575 | + state->m_InitDiversityFront = NULL; | |
| 1576 | + state->m_InitDiversityEnd = NULL; | |
| 1577 | + state->m_DisableDiversity = NULL; | |
| 1578 | + state->m_StartDiversityFront = NULL; | |
| 1579 | + state->m_StartDiversityEnd = NULL; | |
| 1580 | + state->m_DiversityDelay8MHZ = NULL; | |
| 1581 | + state->m_DiversityDelay6MHZ = NULL; | |
| 1582 | + } | |
| 1583 | + | |
| 1584 | + return status; | |
| 1585 | +} | |
| 1586 | + | |
| 1587 | +static int CorrectSysClockDeviation(struct drxd_state *state) | |
| 1588 | +{ | |
| 1589 | + int status; | |
| 1590 | + s32 incr = 0; | |
| 1591 | + s32 nomincr = 0; | |
| 1592 | + u32 bandwidth = 0; | |
| 1593 | + u32 sysClockInHz = 0; | |
| 1594 | + u32 sysClockFreq = 0; /* in kHz */ | |
| 1595 | + s16 oscClockDeviation; | |
| 1596 | + s16 Diff; | |
| 1597 | + | |
| 1598 | + do { | |
| 1599 | + /* Retrieve bandwidth and incr, sanity check */ | |
| 1600 | + | |
| 1601 | + /* These accesses should be AtomicReadReg32, but that | |
| 1602 | + causes trouble (at least for diversity */ | |
| 1603 | + status = Read32(state, LC_RA_RAM_IFINCR_NOM_L__A, ((u32 *) &nomincr), 0); | |
| 1604 | + if (status < 0) | |
| 1605 | + break; | |
| 1606 | + status = Read32(state, FE_IF_REG_INCR0__A, (u32 *) &incr, 0); | |
| 1607 | + if (status < 0) | |
| 1608 | + break; | |
| 1609 | + | |
| 1610 | + if (state->type_A) { | |
| 1611 | + if ((nomincr - incr < -500) || (nomincr - incr > 500)) | |
| 1612 | + break; | |
| 1613 | + } else { | |
| 1614 | + if ((nomincr - incr < -2000) || (nomincr - incr > 2000)) | |
| 1615 | + break; | |
| 1616 | + } | |
| 1617 | + | |
| 1618 | + switch (state->param.u.ofdm.bandwidth) { | |
| 1619 | + case BANDWIDTH_8_MHZ: | |
| 1620 | + bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ; | |
| 1621 | + break; | |
| 1622 | + case BANDWIDTH_7_MHZ: | |
| 1623 | + bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ; | |
| 1624 | + break; | |
| 1625 | + case BANDWIDTH_6_MHZ: | |
| 1626 | + bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ; | |
| 1627 | + break; | |
| 1628 | + default: | |
| 1629 | + return -1; | |
| 1630 | + break; | |
| 1631 | + } | |
| 1632 | + | |
| 1633 | + /* Compute new sysclock value | |
| 1634 | + sysClockFreq = (((incr + 2^23)*bandwidth)/2^21)/1000 */ | |
| 1635 | + incr += (1 << 23); | |
| 1636 | + sysClockInHz = MulDiv32(incr, bandwidth, 1 << 21); | |
| 1637 | + sysClockFreq = (u32) (sysClockInHz / 1000); | |
| 1638 | + /* rounding */ | |
| 1639 | + if ((sysClockInHz % 1000) > 500) | |
| 1640 | + sysClockFreq++; | |
| 1641 | + | |
| 1642 | + /* Compute clock deviation in ppm */ | |
| 1643 | + oscClockDeviation = (u16) ((((s32) (sysClockFreq) - | |
| 1644 | + (s32) | |
| 1645 | + (state->expected_sys_clock_freq)) * | |
| 1646 | + 1000000L) / | |
| 1647 | + (s32) | |
| 1648 | + (state->expected_sys_clock_freq)); | |
| 1649 | + | |
| 1650 | + Diff = oscClockDeviation - state->osc_clock_deviation; | |
| 1651 | + /*printk(KERN_INFO "sysclockdiff=%d\n", Diff); */ | |
| 1652 | + if (Diff >= -200 && Diff <= 200) { | |
| 1653 | + state->sys_clock_freq = (u16) sysClockFreq; | |
| 1654 | + if (oscClockDeviation != state->osc_clock_deviation) { | |
| 1655 | + if (state->config.osc_deviation) { | |
| 1656 | + state->config.osc_deviation(state->priv, | |
| 1657 | + oscClockDeviation, | |
| 1658 | + 1); | |
| 1659 | + state->osc_clock_deviation = | |
| 1660 | + oscClockDeviation; | |
| 1661 | + } | |
| 1662 | + } | |
| 1663 | + /* switch OFF SRMM scan in SC */ | |
| 1664 | + status = Write16(state, SC_RA_RAM_SAMPLE_RATE_COUNT__A, DRXD_OSCDEV_DONT_SCAN, 0); | |
| 1665 | + if (status < 0) | |
| 1666 | + break; | |
| 1667 | + /* overrule FE_IF internal value for | |
| 1668 | + proper re-locking */ | |
| 1669 | + status = Write16(state, SC_RA_RAM_IF_SAVE__AX, state->current_fe_if_incr, 0); | |
| 1670 | + if (status < 0) | |
| 1671 | + break; | |
| 1672 | + state->cscd_state = CSCD_SAVED; | |
| 1673 | + } | |
| 1674 | + } while (0); | |
| 1675 | + | |
| 1676 | + return status; | |
| 1677 | +} | |
| 1678 | + | |
| 1679 | +static int DRX_Stop(struct drxd_state *state) | |
| 1680 | +{ | |
| 1681 | + int status; | |
| 1682 | + | |
| 1683 | + if (state->drxd_state != DRXD_STARTED) | |
| 1684 | + return 0; | |
| 1685 | + | |
| 1686 | + do { | |
| 1687 | + if (state->cscd_state != CSCD_SAVED) { | |
| 1688 | + u32 lock; | |
| 1689 | + status = DRX_GetLockStatus(state, &lock); | |
| 1690 | + if (status < 0) | |
| 1691 | + break; | |
| 1692 | + } | |
| 1693 | + | |
| 1694 | + status = StopOC(state); | |
| 1695 | + if (status < 0) | |
| 1696 | + break; | |
| 1697 | + | |
| 1698 | + state->drxd_state = DRXD_STOPPED; | |
| 1699 | + | |
| 1700 | + status = ConfigureMPEGOutput(state, 0); | |
| 1701 | + if (status < 0) | |
| 1702 | + break; | |
| 1703 | + | |
| 1704 | + if (state->type_A) { | |
| 1705 | + /* Stop relevant processors off the device */ | |
| 1706 | + status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0000, 0x0000); | |
| 1707 | + if (status < 0) | |
| 1708 | + break; | |
| 1709 | + | |
| 1710 | + status = Write16(state, SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | |
| 1711 | + if (status < 0) | |
| 1712 | + break; | |
| 1713 | + status = Write16(state, LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | |
| 1714 | + if (status < 0) | |
| 1715 | + break; | |
| 1716 | + } else { | |
| 1717 | + /* Stop all processors except HI & CC & FE */ | |
| 1718 | + status = Write16(state, B_SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | |
| 1719 | + if (status < 0) | |
| 1720 | + break; | |
| 1721 | + status = Write16(state, B_LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | |
| 1722 | + if (status < 0) | |
| 1723 | + break; | |
| 1724 | + status = Write16(state, B_FT_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | |
| 1725 | + if (status < 0) | |
| 1726 | + break; | |
| 1727 | + status = Write16(state, B_CP_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | |
| 1728 | + if (status < 0) | |
| 1729 | + break; | |
| 1730 | + status = Write16(state, B_CE_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | |
| 1731 | + if (status < 0) | |
| 1732 | + break; | |
| 1733 | + status = Write16(state, B_EQ_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | |
| 1734 | + if (status < 0) | |
| 1735 | + break; | |
| 1736 | + status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0000, 0); | |
| 1737 | + if (status < 0) | |
| 1738 | + break; | |
| 1739 | + } | |
| 1740 | + | |
| 1741 | + } while (0); | |
| 1742 | + return status; | |
| 1743 | +} | |
| 1744 | + | |
| 1745 | +int SetOperationMode(struct drxd_state *state, int oMode) | |
| 1746 | +{ | |
| 1747 | + int status; | |
| 1748 | + | |
| 1749 | + do { | |
| 1750 | + if (state->drxd_state != DRXD_STOPPED) { | |
| 1751 | + status = -1; | |
| 1752 | + break; | |
| 1753 | + } | |
| 1754 | + | |
| 1755 | + if (oMode == state->operation_mode) { | |
| 1756 | + status = 0; | |
| 1757 | + break; | |
| 1758 | + } | |
| 1759 | + | |
| 1760 | + if (oMode != OM_Default && !state->diversity) { | |
| 1761 | + status = -1; | |
| 1762 | + break; | |
| 1763 | + } | |
| 1764 | + | |
| 1765 | + switch (oMode) { | |
| 1766 | + case OM_DVBT_Diversity_Front: | |
| 1767 | + status = WriteTable(state, state->m_InitDiversityFront); | |
| 1768 | + break; | |
| 1769 | + case OM_DVBT_Diversity_End: | |
| 1770 | + status = WriteTable(state, state->m_InitDiversityEnd); | |
| 1771 | + break; | |
| 1772 | + case OM_Default: | |
| 1773 | + /* We need to check how to | |
| 1774 | + get DRXD out of diversity */ | |
| 1775 | + default: | |
| 1776 | + status = WriteTable(state, state->m_DisableDiversity); | |
| 1777 | + break; | |
| 1778 | + } | |
| 1779 | + } while (0); | |
| 1780 | + | |
| 1781 | + if (!status) | |
| 1782 | + state->operation_mode = oMode; | |
| 1783 | + return status; | |
| 1784 | +} | |
| 1785 | + | |
| 1786 | +static int StartDiversity(struct drxd_state *state) | |
| 1787 | +{ | |
| 1788 | + int status = 0; | |
| 1789 | + u16 rcControl; | |
| 1790 | + | |
| 1791 | + do { | |
| 1792 | + if (state->operation_mode == OM_DVBT_Diversity_Front) { | |
| 1793 | + status = WriteTable(state, state->m_StartDiversityFront); | |
| 1794 | + if (status < 0) | |
| 1795 | + break; | |
| 1796 | + } else if (state->operation_mode == OM_DVBT_Diversity_End) { | |
| 1797 | + status = WriteTable(state, state->m_StartDiversityEnd); | |
| 1798 | + if (status < 0) | |
| 1799 | + break; | |
| 1800 | + if (state->param.u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { | |
| 1801 | + status = WriteTable(state, state->m_DiversityDelay8MHZ); | |
| 1802 | + if (status < 0) | |
| 1803 | + break; | |
| 1804 | + } else { | |
| 1805 | + status = WriteTable(state, state->m_DiversityDelay6MHZ); | |
| 1806 | + if (status < 0) | |
| 1807 | + break; | |
| 1808 | + } | |
| 1809 | + | |
| 1810 | + status = Read16(state, B_EQ_REG_RC_SEL_CAR__A, &rcControl, 0); | |
| 1811 | + if (status < 0) | |
| 1812 | + break; | |
| 1813 | + rcControl &= ~(B_EQ_REG_RC_SEL_CAR_FFTMODE__M); | |
| 1814 | + rcControl |= B_EQ_REG_RC_SEL_CAR_DIV_ON | | |
| 1815 | + /* combining enabled */ | |
| 1816 | + B_EQ_REG_RC_SEL_CAR_MEAS_A_CC | | |
| 1817 | + B_EQ_REG_RC_SEL_CAR_PASS_A_CC | | |
| 1818 | + B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC; | |
| 1819 | + status = Write16(state, B_EQ_REG_RC_SEL_CAR__A, rcControl, 0); | |
| 1820 | + if (status < 0) | |
| 1821 | + break; | |
| 1822 | + } | |
| 1823 | + } while (0); | |
| 1824 | + return status; | |
| 1825 | +} | |
| 1826 | + | |
| 1827 | +static int SetFrequencyShift(struct drxd_state *state, | |
| 1828 | + u32 offsetFreq, int channelMirrored) | |
| 1829 | +{ | |
| 1830 | + int negativeShift = (state->tuner_mirrors == channelMirrored); | |
| 1831 | + | |
| 1832 | + /* Handle all mirroring | |
| 1833 | + * | |
| 1834 | + * Note: ADC mirroring (aliasing) is implictly handled by limiting | |
| 1835 | + * feFsRegAddInc to 28 bits below | |
| 1836 | + * (if the result before masking is more than 28 bits, this means | |
| 1837 | + * that the ADC is mirroring. | |
| 1838 | + * The masking is in fact the aliasing of the ADC) | |
| 1839 | + * | |
| 1840 | + */ | |
| 1841 | + | |
| 1842 | + /* Compute register value, unsigned computation */ | |
| 1843 | + state->fe_fs_add_incr = MulDiv32(state->intermediate_freq + | |
| 1844 | + offsetFreq, | |
| 1845 | + 1 << 28, state->sys_clock_freq); | |
| 1846 | + /* Remove integer part */ | |
| 1847 | + state->fe_fs_add_incr &= 0x0FFFFFFFL; | |
| 1848 | + if (negativeShift) | |
| 1849 | + state->fe_fs_add_incr = ((1 << 28) - state->fe_fs_add_incr); | |
| 1850 | + | |
| 1851 | + /* Save the frequency shift without tunerOffset compensation | |
| 1852 | + for CtrlGetChannel. */ | |
| 1853 | + state->org_fe_fs_add_incr = MulDiv32(state->intermediate_freq, | |
| 1854 | + 1 << 28, state->sys_clock_freq); | |
| 1855 | + /* Remove integer part */ | |
| 1856 | + state->org_fe_fs_add_incr &= 0x0FFFFFFFL; | |
| 1857 | + if (negativeShift) | |
| 1858 | + state->org_fe_fs_add_incr = ((1L << 28) - | |
| 1859 | + state->org_fe_fs_add_incr); | |
| 1860 | + | |
| 1861 | + return Write32(state, FE_FS_REG_ADD_INC_LOP__A, | |
| 1862 | + state->fe_fs_add_incr, 0); | |
| 1863 | +} | |
| 1864 | + | |
| 1865 | +static int SetCfgNoiseCalibration(struct drxd_state *state, | |
| 1866 | + struct SNoiseCal *noiseCal) | |
| 1867 | +{ | |
| 1868 | + u16 beOptEna; | |
| 1869 | + int status = 0; | |
| 1870 | + | |
| 1871 | + do { | |
| 1872 | + status = Read16(state, SC_RA_RAM_BE_OPT_ENA__A, &beOptEna, 0); | |
| 1873 | + if (status < 0) | |
| 1874 | + break; | |
| 1875 | + if (noiseCal->cpOpt) { | |
| 1876 | + beOptEna |= (1 << SC_RA_RAM_BE_OPT_ENA_CP_OPT); | |
| 1877 | + } else { | |
| 1878 | + beOptEna &= ~(1 << SC_RA_RAM_BE_OPT_ENA_CP_OPT); | |
| 1879 | + status = Write16(state, CP_REG_AC_NEXP_OFFS__A, noiseCal->cpNexpOfs, 0); | |
| 1880 | + if (status < 0) | |
| 1881 | + break; | |
| 1882 | + } | |
| 1883 | + status = Write16(state, SC_RA_RAM_BE_OPT_ENA__A, beOptEna, 0); | |
| 1884 | + if (status < 0) | |
| 1885 | + break; | |
| 1886 | + | |
| 1887 | + if (!state->type_A) { | |
| 1888 | + status = Write16(state, B_SC_RA_RAM_CO_TD_CAL_2K__A, noiseCal->tdCal2k, 0); | |
| 1889 | + if (status < 0) | |
| 1890 | + break; | |
| 1891 | + status = Write16(state, B_SC_RA_RAM_CO_TD_CAL_8K__A, noiseCal->tdCal8k, 0); | |
| 1892 | + if (status < 0) | |
| 1893 | + break; | |
| 1894 | + } | |
| 1895 | + } while (0); | |
| 1896 | + | |
| 1897 | + return status; | |
| 1898 | +} | |
| 1899 | + | |
| 1900 | +static int DRX_Start(struct drxd_state *state, s32 off) | |
| 1901 | +{ | |
| 1902 | + struct dvb_ofdm_parameters *p = &state->param.u.ofdm; | |
| 1903 | + int status; | |
| 1904 | + | |
| 1905 | + u16 transmissionParams = 0; | |
| 1906 | + u16 operationMode = 0; | |
| 1907 | + u16 qpskTdTpsPwr = 0; | |
| 1908 | + u16 qam16TdTpsPwr = 0; | |
| 1909 | + u16 qam64TdTpsPwr = 0; | |
| 1910 | + u32 feIfIncr = 0; | |
| 1911 | + u32 bandwidth = 0; | |
| 1912 | + int mirrorFreqSpect; | |
| 1913 | + | |
| 1914 | + u16 qpskSnCeGain = 0; | |
| 1915 | + u16 qam16SnCeGain = 0; | |
| 1916 | + u16 qam64SnCeGain = 0; | |
| 1917 | + u16 qpskIsGainMan = 0; | |
| 1918 | + u16 qam16IsGainMan = 0; | |
| 1919 | + u16 qam64IsGainMan = 0; | |
| 1920 | + u16 qpskIsGainExp = 0; | |
| 1921 | + u16 qam16IsGainExp = 0; | |
| 1922 | + u16 qam64IsGainExp = 0; | |
| 1923 | + u16 bandwidthParam = 0; | |
| 1924 | + | |
| 1925 | + if (off < 0) | |
| 1926 | + off = (off - 500) / 1000; | |
| 1927 | + else | |
| 1928 | + off = (off + 500) / 1000; | |
| 1929 | + | |
| 1930 | + do { | |
| 1931 | + if (state->drxd_state != DRXD_STOPPED) | |
| 1932 | + return -1; | |
| 1933 | + status = ResetECOD(state); | |
| 1934 | + if (status < 0) | |
| 1935 | + break; | |
| 1936 | + if (state->type_A) { | |
| 1937 | + status = InitSC(state); | |
| 1938 | + if (status < 0) | |
| 1939 | + break; | |
| 1940 | + } else { | |
| 1941 | + status = InitFT(state); | |
| 1942 | + if (status < 0) | |
| 1943 | + break; | |
| 1944 | + status = InitCP(state); | |
| 1945 | + if (status < 0) | |
| 1946 | + break; | |
| 1947 | + status = InitCE(state); | |
| 1948 | + if (status < 0) | |
| 1949 | + break; | |
| 1950 | + status = InitEQ(state); | |
| 1951 | + if (status < 0) | |
| 1952 | + break; | |
| 1953 | + status = InitSC(state); | |
| 1954 | + if (status < 0) | |
| 1955 | + break; | |
| 1956 | + } | |
| 1957 | + | |
| 1958 | + /* Restore current IF & RF AGC settings */ | |
| 1959 | + | |
| 1960 | + status = SetCfgIfAgc(state, &state->if_agc_cfg); | |
| 1961 | + if (status < 0) | |
| 1962 | + break; | |
| 1963 | + status = SetCfgRfAgc(state, &state->rf_agc_cfg); | |
| 1964 | + if (status < 0) | |
| 1965 | + break; | |
| 1966 | + | |
| 1967 | + mirrorFreqSpect = (state->param.inversion == INVERSION_ON); | |
| 1968 | + | |
| 1969 | + switch (p->transmission_mode) { | |
| 1970 | + default: /* Not set, detect it automatically */ | |
| 1971 | + operationMode |= SC_RA_RAM_OP_AUTO_MODE__M; | |
| 1972 | + /* fall through , try first guess DRX_FFTMODE_8K */ | |
| 1973 | + case TRANSMISSION_MODE_8K: | |
| 1974 | + transmissionParams |= SC_RA_RAM_OP_PARAM_MODE_8K; | |
| 1975 | + if (state->type_A) { | |
| 1976 | + status = Write16(state, EC_SB_REG_TR_MODE__A, EC_SB_REG_TR_MODE_8K, 0x0000); | |
| 1977 | + if (status < 0) | |
| 1978 | + break; | |
| 1979 | + qpskSnCeGain = 99; | |
| 1980 | + qam16SnCeGain = 83; | |
| 1981 | + qam64SnCeGain = 67; | |
| 1982 | + } | |
| 1983 | + break; | |
| 1984 | + case TRANSMISSION_MODE_2K: | |
| 1985 | + transmissionParams |= SC_RA_RAM_OP_PARAM_MODE_2K; | |
| 1986 | + if (state->type_A) { | |
| 1987 | + status = Write16(state, EC_SB_REG_TR_MODE__A, EC_SB_REG_TR_MODE_2K, 0x0000); | |
| 1988 | + if (status < 0) | |
| 1989 | + break; | |
| 1990 | + qpskSnCeGain = 97; | |
| 1991 | + qam16SnCeGain = 71; | |
| 1992 | + qam64SnCeGain = 65; | |
| 1993 | + } | |
| 1994 | + break; | |
| 1995 | + } | |
| 1996 | + | |
| 1997 | + switch (p->guard_interval) { | |
| 1998 | + case GUARD_INTERVAL_1_4: | |
| 1999 | + transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_4; | |
| 2000 | + break; | |
| 2001 | + case GUARD_INTERVAL_1_8: | |
| 2002 | + transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_8; | |
| 2003 | + break; | |
| 2004 | + case GUARD_INTERVAL_1_16: | |
| 2005 | + transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_16; | |
| 2006 | + break; | |
| 2007 | + case GUARD_INTERVAL_1_32: | |
| 2008 | + transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_32; | |
| 2009 | + break; | |
| 2010 | + default: /* Not set, detect it automatically */ | |
| 2011 | + operationMode |= SC_RA_RAM_OP_AUTO_GUARD__M; | |
| 2012 | + /* try first guess 1/4 */ | |
| 2013 | + transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_4; | |
| 2014 | + break; | |
| 2015 | + } | |
| 2016 | + | |
| 2017 | + switch (p->hierarchy_information) { | |
| 2018 | + case HIERARCHY_1: | |
| 2019 | + transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A1; | |
| 2020 | + if (state->type_A) { | |
| 2021 | + status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0001, 0x0000); | |
| 2022 | + if (status < 0) | |
| 2023 | + break; | |
| 2024 | + status = Write16(state, EC_SB_REG_ALPHA__A, 0x0001, 0x0000); | |
| 2025 | + if (status < 0) | |
| 2026 | + break; | |
| 2027 | + | |
| 2028 | + qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN; | |
| 2029 | + qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA1; | |
| 2030 | + qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA1; | |
| 2031 | + | |
| 2032 | + qpskIsGainMan = | |
| 2033 | + SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE; | |
| 2034 | + qam16IsGainMan = | |
| 2035 | + SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE; | |
| 2036 | + qam64IsGainMan = | |
| 2037 | + SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE; | |
| 2038 | + | |
| 2039 | + qpskIsGainExp = | |
| 2040 | + SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE; | |
| 2041 | + qam16IsGainExp = | |
| 2042 | + SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE; | |
| 2043 | + qam64IsGainExp = | |
| 2044 | + SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE; | |
| 2045 | + } | |
| 2046 | + break; | |
| 2047 | + | |
| 2048 | + case HIERARCHY_2: | |
| 2049 | + transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A2; | |
| 2050 | + if (state->type_A) { | |
| 2051 | + status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0002, 0x0000); | |
| 2052 | + if (status < 0) | |
| 2053 | + break; | |
| 2054 | + status = Write16(state, EC_SB_REG_ALPHA__A, 0x0002, 0x0000); | |
| 2055 | + if (status < 0) | |
| 2056 | + break; | |
| 2057 | + | |
| 2058 | + qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN; | |
| 2059 | + qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA2; | |
| 2060 | + qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA2; | |
| 2061 | + | |
| 2062 | + qpskIsGainMan = | |
| 2063 | + SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE; | |
| 2064 | + qam16IsGainMan = | |
| 2065 | + SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE; | |
| 2066 | + qam64IsGainMan = | |
| 2067 | + SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE; | |
| 2068 | + | |
| 2069 | + qpskIsGainExp = | |
| 2070 | + SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE; | |
| 2071 | + qam16IsGainExp = | |
| 2072 | + SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE; | |
| 2073 | + qam64IsGainExp = | |
| 2074 | + SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE; | |
| 2075 | + } | |
| 2076 | + break; | |
| 2077 | + case HIERARCHY_4: | |
| 2078 | + transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A4; | |
| 2079 | + if (state->type_A) { | |
| 2080 | + status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0003, 0x0000); | |
| 2081 | + if (status < 0) | |
| 2082 | + break; | |
| 2083 | + status = Write16(state, EC_SB_REG_ALPHA__A, 0x0003, 0x0000); | |
| 2084 | + if (status < 0) | |
| 2085 | + break; | |
| 2086 | + | |
| 2087 | + qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN; | |
| 2088 | + qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA4; | |
| 2089 | + qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA4; | |
| 2090 | + | |
| 2091 | + qpskIsGainMan = | |
| 2092 | + SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE; | |
| 2093 | + qam16IsGainMan = | |
| 2094 | + SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE; | |
| 2095 | + qam64IsGainMan = | |
| 2096 | + SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE; | |
| 2097 | + | |
| 2098 | + qpskIsGainExp = | |
| 2099 | + SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE; | |
| 2100 | + qam16IsGainExp = | |
| 2101 | + SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE; | |
| 2102 | + qam64IsGainExp = | |
| 2103 | + SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE; | |
| 2104 | + } | |
| 2105 | + break; | |
| 2106 | + case HIERARCHY_AUTO: | |
| 2107 | + default: | |
| 2108 | + /* Not set, detect it automatically, start with none */ | |
| 2109 | + operationMode |= SC_RA_RAM_OP_AUTO_HIER__M; | |
| 2110 | + transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_NO; | |
| 2111 | + if (state->type_A) { | |
| 2112 | + status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0000, 0x0000); | |
| 2113 | + if (status < 0) | |
| 2114 | + break; | |
| 2115 | + status = Write16(state, EC_SB_REG_ALPHA__A, 0x0000, 0x0000); | |
| 2116 | + if (status < 0) | |
| 2117 | + break; | |
| 2118 | + | |
| 2119 | + qpskTdTpsPwr = EQ_TD_TPS_PWR_QPSK; | |
| 2120 | + qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHAN; | |
| 2121 | + qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHAN; | |
| 2122 | + | |
| 2123 | + qpskIsGainMan = | |
| 2124 | + SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE; | |
| 2125 | + qam16IsGainMan = | |
| 2126 | + SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE; | |
| 2127 | + qam64IsGainMan = | |
| 2128 | + SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE; | |
| 2129 | + | |
| 2130 | + qpskIsGainExp = | |
| 2131 | + SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE; | |
| 2132 | + qam16IsGainExp = | |
| 2133 | + SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE; | |
| 2134 | + qam64IsGainExp = | |
| 2135 | + SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE; | |
| 2136 | + } | |
| 2137 | + break; | |
| 2138 | + } | |
| 2139 | + status = status; | |
| 2140 | + if (status < 0) | |
| 2141 | + break; | |
| 2142 | + | |
| 2143 | + switch (p->constellation) { | |
| 2144 | + default: | |
| 2145 | + operationMode |= SC_RA_RAM_OP_AUTO_CONST__M; | |
| 2146 | + /* fall through , try first guess | |
| 2147 | + DRX_CONSTELLATION_QAM64 */ | |
| 2148 | + case QAM_64: | |
| 2149 | + transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QAM64; | |
| 2150 | + if (state->type_A) { | |
| 2151 | + status = Write16(state, EQ_REG_OT_CONST__A, 0x0002, 0x0000); | |
| 2152 | + if (status < 0) | |
| 2153 | + break; | |
| 2154 | + status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_64QAM, 0x0000); | |
| 2155 | + if (status < 0) | |
| 2156 | + break; | |
| 2157 | + status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0020, 0x0000); | |
| 2158 | + if (status < 0) | |
| 2159 | + break; | |
| 2160 | + status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0008, 0x0000); | |
| 2161 | + if (status < 0) | |
| 2162 | + break; | |
| 2163 | + status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0002, 0x0000); | |
| 2164 | + if (status < 0) | |
| 2165 | + break; | |
| 2166 | + | |
| 2167 | + status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qam64TdTpsPwr, 0x0000); | |
| 2168 | + if (status < 0) | |
| 2169 | + break; | |
| 2170 | + status = Write16(state, EQ_REG_SN_CEGAIN__A, qam64SnCeGain, 0x0000); | |
| 2171 | + if (status < 0) | |
| 2172 | + break; | |
| 2173 | + status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qam64IsGainMan, 0x0000); | |
| 2174 | + if (status < 0) | |
| 2175 | + break; | |
| 2176 | + status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qam64IsGainExp, 0x0000); | |
| 2177 | + if (status < 0) | |
| 2178 | + break; | |
| 2179 | + } | |
| 2180 | + break; | |
| 2181 | + case QPSK: | |
| 2182 | + transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QPSK; | |
| 2183 | + if (state->type_A) { | |
| 2184 | + status = Write16(state, EQ_REG_OT_CONST__A, 0x0000, 0x0000); | |
| 2185 | + if (status < 0) | |
| 2186 | + break; | |
| 2187 | + status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_QPSK, 0x0000); | |
| 2188 | + if (status < 0) | |
| 2189 | + break; | |
| 2190 | + status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0010, 0x0000); | |
| 2191 | + if (status < 0) | |
| 2192 | + break; | |
| 2193 | + status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0000, 0x0000); | |
| 2194 | + if (status < 0) | |
| 2195 | + break; | |
| 2196 | + status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0000, 0x0000); | |
| 2197 | + if (status < 0) | |
| 2198 | + break; | |
| 2199 | + | |
| 2200 | + status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qpskTdTpsPwr, 0x0000); | |
| 2201 | + if (status < 0) | |
| 2202 | + break; | |
| 2203 | + status = Write16(state, EQ_REG_SN_CEGAIN__A, qpskSnCeGain, 0x0000); | |
| 2204 | + if (status < 0) | |
| 2205 | + break; | |
| 2206 | + status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qpskIsGainMan, 0x0000); | |
| 2207 | + if (status < 0) | |
| 2208 | + break; | |
| 2209 | + status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qpskIsGainExp, 0x0000); | |
| 2210 | + if (status < 0) | |
| 2211 | + break; | |
| 2212 | + } | |
| 2213 | + break; | |
| 2214 | + | |
| 2215 | + case QAM_16: | |
| 2216 | + transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QAM16; | |
| 2217 | + if (state->type_A) { | |
| 2218 | + status = Write16(state, EQ_REG_OT_CONST__A, 0x0001, 0x0000); | |
| 2219 | + if (status < 0) | |
| 2220 | + break; | |
| 2221 | + status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_16QAM, 0x0000); | |
| 2222 | + if (status < 0) | |
| 2223 | + break; | |
| 2224 | + status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0010, 0x0000); | |
| 2225 | + if (status < 0) | |
| 2226 | + break; | |
| 2227 | + status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0004, 0x0000); | |
| 2228 | + if (status < 0) | |
| 2229 | + break; | |
| 2230 | + status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0000, 0x0000); | |
| 2231 | + if (status < 0) | |
| 2232 | + break; | |
| 2233 | + | |
| 2234 | + status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qam16TdTpsPwr, 0x0000); | |
| 2235 | + if (status < 0) | |
| 2236 | + break; | |
| 2237 | + status = Write16(state, EQ_REG_SN_CEGAIN__A, qam16SnCeGain, 0x0000); | |
| 2238 | + if (status < 0) | |
| 2239 | + break; | |
| 2240 | + status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qam16IsGainMan, 0x0000); | |
| 2241 | + if (status < 0) | |
| 2242 | + break; | |
| 2243 | + status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qam16IsGainExp, 0x0000); | |
| 2244 | + if (status < 0) | |
| 2245 | + break; | |
| 2246 | + } | |
| 2247 | + break; | |
| 2248 | + | |
| 2249 | + } | |
| 2250 | + status = status; | |
| 2251 | + if (status < 0) | |
| 2252 | + break; | |
| 2253 | + | |
| 2254 | + switch (DRX_CHANNEL_HIGH) { | |
| 2255 | + default: | |
| 2256 | + case DRX_CHANNEL_AUTO: | |
| 2257 | + case DRX_CHANNEL_LOW: | |
| 2258 | + transmissionParams |= SC_RA_RAM_OP_PARAM_PRIO_LO; | |
| 2259 | + status = Write16(state, EC_SB_REG_PRIOR__A, EC_SB_REG_PRIOR_LO, 0x0000); | |
| 2260 | + if (status < 0) | |
| 2261 | + break; | |
| 2262 | + break; | |
| 2263 | + case DRX_CHANNEL_HIGH: | |
| 2264 | + transmissionParams |= SC_RA_RAM_OP_PARAM_PRIO_HI; | |
| 2265 | + status = Write16(state, EC_SB_REG_PRIOR__A, EC_SB_REG_PRIOR_HI, 0x0000); | |
| 2266 | + if (status < 0) | |
| 2267 | + break; | |
| 2268 | + break; | |
| 2269 | + | |
| 2270 | + } | |
| 2271 | + | |
| 2272 | + switch (p->code_rate_HP) { | |
| 2273 | + case FEC_1_2: | |
| 2274 | + transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_1_2; | |
| 2275 | + if (state->type_A) { | |
| 2276 | + status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C1_2, 0x0000); | |
| 2277 | + if (status < 0) | |
| 2278 | + break; | |
| 2279 | + } | |
| 2280 | + break; | |
| 2281 | + default: | |
| 2282 | + operationMode |= SC_RA_RAM_OP_AUTO_RATE__M; | |
| 2283 | + case FEC_2_3: | |
| 2284 | + transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_2_3; | |
| 2285 | + if (state->type_A) { | |
| 2286 | + status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C2_3, 0x0000); | |
| 2287 | + if (status < 0) | |
| 2288 | + break; | |
| 2289 | + } | |
| 2290 | + break; | |
| 2291 | + case FEC_3_4: | |
| 2292 | + transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_3_4; | |
| 2293 | + if (state->type_A) { | |
| 2294 | + status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C3_4, 0x0000); | |
| 2295 | + if (status < 0) | |
| 2296 | + break; | |
| 2297 | + } | |
| 2298 | + break; | |
| 2299 | + case FEC_5_6: | |
| 2300 | + transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_5_6; | |
| 2301 | + if (state->type_A) { | |
| 2302 | + status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C5_6, 0x0000); | |
| 2303 | + if (status < 0) | |
| 2304 | + break; | |
| 2305 | + } | |
| 2306 | + break; | |
| 2307 | + case FEC_7_8: | |
| 2308 | + transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_7_8; | |
| 2309 | + if (state->type_A) { | |
| 2310 | + status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C7_8, 0x0000); | |
| 2311 | + if (status < 0) | |
| 2312 | + break; | |
| 2313 | + } | |
| 2314 | + break; | |
| 2315 | + } | |
| 2316 | + status = status; | |
| 2317 | + if (status < 0) | |
| 2318 | + break; | |
| 2319 | + | |
| 2320 | + /* First determine real bandwidth (Hz) */ | |
| 2321 | + /* Also set delay for impulse noise cruncher (only A2) */ | |
| 2322 | + /* Also set parameters for EC_OC fix, note | |
| 2323 | + EC_OC_REG_TMD_HIL_MAR is changed | |
| 2324 | + by SC for fix for some 8K,1/8 guard but is restored by | |
| 2325 | + InitEC and ResetEC | |
| 2326 | + functions */ | |
| 2327 | + switch (p->bandwidth) { | |
| 2328 | + case BANDWIDTH_AUTO: | |
| 2329 | + case BANDWIDTH_8_MHZ: | |
| 2330 | + /* (64/7)*(8/8)*1000000 */ | |
| 2331 | + bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ; | |
| 2332 | + | |
| 2333 | + bandwidthParam = 0; | |
| 2334 | + status = Write16(state, | |
| 2335 | + FE_AG_REG_IND_DEL__A, 50, 0x0000); | |
| 2336 | + break; | |
| 2337 | + case BANDWIDTH_7_MHZ: | |
| 2338 | + /* (64/7)*(7/8)*1000000 */ | |
| 2339 | + bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ; | |
| 2340 | + bandwidthParam = 0x4807; /*binary:0100 1000 0000 0111 */ | |
| 2341 | + status = Write16(state, | |
| 2342 | + FE_AG_REG_IND_DEL__A, 59, 0x0000); | |
| 2343 | + break; | |
| 2344 | + case BANDWIDTH_6_MHZ: | |
| 2345 | + /* (64/7)*(6/8)*1000000 */ | |
| 2346 | + bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ; | |
| 2347 | + bandwidthParam = 0x0F07; /*binary: 0000 1111 0000 0111 */ | |
| 2348 | + status = Write16(state, | |
| 2349 | + FE_AG_REG_IND_DEL__A, 71, 0x0000); | |
| 2350 | + break; | |
| 2351 | + default: | |
| 2352 | + status = -EINVAL; | |
| 2353 | + } | |
| 2354 | + if (status < 0) | |
| 2355 | + break; | |
| 2356 | + | |
| 2357 | + status = Write16(state, SC_RA_RAM_BAND__A, bandwidthParam, 0x0000); | |
| 2358 | + if (status < 0) | |
| 2359 | + break; | |
| 2360 | + | |
| 2361 | + { | |
| 2362 | + u16 sc_config; | |
| 2363 | + status = Read16(state, SC_RA_RAM_CONFIG__A, &sc_config, 0); | |
| 2364 | + if (status < 0) | |
| 2365 | + break; | |
| 2366 | + | |
| 2367 | + /* enable SLAVE mode in 2k 1/32 to | |
| 2368 | + prevent timing change glitches */ | |
| 2369 | + if ((p->transmission_mode == TRANSMISSION_MODE_2K) && | |
| 2370 | + (p->guard_interval == GUARD_INTERVAL_1_32)) { | |
| 2371 | + /* enable slave */ | |
| 2372 | + sc_config |= SC_RA_RAM_CONFIG_SLAVE__M; | |
| 2373 | + } else { | |
| 2374 | + /* disable slave */ | |
| 2375 | + sc_config &= ~SC_RA_RAM_CONFIG_SLAVE__M; | |
| 2376 | + } | |
| 2377 | + status = Write16(state, SC_RA_RAM_CONFIG__A, sc_config, 0); | |
| 2378 | + if (status < 0) | |
| 2379 | + break; | |
| 2380 | + } | |
| 2381 | + | |
| 2382 | + status = SetCfgNoiseCalibration(state, &state->noise_cal); | |
| 2383 | + if (status < 0) | |
| 2384 | + break; | |
| 2385 | + | |
| 2386 | + if (state->cscd_state == CSCD_INIT) { | |
| 2387 | + /* switch on SRMM scan in SC */ | |
| 2388 | + status = Write16(state, SC_RA_RAM_SAMPLE_RATE_COUNT__A, DRXD_OSCDEV_DO_SCAN, 0x0000); | |
| 2389 | + if (status < 0) | |
| 2390 | + break; | |
| 2391 | +/* CHK_ERROR(Write16(SC_RA_RAM_SAMPLE_RATE_STEP__A, DRXD_OSCDEV_STEP, 0x0000));*/ | |
| 2392 | + state->cscd_state = CSCD_SET; | |
| 2393 | + } | |
| 2394 | + | |
| 2395 | + /* Now compute FE_IF_REG_INCR */ | |
| 2396 | + /*((( SysFreq/BandWidth)/2)/2) -1) * 2^23) => | |
| 2397 | + ((SysFreq / BandWidth) * (2^21) ) - (2^23) */ | |
| 2398 | + feIfIncr = MulDiv32(state->sys_clock_freq * 1000, | |
| 2399 | + (1ULL << 21), bandwidth) - (1 << 23); | |
| 2400 | + status = Write16(state, FE_IF_REG_INCR0__A, (u16) (feIfIncr & FE_IF_REG_INCR0__M), 0x0000); | |
| 2401 | + if (status < 0) | |
| 2402 | + break; | |
| 2403 | + status = Write16(state, FE_IF_REG_INCR1__A, (u16) ((feIfIncr >> FE_IF_REG_INCR0__W) & FE_IF_REG_INCR1__M), 0x0000); | |
| 2404 | + if (status < 0) | |
| 2405 | + break; | |
| 2406 | + /* Bandwidth setting done */ | |
| 2407 | + | |
| 2408 | + /* Mirror & frequency offset */ | |
| 2409 | + SetFrequencyShift(state, off, mirrorFreqSpect); | |
| 2410 | + | |
| 2411 | + /* Start SC, write channel settings to SC */ | |
| 2412 | + | |
| 2413 | + /* Enable SC after setting all other parameters */ | |
| 2414 | + status = Write16(state, SC_COMM_STATE__A, 0, 0x0000); | |
| 2415 | + if (status < 0) | |
| 2416 | + break; | |
| 2417 | + status = Write16(state, SC_COMM_EXEC__A, 1, 0x0000); | |
| 2418 | + if (status < 0) | |
| 2419 | + break; | |
| 2420 | + | |
| 2421 | + /* Write SC parameter registers, operation mode */ | |
| 2422 | +#if 1 | |
| 2423 | + operationMode = (SC_RA_RAM_OP_AUTO_MODE__M | | |
| 2424 | + SC_RA_RAM_OP_AUTO_GUARD__M | | |
| 2425 | + SC_RA_RAM_OP_AUTO_CONST__M | | |
| 2426 | + SC_RA_RAM_OP_AUTO_HIER__M | | |
| 2427 | + SC_RA_RAM_OP_AUTO_RATE__M); | |
| 2428 | +#endif | |
| 2429 | + status = SC_SetPrefParamCommand(state, 0x0000, transmissionParams, operationMode); | |
| 2430 | + if (status < 0) | |
| 2431 | + break; | |
| 2432 | + | |
| 2433 | + /* Start correct processes to get in lock */ | |
| 2434 | + status = SC_ProcStartCommand(state, SC_RA_RAM_PROC_LOCKTRACK, SC_RA_RAM_SW_EVENT_RUN_NMASK__M, SC_RA_RAM_LOCKTRACK_MIN); | |
| 2435 | + if (status < 0) | |
| 2436 | + break; | |
| 2437 | + | |
| 2438 | + status = StartOC(state); | |
| 2439 | + if (status < 0) | |
| 2440 | + break; | |
| 2441 | + | |
| 2442 | + if (state->operation_mode != OM_Default) { | |
| 2443 | + status = StartDiversity(state); | |
| 2444 | + if (status < 0) | |
| 2445 | + break; | |
| 2446 | + } | |
| 2447 | + | |
| 2448 | + state->drxd_state = DRXD_STARTED; | |
| 2449 | + } while (0); | |
| 2450 | + | |
| 2451 | + return status; | |
| 2452 | +} | |
| 2453 | + | |
| 2454 | +static int CDRXD(struct drxd_state *state, u32 IntermediateFrequency) | |
| 2455 | +{ | |
| 2456 | + u32 ulRfAgcOutputLevel = 0xffffffff; | |
| 2457 | + u32 ulRfAgcSettleLevel = 528; /* Optimum value for MT2060 */ | |
| 2458 | + u32 ulRfAgcMinLevel = 0; /* Currently unused */ | |
| 2459 | + u32 ulRfAgcMaxLevel = DRXD_FE_CTRL_MAX; /* Currently unused */ | |
| 2460 | + u32 ulRfAgcSpeed = 0; /* Currently unused */ | |
| 2461 | + u32 ulRfAgcMode = 0; /*2; Off */ | |
| 2462 | + u32 ulRfAgcR1 = 820; | |
| 2463 | + u32 ulRfAgcR2 = 2200; | |
| 2464 | + u32 ulRfAgcR3 = 150; | |
| 2465 | + u32 ulIfAgcMode = 0; /* Auto */ | |
| 2466 | + u32 ulIfAgcOutputLevel = 0xffffffff; | |
| 2467 | + u32 ulIfAgcSettleLevel = 0xffffffff; | |
| 2468 | + u32 ulIfAgcMinLevel = 0xffffffff; | |
| 2469 | + u32 ulIfAgcMaxLevel = 0xffffffff; | |
| 2470 | + u32 ulIfAgcSpeed = 0xffffffff; | |
| 2471 | + u32 ulIfAgcR1 = 820; | |
| 2472 | + u32 ulIfAgcR2 = 2200; | |
| 2473 | + u32 ulIfAgcR3 = 150; | |
| 2474 | + u32 ulClock = state->config.clock; | |
| 2475 | + u32 ulSerialMode = 0; | |
| 2476 | + u32 ulEcOcRegOcModeLop = 4; /* Dynamic DTO source */ | |
| 2477 | + u32 ulHiI2cDelay = HI_I2C_DELAY; | |
| 2478 | + u32 ulHiI2cBridgeDelay = HI_I2C_BRIDGE_DELAY; | |
| 2479 | + u32 ulHiI2cPatch = 0; | |
| 2480 | + u32 ulEnvironment = APPENV_PORTABLE; | |
| 2481 | + u32 ulEnvironmentDiversity = APPENV_MOBILE; | |
| 2482 | + u32 ulIFFilter = IFFILTER_SAW; | |
| 2483 | + | |
| 2484 | + state->if_agc_cfg.ctrlMode = AGC_CTRL_AUTO; | |
| 2485 | + state->if_agc_cfg.outputLevel = 0; | |
| 2486 | + state->if_agc_cfg.settleLevel = 140; | |
| 2487 | + state->if_agc_cfg.minOutputLevel = 0; | |
| 2488 | + state->if_agc_cfg.maxOutputLevel = 1023; | |
| 2489 | + state->if_agc_cfg.speed = 904; | |
| 2490 | + | |
| 2491 | + if (ulIfAgcMode == 1 && ulIfAgcOutputLevel <= DRXD_FE_CTRL_MAX) { | |
| 2492 | + state->if_agc_cfg.ctrlMode = AGC_CTRL_USER; | |
| 2493 | + state->if_agc_cfg.outputLevel = (u16) (ulIfAgcOutputLevel); | |
| 2494 | + } | |
| 2495 | + | |
| 2496 | + if (ulIfAgcMode == 0 && | |
| 2497 | + ulIfAgcSettleLevel <= DRXD_FE_CTRL_MAX && | |
| 2498 | + ulIfAgcMinLevel <= DRXD_FE_CTRL_MAX && | |
| 2499 | + ulIfAgcMaxLevel <= DRXD_FE_CTRL_MAX && | |
| 2500 | + ulIfAgcSpeed <= DRXD_FE_CTRL_MAX) { | |
| 2501 | + state->if_agc_cfg.ctrlMode = AGC_CTRL_AUTO; | |
| 2502 | + state->if_agc_cfg.settleLevel = (u16) (ulIfAgcSettleLevel); | |
| 2503 | + state->if_agc_cfg.minOutputLevel = (u16) (ulIfAgcMinLevel); | |
| 2504 | + state->if_agc_cfg.maxOutputLevel = (u16) (ulIfAgcMaxLevel); | |
| 2505 | + state->if_agc_cfg.speed = (u16) (ulIfAgcSpeed); | |
| 2506 | + } | |
| 2507 | + | |
| 2508 | + state->if_agc_cfg.R1 = (u16) (ulIfAgcR1); | |
| 2509 | + state->if_agc_cfg.R2 = (u16) (ulIfAgcR2); | |
| 2510 | + state->if_agc_cfg.R3 = (u16) (ulIfAgcR3); | |
| 2511 | + | |
| 2512 | + state->rf_agc_cfg.R1 = (u16) (ulRfAgcR1); | |
| 2513 | + state->rf_agc_cfg.R2 = (u16) (ulRfAgcR2); | |
| 2514 | + state->rf_agc_cfg.R3 = (u16) (ulRfAgcR3); | |
| 2515 | + | |
| 2516 | + state->rf_agc_cfg.ctrlMode = AGC_CTRL_AUTO; | |
| 2517 | + /* rest of the RFAgcCfg structure currently unused */ | |
| 2518 | + if (ulRfAgcMode == 1 && ulRfAgcOutputLevel <= DRXD_FE_CTRL_MAX) { | |
| 2519 | + state->rf_agc_cfg.ctrlMode = AGC_CTRL_USER; | |
| 2520 | + state->rf_agc_cfg.outputLevel = (u16) (ulRfAgcOutputLevel); | |
| 2521 | + } | |
| 2522 | + | |
| 2523 | + if (ulRfAgcMode == 0 && | |
| 2524 | + ulRfAgcSettleLevel <= DRXD_FE_CTRL_MAX && | |
| 2525 | + ulRfAgcMinLevel <= DRXD_FE_CTRL_MAX && | |
| 2526 | + ulRfAgcMaxLevel <= DRXD_FE_CTRL_MAX && | |
| 2527 | + ulRfAgcSpeed <= DRXD_FE_CTRL_MAX) { | |
| 2528 | + state->rf_agc_cfg.ctrlMode = AGC_CTRL_AUTO; | |
| 2529 | + state->rf_agc_cfg.settleLevel = (u16) (ulRfAgcSettleLevel); | |
| 2530 | + state->rf_agc_cfg.minOutputLevel = (u16) (ulRfAgcMinLevel); | |
| 2531 | + state->rf_agc_cfg.maxOutputLevel = (u16) (ulRfAgcMaxLevel); | |
| 2532 | + state->rf_agc_cfg.speed = (u16) (ulRfAgcSpeed); | |
| 2533 | + } | |
| 2534 | + | |
| 2535 | + if (ulRfAgcMode == 2) | |
| 2536 | + state->rf_agc_cfg.ctrlMode = AGC_CTRL_OFF; | |
| 2537 | + | |
| 2538 | + if (ulEnvironment <= 2) | |
| 2539 | + state->app_env_default = (enum app_env) | |
| 2540 | + (ulEnvironment); | |
| 2541 | + if (ulEnvironmentDiversity <= 2) | |
| 2542 | + state->app_env_diversity = (enum app_env) | |
| 2543 | + (ulEnvironmentDiversity); | |
| 2544 | + | |
| 2545 | + if (ulIFFilter == IFFILTER_DISCRETE) { | |
| 2546 | + /* discrete filter */ | |
| 2547 | + state->noise_cal.cpOpt = 0; | |
| 2548 | + state->noise_cal.cpNexpOfs = 40; | |
| 2549 | + state->noise_cal.tdCal2k = -40; | |
| 2550 | + state->noise_cal.tdCal8k = -24; | |
| 2551 | + } else { | |
| 2552 | + /* SAW filter */ | |
| 2553 | + state->noise_cal.cpOpt = 1; | |
| 2554 | + state->noise_cal.cpNexpOfs = 0; | |
| 2555 | + state->noise_cal.tdCal2k = -21; | |
| 2556 | + state->noise_cal.tdCal8k = -24; | |
| 2557 | + } | |
| 2558 | + state->m_EcOcRegOcModeLop = (u16) (ulEcOcRegOcModeLop); | |
| 2559 | + | |
| 2560 | + state->chip_adr = (state->config.demod_address << 1) | 1; | |
| 2561 | + switch (ulHiI2cPatch) { | |
| 2562 | + case 1: | |
| 2563 | + state->m_HiI2cPatch = DRXD_HiI2cPatch_1; | |
| 2564 | + break; | |
| 2565 | + case 3: | |
| 2566 | + state->m_HiI2cPatch = DRXD_HiI2cPatch_3; | |
| 2567 | + break; | |
| 2568 | + default: | |
| 2569 | + state->m_HiI2cPatch = NULL; | |
| 2570 | + } | |
| 2571 | + | |
| 2572 | + /* modify tuner and clock attributes */ | |
| 2573 | + state->intermediate_freq = (u16) (IntermediateFrequency / 1000); | |
| 2574 | + /* expected system clock frequency in kHz */ | |
| 2575 | + state->expected_sys_clock_freq = 48000; | |
| 2576 | + /* real system clock frequency in kHz */ | |
| 2577 | + state->sys_clock_freq = 48000; | |
| 2578 | + state->osc_clock_freq = (u16) ulClock; | |
| 2579 | + state->osc_clock_deviation = 0; | |
| 2580 | + state->cscd_state = CSCD_INIT; | |
| 2581 | + state->drxd_state = DRXD_UNINITIALIZED; | |
| 2582 | + | |
| 2583 | + state->PGA = 0; | |
| 2584 | + state->type_A = 0; | |
| 2585 | + state->tuner_mirrors = 0; | |
| 2586 | + | |
| 2587 | + /* modify MPEG output attributes */ | |
| 2588 | + state->insert_rs_byte = state->config.insert_rs_byte; | |
| 2589 | + state->enable_parallel = (ulSerialMode != 1); | |
| 2590 | + | |
| 2591 | + /* Timing div, 250ns/Psys */ | |
| 2592 | + /* Timing div, = ( delay (nano seconds) * sysclk (kHz) )/ 1000 */ | |
| 2593 | + | |
| 2594 | + state->hi_cfg_timing_div = (u16) ((state->sys_clock_freq / 1000) * | |
| 2595 | + ulHiI2cDelay) / 1000; | |
| 2596 | + /* Bridge delay, uses oscilator clock */ | |
| 2597 | + /* Delay = ( delay (nano seconds) * oscclk (kHz) )/ 1000 */ | |
| 2598 | + state->hi_cfg_bridge_delay = (u16) ((state->osc_clock_freq / 1000) * | |
| 2599 | + ulHiI2cBridgeDelay) / 1000; | |
| 2600 | + | |
| 2601 | + state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_CONSUMER; | |
| 2602 | + /* state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_PRO; */ | |
| 2603 | + state->m_FeAgRegAgAgcSio = DRXD_DEF_AG_AGC_SIO; | |
| 2604 | + return 0; | |
| 2605 | +} | |
| 2606 | + | |
| 2607 | +int DRXD_init(struct drxd_state *state, const u8 * fw, u32 fw_size) | |
| 2608 | +{ | |
| 2609 | + int status = 0; | |
| 2610 | + u32 driverVersion; | |
| 2611 | + | |
| 2612 | + if (state->init_done) | |
| 2613 | + return 0; | |
| 2614 | + | |
| 2615 | + CDRXD(state, state->config.IF ? state->config.IF : 36000000); | |
| 2616 | + | |
| 2617 | + do { | |
| 2618 | + state->operation_mode = OM_Default; | |
| 2619 | + | |
| 2620 | + status = SetDeviceTypeId(state); | |
| 2621 | + if (status < 0) | |
| 2622 | + break; | |
| 2623 | + | |
| 2624 | + /* Apply I2c address patch to B1 */ | |
| 2625 | + if (!state->type_A && state->m_HiI2cPatch != NULL) | |
| 2626 | + status = WriteTable(state, state->m_HiI2cPatch); | |
| 2627 | + if (status < 0) | |
| 2628 | + break; | |
| 2629 | + | |
| 2630 | + if (state->type_A) { | |
| 2631 | + /* HI firmware patch for UIO readout, | |
| 2632 | + avoid clearing of result register */ | |
| 2633 | + status = Write16(state, 0x43012D, 0x047f, 0); | |
| 2634 | + if (status < 0) | |
| 2635 | + break; | |
| 2636 | + } | |
| 2637 | + | |
| 2638 | + status = HI_ResetCommand(state); | |
| 2639 | + if (status < 0) | |
| 2640 | + break; | |
| 2641 | + | |
| 2642 | + status = StopAllProcessors(state); | |
| 2643 | + if (status < 0) | |
| 2644 | + break; | |
| 2645 | + status = InitCC(state); | |
| 2646 | + if (status < 0) | |
| 2647 | + break; | |
| 2648 | + | |
| 2649 | + state->osc_clock_deviation = 0; | |
| 2650 | + | |
| 2651 | + if (state->config.osc_deviation) | |
| 2652 | + state->osc_clock_deviation = | |
| 2653 | + state->config.osc_deviation(state->priv, 0, 0); | |
| 2654 | + { | |
| 2655 | + /* Handle clock deviation */ | |
| 2656 | + s32 devB; | |
| 2657 | + s32 devA = (s32) (state->osc_clock_deviation) * | |
| 2658 | + (s32) (state->expected_sys_clock_freq); | |
| 2659 | + /* deviation in kHz */ | |
| 2660 | + s32 deviation = (devA / (1000000L)); | |
| 2661 | + /* rounding, signed */ | |
| 2662 | + if (devA > 0) | |
| 2663 | + devB = (2); | |
| 2664 | + else | |
| 2665 | + devB = (-2); | |
| 2666 | + if ((devB * (devA % 1000000L) > 1000000L)) { | |
| 2667 | + /* add +1 or -1 */ | |
| 2668 | + deviation += (devB / 2); | |
| 2669 | + } | |
| 2670 | + | |
| 2671 | + state->sys_clock_freq = | |
| 2672 | + (u16) ((state->expected_sys_clock_freq) + | |
| 2673 | + deviation); | |
| 2674 | + } | |
| 2675 | + status = InitHI(state); | |
| 2676 | + if (status < 0) | |
| 2677 | + break; | |
| 2678 | + status = InitAtomicRead(state); | |
| 2679 | + if (status < 0) | |
| 2680 | + break; | |
| 2681 | + | |
| 2682 | + status = EnableAndResetMB(state); | |
| 2683 | + if (status < 0) | |
| 2684 | + break; | |
| 2685 | + if (state->type_A) | |
| 2686 | + status = ResetCEFR(state); | |
| 2687 | + if (status < 0) | |
| 2688 | + break; | |
| 2689 | + | |
| 2690 | + if (fw) { | |
| 2691 | + status = DownloadMicrocode(state, fw, fw_size); | |
| 2692 | + if (status < 0) | |
| 2693 | + break; | |
| 2694 | + } else { | |
| 2695 | + status = DownloadMicrocode(state, state->microcode, state->microcode_length); | |
| 2696 | + if (status < 0) | |
| 2697 | + break; | |
| 2698 | + } | |
| 2699 | + | |
| 2700 | + if (state->PGA) { | |
| 2701 | + state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_PRO; | |
| 2702 | + SetCfgPga(state, 0); /* PGA = 0 dB */ | |
| 2703 | + } else { | |
| 2704 | + state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_CONSUMER; | |
| 2705 | + } | |
| 2706 | + | |
| 2707 | + state->m_FeAgRegAgAgcSio = DRXD_DEF_AG_AGC_SIO; | |
| 2708 | + | |
| 2709 | + status = InitFE(state); | |
| 2710 | + if (status < 0) | |
| 2711 | + break; | |
| 2712 | + status = InitFT(state); | |
| 2713 | + if (status < 0) | |
| 2714 | + break; | |
| 2715 | + status = InitCP(state); | |
| 2716 | + if (status < 0) | |
| 2717 | + break; | |
| 2718 | + status = InitCE(state); | |
| 2719 | + if (status < 0) | |
| 2720 | + break; | |
| 2721 | + status = InitEQ(state); | |
| 2722 | + if (status < 0) | |
| 2723 | + break; | |
| 2724 | + status = InitEC(state); | |
| 2725 | + if (status < 0) | |
| 2726 | + break; | |
| 2727 | + status = InitSC(state); | |
| 2728 | + if (status < 0) | |
| 2729 | + break; | |
| 2730 | + | |
| 2731 | + status = SetCfgIfAgc(state, &state->if_agc_cfg); | |
| 2732 | + if (status < 0) | |
| 2733 | + break; | |
| 2734 | + status = SetCfgRfAgc(state, &state->rf_agc_cfg); | |
| 2735 | + if (status < 0) | |
| 2736 | + break; | |
| 2737 | + | |
| 2738 | + state->cscd_state = CSCD_INIT; | |
| 2739 | + status = Write16(state, SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | |
| 2740 | + if (status < 0) | |
| 2741 | + break; | |
| 2742 | + status = Write16(state, LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0); | |
| 2743 | + if (status < 0) | |
| 2744 | + break; | |
| 2745 | + | |
| 2746 | + driverVersion = (((VERSION_MAJOR / 10) << 4) + | |
| 2747 | + (VERSION_MAJOR % 10)) << 24; | |
| 2748 | + driverVersion += (((VERSION_MINOR / 10) << 4) + | |
| 2749 | + (VERSION_MINOR % 10)) << 16; | |
| 2750 | + driverVersion += ((VERSION_PATCH / 1000) << 12) + | |
| 2751 | + ((VERSION_PATCH / 100) << 8) + | |
| 2752 | + ((VERSION_PATCH / 10) << 4) + (VERSION_PATCH % 10); | |
| 2753 | + | |
| 2754 | + status = Write32(state, SC_RA_RAM_DRIVER_VERSION__AX, driverVersion, 0); | |
| 2755 | + if (status < 0) | |
| 2756 | + break; | |
| 2757 | + | |
| 2758 | + status = StopOC(state); | |
| 2759 | + if (status < 0) | |
| 2760 | + break; | |
| 2761 | + | |
| 2762 | + state->drxd_state = DRXD_STOPPED; | |
| 2763 | + state->init_done = 1; | |
| 2764 | + status = 0; | |
| 2765 | + } while (0); | |
| 2766 | + return status; | |
| 2767 | +} | |
| 2768 | + | |
| 2769 | +int DRXD_status(struct drxd_state *state, u32 * pLockStatus) | |
| 2770 | +{ | |
| 2771 | + DRX_GetLockStatus(state, pLockStatus); | |
| 2772 | + | |
| 2773 | + /*if (*pLockStatus&DRX_LOCK_MPEG) */ | |
| 2774 | + if (*pLockStatus & DRX_LOCK_FEC) { | |
| 2775 | + ConfigureMPEGOutput(state, 1); | |
| 2776 | + /* Get status again, in case we have MPEG lock now */ | |
| 2777 | + /*DRX_GetLockStatus(state, pLockStatus); */ | |
| 2778 | + } | |
| 2779 | + | |
| 2780 | + return 0; | |
| 2781 | +} | |
| 2782 | + | |
| 2783 | +/****************************************************************************/ | |
| 2784 | +/****************************************************************************/ | |
| 2785 | +/****************************************************************************/ | |
| 2786 | + | |
| 2787 | +static int drxd_read_signal_strength(struct dvb_frontend *fe, u16 * strength) | |
| 2788 | +{ | |
| 2789 | + struct drxd_state *state = fe->demodulator_priv; | |
| 2790 | + u32 value; | |
| 2791 | + int res; | |
| 2792 | + | |
| 2793 | + res = ReadIFAgc(state, &value); | |
| 2794 | + if (res < 0) | |
| 2795 | + *strength = 0; | |
| 2796 | + else | |
| 2797 | + *strength = 0xffff - (value << 4); | |
| 2798 | + return 0; | |
| 2799 | +} | |
| 2800 | + | |
| 2801 | +static int drxd_read_status(struct dvb_frontend *fe, fe_status_t * status) | |
| 2802 | +{ | |
| 2803 | + struct drxd_state *state = fe->demodulator_priv; | |
| 2804 | + u32 lock; | |
| 2805 | + | |
| 2806 | + DRXD_status(state, &lock); | |
| 2807 | + *status = 0; | |
| 2808 | + /* No MPEG lock in V255 firmware, bug ? */ | |
| 2809 | +#if 1 | |
| 2810 | + if (lock & DRX_LOCK_MPEG) | |
| 2811 | + *status |= FE_HAS_LOCK; | |
| 2812 | +#else | |
| 2813 | + if (lock & DRX_LOCK_FEC) | |
| 2814 | + *status |= FE_HAS_LOCK; | |
| 2815 | +#endif | |
| 2816 | + if (lock & DRX_LOCK_FEC) | |
| 2817 | + *status |= FE_HAS_VITERBI | FE_HAS_SYNC; | |
| 2818 | + if (lock & DRX_LOCK_DEMOD) | |
| 2819 | + *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; | |
| 2820 | + | |
| 2821 | + return 0; | |
| 2822 | +} | |
| 2823 | + | |
| 2824 | +static int drxd_init(struct dvb_frontend *fe) | |
| 2825 | +{ | |
| 2826 | + struct drxd_state *state = fe->demodulator_priv; | |
| 2827 | + int err = 0; | |
| 2828 | + | |
| 2829 | +/* if (request_firmware(&state->fw, "drxd.fw", state->dev)<0) */ | |
| 2830 | + return DRXD_init(state, 0, 0); | |
| 2831 | + | |
| 2832 | + err = DRXD_init(state, state->fw->data, state->fw->size); | |
| 2833 | + release_firmware(state->fw); | |
| 2834 | + return err; | |
| 2835 | +} | |
| 2836 | + | |
| 2837 | +int drxd_config_i2c(struct dvb_frontend *fe, int onoff) | |
| 2838 | +{ | |
| 2839 | + struct drxd_state *state = fe->demodulator_priv; | |
| 2840 | + | |
| 2841 | + if (state->config.disable_i2c_gate_ctrl == 1) | |
| 2842 | + return 0; | |
| 2843 | + | |
| 2844 | + return DRX_ConfigureI2CBridge(state, onoff); | |
| 2845 | +} | |
| 2846 | +EXPORT_SYMBOL(drxd_config_i2c); | |
| 2847 | + | |
| 2848 | +static int drxd_get_tune_settings(struct dvb_frontend *fe, | |
| 2849 | + struct dvb_frontend_tune_settings *sets) | |
| 2850 | +{ | |
| 2851 | + sets->min_delay_ms = 10000; | |
| 2852 | + sets->max_drift = 0; | |
| 2853 | + sets->step_size = 0; | |
| 2854 | + return 0; | |
| 2855 | +} | |
| 2856 | + | |
| 2857 | +static int drxd_read_ber(struct dvb_frontend *fe, u32 * ber) | |
| 2858 | +{ | |
| 2859 | + *ber = 0; | |
| 2860 | + return 0; | |
| 2861 | +} | |
| 2862 | + | |
| 2863 | +static int drxd_read_snr(struct dvb_frontend *fe, u16 * snr) | |
| 2864 | +{ | |
| 2865 | + *snr = 0; | |
| 2866 | + return 0; | |
| 2867 | +} | |
| 2868 | + | |
| 2869 | +static int drxd_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks) | |
| 2870 | +{ | |
| 2871 | + *ucblocks = 0; | |
| 2872 | + return 0; | |
| 2873 | +} | |
| 2874 | + | |
| 2875 | +static int drxd_sleep(struct dvb_frontend *fe) | |
| 2876 | +{ | |
| 2877 | + struct drxd_state *state = fe->demodulator_priv; | |
| 2878 | + | |
| 2879 | + ConfigureMPEGOutput(state, 0); | |
| 2880 | + return 0; | |
| 2881 | +} | |
| 2882 | + | |
| 2883 | +static int drxd_get_frontend(struct dvb_frontend *fe, | |
| 2884 | + struct dvb_frontend_parameters *param) | |
| 2885 | +{ | |
| 2886 | + return 0; | |
| 2887 | +} | |
| 2888 | + | |
| 2889 | +static int drxd_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | |
| 2890 | +{ | |
| 2891 | + return drxd_config_i2c(fe, enable); | |
| 2892 | +} | |
| 2893 | + | |
| 2894 | +static int drxd_set_frontend(struct dvb_frontend *fe, | |
| 2895 | + struct dvb_frontend_parameters *param) | |
| 2896 | +{ | |
| 2897 | + struct drxd_state *state = fe->demodulator_priv; | |
| 2898 | + s32 off = 0; | |
| 2899 | + | |
| 2900 | + state->param = *param; | |
| 2901 | + DRX_Stop(state); | |
| 2902 | + | |
| 2903 | + if (fe->ops.tuner_ops.set_params) { | |
| 2904 | + fe->ops.tuner_ops.set_params(fe, param); | |
| 2905 | + if (fe->ops.i2c_gate_ctrl) | |
| 2906 | + fe->ops.i2c_gate_ctrl(fe, 0); | |
| 2907 | + } | |
| 2908 | + | |
| 2909 | + /* FIXME: move PLL drivers */ | |
| 2910 | + if (state->config.pll_set && | |
| 2911 | + state->config.pll_set(state->priv, param, | |
| 2912 | + state->config.pll_address, | |
| 2913 | + state->config.demoda_address, &off) < 0) { | |
| 2914 | + printk(KERN_ERR "Error in pll_set\n"); | |
| 2915 | + return -1; | |
| 2916 | + } | |
| 2917 | + | |
| 2918 | + msleep(200); | |
| 2919 | + | |
| 2920 | + return DRX_Start(state, off); | |
| 2921 | +} | |
| 2922 | + | |
| 2923 | +static void drxd_release(struct dvb_frontend *fe) | |
| 2924 | +{ | |
| 2925 | + struct drxd_state *state = fe->demodulator_priv; | |
| 2926 | + | |
| 2927 | + kfree(state); | |
| 2928 | +} | |
| 2929 | + | |
| 2930 | +static struct dvb_frontend_ops drxd_ops = { | |
| 2931 | + | |
| 2932 | + .info = { | |
| 2933 | + .name = "Micronas DRXD DVB-T", | |
| 2934 | + .type = FE_OFDM, | |
| 2935 | + .frequency_min = 47125000, | |
| 2936 | + .frequency_max = 855250000, | |
| 2937 | + .frequency_stepsize = 166667, | |
| 2938 | + .frequency_tolerance = 0, | |
| 2939 | + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | | |
| 2940 | + FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | | |
| 2941 | + FE_CAN_FEC_AUTO | | |
| 2942 | + FE_CAN_QAM_16 | FE_CAN_QAM_64 | | |
| 2943 | + FE_CAN_QAM_AUTO | | |
| 2944 | + FE_CAN_TRANSMISSION_MODE_AUTO | | |
| 2945 | + FE_CAN_GUARD_INTERVAL_AUTO | | |
| 2946 | + FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS}, | |
| 2947 | + | |
| 2948 | + .release = drxd_release, | |
| 2949 | + .init = drxd_init, | |
| 2950 | + .sleep = drxd_sleep, | |
| 2951 | + .i2c_gate_ctrl = drxd_i2c_gate_ctrl, | |
| 2952 | + | |
| 2953 | + .set_frontend = drxd_set_frontend, | |
| 2954 | + .get_frontend = drxd_get_frontend, | |
| 2955 | + .get_tune_settings = drxd_get_tune_settings, | |
| 2956 | + | |
| 2957 | + .read_status = drxd_read_status, | |
| 2958 | + .read_ber = drxd_read_ber, | |
| 2959 | + .read_signal_strength = drxd_read_signal_strength, | |
| 2960 | + .read_snr = drxd_read_snr, | |
| 2961 | + .read_ucblocks = drxd_read_ucblocks, | |
| 2962 | +}; | |
| 2963 | + | |
| 2964 | +struct dvb_frontend *drxd_attach(const struct drxd_config *config, | |
| 2965 | + void *priv, struct i2c_adapter *i2c, | |
| 2966 | + struct device *dev) | |
| 2967 | +{ | |
| 2968 | + struct drxd_state *state = NULL; | |
| 2969 | + | |
| 2970 | + state = kmalloc(sizeof(struct drxd_state), GFP_KERNEL); | |
| 2971 | + if (!state) | |
| 2972 | + return NULL; | |
| 2973 | + memset(state, 0, sizeof(*state)); | |
| 2974 | + | |
| 2975 | + memcpy(&state->ops, &drxd_ops, sizeof(struct dvb_frontend_ops)); | |
| 2976 | + state->dev = dev; | |
| 2977 | + state->config = *config; | |
| 2978 | + state->i2c = i2c; | |
| 2979 | + state->priv = priv; | |
| 2980 | + | |
| 2981 | + mutex_init(&state->mutex); | |
| 2982 | + | |
| 2983 | + if (Read16(state, 0, 0, 0) < 0) | |
| 2984 | + goto error; | |
| 2985 | + | |
| 2986 | + memcpy(&state->frontend.ops, &drxd_ops, | |
| 2987 | + sizeof(struct dvb_frontend_ops)); | |
| 2988 | + state->frontend.demodulator_priv = state; | |
| 2989 | + ConfigureMPEGOutput(state, 0); | |
| 2990 | + return &state->frontend; | |
| 2991 | + | |
| 2992 | +error: | |
| 2993 | + printk(KERN_ERR "drxd: not found\n"); | |
| 2994 | + kfree(state); | |
| 2995 | + return NULL; | |
| 2996 | +} | |
| 2997 | +EXPORT_SYMBOL(drxd_attach); | |
| 2998 | + | |
| 2999 | +MODULE_DESCRIPTION("DRXD driver"); | |
| 3000 | +MODULE_AUTHOR("Micronas"); | |
| 3001 | +MODULE_LICENSE("GPL"); | |
| @@ -0,0 +1,1013 @@ | ||
| 1 | +/* | |
| 2 | + * drx3973d_map_firm.h | |
| 3 | + * | |
| 4 | + * Copyright (C) 2006-2007 Micronas | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or | |
| 7 | + * modify it under the terms of the GNU General Public License | |
| 8 | + * version 2 only, as published by the Free Software Foundation. | |
| 9 | + * | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU General Public License | |
| 18 | + * along with this program; if not, write to the Free Software | |
| 19 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| 20 | + * 02110-1301, USA | |
| 21 | + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | |
| 22 | + */ | |
| 23 | + | |
| 24 | +#ifndef __DRX3973D_MAP__H__ | |
| 25 | +#define __DRX3973D_MAP__H__ | |
| 26 | + | |
| 27 | +/* | |
| 28 | + * Note: originally, this file contained 12000+ lines of data | |
| 29 | + * Probably a few lines for every firwmare assembler instruction. However, | |
| 30 | + * only a few defines were actually used. So, removed all uneeded lines. | |
| 31 | + * If ever needed, the other lines can be easily obtained via git history. | |
| 32 | + */ | |
| 33 | + | |
| 34 | +#define HI_COMM_EXEC__A 0x400000 | |
| 35 | +#define HI_COMM_MB__A 0x400002 | |
| 36 | +#define HI_CT_REG_COMM_STATE__A 0x410001 | |
| 37 | +#define HI_RA_RAM_SRV_RES__A 0x420031 | |
| 38 | +#define HI_RA_RAM_SRV_CMD__A 0x420032 | |
| 39 | +#define HI_RA_RAM_SRV_CMD_RESET 0x2 | |
| 40 | +#define HI_RA_RAM_SRV_CMD_CONFIG 0x3 | |
| 41 | +#define HI_RA_RAM_SRV_CMD_EXECUTE 0x6 | |
| 42 | +#define HI_RA_RAM_SRV_RST_KEY__A 0x420033 | |
| 43 | +#define HI_RA_RAM_SRV_RST_KEY_ACT 0x3973 | |
| 44 | +#define HI_RA_RAM_SRV_CFG_KEY__A 0x420033 | |
| 45 | +#define HI_RA_RAM_SRV_CFG_DIV__A 0x420034 | |
| 46 | +#define HI_RA_RAM_SRV_CFG_BDL__A 0x420035 | |
| 47 | +#define HI_RA_RAM_SRV_CFG_WUP__A 0x420036 | |
| 48 | +#define HI_RA_RAM_SRV_CFG_ACT__A 0x420037 | |
| 49 | +#define HI_RA_RAM_SRV_CFG_ACT_SLV0_ON 0x1 | |
| 50 | +#define HI_RA_RAM_SRV_CFG_ACT_BRD__M 0x4 | |
| 51 | +#define HI_RA_RAM_SRV_CFG_ACT_BRD_OFF 0x0 | |
| 52 | +#define HI_RA_RAM_SRV_CFG_ACT_BRD_ON 0x4 | |
| 53 | +#define HI_RA_RAM_SRV_CFG_ACT_PWD_EXE 0x8 | |
| 54 | +#define HI_RA_RAM_USR_BEGIN__A 0x420040 | |
| 55 | +#define HI_IF_RAM_TRP_BPT0__AX 0x430000 | |
| 56 | +#define HI_IF_RAM_USR_BEGIN__A 0x430200 | |
| 57 | +#define SC_COMM_EXEC__A 0x800000 | |
| 58 | +#define SC_COMM_EXEC_CTL_STOP 0x0 | |
| 59 | +#define SC_COMM_STATE__A 0x800001 | |
| 60 | +#define SC_RA_RAM_PARAM0__A 0x820040 | |
| 61 | +#define SC_RA_RAM_PARAM1__A 0x820041 | |
| 62 | +#define SC_RA_RAM_CMD_ADDR__A 0x820042 | |
| 63 | +#define SC_RA_RAM_CMD__A 0x820043 | |
| 64 | +#define SC_RA_RAM_CMD_PROC_START 0x1 | |
| 65 | +#define SC_RA_RAM_CMD_SET_PREF_PARAM 0x3 | |
| 66 | +#define SC_RA_RAM_CMD_GET_OP_PARAM 0x5 | |
| 67 | +#define SC_RA_RAM_SW_EVENT_RUN_NMASK__M 0x1 | |
| 68 | +#define SC_RA_RAM_LOCKTRACK_MIN 0x1 | |
| 69 | +#define SC_RA_RAM_OP_PARAM_MODE_2K 0x0 | |
| 70 | +#define SC_RA_RAM_OP_PARAM_MODE_8K 0x1 | |
| 71 | +#define SC_RA_RAM_OP_PARAM_GUARD_32 0x0 | |
| 72 | +#define SC_RA_RAM_OP_PARAM_GUARD_16 0x4 | |
| 73 | +#define SC_RA_RAM_OP_PARAM_GUARD_8 0x8 | |
| 74 | +#define SC_RA_RAM_OP_PARAM_GUARD_4 0xC | |
| 75 | +#define SC_RA_RAM_OP_PARAM_CONST_QPSK 0x0 | |
| 76 | +#define SC_RA_RAM_OP_PARAM_CONST_QAM16 0x10 | |
| 77 | +#define SC_RA_RAM_OP_PARAM_CONST_QAM64 0x20 | |
| 78 | +#define SC_RA_RAM_OP_PARAM_HIER_NO 0x0 | |
| 79 | +#define SC_RA_RAM_OP_PARAM_HIER_A1 0x40 | |
| 80 | +#define SC_RA_RAM_OP_PARAM_HIER_A2 0x80 | |
| 81 | +#define SC_RA_RAM_OP_PARAM_HIER_A4 0xC0 | |
| 82 | +#define SC_RA_RAM_OP_PARAM_RATE_1_2 0x0 | |
| 83 | +#define SC_RA_RAM_OP_PARAM_RATE_2_3 0x200 | |
| 84 | +#define SC_RA_RAM_OP_PARAM_RATE_3_4 0x400 | |
| 85 | +#define SC_RA_RAM_OP_PARAM_RATE_5_6 0x600 | |
| 86 | +#define SC_RA_RAM_OP_PARAM_RATE_7_8 0x800 | |
| 87 | +#define SC_RA_RAM_OP_PARAM_PRIO_HI 0x0 | |
| 88 | +#define SC_RA_RAM_OP_PARAM_PRIO_LO 0x1000 | |
| 89 | +#define SC_RA_RAM_OP_AUTO_MODE__M 0x1 | |
| 90 | +#define SC_RA_RAM_OP_AUTO_GUARD__M 0x2 | |
| 91 | +#define SC_RA_RAM_OP_AUTO_CONST__M 0x4 | |
| 92 | +#define SC_RA_RAM_OP_AUTO_HIER__M 0x8 | |
| 93 | +#define SC_RA_RAM_OP_AUTO_RATE__M 0x10 | |
| 94 | +#define SC_RA_RAM_LOCK__A 0x82004B | |
| 95 | +#define SC_RA_RAM_LOCK_DEMOD__M 0x1 | |
| 96 | +#define SC_RA_RAM_LOCK_FEC__M 0x2 | |
| 97 | +#define SC_RA_RAM_LOCK_MPEG__M 0x4 | |
| 98 | +#define SC_RA_RAM_BE_OPT_ENA__A 0x82004C | |
| 99 | +#define SC_RA_RAM_BE_OPT_ENA_CP_OPT 0x1 | |
| 100 | +#define SC_RA_RAM_BE_OPT_DELAY__A 0x82004D | |
| 101 | +#define SC_RA_RAM_CONFIG__A 0x820050 | |
| 102 | +#define SC_RA_RAM_CONFIG_FR_ENABLE__M 0x4 | |
| 103 | +#define SC_RA_RAM_CONFIG_FREQSCAN__M 0x10 | |
| 104 | +#define SC_RA_RAM_CONFIG_SLAVE__M 0x20 | |
| 105 | +#define SC_RA_RAM_IF_SAVE__AX 0x82008E | |
| 106 | +#define SC_RA_RAM_IR_COARSE_2K_LENGTH__A 0x8200D1 | |
| 107 | +#define SC_RA_RAM_IR_COARSE_2K_LENGTH__PRE 0x9 | |
| 108 | +#define SC_RA_RAM_IR_COARSE_2K_FREQINC__A 0x8200D2 | |
| 109 | +#define SC_RA_RAM_IR_COARSE_2K_FREQINC__PRE 0x4 | |
| 110 | +#define SC_RA_RAM_IR_COARSE_2K_KAISINC__A 0x8200D3 | |
| 111 | +#define SC_RA_RAM_IR_COARSE_2K_KAISINC__PRE 0x100 | |
| 112 | +#define SC_RA_RAM_IR_COARSE_8K_LENGTH__A 0x8200D4 | |
| 113 | +#define SC_RA_RAM_IR_COARSE_8K_LENGTH__PRE 0x8 | |
| 114 | +#define SC_RA_RAM_IR_COARSE_8K_FREQINC__A 0x8200D5 | |
| 115 | +#define SC_RA_RAM_IR_COARSE_8K_FREQINC__PRE 0x8 | |
| 116 | +#define SC_RA_RAM_IR_COARSE_8K_KAISINC__A 0x8200D6 | |
| 117 | +#define SC_RA_RAM_IR_COARSE_8K_KAISINC__PRE 0x200 | |
| 118 | +#define SC_RA_RAM_IR_FINE_2K_LENGTH__A 0x8200D7 | |
| 119 | +#define SC_RA_RAM_IR_FINE_2K_LENGTH__PRE 0x9 | |
| 120 | +#define SC_RA_RAM_IR_FINE_2K_FREQINC__A 0x8200D8 | |
| 121 | +#define SC_RA_RAM_IR_FINE_2K_FREQINC__PRE 0x4 | |
| 122 | +#define SC_RA_RAM_IR_FINE_2K_KAISINC__A 0x8200D9 | |
| 123 | +#define SC_RA_RAM_IR_FINE_2K_KAISINC__PRE 0x100 | |
| 124 | +#define SC_RA_RAM_IR_FINE_8K_LENGTH__A 0x8200DA | |
| 125 | +#define SC_RA_RAM_IR_FINE_8K_LENGTH__PRE 0xB | |
| 126 | +#define SC_RA_RAM_IR_FINE_8K_FREQINC__A 0x8200DB | |
| 127 | +#define SC_RA_RAM_IR_FINE_8K_FREQINC__PRE 0x1 | |
| 128 | +#define SC_RA_RAM_IR_FINE_8K_KAISINC__A 0x8200DC | |
| 129 | +#define SC_RA_RAM_IR_FINE_8K_KAISINC__PRE 0x40 | |
| 130 | +#define SC_RA_RAM_ECHO_SHIFT_LIM__A 0x8200DD | |
| 131 | +#define SC_RA_RAM_SAMPLE_RATE_COUNT__A 0x8200E8 | |
| 132 | +#define SC_RA_RAM_SAMPLE_RATE_STEP__A 0x8200E9 | |
| 133 | +#define SC_RA_RAM_BAND__A 0x8200EC | |
| 134 | +#define SC_RA_RAM_LC_ABS_2K__A 0x8200F4 | |
| 135 | +#define SC_RA_RAM_LC_ABS_2K__PRE 0x1F | |
| 136 | +#define SC_RA_RAM_LC_ABS_8K__A 0x8200F5 | |
| 137 | +#define SC_RA_RAM_LC_ABS_8K__PRE 0x1F | |
| 138 | +#define SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE 0x1D6 | |
| 139 | +#define SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE 0x4 | |
| 140 | +#define SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE 0x1BB | |
| 141 | +#define SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE 0x5 | |
| 142 | +#define SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE 0x1EF | |
| 143 | +#define SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE 0x5 | |
| 144 | +#define SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE 0x15E | |
| 145 | +#define SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE 0x5 | |
| 146 | +#define SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE 0x11A | |
| 147 | +#define SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE 0x6 | |
| 148 | +#define SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE 0x1FB | |
| 149 | +#define SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE 0x5 | |
| 150 | +#define SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE 0x12F | |
| 151 | +#define SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE 0x5 | |
| 152 | +#define SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE 0x197 | |
| 153 | +#define SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE 0x5 | |
| 154 | +#define SC_RA_RAM_DRIVER_VERSION__AX 0x8201FE | |
| 155 | +#define SC_RA_RAM_PROC_LOCKTRACK 0x0 | |
| 156 | +#define FE_COMM_EXEC__A 0xC00000 | |
| 157 | +#define FE_AD_REG_COMM_EXEC__A 0xC10000 | |
| 158 | +#define FE_AD_REG_FDB_IN__A 0xC10012 | |
| 159 | +#define FE_AD_REG_PD__A 0xC10013 | |
| 160 | +#define FE_AD_REG_INVEXT__A 0xC10014 | |
| 161 | +#define FE_AD_REG_CLKNEG__A 0xC10015 | |
| 162 | +#define FE_AG_REG_COMM_EXEC__A 0xC20000 | |
| 163 | +#define FE_AG_REG_AG_MODE_LOP__A 0xC20010 | |
| 164 | +#define FE_AG_REG_AG_MODE_LOP_MODE_4__M 0x10 | |
| 165 | +#define FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC 0x0 | |
| 166 | +#define FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC 0x10 | |
| 167 | +#define FE_AG_REG_AG_MODE_LOP_MODE_5__M 0x20 | |
| 168 | +#define FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC 0x0 | |
| 169 | +#define FE_AG_REG_AG_MODE_LOP_MODE_C__M 0x1000 | |
| 170 | +#define FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC 0x0 | |
| 171 | +#define FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC 0x1000 | |
| 172 | +#define FE_AG_REG_AG_MODE_LOP_MODE_E__M 0x4000 | |
| 173 | +#define FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC 0x0 | |
| 174 | +#define FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC 0x4000 | |
| 175 | +#define FE_AG_REG_AG_MODE_HIP__A 0xC20011 | |
| 176 | +#define FE_AG_REG_AG_PGA_MODE__A 0xC20012 | |
| 177 | +#define FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN 0x0 | |
| 178 | +#define FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN 0x1 | |
| 179 | +#define FE_AG_REG_AG_AGC_SIO__A 0xC20013 | |
| 180 | +#define FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M 0x2 | |
| 181 | +#define FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT 0x0 | |
| 182 | +#define FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT 0x2 | |
| 183 | +#define FE_AG_REG_AG_PWD__A 0xC20015 | |
| 184 | +#define FE_AG_REG_AG_PWD_PWD_PD2__M 0x2 | |
| 185 | +#define FE_AG_REG_AG_PWD_PWD_PD2_DISABLE 0x0 | |
| 186 | +#define FE_AG_REG_AG_PWD_PWD_PD2_ENABLE 0x2 | |
| 187 | +#define FE_AG_REG_DCE_AUR_CNT__A 0xC20016 | |
| 188 | +#define FE_AG_REG_DCE_RUR_CNT__A 0xC20017 | |
| 189 | +#define FE_AG_REG_ACE_AUR_CNT__A 0xC2001A | |
| 190 | +#define FE_AG_REG_ACE_RUR_CNT__A 0xC2001B | |
| 191 | +#define FE_AG_REG_CDR_RUR_CNT__A 0xC20020 | |
| 192 | +#define FE_AG_REG_EGC_RUR_CNT__A 0xC20024 | |
| 193 | +#define FE_AG_REG_EGC_SET_LVL__A 0xC20025 | |
| 194 | +#define FE_AG_REG_EGC_SET_LVL__M 0x1FF | |
| 195 | +#define FE_AG_REG_EGC_FLA_RGN__A 0xC20026 | |
| 196 | +#define FE_AG_REG_EGC_SLO_RGN__A 0xC20027 | |
| 197 | +#define FE_AG_REG_EGC_JMP_PSN__A 0xC20028 | |
| 198 | +#define FE_AG_REG_EGC_FLA_INC__A 0xC20029 | |
| 199 | +#define FE_AG_REG_EGC_FLA_DEC__A 0xC2002A | |
| 200 | +#define FE_AG_REG_EGC_SLO_INC__A 0xC2002B | |
| 201 | +#define FE_AG_REG_EGC_SLO_DEC__A 0xC2002C | |
| 202 | +#define FE_AG_REG_EGC_FAS_INC__A 0xC2002D | |
| 203 | +#define FE_AG_REG_EGC_FAS_DEC__A 0xC2002E | |
| 204 | +#define FE_AG_REG_PM1_AGC_WRI__A 0xC20030 | |
| 205 | +#define FE_AG_REG_PM1_AGC_WRI__M 0x7FF | |
| 206 | +#define FE_AG_REG_GC1_AGC_RIC__A 0xC20031 | |
| 207 | +#define FE_AG_REG_GC1_AGC_OFF__A 0xC20032 | |
| 208 | +#define FE_AG_REG_GC1_AGC_MAX__A 0xC20033 | |
| 209 | +#define FE_AG_REG_GC1_AGC_MIN__A 0xC20034 | |
| 210 | +#define FE_AG_REG_GC1_AGC_DAT__A 0xC20035 | |
| 211 | +#define FE_AG_REG_GC1_AGC_DAT__M 0x3FF | |
| 212 | +#define FE_AG_REG_PM2_AGC_WRI__A 0xC20036 | |
| 213 | +#define FE_AG_REG_IND_WIN__A 0xC2003C | |
| 214 | +#define FE_AG_REG_IND_THD_LOL__A 0xC2003D | |
| 215 | +#define FE_AG_REG_IND_THD_HIL__A 0xC2003E | |
| 216 | +#define FE_AG_REG_IND_DEL__A 0xC2003F | |
| 217 | +#define FE_AG_REG_IND_PD1_WRI__A 0xC20040 | |
| 218 | +#define FE_AG_REG_PDA_AUR_CNT__A 0xC20041 | |
| 219 | +#define FE_AG_REG_PDA_RUR_CNT__A 0xC20042 | |
| 220 | +#define FE_AG_REG_PDA_AVE_DAT__A 0xC20043 | |
| 221 | +#define FE_AG_REG_PDC_RUR_CNT__A 0xC20044 | |
| 222 | +#define FE_AG_REG_PDC_SET_LVL__A 0xC20045 | |
| 223 | +#define FE_AG_REG_PDC_FLA_RGN__A 0xC20046 | |
| 224 | +#define FE_AG_REG_PDC_JMP_PSN__A 0xC20047 | |
| 225 | +#define FE_AG_REG_PDC_FLA_STP__A 0xC20048 | |
| 226 | +#define FE_AG_REG_PDC_SLO_STP__A 0xC20049 | |
| 227 | +#define FE_AG_REG_PDC_PD2_WRI__A 0xC2004A | |
| 228 | +#define FE_AG_REG_PDC_MAP_DAT__A 0xC2004B | |
| 229 | +#define FE_AG_REG_PDC_MAX__A 0xC2004C | |
| 230 | +#define FE_AG_REG_TGA_AUR_CNT__A 0xC2004D | |
| 231 | +#define FE_AG_REG_TGA_RUR_CNT__A 0xC2004E | |
| 232 | +#define FE_AG_REG_TGA_AVE_DAT__A 0xC2004F | |
| 233 | +#define FE_AG_REG_TGC_RUR_CNT__A 0xC20050 | |
| 234 | +#define FE_AG_REG_TGC_SET_LVL__A 0xC20051 | |
| 235 | +#define FE_AG_REG_TGC_SET_LVL__M 0x3F | |
| 236 | +#define FE_AG_REG_TGC_FLA_RGN__A 0xC20052 | |
| 237 | +#define FE_AG_REG_TGC_JMP_PSN__A 0xC20053 | |
| 238 | +#define FE_AG_REG_TGC_FLA_STP__A 0xC20054 | |
| 239 | +#define FE_AG_REG_TGC_SLO_STP__A 0xC20055 | |
| 240 | +#define FE_AG_REG_TGC_MAP_DAT__A 0xC20056 | |
| 241 | +#define FE_AG_REG_FGA_AUR_CNT__A 0xC20057 | |
| 242 | +#define FE_AG_REG_FGA_RUR_CNT__A 0xC20058 | |
| 243 | +#define FE_AG_REG_FGM_WRI__A 0xC20061 | |
| 244 | +#define FE_AG_REG_BGC_FGC_WRI__A 0xC20068 | |
| 245 | +#define FE_AG_REG_BGC_CGC_WRI__A 0xC20069 | |
| 246 | +#define FE_FS_REG_COMM_EXEC__A 0xC30000 | |
| 247 | +#define FE_FS_REG_ADD_INC_LOP__A 0xC30010 | |
| 248 | +#define FE_FD_REG_COMM_EXEC__A 0xC40000 | |
| 249 | +#define FE_FD_REG_SCL__A 0xC40010 | |
| 250 | +#define FE_FD_REG_MAX_LEV__A 0xC40011 | |
| 251 | +#define FE_FD_REG_NR__A 0xC40012 | |
| 252 | +#define FE_FD_REG_MEAS_VAL__A 0xC40014 | |
| 253 | +#define FE_IF_REG_COMM_EXEC__A 0xC50000 | |
| 254 | +#define FE_IF_REG_INCR0__A 0xC50010 | |
| 255 | +#define FE_IF_REG_INCR0__W 16 | |
| 256 | +#define FE_IF_REG_INCR0__M 0xFFFF | |
| 257 | +#define FE_IF_REG_INCR1__A 0xC50011 | |
| 258 | +#define FE_IF_REG_INCR1__M 0xFF | |
| 259 | +#define FE_CF_REG_COMM_EXEC__A 0xC60000 | |
| 260 | +#define FE_CF_REG_SCL__A 0xC60010 | |
| 261 | +#define FE_CF_REG_MAX_LEV__A 0xC60011 | |
| 262 | +#define FE_CF_REG_NR__A 0xC60012 | |
| 263 | +#define FE_CF_REG_IMP_VAL__A 0xC60013 | |
| 264 | +#define FE_CF_REG_MEAS_VAL__A 0xC60014 | |
| 265 | +#define FE_CU_REG_COMM_EXEC__A 0xC70000 | |
| 266 | +#define FE_CU_REG_FRM_CNT_RST__A 0xC70011 | |
| 267 | +#define FE_CU_REG_FRM_CNT_STR__A 0xC70012 | |
| 268 | +#define FT_COMM_EXEC__A 0x1000000 | |
| 269 | +#define FT_REG_COMM_EXEC__A 0x1010000 | |
| 270 | +#define CP_COMM_EXEC__A 0x1400000 | |
| 271 | +#define CP_REG_COMM_EXEC__A 0x1410000 | |
| 272 | +#define CP_REG_INTERVAL__A 0x1410011 | |
| 273 | +#define CP_REG_BR_SPL_OFFSET__A 0x1410023 | |
| 274 | +#define CP_REG_BR_STR_DEL__A 0x1410024 | |
| 275 | +#define CP_REG_RT_ANG_INC0__A 0x1410030 | |
| 276 | +#define CP_REG_RT_ANG_INC1__A 0x1410031 | |
| 277 | +#define CP_REG_RT_DETECT_ENA__A 0x1410032 | |
| 278 | +#define CP_REG_RT_DETECT_TRH__A 0x1410033 | |
| 279 | +#define CP_REG_RT_EXP_MARG__A 0x141003E | |
| 280 | +#define CP_REG_AC_NEXP_OFFS__A 0x1410040 | |
| 281 | +#define CP_REG_AC_AVER_POW__A 0x1410041 | |
| 282 | +#define CP_REG_AC_MAX_POW__A 0x1410042 | |
| 283 | +#define CP_REG_AC_WEIGHT_MAN__A 0x1410043 | |
| 284 | +#define CP_REG_AC_WEIGHT_EXP__A 0x1410044 | |
| 285 | +#define CP_REG_AC_AMP_MODE__A 0x1410047 | |
| 286 | +#define CP_REG_AC_AMP_FIX__A 0x1410048 | |
| 287 | +#define CP_REG_AC_ANG_MODE__A 0x141004A | |
| 288 | +#define CE_COMM_EXEC__A 0x1800000 | |
| 289 | +#define CE_REG_COMM_EXEC__A 0x1810000 | |
| 290 | +#define CE_REG_TAPSET__A 0x1810011 | |
| 291 | +#define CE_REG_AVG_POW__A 0x1810012 | |
| 292 | +#define CE_REG_MAX_POW__A 0x1810013 | |
| 293 | +#define CE_REG_ATT__A 0x1810014 | |
| 294 | +#define CE_REG_NRED__A 0x1810015 | |
| 295 | +#define CE_REG_NE_ERR_SELECT__A 0x1810043 | |
| 296 | +#define CE_REG_NE_TD_CAL__A 0x1810044 | |
| 297 | +#define CE_REG_NE_MIXAVG__A 0x1810046 | |
| 298 | +#define CE_REG_NE_NUPD_OFS__A 0x1810047 | |
| 299 | +#define CE_REG_PE_NEXP_OFFS__A 0x1810050 | |
| 300 | +#define CE_REG_PE_TIMESHIFT__A 0x1810051 | |
| 301 | +#define CE_REG_TP_A0_TAP_NEW__A 0x1810064 | |
| 302 | +#define CE_REG_TP_A0_TAP_NEW_VALID__A 0x1810065 | |
| 303 | +#define CE_REG_TP_A0_MU_LMS_STEP__A 0x1810066 | |
| 304 | +#define CE_REG_TP_A1_TAP_NEW__A 0x1810068 | |
| 305 | +#define CE_REG_TP_A1_TAP_NEW_VALID__A 0x1810069 | |
| 306 | +#define CE_REG_TP_A1_MU_LMS_STEP__A 0x181006A | |
| 307 | +#define CE_REG_TI_NEXP_OFFS__A 0x1810070 | |
| 308 | +#define CE_REG_FI_SHT_INCR__A 0x1810090 | |
| 309 | +#define CE_REG_FI_EXP_NORM__A 0x1810091 | |
| 310 | +#define CE_REG_IR_INPUTSEL__A 0x18100A0 | |
| 311 | +#define CE_REG_IR_STARTPOS__A 0x18100A1 | |
| 312 | +#define CE_REG_IR_NEXP_THRES__A 0x18100A2 | |
| 313 | +#define CE_REG_FR_TREAL00__A 0x1820010 | |
| 314 | +#define CE_REG_FR_TIMAG00__A 0x1820011 | |
| 315 | +#define CE_REG_FR_TREAL01__A 0x1820012 | |
| 316 | +#define CE_REG_FR_TIMAG01__A 0x1820013 | |
| 317 | +#define CE_REG_FR_TREAL02__A 0x1820014 | |
| 318 | +#define CE_REG_FR_TIMAG02__A 0x1820015 | |
| 319 | +#define CE_REG_FR_TREAL03__A 0x1820016 | |
| 320 | +#define CE_REG_FR_TIMAG03__A 0x1820017 | |
| 321 | +#define CE_REG_FR_TREAL04__A 0x1820018 | |
| 322 | +#define CE_REG_FR_TIMAG04__A 0x1820019 | |
| 323 | +#define CE_REG_FR_TREAL05__A 0x182001A | |
| 324 | +#define CE_REG_FR_TIMAG05__A 0x182001B | |
| 325 | +#define CE_REG_FR_TREAL06__A 0x182001C | |
| 326 | +#define CE_REG_FR_TIMAG06__A 0x182001D | |
| 327 | +#define CE_REG_FR_TREAL07__A 0x182001E | |
| 328 | +#define CE_REG_FR_TIMAG07__A 0x182001F | |
| 329 | +#define CE_REG_FR_TREAL08__A 0x1820020 | |
| 330 | +#define CE_REG_FR_TIMAG08__A 0x1820021 | |
| 331 | +#define CE_REG_FR_TREAL09__A 0x1820022 | |
| 332 | +#define CE_REG_FR_TIMAG09__A 0x1820023 | |
| 333 | +#define CE_REG_FR_TREAL10__A 0x1820024 | |
| 334 | +#define CE_REG_FR_TIMAG10__A 0x1820025 | |
| 335 | +#define CE_REG_FR_TREAL11__A 0x1820026 | |
| 336 | +#define CE_REG_FR_TIMAG11__A 0x1820027 | |
| 337 | +#define CE_REG_FR_MID_TAP__A 0x1820028 | |
| 338 | +#define CE_REG_FR_SQS_G00__A 0x1820029 | |
| 339 | +#define CE_REG_FR_SQS_G01__A 0x182002A | |
| 340 | +#define CE_REG_FR_SQS_G02__A 0x182002B | |
| 341 | +#define CE_REG_FR_SQS_G03__A 0x182002C | |
| 342 | +#define CE_REG_FR_SQS_G04__A 0x182002D | |
| 343 | +#define CE_REG_FR_SQS_G05__A 0x182002E | |
| 344 | +#define CE_REG_FR_SQS_G06__A 0x182002F | |
| 345 | +#define CE_REG_FR_SQS_G07__A 0x1820030 | |
| 346 | +#define CE_REG_FR_SQS_G08__A 0x1820031 | |
| 347 | +#define CE_REG_FR_SQS_G09__A 0x1820032 | |
| 348 | +#define CE_REG_FR_SQS_G10__A 0x1820033 | |
| 349 | +#define CE_REG_FR_SQS_G11__A 0x1820034 | |
| 350 | +#define CE_REG_FR_SQS_G12__A 0x1820035 | |
| 351 | +#define CE_REG_FR_RIO_G00__A 0x1820036 | |
| 352 | +#define CE_REG_FR_RIO_G01__A 0x1820037 | |
| 353 | +#define CE_REG_FR_RIO_G02__A 0x1820038 | |
| 354 | +#define CE_REG_FR_RIO_G03__A 0x1820039 | |
| 355 | +#define CE_REG_FR_RIO_G04__A 0x182003A | |
| 356 | +#define CE_REG_FR_RIO_G05__A 0x182003B | |
| 357 | +#define CE_REG_FR_RIO_G06__A 0x182003C | |
| 358 | +#define CE_REG_FR_RIO_G07__A 0x182003D | |
| 359 | +#define CE_REG_FR_RIO_G08__A 0x182003E | |
| 360 | +#define CE_REG_FR_RIO_G09__A 0x182003F | |
| 361 | +#define CE_REG_FR_RIO_G10__A 0x1820040 | |
| 362 | +#define CE_REG_FR_MODE__A 0x1820041 | |
| 363 | +#define CE_REG_FR_SQS_TRH__A 0x1820042 | |
| 364 | +#define CE_REG_FR_RIO_GAIN__A 0x1820043 | |
| 365 | +#define CE_REG_FR_BYPASS__A 0x1820044 | |
| 366 | +#define CE_REG_FR_PM_SET__A 0x1820045 | |
| 367 | +#define CE_REG_FR_ERR_SH__A 0x1820046 | |
| 368 | +#define CE_REG_FR_MAN_SH__A 0x1820047 | |
| 369 | +#define CE_REG_FR_TAP_SH__A 0x1820048 | |
| 370 | +#define EQ_COMM_EXEC__A 0x1C00000 | |
| 371 | +#define EQ_REG_COMM_EXEC__A 0x1C10000 | |
| 372 | +#define EQ_REG_COMM_MB__A 0x1C10002 | |
| 373 | +#define EQ_REG_IS_GAIN_MAN__A 0x1C10015 | |
| 374 | +#define EQ_REG_IS_GAIN_EXP__A 0x1C10016 | |
| 375 | +#define EQ_REG_IS_CLIP_EXP__A 0x1C10017 | |
| 376 | +#define EQ_REG_SN_CEGAIN__A 0x1C1002A | |
| 377 | +#define EQ_REG_SN_OFFSET__A 0x1C1002B | |
| 378 | +#define EQ_REG_RC_SEL_CAR__A 0x1C10032 | |
| 379 | +#define EQ_REG_RC_SEL_CAR_INIT 0x0 | |
| 380 | +#define EQ_REG_RC_SEL_CAR_DIV_ON 0x1 | |
| 381 | +#define EQ_REG_RC_SEL_CAR_PASS_A_CC 0x0 | |
| 382 | +#define EQ_REG_RC_SEL_CAR_PASS_B_CE 0x2 | |
| 383 | +#define EQ_REG_RC_SEL_CAR_LOCAL_A_CC 0x0 | |
| 384 | +#define EQ_REG_RC_SEL_CAR_LOCAL_B_CE 0x8 | |
| 385 | +#define EQ_REG_RC_SEL_CAR_MEAS_A_CC 0x0 | |
| 386 | +#define EQ_REG_RC_SEL_CAR_MEAS_B_CE 0x20 | |
| 387 | +#define EQ_REG_OT_CONST__A 0x1C10046 | |
| 388 | +#define EQ_REG_OT_ALPHA__A 0x1C10047 | |
| 389 | +#define EQ_REG_OT_QNT_THRES0__A 0x1C10048 | |
| 390 | +#define EQ_REG_OT_QNT_THRES1__A 0x1C10049 | |
| 391 | +#define EQ_REG_OT_CSI_STEP__A 0x1C1004A | |
| 392 | +#define EQ_REG_OT_CSI_OFFSET__A 0x1C1004B | |
| 393 | +#define EQ_REG_TD_REQ_SMB_CNT__A 0x1C10061 | |
| 394 | +#define EQ_REG_TD_TPS_PWR_OFS__A 0x1C10062 | |
| 395 | +#define EC_SB_REG_COMM_EXEC__A 0x2010000 | |
| 396 | +#define EC_SB_REG_TR_MODE__A 0x2010010 | |
| 397 | +#define EC_SB_REG_TR_MODE_8K 0x0 | |
| 398 | +#define EC_SB_REG_TR_MODE_2K 0x1 | |
| 399 | +#define EC_SB_REG_CONST__A 0x2010011 | |
| 400 | +#define EC_SB_REG_CONST_QPSK 0x0 | |
| 401 | +#define EC_SB_REG_CONST_16QAM 0x1 | |
| 402 | +#define EC_SB_REG_CONST_64QAM 0x2 | |
| 403 | +#define EC_SB_REG_ALPHA__A 0x2010012 | |
| 404 | +#define EC_SB_REG_PRIOR__A 0x2010013 | |
| 405 | +#define EC_SB_REG_PRIOR_HI 0x0 | |
| 406 | +#define EC_SB_REG_PRIOR_LO 0x1 | |
| 407 | +#define EC_SB_REG_CSI_HI__A 0x2010014 | |
| 408 | +#define EC_SB_REG_CSI_LO__A 0x2010015 | |
| 409 | +#define EC_SB_REG_SMB_TGL__A 0x2010016 | |
| 410 | +#define EC_SB_REG_SNR_HI__A 0x2010017 | |
| 411 | +#define EC_SB_REG_SNR_MID__A 0x2010018 | |
| 412 | +#define EC_SB_REG_SNR_LO__A 0x2010019 | |
| 413 | +#define EC_SB_REG_SCALE_MSB__A 0x201001A | |
| 414 | +#define EC_SB_REG_SCALE_BIT2__A 0x201001B | |
| 415 | +#define EC_SB_REG_SCALE_LSB__A 0x201001C | |
| 416 | +#define EC_SB_REG_CSI_OFS__A 0x201001D | |
| 417 | +#define EC_VD_REG_COMM_EXEC__A 0x2090000 | |
| 418 | +#define EC_VD_REG_FORCE__A 0x2090010 | |
| 419 | +#define EC_VD_REG_SET_CODERATE__A 0x2090011 | |
| 420 | +#define EC_VD_REG_SET_CODERATE_C1_2 0x0 | |
| 421 | +#define EC_VD_REG_SET_CODERATE_C2_3 0x1 | |
| 422 | +#define EC_VD_REG_SET_CODERATE_C3_4 0x2 | |
| 423 | +#define EC_VD_REG_SET_CODERATE_C5_6 0x3 | |
| 424 | +#define EC_VD_REG_SET_CODERATE_C7_8 0x4 | |
| 425 | +#define EC_VD_REG_REQ_SMB_CNT__A 0x2090012 | |
| 426 | +#define EC_VD_REG_RLK_ENA__A 0x2090014 | |
| 427 | +#define EC_OD_REG_COMM_EXEC__A 0x2110000 | |
| 428 | +#define EC_OD_REG_SYNC__A 0x2110010 | |
| 429 | +#define EC_OD_DEINT_RAM__A 0x2120000 | |
| 430 | +#define EC_RS_REG_COMM_EXEC__A 0x2130000 | |
| 431 | +#define EC_RS_REG_REQ_PCK_CNT__A 0x2130010 | |
| 432 | +#define EC_RS_REG_VAL__A 0x2130011 | |
| 433 | +#define EC_RS_REG_VAL_PCK 0x1 | |
| 434 | +#define EC_RS_EC_RAM__A 0x2140000 | |
| 435 | +#define EC_OC_REG_COMM_EXEC__A 0x2150000 | |
| 436 | +#define EC_OC_REG_COMM_EXEC_CTL_ACTIVE 0x1 | |
| 437 | +#define EC_OC_REG_COMM_EXEC_CTL_HOLD 0x2 | |
| 438 | +#define EC_OC_REG_COMM_INT_STA__A 0x2150007 | |
| 439 | +#define EC_OC_REG_OC_MODE_LOP__A 0x2150010 | |
| 440 | +#define EC_OC_REG_OC_MODE_LOP_PAR_ENA__M 0x1 | |
| 441 | +#define EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE 0x0 | |
| 442 | +#define EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE 0x1 | |
| 443 | +#define EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M 0x4 | |
| 444 | +#define EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC 0x0 | |
| 445 | +#define EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M 0x80 | |
| 446 | +#define EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL 0x80 | |
| 447 | +#define EC_OC_REG_OC_MODE_HIP__A 0x2150011 | |
| 448 | +#define EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR 0x10 | |
| 449 | +#define EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M 0x200 | |
| 450 | +#define EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE 0x0 | |
| 451 | +#define EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE 0x200 | |
| 452 | +#define EC_OC_REG_OC_MPG_SIO__A 0x2150012 | |
| 453 | +#define EC_OC_REG_OC_MPG_SIO__M 0xFFF | |
| 454 | +#define EC_OC_REG_OC_MON_SIO__A 0x2150013 | |
| 455 | +#define EC_OC_REG_DTO_INC_LOP__A 0x2150014 | |
| 456 | +#define EC_OC_REG_DTO_INC_HIP__A 0x2150015 | |
| 457 | +#define EC_OC_REG_SNC_ISC_LVL__A 0x2150016 | |
| 458 | +#define EC_OC_REG_SNC_ISC_LVL_OSC__M 0xF0 | |
| 459 | +#define EC_OC_REG_TMD_TOP_MODE__A 0x215001D | |
| 460 | +#define EC_OC_REG_TMD_TOP_CNT__A 0x215001E | |
| 461 | +#define EC_OC_REG_TMD_HIL_MAR__A 0x215001F | |
| 462 | +#define EC_OC_REG_TMD_LOL_MAR__A 0x2150020 | |
| 463 | +#define EC_OC_REG_TMD_CUR_CNT__A 0x2150021 | |
| 464 | +#define EC_OC_REG_AVR_ASH_CNT__A 0x2150023 | |
| 465 | +#define EC_OC_REG_AVR_BSH_CNT__A 0x2150024 | |
| 466 | +#define EC_OC_REG_RCN_MODE__A 0x2150027 | |
| 467 | +#define EC_OC_REG_RCN_CRA_LOP__A 0x2150028 | |
| 468 | +#define EC_OC_REG_RCN_CRA_HIP__A 0x2150029 | |
| 469 | +#define EC_OC_REG_RCN_CST_LOP__A 0x215002A | |
| 470 | +#define EC_OC_REG_RCN_CST_HIP__A 0x215002B | |
| 471 | +#define EC_OC_REG_RCN_SET_LVL__A 0x215002C | |
| 472 | +#define EC_OC_REG_RCN_GAI_LVL__A 0x215002D | |
| 473 | +#define EC_OC_REG_RCN_CLP_LOP__A 0x2150032 | |
| 474 | +#define EC_OC_REG_RCN_CLP_HIP__A 0x2150033 | |
| 475 | +#define EC_OC_REG_RCN_MAP_LOP__A 0x2150034 | |
| 476 | +#define EC_OC_REG_RCN_MAP_HIP__A 0x2150035 | |
| 477 | +#define EC_OC_REG_OCR_MPG_UOS__A 0x2150036 | |
| 478 | +#define EC_OC_REG_OCR_MPG_UOS__M 0xFFF | |
| 479 | +#define EC_OC_REG_OCR_MPG_UOS_INIT 0x0 | |
| 480 | +#define EC_OC_REG_OCR_MPG_USR_DAT__A 0x2150038 | |
| 481 | +#define EC_OC_REG_OCR_MON_UOS__A 0x2150039 | |
| 482 | +#define EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE 0x1 | |
| 483 | +#define EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE 0x2 | |
| 484 | +#define EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE 0x4 | |
| 485 | +#define EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE 0x8 | |
| 486 | +#define EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE 0x10 | |
| 487 | +#define EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE 0x20 | |
| 488 | +#define EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE 0x40 | |
| 489 | +#define EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE 0x80 | |
| 490 | +#define EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE 0x100 | |
| 491 | +#define EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE 0x200 | |
| 492 | +#define EC_OC_REG_OCR_MON_UOS_VAL_ENABLE 0x400 | |
| 493 | +#define EC_OC_REG_OCR_MON_UOS_CLK_ENABLE 0x800 | |
| 494 | +#define EC_OC_REG_OCR_MON_WRI__A 0x215003A | |
| 495 | +#define EC_OC_REG_OCR_MON_WRI_INIT 0x0 | |
| 496 | +#define EC_OC_REG_IPR_INV_MPG__A 0x2150045 | |
| 497 | +#define CC_REG_OSC_MODE__A 0x2410010 | |
| 498 | +#define CC_REG_OSC_MODE_M20 0x1 | |
| 499 | +#define CC_REG_PLL_MODE__A 0x2410011 | |
| 500 | +#define CC_REG_PLL_MODE_BYPASS_PLL 0x1 | |
| 501 | +#define CC_REG_PLL_MODE_PUMP_CUR_12 0x14 | |
| 502 | +#define CC_REG_REF_DIVIDE__A 0x2410012 | |
| 503 | +#define CC_REG_PWD_MODE__A 0x2410015 | |
| 504 | +#define CC_REG_PWD_MODE_DOWN_PLL 0x2 | |
| 505 | +#define CC_REG_UPDATE__A 0x2410017 | |
| 506 | +#define CC_REG_UPDATE_KEY 0x3973 | |
| 507 | +#define CC_REG_JTAGID_L__A 0x2410019 | |
| 508 | +#define LC_COMM_EXEC__A 0x2800000 | |
| 509 | +#define LC_RA_RAM_IFINCR_NOM_L__A 0x282000C | |
| 510 | +#define LC_RA_RAM_FILTER_SYM_SET__A 0x282001A | |
| 511 | +#define LC_RA_RAM_FILTER_SYM_SET__PRE 0x3E8 | |
| 512 | +#define LC_RA_RAM_FILTER_CRMM_A__A 0x2820060 | |
| 513 | +#define LC_RA_RAM_FILTER_CRMM_A__PRE 0x4 | |
| 514 | +#define LC_RA_RAM_FILTER_CRMM_B__A 0x2820061 | |
| 515 | +#define LC_RA_RAM_FILTER_CRMM_B__PRE 0x1 | |
| 516 | +#define LC_RA_RAM_FILTER_SRMM_A__A 0x2820068 | |
| 517 | +#define LC_RA_RAM_FILTER_SRMM_A__PRE 0x4 | |
| 518 | +#define LC_RA_RAM_FILTER_SRMM_B__A 0x2820069 | |
| 519 | +#define LC_RA_RAM_FILTER_SRMM_B__PRE 0x1 | |
| 520 | +#define B_HI_COMM_EXEC__A 0x400000 | |
| 521 | +#define B_HI_COMM_MB__A 0x400002 | |
| 522 | +#define B_HI_CT_REG_COMM_STATE__A 0x410001 | |
| 523 | +#define B_HI_RA_RAM_SRV_RES__A 0x420031 | |
| 524 | +#define B_HI_RA_RAM_SRV_CMD__A 0x420032 | |
| 525 | +#define B_HI_RA_RAM_SRV_CMD_RESET 0x2 | |
| 526 | +#define B_HI_RA_RAM_SRV_CMD_CONFIG 0x3 | |
| 527 | +#define B_HI_RA_RAM_SRV_CMD_EXECUTE 0x6 | |
| 528 | +#define B_HI_RA_RAM_SRV_RST_KEY__A 0x420033 | |
| 529 | +#define B_HI_RA_RAM_SRV_RST_KEY_ACT 0x3973 | |
| 530 | +#define B_HI_RA_RAM_SRV_CFG_KEY__A 0x420033 | |
| 531 | +#define B_HI_RA_RAM_SRV_CFG_DIV__A 0x420034 | |
| 532 | +#define B_HI_RA_RAM_SRV_CFG_BDL__A 0x420035 | |
| 533 | +#define B_HI_RA_RAM_SRV_CFG_WUP__A 0x420036 | |
| 534 | +#define B_HI_RA_RAM_SRV_CFG_ACT__A 0x420037 | |
| 535 | +#define B_HI_RA_RAM_SRV_CFG_ACT_SLV0_ON 0x1 | |
| 536 | +#define B_HI_RA_RAM_SRV_CFG_ACT_BRD__M 0x4 | |
| 537 | +#define B_HI_RA_RAM_SRV_CFG_ACT_BRD_OFF 0x0 | |
| 538 | +#define B_HI_RA_RAM_SRV_CFG_ACT_BRD_ON 0x4 | |
| 539 | +#define B_HI_RA_RAM_SRV_CFG_ACT_PWD_EXE 0x8 | |
| 540 | +#define B_HI_RA_RAM_USR_BEGIN__A 0x420040 | |
| 541 | +#define B_HI_IF_RAM_TRP_BPT0__AX 0x430000 | |
| 542 | +#define B_HI_IF_RAM_USR_BEGIN__A 0x430200 | |
| 543 | +#define B_SC_COMM_EXEC__A 0x800000 | |
| 544 | +#define B_SC_COMM_EXEC_CTL_STOP 0x0 | |
| 545 | +#define B_SC_COMM_STATE__A 0x800001 | |
| 546 | +#define B_SC_RA_RAM_PARAM0__A 0x820040 | |
| 547 | +#define B_SC_RA_RAM_PARAM1__A 0x820041 | |
| 548 | +#define B_SC_RA_RAM_CMD_ADDR__A 0x820042 | |
| 549 | +#define B_SC_RA_RAM_CMD__A 0x820043 | |
| 550 | +#define B_SC_RA_RAM_CMD_PROC_START 0x1 | |
| 551 | +#define B_SC_RA_RAM_CMD_SET_PREF_PARAM 0x3 | |
| 552 | +#define B_SC_RA_RAM_CMD_GET_OP_PARAM 0x5 | |
| 553 | +#define B_SC_RA_RAM_SW_EVENT_RUN_NMASK__M 0x1 | |
| 554 | +#define B_SC_RA_RAM_LOCKTRACK_MIN 0x1 | |
| 555 | +#define B_SC_RA_RAM_OP_PARAM_MODE_2K 0x0 | |
| 556 | +#define B_SC_RA_RAM_OP_PARAM_MODE_8K 0x1 | |
| 557 | +#define B_SC_RA_RAM_OP_PARAM_GUARD_32 0x0 | |
| 558 | +#define B_SC_RA_RAM_OP_PARAM_GUARD_16 0x4 | |
| 559 | +#define B_SC_RA_RAM_OP_PARAM_GUARD_8 0x8 | |
| 560 | +#define B_SC_RA_RAM_OP_PARAM_GUARD_4 0xC | |
| 561 | +#define B_SC_RA_RAM_OP_PARAM_CONST_QPSK 0x0 | |
| 562 | +#define B_SC_RA_RAM_OP_PARAM_CONST_QAM16 0x10 | |
| 563 | +#define B_SC_RA_RAM_OP_PARAM_CONST_QAM64 0x20 | |
| 564 | +#define B_SC_RA_RAM_OP_PARAM_HIER_NO 0x0 | |
| 565 | +#define B_SC_RA_RAM_OP_PARAM_HIER_A1 0x40 | |
| 566 | +#define B_SC_RA_RAM_OP_PARAM_HIER_A2 0x80 | |
| 567 | +#define B_SC_RA_RAM_OP_PARAM_HIER_A4 0xC0 | |
| 568 | +#define B_SC_RA_RAM_OP_PARAM_RATE_1_2 0x0 | |
| 569 | +#define B_SC_RA_RAM_OP_PARAM_RATE_2_3 0x200 | |
| 570 | +#define B_SC_RA_RAM_OP_PARAM_RATE_3_4 0x400 | |
| 571 | +#define B_SC_RA_RAM_OP_PARAM_RATE_5_6 0x600 | |
| 572 | +#define B_SC_RA_RAM_OP_PARAM_RATE_7_8 0x800 | |
| 573 | +#define B_SC_RA_RAM_OP_PARAM_PRIO_HI 0x0 | |
| 574 | +#define B_SC_RA_RAM_OP_PARAM_PRIO_LO 0x1000 | |
| 575 | +#define B_SC_RA_RAM_OP_AUTO_MODE__M 0x1 | |
| 576 | +#define B_SC_RA_RAM_OP_AUTO_GUARD__M 0x2 | |
| 577 | +#define B_SC_RA_RAM_OP_AUTO_CONST__M 0x4 | |
| 578 | +#define B_SC_RA_RAM_OP_AUTO_HIER__M 0x8 | |
| 579 | +#define B_SC_RA_RAM_OP_AUTO_RATE__M 0x10 | |
| 580 | +#define B_SC_RA_RAM_LOCK__A 0x82004B | |
| 581 | +#define B_SC_RA_RAM_LOCK_DEMOD__M 0x1 | |
| 582 | +#define B_SC_RA_RAM_LOCK_FEC__M 0x2 | |
| 583 | +#define B_SC_RA_RAM_LOCK_MPEG__M 0x4 | |
| 584 | +#define B_SC_RA_RAM_BE_OPT_ENA__A 0x82004C | |
| 585 | +#define B_SC_RA_RAM_BE_OPT_ENA_CP_OPT 0x1 | |
| 586 | +#define B_SC_RA_RAM_BE_OPT_DELAY__A 0x82004D | |
| 587 | +#define B_SC_RA_RAM_CONFIG__A 0x820050 | |
| 588 | +#define B_SC_RA_RAM_CONFIG_FR_ENABLE__M 0x4 | |
| 589 | +#define B_SC_RA_RAM_CONFIG_FREQSCAN__M 0x10 | |
| 590 | +#define B_SC_RA_RAM_CONFIG_SLAVE__M 0x20 | |
| 591 | +#define B_SC_RA_RAM_CONFIG_DIV_BLANK_ENABLE__M 0x200 | |
| 592 | +#define B_SC_RA_RAM_CONFIG_DIV_ECHO_ENABLE__M 0x400 | |
| 593 | +#define B_SC_RA_RAM_CO_TD_CAL_2K__A 0x82005D | |
| 594 | +#define B_SC_RA_RAM_CO_TD_CAL_8K__A 0x82005E | |
| 595 | +#define B_SC_RA_RAM_IF_SAVE__AX 0x82008E | |
| 596 | +#define B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A 0x820098 | |
| 597 | +#define B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A 0x820099 | |
| 598 | +#define B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A 0x82009A | |
| 599 | +#define B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A 0x82009B | |
| 600 | +#define B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A 0x82009C | |
| 601 | +#define B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A 0x82009D | |
| 602 | +#define B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A 0x82009E | |
| 603 | +#define B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A 0x82009F | |
| 604 | +#define B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A 0x8200D1 | |
| 605 | +#define B_SC_RA_RAM_IR_COARSE_2K_LENGTH__PRE 0x9 | |
| 606 | +#define B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A 0x8200D2 | |
| 607 | +#define B_SC_RA_RAM_IR_COARSE_2K_FREQINC__PRE 0x4 | |
| 608 | +#define B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A 0x8200D3 | |
| 609 | +#define B_SC_RA_RAM_IR_COARSE_2K_KAISINC__PRE 0x100 | |
| 610 | +#define B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A 0x8200D4 | |
| 611 | +#define B_SC_RA_RAM_IR_COARSE_8K_LENGTH__PRE 0x8 | |
| 612 | +#define B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A 0x8200D5 | |
| 613 | +#define B_SC_RA_RAM_IR_COARSE_8K_FREQINC__PRE 0x8 | |
| 614 | +#define B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A 0x8200D6 | |
| 615 | +#define B_SC_RA_RAM_IR_COARSE_8K_KAISINC__PRE 0x200 | |
| 616 | +#define B_SC_RA_RAM_IR_FINE_2K_LENGTH__A 0x8200D7 | |
| 617 | +#define B_SC_RA_RAM_IR_FINE_2K_LENGTH__PRE 0x9 | |
| 618 | +#define B_SC_RA_RAM_IR_FINE_2K_FREQINC__A 0x8200D8 | |
| 619 | +#define B_SC_RA_RAM_IR_FINE_2K_FREQINC__PRE 0x4 | |
| 620 | +#define B_SC_RA_RAM_IR_FINE_2K_KAISINC__A 0x8200D9 | |
| 621 | +#define B_SC_RA_RAM_IR_FINE_2K_KAISINC__PRE 0x100 | |
| 622 | +#define B_SC_RA_RAM_IR_FINE_8K_LENGTH__A 0x8200DA | |
| 623 | +#define B_SC_RA_RAM_IR_FINE_8K_LENGTH__PRE 0xB | |
| 624 | +#define B_SC_RA_RAM_IR_FINE_8K_FREQINC__A 0x8200DB | |
| 625 | +#define B_SC_RA_RAM_IR_FINE_8K_FREQINC__PRE 0x1 | |
| 626 | +#define B_SC_RA_RAM_IR_FINE_8K_KAISINC__A 0x8200DC | |
| 627 | +#define B_SC_RA_RAM_IR_FINE_8K_KAISINC__PRE 0x40 | |
| 628 | +#define B_SC_RA_RAM_ECHO_SHIFT_LIM__A 0x8200DD | |
| 629 | +#define B_SC_RA_RAM_SAMPLE_RATE_COUNT__A 0x8200E8 | |
| 630 | +#define B_SC_RA_RAM_SAMPLE_RATE_STEP__A 0x8200E9 | |
| 631 | +#define B_SC_RA_RAM_BAND__A 0x8200EC | |
| 632 | +#define B_SC_RA_RAM_LC_ABS_2K__A 0x8200F4 | |
| 633 | +#define B_SC_RA_RAM_LC_ABS_2K__PRE 0x1F | |
| 634 | +#define B_SC_RA_RAM_LC_ABS_8K__A 0x8200F5 | |
| 635 | +#define B_SC_RA_RAM_LC_ABS_8K__PRE 0x1F | |
| 636 | +#define B_SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE 0x100 | |
| 637 | +#define B_SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE 0x4 | |
| 638 | +#define B_SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE 0x1E2 | |
| 639 | +#define B_SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE 0x4 | |
| 640 | +#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE 0x10D | |
| 641 | +#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE 0x5 | |
| 642 | +#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE 0x17D | |
| 643 | +#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE 0x4 | |
| 644 | +#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE 0x133 | |
| 645 | +#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE 0x5 | |
| 646 | +#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE 0x114 | |
| 647 | +#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE 0x5 | |
| 648 | +#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE 0x14A | |
| 649 | +#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE 0x4 | |
| 650 | +#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE 0x1BB | |
| 651 | +#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE 0x4 | |
| 652 | +#define B_SC_RA_RAM_DRIVER_VERSION__AX 0x8201FE | |
| 653 | +#define B_SC_RA_RAM_PROC_LOCKTRACK 0x0 | |
| 654 | +#define B_FE_COMM_EXEC__A 0xC00000 | |
| 655 | +#define B_FE_AD_REG_COMM_EXEC__A 0xC10000 | |
| 656 | +#define B_FE_AD_REG_FDB_IN__A 0xC10012 | |
| 657 | +#define B_FE_AD_REG_PD__A 0xC10013 | |
| 658 | +#define B_FE_AD_REG_INVEXT__A 0xC10014 | |
| 659 | +#define B_FE_AD_REG_CLKNEG__A 0xC10015 | |
| 660 | +#define B_FE_AG_REG_COMM_EXEC__A 0xC20000 | |
| 661 | +#define B_FE_AG_REG_AG_MODE_LOP__A 0xC20010 | |
| 662 | +#define B_FE_AG_REG_AG_MODE_LOP_MODE_4__M 0x10 | |
| 663 | +#define B_FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC 0x0 | |
| 664 | +#define B_FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC 0x10 | |
| 665 | +#define B_FE_AG_REG_AG_MODE_LOP_MODE_5__M 0x20 | |
| 666 | +#define B_FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC 0x0 | |
| 667 | +#define B_FE_AG_REG_AG_MODE_LOP_MODE_C__M 0x1000 | |
| 668 | +#define B_FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC 0x0 | |
| 669 | +#define B_FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC 0x1000 | |
| 670 | +#define B_FE_AG_REG_AG_MODE_LOP_MODE_E__M 0x4000 | |
| 671 | +#define B_FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC 0x0 | |
| 672 | +#define B_FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC 0x4000 | |
| 673 | +#define B_FE_AG_REG_AG_MODE_HIP__A 0xC20011 | |
| 674 | +#define B_FE_AG_REG_AG_MODE_HIP_MODE_J__M 0x8 | |
| 675 | +#define B_FE_AG_REG_AG_MODE_HIP_MODE_J_STATIC 0x0 | |
| 676 | +#define B_FE_AG_REG_AG_MODE_HIP_MODE_J_DYNAMIC 0x8 | |
| 677 | +#define B_FE_AG_REG_AG_PGA_MODE__A 0xC20012 | |
| 678 | +#define B_FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN 0x0 | |
| 679 | +#define B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN 0x1 | |
| 680 | +#define B_FE_AG_REG_AG_AGC_SIO__A 0xC20013 | |
| 681 | +#define B_FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M 0x2 | |
| 682 | +#define B_FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT 0x0 | |
| 683 | +#define B_FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT 0x2 | |
| 684 | +#define B_FE_AG_REG_AG_PWD__A 0xC20015 | |
| 685 | +#define B_FE_AG_REG_AG_PWD_PWD_PD2__M 0x2 | |
| 686 | +#define B_FE_AG_REG_AG_PWD_PWD_PD2_DISABLE 0x0 | |
| 687 | +#define B_FE_AG_REG_AG_PWD_PWD_PD2_ENABLE 0x2 | |
| 688 | +#define B_FE_AG_REG_DCE_AUR_CNT__A 0xC20016 | |
| 689 | +#define B_FE_AG_REG_DCE_RUR_CNT__A 0xC20017 | |
| 690 | +#define B_FE_AG_REG_ACE_AUR_CNT__A 0xC2001A | |
| 691 | +#define B_FE_AG_REG_ACE_RUR_CNT__A 0xC2001B | |
| 692 | +#define B_FE_AG_REG_CDR_RUR_CNT__A 0xC20020 | |
| 693 | +#define B_FE_AG_REG_EGC_RUR_CNT__A 0xC20024 | |
| 694 | +#define B_FE_AG_REG_EGC_SET_LVL__A 0xC20025 | |
| 695 | +#define B_FE_AG_REG_EGC_SET_LVL__M 0x1FF | |
| 696 | +#define B_FE_AG_REG_EGC_FLA_RGN__A 0xC20026 | |
| 697 | +#define B_FE_AG_REG_EGC_SLO_RGN__A 0xC20027 | |
| 698 | +#define B_FE_AG_REG_EGC_JMP_PSN__A 0xC20028 | |
| 699 | +#define B_FE_AG_REG_EGC_FLA_INC__A 0xC20029 | |
| 700 | +#define B_FE_AG_REG_EGC_FLA_DEC__A 0xC2002A | |
| 701 | +#define B_FE_AG_REG_EGC_SLO_INC__A 0xC2002B | |
| 702 | +#define B_FE_AG_REG_EGC_SLO_DEC__A 0xC2002C | |
| 703 | +#define B_FE_AG_REG_EGC_FAS_INC__A 0xC2002D | |
| 704 | +#define B_FE_AG_REG_EGC_FAS_DEC__A 0xC2002E | |
| 705 | +#define B_FE_AG_REG_PM1_AGC_WRI__A 0xC20030 | |
| 706 | +#define B_FE_AG_REG_PM1_AGC_WRI__M 0x7FF | |
| 707 | +#define B_FE_AG_REG_GC1_AGC_RIC__A 0xC20031 | |
| 708 | +#define B_FE_AG_REG_GC1_AGC_OFF__A 0xC20032 | |
| 709 | +#define B_FE_AG_REG_GC1_AGC_MAX__A 0xC20033 | |
| 710 | +#define B_FE_AG_REG_GC1_AGC_MIN__A 0xC20034 | |
| 711 | +#define B_FE_AG_REG_GC1_AGC_DAT__A 0xC20035 | |
| 712 | +#define B_FE_AG_REG_GC1_AGC_DAT__M 0x3FF | |
| 713 | +#define B_FE_AG_REG_PM2_AGC_WRI__A 0xC20036 | |
| 714 | +#define B_FE_AG_REG_IND_WIN__A 0xC2003C | |
| 715 | +#define B_FE_AG_REG_IND_THD_LOL__A 0xC2003D | |
| 716 | +#define B_FE_AG_REG_IND_THD_HIL__A 0xC2003E | |
| 717 | +#define B_FE_AG_REG_IND_DEL__A 0xC2003F | |
| 718 | +#define B_FE_AG_REG_IND_PD1_WRI__A 0xC20040 | |
| 719 | +#define B_FE_AG_REG_PDA_AUR_CNT__A 0xC20041 | |
| 720 | +#define B_FE_AG_REG_PDA_RUR_CNT__A 0xC20042 | |
| 721 | +#define B_FE_AG_REG_PDA_AVE_DAT__A 0xC20043 | |
| 722 | +#define B_FE_AG_REG_PDC_RUR_CNT__A 0xC20044 | |
| 723 | +#define B_FE_AG_REG_PDC_SET_LVL__A 0xC20045 | |
| 724 | +#define B_FE_AG_REG_PDC_FLA_RGN__A 0xC20046 | |
| 725 | +#define B_FE_AG_REG_PDC_JMP_PSN__A 0xC20047 | |
| 726 | +#define B_FE_AG_REG_PDC_FLA_STP__A 0xC20048 | |
| 727 | +#define B_FE_AG_REG_PDC_SLO_STP__A 0xC20049 | |
| 728 | +#define B_FE_AG_REG_PDC_PD2_WRI__A 0xC2004A | |
| 729 | +#define B_FE_AG_REG_PDC_MAP_DAT__A 0xC2004B | |
| 730 | +#define B_FE_AG_REG_PDC_MAX__A 0xC2004C | |
| 731 | +#define B_FE_AG_REG_TGA_AUR_CNT__A 0xC2004D | |
| 732 | +#define B_FE_AG_REG_TGA_RUR_CNT__A 0xC2004E | |
| 733 | +#define B_FE_AG_REG_TGA_AVE_DAT__A 0xC2004F | |
| 734 | +#define B_FE_AG_REG_TGC_RUR_CNT__A 0xC20050 | |
| 735 | +#define B_FE_AG_REG_TGC_SET_LVL__A 0xC20051 | |
| 736 | +#define B_FE_AG_REG_TGC_SET_LVL__M 0x3F | |
| 737 | +#define B_FE_AG_REG_TGC_FLA_RGN__A 0xC20052 | |
| 738 | +#define B_FE_AG_REG_TGC_JMP_PSN__A 0xC20053 | |
| 739 | +#define B_FE_AG_REG_TGC_FLA_STP__A 0xC20054 | |
| 740 | +#define B_FE_AG_REG_TGC_SLO_STP__A 0xC20055 | |
| 741 | +#define B_FE_AG_REG_TGC_MAP_DAT__A 0xC20056 | |
| 742 | +#define B_FE_AG_REG_FGM_WRI__A 0xC20061 | |
| 743 | +#define B_FE_AG_REG_BGC_FGC_WRI__A 0xC20068 | |
| 744 | +#define B_FE_AG_REG_BGC_CGC_WRI__A 0xC20069 | |
| 745 | +#define B_FE_FS_REG_COMM_EXEC__A 0xC30000 | |
| 746 | +#define B_FE_FS_REG_ADD_INC_LOP__A 0xC30010 | |
| 747 | +#define B_FE_FD_REG_COMM_EXEC__A 0xC40000 | |
| 748 | +#define B_FE_FD_REG_SCL__A 0xC40010 | |
| 749 | +#define B_FE_FD_REG_MAX_LEV__A 0xC40011 | |
| 750 | +#define B_FE_FD_REG_NR__A 0xC40012 | |
| 751 | +#define B_FE_FD_REG_MEAS_VAL__A 0xC40014 | |
| 752 | +#define B_FE_IF_REG_COMM_EXEC__A 0xC50000 | |
| 753 | +#define B_FE_IF_REG_INCR0__A 0xC50010 | |
| 754 | +#define B_FE_IF_REG_INCR0__W 16 | |
| 755 | +#define B_FE_IF_REG_INCR0__M 0xFFFF | |
| 756 | +#define B_FE_IF_REG_INCR1__A 0xC50011 | |
| 757 | +#define B_FE_IF_REG_INCR1__M 0xFF | |
| 758 | +#define B_FE_CF_REG_COMM_EXEC__A 0xC60000 | |
| 759 | +#define B_FE_CF_REG_SCL__A 0xC60010 | |
| 760 | +#define B_FE_CF_REG_MAX_LEV__A 0xC60011 | |
| 761 | +#define B_FE_CF_REG_NR__A 0xC60012 | |
| 762 | +#define B_FE_CF_REG_IMP_VAL__A 0xC60013 | |
| 763 | +#define B_FE_CF_REG_MEAS_VAL__A 0xC60014 | |
| 764 | +#define B_FE_CU_REG_COMM_EXEC__A 0xC70000 | |
| 765 | +#define B_FE_CU_REG_FRM_CNT_RST__A 0xC70011 | |
| 766 | +#define B_FE_CU_REG_FRM_CNT_STR__A 0xC70012 | |
| 767 | +#define B_FE_CU_REG_CTR_NFC_ICR__A 0xC70020 | |
| 768 | +#define B_FE_CU_REG_CTR_NFC_OCR__A 0xC70021 | |
| 769 | +#define B_FE_CU_REG_DIV_NFC_CLP__A 0xC70027 | |
| 770 | +#define B_FT_COMM_EXEC__A 0x1000000 | |
| 771 | +#define B_FT_REG_COMM_EXEC__A 0x1010000 | |
| 772 | +#define B_CP_COMM_EXEC__A 0x1400000 | |
| 773 | +#define B_CP_REG_COMM_EXEC__A 0x1410000 | |
| 774 | +#define B_CP_REG_INTERVAL__A 0x1410011 | |
| 775 | +#define B_CP_REG_BR_SPL_OFFSET__A 0x1410023 | |
| 776 | +#define B_CP_REG_BR_STR_DEL__A 0x1410024 | |
| 777 | +#define B_CP_REG_RT_ANG_INC0__A 0x1410030 | |
| 778 | +#define B_CP_REG_RT_ANG_INC1__A 0x1410031 | |
| 779 | +#define B_CP_REG_RT_DETECT_TRH__A 0x1410033 | |
| 780 | +#define B_CP_REG_AC_NEXP_OFFS__A 0x1410040 | |
| 781 | +#define B_CP_REG_AC_AVER_POW__A 0x1410041 | |
| 782 | +#define B_CP_REG_AC_MAX_POW__A 0x1410042 | |
| 783 | +#define B_CP_REG_AC_WEIGHT_MAN__A 0x1410043 | |
| 784 | +#define B_CP_REG_AC_WEIGHT_EXP__A 0x1410044 | |
| 785 | +#define B_CP_REG_AC_AMP_MODE__A 0x1410047 | |
| 786 | +#define B_CP_REG_AC_AMP_FIX__A 0x1410048 | |
| 787 | +#define B_CP_REG_AC_ANG_MODE__A 0x141004A | |
| 788 | +#define B_CE_COMM_EXEC__A 0x1800000 | |
| 789 | +#define B_CE_REG_COMM_EXEC__A 0x1810000 | |
| 790 | +#define B_CE_REG_TAPSET__A 0x1810011 | |
| 791 | +#define B_CE_REG_AVG_POW__A 0x1810012 | |
| 792 | +#define B_CE_REG_MAX_POW__A 0x1810013 | |
| 793 | +#define B_CE_REG_ATT__A 0x1810014 | |
| 794 | +#define B_CE_REG_NRED__A 0x1810015 | |
| 795 | +#define B_CE_REG_NE_ERR_SELECT__A 0x1810043 | |
| 796 | +#define B_CE_REG_NE_TD_CAL__A 0x1810044 | |
| 797 | +#define B_CE_REG_NE_MIXAVG__A 0x1810046 | |
| 798 | +#define B_CE_REG_NE_NUPD_OFS__A 0x1810047 | |
| 799 | +#define B_CE_REG_PE_NEXP_OFFS__A 0x1810050 | |
| 800 | +#define B_CE_REG_PE_TIMESHIFT__A 0x1810051 | |
| 801 | +#define B_CE_REG_TP_A0_TAP_NEW__A 0x1810064 | |
| 802 | +#define B_CE_REG_TP_A0_TAP_NEW_VALID__A 0x1810065 | |
| 803 | +#define B_CE_REG_TP_A0_MU_LMS_STEP__A 0x1810066 | |
| 804 | +#define B_CE_REG_TP_A1_TAP_NEW__A 0x1810068 | |
| 805 | +#define B_CE_REG_TP_A1_TAP_NEW_VALID__A 0x1810069 | |
| 806 | +#define B_CE_REG_TP_A1_MU_LMS_STEP__A 0x181006A | |
| 807 | +#define B_CE_REG_TI_PHN_ENABLE__A 0x1810073 | |
| 808 | +#define B_CE_REG_FI_SHT_INCR__A 0x1810090 | |
| 809 | +#define B_CE_REG_FI_EXP_NORM__A 0x1810091 | |
| 810 | +#define B_CE_REG_IR_INPUTSEL__A 0x18100A0 | |
| 811 | +#define B_CE_REG_IR_STARTPOS__A 0x18100A1 | |
| 812 | +#define B_CE_REG_IR_NEXP_THRES__A 0x18100A2 | |
| 813 | +#define B_CE_REG_FR_TREAL00__A 0x1820010 | |
| 814 | +#define B_CE_REG_FR_TIMAG00__A 0x1820011 | |
| 815 | +#define B_CE_REG_FR_TREAL01__A 0x1820012 | |
| 816 | +#define B_CE_REG_FR_TIMAG01__A 0x1820013 | |
| 817 | +#define B_CE_REG_FR_TREAL02__A 0x1820014 | |
| 818 | +#define B_CE_REG_FR_TIMAG02__A 0x1820015 | |
| 819 | +#define B_CE_REG_FR_TREAL03__A 0x1820016 | |
| 820 | +#define B_CE_REG_FR_TIMAG03__A 0x1820017 | |
| 821 | +#define B_CE_REG_FR_TREAL04__A 0x1820018 | |
| 822 | +#define B_CE_REG_FR_TIMAG04__A 0x1820019 | |
| 823 | +#define B_CE_REG_FR_TREAL05__A 0x182001A | |
| 824 | +#define B_CE_REG_FR_TIMAG05__A 0x182001B | |
| 825 | +#define B_CE_REG_FR_TREAL06__A 0x182001C | |
| 826 | +#define B_CE_REG_FR_TIMAG06__A 0x182001D | |
| 827 | +#define B_CE_REG_FR_TREAL07__A 0x182001E | |
| 828 | +#define B_CE_REG_FR_TIMAG07__A 0x182001F | |
| 829 | +#define B_CE_REG_FR_TREAL08__A 0x1820020 | |
| 830 | +#define B_CE_REG_FR_TIMAG08__A 0x1820021 | |
| 831 | +#define B_CE_REG_FR_TREAL09__A 0x1820022 | |
| 832 | +#define B_CE_REG_FR_TIMAG09__A 0x1820023 | |
| 833 | +#define B_CE_REG_FR_TREAL10__A 0x1820024 | |
| 834 | +#define B_CE_REG_FR_TIMAG10__A 0x1820025 | |
| 835 | +#define B_CE_REG_FR_TREAL11__A 0x1820026 | |
| 836 | +#define B_CE_REG_FR_TIMAG11__A 0x1820027 | |
| 837 | +#define B_CE_REG_FR_MID_TAP__A 0x1820028 | |
| 838 | +#define B_CE_REG_FR_SQS_G00__A 0x1820029 | |
| 839 | +#define B_CE_REG_FR_SQS_G01__A 0x182002A | |
| 840 | +#define B_CE_REG_FR_SQS_G02__A 0x182002B | |
| 841 | +#define B_CE_REG_FR_SQS_G03__A 0x182002C | |
| 842 | +#define B_CE_REG_FR_SQS_G04__A 0x182002D | |
| 843 | +#define B_CE_REG_FR_SQS_G05__A 0x182002E | |
| 844 | +#define B_CE_REG_FR_SQS_G06__A 0x182002F | |
| 845 | +#define B_CE_REG_FR_SQS_G07__A 0x1820030 | |
| 846 | +#define B_CE_REG_FR_SQS_G08__A 0x1820031 | |
| 847 | +#define B_CE_REG_FR_SQS_G09__A 0x1820032 | |
| 848 | +#define B_CE_REG_FR_SQS_G10__A 0x1820033 | |
| 849 | +#define B_CE_REG_FR_SQS_G11__A 0x1820034 | |
| 850 | +#define B_CE_REG_FR_SQS_G12__A 0x1820035 | |
| 851 | +#define B_CE_REG_FR_RIO_G00__A 0x1820036 | |
| 852 | +#define B_CE_REG_FR_RIO_G01__A 0x1820037 | |
| 853 | +#define B_CE_REG_FR_RIO_G02__A 0x1820038 | |
| 854 | +#define B_CE_REG_FR_RIO_G03__A 0x1820039 | |
| 855 | +#define B_CE_REG_FR_RIO_G04__A 0x182003A | |
| 856 | +#define B_CE_REG_FR_RIO_G05__A 0x182003B | |
| 857 | +#define B_CE_REG_FR_RIO_G06__A 0x182003C | |
| 858 | +#define B_CE_REG_FR_RIO_G07__A 0x182003D | |
| 859 | +#define B_CE_REG_FR_RIO_G08__A 0x182003E | |
| 860 | +#define B_CE_REG_FR_RIO_G09__A 0x182003F | |
| 861 | +#define B_CE_REG_FR_RIO_G10__A 0x1820040 | |
| 862 | +#define B_CE_REG_FR_MODE__A 0x1820041 | |
| 863 | +#define B_CE_REG_FR_SQS_TRH__A 0x1820042 | |
| 864 | +#define B_CE_REG_FR_RIO_GAIN__A 0x1820043 | |
| 865 | +#define B_CE_REG_FR_BYPASS__A 0x1820044 | |
| 866 | +#define B_CE_REG_FR_PM_SET__A 0x1820045 | |
| 867 | +#define B_CE_REG_FR_ERR_SH__A 0x1820046 | |
| 868 | +#define B_CE_REG_FR_MAN_SH__A 0x1820047 | |
| 869 | +#define B_CE_REG_FR_TAP_SH__A 0x1820048 | |
| 870 | +#define B_EQ_COMM_EXEC__A 0x1C00000 | |
| 871 | +#define B_EQ_REG_COMM_EXEC__A 0x1C10000 | |
| 872 | +#define B_EQ_REG_COMM_MB__A 0x1C10002 | |
| 873 | +#define B_EQ_REG_IS_GAIN_MAN__A 0x1C10015 | |
| 874 | +#define B_EQ_REG_IS_GAIN_EXP__A 0x1C10016 | |
| 875 | +#define B_EQ_REG_IS_CLIP_EXP__A 0x1C10017 | |
| 876 | +#define B_EQ_REG_SN_CEGAIN__A 0x1C1002A | |
| 877 | +#define B_EQ_REG_SN_OFFSET__A 0x1C1002B | |
| 878 | +#define B_EQ_REG_RC_SEL_CAR__A 0x1C10032 | |
| 879 | +#define B_EQ_REG_RC_SEL_CAR_INIT 0x2 | |
| 880 | +#define B_EQ_REG_RC_SEL_CAR_DIV_ON 0x1 | |
| 881 | +#define B_EQ_REG_RC_SEL_CAR_PASS_A_CC 0x0 | |
| 882 | +#define B_EQ_REG_RC_SEL_CAR_PASS_B_CE 0x2 | |
| 883 | +#define B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC 0x0 | |
| 884 | +#define B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE 0x8 | |
| 885 | +#define B_EQ_REG_RC_SEL_CAR_MEAS_A_CC 0x0 | |
| 886 | +#define B_EQ_REG_RC_SEL_CAR_MEAS_B_CE 0x20 | |
| 887 | +#define B_EQ_REG_RC_SEL_CAR_FFTMODE__M 0x80 | |
| 888 | +#define B_EQ_REG_OT_CONST__A 0x1C10046 | |
| 889 | +#define B_EQ_REG_OT_ALPHA__A 0x1C10047 | |
| 890 | +#define B_EQ_REG_OT_QNT_THRES0__A 0x1C10048 | |
| 891 | +#define B_EQ_REG_OT_QNT_THRES1__A 0x1C10049 | |
| 892 | +#define B_EQ_REG_OT_CSI_STEP__A 0x1C1004A | |
| 893 | +#define B_EQ_REG_OT_CSI_OFFSET__A 0x1C1004B | |
| 894 | +#define B_EQ_REG_TD_REQ_SMB_CNT__A 0x1C10061 | |
| 895 | +#define B_EQ_REG_TD_TPS_PWR_OFS__A 0x1C10062 | |
| 896 | +#define B_EC_SB_REG_COMM_EXEC__A 0x2010000 | |
| 897 | +#define B_EC_SB_REG_TR_MODE__A 0x2010010 | |
| 898 | +#define B_EC_SB_REG_TR_MODE_8K 0x0 | |
| 899 | +#define B_EC_SB_REG_TR_MODE_2K 0x1 | |
| 900 | +#define B_EC_SB_REG_CONST__A 0x2010011 | |
| 901 | +#define B_EC_SB_REG_CONST_QPSK 0x0 | |
| 902 | +#define B_EC_SB_REG_CONST_16QAM 0x1 | |
| 903 | +#define B_EC_SB_REG_CONST_64QAM 0x2 | |
| 904 | +#define B_EC_SB_REG_ALPHA__A 0x2010012 | |
| 905 | +#define B_EC_SB_REG_PRIOR__A 0x2010013 | |
| 906 | +#define B_EC_SB_REG_PRIOR_HI 0x0 | |
| 907 | +#define B_EC_SB_REG_PRIOR_LO 0x1 | |
| 908 | +#define B_EC_SB_REG_CSI_HI__A 0x2010014 | |
| 909 | +#define B_EC_SB_REG_CSI_LO__A 0x2010015 | |
| 910 | +#define B_EC_SB_REG_SMB_TGL__A 0x2010016 | |
| 911 | +#define B_EC_SB_REG_SNR_HI__A 0x2010017 | |
| 912 | +#define B_EC_SB_REG_SNR_MID__A 0x2010018 | |
| 913 | +#define B_EC_SB_REG_SNR_LO__A 0x2010019 | |
| 914 | +#define B_EC_SB_REG_SCALE_MSB__A 0x201001A | |
| 915 | +#define B_EC_SB_REG_SCALE_BIT2__A 0x201001B | |
| 916 | +#define B_EC_SB_REG_SCALE_LSB__A 0x201001C | |
| 917 | +#define B_EC_SB_REG_CSI_OFS0__A 0x201001D | |
| 918 | +#define B_EC_SB_REG_CSI_OFS1__A 0x201001E | |
| 919 | +#define B_EC_SB_REG_CSI_OFS2__A 0x201001F | |
| 920 | +#define B_EC_VD_REG_COMM_EXEC__A 0x2090000 | |
| 921 | +#define B_EC_VD_REG_FORCE__A 0x2090010 | |
| 922 | +#define B_EC_VD_REG_SET_CODERATE__A 0x2090011 | |
| 923 | +#define B_EC_VD_REG_SET_CODERATE_C1_2 0x0 | |
| 924 | +#define B_EC_VD_REG_SET_CODERATE_C2_3 0x1 | |
| 925 | +#define B_EC_VD_REG_SET_CODERATE_C3_4 0x2 | |
| 926 | +#define B_EC_VD_REG_SET_CODERATE_C5_6 0x3 | |
| 927 | +#define B_EC_VD_REG_SET_CODERATE_C7_8 0x4 | |
| 928 | +#define B_EC_VD_REG_REQ_SMB_CNT__A 0x2090012 | |
| 929 | +#define B_EC_VD_REG_RLK_ENA__A 0x2090014 | |
| 930 | +#define B_EC_OD_REG_COMM_EXEC__A 0x2110000 | |
| 931 | +#define B_EC_OD_REG_SYNC__A 0x2110664 | |
| 932 | +#define B_EC_OD_DEINT_RAM__A 0x2120000 | |
| 933 | +#define B_EC_RS_REG_COMM_EXEC__A 0x2130000 | |
| 934 | +#define B_EC_RS_REG_REQ_PCK_CNT__A 0x2130010 | |
| 935 | +#define B_EC_RS_REG_VAL__A 0x2130011 | |
| 936 | +#define B_EC_RS_REG_VAL_PCK 0x1 | |
| 937 | +#define B_EC_RS_EC_RAM__A 0x2140000 | |
| 938 | +#define B_EC_OC_REG_COMM_EXEC__A 0x2150000 | |
| 939 | +#define B_EC_OC_REG_COMM_EXEC_CTL_ACTIVE 0x1 | |
| 940 | +#define B_EC_OC_REG_COMM_EXEC_CTL_HOLD 0x2 | |
| 941 | +#define B_EC_OC_REG_COMM_INT_STA__A 0x2150007 | |
| 942 | +#define B_EC_OC_REG_OC_MODE_LOP__A 0x2150010 | |
| 943 | +#define B_EC_OC_REG_OC_MODE_LOP_PAR_ENA__M 0x1 | |
| 944 | +#define B_EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE 0x0 | |
| 945 | +#define B_EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE 0x1 | |
| 946 | +#define B_EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M 0x4 | |
| 947 | +#define B_EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC 0x0 | |
| 948 | +#define B_EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M 0x80 | |
| 949 | +#define B_EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL 0x80 | |
| 950 | +#define B_EC_OC_REG_OC_MODE_HIP__A 0x2150011 | |
| 951 | +#define B_EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR 0x10 | |
| 952 | +#define B_EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M 0x200 | |
| 953 | +#define B_EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE 0x0 | |
| 954 | +#define B_EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE 0x200 | |
| 955 | +#define B_EC_OC_REG_OC_MPG_SIO__A 0x2150012 | |
| 956 | +#define B_EC_OC_REG_OC_MPG_SIO__M 0xFFF | |
| 957 | +#define B_EC_OC_REG_DTO_INC_LOP__A 0x2150014 | |
| 958 | +#define B_EC_OC_REG_DTO_INC_HIP__A 0x2150015 | |
| 959 | +#define B_EC_OC_REG_SNC_ISC_LVL__A 0x2150016 | |
| 960 | +#define B_EC_OC_REG_SNC_ISC_LVL_OSC__M 0xF0 | |
| 961 | +#define B_EC_OC_REG_TMD_TOP_MODE__A 0x215001D | |
| 962 | +#define B_EC_OC_REG_TMD_TOP_CNT__A 0x215001E | |
| 963 | +#define B_EC_OC_REG_TMD_HIL_MAR__A 0x215001F | |
| 964 | +#define B_EC_OC_REG_TMD_LOL_MAR__A 0x2150020 | |
| 965 | +#define B_EC_OC_REG_TMD_CUR_CNT__A 0x2150021 | |
| 966 | +#define B_EC_OC_REG_AVR_ASH_CNT__A 0x2150023 | |
| 967 | +#define B_EC_OC_REG_AVR_BSH_CNT__A 0x2150024 | |
| 968 | +#define B_EC_OC_REG_RCN_MODE__A 0x2150027 | |
| 969 | +#define B_EC_OC_REG_RCN_CRA_LOP__A 0x2150028 | |
| 970 | +#define B_EC_OC_REG_RCN_CRA_HIP__A 0x2150029 | |
| 971 | +#define B_EC_OC_REG_RCN_CST_LOP__A 0x215002A | |
| 972 | +#define B_EC_OC_REG_RCN_CST_HIP__A 0x215002B | |
| 973 | +#define B_EC_OC_REG_RCN_SET_LVL__A 0x215002C | |
| 974 | +#define B_EC_OC_REG_RCN_GAI_LVL__A 0x215002D | |
| 975 | +#define B_EC_OC_REG_RCN_CLP_LOP__A 0x2150032 | |
| 976 | +#define B_EC_OC_REG_RCN_CLP_HIP__A 0x2150033 | |
| 977 | +#define B_EC_OC_REG_RCN_MAP_LOP__A 0x2150034 | |
| 978 | +#define B_EC_OC_REG_RCN_MAP_HIP__A 0x2150035 | |
| 979 | +#define B_EC_OC_REG_OCR_MPG_UOS__A 0x2150036 | |
| 980 | +#define B_EC_OC_REG_OCR_MPG_UOS__M 0xFFF | |
| 981 | +#define B_EC_OC_REG_OCR_MPG_UOS_INIT 0x0 | |
| 982 | +#define B_EC_OC_REG_OCR_MPG_USR_DAT__A 0x2150038 | |
| 983 | +#define B_EC_OC_REG_IPR_INV_MPG__A 0x2150045 | |
| 984 | +#define B_EC_OC_REG_DTO_CLKMODE__A 0x2150047 | |
| 985 | +#define B_EC_OC_REG_DTO_PER__A 0x2150048 | |
| 986 | +#define B_EC_OC_REG_DTO_BUR__A 0x2150049 | |
| 987 | +#define B_EC_OC_REG_RCR_CLKMODE__A 0x215004A | |
| 988 | +#define B_CC_REG_OSC_MODE__A 0x2410010 | |
| 989 | +#define B_CC_REG_OSC_MODE_M20 0x1 | |
| 990 | +#define B_CC_REG_PLL_MODE__A 0x2410011 | |
| 991 | +#define B_CC_REG_PLL_MODE_BYPASS_PLL 0x1 | |
| 992 | +#define B_CC_REG_PLL_MODE_PUMP_CUR_12 0x14 | |
| 993 | +#define B_CC_REG_REF_DIVIDE__A 0x2410012 | |
| 994 | +#define B_CC_REG_PWD_MODE__A 0x2410015 | |
| 995 | +#define B_CC_REG_PWD_MODE_DOWN_PLL 0x2 | |
| 996 | +#define B_CC_REG_UPDATE__A 0x2410017 | |
| 997 | +#define B_CC_REG_UPDATE_KEY 0x3973 | |
| 998 | +#define B_CC_REG_JTAGID_L__A 0x2410019 | |
| 999 | +#define B_CC_REG_DIVERSITY__A 0x241001B | |
| 1000 | +#define B_LC_COMM_EXEC__A 0x2800000 | |
| 1001 | +#define B_LC_RA_RAM_IFINCR_NOM_L__A 0x282000C | |
| 1002 | +#define B_LC_RA_RAM_FILTER_SYM_SET__A 0x282001A | |
| 1003 | +#define B_LC_RA_RAM_FILTER_SYM_SET__PRE 0x3E8 | |
| 1004 | +#define B_LC_RA_RAM_FILTER_CRMM_A__A 0x2820060 | |
| 1005 | +#define B_LC_RA_RAM_FILTER_CRMM_A__PRE 0x4 | |
| 1006 | +#define B_LC_RA_RAM_FILTER_CRMM_B__A 0x2820061 | |
| 1007 | +#define B_LC_RA_RAM_FILTER_CRMM_B__PRE 0x1 | |
| 1008 | +#define B_LC_RA_RAM_FILTER_SRMM_A__A 0x2820068 | |
| 1009 | +#define B_LC_RA_RAM_FILTER_SRMM_A__PRE 0x4 | |
| 1010 | +#define B_LC_RA_RAM_FILTER_SRMM_B__A 0x2820069 | |
| 1011 | +#define B_LC_RA_RAM_FILTER_SRMM_B__PRE 0x1 | |
| 1012 | + | |
| 1013 | +#endif | |
| @@ -61,7 +61,7 @@ static u8 stv0288_earda_inittab[] = { · 60 unmodified lines | ||
| 61 | 61 | 0x3d, 0x30, |
| 62 | 62 | 0x40, 0x63, |
| 63 | 63 | 0x41, 0x04, |
| 64 | − 0x42, 0x60, | |
| 64 | + 0x42, 0x20, | |
| 65 | 65 | 0x43, 0x00, |
| 66 | 66 | 0x44, 0x00, |
| 67 | 67 | 0x45, 0x00, |
| @@ -218,11 +218,13 @@ static int ix2505v_set_params(struct dvb_frontend *fe, · 217 unmodified lines | ||
| 218 | 218 | fe->ops.i2c_gate_ctrl(fe, 1); |
| 219 | 219 | |
| 220 | 220 | len = sizeof(data); |
| 221 | − | |
| 222 | 221 | ret |= ix2505v_write(state, data, len); |
| 223 | 222 | |
| 224 | 223 | data[2] |= 0x4; /* set TM = 1 other bits same */ |
| 225 | 224 | |
| 225 | + if (fe->ops.i2c_gate_ctrl) | |
| 226 | + fe->ops.i2c_gate_ctrl(fe, 1); | |
| 227 | + | |
| 226 | 228 | len = 1; |
| 227 | 229 | ret |= ix2505v_write(state, &data[2], len); /* write byte 4 only */ |
| 228 | 230 | |
| @@ -233,12 +235,12 @@ static int ix2505v_set_params(struct dvb_frontend *fe, · 4 unmodified lines | ||
| 233 | 235 | |
| 234 | 236 | deb_info("Data 2=[%x%x]\n", data[2], data[3]); |
| 235 | 237 | |
| 238 | + if (fe->ops.i2c_gate_ctrl) | |
| 239 | + fe->ops.i2c_gate_ctrl(fe, 1); | |
| 240 | + | |
| 236 | 241 | len = 2; |
| 237 | 242 | ret |= ix2505v_write(state, &data[2], len); /* write byte 4 & 5 */ |
| 238 | 243 | |
| 239 | − if (fe->ops.i2c_gate_ctrl) | |
| 240 | − fe->ops.i2c_gate_ctrl(fe, 0); | |
| 241 | − | |
| 242 | 244 | if (state->config->min_delay_ms) |
| 243 | 245 | msleep(state->config->min_delay_ms); |
| 244 | 246 | |
| @@ -253,7 +253,7 @@ static u8 stv0288_inittab[] = { · 252 unmodified lines | ||
| 253 | 253 | 0x3d, 0x30, |
| 254 | 254 | 0x40, 0x63, |
| 255 | 255 | 0x41, 0x04, |
| 256 | − 0x42, 0x60, | |
| 256 | + 0x42, 0x20, | |
| 257 | 257 | 0x43, 0x00, |
| 258 | 258 | 0x44, 0x00, |
| 259 | 259 | 0x45, 0x00, |
| @@ -64,6 +64,7 @@ struct stv0299_state { · 63 unmodified lines | ||
| 64 | 64 | fe_code_rate_t fec_inner; |
| 65 | 65 | int errmode; |
| 66 | 66 | u32 ucblocks; |
| 67 | + u8 mcr_reg; | |
| 67 | 68 | }; |
| 68 | 69 | |
| 69 | 70 | #define STATUS_BER 0 |
| @@ -457,6 +458,9 @@ static int stv0299_init (struct dvb_frontend* fe) · 387 unmodified lines | ||
| 457 | 458 | |
| 458 | 459 | dprintk("stv0299: init chip\n"); |
| 459 | 460 | |
| 461 | + stv0299_writeregI(state, 0x02, 0x30 | state->mcr_reg); | |
| 462 | + msleep(50); | |
| 463 | + | |
| 460 | 464 | for (i = 0; ; i += 2) { |
| 461 | 465 | reg = state->config->inittab[i]; |
| 462 | 466 | val = state->config->inittab[i+1]; |
| @@ -464,6 +468,8 @@ static int stv0299_init (struct dvb_frontend* fe) · 1 unmodified line | ||
| 464 | 468 | break; |
| 465 | 469 | if (reg == 0x0c && state->config->op0_off) |
| 466 | 470 | val &= ~0x10; |
| 471 | + if (reg == 0x2) | |
| 472 | + state->mcr_reg = val & 0xf; | |
| 467 | 473 | stv0299_writeregI(state, reg, val); |
| 468 | 474 | } |
| 469 | 475 | |
| @@ -618,7 +624,7 @@ static int stv0299_sleep(struct dvb_frontend* fe) · 148 unmodified lines | ||
| 618 | 624 | { |
| 619 | 625 | struct stv0299_state* state = fe->demodulator_priv; |
| 620 | 626 | |
| 621 | − stv0299_writeregI(state, 0x02, 0x80); | |
| 627 | + stv0299_writeregI(state, 0x02, 0xb0 | state->mcr_reg); | |
| 622 | 628 | state->initialised = 0; |
| 623 | 629 | |
| 624 | 630 | return 0; |
| @@ -680,7 +686,7 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, · 55 unmodified lines | ||
| 680 | 686 | state->errmode = STATUS_BER; |
| 681 | 687 | |
| 682 | 688 | /* check if the demod is there */ |
| 683 | − stv0299_writeregI(state, 0x02, 0x34); /* standby off */ | |
| 689 | + stv0299_writeregI(state, 0x02, 0x30); /* standby off */ | |
| 684 | 690 | msleep(200); |
| 685 | 691 | id = stv0299_readreg(state, 0x00); |
| 686 | 692 | |
| @@ -42,7 +42,7 @@ static int sharp_z0194a_set_symbol_rate(struct dvb_frontend *fe, · 41 unmodified lines | ||
| 42 | 42 | |
| 43 | 43 | static u8 sharp_z0194a_inittab[] = { |
| 44 | 44 | 0x01, 0x15, |
| 45 | − 0x02, 0x00, | |
| 45 | + 0x02, 0x30, | |
| 46 | 46 | 0x03, 0x00, |
| 47 | 47 | 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ |
| 48 | 48 | 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ |
| @@ -44,7 +44,7 @@ · 43 unmodified lines | ||
| 44 | 44 | |
| 45 | 45 | static unsigned int verbose; |
| 46 | 46 | module_param(verbose, int, 0644); |
| 47 | −MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); | |
| 47 | +MODULE_PARM_DESC(verbose, "verbose startup messages, default is 0 (no)"); | |
| 48 | 48 | |
| 49 | 49 | #define DRIVER_NAME "Hopper" |
| 50 | 50 | |
| @@ -52,7 +52,7 @@ · 51 unmodified lines | ||
| 52 | 52 | |
| 53 | 53 | static unsigned int verbose; |
| 54 | 54 | module_param(verbose, int, 0644); |
| 55 | −MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); | |
| 55 | +MODULE_PARM_DESC(verbose, "verbose startup messages, default is 0 (no)"); | |
| 56 | 56 | |
| 57 | 57 | static int devs; |
| 58 | 58 | |
| @@ -48,7 +48,7 @@ · 47 unmodified lines | ||
| 48 | 48 | |
| 49 | 49 | int __devinit mantis_pci_init(struct mantis_pci *mantis) |
| 50 | 50 | { |
| 51 | − u8 revision, latency; | |
| 51 | + u8 latency; | |
| 52 | 52 | struct mantis_hwconfig *config = mantis->hwconfig; |
| 53 | 53 | struct pci_dev *pdev = mantis->pdev; |
| 54 | 54 | int err, ret = 0; |
| @@ -95,9 +95,8 @@ int __devinit mantis_pci_init(struct mantis_pci *mantis) · 40 unmodified lines | ||
| 95 | 95 | } |
| 96 | 96 | |
| 97 | 97 | pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency); |
| 98 | − pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); | |
| 99 | 98 | mantis->latency = latency; |
| 100 | − mantis->revision = revision; | |
| 99 | + mantis->revision = pdev->revision; | |
| 101 | 100 | |
| 102 | 101 | dprintk(MANTIS_ERROR, 0, " Mantis Rev %d [%04x:%04x], ", |
| 103 | 102 | mantis->revision, |
| @@ -37,7 +37,7 @@ · 36 unmodified lines | ||
| 37 | 37 | |
| 38 | 38 | u8 lgtdqcs001f_inittab[] = { |
| 39 | 39 | 0x01, 0x15, |
| 40 | − 0x02, 0x00, | |
| 40 | + 0x02, 0x30, | |
| 41 | 41 | 0x03, 0x00, |
| 42 | 42 | 0x04, 0x2a, |
| 43 | 43 | 0x05, 0x85, |
| @@ -1090,6 +1090,7 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 1089 unmodified lines | ||
| 1090 | 1090 | i2c_adap->algo = &pt1_i2c_algo; |
| 1091 | 1091 | i2c_adap->algo_data = NULL; |
| 1092 | 1092 | i2c_adap->dev.parent = &pdev->dev; |
| 1093 | + strcpy(i2c_adap->name, DRIVER_NAME); | |
| 1093 | 1094 | i2c_set_adapdata(i2c_adap, pt1); |
| 1094 | 1095 | ret = i2c_add_adapter(i2c_adap); |
| 1095 | 1096 | if (ret < 0) |
| @@ -1156,10 +1157,10 @@ err_pt1_disable_ram: · 60 unmodified lines | ||
| 1156 | 1157 | pt1->power = 0; |
| 1157 | 1158 | pt1->reset = 1; |
| 1158 | 1159 | pt1_update_power(pt1); |
| 1159 | −err_pt1_cleanup_adapters: | |
| 1160 | − pt1_cleanup_adapters(pt1); | |
| 1161 | 1160 | err_i2c_del_adapter: |
| 1162 | 1161 | i2c_del_adapter(i2c_adap); |
| 1162 | +err_pt1_cleanup_adapters: | |
| 1163 | + pt1_cleanup_adapters(pt1); | |
| 1163 | 1164 | err_kfree: |
| 1164 | 1165 | pci_set_drvdata(pdev, NULL); |
| 1165 | 1166 | kfree(pt1); |
| @@ -297,9 +297,8 @@ static void smsusb_term_device(struct usb_interface *intf) · 296 unmodified lines | ||
| 297 | 297 | if (dev->coredev) |
| 298 | 298 | smscore_unregister_device(dev->coredev); |
| 299 | 299 | |
| 300 | − kfree(dev); | |
| 301 | − | |
| 302 | 300 | sms_info("device %p destroyed", dev); |
| 301 | + kfree(dev); | |
| 303 | 302 | } |
| 304 | 303 | |
| 305 | 304 | usb_set_intfdata(intf, NULL); |
| @@ -95,6 +95,8 @@ config DVB_BUDGET_CI · 94 unmodified lines | ||
| 95 | 95 | select DVB_STB0899 if !DVB_FE_CUSTOMISE |
| 96 | 96 | select DVB_STB6100 if !DVB_FE_CUSTOMISE |
| 97 | 97 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE |
| 98 | + select DVB_STV0288 if !DVB_FE_CUSTOMISE | |
| 99 | + select DVB_STB6000 if !DVB_FE_CUSTOMISE | |
| 98 | 100 | select DVB_TDA10023 if !DVB_FE_CUSTOMISE |
| 99 | 101 | select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE |
| 100 | 102 | depends on RC_CORE |
| @@ -52,6 +52,7 @@ · 51 unmodified lines | ||
| 52 | 52 | #include "bsru6.h" |
| 53 | 53 | #include "tda1002x.h" |
| 54 | 54 | #include "tda827x.h" |
| 55 | +#include "bsbe1-d01a.h" | |
| 55 | 56 | |
| 56 | 57 | #define MODULE_NAME "budget_ci" |
| 57 | 58 | |
| @@ -224,6 +225,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) · 166 unmodified lines | ||
| 224 | 225 | case 0x1017: |
| 225 | 226 | case 0x1019: |
| 226 | 227 | case 0x101a: |
| 228 | + case 0x101b: | |
| 227 | 229 | /* for the Technotrend 1500 bundled remote */ |
| 228 | 230 | dev->map_name = RC_MAP_TT_1500; |
| 229 | 231 | break; |
| @@ -1388,6 +1390,23 @@ static void frontend_init(struct budget_ci *budget_ci) · 1158 unmodified lines | ||
| 1388 | 1390 | } |
| 1389 | 1391 | break; |
| 1390 | 1392 | |
| 1393 | + case 0x101b: /* TT S-1500B (BSBE1-D01A - STV0288/STB6000/LNBP21) */ | |
| 1394 | + budget_ci->budget.dvb_frontend = dvb_attach(stv0288_attach, &stv0288_bsbe1_d01a_config, &budget_ci->budget.i2c_adap); | |
| 1395 | + if (budget_ci->budget.dvb_frontend) { | |
| 1396 | + if (dvb_attach(stb6000_attach, budget_ci->budget.dvb_frontend, 0x63, &budget_ci->budget.i2c_adap)) { | |
| 1397 | + if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) { | |
| 1398 | + printk(KERN_ERR "%s: No LNBP21 found!\n", __func__); | |
| 1399 | + dvb_frontend_detach(budget_ci->budget.dvb_frontend); | |
| 1400 | + budget_ci->budget.dvb_frontend = NULL; | |
| 1401 | + } | |
| 1402 | + } else { | |
| 1403 | + printk(KERN_ERR "%s: No STB6000 found!\n", __func__); | |
| 1404 | + dvb_frontend_detach(budget_ci->budget.dvb_frontend); | |
| 1405 | + budget_ci->budget.dvb_frontend = NULL; | |
| 1406 | + } | |
| 1407 | + } | |
| 1408 | + break; | |
| 1409 | + | |
| 1391 | 1410 | case 0x1019: // TT S2-3200 PCI |
| 1392 | 1411 | /* |
| 1393 | 1412 | * 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); · 124 unmodified lines | ||
| 1518 | 1537 | MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT); |
| 1519 | 1538 | MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT); |
| 1520 | 1539 | MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT); |
| 1540 | +MAKE_BUDGET_INFO(ttbs1500b, "TT-Budget S-1500B PCI", BUDGET_TT); | |
| 1521 | 1541 | |
| 1522 | 1542 | static struct pci_device_id pci_tbl[] = { |
| 1523 | 1543 | MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c), |
| @@ -1528,6 +1548,7 @@ static struct pci_device_id pci_tbl[] = { · 4 unmodified lines | ||
| 1528 | 1548 | MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017), |
| 1529 | 1549 | MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a), |
| 1530 | 1550 | MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019), |
| 1551 | + MAKE_EXTENSION_PCI(ttbs1500b, 0x13c2, 0x101b), | |
| 1531 | 1552 | { |
| 1532 | 1553 | .vendor = 0, |
| 1533 | 1554 | } |
| @@ -52,7 +52,7 @@ · 51 unmodified lines | ||
| 52 | 52 | my TTUSB, so let it undef'd unless you want to implement another |
| 53 | 53 | frontend. never tested. |
| 54 | 54 | |
| 55 | − DEBUG: | |
| 55 | + debug: | |
| 56 | 56 | define it to > 3 for really hardcore debugging. you probably don't want |
| 57 | 57 | this unless the device doesn't load at all. > 2 for bandwidth statistics. |
| 58 | 58 | */ |
| @@ -134,20 +134,19 @@ struct ttusb { · 75 unmodified lines | ||
| 134 | 134 | /* ugly workaround ... don't know why it's necessary to read */ |
| 135 | 135 | /* all result codes. */ |
| 136 | 136 | |
| 137 | −#define DEBUG 0 | |
| 138 | 137 | static int ttusb_cmd(struct ttusb *ttusb, |
| 139 | 138 | const u8 * data, int len, int needresult) |
| 140 | 139 | { |
| 141 | 140 | int actual_len; |
| 142 | 141 | int err; |
| 143 | −#if DEBUG >= 3 | |
| 144 | 142 | int i; |
| 145 | 143 | |
| 146 | − printk(">"); | |
| 147 | − for (i = 0; i < len; ++i) | |
| 148 | − printk(" %02x", data[i]); | |
| 149 | − printk("\n"); | |
| 150 | −#endif | |
| 144 | + if (debug >= 3) { | |
| 145 | + printk(KERN_DEBUG ">"); | |
| 146 | + for (i = 0; i < len; ++i) | |
| 147 | + printk(KERN_CONT " %02x", data[i]); | |
| 148 | + printk(KERN_CONT "\n"); | |
| 149 | + } | |
| 151 | 150 | |
| 152 | 151 | if (mutex_lock_interruptible(&ttusb->semusb) < 0) |
| 153 | 152 | return -EAGAIN; |
| @@ -176,13 +175,15 @@ static int ttusb_cmd(struct ttusb *ttusb, · 22 unmodified lines | ||
| 176 | 175 | mutex_unlock(&ttusb->semusb); |
| 177 | 176 | return err; |
| 178 | 177 | } |
| 179 | −#if DEBUG >= 3 | |
| 180 | − actual_len = ttusb->last_result[3] + 4; | |
| 181 | − printk("<"); | |
| 182 | − for (i = 0; i < actual_len; ++i) | |
| 183 | − printk(" %02x", ttusb->last_result[i]); | |
| 184 | − printk("\n"); | |
| 185 | −#endif | |
| 178 | + | |
| 179 | + if (debug >= 3) { | |
| 180 | + actual_len = ttusb->last_result[3] + 4; | |
| 181 | + printk(KERN_DEBUG "<"); | |
| 182 | + for (i = 0; i < actual_len; ++i) | |
| 183 | + printk(KERN_CONT " %02x", ttusb->last_result[i]); | |
| 184 | + printk(KERN_CONT "\n"); | |
| 185 | + } | |
| 186 | + | |
| 186 | 187 | if (!needresult) |
| 187 | 188 | mutex_unlock(&ttusb->semusb); |
| 188 | 189 | return 0; |
| @@ -636,16 +637,13 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len) · 447 unmodified lines | ||
| 636 | 637 | ++ttusb->mux_state; |
| 637 | 638 | else { |
| 638 | 639 | ttusb->mux_state = 0; |
| 639 | −#if DEBUG > 3 | |
| 640 | − if (ttusb->insync) | |
| 641 | − printk("%02x ", data[-1]); | |
| 642 | −#else | |
| 643 | 640 | if (ttusb->insync) { |
| 644 | − printk("%s: lost sync.\n", | |
| 641 | + dprintk("%s: %02x\n", | |
| 642 | + __func__, data[-1]); | |
| 643 | + printk(KERN_INFO "%s: lost sync.\n", | |
| 645 | 644 | __func__); |
| 646 | 645 | ttusb->insync = 0; |
| 647 | 646 | } |
| 648 | −#endif | |
| 649 | 647 | } |
| 650 | 648 | break; |
| 651 | 649 | case 3: |
| @@ -744,6 +742,9 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len) · 92 unmodified lines | ||
| 744 | 742 | static void ttusb_iso_irq(struct urb *urb) |
| 745 | 743 | { |
| 746 | 744 | struct ttusb *ttusb = urb->context; |
| 745 | + struct usb_iso_packet_descriptor *d; | |
| 746 | + u8 *data; | |
| 747 | + int len, i; | |
| 747 | 748 | |
| 748 | 749 | if (!ttusb->iso_streaming) |
| 749 | 750 | return; |
| @@ -755,21 +756,14 @@ static void ttusb_iso_irq(struct urb *urb) · 5 unmodified lines | ||
| 755 | 756 | #endif |
| 756 | 757 | |
| 757 | 758 | if (!urb->status) { |
| 758 | − int i; | |
| 759 | 759 | for (i = 0; i < urb->number_of_packets; ++i) { |
| 760 | − struct usb_iso_packet_descriptor *d; | |
| 761 | − u8 *data; | |
| 762 | − int len; | |
| 763 | 760 | numpkt++; |
| 764 | 761 | if (time_after_eq(jiffies, lastj + HZ)) { |
| 765 | −#if DEBUG > 2 | |
| 766 | − printk | |
| 767 | − ("frames/s: %d (ts: %d, stuff %d, sec: %d, invalid: %d, all: %d)\n", | |
| 768 | − numpkt * HZ / (jiffies - lastj), | |
| 769 | − numts, numstuff, numsec, numinvalid, | |
| 770 | − numts + numstuff + numsec + | |
| 771 | − numinvalid); | |
| 772 | −#endif | |
| 762 | + dprintk("frames/s: %lu (ts: %d, stuff %d, " | |
| 763 | + "sec: %d, invalid: %d, all: %d)\n", | |
| 764 | + numpkt * HZ / (jiffies - lastj), | |
| 765 | + numts, numstuff, numsec, numinvalid, | |
| 766 | + numts + numstuff + numsec + numinvalid); | |
| 773 | 767 | numts = numstuff = numsec = numinvalid = 0; |
| 774 | 768 | lastj = jiffies; |
| 775 | 769 | numpkt = 0; |
| @@ -174,15 +174,27 @@ static int si470x_set_chan(struct si470x_device *radio, unsigned short chan) · 173 unmodified lines | ||
| 174 | 174 | if (retval < 0) |
| 175 | 175 | goto done; |
| 176 | 176 | |
| 177 | − /* wait till tune operation has completed */ | |
| 178 | − timeout = jiffies + msecs_to_jiffies(tune_timeout); | |
| 179 | − do { | |
| 180 | − retval = si470x_get_register(radio, STATUSRSSI); | |
| 181 | − if (retval < 0) | |
| 182 | − goto stop; | |
| 183 | − timed_out = time_after(jiffies, timeout); | |
| 184 | − } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && | |
| 185 | − (!timed_out)); | |
| 177 | + /* currently I2C driver only uses interrupt way to tune */ | |
| 178 | + if (radio->stci_enabled) { | |
| 179 | + INIT_COMPLETION(radio->completion); | |
| 180 | + | |
| 181 | + /* wait till tune operation has completed */ | |
| 182 | + retval = wait_for_completion_timeout(&radio->completion, | |
| 183 | + msecs_to_jiffies(tune_timeout)); | |
| 184 | + if (!retval) | |
| 185 | + timed_out = true; | |
| 186 | + } else { | |
| 187 | + /* wait till tune operation has completed */ | |
| 188 | + timeout = jiffies + msecs_to_jiffies(tune_timeout); | |
| 189 | + do { | |
| 190 | + retval = si470x_get_register(radio, STATUSRSSI); | |
| 191 | + if (retval < 0) | |
| 192 | + goto stop; | |
| 193 | + timed_out = time_after(jiffies, timeout); | |
| 194 | + } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) | |
| 195 | + && (!timed_out)); | |
| 196 | + } | |
| 197 | + | |
| 186 | 198 | if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) |
| 187 | 199 | dev_warn(&radio->videodev->dev, "tune does not complete\n"); |
| 188 | 200 | if (timed_out) |
| @@ -310,15 +322,27 @@ static int si470x_set_seek(struct si470x_device *radio, · 121 unmodified lines | ||
| 310 | 322 | if (retval < 0) |
| 311 | 323 | goto done; |
| 312 | 324 | |
| 313 | − /* wait till seek operation has completed */ | |
| 314 | − timeout = jiffies + msecs_to_jiffies(seek_timeout); | |
| 315 | − do { | |
| 316 | − retval = si470x_get_register(radio, STATUSRSSI); | |
| 317 | − if (retval < 0) | |
| 318 | − goto stop; | |
| 319 | − timed_out = time_after(jiffies, timeout); | |
| 320 | − } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && | |
| 321 | − (!timed_out)); | |
| 325 | + /* currently I2C driver only uses interrupt way to seek */ | |
| 326 | + if (radio->stci_enabled) { | |
| 327 | + INIT_COMPLETION(radio->completion); | |
| 328 | + | |
| 329 | + /* wait till seek operation has completed */ | |
| 330 | + retval = wait_for_completion_timeout(&radio->completion, | |
| 331 | + msecs_to_jiffies(seek_timeout)); | |
| 332 | + if (!retval) | |
| 333 | + timed_out = true; | |
| 334 | + } else { | |
| 335 | + /* wait till seek operation has completed */ | |
| 336 | + timeout = jiffies + msecs_to_jiffies(seek_timeout); | |
| 337 | + do { | |
| 338 | + retval = si470x_get_register(radio, STATUSRSSI); | |
| 339 | + if (retval < 0) | |
| 340 | + goto stop; | |
| 341 | + timed_out = time_after(jiffies, timeout); | |
| 342 | + } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) | |
| 343 | + && (!timed_out)); | |
| 344 | + } | |
| 345 | + | |
| 322 | 346 | if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) |
| 323 | 347 | dev_warn(&radio->videodev->dev, "seek does not complete\n"); |
| 324 | 348 | if (radio->registers[STATUSRSSI] & STATUSRSSI_SF) |
| @@ -197,8 +197,9 @@ int si470x_fops_open(struct file *file) · 196 unmodified lines | ||
| 197 | 197 | if (retval < 0) |
| 198 | 198 | goto done; |
| 199 | 199 | |
| 200 | − /* enable RDS interrupt */ | |
| 200 | + /* enable RDS / STC interrupt */ | |
| 201 | 201 | radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN; |
| 202 | + radio->registers[SYSCONFIG1] |= SYSCONFIG1_STCIEN; | |
| 202 | 203 | radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_GPIO2; |
| 203 | 204 | radio->registers[SYSCONFIG1] |= 0x1 << 2; |
| 204 | 205 | retval = si470x_set_register(radio, SYSCONFIG1); |
| @@ -261,12 +262,11 @@ int si470x_vidioc_querycap(struct file *file, void *priv, · 56 unmodified lines | ||
| 261 | 262 | **************************************************************************/ |
| 262 | 263 | |
| 263 | 264 | /* |
| 264 | − * si470x_i2c_interrupt_work - rds processing function | |
| 265 | + * si470x_i2c_interrupt - interrupt handler | |
| 265 | 266 | */ |
| 266 | −static void si470x_i2c_interrupt_work(struct work_struct *work) | |
| 267 | +static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id) | |
| 267 | 268 | { |
| 268 | − struct si470x_device *radio = container_of(work, | |
| 269 | − struct si470x_device, radio_work); | |
| 269 | + struct si470x_device *radio = dev_id; | |
| 270 | 270 | unsigned char regnr; |
| 271 | 271 | unsigned char blocknum; |
| 272 | 272 | unsigned short bler; /* rds block errors */ |
| @@ -274,21 +274,29 @@ static void si470x_i2c_interrupt_work(struct work_struct *work) · 1 unmodified line | ||
| 274 | 274 | unsigned char tmpbuf[3]; |
| 275 | 275 | int retval = 0; |
| 276 | 276 | |
| 277 | + /* check Seek/Tune Complete */ | |
| 278 | + retval = si470x_get_register(radio, STATUSRSSI); | |
| 279 | + if (retval < 0) | |
| 280 | + goto end; | |
| 281 | + | |
| 282 | + if (radio->registers[STATUSRSSI] & STATUSRSSI_STC) | |
| 283 | + complete(&radio->completion); | |
| 284 | + | |
| 277 | 285 | /* safety checks */ |
| 278 | 286 | if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) |
| 279 | − return; | |
| 287 | + goto end; | |
| 280 | 288 | |
| 281 | 289 | /* Update RDS registers */ |
| 282 | − for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) { | |
| 290 | + for (regnr = 1; regnr < RDS_REGISTER_NUM; regnr++) { | |
| 283 | 291 | retval = si470x_get_register(radio, STATUSRSSI + regnr); |
| 284 | 292 | if (retval < 0) |
| 285 | − return; | |
| 293 | + goto end; | |
| 286 | 294 | } |
| 287 | 295 | |
| 288 | 296 | /* get rds blocks */ |
| 289 | 297 | if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) |
| 290 | 298 | /* No RDS group ready, better luck next time */ |
| 291 | − return; | |
| 299 | + goto end; | |
| 292 | 300 | |
| 293 | 301 | for (blocknum = 0; blocknum < 4; blocknum++) { |
| 294 | 302 | switch (blocknum) { |
| @@ -342,19 +350,8 @@ static void si470x_i2c_interrupt_work(struct work_struct *work) · 47 unmodified lines | ||
| 342 | 350 | |
| 343 | 351 | if (radio->wr_index != radio->rd_index) |
| 344 | 352 | wake_up_interruptible(&radio->read_queue); |
| 345 | −} | |
| 346 | − | |
| 347 | − | |
| 348 | −/* | |
| 349 | − * si470x_i2c_interrupt - interrupt handler | |
| 350 | − */ | |
| 351 | −static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id) | |
| 352 | −{ | |
| 353 | − struct si470x_device *radio = dev_id; | |
| 354 | − | |
| 355 | − if (!work_pending(&radio->radio_work)) | |
| 356 | − schedule_work(&radio->radio_work); | |
| 357 | 353 | |
| 354 | +end: | |
| 358 | 355 | return IRQ_HANDLED; |
| 359 | 356 | } |
| 360 | 357 | |
| @@ -376,7 +373,6 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, · 15 unmodified lines | ||
| 376 | 373 | goto err_initial; |
| 377 | 374 | } |
| 378 | 375 | |
| 379 | − INIT_WORK(&radio->radio_work, si470x_i2c_interrupt_work); | |
| 380 | 376 | radio->users = 0; |
| 381 | 377 | radio->client = client; |
| 382 | 378 | mutex_init(&radio->lock); |
| @@ -441,7 +437,11 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, · 58 unmodified lines | ||
| 441 | 437 | radio->rd_index = 0; |
| 442 | 438 | init_waitqueue_head(&radio->read_queue); |
| 443 | 439 | |
| 444 | − retval = request_irq(client->irq, si470x_i2c_interrupt, | |
| 440 | + /* mark Seek/Tune Complete Interrupt enabled */ | |
| 441 | + radio->stci_enabled = true; | |
| 442 | + init_completion(&radio->completion); | |
| 443 | + | |
| 444 | + retval = request_threaded_irq(client->irq, NULL, si470x_i2c_interrupt, | |
| 445 | 445 | IRQF_TRIGGER_FALLING, DRIVER_NAME, radio); |
| 446 | 446 | if (retval) { |
| 447 | 447 | dev_err(&client->dev, "Failed to register interrupt\n"); |
| @@ -479,7 +479,6 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client) · 31 unmodified lines | ||
| 479 | 479 | struct si470x_device *radio = i2c_get_clientdata(client); |
| 480 | 480 | |
| 481 | 481 | free_irq(client->irq, radio); |
| 482 | − cancel_work_sync(&radio->radio_work); | |
| 483 | 482 | video_unregister_device(radio->videodev); |
| 484 | 483 | kfree(radio); |
| 485 | 484 | |
| @@ -491,8 +490,9 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client) · 5 unmodified lines | ||
| 491 | 490 | /* |
| 492 | 491 | * si470x_i2c_suspend - suspend the device |
| 493 | 492 | */ |
| 494 | −static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg) | |
| 493 | +static int si470x_i2c_suspend(struct device *dev) | |
| 495 | 494 | { |
| 495 | + struct i2c_client *client = to_i2c_client(dev); | |
| 496 | 496 | struct si470x_device *radio = i2c_get_clientdata(client); |
| 497 | 497 | |
| 498 | 498 | /* power down */ |
| @@ -507,8 +507,9 @@ static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg) · 8 unmodified lines | ||
| 507 | 507 | /* |
| 508 | 508 | * si470x_i2c_resume - resume the device |
| 509 | 509 | */ |
| 510 | −static int si470x_i2c_resume(struct i2c_client *client) | |
| 510 | +static int si470x_i2c_resume(struct device *dev) | |
| 511 | 511 | { |
| 512 | + struct i2c_client *client = to_i2c_client(dev); | |
| 512 | 513 | struct si470x_device *radio = i2c_get_clientdata(client); |
| 513 | 514 | |
| 514 | 515 | /* power up : need 110ms */ |
| @@ -519,9 +520,8 @@ static int si470x_i2c_resume(struct i2c_client *client) · 4 unmodified lines | ||
| 519 | 520 | |
| 520 | 521 | return 0; |
| 521 | 522 | } |
| 522 | −#else | |
| 523 | −#define si470x_i2c_suspend NULL | |
| 524 | −#define si470x_i2c_resume NULL | |
| 523 | + | |
| 524 | +static SIMPLE_DEV_PM_OPS(si470x_i2c_pm, si470x_i2c_suspend, si470x_i2c_resume); | |
| 525 | 525 | #endif |
| 526 | 526 | |
| 527 | 527 | |
| @@ -532,11 +532,12 @@ static struct i2c_driver si470x_i2c_driver = { · 4 unmodified lines | ||
| 532 | 532 | .driver = { |
| 533 | 533 | .name = "si470x", |
| 534 | 534 | .owner = THIS_MODULE, |
| 535 | +#ifdef CONFIG_PM | |
| 536 | + .pm = &si470x_i2c_pm, | |
| 537 | +#endif | |
| 535 | 538 | }, |
| 536 | 539 | .probe = si470x_i2c_probe, |
| 537 | 540 | .remove = __devexit_p(si470x_i2c_remove), |
| 538 | − .suspend = si470x_i2c_suspend, | |
| 539 | − .resume = si470x_i2c_resume, | |
| 540 | 541 | .id_table = si470x_i2c_id, |
| 541 | 542 | }; |
| 542 | 543 | |
| @@ -158,6 +158,9 @@ struct si470x_device { · 157 unmodified lines | ||
| 158 | 158 | unsigned int rd_index; |
| 159 | 159 | unsigned int wr_index; |
| 160 | 160 | |
| 161 | + struct completion completion; | |
| 162 | + bool stci_enabled; /* Seek/Tune Complete Interrupt */ | |
| 163 | + | |
| 161 | 164 | #if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE) |
| 162 | 165 | /* reference to USB and video device */ |
| 163 | 166 | struct usb_device *usbdev; |
| @@ -179,7 +182,6 @@ struct si470x_device { · 15 unmodified lines | ||
| 179 | 182 | |
| 180 | 183 | #if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE) |
| 181 | 184 | struct i2c_client *client; |
| 182 | − struct work_struct radio_work; | |
| 183 | 185 | #endif |
| 184 | 186 | }; |
| 185 | 187 | |
| @@ -55,8 +55,6 @@ · 54 unmodified lines | ||
| 55 | 55 | #define FM_DRV_TX_TIMEOUT (5*HZ) /* 5 seconds */ |
| 56 | 56 | #define FM_DRV_RX_SEEK_TIMEOUT (20*HZ) /* 20 seconds */ |
| 57 | 57 | |
| 58 | −#define NO_OF_ENTRIES_IN_ARRAY(array) (sizeof(array) / sizeof(array[0])) | |
| 59 | − | |
| 60 | 58 | #define fmerr(format, ...) \ |
| 61 | 59 | printk(KERN_ERR "fmdrv: " format, ## __VA_ARGS__) |
| 62 | 60 | #define fmwarn(format, ...) \ |
| @@ -161,6 +161,17 @@ config IR_NUVOTON · 160 unmodified lines | ||
| 161 | 161 | To compile this driver as a module, choose M here: the |
| 162 | 162 | module will be called nuvoton-cir. |
| 163 | 163 | |
| 164 | +config IR_REDRAT3 | |
| 165 | + tristate "RedRat3 IR Transceiver" | |
| 166 | + depends on USB_ARCH_HAS_HCD | |
| 167 | + depends on RC_CORE | |
| 168 | + select USB | |
| 169 | + ---help--- | |
| 170 | + Say Y here if you want to use a RedRat3 Infrared Transceiver. | |
| 171 | + | |
| 172 | + To compile this driver as a module, choose M here: the | |
| 173 | + module will be called redrat3. | |
| 174 | + | |
| 164 | 175 | config IR_STREAMZAP |
| 165 | 176 | tristate "Streamzap PC Remote IR Receiver" |
| 166 | 177 | depends on USB_ARCH_HAS_HCD |
| @@ -18,6 +18,7 @@ obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o · 17 unmodified lines | ||
| 18 | 18 | obj-$(CONFIG_IR_MCEUSB) += mceusb.o |
| 19 | 19 | obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o |
| 20 | 20 | obj-$(CONFIG_IR_ENE) += ene_ir.o |
| 21 | +obj-$(CONFIG_IR_REDRAT3) += redrat3.o | |
| 21 | 22 | obj-$(CONFIG_IR_STREAMZAP) += streamzap.o |
| 22 | 23 | obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o |
| 23 | 24 | obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o |
| @@ -443,16 +443,6 @@ static int display_close(struct inode *inode, struct file *file) · 442 unmodified lines | ||
| 443 | 443 | } else { |
| 444 | 444 | ictx->display_isopen = false; |
| 445 | 445 | dev_dbg(ictx->dev, "display port closed\n"); |
| 446 | − if (!ictx->dev_present_intf0) { | |
| 447 | − /* | |
| 448 | − * Device disconnected before close and IR port is not | |
| 449 | − * open. If IR port is open, context will be deleted by | |
| 450 | − * ir_close. | |
| 451 | − */ | |
| 452 | − mutex_unlock(&ictx->lock); | |
| 453 | − free_imon_context(ictx); | |
| 454 | − return retval; | |
| 455 | − } | |
| 456 | 446 | } |
| 457 | 447 | |
| 458 | 448 | mutex_unlock(&ictx->lock); |
| @@ -1492,7 +1482,6 @@ static void imon_incoming_packet(struct imon_context *ictx, · 1033 unmodified lines | ||
| 1492 | 1482 | struct device *dev = ictx->dev; |
| 1493 | 1483 | unsigned long flags; |
| 1494 | 1484 | u32 kc; |
| 1495 | − bool norelease = false; | |
| 1496 | 1485 | int i; |
| 1497 | 1486 | u64 scancode; |
| 1498 | 1487 | int press_type = 0; |
| @@ -1560,7 +1549,6 @@ static void imon_incoming_packet(struct imon_context *ictx, · 61 unmodified lines | ||
| 1560 | 1549 | !(buf[1] & 0x1 || buf[1] >> 2 & 0x1))) { |
| 1561 | 1550 | len = 8; |
| 1562 | 1551 | imon_pad_to_keys(ictx, buf); |
| 1563 | − norelease = true; | |
| 1564 | 1552 | } |
| 1565 | 1553 | |
| 1566 | 1554 | if (debug) { |
| @@ -1982,7 +1970,7 @@ static struct input_dev *imon_init_touch(struct imon_context *ictx) · 415 unmodified lines | ||
| 1982 | 1970 | return touch; |
| 1983 | 1971 | |
| 1984 | 1972 | touch_register_failed: |
| 1985 | − input_free_device(ictx->touch); | |
| 1973 | + input_free_device(touch); | |
| 1986 | 1974 | |
| 1987 | 1975 | touch_alloc_failed: |
| 1988 | 1976 | return NULL; |
| @@ -2274,14 +2262,12 @@ static int __devinit imon_probe(struct usb_interface *interface, · 285 unmodified lines | ||
| 2274 | 2262 | struct usb_host_interface *iface_desc = NULL; |
| 2275 | 2263 | struct usb_interface *first_if; |
| 2276 | 2264 | struct device *dev = &interface->dev; |
| 2277 | − int ifnum, code_length, sysfs_err; | |
| 2265 | + int ifnum, sysfs_err; | |
| 2278 | 2266 | int ret = 0; |
| 2279 | 2267 | struct imon_context *ictx = NULL; |
| 2280 | 2268 | struct imon_context *first_if_ctx = NULL; |
| 2281 | 2269 | u16 vendor, product; |
| 2282 | 2270 | |
| 2283 | − code_length = BUF_CHUNK_SIZE * 8; | |
| 2284 | − | |
| 2285 | 2271 | usbdev = usb_get_dev(interface_to_usbdev(interface)); |
| 2286 | 2272 | iface_desc = interface->cur_altsetting; |
| 2287 | 2273 | ifnum = iface_desc->desc.bInterfaceNumber; |
| @@ -2366,8 +2352,6 @@ static void __devexit imon_disconnect(struct usb_interface *interface) · 78 unmodified lines | ||
| 2366 | 2352 | dev = ictx->dev; |
| 2367 | 2353 | ifnum = interface->cur_altsetting->desc.bInterfaceNumber; |
| 2368 | 2354 | |
| 2369 | − mutex_lock(&ictx->lock); | |
| 2370 | − | |
| 2371 | 2355 | /* |
| 2372 | 2356 | * sysfs_remove_group is safe to call even if sysfs_create_group |
| 2373 | 2357 | * hasn't been called |
| @@ -2391,24 +2375,20 @@ static void __devexit imon_disconnect(struct usb_interface *interface) · 17 unmodified lines | ||
| 2391 | 2375 | if (ictx->display_supported) { |
| 2392 | 2376 | if (ictx->display_type == IMON_DISPLAY_TYPE_LCD) |
| 2393 | 2377 | usb_deregister_dev(interface, &imon_lcd_class); |
| 2394 | − else | |
| 2378 | + else if (ictx->display_type == IMON_DISPLAY_TYPE_VFD) | |
| 2395 | 2379 | usb_deregister_dev(interface, &imon_vfd_class); |
| 2396 | 2380 | } |
| 2397 | 2381 | } else { |
| 2398 | 2382 | ictx->dev_present_intf1 = false; |
| 2399 | 2383 | usb_kill_urb(ictx->rx_urb_intf1); |
| 2400 | − if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) | |
| 2384 | + if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { | |
| 2401 | 2385 | input_unregister_device(ictx->touch); |
| 2386 | + del_timer_sync(&ictx->ttimer); | |
| 2387 | + } | |
| 2402 | 2388 | } |
| 2403 | 2389 | |
| 2404 | − if (!ictx->dev_present_intf0 && !ictx->dev_present_intf1) { | |
| 2405 | − if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) | |
| 2406 | − del_timer_sync(&ictx->ttimer); | |
| 2407 | − mutex_unlock(&ictx->lock); | |
| 2408 | − if (!ictx->display_isopen) | |
| 2409 | − free_imon_context(ictx); | |
| 2410 | − } else | |
| 2411 | − mutex_unlock(&ictx->lock); | |
| 2390 | + if (!ictx->dev_present_intf0 && !ictx->dev_present_intf1) | |
| 2391 | + free_imon_context(ictx); | |
| 2412 | 2392 | |
| 2413 | 2393 | mutex_unlock(&driver_lock); |
| 2414 | 2394 | |
| @@ -1250,11 +1250,9 @@ static void it8709_disable(struct ite_dev *dev) · 1249 unmodified lines | ||
| 1250 | 1250 | ite_dbg("%s called", __func__); |
| 1251 | 1251 | |
| 1252 | 1252 | /* clear out all interrupt enable flags */ |
| 1253 | − it8709_wr(dev, | |
| 1254 | − it8709_rr(dev, | |
| 1255 | − IT85_C0IER) & ~(IT85_IEC | IT85_RFOIE | | |
| 1256 | − IT85_RDAIE | | |
| 1257 | − IT85_TLDLIE), IT85_C0IER); | |
| 1253 | + it8709_wr(dev, it8709_rr(dev, IT85_C0IER) & | |
| 1254 | + ~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE), | |
| 1255 | + IT85_C0IER); | |
| 1258 | 1256 | |
| 1259 | 1257 | /* disable the receiver */ |
| 1260 | 1258 | it8709_disable_rx(dev); |
| @@ -1270,11 +1268,9 @@ static void it8709_init_hardware(struct ite_dev *dev) · 9 unmodified lines | ||
| 1270 | 1268 | ite_dbg("%s called", __func__); |
| 1271 | 1269 | |
| 1272 | 1270 | /* disable all the interrupts */ |
| 1273 | − it8709_wr(dev, | |
| 1274 | − it8709_rr(dev, | |
| 1275 | − IT85_C0IER) & ~(IT85_IEC | IT85_RFOIE | | |
| 1276 | − IT85_RDAIE | | |
| 1277 | − IT85_TLDLIE), IT85_C0IER); | |
| 1271 | + it8709_wr(dev, it8709_rr(dev, IT85_C0IER) & | |
| 1272 | + ~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE), | |
| 1273 | + IT85_C0IER); | |
| 1278 | 1274 | |
| 1279 | 1275 | /* program the baud rate divisor */ |
| 1280 | 1276 | it8709_wr(dev, ITE_BAUDRATE_DIVISOR & 0xff, IT85_C0BDLR); |
| @@ -1282,28 +1278,22 @@ static void it8709_init_hardware(struct ite_dev *dev) · 1 unmodified line | ||
| 1282 | 1278 | IT85_C0BDHR); |
| 1283 | 1279 | |
| 1284 | 1280 | /* program the C0MSTCR register defaults */ |
| 1285 | − it8709_wr(dev, (it8709_rr(dev, IT85_C0MSTCR) & ~(IT85_ILSEL | | |
| 1286 | − IT85_ILE | |
| 1287 | − | IT85_FIFOTL | |
| 1288 | − | | |
| 1289 | − IT85_FIFOCLR | |
| 1290 | − | | |
| 1291 | − IT85_RESET)) | |
| 1292 | − | IT85_FIFOTL_DEFAULT, IT85_C0MSTCR); | |
| 1281 | + it8709_wr(dev, (it8709_rr(dev, IT85_C0MSTCR) & | |
| 1282 | + ~(IT85_ILSEL | IT85_ILE | IT85_FIFOTL | |
| 1283 | + | IT85_FIFOCLR | IT85_RESET)) | IT85_FIFOTL_DEFAULT, | |
| 1284 | + IT85_C0MSTCR); | |
| 1293 | 1285 | |
| 1294 | 1286 | /* program the C0RCR register defaults */ |
| 1295 | − it8709_wr(dev, | |
| 1296 | − (it8709_rr(dev, IT85_C0RCR) & | |
| 1297 | − ~(IT85_RXEN | IT85_RDWOS | IT85_RXEND | |
| 1298 | − | IT85_RXACT | IT85_RXDCR)) | | |
| 1299 | − ITE_RXDCR_DEFAULT, IT85_C0RCR); | |
| 1287 | + it8709_wr(dev, (it8709_rr(dev, IT85_C0RCR) & | |
| 1288 | + ~(IT85_RXEN | IT85_RDWOS | IT85_RXEND | IT85_RXACT | |
| 1289 | + | IT85_RXDCR)) | ITE_RXDCR_DEFAULT, | |
| 1290 | + IT85_C0RCR); | |
| 1300 | 1291 | |
| 1301 | 1292 | /* program the C0TCR register defaults */ |
| 1302 | − it8709_wr(dev, (it8709_rr(dev, IT85_C0TCR) | |
| 1303 | − &~(IT85_TXMPM | IT85_TXMPW)) | |
| 1304 | − |IT85_TXRLE | IT85_TXENDF | | |
| 1305 | − IT85_TXMPM_DEFAULT | | |
| 1306 | − IT85_TXMPW_DEFAULT, IT85_C0TCR); | |
| 1293 | + it8709_wr(dev, (it8709_rr(dev, IT85_C0TCR) & ~(IT85_TXMPM | IT85_TXMPW)) | |
| 1294 | + | IT85_TXRLE | IT85_TXENDF | IT85_TXMPM_DEFAULT | |
| 1295 | + | IT85_TXMPW_DEFAULT, | |
| 1296 | + IT85_C0TCR); | |
| 1307 | 1297 | |
| 1308 | 1298 | /* program the carrier parameters */ |
| 1309 | 1299 | ite_set_carrier_params(dev); |
| @@ -1660,6 +1650,9 @@ static int ite_suspend(struct pnp_dev *pdev, pm_message_t state) · 350 unmodified lines | ||
| 1660 | 1650 | |
| 1661 | 1651 | ite_dbg("%s called", __func__); |
| 1662 | 1652 | |
| 1653 | + /* wait for any transmission to end */ | |
| 1654 | + wait_event_interruptible(dev->tx_ended, !dev->transmitting); | |
| 1655 | + | |
| 1663 | 1656 | spin_lock_irqsave(&dev->lock, flags); |
| 1664 | 1657 | |
| 1665 | 1658 | /* disable all interrupts */ |
| @@ -1680,13 +1673,10 @@ static int ite_resume(struct pnp_dev *pdev) · 14 unmodified lines | ||
| 1680 | 1673 | |
| 1681 | 1674 | spin_lock_irqsave(&dev->lock, flags); |
| 1682 | 1675 | |
| 1683 | − if (dev->transmitting) { | |
| 1684 | − /* wake up the transmitter */ | |
| 1685 | − wake_up_interruptible(&dev->tx_queue); | |
| 1686 | − } else { | |
| 1687 | − /* enable the receiver */ | |
| 1688 | − dev->params.enable_rx(dev); | |
| 1689 | − } | |
| 1676 | + /* reinitialize hardware config registers */ | |
| 1677 | + dev->params.init_hardware(dev); | |
| 1678 | + /* enable the receiver */ | |
| 1679 | + dev->params.enable_rx(dev); | |
| 1690 | 1680 | |
| 1691 | 1681 | spin_unlock_irqrestore(&dev->lock, flags); |
| 1692 | 1682 | |
| @@ -77,6 +77,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ · 76 unmodified lines | ||
| 77 | 77 | rc-terratec-slim.o \ |
| 78 | 78 | rc-terratec-slim-2.o \ |
| 79 | 79 | rc-tevii-nec.o \ |
| 80 | + rc-tivo.o \ | |
| 80 | 81 | rc-total-media-in-hand.o \ |
| 81 | 82 | rc-trekstor.o \ |
| 82 | 83 | rc-tt-1500.o \ |
| @@ -52,7 +52,7 @@ static struct rc_map_table avermedia_cardbus[] = { · 51 unmodified lines | ||
| 52 | 52 | { 0x28, KEY_SELECT }, /* Select */ |
| 53 | 53 | { 0x29, KEY_BLUE }, /* Blue/Picture */ |
| 54 | 54 | { 0x2a, KEY_BACKSPACE }, /* Back */ |
| 55 | − { 0x2b, KEY_MEDIA }, /* PIP (Picture-in-picture) */ | |
| 55 | + { 0x2b, KEY_VIDEO }, /* PIP (Picture-in-picture) */ | |
| 56 | 56 | { 0x2c, KEY_DOWN }, |
| 57 | 57 | { 0x2e, KEY_DOT }, |
| 58 | 58 | { 0x2f, KEY_TV }, /* Live TV */ |
| @@ -111,7 +111,7 @@ static struct rc_map_table imon_mce[] = { · 110 unmodified lines | ||
| 111 | 111 | { 0x800ff44d, KEY_TITLE }, |
| 112 | 112 | |
| 113 | 113 | { 0x800ff40c, KEY_POWER }, |
| 114 | − { 0x800ff40d, KEY_LEFTMETA }, /* Windows MCE button */ | |
| 114 | + { 0x800ff40d, KEY_MEDIA }, /* Windows MCE button */ | |
| 115 | 115 | |
| 116 | 116 | }; |
| 117 | 117 | |
| @@ -87,7 +87,7 @@ static struct rc_map_table imon_pad[] = { · 86 unmodified lines | ||
| 87 | 87 | |
| 88 | 88 | { 0x2b8515b7, KEY_VIDEO }, |
| 89 | 89 | { 0x299195b7, KEY_AUDIO }, |
| 90 | − { 0x2ba115b7, KEY_CAMERA }, | |
| 90 | + { 0x2ba115b7, KEY_IMAGES }, | |
| 91 | 91 | { 0x28a515b7, KEY_TV }, |
| 92 | 92 | { 0x29a395b7, KEY_DVD }, |
| 93 | 93 | { 0x29a295b7, KEY_DVD }, |
| @@ -97,7 +97,7 @@ static struct rc_map_table imon_pad[] = { · 3 unmodified lines | ||
| 97 | 97 | { 0x2ba395b7, KEY_MENU }, |
| 98 | 98 | |
| 99 | 99 | { 0x288515b7, KEY_BOOKMARKS }, |
| 100 | − { 0x2ab715b7, KEY_MEDIA }, /* Thumbnail */ | |
| 100 | + { 0x2ab715b7, KEY_CAMERA }, /* Thumbnail */ | |
| 101 | 101 | { 0x298595b7, KEY_SUBTITLE }, |
| 102 | 102 | { 0x2b8595b7, KEY_LANGUAGE }, |
| 103 | 103 | |
| @@ -125,7 +125,7 @@ static struct rc_map_table imon_pad[] = { · 21 unmodified lines | ||
| 125 | 125 | { 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/ |
| 126 | 126 | { 0x02000065, KEY_COMPOSE }, /* RightMenu */ |
| 127 | 127 | { 0x28b715b7, KEY_COMPOSE }, /* RightMenu */ |
| 128 | − { 0x2ab195b7, KEY_LEFTMETA }, /* Go or MultiMon */ | |
| 128 | + { 0x2ab195b7, KEY_MEDIA }, /* Go or MultiMon */ | |
| 129 | 129 | { 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */ |
| 130 | 130 | }; |
| 131 | 131 | |
| @@ -17,7 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | */ |
| 18 | 18 | |
| 19 | 19 | static struct rc_map_table kworld_plus_tv_analog[] = { |
| 20 | − { 0x0c, KEY_LEFTMETA }, /* Kworld key */ | |
| 20 | + { 0x0c, KEY_MEDIA }, /* Kworld key */ | |
| 21 | 21 | { 0x16, KEY_CLOSECD }, /* -> ) */ |
| 22 | 22 | { 0x1d, KEY_POWER2 }, |
| 23 | 23 | |
| @@ -30,7 +30,7 @@ static struct rc_map_table rc6_mce[] = { · 29 unmodified lines | ||
| 30 | 30 | { 0x800f040a, KEY_DELETE }, |
| 31 | 31 | { 0x800f040b, KEY_ENTER }, |
| 32 | 32 | { 0x800f040c, KEY_POWER }, /* PC Power */ |
| 33 | − { 0x800f040d, KEY_LEFTMETA }, /* Windows MCE button */ | |
| 33 | + { 0x800f040d, KEY_MEDIA }, /* Windows MCE button */ | |
| 34 | 34 | { 0x800f040e, KEY_MUTE }, |
| 35 | 35 | { 0x800f040f, KEY_INFO }, |
| 36 | 36 | |
| @@ -87,7 +87,7 @@ static struct rc_map_table rc6_mce[] = { · 50 unmodified lines | ||
| 87 | 87 | |
| 88 | 88 | { 0x800f0465, KEY_POWER2 }, /* TV Power */ |
| 89 | 89 | { 0x800f046e, KEY_PLAYPAUSE }, |
| 90 | − { 0x800f046f, KEY_MEDIA }, /* Start media application (NEW) */ | |
| 90 | + { 0x800f046f, KEY_PLAYER }, /* Start media application (NEW) */ | |
| 91 | 91 | |
| 92 | 92 | { 0x800f0480, KEY_BRIGHTNESSDOWN }, |
| 93 | 93 | { 0x800f0481, KEY_PLAYPAUSE }, |
| @@ -0,0 +1,98 @@ | ||
| 1 | +/* rc-tivo.c - Keytable for TiVo remotes | |
| 2 | + * | |
| 3 | + * Copyright (c) 2011 by Jarod Wilson <jarod@redhat.com> | |
| 4 | + * | |
| 5 | + * This program is free software; you can redistribute it and/or modify | |
| 6 | + * it under the terms of the GNU General Public License as published by | |
| 7 | + * the Free Software Foundation; either version 2 of the License, or | |
| 8 | + * (at your option) any later version. | |
| 9 | + */ | |
| 10 | + | |
| 11 | +#include <media/rc-map.h> | |
| 12 | + | |
| 13 | +/* | |
| 14 | + * Initial mapping is for the TiVo remote included in the Nero LiquidTV bundle, | |
| 15 | + * which also ships with a TiVo-branded IR transceiver, supported by the mceusb | |
| 16 | + * driver. Note that the remote uses an NEC-ish protocol, but instead of having | |
| 17 | + * a command/not_command pair, it has a vendor ID of 0xa10c, but some keys, the | |
| 18 | + * NEC extended checksums do pass, so the table presently has the intended | |
| 19 | + * values and the checksum-passed versions for those keys. | |
| 20 | + */ | |
| 21 | +static struct rc_map_table tivo[] = { | |
| 22 | + { 0xa10c900f, KEY_MEDIA }, /* TiVo Button */ | |
| 23 | + { 0xa10c0807, KEY_POWER2 }, /* TV Power */ | |
| 24 | + { 0xa10c8807, KEY_TV }, /* Live TV/Swap */ | |
| 25 | + { 0xa10c2c03, KEY_VIDEO_NEXT }, /* TV Input */ | |
| 26 | + { 0xa10cc807, KEY_INFO }, | |
| 27 | + { 0xa10cfa05, KEY_CYCLEWINDOWS }, /* Window */ | |
| 28 | + { 0x0085305f, KEY_CYCLEWINDOWS }, | |
| 29 | + { 0xa10c6c03, KEY_EPG }, /* Guide */ | |
| 30 | + | |
| 31 | + { 0xa10c2807, KEY_UP }, | |
| 32 | + { 0xa10c6807, KEY_DOWN }, | |
| 33 | + { 0xa10ce807, KEY_LEFT }, | |
| 34 | + { 0xa10ca807, KEY_RIGHT }, | |
| 35 | + | |
| 36 | + { 0xa10c1807, KEY_SCROLLDOWN }, /* Red Thumbs Down */ | |
| 37 | + { 0xa10c9807, KEY_SELECT }, | |
| 38 | + { 0xa10c5807, KEY_SCROLLUP }, /* Green Thumbs Up */ | |
| 39 | + | |
| 40 | + { 0xa10c3807, KEY_VOLUMEUP }, | |
| 41 | + { 0xa10cb807, KEY_VOLUMEDOWN }, | |
| 42 | + { 0xa10cd807, KEY_MUTE }, | |
| 43 | + { 0xa10c040b, KEY_RECORD }, | |
| 44 | + { 0xa10c7807, KEY_CHANNELUP }, | |
| 45 | + { 0xa10cf807, KEY_CHANNELDOWN }, | |
| 46 | + { 0x0085301f, KEY_CHANNELDOWN }, | |
| 47 | + | |
| 48 | + { 0xa10c840b, KEY_PLAY }, | |
| 49 | + { 0xa10cc40b, KEY_PAUSE }, | |
| 50 | + { 0xa10ca40b, KEY_SLOW }, | |
| 51 | + { 0xa10c440b, KEY_REWIND }, | |
| 52 | + { 0xa10c240b, KEY_FASTFORWARD }, | |
| 53 | + { 0xa10c640b, KEY_PREVIOUS }, | |
| 54 | + { 0xa10ce40b, KEY_NEXT }, /* ->| */ | |
| 55 | + | |
| 56 | + { 0xa10c220d, KEY_ZOOM }, /* Aspect */ | |
| 57 | + { 0xa10c120d, KEY_STOP }, | |
| 58 | + { 0xa10c520d, KEY_DVD }, /* DVD Menu */ | |
| 59 | + | |
| 60 | + { 0xa10c140b, KEY_NUMERIC_1 }, | |
| 61 | + { 0xa10c940b, KEY_NUMERIC_2 }, | |
| 62 | + { 0xa10c540b, KEY_NUMERIC_3 }, | |
| 63 | + { 0xa10cd40b, KEY_NUMERIC_4 }, | |
| 64 | + { 0xa10c340b, KEY_NUMERIC_5 }, | |
| 65 | + { 0xa10cb40b, KEY_NUMERIC_6 }, | |
| 66 | + { 0xa10c740b, KEY_NUMERIC_7 }, | |
| 67 | + { 0xa10cf40b, KEY_NUMERIC_8 }, | |
| 68 | + { 0x0085302f, KEY_NUMERIC_8 }, | |
| 69 | + { 0xa10c0c03, KEY_NUMERIC_9 }, | |
| 70 | + { 0xa10c8c03, KEY_NUMERIC_0 }, | |
| 71 | + { 0xa10ccc03, KEY_ENTER }, | |
| 72 | + { 0xa10c4c03, KEY_CLEAR }, | |
| 73 | +}; | |
| 74 | + | |
| 75 | +static struct rc_map_list tivo_map = { | |
| 76 | + .map = { | |
| 77 | + .scan = tivo, | |
| 78 | + .size = ARRAY_SIZE(tivo), | |
| 79 | + .rc_type = RC_TYPE_NEC, | |
| 80 | + .name = RC_MAP_TIVO, | |
| 81 | + } | |
| 82 | +}; | |
| 83 | + | |
| 84 | +static int __init init_rc_map_tivo(void) | |
| 85 | +{ | |
| 86 | + return rc_map_register(&tivo_map); | |
| 87 | +} | |
| 88 | + | |
| 89 | +static void __exit exit_rc_map_tivo(void) | |
| 90 | +{ | |
| 91 | + rc_map_unregister(&tivo_map); | |
| 92 | +} | |
| 93 | + | |
| 94 | +module_init(init_rc_map_tivo) | |
| 95 | +module_exit(exit_rc_map_tivo) | |
| 96 | + | |
| 97 | +MODULE_LICENSE("GPL"); | |
| 98 | +MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>"); | |
| @@ -32,8 +32,8 @@ static struct rc_map_table winfast[] = { · 31 unmodified lines | ||
| 32 | 32 | { 0x02, KEY_TUNER }, /* TV/FM, not on Y0400052 */ |
| 33 | 33 | { 0x1e, KEY_VIDEO }, /* Video Source */ |
| 34 | 34 | { 0x16, KEY_INFO }, /* Display information */ |
| 35 | − { 0x04, KEY_LEFT }, | |
| 36 | − { 0x08, KEY_RIGHT }, | |
| 35 | + { 0x04, KEY_RIGHT }, | |
| 36 | + { 0x08, KEY_LEFT }, | |
| 37 | 37 | { 0x0c, KEY_UP }, |
| 38 | 38 | { 0x10, KEY_DOWN }, |
| 39 | 39 | { 0x03, KEY_ZOOM }, /* fullscreen */ |
| @@ -149,6 +149,8 @@ enum mceusb_model_type { · 148 unmodified lines | ||
| 149 | 149 | POLARIS_EVK, |
| 150 | 150 | CX_HYBRID_TV, |
| 151 | 151 | MULTIFUNCTION, |
| 152 | + TIVO_KIT, | |
| 153 | + MCE_GEN2_NO_TX, | |
| 152 | 154 | }; |
| 153 | 155 | |
| 154 | 156 | struct mceusb_model { |
| @@ -172,6 +174,10 @@ static const struct mceusb_model mceusb_model[] = { · 17 unmodified lines | ||
| 172 | 174 | [MCE_GEN2] = { |
| 173 | 175 | .mce_gen2 = 1, |
| 174 | 176 | }, |
| 177 | + [MCE_GEN2_NO_TX] = { | |
| 178 | + .mce_gen2 = 1, | |
| 179 | + .no_tx = 1, | |
| 180 | + }, | |
| 175 | 181 | [MCE_GEN2_TX_INV] = { |
| 176 | 182 | .mce_gen2 = 1, |
| 177 | 183 | .tx_mask_normal = 1, |
| @@ -197,6 +203,10 @@ static const struct mceusb_model mceusb_model[] = { · 19 unmodified lines | ||
| 197 | 203 | .mce_gen2 = 1, |
| 198 | 204 | .ir_intfnum = 2, |
| 199 | 205 | }, |
| 206 | + [TIVO_KIT] = { | |
| 207 | + .mce_gen2 = 1, | |
| 208 | + .rc_map = RC_MAP_TIVO, | |
| 209 | + }, | |
| 200 | 210 | }; |
| 201 | 211 | |
| 202 | 212 | static struct usb_device_id mceusb_dev_table[] = { |
| @@ -279,7 +289,8 @@ static struct usb_device_id mceusb_dev_table[] = { · 76 unmodified lines | ||
| 279 | 289 | /* Formosa21 / eHome Infrared Receiver */ |
| 280 | 290 | { USB_DEVICE(VENDOR_FORMOSA, 0xe016) }, |
| 281 | 291 | /* Formosa aim / Trust MCE Infrared Receiver */ |
| 282 | − { USB_DEVICE(VENDOR_FORMOSA, 0xe017) }, | |
| 292 | + { USB_DEVICE(VENDOR_FORMOSA, 0xe017), | |
| 293 | + .driver_info = MCE_GEN2_NO_TX }, | |
| 283 | 294 | /* Formosa Industrial Computing / Beanbag Emulation Device */ |
| 284 | 295 | { USB_DEVICE(VENDOR_FORMOSA, 0xe018) }, |
| 285 | 296 | /* Formosa21 / eHome Infrared Receiver */ |
| @@ -308,7 +319,8 @@ static struct usb_device_id mceusb_dev_table[] = { · 22 unmodified lines | ||
| 308 | 319 | /* Northstar Systems, Inc. eHome Infrared Transceiver */ |
| 309 | 320 | { USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) }, |
| 310 | 321 | /* TiVo PC IR Receiver */ |
| 311 | − { USB_DEVICE(VENDOR_TIVO, 0x2000) }, | |
| 322 | + { USB_DEVICE(VENDOR_TIVO, 0x2000), | |
| 323 | + .driver_info = TIVO_KIT }, | |
| 312 | 324 | /* Conexant Hybrid TV "Shelby" Polaris SDK */ |
| 313 | 325 | { USB_DEVICE(VENDOR_CONEXANT, 0x58a1), |
| 314 | 326 | .driver_info = POLARIS_EVK }, |
| @@ -603,11 +615,10 @@ static void mce_async_callback(struct urb *urb, struct pt_regs *regs) · 288 unmodified lines | ||
| 603 | 615 | } |
| 604 | 616 | |
| 605 | 617 | /* request incoming or send outgoing usb packet - used to initialize remote */ |
| 606 | −static void mce_request_packet(struct mceusb_dev *ir, | |
| 607 | − struct usb_endpoint_descriptor *ep, | |
| 608 | − unsigned char *data, int size, int urb_type) | |
| 618 | +static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data, | |
| 619 | + int size, int urb_type) | |
| 609 | 620 | { |
| 610 | − int res; | |
| 621 | + int res, pipe; | |
| 611 | 622 | struct urb *async_urb; |
| 612 | 623 | struct device *dev = ir->dev; |
| 613 | 624 | unsigned char *async_buf; |
| @@ -627,10 +638,11 @@ static void mce_request_packet(struct mceusb_dev *ir, · 13 unmodified lines | ||
| 627 | 638 | } |
| 628 | 639 | |
| 629 | 640 | /* outbound data */ |
| 630 | − usb_fill_int_urb(async_urb, ir->usbdev, | |
| 631 | − usb_sndintpipe(ir->usbdev, ep->bEndpointAddress), | |
| 641 | + pipe = usb_sndintpipe(ir->usbdev, | |
| 642 | + ir->usb_ep_out->bEndpointAddress); | |
| 643 | + usb_fill_int_urb(async_urb, ir->usbdev, pipe, | |
| 632 | 644 | async_buf, size, (usb_complete_t)mce_async_callback, |
| 633 | − ir, ep->bInterval); | |
| 645 | + ir, ir->usb_ep_out->bInterval); | |
| 634 | 646 | memcpy(async_buf, data, size); |
| 635 | 647 | |
| 636 | 648 | } else if (urb_type == MCEUSB_RX) { |
| @@ -658,12 +670,12 @@ static void mce_request_packet(struct mceusb_dev *ir, · 21 unmodified lines | ||
| 658 | 670 | |
| 659 | 671 | static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size) |
| 660 | 672 | { |
| 661 | − mce_request_packet(ir, ir->usb_ep_out, data, size, MCEUSB_TX); | |
| 673 | + mce_request_packet(ir, data, size, MCEUSB_TX); | |
| 662 | 674 | } |
| 663 | 675 | |
| 664 | 676 | static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size) |
| 665 | 677 | { |
| 666 | − mce_request_packet(ir, ir->usb_ep_in, data, size, MCEUSB_RX); | |
| 678 | + mce_request_packet(ir, data, size, MCEUSB_RX); | |
| 667 | 679 | } |
| 668 | 680 | |
| 669 | 681 | /* Send data out the IR blaster port(s) */ |
| @@ -37,8 +37,6 @@ · 36 unmodified lines | ||
| 37 | 37 | |
| 38 | 38 | #include "nuvoton-cir.h" |
| 39 | 39 | |
| 40 | −static char *chip_id = "w836x7hg"; | |
| 41 | − | |
| 42 | 40 | /* write val to config reg */ |
| 43 | 41 | static inline void nvt_cr_write(struct nvt_dev *nvt, u8 val, u8 reg) |
| 44 | 42 | { |
| @@ -233,6 +231,8 @@ static int nvt_hw_detect(struct nvt_dev *nvt) · 188 unmodified lines | ||
| 233 | 231 | unsigned long flags; |
| 234 | 232 | u8 chip_major, chip_minor; |
| 235 | 233 | int ret = 0; |
| 234 | + char chip_id[12]; | |
| 235 | + bool chip_unknown = false; | |
| 236 | 236 | |
| 237 | 237 | nvt_efm_enable(nvt); |
| 238 | 238 | |
| @@ -246,15 +246,39 @@ static int nvt_hw_detect(struct nvt_dev *nvt) · 7 unmodified lines | ||
| 246 | 246 | } |
| 247 | 247 | |
| 248 | 248 | chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); |
| 249 | − nvt_dbg("%s: chip id: 0x%02x 0x%02x", chip_id, chip_major, chip_minor); | |
| 250 | 249 | |
| 251 | − if (chip_major != CHIP_ID_HIGH || | |
| 252 | − (chip_minor != CHIP_ID_LOW && chip_minor != CHIP_ID_LOW2)) { | |
| 253 | − nvt_pr(KERN_ERR, "%s: unsupported chip, id: 0x%02x 0x%02x", | |
| 254 | − chip_id, chip_major, chip_minor); | |
| 255 | − ret = -ENODEV; | |
| 250 | + /* these are the known working chip revisions... */ | |
| 251 | + switch (chip_major) { | |
| 252 | + case CHIP_ID_HIGH_667: | |
| 253 | + strcpy(chip_id, "w83667hg\0"); | |
| 254 | + if (chip_minor != CHIP_ID_LOW_667) | |
| 255 | + chip_unknown = true; | |
| 256 | + break; | |
| 257 | + case CHIP_ID_HIGH_677B: | |
| 258 | + strcpy(chip_id, "w83677hg\0"); | |
| 259 | + if (chip_minor != CHIP_ID_LOW_677B2 && | |
| 260 | + chip_minor != CHIP_ID_LOW_677B3) | |
| 261 | + chip_unknown = true; | |
| 262 | + break; | |
| 263 | + case CHIP_ID_HIGH_677C: | |
| 264 | + strcpy(chip_id, "w83677hg-c\0"); | |
| 265 | + if (chip_minor != CHIP_ID_LOW_677C) | |
| 266 | + chip_unknown = true; | |
| 267 | + break; | |
| 268 | + default: | |
| 269 | + strcpy(chip_id, "w836x7hg\0"); | |
| 270 | + chip_unknown = true; | |
| 271 | + break; | |
| 256 | 272 | } |
| 257 | 273 | |
| 274 | + /* warn, but still let the driver load, if we don't know this chip */ | |
| 275 | + if (chip_unknown) | |
| 276 | + nvt_pr(KERN_WARNING, "%s: unknown chip, id: 0x%02x 0x%02x, " | |
| 277 | + "it may not work...", chip_id, chip_major, chip_minor); | |
| 278 | + else | |
| 279 | + nvt_dbg("%s: chip id: 0x%02x 0x%02x", | |
| 280 | + chip_id, chip_major, chip_minor); | |
| 281 | + | |
| 258 | 282 | nvt_efm_disable(nvt); |
| 259 | 283 | |
| 260 | 284 | spin_lock_irqsave(&nvt->nvt_lock, flags); |
| @@ -267,13 +291,23 @@ static int nvt_hw_detect(struct nvt_dev *nvt) · 6 unmodified lines | ||
| 267 | 291 | |
| 268 | 292 | static void nvt_cir_ldev_init(struct nvt_dev *nvt) |
| 269 | 293 | { |
| 270 | − u8 val; | |
| 294 | + u8 val, psreg, psmask, psval; | |
| 295 | + | |
| 296 | + if (nvt->chip_major == CHIP_ID_HIGH_667) { | |
| 297 | + psreg = CR_MULTIFUNC_PIN_SEL; | |
| 298 | + psmask = MULTIFUNC_PIN_SEL_MASK; | |
| 299 | + psval = MULTIFUNC_ENABLE_CIR | MULTIFUNC_ENABLE_CIRWB; | |
| 300 | + } else { | |
| 301 | + psreg = CR_OUTPUT_PIN_SEL; | |
| 302 | + psmask = OUTPUT_PIN_SEL_MASK; | |
| 303 | + psval = OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB; | |
| 304 | + } | |
| 271 | 305 | |
| 272 | − /* output pin selection (Pin95=CIRRX, Pin96=CIRTX1, WB enabled */ | |
| 273 | − val = nvt_cr_read(nvt, CR_OUTPUT_PIN_SEL); | |
| 274 | − val &= OUTPUT_PIN_SEL_MASK; | |
| 275 | − val |= (OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB); | |
| 276 | − nvt_cr_write(nvt, val, CR_OUTPUT_PIN_SEL); | |
| 306 | + /* output pin selection: enable CIR, with WB sensor enabled */ | |
| 307 | + val = nvt_cr_read(nvt, psreg); | |
| 308 | + val &= psmask; | |
| 309 | + val |= psval; | |
| 310 | + nvt_cr_write(nvt, val, psreg); | |
| 277 | 311 | |
| 278 | 312 | /* Select CIR logical device and enable */ |
| 279 | 313 | nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); |
| @@ -640,7 +674,7 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt) · 360 unmodified lines | ||
| 640 | 674 | rawir.pulse ? "pulse" : "space", |
| 641 | 675 | rawir.duration); |
| 642 | 676 | |
| 643 | − ir_raw_event_store(nvt->rdev, &rawir); | |
| 677 | + ir_raw_event_store_with_filter(nvt->rdev, &rawir); | |
| 644 | 678 | } |
| 645 | 679 | |
| 646 | 680 | /* |
| @@ -1070,18 +1104,20 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) · 423 unmodified lines | ||
| 1070 | 1104 | rdev->tx_ir = nvt_tx_ir; |
| 1071 | 1105 | rdev->s_tx_carrier = nvt_set_tx_carrier; |
| 1072 | 1106 | rdev->input_name = "Nuvoton w836x7hg Infrared Remote Transceiver"; |
| 1107 | + rdev->input_phys = "nuvoton/cir0"; | |
| 1073 | 1108 | rdev->input_id.bustype = BUS_HOST; |
| 1074 | 1109 | rdev->input_id.vendor = PCI_VENDOR_ID_WINBOND2; |
| 1075 | 1110 | rdev->input_id.product = nvt->chip_major; |
| 1076 | 1111 | rdev->input_id.version = nvt->chip_minor; |
| 1112 | + rdev->dev.parent = &pdev->dev; | |
| 1077 | 1113 | rdev->driver_name = NVT_DRIVER_NAME; |
| 1078 | 1114 | rdev->map_name = RC_MAP_RC6_MCE; |
| 1115 | + rdev->timeout = US_TO_NS(1000); | |
| 1116 | + /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ | |
| 1117 | + rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD); | |
| 1079 | 1118 | #if 0 |
| 1080 | 1119 | rdev->min_timeout = XYZ; |
| 1081 | 1120 | rdev->max_timeout = XYZ; |
| 1082 | − rdev->timeout = XYZ; | |
| 1083 | − /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ | |
| 1084 | − rdev->rx_resolution = XYZ; | |
| 1085 | 1121 | /* tx bits */ |
| 1086 | 1122 | rdev->tx_resolution = XYZ; |
| 1087 | 1123 | #endif |
| @@ -1090,8 +1126,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) · 2 unmodified lines | ||
| 1090 | 1126 | if (ret) |
| 1091 | 1127 | goto failure; |
| 1092 | 1128 | |
| 1093 | − device_set_wakeup_capable(&pdev->dev, 1); | |
| 1094 | − device_set_wakeup_enable(&pdev->dev, 1); | |
| 1129 | + device_init_wakeup(&pdev->dev, true); | |
| 1095 | 1130 | nvt->rdev = rdev; |
| 1096 | 1131 | nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n"); |
| 1097 | 1132 | if (debug) { |
| @@ -330,9 +330,13 @@ struct nvt_dev { · 329 unmodified lines | ||
| 330 | 330 | #define EFER_EFM_DISABLE 0xaa |
| 331 | 331 | |
| 332 | 332 | /* Chip IDs found in CR_CHIP_ID_{HI,LO} */ |
| 333 | −#define CHIP_ID_HIGH 0xb4 | |
| 334 | −#define CHIP_ID_LOW 0x72 | |
| 335 | −#define CHIP_ID_LOW2 0x73 | |
| 333 | +#define CHIP_ID_HIGH_667 0xa5 | |
| 334 | +#define CHIP_ID_HIGH_677B 0xb4 | |
| 335 | +#define CHIP_ID_HIGH_677C 0xc3 | |
| 336 | +#define CHIP_ID_LOW_667 0x13 | |
| 337 | +#define CHIP_ID_LOW_677B2 0x72 | |
| 338 | +#define CHIP_ID_LOW_677B3 0x73 | |
| 339 | +#define CHIP_ID_LOW_677C 0x33 | |
| 336 | 340 | |
| 337 | 341 | /* Config regs we need to care about */ |
| 338 | 342 | #define CR_SOFTWARE_RESET 0x02 |
| @@ -341,6 +345,7 @@ struct nvt_dev { · 2 unmodified lines | ||
| 341 | 345 | #define CR_CHIP_ID_LO 0x21 |
| 342 | 346 | #define CR_DEV_POWER_DOWN 0x22 /* bit 2 is CIR power, default power on */ |
| 343 | 347 | #define CR_OUTPUT_PIN_SEL 0x27 |
| 348 | +#define CR_MULTIFUNC_PIN_SEL 0x2c | |
| 344 | 349 | #define CR_LOGICAL_DEV_EN 0x30 /* valid for all logical devices */ |
| 345 | 350 | /* next three regs valid for both the CIR and CIR_WAKE logical devices */ |
| 346 | 351 | #define CR_CIR_BASE_ADDR_HI 0x60 |
| @@ -364,10 +369,16 @@ struct nvt_dev { · 17 unmodified lines | ||
| 364 | 369 | #define CIR_INTR_MOUSE_IRQ_BIT 0x80 |
| 365 | 370 | #define PME_INTR_CIR_PASS_BIT 0x08 |
| 366 | 371 | |
| 372 | +/* w83677hg CIR pin config */ | |
| 367 | 373 | #define OUTPUT_PIN_SEL_MASK 0xbc |
| 368 | 374 | #define OUTPUT_ENABLE_CIR 0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */ |
| 369 | 375 | #define OUTPUT_ENABLE_CIRWB 0x40 /* enable wide-band sensor */ |
| 370 | 376 | |
| 377 | +/* w83667hg CIR pin config */ | |
| 378 | +#define MULTIFUNC_PIN_SEL_MASK 0x1f | |
| 379 | +#define MULTIFUNC_ENABLE_CIR 0x80 /* Pin75=CIRRX, Pin76=CIRTX1 */ | |
| 380 | +#define MULTIFUNC_ENABLE_CIRWB 0x20 /* enable wide-band sensor */ | |
| 381 | + | |
| 371 | 382 | /* MCE CIR signal length, related on sample period */ |
| 372 | 383 | |
| 373 | 384 | /* MCE CIR controller signal length: about 43ms |
| @@ -146,6 +146,12 @@ static int loop_tx_ir(struct rc_dev *dev, int *txbuf, u32 n) · 145 unmodified lines | ||
| 146 | 146 | if (rawir.duration) |
| 147 | 147 | ir_raw_event_store_with_filter(dev, &rawir); |
| 148 | 148 | } |
| 149 | + | |
| 150 | + /* Fake a silence long enough to cause us to go idle */ | |
| 151 | + rawir.pulse = false; | |
| 152 | + rawir.duration = dev->timeout; | |
| 153 | + ir_raw_event_store_with_filter(dev, &rawir); | |
| 154 | + | |
| 149 | 155 | ir_raw_event_handle(dev); |
| 150 | 156 | |
| 151 | 157 | out: |
| @@ -749,6 +749,9 @@ static struct { · 748 unmodified lines | ||
| 749 | 749 | * it is trigged by reading /sys/class/rc/rc?/protocols. |
| 750 | 750 | * It returns the protocol names of supported protocols. |
| 751 | 751 | * Enabled protocols are printed in brackets. |
| 752 | + * | |
| 753 | + * dev->lock is taken to guard against races between device | |
| 754 | + * registration, store_protocols and show_protocols. | |
| 752 | 755 | */ |
| 753 | 756 | static ssize_t show_protocols(struct device *device, |
| 754 | 757 | struct device_attribute *mattr, char *buf) |
| @@ -762,6 +765,8 @@ static ssize_t show_protocols(struct device *device, · 7 unmodified lines | ||
| 762 | 765 | if (!dev) |
| 763 | 766 | return -EINVAL; |
| 764 | 767 | |
| 768 | + mutex_lock(&dev->lock); | |
| 769 | + | |
| 765 | 770 | if (dev->driver_type == RC_DRIVER_SCANCODE) { |
| 766 | 771 | enabled = dev->rc_map.rc_type; |
| 767 | 772 | allowed = dev->allowed_protos; |
| @@ -784,6 +789,9 @@ static ssize_t show_protocols(struct device *device, · 16 unmodified lines | ||
| 784 | 789 | if (tmp != buf) |
| 785 | 790 | tmp--; |
| 786 | 791 | *tmp = '\n'; |
| 792 | + | |
| 793 | + mutex_unlock(&dev->lock); | |
| 794 | + | |
| 787 | 795 | return tmp + 1 - buf; |
| 788 | 796 | } |
| 789 | 797 | |
| @@ -802,6 +810,9 @@ static ssize_t show_protocols(struct device *device, · 12 unmodified lines | ||
| 802 | 810 | * Writing "none" will disable all protocols. |
| 803 | 811 | * Returns -EINVAL if an invalid protocol combination or unknown protocol name |
| 804 | 812 | * is used, otherwise @len. |
| 813 | + * | |
| 814 | + * dev->lock is taken to guard against races between device | |
| 815 | + * registration, store_protocols and show_protocols. | |
| 805 | 816 | */ |
| 806 | 817 | static ssize_t store_protocols(struct device *device, |
| 807 | 818 | struct device_attribute *mattr, |
| @@ -815,18 +826,22 @@ static ssize_t store_protocols(struct device *device, · 7 unmodified lines | ||
| 815 | 826 | u64 mask; |
| 816 | 827 | int rc, i, count = 0; |
| 817 | 828 | unsigned long flags; |
| 829 | + ssize_t ret; | |
| 818 | 830 | |
| 819 | 831 | /* Device is being removed */ |
| 820 | 832 | if (!dev) |
| 821 | 833 | return -EINVAL; |
| 822 | 834 | |
| 835 | + mutex_lock(&dev->lock); | |
| 836 | + | |
| 823 | 837 | if (dev->driver_type == RC_DRIVER_SCANCODE) |
| 824 | 838 | type = dev->rc_map.rc_type; |
| 825 | 839 | else if (dev->raw) |
| 826 | 840 | type = dev->raw->enabled_protocols; |
| 827 | 841 | else { |
| 828 | 842 | IR_dprintk(1, "Protocol switching not supported\n"); |
| 829 | − return -EINVAL; | |
| 843 | + ret = -EINVAL; | |
| 844 | + goto out; | |
| 830 | 845 | } |
| 831 | 846 | |
| 832 | 847 | while ((tmp = strsep((char **) &data, " \n")) != NULL) { |
| @@ -860,7 +875,8 @@ static ssize_t store_protocols(struct device *device, · 27 unmodified lines | ||
| 860 | 875 | } |
| 861 | 876 | if (i == ARRAY_SIZE(proto_names)) { |
| 862 | 877 | IR_dprintk(1, "Unknown protocol: '%s'\n", tmp); |
| 863 | − return -EINVAL; | |
| 878 | + ret = -EINVAL; | |
| 879 | + goto out; | |
| 864 | 880 | } |
| 865 | 881 | count++; |
| 866 | 882 | } |
| @@ -875,7 +891,8 @@ static ssize_t store_protocols(struct device *device, · 8 unmodified lines | ||
| 875 | 891 | |
| 876 | 892 | if (!count) { |
| 877 | 893 | IR_dprintk(1, "Protocol not specified\n"); |
| 878 | − return -EINVAL; | |
| 894 | + ret = -EINVAL; | |
| 895 | + goto out; | |
| 879 | 896 | } |
| 880 | 897 | |
| 881 | 898 | if (dev->change_protocol) { |
| @@ -883,7 +900,8 @@ static ssize_t store_protocols(struct device *device, · 1 unmodified line | ||
| 883 | 900 | if (rc < 0) { |
| 884 | 901 | IR_dprintk(1, "Error setting protocols to 0x%llx\n", |
| 885 | 902 | (long long)type); |
| 886 | − return -EINVAL; | |
| 903 | + ret = -EINVAL; | |
| 904 | + goto out; | |
| 887 | 905 | } |
| 888 | 906 | } |
| 889 | 907 | |
| @@ -898,7 +916,11 @@ static ssize_t store_protocols(struct device *device, · 8 unmodified lines | ||
| 898 | 916 | IR_dprintk(1, "Current protocol(s): 0x%llx\n", |
| 899 | 917 | (long long)type); |
| 900 | 918 | |
| 901 | − return len; | |
| 919 | + ret = len; | |
| 920 | + | |
| 921 | +out: | |
| 922 | + mutex_unlock(&dev->lock); | |
| 923 | + return ret; | |
| 902 | 924 | } |
| 903 | 925 | |
| 904 | 926 | static void rc_dev_release(struct device *device) |
| @@ -974,6 +996,7 @@ struct rc_dev *rc_allocate_device(void) · 69 unmodified lines | ||
| 974 | 996 | |
| 975 | 997 | spin_lock_init(&dev->rc_map.lock); |
| 976 | 998 | spin_lock_init(&dev->keylock); |
| 999 | + mutex_init(&dev->lock); | |
| 977 | 1000 | setup_timer(&dev->timer_keyup, ir_timer_keyup, (unsigned long)dev); |
| 978 | 1001 | |
| 979 | 1002 | dev->dev.type = &rc_dev_type; |
| @@ -1019,12 +1042,21 @@ int rc_register_device(struct rc_dev *dev) · 39 unmodified lines | ||
| 1019 | 1042 | if (dev->close) |
| 1020 | 1043 | dev->input_dev->close = ir_close; |
| 1021 | 1044 | |
| 1045 | + /* | |
| 1046 | + * Take the lock here, as the device sysfs node will appear | |
| 1047 | + * when device_add() is called, which may trigger an ir-keytable udev | |
| 1048 | + * rule, which will in turn call show_protocols and access either | |
| 1049 | + * dev->rc_map.rc_type or dev->raw->enabled_protocols before it has | |
| 1050 | + * been initialized. | |
| 1051 | + */ | |
| 1052 | + mutex_lock(&dev->lock); | |
| 1053 | + | |
| 1022 | 1054 | dev->devno = (unsigned long)(atomic_inc_return(&devno) - 1); |
| 1023 | 1055 | dev_set_name(&dev->dev, "rc%ld", dev->devno); |
| 1024 | 1056 | dev_set_drvdata(&dev->dev, dev); |
| 1025 | 1057 | rc = device_add(&dev->dev); |
| 1026 | 1058 | if (rc) |
| 1027 | − return rc; | |
| 1059 | + goto out_unlock; | |
| 1028 | 1060 | |
| 1029 | 1061 | rc = ir_setkeytable(dev, rc_map); |
| 1030 | 1062 | if (rc) |
| @@ -1046,6 +1078,13 @@ int rc_register_device(struct rc_dev *dev) · 15 unmodified lines | ||
| 1046 | 1078 | */ |
| 1047 | 1079 | dev->input_dev->rep[REP_DELAY] = 500; |
| 1048 | 1080 | |
| 1081 | + /* | |
| 1082 | + * As a repeat event on protocols like RC-5 and NEC take as long as | |
| 1083 | + * 110/114ms, using 33ms as a repeat period is not the right thing | |
| 1084 | + * to do. | |
| 1085 | + */ | |
| 1086 | + dev->input_dev->rep[REP_PERIOD] = 125; | |
| 1087 | + | |
| 1049 | 1088 | path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); |
| 1050 | 1089 | printk(KERN_INFO "%s: %s as %s\n", |
| 1051 | 1090 | dev_name(&dev->dev), |
| @@ -1058,6 +1097,7 @@ int rc_register_device(struct rc_dev *dev) · 6 unmodified lines | ||
| 1058 | 1097 | if (rc < 0) |
| 1059 | 1098 | goto out_input; |
| 1060 | 1099 | } |
| 1100 | + mutex_unlock(&dev->lock); | |
| 1061 | 1101 | |
| 1062 | 1102 | if (dev->change_protocol) { |
| 1063 | 1103 | rc = dev->change_protocol(dev, rc_map->rc_type); |
| @@ -1083,6 +1123,8 @@ out_table: · 19 unmodified lines | ||
| 1083 | 1123 | ir_free_table(&dev->rc_map); |
| 1084 | 1124 | out_dev: |
| 1085 | 1125 | device_del(&dev->dev); |
| 1126 | +out_unlock: | |
| 1127 | + mutex_unlock(&dev->lock); | |
| 1086 | 1128 | return rc; |
| 1087 | 1129 | } |
| 1088 | 1130 | EXPORT_SYMBOL_GPL(rc_register_device); |
| @@ -0,0 +1,1344 @@ | ||
| 1 | +/* | |
| 2 | + * USB RedRat3 IR Transceiver rc-core driver | |
| 3 | + * | |
| 4 | + * Copyright (c) 2011 by Jarod Wilson <jarod@redhat.com> | |
| 5 | + * based heavily on the work of Stephen Cox, with additional | |
| 6 | + * help from RedRat Ltd. | |
| 7 | + * | |
| 8 | + * This driver began life based an an old version of the first-generation | |
| 9 | + * lirc_mceusb driver from the lirc 0.7.2 distribution. It was then | |
| 10 | + * significantly rewritten by Stephen Cox with the aid of RedRat Ltd's | |
| 11 | + * Chris Dodge. | |
| 12 | + * | |
| 13 | + * The driver was then ported to rc-core and significantly rewritten again, | |
| 14 | + * by Jarod, using the in-kernel mceusb driver as a guide, after an initial | |
| 15 | + * port effort was started by Stephen. | |
| 16 | + * | |
| 17 | + * TODO LIST: | |
| 18 | + * - fix lirc not showing repeats properly | |
| 19 | + * -- | |
| 20 | + * | |
| 21 | + * The RedRat3 is a USB transceiver with both send & receive, | |
| 22 | + * with 2 separate sensors available for receive to enable | |
| 23 | + * both good long range reception for general use, and good | |
| 24 | + * short range reception when required for learning a signal. | |
| 25 | + * | |
| 26 | + * http://www.redrat.co.uk/ | |
| 27 | + * | |
| 28 | + * It uses its own little protocol to communicate, the required | |
| 29 | + * parts of which are embedded within this driver. | |
| 30 | + * -- | |
| 31 | + * | |
| 32 | + * This program is free software; you can redistribute it and/or modify | |
| 33 | + * it under the terms of the GNU General Public License as published by | |
| 34 | + * the Free Software Foundation; either version 2 of the License, or | |
| 35 | + * (at your option) any later version. | |
| 36 | + * | |
| 37 | + * This program is distributed in the hope that it will be useful, | |
| 38 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 39 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 40 | + * GNU General Public License for more details. | |
| 41 | + * | |
| 42 | + * You should have received a copy of the GNU General Public License | |
| 43 | + * along with this program; if not, write to the Free Software | |
| 44 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 45 | + * | |
| 46 | + */ | |
| 47 | + | |
| 48 | +#include <linux/device.h> | |
| 49 | +#include <linux/module.h> | |
| 50 | +#include <linux/slab.h> | |
| 51 | +#include <linux/usb.h> | |
| 52 | +#include <linux/usb/input.h> | |
| 53 | +#include <media/rc-core.h> | |
| 54 | + | |
| 55 | +/* Driver Information */ | |
| 56 | +#define DRIVER_VERSION "0.70" | |
| 57 | +#define DRIVER_AUTHOR "Jarod Wilson <jarod@redhat.com>" | |
| 58 | +#define DRIVER_AUTHOR2 "The Dweller, Stephen Cox" | |
| 59 | +#define DRIVER_DESC "RedRat3 USB IR Transceiver Driver" | |
| 60 | +#define DRIVER_NAME "redrat3" | |
| 61 | + | |
| 62 | +/* module parameters */ | |
| 63 | +#ifdef CONFIG_USB_DEBUG | |
| 64 | +static int debug = 1; | |
| 65 | +#else | |
| 66 | +static int debug; | |
| 67 | +#endif | |
| 68 | + | |
| 69 | +#define RR3_DEBUG_STANDARD 0x1 | |
| 70 | +#define RR3_DEBUG_FUNCTION_TRACE 0x2 | |
| 71 | + | |
| 72 | +#define rr3_dbg(dev, fmt, ...) \ | |
| 73 | + do { \ | |
| 74 | + if (debug & RR3_DEBUG_STANDARD) \ | |
| 75 | + dev_info(dev, fmt, ## __VA_ARGS__); \ | |
| 76 | + } while (0) | |
| 77 | + | |
| 78 | +#define rr3_ftr(dev, fmt, ...) \ | |
| 79 | + do { \ | |
| 80 | + if (debug & RR3_DEBUG_FUNCTION_TRACE) \ | |
| 81 | + dev_info(dev, fmt, ## __VA_ARGS__); \ | |
| 82 | + } while (0) | |
| 83 | + | |
| 84 | +/* bulk data transfer types */ | |
| 85 | +#define RR3_ERROR 0x01 | |
| 86 | +#define RR3_MOD_SIGNAL_IN 0x20 | |
| 87 | +#define RR3_MOD_SIGNAL_OUT 0x21 | |
| 88 | + | |
| 89 | +/* Get the RR firmware version */ | |
| 90 | +#define RR3_FW_VERSION 0xb1 | |
| 91 | +#define RR3_FW_VERSION_LEN 64 | |
| 92 | +/* Send encoded signal bulk-sent earlier*/ | |
| 93 | +#define RR3_TX_SEND_SIGNAL 0xb3 | |
| 94 | +#define RR3_SET_IR_PARAM 0xb7 | |
| 95 | +#define RR3_GET_IR_PARAM 0xb8 | |
| 96 | +/* Blink the red LED on the device */ | |
| 97 | +#define RR3_BLINK_LED 0xb9 | |
| 98 | +/* Read serial number of device */ | |
| 99 | +#define RR3_READ_SER_NO 0xba | |
| 100 | +#define RR3_SER_NO_LEN 4 | |
| 101 | +/* Start capture with the RC receiver */ | |
| 102 | +#define RR3_RC_DET_ENABLE 0xbb | |
| 103 | +/* Stop capture with the RC receiver */ | |
| 104 | +#define RR3_RC_DET_DISABLE 0xbc | |
| 105 | +/* Return the status of RC detector capture */ | |
| 106 | +#define RR3_RC_DET_STATUS 0xbd | |
| 107 | +/* Reset redrat */ | |
| 108 | +#define RR3_RESET 0xa0 | |
| 109 | + | |
| 110 | +/* Max number of lengths in the signal. */ | |
| 111 | +#define RR3_IR_IO_MAX_LENGTHS 0x01 | |
| 112 | +/* Periods to measure mod. freq. */ | |
| 113 | +#define RR3_IR_IO_PERIODS_MF 0x02 | |
| 114 | +/* Size of memory for main signal data */ | |
| 115 | +#define RR3_IR_IO_SIG_MEM_SIZE 0x03 | |
| 116 | +/* Delta value when measuring lengths */ | |
| 117 | +#define RR3_IR_IO_LENGTH_FUZZ 0x04 | |
| 118 | +/* Timeout for end of signal detection */ | |
| 119 | +#define RR3_IR_IO_SIG_TIMEOUT 0x05 | |
| 120 | +/* Minumum value for pause recognition. */ | |
| 121 | +#define RR3_IR_IO_MIN_PAUSE 0x06 | |
| 122 | + | |
| 123 | +/* Clock freq. of EZ-USB chip */ | |
| 124 | +#define RR3_CLK 24000000 | |
| 125 | +/* Clock periods per timer count */ | |
| 126 | +#define RR3_CLK_PER_COUNT 12 | |
| 127 | +/* (RR3_CLK / RR3_CLK_PER_COUNT) */ | |
| 128 | +#define RR3_CLK_CONV_FACTOR 2000000 | |
| 129 | +/* USB bulk-in IR data endpoint address */ | |
| 130 | +#define RR3_BULK_IN_EP_ADDR 0x82 | |
| 131 | + | |
| 132 | +/* Raw Modulated signal data value offsets */ | |
| 133 | +#define RR3_PAUSE_OFFSET 0 | |
| 134 | +#define RR3_FREQ_COUNT_OFFSET 4 | |
| 135 | +#define RR3_NUM_PERIOD_OFFSET 6 | |
| 136 | +#define RR3_MAX_LENGTHS_OFFSET 8 | |
| 137 | +#define RR3_NUM_LENGTHS_OFFSET 9 | |
| 138 | +#define RR3_MAX_SIGS_OFFSET 10 | |
| 139 | +#define RR3_NUM_SIGS_OFFSET 12 | |
| 140 | +#define RR3_REPEATS_OFFSET 14 | |
| 141 | + | |
| 142 | +/* Size of the fixed-length portion of the signal */ | |
| 143 | +#define RR3_HEADER_LENGTH 15 | |
| 144 | +#define RR3_DRIVER_MAXLENS 128 | |
| 145 | +#define RR3_MAX_SIG_SIZE 512 | |
| 146 | +#define RR3_MAX_BUF_SIZE \ | |
| 147 | + ((2 * RR3_HEADER_LENGTH) + RR3_DRIVER_MAXLENS + RR3_MAX_SIG_SIZE) | |
| 148 | +#define RR3_TIME_UNIT 50 | |
| 149 | +#define RR3_END_OF_SIGNAL 0x7f | |
| 150 | +#define RR3_TX_HEADER_OFFSET 4 | |
| 151 | +#define RR3_TX_TRAILER_LEN 2 | |
| 152 | +#define RR3_RX_MIN_TIMEOUT 5 | |
| 153 | +#define RR3_RX_MAX_TIMEOUT 2000 | |
| 154 | + | |
| 155 | +/* The 8051's CPUCS Register address */ | |
| 156 | +#define RR3_CPUCS_REG_ADDR 0x7f92 | |
| 157 | + | |
| 158 | +#define USB_RR3USB_VENDOR_ID 0x112a | |
| 159 | +#define USB_RR3USB_PRODUCT_ID 0x0001 | |
| 160 | +#define USB_RR3IIUSB_PRODUCT_ID 0x0005 | |
| 161 | + | |
| 162 | +/* table of devices that work with this driver */ | |
| 163 | +static struct usb_device_id redrat3_dev_table[] = { | |
| 164 | + /* Original version of the RedRat3 */ | |
| 165 | + {USB_DEVICE(USB_RR3USB_VENDOR_ID, USB_RR3USB_PRODUCT_ID)}, | |
| 166 | + /* Second Version/release of the RedRat3 - RetRat3-II */ | |
| 167 | + {USB_DEVICE(USB_RR3USB_VENDOR_ID, USB_RR3IIUSB_PRODUCT_ID)}, | |
| 168 | + {} /* Terminating entry */ | |
| 169 | +}; | |
| 170 | + | |
| 171 | +/* Structure to hold all of our device specific stuff */ | |
| 172 | +struct redrat3_dev { | |
| 173 | + /* core device bits */ | |
| 174 | + struct rc_dev *rc; | |
| 175 | + struct device *dev; | |
| 176 | + | |
| 177 | + /* save off the usb device pointer */ | |
| 178 | + struct usb_device *udev; | |
| 179 | + | |
| 180 | + /* the receive endpoint */ | |
| 181 | + struct usb_endpoint_descriptor *ep_in; | |
| 182 | + /* the buffer to receive data */ | |
| 183 | + unsigned char *bulk_in_buf; | |
| 184 | + /* urb used to read ir data */ | |
| 185 | + struct urb *read_urb; | |
| 186 | + | |
| 187 | + /* the send endpoint */ | |
| 188 | + struct usb_endpoint_descriptor *ep_out; | |
| 189 | + /* the buffer to send data */ | |
| 190 | + unsigned char *bulk_out_buf; | |
| 191 | + /* the urb used to send data */ | |
| 192 | + struct urb *write_urb; | |
| 193 | + | |
| 194 | + /* usb dma */ | |
| 195 | + dma_addr_t dma_in; | |
| 196 | + dma_addr_t dma_out; | |
| 197 | + | |
| 198 | + /* true if write urb is busy */ | |
| 199 | + bool write_busy; | |
| 200 | + /* wait for the write to finish */ | |
| 201 | + struct completion write_finished; | |
| 202 | + | |
| 203 | + /* locks this structure */ | |
| 204 | + struct mutex lock; | |
| 205 | + | |
| 206 | + /* rx signal timeout timer */ | |
| 207 | + struct timer_list rx_timeout; | |
| 208 | + | |
| 209 | + /* Is the device currently receiving? */ | |
| 210 | + bool recv_in_progress; | |
| 211 | + /* is the detector enabled*/ | |
| 212 | + bool det_enabled; | |
| 213 | + /* Is the device currently transmitting?*/ | |
| 214 | + bool transmitting; | |
| 215 | + | |
| 216 | + /* store for current packet */ | |
| 217 | + char pbuf[RR3_MAX_BUF_SIZE]; | |
| 218 | + u16 pktlen; | |
| 219 | + u16 pkttype; | |
| 220 | + u16 bytes_read; | |
| 221 | + /* indicate whether we are going to reprocess | |
| 222 | + * the USB callback with a bigger buffer */ | |
| 223 | + int buftoosmall; | |
| 224 | + char *datap; | |
| 225 | + | |
| 226 | + u32 carrier; | |
| 227 | + | |
| 228 | + char name[128]; | |
| 229 | + char phys[64]; | |
| 230 | +}; | |
| 231 | + | |
| 232 | +/* All incoming data buffers adhere to a very specific data format */ | |
| 233 | +struct redrat3_signal_header { | |
| 234 | + u16 length; /* Length of data being transferred */ | |
| 235 | + u16 transfer_type; /* Type of data transferred */ | |
| 236 | + u32 pause; /* Pause between main and repeat signals */ | |
| 237 | + u16 mod_freq_count; /* Value of timer on mod. freq. measurement */ | |
| 238 | + u16 no_periods; /* No. of periods over which mod. freq. is measured */ | |
| 239 | + u8 max_lengths; /* Max no. of lengths (i.e. size of array) */ | |
| 240 | + u8 no_lengths; /* Actual no. of elements in lengths array */ | |
| 241 | + u16 max_sig_size; /* Max no. of values in signal data array */ | |
| 242 | + u16 sig_size; /* Acuto no. of values in signal data array */ | |
| 243 | + u8 no_repeats; /* No. of repeats of repeat signal section */ | |
| 244 | + /* Here forward is the lengths and signal data */ | |
| 245 | +}; | |
| 246 | + | |
| 247 | +static void redrat3_dump_signal_header(struct redrat3_signal_header *header) | |
| 248 | +{ | |
| 249 | + pr_info("%s:\n", __func__); | |
| 250 | + pr_info(" * length: %u, transfer_type: 0x%02x\n", | |
| 251 | + header->length, header->transfer_type); | |
| 252 | + pr_info(" * pause: %u, freq_count: %u, no_periods: %u\n", | |
| 253 | + header->pause, header->mod_freq_count, header->no_periods); | |
| 254 | + pr_info(" * lengths: %u (max: %u)\n", | |
| 255 | + header->no_lengths, header->max_lengths); | |
| 256 | + pr_info(" * sig_size: %u (max: %u)\n", | |
| 257 | + header->sig_size, header->max_sig_size); | |
| 258 | + pr_info(" * repeats: %u\n", header->no_repeats); | |
| 259 | +} | |
| 260 | + | |
| 261 | +static void redrat3_dump_signal_data(char *buffer, u16 len) | |
| 262 | +{ | |
| 263 | + int offset, i; | |
| 264 | + char *data_vals; | |
| 265 | + | |
| 266 | + pr_info("%s:", __func__); | |
| 267 | + | |
| 268 | + offset = RR3_TX_HEADER_OFFSET + RR3_HEADER_LENGTH | |
| 269 | + + (RR3_DRIVER_MAXLENS * sizeof(u16)); | |
| 270 | + | |
| 271 | + /* read RR3_DRIVER_MAXLENS from ctrl msg */ | |
| 272 | + data_vals = buffer + offset; | |
| 273 | + | |
| 274 | + for (i = 0; i < len; i++) { | |
| 275 | + if (i % 10 == 0) | |
| 276 | + pr_cont("\n * "); | |
| 277 | + pr_cont("%02x ", *data_vals++); | |
| 278 | + } | |
| 279 | + | |
| 280 | + pr_cont("\n"); | |
| 281 | +} | |
| 282 | + | |
| 283 | +/* | |
| 284 | + * redrat3_issue_async | |
| 285 | + * | |
| 286 | + * Issues an async read to the ir data in port.. | |
| 287 | + * sets the callback to be redrat3_handle_async | |
| 288 | + */ | |
| 289 | +static void redrat3_issue_async(struct redrat3_dev *rr3) | |
| 290 | +{ | |
| 291 | + int res; | |
| 292 | + | |
| 293 | + rr3_ftr(rr3->dev, "Entering %s\n", __func__); | |
| 294 | + | |
| 295 | + if (!rr3->det_enabled) { | |
| 296 | + dev_warn(rr3->dev, "not issuing async read, " | |
| 297 | + "detector not enabled\n"); | |
| 298 | + return; | |
| 299 | + } | |
| 300 | + | |
| 301 | + memset(rr3->bulk_in_buf, 0, rr3->ep_in->wMaxPacketSize); | |
| 302 | + res = usb_submit_urb(rr3->read_urb, GFP_ATOMIC); | |
| 303 | + if (res) | |
| 304 | + rr3_dbg(rr3->dev, "%s: receive request FAILED! " | |
| 305 | + "(res %d, len %d)\n", __func__, res, | |
| 306 | + rr3->read_urb->transfer_buffer_length); | |
| 307 | +} | |
| 308 | + | |
| 309 | +static void redrat3_dump_fw_error(struct redrat3_dev *rr3, int code) | |
| 310 | +{ | |
| 311 | + if (!rr3->transmitting && (code != 0x40)) | |
| 312 | + dev_info(rr3->dev, "fw error code 0x%02x: ", code); | |
| 313 | + | |
| 314 | + switch (code) { | |
| 315 | + case 0x00: | |
| 316 | + pr_cont("No Error\n"); | |
| 317 | + break; | |
| 318 | + | |
| 319 | + /* Codes 0x20 through 0x2f are IR Firmware Errors */ | |
| 320 | + case 0x20: | |
| 321 | + pr_cont("Initial signal pulse not long enough " | |
| 322 | + "to measure carrier frequency\n"); | |
| 323 | + break; | |
| 324 | + case 0x21: | |
| 325 | + pr_cont("Not enough length values allocated for signal\n"); | |
| 326 | + break; | |
| 327 | + case 0x22: | |
| 328 | + pr_cont("Not enough memory allocated for signal data\n"); | |
| 329 | + break; | |
| 330 | + case 0x23: | |
| 331 | + pr_cont("Too many signal repeats\n"); | |
| 332 | + break; | |
| 333 | + case 0x28: | |
| 334 | + pr_cont("Insufficient memory available for IR signal " | |
| 335 | + "data memory allocation\n"); | |
| 336 | + break; | |
| 337 | + case 0x29: | |
| 338 | + pr_cont("Insufficient memory available " | |
| 339 | + "for IrDa signal data memory allocation\n"); | |
| 340 | + break; | |
| 341 | + | |
| 342 | + /* Codes 0x30 through 0x3f are USB Firmware Errors */ | |
| 343 | + case 0x30: | |
| 344 | + pr_cont("Insufficient memory available for bulk " | |
| 345 | + "transfer structure\n"); | |
| 346 | + break; | |
| 347 | + | |
| 348 | + /* | |
| 349 | + * Other error codes... These are primarily errors that can occur in | |
| 350 | + * the control messages sent to the redrat | |
| 351 | + */ | |
| 352 | + case 0x40: | |
| 353 | + if (!rr3->transmitting) | |
| 354 | + pr_cont("Signal capture has been terminated\n"); | |
| 355 | + break; | |
| 356 | + case 0x41: | |
| 357 | + pr_cont("Attempt to set/get and unknown signal I/O " | |
| 358 | + "algorithm parameter\n"); | |
| 359 | + break; | |
| 360 | + case 0x42: | |
| 361 | + pr_cont("Signal capture already started\n"); | |
| 362 | + break; | |
| 363 | + | |
| 364 | + default: | |
| 365 | + pr_cont("Unknown Error\n"); | |
| 366 | + break; | |
| 367 | + } | |
| 368 | +} | |
| 369 | + | |
| 370 | +static u32 redrat3_val_to_mod_freq(struct redrat3_signal_header *ph) | |
| 371 | +{ | |
| 372 | + u32 mod_freq = 0; | |
| 373 | + | |
| 374 | + if (ph->mod_freq_count != 0) | |
| 375 | + mod_freq = (RR3_CLK * ph->no_periods) / | |
| 376 | + (ph->mod_freq_count * RR3_CLK_PER_COUNT); | |
| 377 | + | |
| 378 | + return mod_freq; | |
| 379 | +} | |
| 380 | + | |
| 381 | +/* this function scales down the figures for the same result... */ | |
| 382 | +static u32 redrat3_len_to_us(u32 length) | |
| 383 | +{ | |
| 384 | + u32 biglen = length * 1000; | |
| 385 | + u32 divisor = (RR3_CLK_CONV_FACTOR) / 1000; | |
| 386 | + u32 result = (u32) (biglen / divisor); | |
| 387 | + | |
| 388 | + /* don't allow zero lengths to go back, breaks lirc */ | |
| 389 | + return result ? result : 1; | |
| 390 | +} | |
| 391 | + | |
| 392 | +/* | |
| 393 | + * convert us back into redrat3 lengths | |
| 394 | + * | |
| 395 | + * length * 1000 length * 1000000 | |
| 396 | + * ------------- = ---------------- = micro | |
| 397 | + * rr3clk / 1000 rr3clk | |
| 398 | + | |
| 399 | + * 6 * 2 4 * 3 micro * rr3clk micro * rr3clk / 1000 | |
| 400 | + * ----- = 4 ----- = 6 -------------- = len --------------------- | |
| 401 | + * 3 2 1000000 1000 | |
| 402 | + */ | |
| 403 | +static u32 redrat3_us_to_len(u32 microsec) | |
| 404 | +{ | |
| 405 | + u32 result; | |
| 406 | + u32 divisor; | |
| 407 | + | |
| 408 | + microsec &= IR_MAX_DURATION; | |
| 409 | + divisor = (RR3_CLK_CONV_FACTOR / 1000); | |
| 410 | + result = (u32)(microsec * divisor) / 1000; | |
| 411 | + | |
| 412 | + /* don't allow zero lengths to go back, breaks lirc */ | |
| 413 | + return result ? result : 1; | |
| 414 | + | |
| 415 | +} | |
| 416 | + | |
| 417 | +/* timer callback to send long trailing space on receive timeout */ | |
| 418 | +static void redrat3_rx_timeout(unsigned long data) | |
| 419 | +{ | |
| 420 | + struct redrat3_dev *rr3 = (struct redrat3_dev *)data; | |
| 421 | + DEFINE_IR_RAW_EVENT(rawir); | |
| 422 | + | |
| 423 | + rawir.pulse = false; | |
| 424 | + rawir.duration = rr3->rc->timeout; | |
| 425 | + rr3_dbg(rr3->dev, "storing trailing space with duration %d\n", | |
| 426 | + rawir.duration); | |
| 427 | + ir_raw_event_store_with_filter(rr3->rc, &rawir); | |
| 428 | + | |
| 429 | + rr3_dbg(rr3->dev, "calling ir_raw_event_handle\n"); | |
| 430 | + ir_raw_event_handle(rr3->rc); | |
| 431 | + | |
| 432 | + rr3_dbg(rr3->dev, "calling ir_raw_event_reset\n"); | |
| 433 | + ir_raw_event_reset(rr3->rc); | |
| 434 | +} | |
| 435 | + | |
| 436 | +static void redrat3_process_ir_data(struct redrat3_dev *rr3) | |
| 437 | +{ | |
| 438 | + DEFINE_IR_RAW_EVENT(rawir); | |
| 439 | + struct redrat3_signal_header header; | |
| 440 | + struct device *dev; | |
| 441 | + int i; | |
| 442 | + unsigned long delay; | |
| 443 | + u32 mod_freq, single_len; | |
| 444 | + u16 *len_vals; | |
| 445 | + u8 *data_vals; | |
| 446 | + u32 tmp32; | |
| 447 | + u16 tmp16; | |
| 448 | + char *sig_data; | |
| 449 | + | |
| 450 | + if (!rr3) { | |
| 451 | + pr_err("%s called with no context!\n", __func__); | |
| 452 | + return; | |
| 453 | + } | |
| 454 | + | |
| 455 | + rr3_ftr(rr3->dev, "Entered %s\n", __func__); | |
| 456 | + | |
| 457 | + dev = rr3->dev; | |
| 458 | + sig_data = rr3->pbuf; | |
| 459 | + | |
| 460 | + header.length = rr3->pktlen; | |
| 461 | + header.transfer_type = rr3->pkttype; | |
| 462 | + | |
| 463 | + /* Sanity check */ | |
| 464 | + if (!(header.length >= RR3_HEADER_LENGTH)) | |
| 465 | + dev_warn(dev, "read returned less than rr3 header len\n"); | |
| 466 | + | |
| 467 | + delay = usecs_to_jiffies(rr3->rc->timeout / 1000); | |
| 468 | + mod_timer(&rr3->rx_timeout, jiffies + delay); | |
| 469 | + | |
| 470 | + memcpy(&tmp32, sig_data + RR3_PAUSE_OFFSET, sizeof(tmp32)); | |
| 471 | + header.pause = be32_to_cpu(tmp32); | |
| 472 | + | |
| 473 | + memcpy(&tmp16, sig_data + RR3_FREQ_COUNT_OFFSET, sizeof(tmp16)); | |
| 474 | + header.mod_freq_count = be16_to_cpu(tmp16); | |
| 475 | + | |
| 476 | + memcpy(&tmp16, sig_data + RR3_NUM_PERIOD_OFFSET, sizeof(tmp16)); | |
| 477 | + header.no_periods = be16_to_cpu(tmp16); | |
| 478 | + | |
| 479 | + header.max_lengths = sig_data[RR3_MAX_LENGTHS_OFFSET]; | |
| 480 | + header.no_lengths = sig_data[RR3_NUM_LENGTHS_OFFSET]; | |
| 481 | + | |
| 482 | + memcpy(&tmp16, sig_data + RR3_MAX_SIGS_OFFSET, sizeof(tmp16)); | |
| 483 | + header.max_sig_size = be16_to_cpu(tmp16); | |
| 484 | + | |
| 485 | + memcpy(&tmp16, sig_data + RR3_NUM_SIGS_OFFSET, sizeof(tmp16)); | |
| 486 | + header.sig_size = be16_to_cpu(tmp16); | |
| 487 | + | |
| 488 | + header.no_repeats= sig_data[RR3_REPEATS_OFFSET]; | |
| 489 | + | |
| 490 | + if (debug) { | |
| 491 | + redrat3_dump_signal_header(&header); | |
| 492 | + redrat3_dump_signal_data(sig_data, header.sig_size); | |
| 493 | + } | |
| 494 | + | |
| 495 | + mod_freq = redrat3_val_to_mod_freq(&header); | |
| 496 | + rr3_dbg(dev, "Got mod_freq of %u\n", mod_freq); | |
| 497 | + | |
| 498 | + /* Here we pull out the 'length' values from the signal */ | |
| 499 | + len_vals = (u16 *)(sig_data + RR3_HEADER_LENGTH); | |
| 500 | + | |
| 501 | + data_vals = sig_data + RR3_HEADER_LENGTH + | |
| 502 | + (header.max_lengths * sizeof(u16)); | |
| 503 | + | |
| 504 | + /* process each rr3 encoded byte into an int */ | |
| 505 | + for (i = 0; i < header.sig_size; i++) { | |
| 506 | + u16 val = len_vals[data_vals[i]]; | |
| 507 | + single_len = redrat3_len_to_us((u32)be16_to_cpu(val)); | |
| 508 | + | |
| 509 | + /* cap the value to IR_MAX_DURATION */ | |
| 510 | + single_len &= IR_MAX_DURATION; | |
| 511 | + | |
| 512 | + /* we should always get pulse/space/pulse/space samples */ | |
| 513 | + if (i % 2) | |
| 514 | + rawir.pulse = false; | |
| 515 | + else | |
| 516 | + rawir.pulse = true; | |
| 517 | + | |
| 518 | + rawir.duration = US_TO_NS(single_len); | |
| 519 | + rr3_dbg(dev, "storing %s with duration %d (i: %d)\n", | |
| 520 | + rawir.pulse ? "pulse" : "space", rawir.duration, i); | |
| 521 | + ir_raw_event_store_with_filter(rr3->rc, &rawir); | |
| 522 | + } | |
| 523 | + | |
| 524 | + /* add a trailing space, if need be */ | |
| 525 | + if (i % 2) { | |
| 526 | + rawir.pulse = false; | |
| 527 | + /* this duration is made up, and may not be ideal... */ | |
| 528 | + rawir.duration = rr3->rc->timeout / 2; | |
| 529 | + rr3_dbg(dev, "storing trailing space with duration %d\n", | |
| 530 | + rawir.duration); | |
| 531 | + ir_raw_event_store_with_filter(rr3->rc, &rawir); | |
| 532 | + } | |
| 533 | + | |
| 534 | + rr3_dbg(dev, "calling ir_raw_event_handle\n"); | |
| 535 | + ir_raw_event_handle(rr3->rc); | |
| 536 | + | |
| 537 | + return; | |
| 538 | +} | |
| 539 | + | |
| 540 | +/* Util fn to send rr3 cmds */ | |
| 541 | +static u8 redrat3_send_cmd(int cmd, struct redrat3_dev *rr3) | |
| 542 | +{ | |
| 543 | + struct usb_device *udev; | |
| 544 | + u8 *data; | |
| 545 | + int res; | |
| 546 | + | |
| 547 | + data = kzalloc(sizeof(u8), GFP_KERNEL); | |
| 548 | + if (!data) | |
| 549 | + return -ENOMEM; | |
| 550 | + | |
| 551 | + udev = rr3->udev; | |
| 552 | + res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), cmd, | |
| 553 | + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | |
| 554 | + 0x0000, 0x0000, data, sizeof(u8), HZ * 10); | |
| 555 | + | |
| 556 | + if (res < 0) { | |
| 557 | + dev_err(rr3->dev, "%s: Error sending rr3 cmd res %d, data %d", | |
| 558 | + __func__, res, *data); | |
| 559 | + res = -EIO; | |
| 560 | + } else | |
| 561 | + res = (u8)data[0]; | |
| 562 | + | |
| 563 | + kfree(data); | |
| 564 | + | |
| 565 | + return res; | |
| 566 | +} | |
| 567 | + | |
| 568 | +/* Enables the long range detector and starts async receive */ | |
| 569 | +static int redrat3_enable_detector(struct redrat3_dev *rr3) | |
| 570 | +{ | |
| 571 | + struct device *dev = rr3->dev; | |
| 572 | + u8 ret; | |
| 573 | + | |
| 574 | + rr3_ftr(dev, "Entering %s\n", __func__); | |
| 575 | + | |
| 576 | + ret = redrat3_send_cmd(RR3_RC_DET_ENABLE, rr3); | |
| 577 | + if (ret != 0) | |
| 578 | + dev_dbg(dev, "%s: unexpected ret of %d\n", | |
| 579 | + __func__, ret); | |
| 580 | + | |
| 581 | + ret = redrat3_send_cmd(RR3_RC_DET_STATUS, rr3); | |
| 582 | + if (ret != 1) { | |
| 583 | + dev_err(dev, "%s: detector status: %d, should be 1\n", | |
| 584 | + __func__, ret); | |
| 585 | + return -EIO; | |
| 586 | + } | |
| 587 | + | |
| 588 | + rr3->det_enabled = true; | |
| 589 | + redrat3_issue_async(rr3); | |
| 590 | + | |
| 591 | + return 0; | |
| 592 | +} | |
| 593 | + | |
| 594 | +/* Disables the rr3 long range detector */ | |
| 595 | +static void redrat3_disable_detector(struct redrat3_dev *rr3) | |
| 596 | +{ | |
| 597 | + struct device *dev = rr3->dev; | |
| 598 | + u8 ret; | |
| 599 | + | |
| 600 | + rr3_ftr(dev, "Entering %s\n", __func__); | |
| 601 | + | |
| 602 | + ret = redrat3_send_cmd(RR3_RC_DET_DISABLE, rr3); | |
| 603 | + if (ret != 0) | |
| 604 | + dev_err(dev, "%s: failure!\n", __func__); | |
| 605 | + | |
| 606 | + ret = redrat3_send_cmd(RR3_RC_DET_STATUS, rr3); | |
| 607 | + if (ret != 0) | |
| 608 | + dev_warn(dev, "%s: detector status: %d, should be 0\n", | |
| 609 | + __func__, ret); | |
| 610 | + | |
| 611 | + rr3->det_enabled = false; | |
| 612 | +} | |
| 613 | + | |
| 614 | +static inline void redrat3_delete(struct redrat3_dev *rr3, | |
| 615 | + struct usb_device *udev) | |
| 616 | +{ | |
| 617 | + rr3_ftr(rr3->dev, "%s cleaning up\n", __func__); | |
| 618 | + usb_kill_urb(rr3->read_urb); | |
| 619 | + usb_kill_urb(rr3->write_urb); | |
| 620 | + | |
| 621 | + usb_free_urb(rr3->read_urb); | |
| 622 | + usb_free_urb(rr3->write_urb); | |
| 623 | + | |
| 624 | + usb_free_coherent(udev, rr3->ep_in->wMaxPacketSize, | |
| 625 | + rr3->bulk_in_buf, rr3->dma_in); | |
| 626 | + usb_free_coherent(udev, rr3->ep_out->wMaxPacketSize, | |
| 627 | + rr3->bulk_out_buf, rr3->dma_out); | |
| 628 | + | |
| 629 | + kfree(rr3); | |
| 630 | +} | |
| 631 | + | |
| 632 | +static u32 redrat3_get_timeout(struct device *dev, | |
| 633 | + struct rc_dev *rc, struct usb_device *udev) | |
| 634 | +{ | |
| 635 | + u32 *tmp; | |
| 636 | + u32 timeout = MS_TO_NS(150); /* a sane default, if things go haywire */ | |
| 637 | + int len, ret, pipe; | |
| 638 | + | |
| 639 | + len = sizeof(*tmp); | |
| 640 | + tmp = kzalloc(len, GFP_KERNEL); | |
| 641 | + if (!tmp) { | |
| 642 | + dev_warn(dev, "Memory allocation faillure\n"); | |
| 643 | + return timeout; | |
| 644 | + } | |
| 645 | + | |
| 646 | + pipe = usb_rcvctrlpipe(udev, 0); | |
| 647 | + ret = usb_control_msg(udev, pipe, RR3_GET_IR_PARAM, | |
| 648 | + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | |
| 649 | + RR3_IR_IO_SIG_TIMEOUT, 0, tmp, len, HZ * 5); | |
| 650 | + if (ret != len) { | |
| 651 | + dev_warn(dev, "Failed to read timeout from hardware\n"); | |
| 652 | + return timeout; | |
| 653 | + } | |
| 654 | + | |
| 655 | + timeout = US_TO_NS(redrat3_len_to_us(be32_to_cpu(*tmp))); | |
| 656 | + if (timeout < rc->min_timeout) | |
| 657 | + timeout = rc->min_timeout; | |
| 658 | + else if (timeout > rc->max_timeout) | |
| 659 | + timeout = rc->max_timeout; | |
| 660 | + | |
| 661 | + rr3_dbg(dev, "Got timeout of %d ms\n", timeout / (1000 * 1000)); | |
| 662 | + return timeout; | |
| 663 | +} | |
| 664 | + | |
| 665 | +static void redrat3_reset(struct redrat3_dev *rr3) | |
| 666 | +{ | |
| 667 | + struct usb_device *udev = rr3->udev; | |
| 668 | + struct device *dev = rr3->dev; | |
| 669 | + int rc, rxpipe, txpipe; | |
| 670 | + u8 *val; | |
| 671 | + int len = sizeof(u8); | |
| 672 | + | |
| 673 | + rr3_ftr(dev, "Entering %s\n", __func__); | |
| 674 | + | |
| 675 | + rxpipe = usb_rcvctrlpipe(udev, 0); | |
| 676 | + txpipe = usb_sndctrlpipe(udev, 0); | |
| 677 | + | |
| 678 | + val = kzalloc(len, GFP_KERNEL); | |
| 679 | + if (!val) { | |
| 680 | + dev_err(dev, "Memory allocation failure\n"); | |
| 681 | + return; | |
| 682 | + } | |
| 683 | + | |
| 684 | + *val = 0x01; | |
| 685 | + rc = usb_control_msg(udev, rxpipe, RR3_RESET, | |
| 686 | + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | |
| 687 | + RR3_CPUCS_REG_ADDR, 0, val, len, HZ * 25); | |
| 688 | + rr3_dbg(dev, "reset returned 0x%02x\n", rc); | |
| 689 | + | |
| 690 | + *val = 5; | |
| 691 | + rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM, | |
| 692 | + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | |
| 693 | + RR3_IR_IO_LENGTH_FUZZ, 0, val, len, HZ * 25); | |
| 694 | + rr3_dbg(dev, "set ir parm len fuzz %d rc 0x%02x\n", *val, rc); | |
| 695 | + | |
| 696 | + *val = RR3_DRIVER_MAXLENS; | |
| 697 | + rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM, | |
| 698 | + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | |
| 699 | + RR3_IR_IO_MAX_LENGTHS, 0, val, len, HZ * 25); | |
| 700 | + rr3_dbg(dev, "set ir parm max lens %d rc 0x%02x\n", *val, rc); | |
| 701 | + | |
| 702 | + kfree(val); | |
| 703 | +} | |
| 704 | + | |
| 705 | +static void redrat3_get_firmware_rev(struct redrat3_dev *rr3) | |
| 706 | +{ | |
| 707 | + int rc = 0; | |
| 708 | + char *buffer; | |
| 709 | + | |
| 710 | + rr3_ftr(rr3->dev, "Entering %s\n", __func__); | |
| 711 | + | |
| 712 | + buffer = kzalloc(sizeof(char) * (RR3_FW_VERSION_LEN + 1), GFP_KERNEL); | |
| 713 | + if (!buffer) { | |
| 714 | + dev_err(rr3->dev, "Memory allocation failure\n"); | |
| 715 | + return; | |
| 716 | + } | |
| 717 | + | |
| 718 | + rc = usb_control_msg(rr3->udev, usb_rcvctrlpipe(rr3->udev, 0), | |
| 719 | + RR3_FW_VERSION, | |
| 720 | + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | |
| 721 | + 0, 0, buffer, RR3_FW_VERSION_LEN, HZ * 5); | |
| 722 | + | |
| 723 | + if (rc >= 0) | |
| 724 | + dev_info(rr3->dev, "Firmware rev: %s", buffer); | |
| 725 | + else | |
| 726 | + dev_err(rr3->dev, "Problem fetching firmware ID\n"); | |
| 727 | + | |
| 728 | + kfree(buffer); | |
| 729 | + rr3_ftr(rr3->dev, "Exiting %s\n", __func__); | |
| 730 | +} | |
| 731 | + | |
| 732 | +static void redrat3_read_packet_start(struct redrat3_dev *rr3, int len) | |
| 733 | +{ | |
| 734 | + u16 tx_error; | |
| 735 | + u16 hdrlen; | |
| 736 | + | |
| 737 | + rr3_ftr(rr3->dev, "Entering %s\n", __func__); | |
| 738 | + | |
| 739 | + /* grab the Length and type of transfer */ | |
| 740 | + memcpy(&(rr3->pktlen), (unsigned char *) rr3->bulk_in_buf, | |
| 741 | + sizeof(rr3->pktlen)); | |
| 742 | + memcpy(&(rr3->pkttype), ((unsigned char *) rr3->bulk_in_buf + | |
| 743 | + sizeof(rr3->pktlen)), | |
| 744 | + sizeof(rr3->pkttype)); | |
| 745 | + | |
| 746 | + /*data needs conversion to know what its real values are*/ | |
| 747 | + rr3->pktlen = be16_to_cpu(rr3->pktlen); | |
| 748 | + rr3->pkttype = be16_to_cpu(rr3->pkttype); | |
| 749 | + | |
| 750 | + switch (rr3->pkttype) { | |
| 751 | + case RR3_ERROR: | |
| 752 | + memcpy(&tx_error, ((unsigned char *)rr3->bulk_in_buf | |
| 753 | + + (sizeof(rr3->pktlen) + sizeof(rr3->pkttype))), | |
| 754 | + sizeof(tx_error)); | |
| 755 | + tx_error = be16_to_cpu(tx_error); | |
| 756 | + redrat3_dump_fw_error(rr3, tx_error); | |
| 757 | + break; | |
| 758 | + | |
| 759 | + case RR3_MOD_SIGNAL_IN: | |
| 760 | + hdrlen = sizeof(rr3->pktlen) + sizeof(rr3->pkttype); | |
| 761 | + rr3->bytes_read = len; | |
| 762 | + rr3->bytes_read -= hdrlen; | |
| 763 | + rr3->datap = &(rr3->pbuf[0]); | |
| 764 | + | |
| 765 | + memcpy(rr3->datap, ((unsigned char *)rr3->bulk_in_buf + hdrlen), | |
| 766 | + rr3->bytes_read); | |
| 767 | + rr3->datap += rr3->bytes_read; | |
| 768 | + rr3_dbg(rr3->dev, "bytes_read %d, pktlen %d\n", | |
| 769 | + rr3->bytes_read, rr3->pktlen); | |
| 770 | + break; | |
| 771 | + | |
| 772 | + default: | |
| 773 | + rr3_dbg(rr3->dev, "ignoring packet with type 0x%02x, " | |
| 774 | + "len of %d, 0x%02x\n", rr3->pkttype, len, rr3->pktlen); | |
| 775 | + break; | |
| 776 | + } | |
| 777 | +} | |
| 778 | + | |
| 779 | +static void redrat3_read_packet_continue(struct redrat3_dev *rr3, int len) | |
| 780 | +{ | |
| 781 | + | |
| 782 | + rr3_ftr(rr3->dev, "Entering %s\n", __func__); | |
| 783 | + | |
| 784 | + memcpy(rr3->datap, (unsigned char *)rr3->bulk_in_buf, len); | |
| 785 | + rr3->datap += len; | |
| 786 | + | |
| 787 | + rr3->bytes_read += len; | |
| 788 | + rr3_dbg(rr3->dev, "bytes_read %d, pktlen %d\n", | |
| 789 | + rr3->bytes_read, rr3->pktlen); | |
| 790 | +} | |
| 791 | + | |
| 792 | +/* gather IR data from incoming urb, process it when we have enough */ | |
| 793 | +static int redrat3_get_ir_data(struct redrat3_dev *rr3, int len) | |
| 794 | +{ | |
| 795 | + struct device *dev = rr3->dev; | |
| 796 | + int ret = 0; | |
| 797 | + | |
| 798 | + rr3_ftr(dev, "Entering %s\n", __func__); | |
| 799 | + | |
| 800 | + if (rr3->pktlen > RR3_MAX_BUF_SIZE) { | |
| 801 | + dev_err(rr3->dev, "error: packet larger than buffer\n"); | |
| 802 | + ret = -EINVAL; | |
| 803 | + goto out; | |
| 804 | + } | |
| 805 | + | |
| 806 | + if ((rr3->bytes_read == 0) && | |
| 807 | + (len >= (sizeof(rr3->pkttype) + sizeof(rr3->pktlen)))) { | |
| 808 | + redrat3_read_packet_start(rr3, len); | |
| 809 | + } else if (rr3->bytes_read != 0) { | |
| 810 | + redrat3_read_packet_continue(rr3, len); | |
| 811 | + } else if (rr3->bytes_read == 0) { | |
| 812 | + dev_err(dev, "error: no packet data read\n"); | |
| 813 | + ret = -ENODATA; | |
| 814 | + goto out; | |
| 815 | + } | |
| 816 | + | |
| 817 | + if (rr3->bytes_read > rr3->pktlen) { | |
| 818 | + dev_err(dev, "bytes_read (%d) greater than pktlen (%d)\n", | |
| 819 | + rr3->bytes_read, rr3->pktlen); | |
| 820 | + ret = -EINVAL; | |
| 821 | + goto out; | |
| 822 | + } else if (rr3->bytes_read < rr3->pktlen) | |
| 823 | + /* we're still accumulating data */ | |
| 824 | + return 0; | |
| 825 | + | |
| 826 | + /* if we get here, we've got IR data to decode */ | |
| 827 | + if (rr3->pkttype == RR3_MOD_SIGNAL_IN) | |
| 828 | + redrat3_process_ir_data(rr3); | |
| 829 | + else | |
| 830 | + rr3_dbg(dev, "discarding non-signal data packet " | |
| 831 | + "(type 0x%02x)\n", rr3->pkttype); | |
| 832 | + | |
| 833 | +out: | |
| 834 | + rr3->bytes_read = 0; | |
| 835 | + rr3->pktlen = 0; | |
| 836 | + rr3->pkttype = 0; | |
| 837 | + return ret; | |
| 838 | +} | |
| 839 | + | |
| 840 | +/* callback function from USB when async USB request has completed */ | |
| 841 | +static void redrat3_handle_async(struct urb *urb, struct pt_regs *regs) | |
| 842 | +{ | |
| 843 | + struct redrat3_dev *rr3; | |
| 844 | + | |
| 845 | + if (!urb) | |
| 846 | + return; | |
| 847 | + | |
| 848 | + rr3 = urb->context; | |
| 849 | + if (!rr3) { | |
| 850 | + pr_err("%s called with invalid context!\n", __func__); | |
| 851 | + usb_unlink_urb(urb); | |
| 852 | + return; | |
| 853 | + } | |
| 854 | + | |
| 855 | + rr3_ftr(rr3->dev, "Entering %s\n", __func__); | |
| 856 | + | |
| 857 | + if (!rr3->det_enabled) { | |
| 858 | + rr3_dbg(rr3->dev, "received a read callback but detector " | |
| 859 | + "disabled - ignoring\n"); | |
| 860 | + return; | |
| 861 | + } | |
| 862 | + | |
| 863 | + switch (urb->status) { | |
| 864 | + case 0: | |
| 865 | + redrat3_get_ir_data(rr3, urb->actual_length); | |
| 866 | + break; | |
| 867 | + | |
| 868 | + case -ECONNRESET: | |
| 869 | + case -ENOENT: | |
| 870 | + case -ESHUTDOWN: | |
| 871 | + usb_unlink_urb(urb); | |
| 872 | + return; | |
| 873 | + | |
| 874 | + case -EPIPE: | |
| 875 | + default: | |
| 876 | + dev_warn(rr3->dev, "Error: urb status = %d\n", urb->status); | |
| 877 | + rr3->bytes_read = 0; | |
| 878 | + rr3->pktlen = 0; | |
| 879 | + rr3->pkttype = 0; | |
| 880 | + break; | |
| 881 | + } | |
| 882 | + | |
| 883 | + if (!rr3->transmitting) | |
| 884 | + redrat3_issue_async(rr3); | |
| 885 | + else | |
| 886 | + rr3_dbg(rr3->dev, "IR transmit in progress\n"); | |
| 887 | +} | |
| 888 | + | |
| 889 | +static void redrat3_write_bulk_callback(struct urb *urb, struct pt_regs *regs) | |
| 890 | +{ | |
| 891 | + struct redrat3_dev *rr3; | |
| 892 | + int len; | |
| 893 | + | |
| 894 | + if (!urb) | |
| 895 | + return; | |
| 896 | + | |
| 897 | + rr3 = urb->context; | |
| 898 | + if (rr3) { | |
| 899 | + len = urb->actual_length; | |
| 900 | + rr3_ftr(rr3->dev, "%s: called (status=%d len=%d)\n", | |
| 901 | + __func__, urb->status, len); | |
| 902 | + } | |
| 903 | +} | |
| 904 | + | |
| 905 | +static u16 mod_freq_to_val(unsigned int mod_freq) | |
| 906 | +{ | |
| 907 | + int mult = 6000000; | |
| 908 | + | |
| 909 | + /* Clk used in mod. freq. generation is CLK24/4. */ | |
| 910 | + return (u16)(65536 - (mult / mod_freq)); | |
| 911 | +} | |
| 912 | + | |
| 913 | +static int redrat3_set_tx_carrier(struct rc_dev *dev, u32 carrier) | |
| 914 | +{ | |
| 915 | + struct redrat3_dev *rr3 = dev->priv; | |
| 916 | + | |
| 917 | + rr3->carrier = carrier; | |
| 918 | + | |
| 919 | + return carrier; | |
| 920 | +} | |
| 921 | + | |
| 922 | +static int redrat3_transmit_ir(struct rc_dev *rcdev, int *txbuf, u32 n) | |
| 923 | +{ | |
| 924 | + struct redrat3_dev *rr3 = rcdev->priv; | |
| 925 | + struct device *dev = rr3->dev; | |
| 926 | + struct redrat3_signal_header header; | |
| 927 | + int i, j, count, ret, ret_len, offset; | |
| 928 | + int lencheck, cur_sample_len, pipe; | |
| 929 | + char *buffer = NULL, *sigdata = NULL; | |
| 930 | + int *sample_lens = NULL; | |
| 931 | + u32 tmpi; | |
| 932 | + u16 tmps; | |
| 933 | + u8 *datap; | |
| 934 | + u8 curlencheck = 0; | |
| 935 | + u16 *lengths_ptr; | |
| 936 | + int sendbuf_len; | |
| 937 | + | |
| 938 | + rr3_ftr(dev, "Entering %s\n", __func__); | |
| 939 | + | |
| 940 | + if (rr3->transmitting) { | |
| 941 | + dev_warn(dev, "%s: transmitter already in use\n", __func__); | |
| 942 | + return -EAGAIN; | |
| 943 | + } | |
| 944 | + | |
| 945 | + count = n / sizeof(int); | |
| 946 | + if (count > (RR3_DRIVER_MAXLENS * 2)) | |
| 947 | + return -EINVAL; | |
| 948 | + | |
| 949 | + rr3->transmitting = true; | |
| 950 | + | |
| 951 | + redrat3_disable_detector(rr3); | |
| 952 | + | |
| 953 | + if (rr3->det_enabled) { | |
| 954 | + dev_err(dev, "%s: cannot tx while rx is enabled\n", __func__); | |
| 955 | + ret = -EIO; | |
| 956 | + goto out; | |
| 957 | + } | |
| 958 | + | |
| 959 | + sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL); | |
| 960 | + if (!sample_lens) { | |
| 961 | + ret = -ENOMEM; | |
| 962 | + goto out; | |
| 963 | + } | |
| 964 | + | |
| 965 | + for (i = 0; i < count; i++) { | |
| 966 | + for (lencheck = 0; lencheck < curlencheck; lencheck++) { | |
| 967 | + cur_sample_len = redrat3_us_to_len(txbuf[i]); | |
| 968 | + if (sample_lens[lencheck] == cur_sample_len) | |
| 969 | + break; | |
| 970 | + } | |
| 971 | + if (lencheck == curlencheck) { | |
| 972 | + cur_sample_len = redrat3_us_to_len(txbuf[i]); | |
| 973 | + rr3_dbg(dev, "txbuf[%d]=%u, pos %d, enc %u\n", | |
| 974 | + i, txbuf[i], curlencheck, cur_sample_len); | |
| 975 | + if (curlencheck < 255) { | |
| 976 | + /* now convert the value to a proper | |
| 977 | + * rr3 value.. */ | |
| 978 | + sample_lens[curlencheck] = cur_sample_len; | |
| 979 | + curlencheck++; | |
| 980 | + } else { | |
| 981 | + dev_err(dev, "signal too long\n"); | |
| 982 | + ret = -EINVAL; | |
| 983 | + goto out; | |
| 984 | + } | |
| 985 | + } | |
| 986 | + } | |
| 987 | + | |
| 988 | + sigdata = kzalloc((count + RR3_TX_TRAILER_LEN), GFP_KERNEL); | |
| 989 | + if (!sigdata) { | |
| 990 | + ret = -ENOMEM; | |
| 991 | + goto out; | |
| 992 | + } | |
| 993 | + | |
| 994 | + sigdata[count] = RR3_END_OF_SIGNAL; | |
| 995 | + sigdata[count + 1] = RR3_END_OF_SIGNAL; | |
| 996 | + for (i = 0; i < count; i++) { | |
| 997 | + for (j = 0; j < curlencheck; j++) { | |
| 998 | + if (sample_lens[j] == redrat3_us_to_len(txbuf[i])) | |
| 999 | + sigdata[i] = j; | |
| 1000 | + } | |
| 1001 | + } | |
| 1002 | + | |
| 1003 | + offset = RR3_TX_HEADER_OFFSET; | |
| 1004 | + sendbuf_len = RR3_HEADER_LENGTH + (sizeof(u16) * RR3_DRIVER_MAXLENS) | |
| 1005 | + + count + RR3_TX_TRAILER_LEN + offset; | |
| 1006 | + | |
| 1007 | + buffer = kzalloc(sendbuf_len, GFP_KERNEL); | |
| 1008 | + if (!buffer) { | |
| 1009 | + ret = -ENOMEM; | |
| 1010 | + goto out; | |
| 1011 | + } | |
| 1012 | + | |
| 1013 | + /* fill in our packet header */ | |
| 1014 | + header.length = sendbuf_len - offset; | |
| 1015 | + header.transfer_type = RR3_MOD_SIGNAL_OUT; | |
| 1016 | + header.pause = redrat3_len_to_us(100); | |
| 1017 | + header.mod_freq_count = mod_freq_to_val(rr3->carrier); | |
| 1018 | + header.no_periods = 0; /* n/a to transmit */ | |
| 1019 | + header.max_lengths = RR3_DRIVER_MAXLENS; | |
| 1020 | + header.no_lengths = curlencheck; | |
| 1021 | + header.max_sig_size = RR3_MAX_SIG_SIZE; | |
| 1022 | + header.sig_size = count + RR3_TX_TRAILER_LEN; | |
| 1023 | + /* we currently rely on repeat handling in the IR encoding source */ | |
| 1024 | + header.no_repeats = 0; | |
| 1025 | + | |
| 1026 | + tmps = cpu_to_be16(header.length); | |
| 1027 | + memcpy(buffer, &tmps, 2); | |
| 1028 | + | |
| 1029 | + tmps = cpu_to_be16(header.transfer_type); | |
| 1030 | + memcpy(buffer + 2, &tmps, 2); | |
| 1031 | + | |
| 1032 | + tmpi = cpu_to_be32(header.pause); | |
| 1033 | + memcpy(buffer + offset, &tmpi, sizeof(tmpi)); | |
| 1034 | + | |
| 1035 | + tmps = cpu_to_be16(header.mod_freq_count); | |
| 1036 | + memcpy(buffer + offset + RR3_FREQ_COUNT_OFFSET, &tmps, 2); | |
| 1037 | + | |
| 1038 | + buffer[offset + RR3_NUM_LENGTHS_OFFSET] = header.no_lengths; | |
| 1039 | + | |
| 1040 | + tmps = cpu_to_be16(header.sig_size); | |
| 1041 | + memcpy(buffer + offset + RR3_NUM_SIGS_OFFSET, &tmps, 2); | |
| 1042 | + | |
| 1043 | + buffer[offset + RR3_REPEATS_OFFSET] = header.no_repeats; | |
| 1044 | + | |
| 1045 | + lengths_ptr = (u16 *)(buffer + offset + RR3_HEADER_LENGTH); | |
| 1046 | + for (i = 0; i < curlencheck; ++i) | |
| 1047 | + lengths_ptr[i] = cpu_to_be16(sample_lens[i]); | |
| 1048 | + | |
| 1049 | + datap = (u8 *)(buffer + offset + RR3_HEADER_LENGTH + | |
| 1050 | + (sizeof(u16) * RR3_DRIVER_MAXLENS)); | |
| 1051 | + memcpy(datap, sigdata, (count + RR3_TX_TRAILER_LEN)); | |
| 1052 | + | |
| 1053 | + if (debug) { | |
| 1054 | + redrat3_dump_signal_header(&header); | |
| 1055 | + redrat3_dump_signal_data(buffer, header.sig_size); | |
| 1056 | + } | |
| 1057 | + | |
| 1058 | + pipe = usb_sndbulkpipe(rr3->udev, rr3->ep_out->bEndpointAddress); | |
| 1059 | + tmps = usb_bulk_msg(rr3->udev, pipe, buffer, | |
| 1060 | + sendbuf_len, &ret_len, 10 * HZ); | |
| 1061 | + rr3_dbg(dev, "sent %d bytes, (ret %d)\n", ret_len, tmps); | |
| 1062 | + | |
| 1063 | + /* now tell the hardware to transmit what we sent it */ | |
| 1064 | + pipe = usb_rcvctrlpipe(rr3->udev, 0); | |
| 1065 | + ret = usb_control_msg(rr3->udev, pipe, RR3_TX_SEND_SIGNAL, | |
| 1066 | + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | |
| 1067 | + 0, 0, buffer, 2, HZ * 10); | |
| 1068 | + | |
| 1069 | + if (ret < 0) | |
| 1070 | + dev_err(dev, "Error: control msg send failed, rc %d\n", ret); | |
| 1071 | + else | |
| 1072 | + ret = n; | |
| 1073 | + | |
| 1074 | +out: | |
| 1075 | + kfree(sample_lens); | |
| 1076 | + kfree(buffer); | |
| 1077 | + kfree(sigdata); | |
| 1078 | + | |
| 1079 | + rr3->transmitting = false; | |
| 1080 | + | |
| 1081 | + redrat3_enable_detector(rr3); | |
| 1082 | + | |
| 1083 | + return ret; | |
| 1084 | +} | |
| 1085 | + | |
| 1086 | +static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3) | |
| 1087 | +{ | |
| 1088 | + struct device *dev = rr3->dev; | |
| 1089 | + struct rc_dev *rc; | |
| 1090 | + int ret = -ENODEV; | |
| 1091 | + u16 prod = le16_to_cpu(rr3->udev->descriptor.idProduct); | |
| 1092 | + | |
| 1093 | + rc = rc_allocate_device(); | |
| 1094 | + if (!rc) { | |
| 1095 | + dev_err(dev, "remote input dev allocation failed\n"); | |
| 1096 | + goto out; | |
| 1097 | + } | |
| 1098 | + | |
| 1099 | + snprintf(rr3->name, sizeof(rr3->name), "RedRat3%s " | |
| 1100 | + "Infrared Remote Transceiver (%04x:%04x)", | |
| 1101 | + prod == USB_RR3IIUSB_PRODUCT_ID ? "-II" : "", | |
| 1102 | + le16_to_cpu(rr3->udev->descriptor.idVendor), prod); | |
| 1103 | + | |
| 1104 | + usb_make_path(rr3->udev, rr3->phys, sizeof(rr3->phys)); | |
| 1105 | + | |
| 1106 | + rc->input_name = rr3->name; | |
| 1107 | + rc->input_phys = rr3->phys; | |
| 1108 | + usb_to_input_id(rr3->udev, &rc->input_id); | |
| 1109 | + rc->dev.parent = dev; | |
| 1110 | + rc->priv = rr3; | |
| 1111 | + rc->driver_type = RC_DRIVER_IR_RAW; | |
| 1112 | + rc->allowed_protos = RC_TYPE_ALL; | |
| 1113 | + rc->min_timeout = MS_TO_NS(RR3_RX_MIN_TIMEOUT); | |
| 1114 | + rc->max_timeout = MS_TO_NS(RR3_RX_MAX_TIMEOUT); | |
| 1115 | + rc->timeout = redrat3_get_timeout(dev, rc, rr3->udev); | |
| 1116 | + rc->tx_ir = redrat3_transmit_ir; | |
| 1117 | + rc->s_tx_carrier = redrat3_set_tx_carrier; | |
| 1118 | + rc->driver_name = DRIVER_NAME; | |
| 1119 | + rc->map_name = RC_MAP_HAUPPAUGE; | |
| 1120 | + | |
| 1121 | + ret = rc_register_device(rc); | |
| 1122 | + if (ret < 0) { | |
| 1123 | + dev_err(dev, "remote dev registration failed\n"); | |
| 1124 | + goto out; | |
| 1125 | + } | |
| 1126 | + | |
| 1127 | + return rc; | |
| 1128 | + | |
| 1129 | +out: | |
| 1130 | + rc_free_device(rc); | |
| 1131 | + return NULL; | |
| 1132 | +} | |
| 1133 | + | |
| 1134 | +static int __devinit redrat3_dev_probe(struct usb_interface *intf, | |
| 1135 | + const struct usb_device_id *id) | |
| 1136 | +{ | |
| 1137 | + struct usb_device *udev = interface_to_usbdev(intf); | |
| 1138 | + struct device *dev = &intf->dev; | |
| 1139 | + struct usb_host_interface *uhi; | |
| 1140 | + struct redrat3_dev *rr3; | |
| 1141 | + struct usb_endpoint_descriptor *ep; | |
| 1142 | + struct usb_endpoint_descriptor *ep_in = NULL; | |
| 1143 | + struct usb_endpoint_descriptor *ep_out = NULL; | |
| 1144 | + u8 addr, attrs; | |
| 1145 | + int pipe, i; | |
| 1146 | + int retval = -ENOMEM; | |
| 1147 | + | |
| 1148 | + rr3_ftr(dev, "%s called\n", __func__); | |
| 1149 | + | |
| 1150 | + uhi = intf->cur_altsetting; | |
| 1151 | + | |
| 1152 | + /* find our bulk-in and bulk-out endpoints */ | |
| 1153 | + for (i = 0; i < uhi->desc.bNumEndpoints; ++i) { | |
| 1154 | + ep = &uhi->endpoint[i].desc; | |
| 1155 | + addr = ep->bEndpointAddress; | |
| 1156 | + attrs = ep->bmAttributes; | |
| 1157 | + | |
| 1158 | + if ((ep_in == NULL) && | |
| 1159 | + ((addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && | |
| 1160 | + ((attrs & USB_ENDPOINT_XFERTYPE_MASK) == | |
| 1161 | + USB_ENDPOINT_XFER_BULK)) { | |
| 1162 | + rr3_dbg(dev, "found bulk-in endpoint at 0x%02x\n", | |
| 1163 | + ep->bEndpointAddress); | |
| 1164 | + /* data comes in on 0x82, 0x81 is for other data... */ | |
| 1165 | + if (ep->bEndpointAddress == RR3_BULK_IN_EP_ADDR) | |
| 1166 | + ep_in = ep; | |
| 1167 | + } | |
| 1168 | + | |
| 1169 | + if ((ep_out == NULL) && | |
| 1170 | + ((addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) && | |
| 1171 | + ((attrs & USB_ENDPOINT_XFERTYPE_MASK) == | |
| 1172 | + USB_ENDPOINT_XFER_BULK)) { | |
| 1173 | + rr3_dbg(dev, "found bulk-out endpoint at 0x%02x\n", | |
| 1174 | + ep->bEndpointAddress); | |
| 1175 | + ep_out = ep; | |
| 1176 | + } | |
| 1177 | + } | |
| 1178 | + | |
| 1179 | + if (!ep_in || !ep_out) { | |
| 1180 | + dev_err(dev, "Couldn't find both in and out endpoints\n"); | |
| 1181 | + retval = -ENODEV; | |
| 1182 | + goto no_endpoints; | |
| 1183 | + } | |
| 1184 | + | |
| 1185 | + /* allocate memory for our device state and initialize it */ | |
| 1186 | + rr3 = kzalloc(sizeof(*rr3), GFP_KERNEL); | |
| 1187 | + if (rr3 == NULL) { | |
| 1188 | + dev_err(dev, "Memory allocation failure\n"); | |
| 1189 | + goto error; | |
| 1190 | + } | |
| 1191 | + | |
| 1192 | + rr3->dev = &intf->dev; | |
| 1193 | + | |
| 1194 | + /* set up bulk-in endpoint */ | |
| 1195 | + rr3->read_urb = usb_alloc_urb(0, GFP_KERNEL); | |
| 1196 | + if (!rr3->read_urb) { | |
| 1197 | + dev_err(dev, "Read urb allocation failure\n"); | |
| 1198 | + goto error; | |
| 1199 | + } | |
| 1200 | + | |
| 1201 | + rr3->ep_in = ep_in; | |
| 1202 | + rr3->bulk_in_buf = usb_alloc_coherent(udev, ep_in->wMaxPacketSize, | |
| 1203 | + GFP_ATOMIC, &rr3->dma_in); | |
| 1204 | + if (!rr3->bulk_in_buf) { | |
| 1205 | + dev_err(dev, "Read buffer allocation failure\n"); | |
| 1206 | + goto error; | |
| 1207 | + } | |
| 1208 | + | |
| 1209 | + pipe = usb_rcvbulkpipe(udev, ep_in->bEndpointAddress); | |
| 1210 | + usb_fill_bulk_urb(rr3->read_urb, udev, pipe, | |
| 1211 | + rr3->bulk_in_buf, ep_in->wMaxPacketSize, | |
| 1212 | + (usb_complete_t)redrat3_handle_async, rr3); | |
| 1213 | + | |
| 1214 | + /* set up bulk-out endpoint*/ | |
| 1215 | + rr3->write_urb = usb_alloc_urb(0, GFP_KERNEL); | |
| 1216 | + if (!rr3->write_urb) { | |
| 1217 | + dev_err(dev, "Write urb allocation failure\n"); | |
| 1218 | + goto error; | |
| 1219 | + } | |
| 1220 | + | |
| 1221 | + rr3->ep_out = ep_out; | |
| 1222 | + rr3->bulk_out_buf = usb_alloc_coherent(udev, ep_out->wMaxPacketSize, | |
| 1223 | + GFP_ATOMIC, &rr3->dma_out); | |
| 1224 | + if (!rr3->bulk_out_buf) { | |
| 1225 | + dev_err(dev, "Write buffer allocation failure\n"); | |
| 1226 | + goto error; | |
| 1227 | + } | |
| 1228 | + | |
| 1229 | + pipe = usb_sndbulkpipe(udev, ep_out->bEndpointAddress); | |
| 1230 | + usb_fill_bulk_urb(rr3->write_urb, udev, pipe, | |
| 1231 | + rr3->bulk_out_buf, ep_out->wMaxPacketSize, | |
| 1232 | + (usb_complete_t)redrat3_write_bulk_callback, rr3); | |
| 1233 | + | |
| 1234 | + mutex_init(&rr3->lock); | |
| 1235 | + rr3->udev = udev; | |
| 1236 | + | |
| 1237 | + redrat3_reset(rr3); | |
| 1238 | + redrat3_get_firmware_rev(rr3); | |
| 1239 | + | |
| 1240 | + /* might be all we need to do? */ | |
| 1241 | + retval = redrat3_enable_detector(rr3); | |
| 1242 | + if (retval < 0) | |
| 1243 | + goto error; | |
| 1244 | + | |
| 1245 | + /* default.. will get overridden by any sends with a freq defined */ | |
| 1246 | + rr3->carrier = 38000; | |
| 1247 | + | |
| 1248 | + rr3->rc = redrat3_init_rc_dev(rr3); | |
| 1249 | + if (!rr3->rc) | |
| 1250 | + goto error; | |
| 1251 | + | |
| 1252 | + setup_timer(&rr3->rx_timeout, redrat3_rx_timeout, (unsigned long)rr3); | |
| 1253 | + | |
| 1254 | + /* we can register the device now, as it is ready */ | |
| 1255 | + usb_set_intfdata(intf, rr3); | |
| 1256 | + | |
| 1257 | + rr3_ftr(dev, "Exiting %s\n", __func__); | |
| 1258 | + return 0; | |
| 1259 | + | |
| 1260 | +error: | |
| 1261 | + redrat3_delete(rr3, rr3->udev); | |
| 1262 | + | |
| 1263 | +no_endpoints: | |
| 1264 | + dev_err(dev, "%s: retval = %x", __func__, retval); | |
| 1265 | + | |
| 1266 | + return retval; | |
| 1267 | +} | |
| 1268 | + | |
| 1269 | +static void __devexit redrat3_dev_disconnect(struct usb_interface *intf) | |
| 1270 | +{ | |
| 1271 | + struct usb_device *udev = interface_to_usbdev(intf); | |
| 1272 | + struct redrat3_dev *rr3 = usb_get_intfdata(intf); | |
| 1273 | + | |
| 1274 | + rr3_ftr(&intf->dev, "Entering %s\n", __func__); | |
| 1275 | + | |
| 1276 | + if (!rr3) | |
| 1277 | + return; | |
| 1278 | + | |
| 1279 | + redrat3_disable_detector(rr3); | |
| 1280 | + | |
| 1281 | + usb_set_intfdata(intf, NULL); | |
| 1282 | + rc_unregister_device(rr3->rc); | |
| 1283 | + redrat3_delete(rr3, udev); | |
| 1284 | + | |
| 1285 | + rr3_ftr(&intf->dev, "RedRat3 IR Transceiver now disconnected\n"); | |
| 1286 | +} | |
| 1287 | + | |
| 1288 | +static int redrat3_dev_suspend(struct usb_interface *intf, pm_message_t message) | |
| 1289 | +{ | |
| 1290 | + struct redrat3_dev *rr3 = usb_get_intfdata(intf); | |
| 1291 | + rr3_ftr(rr3->dev, "suspend\n"); | |
| 1292 | + usb_kill_urb(rr3->read_urb); | |
| 1293 | + return 0; | |
| 1294 | +} | |
| 1295 | + | |
| 1296 | +static int redrat3_dev_resume(struct usb_interface *intf) | |
| 1297 | +{ | |
| 1298 | + struct redrat3_dev *rr3 = usb_get_intfdata(intf); | |
| 1299 | + rr3_ftr(rr3->dev, "resume\n"); | |
| 1300 | + if (usb_submit_urb(rr3->read_urb, GFP_ATOMIC)) | |
| 1301 | + return -EIO; | |
| 1302 | + return 0; | |
| 1303 | +} | |
| 1304 | + | |
| 1305 | +static struct usb_driver redrat3_dev_driver = { | |
| 1306 | + .name = DRIVER_NAME, | |
| 1307 | + .probe = redrat3_dev_probe, | |
| 1308 | + .disconnect = redrat3_dev_disconnect, | |
| 1309 | + .suspend = redrat3_dev_suspend, | |
| 1310 | + .resume = redrat3_dev_resume, | |
| 1311 | + .reset_resume = redrat3_dev_resume, | |
| 1312 | + .id_table = redrat3_dev_table | |
| 1313 | +}; | |
| 1314 | + | |
| 1315 | +static int __init redrat3_dev_init(void) | |
| 1316 | +{ | |
| 1317 | + int ret; | |
| 1318 | + | |
| 1319 | + ret = usb_register(&redrat3_dev_driver); | |
| 1320 | + if (ret < 0) | |
| 1321 | + pr_err(DRIVER_NAME | |
| 1322 | + ": usb register failed, result = %d\n", ret); | |
| 1323 | + | |
| 1324 | + return ret; | |
| 1325 | +} | |
| 1326 | + | |
| 1327 | +static void __exit redrat3_dev_exit(void) | |
| 1328 | +{ | |
| 1329 | + usb_deregister(&redrat3_dev_driver); | |
| 1330 | +} | |
| 1331 | + | |
| 1332 | +module_init(redrat3_dev_init); | |
| 1333 | +module_exit(redrat3_dev_exit); | |
| 1334 | + | |
| 1335 | +MODULE_DESCRIPTION(DRIVER_DESC); | |
| 1336 | +MODULE_AUTHOR(DRIVER_AUTHOR); | |
| 1337 | +MODULE_AUTHOR(DRIVER_AUTHOR2); | |
| 1338 | +MODULE_LICENSE("GPL"); | |
| 1339 | +MODULE_DEVICE_TABLE(usb, redrat3_dev_table); | |
| 1340 | + | |
| 1341 | +module_param(debug, int, S_IRUGO | S_IWUSR); | |
| 1342 | +MODULE_PARM_DESC(debug, "Enable module debug spew. 0 = no debugging (default) " | |
| 1343 | + "0x1 = standard debug messages, 0x2 = function tracing debug. " | |
| 1344 | + "Flag bits are addative (i.e., 0x3 for both debug types)."); | |
| @@ -19,11 +19,12 @@ · 18 unmodified lines | ||
| 19 | 19 | * o DSDT dumps |
| 20 | 20 | * |
| 21 | 21 | * Supported features: |
| 22 | + * o IR Receive | |
| 23 | + * o IR Transmit | |
| 22 | 24 | * o Wake-On-CIR functionality |
| 23 | 25 | * |
| 24 | 26 | * To do: |
| 25 | 27 | * o Learning |
| 26 | − * o IR Transmit | |
| 27 | 28 | * |
| 28 | 29 | * This program is free software; you can redistribute it and/or modify |
| 29 | 30 | * it under the terms of the GNU General Public License as published by |
| @@ -50,6 +51,8 @@ · 20 unmodified lines | ||
| 50 | 51 | #include <linux/io.h> |
| 51 | 52 | #include <linux/bitrev.h> |
| 52 | 53 | #include <linux/slab.h> |
| 54 | +#include <linux/wait.h> | |
| 55 | +#include <linux/sched.h> | |
| 53 | 56 | #include <media/rc-core.h> |
| 54 | 57 | |
| 55 | 58 | #define DRVNAME "winbond-cir" |
| @@ -118,14 +121,24 @@ · 62 unmodified lines | ||
| 118 | 121 | #define WBCIR_IRQ_NONE 0x00 |
| 119 | 122 | /* RX data bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ |
| 120 | 123 | #define WBCIR_IRQ_RX 0x01 |
| 124 | +/* TX data low bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ | |
| 125 | +#define WBCIR_IRQ_TX_LOW 0x02 | |
| 121 | 126 | /* Over/Under-flow bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ |
| 122 | 127 | #define WBCIR_IRQ_ERR 0x04 |
| 128 | +/* TX data empty bit for WBCEIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ | |
| 129 | +#define WBCIR_IRQ_TX_EMPTY 0x20 | |
| 123 | 130 | /* Led enable/disable bit for WBCIR_REG_ECEIR_CTS */ |
| 124 | 131 | #define WBCIR_LED_ENABLE 0x80 |
| 125 | 132 | /* RX data available bit for WBCIR_REG_SP3_LSR */ |
| 126 | 133 | #define WBCIR_RX_AVAIL 0x01 |
| 134 | +/* RX data overrun error bit for WBCIR_REG_SP3_LSR */ | |
| 135 | +#define WBCIR_RX_OVERRUN 0x02 | |
| 136 | +/* TX End-Of-Transmission bit for WBCIR_REG_SP3_ASCR */ | |
| 137 | +#define WBCIR_TX_EOT 0x04 | |
| 127 | 138 | /* RX disable bit for WBCIR_REG_SP3_ASCR */ |
| 128 | 139 | #define WBCIR_RX_DISABLE 0x20 |
| 140 | +/* TX data underrun error bit for WBCIR_REG_SP3_ASCR */ | |
| 141 | +#define WBCIR_TX_UNDERRUN 0x40 | |
| 129 | 142 | /* Extended mode enable bit for WBCIR_REG_SP3_EXCR1 */ |
| 130 | 143 | #define WBCIR_EXT_ENABLE 0x01 |
| 131 | 144 | /* Select compare register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */ |
| @@ -154,6 +167,21 @@ enum wbcir_protocol { · 22 unmodified lines | ||
| 154 | 167 | IR_PROTOCOL_RC6 = 0x2, |
| 155 | 168 | }; |
| 156 | 169 | |
| 170 | +/* Possible states for IR reception */ | |
| 171 | +enum wbcir_rxstate { | |
| 172 | + WBCIR_RXSTATE_INACTIVE = 0, | |
| 173 | + WBCIR_RXSTATE_ACTIVE, | |
| 174 | + WBCIR_RXSTATE_ERROR | |
| 175 | +}; | |
| 176 | + | |
| 177 | +/* Possible states for IR transmission */ | |
| 178 | +enum wbcir_txstate { | |
| 179 | + WBCIR_TXSTATE_INACTIVE = 0, | |
| 180 | + WBCIR_TXSTATE_ACTIVE, | |
| 181 | + WBCIR_TXSTATE_DONE, | |
| 182 | + WBCIR_TXSTATE_ERROR | |
| 183 | +}; | |
| 184 | + | |
| 157 | 185 | /* Misc */ |
| 158 | 186 | #define WBCIR_NAME "Winbond CIR" |
| 159 | 187 | #define WBCIR_ID_FAMILY 0xF1 /* Family ID for the WPCD376I */ |
| @@ -166,22 +194,29 @@ enum wbcir_protocol { · 6 unmodified lines | ||
| 166 | 194 | /* Per-device data */ |
| 167 | 195 | struct wbcir_data { |
| 168 | 196 | spinlock_t spinlock; |
| 197 | + struct rc_dev *dev; | |
| 198 | + struct led_classdev led; | |
| 169 | 199 | |
| 170 | 200 | unsigned long wbase; /* Wake-Up Baseaddr */ |
| 171 | 201 | unsigned long ebase; /* Enhanced Func. Baseaddr */ |
| 172 | 202 | unsigned long sbase; /* Serial Port Baseaddr */ |
| 173 | 203 | unsigned int irq; /* Serial Port IRQ */ |
| 204 | + u8 irqmask; | |
| 174 | 205 | |
| 175 | − struct rc_dev *dev; | |
| 176 | − | |
| 206 | + /* RX state */ | |
| 207 | + enum wbcir_rxstate rxstate; | |
| 177 | 208 | struct led_trigger *rxtrigger; |
| 178 | − struct led_trigger *txtrigger; | |
| 179 | − struct led_classdev led; | |
| 209 | + struct ir_raw_event rxev; | |
| 180 | 210 | |
| 181 | − /* RX irdata state */ | |
| 182 | − bool irdata_active; | |
| 183 | − bool irdata_error; | |
| 184 | − struct ir_raw_event ev; | |
| 211 | + /* TX state */ | |
| 212 | + enum wbcir_txstate txstate; | |
| 213 | + struct led_trigger *txtrigger; | |
| 214 | + u32 txlen; | |
| 215 | + u32 txoff; | |
| 216 | + u32 *txbuf; | |
| 217 | + wait_queue_head_t txwaitq; | |
| 218 | + u8 txmask; | |
| 219 | + u32 txcarrier; | |
| 185 | 220 | }; |
| 186 | 221 | |
| 187 | 222 | static enum wbcir_protocol protocol = IR_PROTOCOL_RC6; |
| @@ -193,6 +228,10 @@ static int invert; /* default = 0 */ · 5 unmodified lines | ||
| 193 | 228 | module_param(invert, bool, 0444); |
| 194 | 229 | MODULE_PARM_DESC(invert, "Invert the signal from the IR receiver"); |
| 195 | 230 | |
| 231 | +static int txandrx; /* default = 0 */ | |
| 232 | +module_param(txandrx, bool, 0444); | |
| 233 | +MODULE_PARM_DESC(invert, "Allow simultaneous TX and RX"); | |
| 234 | + | |
| 196 | 235 | static unsigned int wake_sc = 0x800F040C; |
| 197 | 236 | module_param(wake_sc, uint, 0644); |
| 198 | 237 | MODULE_PARM_DESC(wake_sc, "Scancode of the power-on IR command"); |
| @@ -228,6 +267,17 @@ wbcir_select_bank(struct wbcir_data *data, enum wbcir_bank bank) · 29 unmodified lines | ||
| 228 | 267 | outb(bank, data->sbase + WBCIR_REG_SP3_BSR); |
| 229 | 268 | } |
| 230 | 269 | |
| 270 | +static inline void | |
| 271 | +wbcir_set_irqmask(struct wbcir_data *data, u8 irqmask) | |
| 272 | +{ | |
| 273 | + if (data->irqmask == irqmask) | |
| 274 | + return; | |
| 275 | + | |
| 276 | + wbcir_select_bank(data, WBCIR_BANK_0); | |
| 277 | + outb(irqmask, data->sbase + WBCIR_REG_SP3_IER); | |
| 278 | + data->irqmask = irqmask; | |
| 279 | +} | |
| 280 | + | |
| 231 | 281 | static enum led_brightness |
| 232 | 282 | wbcir_led_brightness_get(struct led_classdev *led_cdev) |
| 233 | 283 | { |
| @@ -279,97 +329,297 @@ wbcir_to_rc6cells(u8 val) · 45 unmodified lines | ||
| 279 | 329 | * |
| 280 | 330 | *****************************************************************************/ |
| 281 | 331 | |
| 332 | +static void | |
| 333 | +wbcir_idle_rx(struct rc_dev *dev, bool idle) | |
| 334 | +{ | |
| 335 | + struct wbcir_data *data = dev->priv; | |
| 336 | + | |
| 337 | + if (!idle && data->rxstate == WBCIR_RXSTATE_INACTIVE) { | |
| 338 | + data->rxstate = WBCIR_RXSTATE_ACTIVE; | |
| 339 | + led_trigger_event(data->rxtrigger, LED_FULL); | |
| 340 | + } | |
| 341 | + | |
| 342 | + if (idle && data->rxstate != WBCIR_RXSTATE_INACTIVE) | |
| 343 | + /* Tell hardware to go idle by setting RXINACTIVE */ | |
| 344 | + outb(WBCIR_RX_DISABLE, data->sbase + WBCIR_REG_SP3_ASCR); | |
| 345 | +} | |
| 346 | + | |
| 347 | +static void | |
| 348 | +wbcir_irq_rx(struct wbcir_data *data, struct pnp_dev *device) | |
| 349 | +{ | |
| 350 | + u8 irdata; | |
| 351 | + DEFINE_IR_RAW_EVENT(rawir); | |
| 352 | + | |
| 353 | + /* Since RXHDLEV is set, at least 8 bytes are in the FIFO */ | |
| 354 | + while (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_AVAIL) { | |
| 355 | + irdata = inb(data->sbase + WBCIR_REG_SP3_RXDATA); | |
| 356 | + if (data->rxstate == WBCIR_RXSTATE_ERROR) | |
| 357 | + continue; | |
| 358 | + rawir.pulse = irdata & 0x80 ? false : true; | |
| 359 | + rawir.duration = US_TO_NS((irdata & 0x7F) * 10); | |
| 360 | + ir_raw_event_store_with_filter(data->dev, &rawir); | |
| 361 | + } | |
| 362 | + | |
| 363 | + /* Check if we should go idle */ | |
| 364 | + if (data->dev->idle) { | |
| 365 | + led_trigger_event(data->rxtrigger, LED_OFF); | |
| 366 | + data->rxstate = WBCIR_RXSTATE_INACTIVE; | |
| 367 | + } | |
| 368 | + | |
| 369 | + ir_raw_event_handle(data->dev); | |
| 370 | +} | |
| 371 | + | |
| 372 | +static void | |
| 373 | +wbcir_irq_tx(struct wbcir_data *data) | |
| 374 | +{ | |
| 375 | + unsigned int space; | |
| 376 | + unsigned int used; | |
| 377 | + u8 bytes[16]; | |
| 378 | + u8 byte; | |
| 379 | + | |
| 380 | + if (!data->txbuf) | |
| 381 | + return; | |
| 382 | + | |
| 383 | + switch (data->txstate) { | |
| 384 | + case WBCIR_TXSTATE_INACTIVE: | |
| 385 | + /* TX FIFO empty */ | |
| 386 | + space = 16; | |
| 387 | + led_trigger_event(data->txtrigger, LED_FULL); | |
| 388 | + break; | |
| 389 | + case WBCIR_TXSTATE_ACTIVE: | |
| 390 | + /* TX FIFO low (3 bytes or less) */ | |
| 391 | + space = 13; | |
| 392 | + break; | |
| 393 | + case WBCIR_TXSTATE_ERROR: | |
| 394 | + space = 0; | |
| 395 | + break; | |
| 396 | + default: | |
| 397 | + return; | |
| 398 | + } | |
| 399 | + | |
| 400 | + /* | |
| 401 | + * TX data is run-length coded in bytes: YXXXXXXX | |
| 402 | + * Y = space (1) or pulse (0) | |
| 403 | + * X = duration, encoded as (X + 1) * 10us (i.e 10 to 1280 us) | |
| 404 | + */ | |
| 405 | + for (used = 0; used < space && data->txoff != data->txlen; used++) { | |
| 406 | + if (data->txbuf[data->txoff] == 0) { | |
| 407 | + data->txoff++; | |
| 408 | + continue; | |
| 409 | + } | |
| 410 | + byte = min((u32)0x80, data->txbuf[data->txoff]); | |
| 411 | + data->txbuf[data->txoff] -= byte; | |
| 412 | + byte--; | |
| 413 | + byte |= (data->txoff % 2 ? 0x80 : 0x00); /* pulse/space */ | |
| 414 | + bytes[used] = byte; | |
| 415 | + } | |
| 416 | + | |
| 417 | + while (data->txbuf[data->txoff] == 0 && data->txoff != data->txlen) | |
| 418 | + data->txoff++; | |
| 419 | + | |
| 420 | + if (used == 0) { | |
| 421 | + /* Finished */ | |
| 422 | + if (data->txstate == WBCIR_TXSTATE_ERROR) | |
| 423 | + /* Clear TX underrun bit */ | |
| 424 | + outb(WBCIR_TX_UNDERRUN, data->sbase + WBCIR_REG_SP3_ASCR); | |
| 425 | + else | |
| 426 | + data->txstate = WBCIR_TXSTATE_DONE; | |
| 427 | + wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR); | |
| 428 | + led_trigger_event(data->txtrigger, LED_OFF); | |
| 429 | + wake_up(&data->txwaitq); | |
| 430 | + } else if (data->txoff == data->txlen) { | |
| 431 | + /* At the end of transmission, tell the hw before last byte */ | |
| 432 | + outsb(data->sbase + WBCIR_REG_SP3_TXDATA, bytes, used - 1); | |
| 433 | + outb(WBCIR_TX_EOT, data->sbase + WBCIR_REG_SP3_ASCR); | |
| 434 | + outb(bytes[used - 1], data->sbase + WBCIR_REG_SP3_TXDATA); | |
| 435 | + wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR | | |
| 436 | + WBCIR_IRQ_TX_EMPTY); | |
| 437 | + } else { | |
| 438 | + /* More data to follow... */ | |
| 439 | + outsb(data->sbase + WBCIR_REG_SP3_RXDATA, bytes, used); | |
| 440 | + if (data->txstate == WBCIR_TXSTATE_INACTIVE) { | |
| 441 | + wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR | | |
| 442 | + WBCIR_IRQ_TX_LOW); | |
| 443 | + data->txstate = WBCIR_TXSTATE_ACTIVE; | |
| 444 | + } | |
| 445 | + } | |
| 446 | +} | |
| 447 | + | |
| 282 | 448 | static irqreturn_t |
| 283 | 449 | wbcir_irq_handler(int irqno, void *cookie) |
| 284 | 450 | { |
| 285 | 451 | struct pnp_dev *device = cookie; |
| 286 | 452 | struct wbcir_data *data = pnp_get_drvdata(device); |
| 287 | 453 | unsigned long flags; |
| 288 | − u8 irdata[8]; | |
| 289 | − u8 disable = true; | |
| 290 | 454 | u8 status; |
| 291 | − int i; | |
| 292 | 455 | |
| 293 | 456 | spin_lock_irqsave(&data->spinlock, flags); |
| 294 | − | |
| 295 | 457 | wbcir_select_bank(data, WBCIR_BANK_0); |
| 296 | − | |
| 297 | 458 | status = inb(data->sbase + WBCIR_REG_SP3_EIR); |
| 459 | + status &= data->irqmask; | |
| 298 | 460 | |
| 299 | − if (!(status & (WBCIR_IRQ_RX | WBCIR_IRQ_ERR))) { | |
| 461 | + if (!status) { | |
| 300 | 462 | spin_unlock_irqrestore(&data->spinlock, flags); |
| 301 | 463 | return IRQ_NONE; |
| 302 | 464 | } |
| 303 | 465 | |
| 304 | − /* Check for e.g. buffer overflow */ | |
| 305 | 466 | if (status & WBCIR_IRQ_ERR) { |
| 306 | − data->irdata_error = true; | |
| 307 | − ir_raw_event_reset(data->dev); | |
| 308 | − } | |
| 309 | − | |
| 310 | − if (!(status & WBCIR_IRQ_RX)) | |
| 311 | − goto out; | |
| 467 | + /* RX overflow? (read clears bit) */ | |
| 468 | + if (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_OVERRUN) { | |
| 469 | + data->rxstate = WBCIR_RXSTATE_ERROR; | |
| 470 | + ir_raw_event_reset(data->dev); | |
| 471 | + } | |
| 312 | 472 | |
| 313 | − if (!data->irdata_active) { | |
| 314 | − data->irdata_active = true; | |
| 315 | − led_trigger_event(data->rxtrigger, LED_FULL); | |
| 473 | + /* TX underflow? */ | |
| 474 | + if (inb(data->sbase + WBCIR_REG_SP3_ASCR) & WBCIR_TX_UNDERRUN) | |
| 475 | + data->txstate = WBCIR_TXSTATE_ERROR; | |
| 316 | 476 | } |
| 317 | 477 | |
| 318 | − /* Since RXHDLEV is set, at least 8 bytes are in the FIFO */ | |
| 319 | − insb(data->sbase + WBCIR_REG_SP3_RXDATA, &irdata[0], 8); | |
| 478 | + if (status & WBCIR_IRQ_RX) | |
| 479 | + wbcir_irq_rx(data, device); | |
| 320 | 480 | |
| 321 | − for (i = 0; i < 8; i++) { | |
| 322 | − u8 pulse; | |
| 323 | − u32 duration; | |
| 481 | + if (status & (WBCIR_IRQ_TX_LOW | WBCIR_IRQ_TX_EMPTY)) | |
| 482 | + wbcir_irq_tx(data); | |
| 324 | 483 | |
| 325 | − if (irdata[i] != 0xFF && irdata[i] != 0x00) | |
| 326 | − disable = false; | |
| 327 | − | |
| 328 | − if (data->irdata_error) | |
| 329 | − continue; | |
| 484 | + spin_unlock_irqrestore(&data->spinlock, flags); | |
| 485 | + return IRQ_HANDLED; | |
| 486 | +} | |
| 330 | 487 | |
| 331 | − pulse = irdata[i] & 0x80 ? false : true; | |
| 332 | − duration = (irdata[i] & 0x7F) * 10000; /* ns */ | |
| 488 | +/***************************************************************************** | |
| 489 | + * | |
| 490 | + * RC-CORE INTERFACE FUNCTIONS | |
| 491 | + * | |
| 492 | + *****************************************************************************/ | |
| 333 | 493 | |
| 334 | − if (data->ev.pulse != pulse) { | |
| 335 | − if (data->ev.duration != 0) { | |
| 336 | − ir_raw_event_store(data->dev, &data->ev); | |
| 337 | − data->ev.duration = 0; | |
| 338 | − } | |
| 494 | +static int | |
| 495 | +wbcir_txcarrier(struct rc_dev *dev, u32 carrier) | |
| 496 | +{ | |
| 497 | + struct wbcir_data *data = dev->priv; | |
| 498 | + unsigned long flags; | |
| 499 | + u8 val; | |
| 500 | + u32 freq; | |
| 501 | + | |
| 502 | + freq = DIV_ROUND_CLOSEST(carrier, 1000); | |
| 503 | + if (freq < 30 || freq > 60) | |
| 504 | + return -EINVAL; | |
| 505 | + | |
| 506 | + switch (freq) { | |
| 507 | + case 58: | |
| 508 | + case 59: | |
| 509 | + case 60: | |
| 510 | + val = freq - 58; | |
| 511 | + freq *= 1000; | |
| 512 | + break; | |
| 513 | + case 57: | |
| 514 | + val = freq - 27; | |
| 515 | + freq = 56900; | |
| 516 | + break; | |
| 517 | + default: | |
| 518 | + val = freq - 27; | |
| 519 | + freq *= 1000; | |
| 520 | + break; | |
| 521 | + } | |
| 339 | 522 | |
| 340 | − data->ev.pulse = pulse; | |
| 341 | − } | |
| 523 | + spin_lock_irqsave(&data->spinlock, flags); | |
| 524 | + if (data->txstate != WBCIR_TXSTATE_INACTIVE) { | |
| 525 | + spin_unlock_irqrestore(&data->spinlock, flags); | |
| 526 | + return -EBUSY; | |
| 527 | + } | |
| 342 | 528 | |
| 343 | − data->ev.duration += duration; | |
| 529 | + if (data->txcarrier != freq) { | |
| 530 | + wbcir_select_bank(data, WBCIR_BANK_7); | |
| 531 | + wbcir_set_bits(data->sbase + WBCIR_REG_SP3_IRTXMC, val, 0x1F); | |
| 532 | + data->txcarrier = freq; | |
| 344 | 533 | } |
| 345 | 534 | |
| 346 | − if (disable) { | |
| 347 | − if (data->ev.duration != 0 && !data->irdata_error) { | |
| 348 | − ir_raw_event_store(data->dev, &data->ev); | |
| 349 | − data->ev.duration = 0; | |
| 350 | − } | |
| 535 | + spin_unlock_irqrestore(&data->spinlock, flags); | |
| 536 | + return 0; | |
| 537 | +} | |
| 351 | 538 | |
| 352 | − /* Set RXINACTIVE */ | |
| 353 | − outb(WBCIR_RX_DISABLE, data->sbase + WBCIR_REG_SP3_ASCR); | |
| 539 | +static int | |
| 540 | +wbcir_txmask(struct rc_dev *dev, u32 mask) | |
| 541 | +{ | |
| 542 | + struct wbcir_data *data = dev->priv; | |
| 543 | + unsigned long flags; | |
| 544 | + u8 val; | |
| 354 | 545 | |
| 355 | − /* Drain the FIFO */ | |
| 356 | − while (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_AVAIL) | |
| 357 | − inb(data->sbase + WBCIR_REG_SP3_RXDATA); | |
| 546 | + /* Four outputs, only one output can be enabled at a time */ | |
| 547 | + switch (mask) { | |
| 548 | + case 0x1: | |
| 549 | + val = 0x0; | |
| 550 | + break; | |
| 551 | + case 0x2: | |
| 552 | + val = 0x1; | |
| 553 | + break; | |
| 554 | + case 0x4: | |
| 555 | + val = 0x2; | |
| 556 | + break; | |
| 557 | + case 0x8: | |
| 558 | + val = 0x3; | |
| 559 | + break; | |
| 560 | + default: | |
| 561 | + return -EINVAL; | |
| 562 | + } | |
| 358 | 563 | |
| 359 | − ir_raw_event_reset(data->dev); | |
| 360 | − data->irdata_error = false; | |
| 361 | − data->irdata_active = false; | |
| 362 | − led_trigger_event(data->rxtrigger, LED_OFF); | |
| 564 | + spin_lock_irqsave(&data->spinlock, flags); | |
| 565 | + if (data->txstate != WBCIR_TXSTATE_INACTIVE) { | |
| 566 | + spin_unlock_irqrestore(&data->spinlock, flags); | |
| 567 | + return -EBUSY; | |
| 363 | 568 | } |
| 364 | 569 | |
| 365 | − ir_raw_event_handle(data->dev); | |
| 570 | + if (data->txmask != mask) { | |
| 571 | + wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CTS, val, 0x0c); | |
| 572 | + data->txmask = mask; | |
| 573 | + } | |
| 366 | 574 | |
| 367 | −out: | |
| 368 | 575 | spin_unlock_irqrestore(&data->spinlock, flags); |
| 369 | − return IRQ_HANDLED; | |
| 576 | + return 0; | |
| 370 | 577 | } |
| 371 | 578 | |
| 579 | +static int | |
| 580 | +wbcir_tx(struct rc_dev *dev, int *buf, u32 bufsize) | |
| 581 | +{ | |
| 582 | + struct wbcir_data *data = dev->priv; | |
| 583 | + u32 count; | |
| 584 | + unsigned i; | |
| 585 | + unsigned long flags; | |
| 586 | + | |
| 587 | + /* bufsize has been sanity checked by the caller */ | |
| 588 | + count = bufsize / sizeof(int); | |
| 372 | 589 | |
| 590 | + /* Not sure if this is possible, but better safe than sorry */ | |
| 591 | + spin_lock_irqsave(&data->spinlock, flags); | |
| 592 | + if (data->txstate != WBCIR_TXSTATE_INACTIVE) { | |
| 593 | + spin_unlock_irqrestore(&data->spinlock, flags); | |
| 594 | + return -EBUSY; | |
| 595 | + } | |
| 596 | + | |
| 597 | + /* Convert values to multiples of 10us */ | |
| 598 | + for (i = 0; i < count; i++) | |
| 599 | + buf[i] = DIV_ROUND_CLOSEST(buf[i], 10); | |
| 600 | + | |
| 601 | + /* Fill the TX fifo once, the irq handler will do the rest */ | |
| 602 | + data->txbuf = buf; | |
| 603 | + data->txlen = count; | |
| 604 | + data->txoff = 0; | |
| 605 | + wbcir_irq_tx(data); | |
| 606 | + | |
| 607 | + /* Wait for the TX to complete */ | |
| 608 | + while (data->txstate == WBCIR_TXSTATE_ACTIVE) { | |
| 609 | + spin_unlock_irqrestore(&data->spinlock, flags); | |
| 610 | + wait_event(data->txwaitq, data->txstate != WBCIR_TXSTATE_ACTIVE); | |
| 611 | + spin_lock_irqsave(&data->spinlock, flags); | |
| 612 | + } | |
| 613 | + | |
| 614 | + /* We're done */ | |
| 615 | + if (data->txstate == WBCIR_TXSTATE_ERROR) | |
| 616 | + count = -EAGAIN; | |
| 617 | + data->txstate = WBCIR_TXSTATE_INACTIVE; | |
| 618 | + data->txbuf = NULL; | |
| 619 | + spin_unlock_irqrestore(&data->spinlock, flags); | |
| 620 | + | |
| 621 | + return count; | |
| 622 | +} | |
| 373 | 623 | |
| 374 | 624 | /***************************************************************************** |
| 375 | 625 | * |
| @@ -382,7 +632,7 @@ wbcir_shutdown(struct pnp_dev *device) · 6 unmodified lines | ||
| 382 | 632 | { |
| 383 | 633 | struct device *dev = &device->dev; |
| 384 | 634 | struct wbcir_data *data = pnp_get_drvdata(device); |
| 385 | − int do_wake = 1; | |
| 635 | + bool do_wake = true; | |
| 386 | 636 | u8 match[11]; |
| 387 | 637 | u8 mask[11]; |
| 388 | 638 | u8 rc6_csl = 0; |
| @@ -392,14 +642,14 @@ wbcir_shutdown(struct pnp_dev *device) · 3 unmodified lines | ||
| 392 | 642 | memset(mask, 0, sizeof(mask)); |
| 393 | 643 | |
| 394 | 644 | if (wake_sc == INVALID_SCANCODE || !device_may_wakeup(dev)) { |
| 395 | − do_wake = 0; | |
| 645 | + do_wake = false; | |
| 396 | 646 | goto finish; |
| 397 | 647 | } |
| 398 | 648 | |
| 399 | 649 | switch (protocol) { |
| 400 | 650 | case IR_PROTOCOL_RC5: |
| 401 | 651 | if (wake_sc > 0xFFF) { |
| 402 | − do_wake = 0; | |
| 652 | + do_wake = false; | |
| 403 | 653 | dev_err(dev, "RC5 - Invalid wake scancode\n"); |
| 404 | 654 | break; |
| 405 | 655 | } |
| @@ -418,7 +668,7 @@ wbcir_shutdown(struct pnp_dev *device) · 12 unmodified lines | ||
| 418 | 668 | |
| 419 | 669 | case IR_PROTOCOL_NEC: |
| 420 | 670 | if (wake_sc > 0xFFFFFF) { |
| 421 | − do_wake = 0; | |
| 671 | + do_wake = false; | |
| 422 | 672 | dev_err(dev, "NEC - Invalid wake scancode\n"); |
| 423 | 673 | break; |
| 424 | 674 | } |
| @@ -440,7 +690,7 @@ wbcir_shutdown(struct pnp_dev *device) · 15 unmodified lines | ||
| 440 | 690 | |
| 441 | 691 | if (wake_rc6mode == 0) { |
| 442 | 692 | if (wake_sc > 0xFFFF) { |
| 443 | − do_wake = 0; | |
| 693 | + do_wake = false; | |
| 444 | 694 | dev_err(dev, "RC6 - Invalid wake scancode\n"); |
| 445 | 695 | break; |
| 446 | 696 | } |
| @@ -496,7 +746,7 @@ wbcir_shutdown(struct pnp_dev *device) · 49 unmodified lines | ||
| 496 | 746 | } else if (wake_sc <= 0x007FFFFF) { |
| 497 | 747 | rc6_csl = 60; |
| 498 | 748 | } else { |
| 499 | − do_wake = 0; | |
| 749 | + do_wake = false; | |
| 500 | 750 | dev_err(dev, "RC6 - Invalid wake scancode\n"); |
| 501 | 751 | break; |
| 502 | 752 | } |
| @@ -508,14 +758,14 @@ wbcir_shutdown(struct pnp_dev *device) · 5 unmodified lines | ||
| 508 | 758 | mask[i++] = 0x0F; |
| 509 | 759 | |
| 510 | 760 | } else { |
| 511 | − do_wake = 0; | |
| 761 | + do_wake = false; | |
| 512 | 762 | dev_err(dev, "RC6 - Invalid wake mode\n"); |
| 513 | 763 | } |
| 514 | 764 | |
| 515 | 765 | break; |
| 516 | 766 | |
| 517 | 767 | default: |
| 518 | − do_wake = 0; | |
| 768 | + do_wake = false; | |
| 519 | 769 | break; |
| 520 | 770 | } |
| 521 | 771 | |
| @@ -551,21 +801,18 @@ finish: · 29 unmodified lines | ||
| 551 | 801 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); |
| 552 | 802 | } |
| 553 | 803 | |
| 554 | − /* Disable interrupts */ | |
| 555 | − wbcir_select_bank(data, WBCIR_BANK_0); | |
| 556 | − outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | |
| 557 | − | |
| 558 | − /* Disable LED */ | |
| 559 | − data->irdata_active = false; | |
| 560 | − led_trigger_event(data->rxtrigger, LED_OFF); | |
| 561 | − | |
| 562 | 804 | /* |
| 563 | 805 | * ACPI will set the HW disable bit for SP3 which means that the |
| 564 | 806 | * output signals are left in an undefined state which may cause |
| 565 | 807 | * spurious interrupts which we need to ignore until the hardware |
| 566 | 808 | * is reinitialized. |
| 567 | 809 | */ |
| 810 | + wbcir_set_irqmask(data, WBCIR_IRQ_NONE); | |
| 568 | 811 | disable_irq(data->irq); |
| 812 | + | |
| 813 | + /* Disable LED */ | |
| 814 | + led_trigger_event(data->rxtrigger, LED_OFF); | |
| 815 | + led_trigger_event(data->txtrigger, LED_OFF); | |
| 569 | 816 | } |
| 570 | 817 | |
| 571 | 818 | static int |
| @@ -581,8 +828,7 @@ wbcir_init_hw(struct wbcir_data *data) · 9 unmodified lines | ||
| 581 | 828 | u8 tmp; |
| 582 | 829 | |
| 583 | 830 | /* Disable interrupts */ |
| 584 | − wbcir_select_bank(data, WBCIR_BANK_0); | |
| 585 | − outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | |
| 831 | + wbcir_set_irqmask(data, WBCIR_IRQ_NONE); | |
| 586 | 832 | |
| 587 | 833 | /* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */ |
| 588 | 834 | tmp = protocol << 4; |
| @@ -606,10 +852,11 @@ wbcir_init_hw(struct wbcir_data *data) · 17 unmodified lines | ||
| 606 | 852 | outb(0x00, data->ebase + WBCIR_REG_ECEIR_CCTL); |
| 607 | 853 | |
| 608 | 854 | /* |
| 609 | − * Clear IR LED, set SP3 clock to 24Mhz | |
| 855 | + * Clear IR LED, set SP3 clock to 24Mhz, set TX mask to IRTX1, | |
| 610 | 856 | * set SP3_IRRX_SW to binary 01, helpfully not documented |
| 611 | 857 | */ |
| 612 | 858 | outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS); |
| 859 | + data->txmask = 0x1; | |
| 613 | 860 | |
| 614 | 861 | /* Enable extended mode */ |
| 615 | 862 | wbcir_select_bank(data, WBCIR_BANK_2); |
| @@ -657,18 +904,21 @@ wbcir_init_hw(struct wbcir_data *data) · 41 unmodified lines | ||
| 657 | 904 | wbcir_select_bank(data, WBCIR_BANK_4); |
| 658 | 905 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1); |
| 659 | 906 | |
| 660 | − /* Enable MSR interrupt, Clear AUX_IRX */ | |
| 907 | + /* Disable MSR interrupt, clear AUX_IRX, mask RX during TX? */ | |
| 661 | 908 | wbcir_select_bank(data, WBCIR_BANK_5); |
| 662 | − outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2); | |
| 909 | + outb(txandrx ? 0x03 : 0x02, data->sbase + WBCIR_REG_SP3_IRCR2); | |
| 663 | 910 | |
| 664 | 911 | /* Disable CRC */ |
| 665 | 912 | wbcir_select_bank(data, WBCIR_BANK_6); |
| 666 | 913 | outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3); |
| 667 | 914 | |
| 668 | − /* Set RX/TX (de)modulation freq, not really used */ | |
| 915 | + /* Set RX demodulation freq, not really used */ | |
| 669 | 916 | wbcir_select_bank(data, WBCIR_BANK_7); |
| 670 | 917 | outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC); |
| 918 | + | |
| 919 | + /* Set TX modulation, 36kHz, 7us pulse width */ | |
| 671 | 920 | outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC); |
| 921 | + data->txcarrier = 36000; | |
| 672 | 922 | |
| 673 | 923 | /* Set invert and pin direction */ |
| 674 | 924 | if (invert) |
| @@ -683,16 +933,23 @@ wbcir_init_hw(struct wbcir_data *data) · 8 unmodified lines | ||
| 683 | 933 | /* Clear AUX status bits */ |
| 684 | 934 | outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR); |
| 685 | 935 | |
| 686 | − /* Clear IR decoding state */ | |
| 687 | − data->irdata_active = false; | |
| 688 | − led_trigger_event(data->rxtrigger, LED_OFF); | |
| 689 | − data->irdata_error = false; | |
| 690 | − data->ev.duration = 0; | |
| 936 | + /* Clear RX state */ | |
| 937 | + data->rxstate = WBCIR_RXSTATE_INACTIVE; | |
| 938 | + data->rxev.duration = 0; | |
| 691 | 939 | ir_raw_event_reset(data->dev); |
| 692 | 940 | ir_raw_event_handle(data->dev); |
| 693 | 941 | |
| 942 | + /* | |
| 943 | + * Check TX state, if we did a suspend/resume cycle while TX was | |
| 944 | + * active, we will have a process waiting in txwaitq. | |
| 945 | + */ | |
| 946 | + if (data->txstate == WBCIR_TXSTATE_ACTIVE) { | |
| 947 | + data->txstate = WBCIR_TXSTATE_ERROR; | |
| 948 | + wake_up(&data->txwaitq); | |
| 949 | + } | |
| 950 | + | |
| 694 | 951 | /* Enable interrupts */ |
| 695 | − outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); | |
| 952 | + wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR); | |
| 696 | 953 | } |
| 697 | 954 | |
| 698 | 955 | static int |
| @@ -729,6 +986,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) · 30 unmodified lines | ||
| 729 | 986 | pnp_set_drvdata(device, data); |
| 730 | 987 | |
| 731 | 988 | spin_lock_init(&data->spinlock); |
| 989 | + init_waitqueue_head(&data->txwaitq); | |
| 732 | 990 | data->ebase = pnp_port_start(device, 0); |
| 733 | 991 | data->wbase = pnp_port_start(device, 1); |
| 734 | 992 | data->sbase = pnp_port_start(device, 2); |
| @@ -807,6 +1065,11 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) · 72 unmodified lines | ||
| 807 | 1065 | data->dev->input_id.vendor = PCI_VENDOR_ID_WINBOND; |
| 808 | 1066 | data->dev->input_id.product = WBCIR_ID_FAMILY; |
| 809 | 1067 | data->dev->input_id.version = WBCIR_ID_CHIP; |
| 1068 | + data->dev->map_name = RC_MAP_RC6_MCE; | |
| 1069 | + data->dev->s_idle = wbcir_idle_rx; | |
| 1070 | + data->dev->s_tx_mask = wbcir_txmask; | |
| 1071 | + data->dev->s_tx_carrier = wbcir_txcarrier; | |
| 1072 | + data->dev->tx_ir = wbcir_tx; | |
| 810 | 1073 | data->dev->priv = data; |
| 811 | 1074 | data->dev->dev.parent = &device->dev; |
| 812 | 1075 | |
| @@ -849,9 +1112,7 @@ wbcir_remove(struct pnp_dev *device) · 36 unmodified lines | ||
| 849 | 1112 | struct wbcir_data *data = pnp_get_drvdata(device); |
| 850 | 1113 | |
| 851 | 1114 | /* Disable interrupts */ |
| 852 | − wbcir_select_bank(data, WBCIR_BANK_0); | |
| 853 | − outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | |
| 854 | − | |
| 1115 | + wbcir_set_irqmask(data, WBCIR_IRQ_NONE); | |
| 855 | 1116 | free_irq(data->irq, device); |
| 856 | 1117 | |
| 857 | 1118 | /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ |
| @@ -128,10 +128,10 @@ config VIDEO_IR_I2C · 127 unmodified lines | ||
| 128 | 128 | # Encoder / Decoder module configuration |
| 129 | 129 | # |
| 130 | 130 | |
| 131 | −menu "Encoders/decoders and other helper chips" | |
| 131 | +menu "Encoders, decoders, sensors and other helper chips" | |
| 132 | 132 | visible if !VIDEO_HELPER_CHIPS_AUTO |
| 133 | 133 | |
| 134 | −comment "Audio decoders" | |
| 134 | +comment "Audio decoders, processors and mixers" | |
| 135 | 135 | |
| 136 | 136 | config VIDEO_TVAUDIO |
| 137 | 137 | tristate "Simple audio decoder chips" |
| @@ -210,15 +210,6 @@ config VIDEO_CS53L32A · 72 unmodified lines | ||
| 210 | 210 | To compile this driver as a module, choose M here: the |
| 211 | 211 | module will be called cs53l32a. |
| 212 | 212 | |
| 213 | −config VIDEO_M52790 | |
| 214 | − tristate "Mitsubishi M52790 A/V switch" | |
| 215 | − depends on VIDEO_V4L2 && I2C | |
| 216 | − ---help--- | |
| 217 | − Support for the Mitsubishi M52790 A/V switch. | |
| 218 | − | |
| 219 | − To compile this driver as a module, choose M here: the | |
| 220 | − module will be called m52790. | |
| 221 | − | |
| 222 | 213 | config VIDEO_TLV320AIC23B |
| 223 | 214 | tristate "Texas Instruments TLV320AIC23B audio codec" |
| 224 | 215 | depends on VIDEO_V4L2 && I2C && EXPERIMENTAL |
| @@ -321,29 +312,6 @@ config VIDEO_KS0127 · 96 unmodified lines | ||
| 321 | 312 | To compile this driver as a module, choose M here: the |
| 322 | 313 | module will be called ks0127. |
| 323 | 314 | |
| 324 | −config VIDEO_OV7670 | |
| 325 | − tristate "OmniVision OV7670 sensor support" | |
| 326 | − depends on I2C && VIDEO_V4L2 | |
| 327 | − ---help--- | |
| 328 | − This is a Video4Linux2 sensor-level driver for the OmniVision | |
| 329 | − OV7670 VGA camera. It currently only works with the M88ALP01 | |
| 330 | − controller. | |
| 331 | − | |
| 332 | −config VIDEO_MT9V011 | |
| 333 | − tristate "Micron mt9v011 sensor support" | |
| 334 | − depends on I2C && VIDEO_V4L2 | |
| 335 | − ---help--- | |
| 336 | − This is a Video4Linux2 sensor-level driver for the Micron | |
| 337 | − mt0v011 1.3 Mpixel camera. It currently only works with the | |
| 338 | − em28xx driver. | |
| 339 | − | |
| 340 | −config VIDEO_TCM825X | |
| 341 | − tristate "TCM825x camera sensor support" | |
| 342 | − depends on I2C && VIDEO_V4L2 | |
| 343 | − ---help--- | |
| 344 | − This is a driver for the Toshiba TCM825x VGA camera sensor. | |
| 345 | − It is used for example in Nokia N800. | |
| 346 | − | |
| 347 | 315 | config VIDEO_SAA7110 |
| 348 | 316 | tristate "Philips SAA7110 video decoder" |
| 349 | 317 | depends on VIDEO_V4L2 && I2C |
| @@ -362,15 +330,6 @@ config VIDEO_SAA711X · 12 unmodified lines | ||
| 362 | 330 | To compile this driver as a module, choose M here: the |
| 363 | 331 | module will be called saa7115. |
| 364 | 332 | |
| 365 | −config VIDEO_SAA717X | |
| 366 | − tristate "Philips SAA7171/3/4 audio/video decoders" | |
| 367 | − depends on VIDEO_V4L2 && I2C | |
| 368 | − ---help--- | |
| 369 | − Support for the Philips SAA7171/3/4 audio/video decoders. | |
| 370 | − | |
| 371 | − To compile this driver as a module, choose M here: the | |
| 372 | − module will be called saa717x. | |
| 373 | − | |
| 374 | 333 | config VIDEO_SAA7191 |
| 375 | 334 | tristate "Philips SAA7191 video decoder" |
| 376 | 335 | depends on VIDEO_V4L2 && I2C |
| @@ -420,6 +379,15 @@ config VIDEO_VPX3220 · 43 unmodified lines | ||
| 420 | 379 | |
| 421 | 380 | comment "Video and audio decoders" |
| 422 | 381 | |
| 382 | +config VIDEO_SAA717X | |
| 383 | + tristate "Philips SAA7171/3/4 audio/video decoders" | |
| 384 | + depends on VIDEO_V4L2 && I2C | |
| 385 | + ---help--- | |
| 386 | + Support for the Philips SAA7171/3/4 audio/video decoders. | |
| 387 | + | |
| 388 | + To compile this driver as a module, choose M here: the | |
| 389 | + module will be called saa717x. | |
| 390 | + | |
| 423 | 391 | source "drivers/media/video/cx25840/Kconfig" |
| 424 | 392 | |
| 425 | 393 | comment "MPEG video encoders" |
| @@ -474,15 +442,6 @@ config VIDEO_ADV7175 · 48 unmodified lines | ||
| 474 | 442 | To compile this driver as a module, choose M here: the |
| 475 | 443 | module will be called adv7175. |
| 476 | 444 | |
| 477 | −config VIDEO_THS7303 | |
| 478 | − tristate "THS7303 Video Amplifier" | |
| 479 | − depends on I2C | |
| 480 | − help | |
| 481 | − Support for TI THS7303 video amplifier | |
| 482 | − | |
| 483 | − To compile this driver as a module, choose M here: the | |
| 484 | − module will be called ths7303. | |
| 485 | − | |
| 486 | 445 | config VIDEO_ADV7343 |
| 487 | 446 | tristate "ADV7343 video encoder" |
| 488 | 447 | depends on I2C |
| @@ -498,6 +457,38 @@ config VIDEO_AK881X · 9 unmodified lines | ||
| 498 | 457 | help |
| 499 | 458 | Video output driver for AKM AK8813 and AK8814 TV encoders |
| 500 | 459 | |
| 460 | +comment "Camera sensor devices" | |
| 461 | + | |
| 462 | +config VIDEO_OV7670 | |
| 463 | + tristate "OmniVision OV7670 sensor support" | |
| 464 | + depends on I2C && VIDEO_V4L2 | |
| 465 | + ---help--- | |
| 466 | + This is a Video4Linux2 sensor-level driver for the OmniVision | |
| 467 | + OV7670 VGA camera. It currently only works with the M88ALP01 | |
| 468 | + controller. | |
| 469 | + | |
| 470 | +config VIDEO_MT9V011 | |
| 471 | + tristate "Micron mt9v011 sensor support" | |
| 472 | + depends on I2C && VIDEO_V4L2 | |
| 473 | + ---help--- | |
| 474 | + This is a Video4Linux2 sensor-level driver for the Micron | |
| 475 | + mt0v011 1.3 Mpixel camera. It currently only works with the | |
| 476 | + em28xx driver. | |
| 477 | + | |
| 478 | +config VIDEO_MT9V032 | |
| 479 | + tristate "Micron MT9V032 sensor support" | |
| 480 | + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API | |
| 481 | + ---help--- | |
| 482 | + This is a Video4Linux2 sensor-level driver for the Micron | |
| 483 | + MT9V032 752x480 CMOS sensor. | |
| 484 | + | |
| 485 | +config VIDEO_TCM825X | |
| 486 | + tristate "TCM825x camera sensor support" | |
| 487 | + depends on I2C && VIDEO_V4L2 | |
| 488 | + ---help--- | |
| 489 | + This is a driver for the Toshiba TCM825x VGA camera sensor. | |
| 490 | + It is used for example in Nokia N800. | |
| 491 | + | |
| 501 | 492 | comment "Video improvement chips" |
| 502 | 493 | |
| 503 | 494 | config VIDEO_UPD64031A |
| @@ -523,6 +514,26 @@ config VIDEO_UPD64083 · 19 unmodified lines | ||
| 523 | 514 | To compile this driver as a module, choose M here: the |
| 524 | 515 | module will be called upd64083. |
| 525 | 516 | |
| 517 | +comment "Miscelaneous helper chips" | |
| 518 | + | |
| 519 | +config VIDEO_THS7303 | |
| 520 | + tristate "THS7303 Video Amplifier" | |
| 521 | + depends on I2C | |
| 522 | + help | |
| 523 | + Support for TI THS7303 video amplifier | |
| 524 | + | |
| 525 | + To compile this driver as a module, choose M here: the | |
| 526 | + module will be called ths7303. | |
| 527 | + | |
| 528 | +config VIDEO_M52790 | |
| 529 | + tristate "Mitsubishi M52790 A/V switch" | |
| 530 | + depends on VIDEO_V4L2 && I2C | |
| 531 | + ---help--- | |
| 532 | + Support for the Mitsubishi M52790 A/V switch. | |
| 533 | + | |
| 534 | + To compile this driver as a module, choose M here: the | |
| 535 | + module will be called m52790. | |
| 536 | + | |
| 526 | 537 | endmenu # encoder / decoder chips |
| 527 | 538 | |
| 528 | 539 | config VIDEO_SH_VOU |
| @@ -682,7 +693,7 @@ config VIDEO_TIMBERDALE · 153 unmodified lines | ||
| 682 | 693 | select VIDEO_ADV7180 |
| 683 | 694 | select VIDEOBUF_DMA_CONTIG |
| 684 | 695 | ---help--- |
| 685 | − Add support for the Video In peripherial of the timberdale FPGA. | |
| 696 | + Add support for the Video In peripherial of the timberdale FPGA. | |
| 686 | 697 | |
| 687 | 698 | source "drivers/media/video/cx88/Kconfig" |
| 688 | 699 | |
| @@ -916,7 +927,7 @@ config VIDEO_OMAP2 · 227 unmodified lines | ||
| 916 | 927 | This is a v4l2 driver for the TI OMAP2 camera capture interface |
| 917 | 928 | |
| 918 | 929 | config VIDEO_MX2_HOSTSUPPORT |
| 919 | − bool | |
| 930 | + bool | |
| 920 | 931 | |
| 921 | 932 | config VIDEO_MX2 |
| 922 | 933 | tristate "i.MX27/i.MX25 Camera Sensor Interface driver" |
| @@ -927,6 +938,26 @@ config VIDEO_MX2 · 4 unmodified lines | ||
| 927 | 938 | This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor |
| 928 | 939 | Interface |
| 929 | 940 | |
| 941 | +config VIDEO_SAMSUNG_S5P_FIMC | |
| 942 | + tristate "Samsung S5P and EXYNOS4 camera host interface driver" | |
| 943 | + depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P | |
| 944 | + select VIDEOBUF2_DMA_CONTIG | |
| 945 | + select V4L2_MEM2MEM_DEV | |
| 946 | + ---help--- | |
| 947 | + This is a v4l2 driver for Samsung S5P and EXYNOS4 camera | |
| 948 | + host interface and video postprocessor. | |
| 949 | + | |
| 950 | + To compile this driver as a module, choose M here: the | |
| 951 | + module will be called s5p-fimc. | |
| 952 | + | |
| 953 | +config VIDEO_S5P_MIPI_CSIS | |
| 954 | + tristate "Samsung S5P and EXYNOS4 MIPI CSI receiver driver" | |
| 955 | + depends on VIDEO_V4L2 && PM_RUNTIME && VIDEO_V4L2_SUBDEV_API | |
| 956 | + ---help--- | |
| 957 | + This is a v4l2 driver for Samsung S5P/EXYNOS4 MIPI-CSI receiver. | |
| 958 | + | |
| 959 | + To compile this driver as a module, choose M here: the | |
| 960 | + module will be called s5p-csis. | |
| 930 | 961 | |
| 931 | 962 | # |
| 932 | 963 | # USB Multimedia device configuration |
| @@ -983,7 +1014,7 @@ config USB_STKWEBCAM · 50 unmodified lines | ||
| 983 | 1014 | Supported devices are typically found in some Asus laptops, |
| 984 | 1015 | with USB id 174f:a311 and 05e1:0501. Other Syntek cameras |
| 985 | 1016 | may be supported by the stk11xx driver, from which this is |
| 986 | − derived, see <http://sourceforge.net/projects/syntekdriver/> | |
| 1017 | + derived, see <http://sourceforge.net/projects/syntekdriver/> | |
| 987 | 1018 | |
| 988 | 1019 | To compile this driver as a module, choose M here: the |
| 989 | 1020 | module will be called stkwebcam. |
| @@ -1022,13 +1053,5 @@ config VIDEO_MEM2MEM_TESTDEV · 32 unmodified lines | ||
| 1022 | 1053 | This is a virtual test device for the memory-to-memory driver |
| 1023 | 1054 | framework. |
| 1024 | 1055 | |
| 1025 | −config VIDEO_SAMSUNG_S5P_FIMC | |
| 1026 | − tristate "Samsung S5P FIMC (video postprocessor) driver" | |
| 1027 | − depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P | |
| 1028 | − select VIDEOBUF2_DMA_CONTIG | |
| 1029 | − select V4L2_MEM2MEM_DEV | |
| 1030 | − help | |
| 1031 | − This is a v4l2 driver for the S5P camera interface | |
| 1032 | − (video postprocessor) | |
| 1033 | 1056 | |
| 1034 | 1057 | endif # V4L_MEM2MEM_DRIVERS |
| @@ -66,6 +66,7 @@ obj-$(CONFIG_VIDEO_OV7670) += ov7670.o · 65 unmodified lines | ||
| 66 | 66 | obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o |
| 67 | 67 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o |
| 68 | 68 | obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o |
| 69 | +obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o | |
| 69 | 70 | obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o |
| 70 | 71 | obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o |
| 71 | 72 | |
| @@ -164,6 +165,7 @@ obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o · 92 unmodified lines | ||
| 164 | 165 | obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o |
| 165 | 166 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o |
| 166 | 167 | obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o |
| 168 | + | |
| 167 | 169 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/ |
| 168 | 170 | |
| 169 | 171 | obj-$(CONFIG_ARCH_DAVINCI) += davinci/ |
| @@ -4303,7 +4303,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, · 4302 unmodified lines | ||
| 4303 | 4303 | goto fail0; |
| 4304 | 4304 | } |
| 4305 | 4305 | |
| 4306 | − pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); | |
| 4306 | + btv->revision = dev->revision; | |
| 4307 | 4307 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); |
| 4308 | 4308 | printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ", |
| 4309 | 4309 | bttv_num,btv->id, btv->revision, pci_name(dev)); |
| @@ -1313,7 +1313,7 @@ static int cpia2_g_priority(struct file *file, void *_fh, enum v4l2_priority *p) · 1312 unmodified lines | ||
| 1313 | 1313 | static int cpia2_s_priority(struct file *file, void *_fh, enum v4l2_priority prio) |
| 1314 | 1314 | { |
| 1315 | 1315 | struct camera_data *cam = video_drvdata(file); |
| 1316 | − struct cpia2_fh *fh = fh; | |
| 1316 | + struct cpia2_fh *fh = _fh; | |
| 1317 | 1317 | |
| 1318 | 1318 | if (cam->streaming && prio != fh->prio && |
| 1319 | 1319 | fh->prio == V4L2_PRIORITY_RECORD) |
| @@ -2,6 +2,7 @@ config VIDEO_CX18 · 1 unmodified line | ||
| 2 | 2 | tristate "Conexant cx23418 MPEG encoder support" |
| 3 | 3 | depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL |
| 4 | 4 | select I2C_ALGOBIT |
| 5 | + select VIDEOBUF_VMALLOC | |
| 5 | 6 | depends on RC_CORE |
| 6 | 7 | select VIDEO_TUNER |
| 7 | 8 | select VIDEO_TVEEPROM |
| @@ -9,6 +10,9 @@ config VIDEO_CX18 · 1 unmodified line | ||
| 9 | 10 | select VIDEO_CS5345 |
| 10 | 11 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE |
| 11 | 12 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE |
| 13 | + select DVB_S5H1411 if !DVB_FE_CUSTOMISE | |
| 14 | + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE | |
| 15 | + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE | |
| 12 | 16 | ---help--- |
| 13 | 17 | This is a video4linux driver for Conexant cx23418 based |
| 14 | 18 | PCI combo video recorder devices. |
| @@ -39,6 +39,16 @@ static struct cx18_card_tuner_i2c cx18_i2c_std = { · 38 unmodified lines | ||
| 39 | 39 | .tv = { 0x61, 0x60, I2C_CLIENT_END }, |
| 40 | 40 | }; |
| 41 | 41 | |
| 42 | +/* | |
| 43 | + * usual i2c tuner addresses to probe with additional demod address for | |
| 44 | + * an NXP TDA8295 at 0x42 (N.B. it can possibly be at 0x4b or 0x4c too). | |
| 45 | + */ | |
| 46 | +static struct cx18_card_tuner_i2c cx18_i2c_nxp = { | |
| 47 | + .radio = { I2C_CLIENT_END }, | |
| 48 | + .demod = { 0x42, 0x43, I2C_CLIENT_END }, | |
| 49 | + .tv = { 0x61, 0x60, I2C_CLIENT_END }, | |
| 50 | +}; | |
| 51 | + | |
| 42 | 52 | /* Please add new PCI IDs to: http://pci-ids.ucw.cz/ |
| 43 | 53 | This keeps the PCI ID database up to date. Note that the entries |
| 44 | 54 | must be added under vendor 0x4444 (Conexant) as subsystem IDs. |
| @@ -131,15 +141,15 @@ static const struct cx18_card cx18_card_hvr1600_s5h1411 = { · 86 unmodified lines | ||
| 131 | 141 | .tune_lane = 0, |
| 132 | 142 | .initial_emrs = 0, |
| 133 | 143 | }, |
| 134 | − .gpio_init.initial_value = 0x3001, | |
| 135 | − .gpio_init.direction = 0x3001, | |
| 144 | + .gpio_init.initial_value = 0x3801, | |
| 145 | + .gpio_init.direction = 0x3801, | |
| 136 | 146 | .gpio_i2c_slave_reset = { |
| 137 | − .active_lo_mask = 0x3001, | |
| 147 | + .active_lo_mask = 0x3801, | |
| 138 | 148 | .msecs_asserted = 10, |
| 139 | 149 | .msecs_recovery = 40, |
| 140 | 150 | .ir_reset_mask = 0x0001, |
| 141 | 151 | }, |
| 142 | − .i2c = &cx18_i2c_std, | |
| 152 | + .i2c = &cx18_i2c_nxp, | |
| 143 | 153 | }; |
| 144 | 154 | |
| 145 | 155 | static const struct cx18_card cx18_card_hvr1600_samsung = { |
| @@ -109,7 +109,7 @@ struct cx18_card_tuner { · 108 unmodified lines | ||
| 109 | 109 | |
| 110 | 110 | struct cx18_card_tuner_i2c { |
| 111 | 111 | unsigned short radio[2];/* radio tuner i2c address to probe */ |
| 112 | − unsigned short demod[2];/* demodulator i2c address to probe */ | |
| 112 | + unsigned short demod[3];/* demodulator i2c address to probe */ | |
| 113 | 113 | unsigned short tv[4]; /* tv tuner i2c addresses to probe */ |
| 114 | 114 | }; |
| 115 | 115 | |
| @@ -423,7 +423,16 @@ static void cx18_process_eeprom(struct cx18 *cx) · 422 unmodified lines | ||
| 423 | 423 | return; |
| 424 | 424 | |
| 425 | 425 | /* autodetect tuner standard */ |
| 426 | − if (tv.tuner_formats & V4L2_STD_PAL) { | |
| 426 | +#define TVEEPROM_TUNER_FORMAT_ALL (V4L2_STD_B | V4L2_STD_GH | \ | |
| 427 | + V4L2_STD_MN | \ | |
| 428 | + V4L2_STD_PAL_I | \ | |
| 429 | + V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC | \ | |
| 430 | + V4L2_STD_DK) | |
| 431 | + if ((tv.tuner_formats & TVEEPROM_TUNER_FORMAT_ALL) | |
| 432 | + == TVEEPROM_TUNER_FORMAT_ALL) { | |
| 433 | + CX18_DEBUG_INFO("Worldwide tuner detected\n"); | |
| 434 | + cx->std = V4L2_STD_ALL; | |
| 435 | + } else if (tv.tuner_formats & V4L2_STD_PAL) { | |
| 427 | 436 | CX18_DEBUG_INFO("PAL tuner detected\n"); |
| 428 | 437 | cx->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H; |
| 429 | 438 | } else if (tv.tuner_formats & V4L2_STD_NTSC) { |
| @@ -818,7 +827,7 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev, · 388 unmodified lines | ||
| 818 | 827 | cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; |
| 819 | 828 | pci_write_config_word(pci_dev, PCI_COMMAND, cmd); |
| 820 | 829 | |
| 821 | − pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &cx->card_rev); | |
| 830 | + cx->card_rev = pci_dev->revision; | |
| 822 | 831 | pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency); |
| 823 | 832 | |
| 824 | 833 | if (pci_latency < 64 && cx18_pci_latency) { |
| @@ -1001,7 +1010,15 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, · 176 unmodified lines | ||
| 1001 | 1010 | if (cx->card->hw_all & CX18_HW_TVEEPROM) { |
| 1002 | 1011 | /* Based on the model number the cardtype may be changed. |
| 1003 | 1012 | The PCI IDs are not always reliable. */ |
| 1013 | + const struct cx18_card *orig_card = cx->card; | |
| 1004 | 1014 | cx18_process_eeprom(cx); |
| 1015 | + | |
| 1016 | + if (cx->card != orig_card) { | |
| 1017 | + /* Changed the cardtype; re-reset the I2C chips */ | |
| 1018 | + cx18_gpio_init(cx); | |
| 1019 | + cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, | |
| 1020 | + core, reset, (u32) CX18_GPIO_RESET_I2C); | |
| 1021 | + } | |
| 1005 | 1022 | } |
| 1006 | 1023 | if (cx->card->comment) |
| 1007 | 1024 | CX18_INFO("%s", cx->card->comment); |
| @@ -1087,6 +1104,8 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, · 79 unmodified lines | ||
| 1087 | 1104 | /* The tuner is fixed to the standard. The other inputs (e.g. S-Video) |
| 1088 | 1105 | are not. */ |
| 1089 | 1106 | cx->tuner_std = cx->std; |
| 1107 | + if (cx->std == V4L2_STD_ALL) | |
| 1108 | + cx->std = V4L2_STD_NTSC_M; | |
| 1090 | 1109 | |
| 1091 | 1110 | retval = cx18_streams_setup(cx); |
| 1092 | 1111 | if (retval) { |
| @@ -1133,6 +1152,7 @@ int cx18_init_on_first_open(struct cx18 *cx) · 40 unmodified lines | ||
| 1133 | 1152 | int fw_retry_count = 3; |
| 1134 | 1153 | struct v4l2_frequency vf; |
| 1135 | 1154 | struct cx18_open_id fh; |
| 1155 | + v4l2_std_id std; | |
| 1136 | 1156 | |
| 1137 | 1157 | fh.cx = cx; |
| 1138 | 1158 | |
| @@ -1220,7 +1240,8 @@ int cx18_init_on_first_open(struct cx18 *cx) · 81 unmodified lines | ||
| 1220 | 1240 | /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code |
| 1221 | 1241 | in one place. */ |
| 1222 | 1242 | cx->std++; /* Force full standard initialization */ |
| 1223 | − cx18_s_std(NULL, &fh, &cx->tuner_std); | |
| 1243 | + std = (cx->tuner_std == V4L2_STD_ALL) ? V4L2_STD_NTSC_M : cx->tuner_std; | |
| 1244 | + cx18_s_std(NULL, &fh, &std); | |
| 1224 | 1245 | cx18_s_frequency(NULL, &fh, &vf); |
| 1225 | 1246 | return 0; |
| 1226 | 1247 | } |
| @@ -65,6 +65,10 @@ · 64 unmodified lines | ||
| 65 | 65 | #include "dvb_net.h" |
| 66 | 66 | #include "dvbdev.h" |
| 67 | 67 | |
| 68 | +/* Videobuf / YUV support */ | |
| 69 | +#include <media/videobuf-core.h> | |
| 70 | +#include <media/videobuf-vmalloc.h> | |
| 71 | + | |
| 68 | 72 | #ifndef CONFIG_PCI |
| 69 | 73 | # error "This driver requires kernel PCI support." |
| 70 | 74 | #endif |
| @@ -403,6 +407,23 @@ struct cx18_stream { · 332 unmodified lines | ||
| 403 | 407 | struct cx18_queue q_idle; /* idle - not in rotation */ |
| 404 | 408 | |
| 405 | 409 | struct work_struct out_work_order; |
| 410 | + | |
| 411 | + /* Videobuf for YUV video */ | |
| 412 | + u32 pixelformat; | |
| 413 | + struct list_head vb_capture; /* video capture queue */ | |
| 414 | + spinlock_t vb_lock; | |
| 415 | + struct timer_list vb_timeout; | |
| 416 | + | |
| 417 | + struct videobuf_queue vbuf_q; | |
| 418 | + spinlock_t vbuf_q_lock; /* Protect vbuf_q */ | |
| 419 | + enum v4l2_buf_type vb_type; | |
| 420 | +}; | |
| 421 | + | |
| 422 | +struct cx18_videobuf_buffer { | |
| 423 | + /* Common video buffer sub-system struct */ | |
| 424 | + struct videobuf_buffer vb; | |
| 425 | + v4l2_std_id tvnorm; /* selected tv norm */ | |
| 426 | + u32 bytes_used; | |
| 406 | 427 | }; |
| 407 | 428 | |
| 408 | 429 | struct cx18_open_id { |
| @@ -410,6 +431,10 @@ struct cx18_open_id { · 1 unmodified line | ||
| 410 | 431 | u32 open_id; |
| 411 | 432 | int type; |
| 412 | 433 | struct cx18 *cx; |
| 434 | + | |
| 435 | + struct videobuf_queue vbuf_q; | |
| 436 | + spinlock_t s_lock; /* Protect vbuf_q */ | |
| 437 | + enum v4l2_buf_type vb_type; | |
| 413 | 438 | }; |
| 414 | 439 | |
| 415 | 440 | static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh) |
| @@ -597,6 +597,13 @@ ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count, · 596 unmodified lines | ||
| 597 | 597 | mutex_unlock(&cx->serialize_lock); |
| 598 | 598 | if (rc) |
| 599 | 599 | return rc; |
| 600 | + | |
93 more lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 212 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 219 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 173 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 334 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 152 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 727 lines aren’t shown here.
This diff is large: its 430 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 213 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 123 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 774 lines aren’t shown here.
This diff is large: its 129 lines aren’t shown here.
This diff is large: its 116 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 94 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 725 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 167 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 298 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 391 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 230 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 761 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 101 lines aren’t shown here.
This diff is large: its 151 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 620 lines aren’t shown here.
This diff is large: its 244 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 1095 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 391 lines aren’t shown here.
This diff is large: its 111 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.