[media] drx-j: Don't use CamelCase
[cascardo/linux.git] / drivers / media / dvb-frontends / drx39xyj / drxj.c
1 /*
2   Copyright (c), 2004-2005,2007-2010 Trident Microsystems, Inc.
3   All rights reserved.
4
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions are met:
7
8   * Redistributions of source code must retain the above copyright notice,
9     this list of conditions and the following disclaimer.
10   * Redistributions in binary form must reproduce the above copyright notice,
11     this list of conditions and the following disclaimer in the documentation
12         and/or other materials provided with the distribution.
13   * Neither the name of Trident Microsystems nor Hauppauge Computer Works
14     nor the names of its contributors may be used to endorse or promote
15         products derived from this software without specific prior written
16         permission.
17
18   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28   POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 /**
32 * \file $Id: drxj.c,v 1.637 2010/01/18 17:21:10 dingtao Exp $
33 *
34 * \brief DRXJ specific implementation of DRX driver
35 *
36 * \author Dragan Savic, Milos Nikolic, Mihajlo Katona, Tao Ding, Paul Janssen
37 */
38
39 /*-----------------------------------------------------------------------------
40 INCLUDE FILES
41 ----------------------------------------------------------------------------*/
42
43 #include "drxj.h"
44 #include "drxj_map.h"
45
46 #ifdef DRXJ_OPTIONS_H
47 #include "drxj_options.h"
48 #endif
49
50 /*============================================================================*/
51 /*=== DEFINES ================================================================*/
52 /*============================================================================*/
53
54 /**
55 * \brief Maximum u32 value.
56 */
57 #ifndef MAX_U32
58 #define MAX_U32  ((u32) (0xFFFFFFFFL))
59 #endif
60
61 /* Customer configurable hardware settings, etc */
62 #ifndef MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH
63 #define MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH 0x02
64 #endif
65
66 #ifndef MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH
67 #define MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH 0x02
68 #endif
69
70 #ifndef MPEG_OUTPUT_CLK_DRIVE_STRENGTH
71 #define MPEG_OUTPUT_CLK_DRIVE_STRENGTH 0x06
72 #endif
73
74 #ifndef OOB_CRX_DRIVE_STRENGTH
75 #define OOB_CRX_DRIVE_STRENGTH 0x02
76 #endif
77
78 #ifndef OOB_DRX_DRIVE_STRENGTH
79 #define OOB_DRX_DRIVE_STRENGTH 0x02
80 #endif
81 /**** START DJCOMBO patches to DRXJ registermap constants *********************/
82 /**** registermap 200706071303 from drxj **************************************/
83 #define   ATV_TOP_CR_AMP_TH_FM                                              0x0
84 #define   ATV_TOP_CR_AMP_TH_L                                               0xA
85 #define   ATV_TOP_CR_AMP_TH_LP                                              0xA
86 #define   ATV_TOP_CR_AMP_TH_BG                                              0x8
87 #define   ATV_TOP_CR_AMP_TH_DK                                              0x8
88 #define   ATV_TOP_CR_AMP_TH_I                                               0x8
89 #define     ATV_TOP_CR_CONT_CR_D_MN                                         0x18
90 #define     ATV_TOP_CR_CONT_CR_D_FM                                         0x0
91 #define     ATV_TOP_CR_CONT_CR_D_L                                          0x20
92 #define     ATV_TOP_CR_CONT_CR_D_LP                                         0x20
93 #define     ATV_TOP_CR_CONT_CR_D_BG                                         0x18
94 #define     ATV_TOP_CR_CONT_CR_D_DK                                         0x18
95 #define     ATV_TOP_CR_CONT_CR_D_I                                          0x18
96 #define     ATV_TOP_CR_CONT_CR_I_MN                                         0x80
97 #define     ATV_TOP_CR_CONT_CR_I_FM                                         0x0
98 #define     ATV_TOP_CR_CONT_CR_I_L                                          0x80
99 #define     ATV_TOP_CR_CONT_CR_I_LP                                         0x80
100 #define     ATV_TOP_CR_CONT_CR_I_BG                                         0x80
101 #define     ATV_TOP_CR_CONT_CR_I_DK                                         0x80
102 #define     ATV_TOP_CR_CONT_CR_I_I                                          0x80
103 #define     ATV_TOP_CR_CONT_CR_P_MN                                         0x4
104 #define     ATV_TOP_CR_CONT_CR_P_FM                                         0x0
105 #define     ATV_TOP_CR_CONT_CR_P_L                                          0x4
106 #define     ATV_TOP_CR_CONT_CR_P_LP                                         0x4
107 #define     ATV_TOP_CR_CONT_CR_P_BG                                         0x4
108 #define     ATV_TOP_CR_CONT_CR_P_DK                                         0x4
109 #define     ATV_TOP_CR_CONT_CR_P_I                                          0x4
110 #define   ATV_TOP_CR_OVM_TH_MN                                              0xA0
111 #define   ATV_TOP_CR_OVM_TH_FM                                              0x0
112 #define   ATV_TOP_CR_OVM_TH_L                                               0xA0
113 #define   ATV_TOP_CR_OVM_TH_LP                                              0xA0
114 #define   ATV_TOP_CR_OVM_TH_BG                                              0xA0
115 #define   ATV_TOP_CR_OVM_TH_DK                                              0xA0
116 #define   ATV_TOP_CR_OVM_TH_I                                               0xA0
117 #define     ATV_TOP_EQU0_EQU_C0_FM                                          0x0
118 #define     ATV_TOP_EQU0_EQU_C0_L                                           0x3
119 #define     ATV_TOP_EQU0_EQU_C0_LP                                          0x3
120 #define     ATV_TOP_EQU0_EQU_C0_BG                                          0x7
121 #define     ATV_TOP_EQU0_EQU_C0_DK                                          0x0
122 #define     ATV_TOP_EQU0_EQU_C0_I                                           0x3
123 #define     ATV_TOP_EQU1_EQU_C1_FM                                          0x0
124 #define     ATV_TOP_EQU1_EQU_C1_L                                           0x1F6
125 #define     ATV_TOP_EQU1_EQU_C1_LP                                          0x1F6
126 #define     ATV_TOP_EQU1_EQU_C1_BG                                          0x197
127 #define     ATV_TOP_EQU1_EQU_C1_DK                                          0x198
128 #define     ATV_TOP_EQU1_EQU_C1_I                                           0x1F6
129 #define     ATV_TOP_EQU2_EQU_C2_FM                                          0x0
130 #define     ATV_TOP_EQU2_EQU_C2_L                                           0x28
131 #define     ATV_TOP_EQU2_EQU_C2_LP                                          0x28
132 #define     ATV_TOP_EQU2_EQU_C2_BG                                          0xC5
133 #define     ATV_TOP_EQU2_EQU_C2_DK                                          0xB0
134 #define     ATV_TOP_EQU2_EQU_C2_I                                           0x28
135 #define     ATV_TOP_EQU3_EQU_C3_FM                                          0x0
136 #define     ATV_TOP_EQU3_EQU_C3_L                                           0x192
137 #define     ATV_TOP_EQU3_EQU_C3_LP                                          0x192
138 #define     ATV_TOP_EQU3_EQU_C3_BG                                          0x12E
139 #define     ATV_TOP_EQU3_EQU_C3_DK                                          0x18E
140 #define     ATV_TOP_EQU3_EQU_C3_I                                           0x192
141 #define     ATV_TOP_STD_MODE_MN                                             0x0
142 #define     ATV_TOP_STD_MODE_FM                                             0x1
143 #define     ATV_TOP_STD_MODE_L                                              0x0
144 #define     ATV_TOP_STD_MODE_LP                                             0x0
145 #define     ATV_TOP_STD_MODE_BG                                             0x0
146 #define     ATV_TOP_STD_MODE_DK                                             0x0
147 #define     ATV_TOP_STD_MODE_I                                              0x0
148 #define     ATV_TOP_STD_VID_POL_MN                                          0x0
149 #define     ATV_TOP_STD_VID_POL_FM                                          0x0
150 #define     ATV_TOP_STD_VID_POL_L                                           0x2
151 #define     ATV_TOP_STD_VID_POL_LP                                          0x2
152 #define     ATV_TOP_STD_VID_POL_BG                                          0x0
153 #define     ATV_TOP_STD_VID_POL_DK                                          0x0
154 #define     ATV_TOP_STD_VID_POL_I                                           0x0
155 #define   ATV_TOP_VID_AMP_MN                                                0x380
156 #define   ATV_TOP_VID_AMP_FM                                                0x0
157 #define   ATV_TOP_VID_AMP_L                                                 0xF50
158 #define   ATV_TOP_VID_AMP_LP                                                0xF50
159 #define   ATV_TOP_VID_AMP_BG                                                0x380
160 #define   ATV_TOP_VID_AMP_DK                                                0x394
161 #define   ATV_TOP_VID_AMP_I                                                 0x3D8
162 #define   IQM_CF_OUT_ENA_OFDM__M                                            0x4
163 #define     IQM_FS_ADJ_SEL_B_QAM                                            0x1
164 #define     IQM_FS_ADJ_SEL_B_OFF                                            0x0
165 #define     IQM_FS_ADJ_SEL_B_VSB                                            0x2
166 #define     IQM_RC_ADJ_SEL_B_OFF                                            0x0
167 #define     IQM_RC_ADJ_SEL_B_QAM                                            0x1
168 #define     IQM_RC_ADJ_SEL_B_VSB                                            0x2
169 /**** END DJCOMBO patches to DRXJ registermap *********************************/
170
171 #include "drx_driver_version.h"
172
173 /* #define DRX_DEBUG */
174 #ifdef DRX_DEBUG
175 #include <stdio.h>
176 #endif
177
178 /*-----------------------------------------------------------------------------
179 ENUMS
180 ----------------------------------------------------------------------------*/
181
182 /*-----------------------------------------------------------------------------
183 DEFINES
184 ----------------------------------------------------------------------------*/
185 #ifndef DRXJ_WAKE_UP_KEY
186 #define DRXJ_WAKE_UP_KEY (demod->my_i2c_dev_addr->i2c_addr)
187 #endif
188
189 /**
190 * \def DRXJ_DEF_I2C_ADDR
191 * \brief Default I2C addres of a demodulator instance.
192 */
193 #define DRXJ_DEF_I2C_ADDR (0x52)
194
195 /**
196 * \def DRXJ_DEF_DEMOD_DEV_ID
197 * \brief Default device identifier of a demodultor instance.
198 */
199 #define DRXJ_DEF_DEMOD_DEV_ID      (1)
200
201 /**
202 * \def DRXJ_SCAN_TIMEOUT
203 * \brief Timeout value for waiting on demod lock during channel scan (millisec).
204 */
205 #define DRXJ_SCAN_TIMEOUT    1000
206
207 /**
208 * \def DRXJ_DAP
209 * \brief Name of structure containing all data access protocol functions.
210 */
211 #define DRXJ_DAP drx_dap_drxj_funct_g
212
213 /**
214 * \def HI_I2C_DELAY
215 * \brief HI timing delay for I2C timing (in nano seconds)
216 *
217 *  Used to compute HI_CFG_DIV
218 */
219 #define HI_I2C_DELAY    42
220
221 /**
222 * \def HI_I2C_BRIDGE_DELAY
223 * \brief HI timing delay for I2C timing (in nano seconds)
224 *
225 *  Used to compute HI_CFG_BDL
226 */
227 #define HI_I2C_BRIDGE_DELAY   750
228
229 /**
230 * \brief Time Window for MER and SER Measurement in Units of Segment duration.
231 */
232 #define VSB_TOP_MEASUREMENT_PERIOD  64
233 #define SYMBOLS_PER_SEGMENT         832
234
235 /**
236 * \brief bit rate and segment rate constants used for SER and BER.
237 */
238 /* values taken from the QAM microcode */
239 #define DRXJ_QAM_SL_SIG_POWER_QAM_UNKNOWN 0
240 #define DRXJ_QAM_SL_SIG_POWER_QPSK        32768
241 #define DRXJ_QAM_SL_SIG_POWER_QAM8        24576
242 #define DRXJ_QAM_SL_SIG_POWER_QAM16       40960
243 #define DRXJ_QAM_SL_SIG_POWER_QAM32       20480
244 #define DRXJ_QAM_SL_SIG_POWER_QAM64       43008
245 #define DRXJ_QAM_SL_SIG_POWER_QAM128      20992
246 #define DRXJ_QAM_SL_SIG_POWER_QAM256      43520
247 /**
248 * \brief Min supported symbolrates.
249 */
250 #ifndef DRXJ_QAM_SYMBOLRATE_MIN
251 #define DRXJ_QAM_SYMBOLRATE_MIN          (520000)
252 #endif
253
254 /**
255 * \brief Max supported symbolrates.
256 */
257 #ifndef DRXJ_QAM_SYMBOLRATE_MAX
258 #define DRXJ_QAM_SYMBOLRATE_MAX         (7233000)
259 #endif
260
261 /**
262 * \def DRXJ_QAM_MAX_WAITTIME
263 * \brief Maximal wait time for QAM auto constellation in ms
264 */
265 #ifndef DRXJ_QAM_MAX_WAITTIME
266 #define DRXJ_QAM_MAX_WAITTIME 900
267 #endif
268
269 #ifndef DRXJ_QAM_FEC_LOCK_WAITTIME
270 #define DRXJ_QAM_FEC_LOCK_WAITTIME 150
271 #endif
272
273 #ifndef DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME
274 #define DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME 200
275 #endif
276
277 /**
278 * \def SCU status and results
279 * \brief SCU
280 */
281 #define DRX_SCU_READY               0
282 #define DRXJ_MAX_WAITTIME           100 /* ms */
283 #define FEC_RS_MEASUREMENT_PERIOD   12894       /* 1 sec */
284 #define FEC_RS_MEASUREMENT_PRESCALE 1   /* n sec */
285
286 /**
287 * \def DRX_AUD_MAX_DEVIATION
288 * \brief Needed for calculation of prescale feature in AUD
289 */
290 #ifndef DRXJ_AUD_MAX_FM_DEVIATION
291 #define DRXJ_AUD_MAX_FM_DEVIATION  100  /* kHz */
292 #endif
293
294 /**
295 * \brief Needed for calculation of NICAM prescale feature in AUD
296 */
297 #ifndef DRXJ_AUD_MAX_NICAM_PRESCALE
298 #define DRXJ_AUD_MAX_NICAM_PRESCALE  (9)        /* dB */
299 #endif
300
301 /**
302 * \brief Needed for calculation of NICAM prescale feature in AUD
303 */
304 #ifndef DRXJ_AUD_MAX_WAITTIME
305 #define DRXJ_AUD_MAX_WAITTIME  250      /* ms */
306 #endif
307
308 /* ATV config changed flags */
309 #define DRXJ_ATV_CHANGED_COEF          (0x00000001UL)
310 #define DRXJ_ATV_CHANGED_PEAK_FLT      (0x00000008UL)
311 #define DRXJ_ATV_CHANGED_NOISE_FLT     (0x00000010UL)
312 #define DRXJ_ATV_CHANGED_OUTPUT        (0x00000020UL)
313 #define DRXJ_ATV_CHANGED_SIF_ATT       (0x00000040UL)
314
315 /* UIO define */
316 #define DRX_UIO_MODE_FIRMWARE_SMA DRX_UIO_MODE_FIRMWARE0
317 #define DRX_UIO_MODE_FIRMWARE_SAW DRX_UIO_MODE_FIRMWARE1
318
319 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
320 /*============================================================================*/
321 /*=== MICROCODE RELATED DEFINES ==============================================*/
322 /*============================================================================*/
323
324 /**
325 * \def DRXJ_UCODE_MAGIC_WORD
326 * \brief Magic word for checking correct Endianess of microcode data.
327 *
328 */
329
330 #ifndef DRXJ_UCODE_MAGIC_WORD
331 #define DRXJ_UCODE_MAGIC_WORD         ((((u16)'H')<<8)+((u16)'L'))
332 #endif
333
334 /**
335 * \def DRXJ_UCODE_CRC_FLAG
336 * \brief CRC flag in ucode header, flags field.
337 *
338 */
339
340 #ifndef DRXJ_UCODE_CRC_FLAG
341 #define DRXJ_UCODE_CRC_FLAG           (0x0001)
342 #endif
343
344 /**
345 * \def DRXJ_UCODE_COMPRESSION_FLAG
346 * \brief Compression flag in ucode header, flags field.
347 *
348 */
349
350 #ifndef DRXJ_UCODE_COMPRESSION_FLAG
351 #define DRXJ_UCODE_COMPRESSION_FLAG   (0x0002)
352 #endif
353
354 /**
355 * \def DRXJ_UCODE_MAX_BUF_SIZE
356 * \brief Maximum size of buffer used to verify the microcode.Must be an even number.
357 *
358 */
359
360 #ifndef DRXJ_UCODE_MAX_BUF_SIZE
361 #define DRXJ_UCODE_MAX_BUF_SIZE       (DRXDAP_MAX_RCHUNKSIZE)
362 #endif
363 #if DRXJ_UCODE_MAX_BUF_SIZE & 1
364 #error DRXJ_UCODE_MAX_BUF_SIZE must be an even number
365 #endif
366
367 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
368
369 /* Pin safe mode macro */
370 #define DRXJ_PIN_SAFE_MODE 0x0000
371 /*============================================================================*/
372 /*=== GLOBAL VARIABLEs =======================================================*/
373 /*============================================================================*/
374 /**
375 */
376
377 /**
378 * \brief Temporary register definitions.
379 *        (register definitions that are not yet available in register master)
380 */
381
382 /******************************************************************************/
383 /* Audio block 0x103 is write only. To avoid shadowing in driver accessing    */
384 /* RAM adresses directly. This must be READ ONLY to avoid problems.           */
385 /* Writing to the interface adresses is more than only writing the RAM        */
386 /* locations                                                                  */
387 /******************************************************************************/
388 /**
389 * \brief RAM location of MODUS registers
390 */
391 #define AUD_DEM_RAM_MODUS_HI__A              0x10204A3
392 #define AUD_DEM_RAM_MODUS_HI__M              0xF000
393
394 #define AUD_DEM_RAM_MODUS_LO__A              0x10204A4
395 #define AUD_DEM_RAM_MODUS_LO__M              0x0FFF
396
397 /**
398 * \brief RAM location of I2S config registers
399 */
400 #define AUD_DEM_RAM_I2S_CONFIG1__A           0x10204B1
401 #define AUD_DEM_RAM_I2S_CONFIG2__A           0x10204B2
402
403 /**
404 * \brief RAM location of DCO config registers
405 */
406 #define AUD_DEM_RAM_DCO_B_HI__A              0x1020461
407 #define AUD_DEM_RAM_DCO_B_LO__A              0x1020462
408 #define AUD_DEM_RAM_DCO_A_HI__A              0x1020463
409 #define AUD_DEM_RAM_DCO_A_LO__A              0x1020464
410
411 /**
412 * \brief RAM location of Threshold registers
413 */
414 #define AUD_DEM_RAM_NICAM_THRSHLD__A         0x102045A
415 #define AUD_DEM_RAM_A2_THRSHLD__A            0x10204BB
416 #define AUD_DEM_RAM_BTSC_THRSHLD__A          0x10204A6
417
418 /**
419 * \brief RAM location of Carrier Threshold registers
420 */
421 #define AUD_DEM_RAM_CM_A_THRSHLD__A          0x10204AF
422 #define AUD_DEM_RAM_CM_B_THRSHLD__A          0x10204B0
423
424 /**
425 * \brief FM Matrix register fix
426 */
427 #ifdef AUD_DEM_WR_FM_MATRIX__A
428 #undef  AUD_DEM_WR_FM_MATRIX__A
429 #endif
430 #define AUD_DEM_WR_FM_MATRIX__A              0x105006F
431
432 /*============================================================================*/
433 /**
434 * \brief Defines required for audio
435 */
436 #define AUD_VOLUME_ZERO_DB                      115
437 #define AUD_VOLUME_DB_MIN                       -60
438 #define AUD_VOLUME_DB_MAX                       12
439 #define AUD_CARRIER_STRENGTH_QP_0DB             0x4000
440 #define AUD_CARRIER_STRENGTH_QP_0DB_LOG10T100   421
441 #define AUD_MAX_AVC_REF_LEVEL                   15
442 #define AUD_I2S_FREQUENCY_MAX                   48000UL
443 #define AUD_I2S_FREQUENCY_MIN                   12000UL
444 #define AUD_RDS_ARRAY_SIZE                      18
445
446 /**
447 * \brief Needed for calculation of prescale feature in AUD
448 */
449 #ifndef DRX_AUD_MAX_FM_DEVIATION
450 #define DRX_AUD_MAX_FM_DEVIATION  (100) /* kHz */
451 #endif
452
453 /**
454 * \brief Needed for calculation of NICAM prescale feature in AUD
455 */
456 #ifndef DRX_AUD_MAX_NICAM_PRESCALE
457 #define DRX_AUD_MAX_NICAM_PRESCALE  (9) /* dB */
458 #endif
459
460 /*============================================================================*/
461 /* Values for I2S Master/Slave pin configurations */
462 #define SIO_PDR_I2S_CL_CFG_MODE__MASTER      0x0004
463 #define SIO_PDR_I2S_CL_CFG_DRIVE__MASTER     0x0008
464 #define SIO_PDR_I2S_CL_CFG_MODE__SLAVE       0x0004
465 #define SIO_PDR_I2S_CL_CFG_DRIVE__SLAVE      0x0000
466
467 #define SIO_PDR_I2S_DA_CFG_MODE__MASTER      0x0003
468 #define SIO_PDR_I2S_DA_CFG_DRIVE__MASTER     0x0008
469 #define SIO_PDR_I2S_DA_CFG_MODE__SLAVE       0x0003
470 #define SIO_PDR_I2S_DA_CFG_DRIVE__SLAVE      0x0008
471
472 #define SIO_PDR_I2S_WS_CFG_MODE__MASTER      0x0004
473 #define SIO_PDR_I2S_WS_CFG_DRIVE__MASTER     0x0008
474 #define SIO_PDR_I2S_WS_CFG_MODE__SLAVE       0x0004
475 #define SIO_PDR_I2S_WS_CFG_DRIVE__SLAVE      0x0000
476
477 /*============================================================================*/
478 /*=== REGISTER ACCESS MACROS =================================================*/
479 /*============================================================================*/
480
481 #ifdef DRXJDRIVER_DEBUG
482 #include <stdio.h>
483 #define CHK_ERROR(s) \
484         do { \
485             if ((s) != DRX_STS_OK) \
486             { \
487                fprintf(stderr, \
488                        "ERROR[\n file    : %s\n line    : %d\n]\n", \
489                        __FILE__, __LINE__); \
490                goto rw_error; }; \
491             } \
492         while (0 != 0)
493 #else
494 #define CHK_ERROR(s) \
495    do { \
496       if ((s) != DRX_STS_OK) { goto rw_error; } \
497    } while (0 != 0)
498 #endif
499
500 #define CHK_ZERO(s) \
501    do { \
502       if ((s) == 0) return DRX_STS_ERROR; \
503    } while (0)
504
505 #define DUMMY_READ() \
506    do { \
507       u16 dummy; \
508       RR16(demod->my_i2c_dev_addr, SCU_RAM_VERSION_HI__A, &dummy); \
509    } while (0)
510
511 #define WR16(dev, addr, val) \
512    CHK_ERROR(DRXJ_DAP.write_reg16func( (dev), (addr), (val), 0) )
513
514 #define RR16(dev, addr, val) \
515    CHK_ERROR(DRXJ_DAP.read_reg16func( (dev), (addr), (val), 0) )
516
517 #define WR32(dev, addr, val) \
518    CHK_ERROR(DRXJ_DAP.write_reg32func( (dev), (addr), (val), 0) )
519
520 #define RR32(dev, addr, val) \
521    CHK_ERROR(DRXJ_DAP.read_reg32func( (dev), (addr), (val), 0) )
522
523 #define WRB(dev, addr, len, block) \
524    CHK_ERROR(DRXJ_DAP.write_block_func( (dev), (addr), (len), (block), 0) )
525
526 #define RRB(dev, addr, len, block) \
527    CHK_ERROR(DRXJ_DAP.read_block_func( (dev), (addr), (len), (block), 0) )
528
529 #define BCWR16(dev, addr, val) \
530    CHK_ERROR(DRXJ_DAP.write_reg16func( (dev), (addr), (val), DRXDAP_FASI_BROADCAST) )
531
532 #define ARR32(dev, addr, val) \
533    CHK_ERROR(drxj_dap_atomic_read_reg32( (dev), (addr), (val), 0) )
534
535 #define SARR16(dev, addr, val) \
536    CHK_ERROR(drxj_dap_scu_atomic_read_reg16( (dev), (addr), (val), 0) )
537
538 #define SAWR16(dev, addr, val) \
539    CHK_ERROR(drxj_dap_scu_atomic_write_reg16( (dev), (addr), (val), 0) )
540
541 /**
542 * This macro is used to create byte arrays for block writes.
543 * Block writes speed up I2C traffic between host and demod.
544 * The macro takes care of the required byte order in a 16 bits word.
545 * x -> lowbyte(x), highbyte(x)
546 */
547 #define DRXJ_16TO8(x) ((u8) (((u16)x) & 0xFF)), \
548                         ((u8)((((u16)x)>>8)&0xFF))
549 /**
550 * This macro is used to convert byte array to 16 bit register value for block read.
551 * Block read speed up I2C traffic between host and demod.
552 * The macro takes care of the required byte order in a 16 bits word.
553 */
554 #define DRXJ_8TO16(x) ((u16) (x[0] | (x[1] << 8)))
555
556 /*============================================================================*/
557 /*=== MISC DEFINES ===========================================================*/
558 /*============================================================================*/
559
560 /*============================================================================*/
561 /*=== HI COMMAND RELATED DEFINES =============================================*/
562 /*============================================================================*/
563
564 /**
565 * \brief General maximum number of retries for ucode command interfaces
566 */
567 #define DRXJ_MAX_RETRIES (100)
568
569 /*============================================================================*/
570 /*=== STANDARD RELATED MACROS ================================================*/
571 /*============================================================================*/
572
573 #define DRXJ_ISATVSTD(std) ( ( std == DRX_STANDARD_PAL_SECAM_BG ) || \
574                                (std == DRX_STANDARD_PAL_SECAM_DK) || \
575                                (std == DRX_STANDARD_PAL_SECAM_I) || \
576                                (std == DRX_STANDARD_PAL_SECAM_L) || \
577                                (std == DRX_STANDARD_PAL_SECAM_LP) || \
578                                (std == DRX_STANDARD_NTSC) || \
579                                (std == DRX_STANDARD_FM) )
580
581 #define DRXJ_ISQAMSTD(std) ( ( std == DRX_STANDARD_ITU_A ) || \
582                                (std == DRX_STANDARD_ITU_B) || \
583                                (std == DRX_STANDARD_ITU_C) || \
584                                (std == DRX_STANDARD_ITU_D))
585
586 /*-----------------------------------------------------------------------------
587 STATIC VARIABLES
588 ----------------------------------------------------------------------------*/
589 int drxj_open(pdrx_demod_instance_t demod);
590 int drxj_close(pdrx_demod_instance_t demod);
591 int drxj_ctrl(pdrx_demod_instance_t demod,
592                       u32 ctrl, void *ctrl_data);
593
594 /*-----------------------------------------------------------------------------
595 GLOBAL VARIABLES
596 ----------------------------------------------------------------------------*/
597 /*
598  * DRXJ DAP structures
599  */
600
601 static int drxj_dap_read_block(struct i2c_device_addr *dev_addr,
602                                       dr_xaddr_t addr,
603                                       u16 datasize,
604                                       u8 *data, dr_xflags_t flags);
605
606 static int drxj_dap_read_modify_write_reg8(struct i2c_device_addr *dev_addr,
607                                                 dr_xaddr_t waddr,
608                                                 dr_xaddr_t raddr,
609                                                 u8 wdata, u8 *rdata);
610
611 static int drxj_dap_read_modify_write_reg16(struct i2c_device_addr *dev_addr,
612                                                  dr_xaddr_t waddr,
613                                                  dr_xaddr_t raddr,
614                                                  u16 wdata, u16 *rdata);
615
616 static int drxj_dap_read_modify_write_reg32(struct i2c_device_addr *dev_addr,
617                                                  dr_xaddr_t waddr,
618                                                  dr_xaddr_t raddr,
619                                                  u32 wdata, u32 *rdata);
620
621 static int drxj_dap_read_reg8(struct i2c_device_addr *dev_addr,
622                                      dr_xaddr_t addr,
623                                      u8 *data, dr_xflags_t flags);
624
625 static int drxj_dap_read_reg16(struct i2c_device_addr *dev_addr,
626                                       dr_xaddr_t addr,
627                                       u16 *data, dr_xflags_t flags);
628
629 static int drxj_dap_read_reg32(struct i2c_device_addr *dev_addr,
630                                       dr_xaddr_t addr,
631                                       u32 *data, dr_xflags_t flags);
632
633 static int drxj_dap_write_block(struct i2c_device_addr *dev_addr,
634                                        dr_xaddr_t addr,
635                                        u16 datasize,
636                                        u8 *data, dr_xflags_t flags);
637
638 static int drxj_dap_write_reg8(struct i2c_device_addr *dev_addr,
639                                       dr_xaddr_t addr,
640                                       u8 data, dr_xflags_t flags);
641
642 static int drxj_dap_write_reg16(struct i2c_device_addr *dev_addr,
643                                        dr_xaddr_t addr,
644                                        u16 data, dr_xflags_t flags);
645
646 static int drxj_dap_write_reg32(struct i2c_device_addr *dev_addr,
647                                        dr_xaddr_t addr,
648                                        u32 data, dr_xflags_t flags);
649
650 /* The version structure of this protocol implementation */
651 char drx_dap_drxj_module_name[] = "DRXJ Data Access Protocol";
652 char drx_dap_drxj_version_text[] = "0.0.0";
653
654 drx_version_t drx_dap_drxj_version = {
655         DRX_MODULE_DAP,       /**< type identifier of the module  */
656         drx_dap_drxj_module_name, /**< name or description of module  */
657
658         0,                    /**< major version number           */
659         0,                    /**< minor version number           */
660         0,                    /**< patch version number           */
661         drx_dap_drxj_version_text /**< version as text string         */
662 };
663
664 /* The structure containing the protocol interface */
665 drx_access_func_t drx_dap_drxj_funct_g = {
666         &drx_dap_drxj_version,
667         drxj_dap_write_block,   /* Supported       */
668         drxj_dap_read_block,    /* Supported       */
669         drxj_dap_write_reg8,    /* Not supported   */
670         drxj_dap_read_reg8,     /* Not supported   */
671         drxj_dap_read_modify_write_reg8,        /* Not supported   */
672         drxj_dap_write_reg16,   /* Supported       */
673         drxj_dap_read_reg16,    /* Supported       */
674         drxj_dap_read_modify_write_reg16,       /* Supported       */
675         drxj_dap_write_reg32,   /* Supported       */
676         drxj_dap_read_reg32,    /* Supported       */
677         drxj_dap_read_modify_write_reg32,       /* Not supported   */
678 };
679
680 /**
681 * /var DRXJ_Func_g
682 * /brief The driver functions of the drxj
683 */
684 drx_demod_func_t drxj_functions_g = {
685         DRXJ_TYPE_ID,
686         drxj_open,
687         drxj_close,
688         drxj_ctrl
689 };
690
691 drxj_data_t drxj_data_g = {
692         false,                  /* has_lna : true if LNA (aka PGA) present      */
693         false,                  /* has_oob : true if OOB supported              */
694         false,                  /* has_ntsc: true if NTSC supported             */
695         false,                  /* has_btsc: true if BTSC supported             */
696         false,                  /* has_smatx: true if SMA_TX pin is available   */
697         false,                  /* has_smarx: true if SMA_RX pin is available   */
698         false,                  /* has_gpio : true if GPIO pin is available     */
699         false,                  /* has_irqn : true if IRQN pin is available     */
700         0,                      /* mfx A1/A2/A... */
701
702         /* tuner settings */
703         false,                  /* tuner mirrors RF signal    */
704         /* standard/channel settings */
705         DRX_STANDARD_UNKNOWN,   /* current standard           */
706         DRX_CONSTELLATION_AUTO, /* constellation              */
707         0,                      /* frequency in KHz           */
708         DRX_BANDWIDTH_UNKNOWN,  /* curr_bandwidth              */
709         DRX_MIRROR_NO,          /* mirror                     */
710
711         /* signal quality information: */
712         /* default values taken from the QAM Programming guide */
713         /*   fec_bits_desired should not be less than 4000000    */
714         4000000,                /* fec_bits_desired    */
715         5,                      /* fec_vd_plen         */
716         4,                      /* qam_vd_prescale     */
717         0xFFFF,                 /* qamVDPeriod       */
718         204 * 8,                /* fec_rs_plen annex A */
719         1,                      /* fec_rs_prescale     */
720         FEC_RS_MEASUREMENT_PERIOD,      /* fec_rs_period     */
721         true,                   /* reset_pkt_err_acc    */
722         0,                      /* pkt_errAccStart    */
723
724         /* HI configuration */
725         0,                      /* hi_cfg_timing_div    */
726         0,                      /* hi_cfg_bridge_delay  */
727         0,                      /* hi_cfg_wake_up_key    */
728         0,                      /* hi_cfg_ctrl         */
729         0,                      /* HICfgTimeout      */
730         /* UIO configuartion */
731         DRX_UIO_MODE_DISABLE,   /* uio_sma_rx_mode      */
732         DRX_UIO_MODE_DISABLE,   /* uio_sma_tx_mode      */
733         DRX_UIO_MODE_DISABLE,   /* uioASELMode       */
734         DRX_UIO_MODE_DISABLE,   /* uio_irqn_mode       */
735         /* FS setting */
736         0UL,                    /* iqm_fs_rate_ofs      */
737         false,                  /* pos_image          */
738         /* RC setting */
739         0UL,                    /* iqm_rc_rate_ofs      */
740         /* AUD information */
741 /*   false,                  * flagSetAUDdone    */
742 /*   false,                  * detectedRDS       */
743 /*   true,                   * flagASDRequest    */
744 /*   false,                  * flagHDevClear     */
745 /*   false,                  * flagHDevSet       */
746 /*   (u16) 0xFFF,          * rdsLastCount      */
747
748 /*#ifdef DRXJ_SPLIT_UCODE_UPLOAD
749    false,                  * flag_aud_mc_uploaded */
750 /*#endif * DRXJ_SPLIT_UCODE_UPLOAD */
751         /* ATV configuartion */
752         0UL,                    /* flags cfg changes */
753         /* shadow of ATV_TOP_EQU0__A */
754         {-5,
755          ATV_TOP_EQU0_EQU_C0_FM,
756          ATV_TOP_EQU0_EQU_C0_L,
757          ATV_TOP_EQU0_EQU_C0_LP,
758          ATV_TOP_EQU0_EQU_C0_BG,
759          ATV_TOP_EQU0_EQU_C0_DK,
760          ATV_TOP_EQU0_EQU_C0_I},
761         /* shadow of ATV_TOP_EQU1__A */
762         {-50,
763          ATV_TOP_EQU1_EQU_C1_FM,
764          ATV_TOP_EQU1_EQU_C1_L,
765          ATV_TOP_EQU1_EQU_C1_LP,
766          ATV_TOP_EQU1_EQU_C1_BG,
767          ATV_TOP_EQU1_EQU_C1_DK,
768          ATV_TOP_EQU1_EQU_C1_I},
769         /* shadow of ATV_TOP_EQU2__A */
770         {210,
771          ATV_TOP_EQU2_EQU_C2_FM,
772          ATV_TOP_EQU2_EQU_C2_L,
773          ATV_TOP_EQU2_EQU_C2_LP,
774          ATV_TOP_EQU2_EQU_C2_BG,
775          ATV_TOP_EQU2_EQU_C2_DK,
776          ATV_TOP_EQU2_EQU_C2_I},
777         /* shadow of ATV_TOP_EQU3__A */
778         {-160,
779          ATV_TOP_EQU3_EQU_C3_FM,
780          ATV_TOP_EQU3_EQU_C3_L,
781          ATV_TOP_EQU3_EQU_C3_LP,
782          ATV_TOP_EQU3_EQU_C3_BG,
783          ATV_TOP_EQU3_EQU_C3_DK,
784          ATV_TOP_EQU3_EQU_C3_I},
785         false,                  /* flag: true=bypass             */
786         ATV_TOP_VID_PEAK__PRE,  /* shadow of ATV_TOP_VID_PEAK__A */
787         ATV_TOP_NOISE_TH__PRE,  /* shadow of ATV_TOP_NOISE_TH__A */
788         true,                   /* flag CVBS ouput enable        */
789         false,                  /* flag SIF ouput enable         */
790         DRXJ_SIF_ATTENUATION_0DB,       /* current SIF att setting       */
791         {                       /* qam_rf_agc_cfg */
792          DRX_STANDARD_ITU_B,    /* standard            */
793          DRX_AGC_CTRL_AUTO,     /* ctrl_mode            */
794          0,                     /* output_level         */
795          0,                     /* min_output_level      */
796          0xFFFF,                /* max_output_level      */
797          0x0000,                /* speed               */
798          0x0000,                /* top                 */
799          0x0000                 /* c.o.c.              */
800          },
801         {                       /* qam_if_agc_cfg */
802          DRX_STANDARD_ITU_B,    /* standard            */
803          DRX_AGC_CTRL_AUTO,     /* ctrl_mode            */
804          0,                     /* output_level         */
805          0,                     /* min_output_level      */
806          0xFFFF,                /* max_output_level      */
807          0x0000,                /* speed               */
808          0x0000,                /* top    (don't care) */
809          0x0000                 /* c.o.c. (don't care) */
810          },
811         {                       /* vsb_rf_agc_cfg */
812          DRX_STANDARD_8VSB,     /* standard       */
813          DRX_AGC_CTRL_AUTO,     /* ctrl_mode       */
814          0,                     /* output_level    */
815          0,                     /* min_output_level */
816          0xFFFF,                /* max_output_level */
817          0x0000,                /* speed          */
818          0x0000,                /* top    (don't care) */
819          0x0000                 /* c.o.c. (don't care) */
820          },
821         {                       /* vsb_if_agc_cfg */
822          DRX_STANDARD_8VSB,     /* standard       */
823          DRX_AGC_CTRL_AUTO,     /* ctrl_mode       */
824          0,                     /* output_level    */
825          0,                     /* min_output_level */
826          0xFFFF,                /* max_output_level */
827          0x0000,                /* speed          */
828          0x0000,                /* top    (don't care) */
829          0x0000                 /* c.o.c. (don't care) */
830          },
831         0,                      /* qam_pga_cfg */
832         0,                      /* vsb_pga_cfg */
833         {                       /* qam_pre_saw_cfg */
834          DRX_STANDARD_ITU_B,    /* standard  */
835          0,                     /* reference */
836          false                  /* use_pre_saw */
837          },
838         {                       /* vsb_pre_saw_cfg */
839          DRX_STANDARD_8VSB,     /* standard  */
840          0,                     /* reference */
841          false                  /* use_pre_saw */
842          },
843
844         /* Version information */
845 #ifndef _CH_
846         {
847          "01234567890",         /* human readable version microcode             */
848          "01234567890"          /* human readable version device specific code  */
849          },
850         {
851          {                      /* drx_version_t for microcode                   */
852           DRX_MODULE_UNKNOWN,
853           (char *)(NULL),
854           0,
855           0,
856           0,
857           (char *)(NULL)
858           },
859          {                      /* drx_version_t for device specific code */
860           DRX_MODULE_UNKNOWN,
861           (char *)(NULL),
862           0,
863           0,
864           0,
865           (char *)(NULL)
866           }
867          },
868         {
869          {                      /* drx_version_list_t for microcode */
870           (pdrx_version_t) (NULL),
871           (p_drx_version_list_t) (NULL)
872           },
873          {                      /* drx_version_list_t for device specific code */
874           (pdrx_version_t) (NULL),
875           (p_drx_version_list_t) (NULL)
876           }
877          },
878 #endif
879         false,                  /* smart_ant_inverted */
880         /* Tracking filter setting for OOB  */
881         {
882          12000,
883          9300,
884          6600,
885          5280,
886          3700,
887          3000,
888          2000,
889          0},
890         false,                  /* oob_power_on           */
891         0,                      /* mpeg_ts_static_bitrate  */
892         false,                  /* disable_te_ihandling   */
893         false,                  /* bit_reverse_mpeg_outout */
894         DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO,        /* mpeg_output_clock_rate */
895         DRXJ_MPEG_START_WIDTH_1CLKCYC,  /* mpeg_start_width */
896
897         /* Pre SAW & Agc configuration for ATV */
898         {
899          DRX_STANDARD_NTSC,     /* standard     */
900          7,                     /* reference    */
901          true                   /* use_pre_saw    */
902          },
903         {                       /* ATV RF-AGC */
904          DRX_STANDARD_NTSC,     /* standard              */
905          DRX_AGC_CTRL_AUTO,     /* ctrl_mode              */
906          0,                     /* output_level           */
907          0,                     /* min_output_level (d.c.) */
908          0,                     /* max_output_level (d.c.) */
909          3,                     /* speed                 */
910          9500,                  /* top                   */
911          4000                   /* cut-off current       */
912          },
913         {                       /* ATV IF-AGC */
914          DRX_STANDARD_NTSC,     /* standard              */
915          DRX_AGC_CTRL_AUTO,     /* ctrl_mode              */
916          0,                     /* output_level           */
917          0,                     /* min_output_level (d.c.) */
918          0,                     /* max_output_level (d.c.) */
919          3,                     /* speed                 */
920          2400,                  /* top                   */
921          0                      /* c.o.c.         (d.c.) */
922          },
923         140,                    /* ATV PGA config */
924         0,                      /* curr_symbol_rate */
925
926         false,                  /* pdr_safe_mode     */
927         SIO_PDR_GPIO_CFG__PRE,  /* pdr_safe_restore_val_gpio  */
928         SIO_PDR_VSYNC_CFG__PRE, /* pdr_safe_restore_val_v_sync */
929         SIO_PDR_SMA_RX_CFG__PRE,        /* pdr_safe_restore_val_sma_rx */
930         SIO_PDR_SMA_TX_CFG__PRE,        /* pdr_safe_restore_val_sma_tx */
931
932         4,                      /* oob_pre_saw            */
933         DRXJ_OOB_LO_POW_MINUS10DB,      /* oob_lo_pow             */
934         {
935          false                  /* aud_data, only first member */
936          },
937 };
938
939 /**
940 * \var drxj_default_addr_g
941 * \brief Default I2C address and device identifier.
942 */
943 struct i2c_device_addr drxj_default_addr_g = {
944         DRXJ_DEF_I2C_ADDR,      /* i2c address */
945         DRXJ_DEF_DEMOD_DEV_ID   /* device id */
946 };
947
948 /**
949 * \var drxj_default_comm_attr_g
950 * \brief Default common attributes of a drxj demodulator instance.
951 */
952 drx_common_attr_t drxj_default_comm_attr_g = {
953         (u8 *) NULL,            /* ucode ptr            */
954         0,                      /* ucode size           */
955         true,                   /* ucode verify switch  */
956         {0},                    /* version record       */
957
958         44000,                  /* IF in kHz in case no tuner instance is used  */
959         (151875 - 0),           /* system clock frequency in kHz                */
960         0,                      /* oscillator frequency kHz                     */
961         0,                      /* oscillator deviation in ppm, signed          */
962         false,                  /* If true mirror frequency spectrum            */
963         {
964          /* MPEG output configuration */
965          true,                  /* If true, enable MPEG ouput    */
966          false,                 /* If true, insert RS byte       */
967          true,                  /* If true, parallel out otherwise serial */
968          false,                 /* If true, invert DATA signals  */
969          false,                 /* If true, invert ERR signal    */
970          false,                 /* If true, invert STR signals   */
971          false,                 /* If true, invert VAL signals   */
972          false,                 /* If true, invert CLK signals   */
973          true,                  /* If true, static MPEG clockrate will
974                                    be used, otherwise clockrate will
975                                    adapt to the bitrate of the TS */
976          19392658UL,            /* Maximum bitrate in b/s in case
977                                    static clockrate is selected */
978          DRX_MPEG_STR_WIDTH_1   /* MPEG Start width in clock cycles */
979          },
980         /* Initilisations below can be ommited, they require no user input and
981            are initialy 0, NULL or false. The compiler will initialize them to these
982            values when ommited.  */
983         false,                  /* is_opened */
984
985         /* SCAN */
986         NULL,                   /* no scan params yet               */
987         0,                      /* current scan index               */
988         0,                      /* next scan frequency              */
989         false,                  /* scan ready flag                  */
990         0,                      /* max channels to scan             */
991         0,                      /* nr of channels scanned           */
992         NULL,                   /* default scan function            */
993         NULL,                   /* default context pointer          */
994         0,                      /* millisec to wait for demod lock  */
995         DRXJ_DEMOD_LOCK,        /* desired lock               */
996         false,
997
998         /* Power management */
999         DRX_POWER_UP,
1000
1001         /* Tuner */
1002         1,                      /* nr of I2C port to wich tuner is     */
1003         0L,                     /* minimum RF input frequency, in kHz  */
1004         0L,                     /* maximum RF input frequency, in kHz  */
1005         false,                  /* Rf Agc Polarity                     */
1006         false,                  /* If Agc Polarity                     */
1007         false,                  /* tuner slow mode                     */
1008
1009         {                       /* current channel (all 0)             */
1010          0UL                    /* channel.frequency */
1011          },
1012         DRX_STANDARD_UNKNOWN,   /* current standard */
1013         DRX_STANDARD_UNKNOWN,   /* previous standard */
1014         DRX_STANDARD_UNKNOWN,   /* di_cache_standard   */
1015         false,                  /* use_bootloader */
1016         0UL,                    /* capabilities */
1017         0                       /* mfx */
1018 };
1019
1020 /**
1021 * \var drxj_default_demod_g
1022 * \brief Default drxj demodulator instance.
1023 */
1024 drx_demod_instance_t drxj_default_demod_g = {
1025         &drxj_functions_g,      /* demod functions */
1026         &DRXJ_DAP,              /* data access protocol functions */
1027         NULL,                   /* tuner instance */
1028         &drxj_default_addr_g,   /* i2c address & device id */
1029         &drxj_default_comm_attr_g,      /* demod common attributes */
1030         &drxj_data_g            /* demod device specific attributes */
1031 };
1032
1033 /**
1034 * \brief Default audio data structure for DRK demodulator instance.
1035 *
1036 * This structure is DRXK specific.
1037 *
1038 */
1039 drx_aud_data_t drxj_default_aud_data_g = {
1040         false,                  /* audio_is_active */
1041         DRX_AUD_STANDARD_AUTO,  /* audio_standard  */
1042
1043         /* i2sdata */
1044         {
1045          false,                 /* output_enable   */
1046          48000,                 /* frequency      */
1047          DRX_I2S_MODE_MASTER,   /* mode           */
1048          DRX_I2S_WORDLENGTH_32, /* word_length     */
1049          DRX_I2S_POLARITY_RIGHT,        /* polarity       */
1050          DRX_I2S_FORMAT_WS_WITH_DATA    /* format         */
1051          },
1052         /* volume            */
1053         {
1054          true,                  /* mute;          */
1055          0,                     /* volume         */
1056          DRX_AUD_AVC_OFF,       /* avc_mode        */
1057          0,                     /* avc_ref_level    */
1058          DRX_AUD_AVC_MAX_GAIN_12DB,     /* avc_max_gain     */
1059          DRX_AUD_AVC_MAX_ATTEN_24DB,    /* avc_max_atten    */
1060          0,                     /* strength_left   */
1061          0                      /* strength_right  */
1062          },
1063         DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_ON, /* auto_sound */
1064         /*  ass_thresholds */
1065         {
1066          440,                   /* A2    */
1067          12,                    /* BTSC  */
1068          700,                   /* NICAM */
1069          },
1070         /* carrier */
1071         {
1072          /* a */
1073          {
1074           42,                   /* thres */
1075           DRX_NO_CARRIER_NOISE, /* opt   */
1076           0,                    /* shift */
1077           0                     /* dco   */
1078           },
1079          /* b */
1080          {
1081           42,                   /* thres */
1082           DRX_NO_CARRIER_MUTE,  /* opt   */
1083           0,                    /* shift */
1084           0                     /* dco   */
1085           },
1086
1087          },
1088         /* mixer */
1089         {
1090          DRX_AUD_SRC_STEREO_OR_A,       /* source_i2s */
1091          DRX_AUD_I2S_MATRIX_STEREO,     /* matrix_i2s */
1092          DRX_AUD_FM_MATRIX_SOUND_A      /* matrix_fm  */
1093          },
1094         DRX_AUD_DEVIATION_NORMAL,       /* deviation */
1095         DRX_AUD_AVSYNC_OFF,     /* av_sync */
1096
1097         /* prescale */
1098         {
1099          DRX_AUD_MAX_FM_DEVIATION,      /* fm_deviation */
1100          DRX_AUD_MAX_NICAM_PRESCALE     /* nicam_gain */
1101          },
1102         DRX_AUD_FM_DEEMPH_75US, /* deemph */
1103         DRX_BTSC_STEREO,        /* btsc_detect */
1104         0,                      /* rds_data_counter */
1105         false                   /* rds_data_present */
1106 };
1107
1108 /*-----------------------------------------------------------------------------
1109 STRUCTURES
1110 ----------------------------------------------------------------------------*/
1111 typedef struct {
1112         u16 eq_mse;
1113         u8 eq_mode;
1114         u8 eq_ctrl;
1115         u8 eq_stat;
1116 } drxjeq_stat_t, *pdrxjeq_stat_t;
1117
1118 /* HI command */
1119 typedef struct {
1120         u16 cmd;
1121         u16 param1;
1122         u16 param2;
1123         u16 param3;
1124         u16 param4;
1125         u16 param5;
1126         u16 param6;
1127 } drxj_hi_cmd_t, *pdrxj_hi_cmd_t;
1128
1129 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
1130 /*============================================================================*/
1131 /*=== MICROCODE RELATED STRUCTURES ===========================================*/
1132 /*============================================================================*/
1133
1134 typedef struct {
1135         u32 addr;
1136         u16 size;
1137         u16 flags;              /* bit[15..2]=reserved,
1138                                    bit[1]= compression on/off
1139                                    bit[0]= CRC on/off */
1140         u16 CRC;
1141 } drxu_code_block_hdr_t, *pdrxu_code_block_hdr_t;
1142 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
1143
1144 /*-----------------------------------------------------------------------------
1145 FUNCTIONS
1146 ----------------------------------------------------------------------------*/
1147 /* Some prototypes */
1148 static int
1149 hi_command(struct i2c_device_addr *dev_addr,
1150           const pdrxj_hi_cmd_t cmd, u16 *result);
1151
1152 static int
1153 ctrl_lock_status(pdrx_demod_instance_t demod, pdrx_lock_status_t lock_stat);
1154
1155 static int
1156 ctrl_power_mode(pdrx_demod_instance_t demod, pdrx_power_mode_t mode);
1157
1158 static int power_down_aud(pdrx_demod_instance_t demod);
1159
1160 #ifndef DRXJ_DIGITAL_ONLY
1161 static int power_up_aud(pdrx_demod_instance_t demod, bool set_standard);
1162 #endif
1163
1164 static int
1165 aud_ctrl_set_standard(pdrx_demod_instance_t demod, pdrx_aud_standard_t standard);
1166
1167 static int
1168 ctrl_set_cfg_pre_saw(pdrx_demod_instance_t demod, p_drxj_cfg_pre_saw_t pre_saw);
1169
1170 static int
1171 ctrl_set_cfg_afe_gain(pdrx_demod_instance_t demod, p_drxj_cfg_afe_gain_t afe_gain);
1172
1173 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
1174 static int
1175 ctrl_u_codeUpload(pdrx_demod_instance_t demod,
1176                 p_drxu_code_info_t mc_info,
1177                 drxu_code_action_t action, bool audio_mc_upload);
1178 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
1179
1180 /*============================================================================*/
1181 /*============================================================================*/
1182 /*==                          HELPER FUNCTIONS                              ==*/
1183 /*============================================================================*/
1184 /*============================================================================*/
1185
1186 /**
1187 * \fn void mult32(u32 a, u32 b, u32 *h, u32 *l)
1188 * \brief 32bitsx32bits signed multiplication
1189 * \param a 32 bits multiplicant, typecast from signed to unisgned
1190 * \param b 32 bits multiplier, typecast from signed to unisgned
1191 * \param h pointer to high part 64 bits result, typecast from signed to unisgned
1192 * \param l pointer to low part 64 bits result
1193 *
1194 * For the 2n+n addition a + b:
1195 * if a >= 0, then h += 0 (sign extension = 0)
1196 * but if a < 0, then h += 2^n-1 ==> h -= 1.
1197 *
1198 * Also, if a + b < 2^n, then a + b  >= a && a + b >= b
1199 * but if a + b >= 2^n, then R = a + b - 2^n,
1200 * and because a < 2^n && b < 2*n ==> R < a && R < b.
1201 * Therefore, to detect overflow, simply compare the addition result with
1202 * one of the operands; if the result is smaller, overflow has occurred and
1203 * h must be incremented.
1204 *
1205 * Booth multiplication uses additions and subtractions to reduce the number
1206 * of iterations. This is done by taking three subsequent bits abc and calculating
1207 * the following multiplication factor: -2a + b + c. This factor is multiplied
1208 * by the second operand and added to the result. Next, the first operand is
1209 * shifted two bits (hence one of the three bits is reused) and the process
1210 * repeated. The last iteration has only two bits left, but we simply add
1211 * a zero to the end.
1212 *
1213 * Hence: (n=4)
1214 *  1 * a =  0 * 4a + 1 * a
1215 *  2 * a =  1 * 4a - 2 * a
1216 *  3 * a =  1 * 4a - 1 * a
1217 * -1 * a =  0 * 4a - 1 * a
1218 * -5 * a = -1 * 4a - 1 * a
1219 *
1220 * etc.
1221 *
1222 * Note that the function is type size independent. Any unsigned integer type
1223 * can be substituted for booth_t.
1224 *
1225 */
1226
1227 #define DRX_IS_BOOTH_NEGATIVE(__a)  (((__a) & (1 << (sizeof(u32) * 8 - 1))) != 0)
1228
1229 static void mult32(u32 a, u32 b, u32 *h, u32 *l)
1230 {
1231         unsigned int i;
1232         *h = *l = 0;
1233
1234         /* n/2 iterations; shift operand a left two bits after each iteration.      */
1235         /* This automatically appends a zero to the operand for the last iteration. */
1236         for (i = 0; i < sizeof(a) * 8; i += 2, a = a << 2) {
1237                 /* Shift result left two bits */
1238                 *h = (*h << 2) + (*l >> (sizeof(*l) * 8 - 2));
1239                 *l = (*l << 2);
1240
1241                 /* Take the first three bits of operand a for the Booth conversion: */
1242                 /* 0, 7: do nothing  */
1243                 /* 1, 2: add b       */
1244                 /* 3   : add 2b      */
1245                 /* 4   : subtract 2b */
1246                 /* 5, 6: subtract b  */
1247                 switch (a >> (sizeof(a) * 8 - 3)) {
1248                 case 3:
1249                         *l += b;
1250                         *h = *h - DRX_IS_BOOTH_NEGATIVE(b) + (*l < b);
1251                 case 1:
1252                 case 2:
1253                         *l += b;
1254                         *h = *h - DRX_IS_BOOTH_NEGATIVE(b) + (*l < b);
1255                         break;
1256                 case 4:
1257                         *l -= b;
1258                         *h = *h - !DRX_IS_BOOTH_NEGATIVE(b) + !b + (*l <
1259                                                                     ((u32)
1260                                                                      (-
1261                                                                       ((s32)
1262                                                                        b))));
1263                 case 5:
1264                 case 6:
1265                         *l -= b;
1266                         *h = *h - !DRX_IS_BOOTH_NEGATIVE(b) + !b + (*l <
1267                                                                     ((u32)
1268                                                                      (-
1269                                                                       ((s32)
1270                                                                        b))));
1271                         break;
1272                 }
1273         }
1274 }
1275
1276 /*============================================================================*/
1277
1278 /*
1279 * \fn u32 frac28(u32 N, u32 D)
1280 * \brief Compute: (1<<28)*N/D
1281 * \param N 32 bits
1282 * \param D 32 bits
1283 * \return (1<<28)*N/D
1284 * This function is used to avoid floating-point calculations as they may
1285 * not be present on the target platform.
1286
1287 * frac28 performs an unsigned 28/28 bits division to 32-bit fixed point
1288 * fraction used for setting the Frequency Shifter registers.
1289 * N and D can hold numbers up to width: 28-bits.
1290 * The 4 bits integer part and the 28 bits fractional part are calculated.
1291
1292 * Usage condition: ((1<<28)*n)/d < ((1<<32)-1) => (n/d) < 15.999
1293
1294 * N: 0...(1<<28)-1 = 268435454
1295 * D: 0...(1<<28)-1
1296 * Q: 0...(1<<32)-1
1297 */
1298 static u32 frac28(u32 N, u32 D)
1299 {
1300         int i = 0;
1301         u32 Q1 = 0;
1302         u32 R0 = 0;
1303
1304         R0 = (N % D) << 4;      /* 32-28 == 4 shifts possible at max */
1305         Q1 = N / D;             /* integer part, only the 4 least significant bits
1306                                    will be visible in the result */
1307
1308         /* division using radix 16, 7 nibbles in the result */
1309         for (i = 0; i < 7; i++) {
1310                 Q1 = (Q1 << 4) | R0 / D;
1311                 R0 = (R0 % D) << 4;
1312         }
1313         /* rounding */
1314         if ((R0 >> 3) >= D)
1315                 Q1++;
1316
1317         return Q1;
1318 }
1319
1320 /**
1321 * \fn u32 log1_times100( u32 x)
1322 * \brief Compute: 100*log10(x)
1323 * \param x 32 bits
1324 * \return 100*log10(x)
1325 *
1326 * 100*log10(x)
1327 * = 100*(log2(x)/log2(10)))
1328 * = (100*(2^15)*log2(x))/((2^15)*log2(10))
1329 * = ((200*(2^15)*log2(x))/((2^15)*log2(10)))/2
1330 * = ((200*(2^15)*(log2(x/y)+log2(y)))/((2^15)*log2(10)))/2
1331 * = ((200*(2^15)*log2(x/y))+(200*(2^15)*log2(y)))/((2^15)*log2(10)))/2
1332 *
1333 * where y = 2^k and 1<= (x/y) < 2
1334 */
1335
1336 static u32 log1_times100(u32 x)
1337 {
1338         static const u8 scale = 15;
1339         static const u8 index_width = 5;
1340         /*
1341            log2lut[n] = (1<<scale) * 200 * log2( 1.0 + ( (1.0/(1<<INDEXWIDTH)) * n ))
1342            0 <= n < ((1<<INDEXWIDTH)+1)
1343          */
1344
1345         static const u32 log2lut[] = {
1346                 0,              /* 0.000000 */
1347                 290941,         /* 290941.300628 */
1348                 573196,         /* 573196.476418 */
1349                 847269,         /* 847269.179851 */
1350                 1113620,        /* 1113620.489452 */
1351                 1372674,        /* 1372673.576986 */
1352                 1624818,        /* 1624817.752104 */
1353                 1870412,        /* 1870411.981536 */
1354                 2109788,        /* 2109787.962654 */
1355                 2343253,        /* 2343252.817465 */
1356                 2571091,        /* 2571091.461923 */
1357                 2793569,        /* 2793568.696416 */
1358                 3010931,        /* 3010931.055901 */
1359                 3223408,        /* 3223408.452106 */
1360                 3431216,        /* 3431215.635215 */
1361                 3634553,        /* 3634553.498355 */
1362                 3833610,        /* 3833610.244726 */
1363                 4028562,        /* 4028562.434393 */
1364                 4219576,        /* 4219575.925308 */
1365                 4406807,        /* 4406806.721144 */
1366                 4590402,        /* 4590401.736809 */
1367                 4770499,        /* 4770499.491025 */
1368                 4947231,        /* 4947230.734179 */
1369                 5120719,        /* 5120719.018555 */
1370                 5291081,        /* 5291081.217197 */
1371                 5458428,        /* 5458427.996830 */
1372                 5622864,        /* 5622864.249668 */
1373                 5784489,        /* 5784489.488298 */
1374                 5943398,        /* 5943398.207380 */
1375                 6099680,        /* 6099680.215452 */
1376                 6253421,        /* 6253420.939751 */
1377                 6404702,        /* 6404701.706649 */
1378                 6553600,        /* 6553600.000000 */
1379         };
1380
1381         u8 i = 0;
1382         u32 y = 0;
1383         u32 d = 0;
1384         u32 k = 0;
1385         u32 r = 0;
1386
1387         if (x == 0)
1388                 return (0);
1389
1390         /* Scale x (normalize) */
1391         /* computing y in log(x/y) = log(x) - log(y) */
1392         if ((x & (((u32) (-1)) << (scale + 1))) == 0) {
1393                 for (k = scale; k > 0; k--) {
1394                         if (x & (((u32) 1) << scale))
1395                                 break;
1396                         x <<= 1;
1397                 }
1398         } else {
1399                 for (k = scale; k < 31; k++) {
1400                         if ((x & (((u32) (-1)) << (scale + 1))) == 0)
1401                                 break;
1402                         x >>= 1;
1403                 }
1404         }
1405         /*
1406            Now x has binary point between bit[scale] and bit[scale-1]
1407            and 1.0 <= x < 2.0 */
1408
1409         /* correction for divison: log(x) = log(x/y)+log(y) */
1410         y = k * ((((u32) 1) << scale) * 200);
1411
1412         /* remove integer part */
1413         x &= ((((u32) 1) << scale) - 1);
1414         /* get index */
1415         i = (u8) (x >> (scale - index_width));
1416         /* compute delta (x-a) */
1417         d = x & ((((u32) 1) << (scale - index_width)) - 1);
1418         /* compute log, multiplication ( d* (.. )) must be within range ! */
1419         y += log2lut[i] +
1420             ((d * (log2lut[i + 1] - log2lut[i])) >> (scale - index_width));
1421         /* Conver to log10() */
1422         y /= 108853;            /* (log2(10) << scale) */
1423         r = (y >> 1);
1424         /* rounding */
1425         if (y & ((u32) 1))
1426                 r++;
1427
1428         return (r);
1429
1430 }
1431
1432 /**
1433 * \fn u32 frac_times1e6( u16 N, u32 D)
1434 * \brief Compute: (N/D) * 1000000.
1435 * \param N nominator 16-bits.
1436 * \param D denominator 32-bits.
1437 * \return u32
1438 * \retval ((N/D) * 1000000), 32 bits
1439 *
1440 * No check on D=0!
1441 */
1442 static u32 frac_times1e6(u32 N, u32 D)
1443 {
1444         u32 remainder = 0;
1445         u32 frac = 0;
1446
1447         /*
1448            frac = (N * 1000000) / D
1449            To let it fit in a 32 bits computation:
1450            frac = (N * (1000000 >> 4)) / (D >> 4)
1451            This would result in a problem in case D < 16 (div by 0).
1452            So we do it more elaborate as shown below.
1453          */
1454         frac = (((u32) N) * (1000000 >> 4)) / D;
1455         frac <<= 4;
1456         remainder = (((u32) N) * (1000000 >> 4)) % D;
1457         remainder <<= 4;
1458         frac += remainder / D;
1459         remainder = remainder % D;
1460         if ((remainder * 2) > D) {
1461                 frac++;
1462         }
1463
1464         return (frac);
1465 }
1466
1467 /*============================================================================*/
1468
1469 /**
1470 * \brief Compute: 100 * 10^( gd_b / 200 ).
1471 * \param  u32   gd_b      Gain in 0.1dB
1472 * \return u32            Gainfactor in 0.01 resolution
1473 *
1474 */
1475 static u32 d_b2lin_times100(u32 gd_b)
1476 {
1477         u32 result = 0;
1478         u32 nr6d_b_steps = 0;
1479         u32 remainder = 0;
1480         u32 remainder_fac = 0;
1481
1482         /* start with factors 2 (6.02dB) */
1483         nr6d_b_steps = gd_b * 1000UL / 60206UL;
1484         if (nr6d_b_steps > 17) {
1485                 /* Result max overflow if > log2( maxu32 / 2e4 ) ~= 17.7 */
1486                 return MAX_U32;
1487         }
1488         result = (1 << nr6d_b_steps);
1489
1490         /* calculate remaining factor,
1491            poly approximation of 10^(gd_b/200):
1492
1493            y = 1E-04x2 + 0.0106x + 1.0026
1494
1495            max deviation < 0.005 for range x = [0 ... 60]
1496          */
1497         remainder = ((gd_b * 1000UL) % 60206UL) / 1000UL;
1498         /* using 1e-4 for poly calculation  */
1499         remainder_fac = 1 * remainder * remainder;
1500         remainder_fac += 106 * remainder;
1501         remainder_fac += 10026;
1502
1503         /* multiply by remaining factor */
1504         result *= remainder_fac;
1505
1506         /* conversion from 1e-4 to 1e-2 */
1507         return ((result + 50) / 100);
1508 }
1509
1510 #ifndef DRXJ_DIGITAL_ONLY
1511 #define FRAC_FLOOR    0
1512 #define FRAC_CEIL     1
1513 #define FRAC_ROUND    2
1514 /**
1515 * \fn u32 frac( u32 N, u32 D, u16 RC )
1516 * \brief Compute: N/D.
1517 * \param N nominator 32-bits.
1518 * \param D denominator 32-bits.
1519 * \param RC-result correction: 0-floor; 1-ceil; 2-round
1520 * \return u32
1521 * \retval N/D, 32 bits
1522 *
1523 * If D=0 returns 0
1524 */
1525 static u32 frac(u32 N, u32 D, u16 RC)
1526 {
1527         u32 remainder = 0;
1528         u32 frac = 0;
1529         u16 bit_cnt = 32;
1530
1531         if (D == 0) {
1532                 frac = 0;
1533                 remainder = 0;
1534
1535                 return (frac);
1536         }
1537
1538         if (D > N) {
1539                 frac = 0;
1540                 remainder = N;
1541         } else {
1542                 remainder = 0;
1543                 frac = N;
1544                 while (bit_cnt-- > 0) {
1545                         remainder <<= 1;
1546                         remainder |= ((frac & 0x80000000) >> 31);
1547                         frac <<= 1;
1548                         if (remainder < D) {
1549                                 frac &= 0xFFFFFFFE;
1550                         } else {
1551                                 remainder -= D;
1552                                 frac |= 0x1;
1553                         }
1554                 }
1555
1556                 /* result correction if needed */
1557                 if ((RC == FRAC_CEIL) && (remainder != 0)) {
1558                         /* ceil the result */
1559                         /*(remainder is not zero -> value behind decimal point exists) */
1560                         frac++;
1561                 }
1562                 if ((RC == FRAC_ROUND) && (remainder >= D >> 1)) {
1563                         /* remainder is bigger from D/2 -> round the result */
1564                         frac++;
1565                 }
1566         }
1567
1568         return (frac);
1569 }
1570 #endif
1571
1572 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
1573 /*============================================================================*/
1574
1575 /**
1576 * \fn u16 u_code_read16( u8 *addr)
1577 * \brief Read a 16 bits word, expect big endian data.
1578 * \return u16 The data read.
1579 */
1580 static u16 u_code_read16(u8 *addr)
1581 {
1582         /* Works fo any host processor */
1583
1584         u16 word = 0;
1585
1586         word = ((u16) addr[0]);
1587         word <<= 8;
1588         word |= ((u16) addr[1]);
1589
1590         return (word);
1591 }
1592
1593 /*============================================================================*/
1594
1595 /**
1596 * \fn u32 u_code_read32( u8 *addr)
1597 * \brief Read a 32 bits word, expect big endian data.
1598 * \return u32 The data read.
1599 */
1600 static u32 u_code_read32(u8 *addr)
1601 {
1602         /* Works fo any host processor */
1603
1604         u32 word = 0;
1605
1606         word = ((u16) addr[0]);
1607         word <<= 8;
1608         word |= ((u16) addr[1]);
1609         word <<= 8;
1610         word |= ((u16) addr[2]);
1611         word <<= 8;
1612         word |= ((u16) addr[3]);
1613
1614         return (word);
1615 }
1616
1617 /*============================================================================*/
1618
1619 /**
1620 * \fn u16 u_code_compute_crc (u8 *block_data, u16 nr_words)
1621 * \brief Compute CRC of block of microcode data.
1622 * \param block_data Pointer to microcode data.
1623 * \param nr_words Size of microcode block (number of 16 bits words).
1624 * \return u16 The computed CRC residu.
1625 */
1626 static u16 u_code_compute_crc(u8 *block_data, u16 nr_words)
1627 {
1628         u16 i = 0;
1629         u16 j = 0;
1630         u32 crc_word = 0;
1631         u32 carry = 0;
1632
1633         while (i < nr_words) {
1634                 crc_word |= (u32) u_code_read16(block_data);
1635                 for (j = 0; j < 16; j++) {
1636                         crc_word <<= 1;
1637                         if (carry != 0)
1638                                 crc_word ^= 0x80050000UL;
1639                         carry = crc_word & 0x80000000UL;
1640                 }
1641                 i++;
1642                 block_data += (sizeof(u16));
1643         }
1644         return ((u16) (crc_word >> 16));
1645 }
1646 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
1647
1648 /**
1649 * \brief Values for NICAM prescaler gain. Computed from dB to integer
1650 *        and rounded. For calc used formula: 16*10^(prescaleGain[dB]/20).
1651 *
1652 */
1653 static const u16 nicam_presc_table_val[43] =
1654     { 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4,
1655         5, 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16,
1656         18, 20, 23, 25, 28, 32, 36, 40, 45,
1657         51, 57, 64, 71, 80, 90, 101, 113, 127
1658 };
1659
1660 /*============================================================================*/
1661 /*==                        END HELPER FUNCTIONS                            ==*/
1662 /*============================================================================*/
1663
1664 /*============================================================================*/
1665 /*============================================================================*/
1666 /*==                      DRXJ DAP FUNCTIONS                                ==*/
1667 /*============================================================================*/
1668 /*============================================================================*/
1669
1670 /*
1671    This layer takes care of some device specific register access protocols:
1672    -conversion to short address format
1673    -access to audio block
1674    This layer is placed between the drx_dap_fasi and the rest of the drxj
1675    specific implementation. This layer can use address map knowledge whereas
1676    dap_fasi may not use memory map knowledge.
1677
1678    * For audio currently only 16 bits read and write register access is
1679      supported. More is not needed. RMW and 32 or 8 bit access on audio
1680      registers will have undefined behaviour. Flags (RMW, CRC reset, broadcast
1681      single/multi master) will be ignored.
1682
1683    TODO: check ignoring single/multimaster is ok for AUD access ?
1684 */
1685
1686 #define DRXJ_ISAUDWRITE(addr) (((((addr)>>16)&1) == 1)?true:false)
1687 #define DRXJ_DAP_AUDTRIF_TIMEOUT 80     /* millisec */
1688 /*============================================================================*/
1689
1690 /**
1691 * \fn bool is_handled_by_aud_tr_if( dr_xaddr_t addr )
1692 * \brief Check if this address is handled by the audio token ring interface.
1693 * \param addr
1694 * \return bool
1695 * \retval true  Yes, handled by audio token ring interface
1696 * \retval false No, not handled by audio token ring interface
1697 *
1698 */
1699 static
1700 bool is_handled_by_aud_tr_if(dr_xaddr_t addr)
1701 {
1702         bool retval = false;
1703
1704         if ((DRXDAP_FASI_ADDR2BLOCK(addr) == 4) &&
1705             (DRXDAP_FASI_ADDR2BANK(addr) > 1) &&
1706             (DRXDAP_FASI_ADDR2BANK(addr) < 6)) {
1707                 retval = true;
1708         }
1709
1710         return (retval);
1711 }
1712
1713 /*============================================================================*/
1714
1715 static int drxj_dap_read_block(struct i2c_device_addr *dev_addr,
1716                                       dr_xaddr_t addr,
1717                                       u16 datasize,
1718                                       u8 *data, dr_xflags_t flags)
1719 {
1720         return drx_dap_fasi_funct_g.read_block_func(dev_addr,
1721                                                addr, datasize, data, flags);
1722 }
1723
1724 /*============================================================================*/
1725
1726 static int drxj_dap_read_modify_write_reg8(struct i2c_device_addr *dev_addr,
1727                                                 dr_xaddr_t waddr,
1728                                                 dr_xaddr_t raddr,
1729                                                 u8 wdata, u8 *rdata)
1730 {
1731         return drx_dap_fasi_funct_g.read_modify_write_reg8func(dev_addr,
1732                                                          waddr,
1733                                                          raddr, wdata, rdata);
1734 }
1735
1736 /*============================================================================*/
1737
1738 /**
1739 * \fn int drxj_dap_rm_write_reg16short
1740 * \brief Read modify write 16 bits audio register using short format only.
1741 * \param dev_addr
1742 * \param waddr    Address to write to
1743 * \param raddr    Address to read from (usually SIO_HI_RA_RAM_S0_RMWBUF__A)
1744 * \param wdata    Data to write
1745 * \param rdata    Buffer for data to read
1746 * \return int
1747 * \retval DRX_STS_OK Succes
1748 * \retval DRX_STS_ERROR Timeout, I2C error, illegal bank
1749 *
1750 * 16 bits register read modify write access using short addressing format only.
1751 * Requires knowledge of the registermap, thus device dependent.
1752 * Using DAP FASI directly to avoid endless recursion of RMWs to audio registers.
1753 *
1754 */
1755
1756 /* TODO correct define should be #if ( DRXDAPFASI_SHORT_ADDR_ALLOWED==1 )
1757    See comments drxj_dap_read_modify_write_reg16 */
1758 #if (DRXDAPFASI_LONG_ADDR_ALLOWED == 0)
1759 static int drxj_dap_rm_write_reg16short(struct i2c_device_addr *dev_addr,
1760                                               dr_xaddr_t waddr,
1761                                               dr_xaddr_t raddr,
1762                                               u16 wdata, u16 *rdata)
1763 {
1764         int rc;
1765
1766         if (rdata == NULL) {
1767                 return DRX_STS_INVALID_ARG;
1768         }
1769
1770         /* Set RMW flag */
1771         rc = drx_dap_fasi_funct_g.write_reg16func(dev_addr,
1772                                               SIO_HI_RA_RAM_S0_FLG_ACC__A,
1773                                               SIO_HI_RA_RAM_S0_FLG_ACC_S0_RWM__M,
1774                                               0x0000);
1775         if (rc == DRX_STS_OK) {
1776                 /* Write new data: triggers RMW */
1777                 rc = drx_dap_fasi_funct_g.write_reg16func(dev_addr, waddr, wdata,
1778                                                       0x0000);
1779         }
1780         if (rc == DRX_STS_OK) {
1781                 /* Read old data */
1782                 rc = drx_dap_fasi_funct_g.read_reg16func(dev_addr, raddr, rdata,
1783                                                      0x0000);
1784         }
1785         if (rc == DRX_STS_OK) {
1786                 /* Reset RMW flag */
1787                 rc = drx_dap_fasi_funct_g.write_reg16func(dev_addr,
1788                                                       SIO_HI_RA_RAM_S0_FLG_ACC__A,
1789                                                       0, 0x0000);
1790         }
1791
1792         return rc;
1793 }
1794 #endif
1795
1796 /*============================================================================*/
1797
1798 static int drxj_dap_read_modify_write_reg16(struct i2c_device_addr *dev_addr,
1799                                                  dr_xaddr_t waddr,
1800                                                  dr_xaddr_t raddr,
1801                                                  u16 wdata, u16 *rdata)
1802 {
1803         /* TODO: correct short/long addressing format decision,
1804            now long format has higher prio then short because short also
1805            needs virt bnks (not impl yet) for certain audio registers */
1806 #if (DRXDAPFASI_LONG_ADDR_ALLOWED == 1)
1807         return drx_dap_fasi_funct_g.read_modify_write_reg16func(dev_addr,
1808                                                           waddr,
1809                                                           raddr, wdata, rdata);
1810 #else
1811         return drxj_dap_rm_write_reg16short(dev_addr, waddr, raddr, wdata, rdata);
1812 #endif
1813 }
1814
1815 /*============================================================================*/
1816
1817 static int drxj_dap_read_modify_write_reg32(struct i2c_device_addr *dev_addr,
1818                                                  dr_xaddr_t waddr,
1819                                                  dr_xaddr_t raddr,
1820                                                  u32 wdata, u32 *rdata)
1821 {
1822         return drx_dap_fasi_funct_g.read_modify_write_reg32func(dev_addr,
1823                                                           waddr,
1824                                                           raddr, wdata, rdata);
1825 }
1826
1827 /*============================================================================*/
1828
1829 static int drxj_dap_read_reg8(struct i2c_device_addr *dev_addr,
1830                                      dr_xaddr_t addr,
1831                                      u8 *data, dr_xflags_t flags)
1832 {
1833         return drx_dap_fasi_funct_g.read_reg8func(dev_addr, addr, data, flags);
1834 }
1835
1836 /*============================================================================*/
1837
1838 /**
1839 * \fn int drxj_dap_read_aud_reg16
1840 * \brief Read 16 bits audio register
1841 * \param dev_addr
1842 * \param addr
1843 * \param data
1844 * \return int
1845 * \retval DRX_STS_OK Succes
1846 * \retval DRX_STS_ERROR Timeout, I2C error, illegal bank
1847 *
1848 * 16 bits register read access via audio token ring interface.
1849 *
1850 */
1851 static int drxj_dap_read_aud_reg16(struct i2c_device_addr *dev_addr,
1852                                          dr_xaddr_t addr, u16 *data)
1853 {
1854         u32 start_timer = 0;
1855         u32 current_timer = 0;
1856         u32 delta_timer = 0;
1857         u16 tr_status = 0;
1858         int stat = DRX_STS_ERROR;
1859
1860         /* No read possible for bank 3, return with error */
1861         if (DRXDAP_FASI_ADDR2BANK(addr) == 3) {
1862                 stat = DRX_STS_INVALID_ARG;
1863         } else {
1864                 const dr_xaddr_t write_bit = ((dr_xaddr_t) 1) << 16;
1865
1866                 /* Force reset write bit */
1867                 addr &= (~write_bit);
1868
1869                 /* Set up read */
1870                 start_timer = drxbsp_hst_clock();
1871                 do {
1872                         /* RMW to aud TR IF until request is granted or timeout */
1873                         stat = drxj_dap_read_modify_write_reg16(dev_addr,
1874                                                              addr,
1875                                                              SIO_HI_RA_RAM_S0_RMWBUF__A,
1876                                                              0x0000, &tr_status);
1877
1878                         if (stat != DRX_STS_OK) {
1879                                 break;
1880                         };
1881
1882                         current_timer = drxbsp_hst_clock();
1883                         delta_timer = current_timer - start_timer;
1884                         if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) {
1885                                 stat = DRX_STS_ERROR;
1886                                 break;
1887                         };
1888
1889                 } while (((tr_status & AUD_TOP_TR_CTR_FIFO_LOCK__M) ==
1890                           AUD_TOP_TR_CTR_FIFO_LOCK_LOCKED) ||
1891                          ((tr_status & AUD_TOP_TR_CTR_FIFO_FULL__M) ==
1892                           AUD_TOP_TR_CTR_FIFO_FULL_FULL));
1893         }                       /* if ( DRXDAP_FASI_ADDR2BANK(addr)!=3 ) */
1894
1895         /* Wait for read ready status or timeout */
1896         if (stat == DRX_STS_OK) {
1897                 start_timer = drxbsp_hst_clock();
1898
1899                 while ((tr_status & AUD_TOP_TR_CTR_FIFO_RD_RDY__M) !=
1900                        AUD_TOP_TR_CTR_FIFO_RD_RDY_READY) {
1901                         stat = drxj_dap_read_reg16(dev_addr,
1902                                                   AUD_TOP_TR_CTR__A,
1903                                                   &tr_status, 0x0000);
1904                         if (stat != DRX_STS_OK) {
1905                                 break;
1906                         };
1907
1908                         current_timer = drxbsp_hst_clock();
1909                         delta_timer = current_timer - start_timer;
1910                         if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) {
1911                                 stat = DRX_STS_ERROR;
1912                                 break;
1913                         };
1914                 }               /* while ( ... ) */
1915         }
1916
1917         /* if { stat == DRX_STS_OK ) */
1918         /* Read value */
1919         if (stat == DRX_STS_OK) {
1920                 stat = drxj_dap_read_modify_write_reg16(dev_addr,
1921                                                      AUD_TOP_TR_RD_REG__A,
1922                                                      SIO_HI_RA_RAM_S0_RMWBUF__A,
1923                                                      0x0000, data);
1924         }
1925         /* if { stat == DRX_STS_OK ) */
1926         return stat;
1927 }
1928
1929 /*============================================================================*/
1930
1931 static int drxj_dap_read_reg16(struct i2c_device_addr *dev_addr,
1932                                       dr_xaddr_t addr,
1933                                       u16 *data, dr_xflags_t flags)
1934 {
1935         int stat = DRX_STS_ERROR;
1936
1937         /* Check param */
1938         if ((dev_addr == NULL) || (data == NULL)) {
1939                 return DRX_STS_INVALID_ARG;
1940         }
1941
1942         if (is_handled_by_aud_tr_if(addr)) {
1943                 stat = drxj_dap_read_aud_reg16(dev_addr, addr, data);
1944         } else {
1945                 stat = drx_dap_fasi_funct_g.read_reg16func(dev_addr,
1946                                                        addr, data, flags);
1947         }
1948
1949         return stat;
1950 }
1951
1952 /*============================================================================*/
1953
1954 static int drxj_dap_read_reg32(struct i2c_device_addr *dev_addr,
1955                                       dr_xaddr_t addr,
1956                                       u32 *data, dr_xflags_t flags)
1957 {
1958         return drx_dap_fasi_funct_g.read_reg32func(dev_addr, addr, data, flags);
1959 }
1960
1961 /*============================================================================*/
1962
1963 static int drxj_dap_write_block(struct i2c_device_addr *dev_addr,
1964                                        dr_xaddr_t addr,
1965                                        u16 datasize,
1966                                        u8 *data, dr_xflags_t flags)
1967 {
1968         return drx_dap_fasi_funct_g.write_block_func(dev_addr,
1969                                                 addr, datasize, data, flags);
1970 }
1971
1972 /*============================================================================*/
1973
1974 static int drxj_dap_write_reg8(struct i2c_device_addr *dev_addr,
1975                                       dr_xaddr_t addr,
1976                                       u8 data, dr_xflags_t flags)
1977 {
1978         return drx_dap_fasi_funct_g.write_reg8func(dev_addr, addr, data, flags);
1979 }
1980
1981 /*============================================================================*/
1982
1983 /**
1984 * \fn int drxj_dap_write_aud_reg16
1985 * \brief Write 16 bits audio register
1986 * \param dev_addr
1987 * \param addr
1988 * \param data
1989 * \return int
1990 * \retval DRX_STS_OK Succes
1991 * \retval DRX_STS_ERROR Timeout, I2C error, illegal bank
1992 *
1993 * 16 bits register write access via audio token ring interface.
1994 *
1995 */
1996 static int drxj_dap_write_aud_reg16(struct i2c_device_addr *dev_addr,
1997                                           dr_xaddr_t addr, u16 data)
1998 {
1999         int stat = DRX_STS_ERROR;
2000
2001         /* No write possible for bank 2, return with error */
2002         if (DRXDAP_FASI_ADDR2BANK(addr) == 2) {
2003                 stat = DRX_STS_INVALID_ARG;
2004         } else {
2005                 u32 start_timer = 0;
2006                 u32 current_timer = 0;
2007                 u32 delta_timer = 0;
2008                 u16 tr_status = 0;
2009                 const dr_xaddr_t write_bit = ((dr_xaddr_t) 1) << 16;
2010
2011                 /* Force write bit */
2012                 addr |= write_bit;
2013                 start_timer = drxbsp_hst_clock();
2014                 do {
2015                         /* RMW to aud TR IF until request is granted or timeout */
2016                         stat = drxj_dap_read_modify_write_reg16(dev_addr,
2017                                                              addr,
2018                                                              SIO_HI_RA_RAM_S0_RMWBUF__A,
2019                                                              data, &tr_status);
2020                         if (stat != DRX_STS_OK) {
2021                                 break;
2022                         };
2023
2024                         current_timer = drxbsp_hst_clock();
2025                         delta_timer = current_timer - start_timer;
2026                         if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) {
2027                                 stat = DRX_STS_ERROR;
2028                                 break;
2029                         };
2030
2031                 } while (((tr_status & AUD_TOP_TR_CTR_FIFO_LOCK__M) ==
2032                           AUD_TOP_TR_CTR_FIFO_LOCK_LOCKED) ||
2033                          ((tr_status & AUD_TOP_TR_CTR_FIFO_FULL__M) ==
2034                           AUD_TOP_TR_CTR_FIFO_FULL_FULL));
2035
2036         }                       /* if ( DRXDAP_FASI_ADDR2BANK(addr)!=2 ) */
2037
2038         return stat;
2039 }
2040
2041 /*============================================================================*/
2042
2043 static int drxj_dap_write_reg16(struct i2c_device_addr *dev_addr,
2044                                        dr_xaddr_t addr,
2045                                        u16 data, dr_xflags_t flags)
2046 {
2047         int stat = DRX_STS_ERROR;
2048
2049         /* Check param */
2050         if (dev_addr == NULL) {
2051                 return DRX_STS_INVALID_ARG;
2052         }
2053
2054         if (is_handled_by_aud_tr_if(addr)) {
2055                 stat = drxj_dap_write_aud_reg16(dev_addr, addr, data);
2056         } else {
2057                 stat = drx_dap_fasi_funct_g.write_reg16func(dev_addr,
2058                                                         addr, data, flags);
2059         }
2060
2061         return stat;
2062 }
2063
2064 /*============================================================================*/
2065
2066 static int drxj_dap_write_reg32(struct i2c_device_addr *dev_addr,
2067                                        dr_xaddr_t addr,
2068                                        u32 data, dr_xflags_t flags)
2069 {
2070         return drx_dap_fasi_funct_g.write_reg32func(dev_addr, addr, data, flags);
2071 }
2072
2073 /*============================================================================*/
2074
2075 /* Free data ram in SIO HI */
2076 #define SIO_HI_RA_RAM_USR_BEGIN__A 0x420040
2077 #define SIO_HI_RA_RAM_USR_END__A   0x420060
2078
2079 #define DRXJ_HI_ATOMIC_BUF_START (SIO_HI_RA_RAM_USR_BEGIN__A)
2080 #define DRXJ_HI_ATOMIC_BUF_END   (SIO_HI_RA_RAM_USR_BEGIN__A + 7)
2081 #define DRXJ_HI_ATOMIC_READ      SIO_HI_RA_RAM_PAR_3_ACP_RW_READ
2082 #define DRXJ_HI_ATOMIC_WRITE     SIO_HI_RA_RAM_PAR_3_ACP_RW_WRITE
2083
2084 /**
2085 * \fn int drxj_dap_atomic_read_write_block()
2086 * \brief Basic access routine for atomic read or write access
2087 * \param dev_addr  pointer to i2c dev address
2088 * \param addr     destination/source address
2089 * \param datasize size of data buffer in bytes
2090 * \param data     pointer to data buffer
2091 * \return int
2092 * \retval DRX_STS_OK Succes
2093 * \retval DRX_STS_ERROR Timeout, I2C error, illegal bank
2094 *
2095 */
2096 static
2097 int drxj_dap_atomic_read_write_block(struct i2c_device_addr *dev_addr,
2098                                           dr_xaddr_t addr,
2099                                           u16 datasize,
2100                                           u8 *data, bool read_flag)
2101 {
2102         drxj_hi_cmd_t hi_cmd;
2103
2104         u16 word;
2105         u16 dummy = 0;
2106         u16 i = 0;
2107
2108         /* Parameter check */
2109         if ((data == NULL) ||
2110             (dev_addr == NULL) || ((datasize % 2) != 0) || ((datasize / 2) > 8)
2111             ) {
2112                 return (DRX_STS_INVALID_ARG);
2113         }
2114
2115         /* Set up HI parameters to read or write n bytes */
2116         hi_cmd.cmd = SIO_HI_RA_RAM_CMD_ATOMIC_COPY;
2117         hi_cmd.param1 =
2118             (u16) ((DRXDAP_FASI_ADDR2BLOCK(DRXJ_HI_ATOMIC_BUF_START) << 6) +
2119                      DRXDAP_FASI_ADDR2BANK(DRXJ_HI_ATOMIC_BUF_START));
2120         hi_cmd.param2 =
2121             (u16) DRXDAP_FASI_ADDR2OFFSET(DRXJ_HI_ATOMIC_BUF_START);
2122         hi_cmd.param3 = (u16) ((datasize / 2) - 1);
2123         if (read_flag == false) {
2124                 hi_cmd.param3 |= DRXJ_HI_ATOMIC_WRITE;
2125         } else {
2126                 hi_cmd.param3 |= DRXJ_HI_ATOMIC_READ;
2127         }
2128         hi_cmd.param4 = (u16) ((DRXDAP_FASI_ADDR2BLOCK(addr) << 6) +
2129                                 DRXDAP_FASI_ADDR2BANK(addr));
2130         hi_cmd.param5 = (u16) DRXDAP_FASI_ADDR2OFFSET(addr);
2131
2132         if (read_flag == false) {
2133                 /* write data to buffer */
2134                 for (i = 0; i < (datasize / 2); i++) {
2135
2136                         word = ((u16) data[2 * i]);
2137                         word += (((u16) data[(2 * i) + 1]) << 8);
2138                         drxj_dap_write_reg16(dev_addr,
2139                                             (DRXJ_HI_ATOMIC_BUF_START + i),
2140                                             word, 0);
2141                 }
2142         }
2143
2144         CHK_ERROR(hi_command(dev_addr, &hi_cmd, &dummy));
2145
2146         if (read_flag == true) {
2147                 /* read data from buffer */
2148                 for (i = 0; i < (datasize / 2); i++) {
2149                         drxj_dap_read_reg16(dev_addr,
2150                                            (DRXJ_HI_ATOMIC_BUF_START + i),
2151                                            &word, 0);
2152                         data[2 * i] = (u8) (word & 0xFF);
2153                         data[(2 * i) + 1] = (u8) (word >> 8);
2154                 }
2155         }
2156
2157         return DRX_STS_OK;
2158
2159 rw_error:
2160         return (DRX_STS_ERROR);
2161
2162 }
2163
2164 /*============================================================================*/
2165
2166 /**
2167 * \fn int drxj_dap_atomic_read_reg32()
2168 * \brief Atomic read of 32 bits words
2169 */
2170 static
2171 int drxj_dap_atomic_read_reg32(struct i2c_device_addr *dev_addr,
2172                                      dr_xaddr_t addr,
2173                                      u32 *data, dr_xflags_t flags)
2174 {
2175         u8 buf[sizeof(*data)];
2176         int rc = DRX_STS_ERROR;
2177         u32 word = 0;
2178
2179         if (!data) {
2180                 return DRX_STS_INVALID_ARG;
2181         }
2182
2183         rc = drxj_dap_atomic_read_write_block(dev_addr, addr,
2184                                            sizeof(*data), buf, true);
2185
2186         word = (u32) buf[3];
2187         word <<= 8;
2188         word |= (u32) buf[2];
2189         word <<= 8;
2190         word |= (u32) buf[1];
2191         word <<= 8;
2192         word |= (u32) buf[0];
2193
2194         *data = word;
2195
2196         return rc;
2197 }
2198
2199 /*============================================================================*/
2200
2201 /*============================================================================*/
2202 /*==                        END DRXJ DAP FUNCTIONS                          ==*/
2203 /*============================================================================*/
2204
2205 /*============================================================================*/
2206 /*============================================================================*/
2207 /*==                      HOST INTERFACE FUNCTIONS                          ==*/
2208 /*============================================================================*/
2209 /*============================================================================*/
2210
2211 /**
2212 * \fn int hi_cfg_command()
2213 * \brief Configure HI with settings stored in the demod structure.
2214 * \param demod Demodulator.
2215 * \return int.
2216 *
2217 * This routine was created because to much orthogonal settings have
2218 * been put into one HI API function (configure). Especially the I2C bridge
2219 * enable/disable should not need re-configuration of the HI.
2220 *
2221 */
2222 static int hi_cfg_command(const pdrx_demod_instance_t demod)
2223 {
2224         pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
2225         drxj_hi_cmd_t hi_cmd;
2226         u16 result = 0;
2227
2228         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
2229
2230         hi_cmd.cmd = SIO_HI_RA_RAM_CMD_CONFIG;
2231         hi_cmd.param1 = SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY;
2232         hi_cmd.param2 = ext_attr->hi_cfg_timing_div;
2233         hi_cmd.param3 = ext_attr->hi_cfg_bridge_delay;
2234         hi_cmd.param4 = ext_attr->hi_cfg_wake_up_key;
2235         hi_cmd.param5 = ext_attr->hi_cfg_ctrl;
2236         hi_cmd.param6 = ext_attr->hi_cfg_transmit;
2237
2238         CHK_ERROR(hi_command(demod->my_i2c_dev_addr, &hi_cmd, &result));
2239
2240         /* Reset power down flag (set one call only) */
2241         ext_attr->hi_cfg_ctrl &= (~(SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ));
2242
2243         return (DRX_STS_OK);
2244
2245 rw_error:
2246         return (DRX_STS_ERROR);
2247 }
2248
2249 /**
2250 * \fn int hi_command()
2251 * \brief Configure HI with settings stored in the demod structure.
2252 * \param dev_addr I2C address.
2253 * \param cmd HI command.
2254 * \param result HI command result.
2255 * \return int.
2256 *
2257 * Sends command to HI
2258 *
2259 */
2260 static int
2261 hi_command(struct i2c_device_addr *dev_addr, const pdrxj_hi_cmd_t cmd, u16 *result)
2262 {
2263         u16 wait_cmd = 0;
2264         u16 nr_retries = 0;
2265         bool powerdown_cmd = false;
2266
2267         /* Write parameters */
2268         switch (cmd->cmd) {
2269
2270         case SIO_HI_RA_RAM_CMD_CONFIG:
2271         case SIO_HI_RA_RAM_CMD_ATOMIC_COPY:
2272                 WR16(dev_addr, SIO_HI_RA_RAM_PAR_6__A, cmd->param6);
2273                 WR16(dev_addr, SIO_HI_RA_RAM_PAR_5__A, cmd->param5);
2274                 WR16(dev_addr, SIO_HI_RA_RAM_PAR_4__A, cmd->param4);
2275                 WR16(dev_addr, SIO_HI_RA_RAM_PAR_3__A, cmd->param3);
2276                 /* fallthrough */
2277         case SIO_HI_RA_RAM_CMD_BRDCTRL:
2278                 WR16(dev_addr, SIO_HI_RA_RAM_PAR_2__A, cmd->param2);
2279                 WR16(dev_addr, SIO_HI_RA_RAM_PAR_1__A, cmd->param1);
2280                 /* fallthrough */
2281         case SIO_HI_RA_RAM_CMD_NULL:
2282                 /* No parameters */
2283                 break;
2284
2285         default:
2286                 return (DRX_STS_INVALID_ARG);
2287                 break;
2288         }
2289
2290         /* Write command */
2291         WR16(dev_addr, SIO_HI_RA_RAM_CMD__A, cmd->cmd);
2292
2293         if ((cmd->cmd) == SIO_HI_RA_RAM_CMD_RESET) {
2294                 /* Allow for HI to reset */
2295                 drxbsp_hst_sleep(1);
2296         }
2297
2298         /* Detect power down to ommit reading result */
2299         powerdown_cmd = (bool) ((cmd->cmd == SIO_HI_RA_RAM_CMD_CONFIG) &&
2300                                   (((cmd->
2301                                      param5) & SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M)
2302                                    == SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ));
2303         if (powerdown_cmd == false) {
2304                 /* Wait until command rdy */
2305                 do {
2306                         nr_retries++;
2307                         if (nr_retries > DRXJ_MAX_RETRIES) {
2308                                 goto rw_error;
2309                         };
2310
2311                         RR16(dev_addr, SIO_HI_RA_RAM_CMD__A, &wait_cmd);
2312                 } while (wait_cmd != 0);
2313
2314                 /* Read result */
2315                 RR16(dev_addr, SIO_HI_RA_RAM_RES__A, result);
2316
2317         }
2318         /* if ( powerdown_cmd == true ) */
2319         return (DRX_STS_OK);
2320 rw_error:
2321         return (DRX_STS_ERROR);
2322 }
2323
2324 /**
2325 * \fn int init_hi( const pdrx_demod_instance_t demod )
2326 * \brief Initialise and configurate HI.
2327 * \param demod pointer to demod data.
2328 * \return int Return status.
2329 * \retval DRX_STS_OK Success.
2330 * \retval DRX_STS_ERROR Failure.
2331 *
2332 * Needs to know Psys (System Clock period) and Posc (Osc Clock period)
2333 * Need to store configuration in driver because of the way I2C
2334 * bridging is controlled.
2335 *
2336 */
2337 static int init_hi(const pdrx_demod_instance_t demod)
2338 {
2339         pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
2340         pdrx_common_attr_t common_attr = (pdrx_common_attr_t) (NULL);
2341         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) (NULL);
2342
2343         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
2344         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
2345         dev_addr = demod->my_i2c_dev_addr;
2346
2347         /* PATCH for bug 5003, HI ucode v3.1.0 */
2348         WR16(dev_addr, 0x4301D7, 0x801);
2349
2350         /* Timing div, 250ns/Psys */
2351         /* Timing div, = ( delay (nano seconds) * sysclk (kHz) )/ 1000 */
2352         ext_attr->hi_cfg_timing_div =
2353             (u16) ((common_attr->sys_clock_freq / 1000) * HI_I2C_DELAY) / 1000;
2354         /* Clipping */
2355         if ((ext_attr->hi_cfg_timing_div) > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M) {
2356                 ext_attr->hi_cfg_timing_div = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M;
2357         }
2358         /* Bridge delay, uses oscilator clock */
2359         /* Delay = ( delay (nano seconds) * oscclk (kHz) )/ 1000 */
2360         /* SDA brdige delay */
2361         ext_attr->hi_cfg_bridge_delay =
2362             (u16) ((common_attr->osc_clock_freq / 1000) * HI_I2C_BRIDGE_DELAY) /
2363             1000;
2364         /* Clipping */
2365         if ((ext_attr->hi_cfg_bridge_delay) > SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M) {
2366                 ext_attr->hi_cfg_bridge_delay = SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M;
2367         }
2368         /* SCL bridge delay, same as SDA for now */
2369         ext_attr->hi_cfg_bridge_delay += ((ext_attr->hi_cfg_bridge_delay) <<
2370                                       SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B);
2371         /* Wakeup key, setting the read flag (as suggest in the documentation) does
2372            not always result into a working solution (barebones worked VI2C failed).
2373            Not setting the bit works in all cases . */
2374         ext_attr->hi_cfg_wake_up_key = DRXJ_WAKE_UP_KEY;
2375         /* port/bridge/power down ctrl */
2376         ext_attr->hi_cfg_ctrl = (SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE);
2377         /* transit mode time out delay and watch dog divider */
2378         ext_attr->hi_cfg_transmit = SIO_HI_RA_RAM_PAR_6__PRE;
2379
2380         CHK_ERROR(hi_cfg_command(demod));
2381
2382         return (DRX_STS_OK);
2383
2384 rw_error:
2385         return (DRX_STS_ERROR);
2386 }
2387
2388 /*============================================================================*/
2389 /*==                   END HOST INTERFACE FUNCTIONS                         ==*/
2390 /*============================================================================*/
2391
2392 /*============================================================================*/
2393 /*============================================================================*/
2394 /*==                        AUXILIARY FUNCTIONS                             ==*/
2395 /*============================================================================*/
2396 /*============================================================================*/
2397
2398 /**
2399 * \fn int get_device_capabilities()
2400 * \brief Get and store device capabilities.
2401 * \param demod  Pointer to demodulator instance.
2402 * \return int.
2403 * \return DRX_STS_OK    Success
2404 * \retval DRX_STS_ERROR Failure
2405 *
2406 * Depending on pulldowns on MDx pins the following internals are set:
2407 *  * common_attr->osc_clock_freq
2408 *  * ext_attr->has_lna
2409 *  * ext_attr->has_ntsc
2410 *  * ext_attr->has_btsc
2411 *  * ext_attr->has_oob
2412 *
2413 */
2414 static int get_device_capabilities(pdrx_demod_instance_t demod)
2415 {
2416         pdrx_common_attr_t common_attr = (pdrx_common_attr_t) (NULL);
2417         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
2418         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) (NULL);
2419         u16 sio_pdr_ohw_cfg = 0;
2420         u32 sio_top_jtagid_lo = 0;
2421         u16 bid = 0;
2422
2423         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
2424         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
2425         dev_addr = demod->my_i2c_dev_addr;
2426
2427         WR16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
2428         RR16(dev_addr, SIO_PDR_OHW_CFG__A, &sio_pdr_ohw_cfg);
2429         WR16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY__PRE);
2430
2431         switch ((sio_pdr_ohw_cfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) {
2432         case 0:
2433                 /* ignore (bypass ?) */
2434                 break;
2435         case 1:
2436                 /* 27 MHz */
2437                 common_attr->osc_clock_freq = 27000;
2438                 break;
2439         case 2:
2440                 /* 20.25 MHz */
2441                 common_attr->osc_clock_freq = 20250;
2442                 break;
2443         case 3:
2444                 /* 4 MHz */
2445                 common_attr->osc_clock_freq = 4000;
2446                 break;
2447         default:
2448                 return (DRX_STS_ERROR);
2449         }
2450
2451         /*
2452            Determine device capabilities
2453            Based on pinning v47
2454          */
2455         RR32(dev_addr, SIO_TOP_JTAGID_LO__A, &sio_top_jtagid_lo);
2456         ext_attr->mfx = (u8) ((sio_top_jtagid_lo >> 29) & 0xF);
2457
2458         switch ((sio_top_jtagid_lo >> 12) & 0xFF) {
2459         case 0x31:
2460                 WR16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
2461                 RR16(dev_addr, SIO_PDR_UIO_IN_HI__A, &bid);
2462                 bid = (bid >> 10) & 0xf;
2463                 WR16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY__PRE);
2464
2465                 ext_attr->has_lna = true;
2466                 ext_attr->has_ntsc = false;
2467                 ext_attr->has_btsc = false;
2468                 ext_attr->has_oob = false;
2469                 ext_attr->has_smatx = true;
2470                 ext_attr->has_smarx = false;
2471                 ext_attr->has_gpio = false;
2472                 ext_attr->has_irqn = false;
2473                 break;
2474         case 0x33:
2475                 ext_attr->has_lna = false;
2476                 ext_attr->has_ntsc = false;
2477                 ext_attr->has_btsc = false;
2478                 ext_attr->has_oob = false;
2479                 ext_attr->has_smatx = true;
2480                 ext_attr->has_smarx = false;
2481                 ext_attr->has_gpio = false;
2482                 ext_attr->has_irqn = false;
2483                 break;
2484         case 0x45:
2485                 ext_attr->has_lna = true;
2486                 ext_attr->has_ntsc = true;
2487                 ext_attr->has_btsc = false;
2488                 ext_attr->has_oob = false;
2489                 ext_attr->has_smatx = true;
2490                 ext_attr->has_smarx = true;
2491                 ext_attr->has_gpio = true;
2492                 ext_attr->has_irqn = false;
2493                 break;
2494         case 0x46:
2495                 ext_attr->has_lna = false;
2496                 ext_attr->has_ntsc = true;
2497                 ext_attr->has_btsc = false;
2498                 ext_attr->has_oob = false;
2499                 ext_attr->has_smatx = true;
2500                 ext_attr->has_smarx = true;
2501                 ext_attr->has_gpio = true;
2502                 ext_attr->has_irqn = false;
2503                 break;
2504         case 0x41:
2505                 ext_attr->has_lna = true;
2506                 ext_attr->has_ntsc = true;
2507                 ext_attr->has_btsc = true;
2508                 ext_attr->has_oob = false;
2509                 ext_attr->has_smatx = true;
2510                 ext_attr->has_smarx = true;
2511                 ext_attr->has_gpio = true;
2512                 ext_attr->has_irqn = false;
2513                 break;
2514         case 0x43:
2515                 ext_attr->has_lna = false;
2516                 ext_attr->has_ntsc = true;
2517                 ext_attr->has_btsc = true;
2518                 ext_attr->has_oob = false;
2519                 ext_attr->has_smatx = true;
2520                 ext_attr->has_smarx = true;
2521                 ext_attr->has_gpio = true;
2522                 ext_attr->has_irqn = false;
2523                 break;
2524         case 0x32:
2525                 ext_attr->has_lna = true;
2526                 ext_attr->has_ntsc = false;
2527                 ext_attr->has_btsc = false;
2528                 ext_attr->has_oob = true;
2529                 ext_attr->has_smatx = true;
2530                 ext_attr->has_smarx = true;
2531                 ext_attr->has_gpio = true;
2532                 ext_attr->has_irqn = true;
2533                 break;
2534         case 0x34:
2535                 ext_attr->has_lna = false;
2536                 ext_attr->has_ntsc = true;
2537                 ext_attr->has_btsc = true;
2538                 ext_attr->has_oob = true;
2539                 ext_attr->has_smatx = true;
2540                 ext_attr->has_smarx = true;
2541                 ext_attr->has_gpio = true;
2542                 ext_attr->has_irqn = true;
2543                 break;
2544         case 0x42:
2545                 ext_attr->has_lna = true;
2546                 ext_attr->has_ntsc = true;
2547                 ext_attr->has_btsc = true;
2548                 ext_attr->has_oob = true;
2549                 ext_attr->has_smatx = true;
2550                 ext_attr->has_smarx = true;
2551                 ext_attr->has_gpio = true;
2552                 ext_attr->has_irqn = true;
2553                 break;
2554         case 0x44:
2555                 ext_attr->has_lna = false;
2556                 ext_attr->has_ntsc = true;
2557                 ext_attr->has_btsc = true;
2558                 ext_attr->has_oob = true;
2559                 ext_attr->has_smatx = true;
2560                 ext_attr->has_smarx = true;
2561                 ext_attr->has_gpio = true;
2562                 ext_attr->has_irqn = true;
2563                 break;
2564         default:
2565                 /* Unknown device variant */
2566                 return (DRX_STS_ERROR);
2567                 break;
2568         }
2569
2570         return (DRX_STS_OK);
2571 rw_error:
2572         return (DRX_STS_ERROR);
2573 }
2574
2575 /**
2576 * \fn int power_up_device()
2577 * \brief Power up device.
2578 * \param demod  Pointer to demodulator instance.
2579 * \return int.
2580 * \return DRX_STS_OK    Success
2581 * \retval DRX_STS_ERROR Failure, I2C or max retries reached
2582 *
2583 */
2584
2585 #ifndef DRXJ_MAX_RETRIES_POWERUP
2586 #define DRXJ_MAX_RETRIES_POWERUP 10
2587 #endif
2588
2589 static int power_up_device(pdrx_demod_instance_t demod)
2590 {
2591         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) (NULL);
2592         u8 data = 0;
2593         u16 retry_count = 0;
2594         struct i2c_device_addr wake_up_addr;
2595
2596         dev_addr = demod->my_i2c_dev_addr;
2597         wake_up_addr.i2c_addr = DRXJ_WAKE_UP_KEY;
2598         wake_up_addr.i2c_dev_id = dev_addr->i2c_dev_id;
2599         wake_up_addr.user_data = dev_addr->user_data;
2600         /* CHK_ERROR macro not used, I2C access may fail in this case: no ack
2601            dummy write must be used to wake uop device, dummy read must be used to
2602            reset HI state machine (avoiding actual writes) */
2603         do {
2604                 data = 0;
2605                 drxbsp_i2c_write_read(&wake_up_addr, 1, &data,
2606                                      (struct i2c_device_addr *) (NULL), 0,
2607                                      (u8 *) (NULL));
2608                 drxbsp_hst_sleep(10);
2609                 retry_count++;
2610         } while ((drxbsp_i2c_write_read
2611                   ((struct i2c_device_addr *) (NULL), 0, (u8 *) (NULL), dev_addr, 1,
2612                    &data)
2613                   != DRX_STS_OK) && (retry_count < DRXJ_MAX_RETRIES_POWERUP));
2614
2615         /* Need some recovery time .... */
2616         drxbsp_hst_sleep(10);
2617
2618         if (retry_count == DRXJ_MAX_RETRIES_POWERUP) {
2619                 return (DRX_STS_ERROR);
2620         }
2621
2622         return (DRX_STS_OK);
2623 }
2624
2625 /*----------------------------------------------------------------------------*/
2626 /* MPEG Output Configuration Functions - begin                                */
2627 /*----------------------------------------------------------------------------*/
2628 /**
2629 * \fn int ctrl_set_cfg_mpeg_output()
2630 * \brief Set MPEG output configuration of the device.
2631 * \param devmod  Pointer to demodulator instance.
2632 * \param cfg_data Pointer to mpeg output configuaration.
2633 * \return int.
2634 *
2635 *  Configure MPEG output parameters.
2636 *
2637 */
2638 static int
2639 ctrl_set_cfg_mpeg_output(pdrx_demod_instance_t demod, pdrx_cfg_mpeg_output_t cfg_data)
2640 {
2641         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) (NULL);
2642         pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
2643         pdrx_common_attr_t common_attr = (pdrx_common_attr_t) (NULL);
2644         u16 fec_oc_reg_mode = 0;
2645         u16 fec_oc_reg_ipr_mode = 0;
2646         u16 fec_oc_reg_ipr_invert = 0;
2647         u32 max_bit_rate = 0;
2648         u32 rcn_rate = 0;
2649         u32 nr_bits = 0;
2650         u16 sio_pdr_md_cfg = 0;
2651         /* data mask for the output data byte */
2652         u16 invert_data_mask =
2653             FEC_OC_IPR_INVERT_MD7__M | FEC_OC_IPR_INVERT_MD6__M |
2654             FEC_OC_IPR_INVERT_MD5__M | FEC_OC_IPR_INVERT_MD4__M |
2655             FEC_OC_IPR_INVERT_MD3__M | FEC_OC_IPR_INVERT_MD2__M |
2656             FEC_OC_IPR_INVERT_MD1__M | FEC_OC_IPR_INVERT_MD0__M;
2657         /* check arguments */
2658         if ((demod == NULL) || (cfg_data == NULL)) {
2659                 return (DRX_STS_INVALID_ARG);
2660         }
2661
2662         dev_addr = demod->my_i2c_dev_addr;
2663         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
2664         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
2665
2666         if (cfg_data->enable_mpeg_output == true) {
2667                 /* quick and dirty patch to set MPEG incase current std is not
2668                    producing MPEG */
2669                 switch (ext_attr->standard) {
2670                 case DRX_STANDARD_8VSB:
2671                 case DRX_STANDARD_ITU_A:
2672                 case DRX_STANDARD_ITU_B:
2673                 case DRX_STANDARD_ITU_C:
2674                         break;
2675                 default:
2676                         /* not an MPEG producing std, just store MPEG cfg */
2677                         common_attr->mpeg_cfg.enable_mpeg_output =
2678                             cfg_data->enable_mpeg_output;
2679                         common_attr->mpeg_cfg.insert_rs_byte =
2680                             cfg_data->insert_rs_byte;
2681                         common_attr->mpeg_cfg.enable_parallel =
2682                             cfg_data->enable_parallel;
2683                         common_attr->mpeg_cfg.invert_data = cfg_data->invert_data;
2684                         common_attr->mpeg_cfg.invert_err = cfg_data->invert_err;
2685                         common_attr->mpeg_cfg.invert_str = cfg_data->invert_str;
2686                         common_attr->mpeg_cfg.invert_val = cfg_data->invert_val;
2687                         common_attr->mpeg_cfg.invert_clk = cfg_data->invert_clk;
2688                         common_attr->mpeg_cfg.static_clk = cfg_data->static_clk;
2689                         common_attr->mpeg_cfg.bitrate = cfg_data->bitrate;
2690                         return (DRX_STS_OK);
2691                 }
2692
2693                 WR16(dev_addr, FEC_OC_OCR_INVERT__A, 0);
2694                 switch (ext_attr->standard) {
2695                 case DRX_STANDARD_8VSB:
2696                         WR16(dev_addr, FEC_OC_FCT_USAGE__A, 7); /* 2048 bytes fifo ram */
2697                         WR16(dev_addr, FEC_OC_TMD_CTL_UPD_RATE__A, 10);
2698                         WR16(dev_addr, FEC_OC_TMD_INT_UPD_RATE__A, 10);
2699                         WR16(dev_addr, FEC_OC_AVR_PARM_A__A, 5);
2700                         WR16(dev_addr, FEC_OC_AVR_PARM_B__A, 7);
2701                         WR16(dev_addr, FEC_OC_RCN_GAIN__A, 10);
2702                         /* Low Water Mark for synchronization  */
2703                         WR16(dev_addr, FEC_OC_SNC_LWM__A, 3);
2704                         /* High Water Mark for synchronization */
2705                         WR16(dev_addr, FEC_OC_SNC_HWM__A, 5);
2706                         break;
2707                 case DRX_STANDARD_ITU_A:
2708                 case DRX_STANDARD_ITU_C:
2709                         switch (ext_attr->constellation) {
2710                         case DRX_CONSTELLATION_QAM256:
2711                                 nr_bits = 8;
2712                                 break;
2713                         case DRX_CONSTELLATION_QAM128:
2714                                 nr_bits = 7;
2715                                 break;
2716                         case DRX_CONSTELLATION_QAM64:
2717                                 nr_bits = 6;
2718                                 break;
2719                         case DRX_CONSTELLATION_QAM32:
2720                                 nr_bits = 5;
2721                                 break;
2722                         case DRX_CONSTELLATION_QAM16:
2723                                 nr_bits = 4;
2724                                 break;
2725                         default:
2726                                 return (DRX_STS_ERROR);
2727                         }       /* ext_attr->constellation */
2728                         /* max_bit_rate = symbol_rate * nr_bits * coef */
2729                         /* coef = 188/204                          */
2730                         max_bit_rate =
2731                             (ext_attr->curr_symbol_rate / 8) * nr_bits * 188;
2732                         /* pass through b/c Annex A/c need following settings */
2733                 case DRX_STANDARD_ITU_B:
2734                         WR16(dev_addr, FEC_OC_FCT_USAGE__A,
2735                              FEC_OC_FCT_USAGE__PRE);
2736                         WR16(dev_addr, FEC_OC_TMD_CTL_UPD_RATE__A,
2737                              FEC_OC_TMD_CTL_UPD_RATE__PRE);
2738                         WR16(dev_addr, FEC_OC_TMD_INT_UPD_RATE__A, 5);
2739                         WR16(dev_addr, FEC_OC_AVR_PARM_A__A,
2740                              FEC_OC_AVR_PARM_A__PRE);
2741                         WR16(dev_addr, FEC_OC_AVR_PARM_B__A,
2742                              FEC_OC_AVR_PARM_B__PRE);
2743                         if (cfg_data->static_clk == true) {
2744                                 WR16(dev_addr, FEC_OC_RCN_GAIN__A, 0xD);
2745                         } else {
2746                                 WR16(dev_addr, FEC_OC_RCN_GAIN__A,
2747                                      FEC_OC_RCN_GAIN__PRE);
2748                         }
2749                         WR16(dev_addr, FEC_OC_SNC_LWM__A, 2);
2750                         WR16(dev_addr, FEC_OC_SNC_HWM__A, 12);
2751                         break;
2752                 default:
2753                         break;
2754                 }               /* swtich (standard) */
2755
2756                 /* Check insertion of the Reed-Solomon parity bytes */
2757                 RR16(dev_addr, FEC_OC_MODE__A, &fec_oc_reg_mode);
2758                 RR16(dev_addr, FEC_OC_IPR_MODE__A, &fec_oc_reg_ipr_mode);
2759                 if (cfg_data->insert_rs_byte == true) {
2760                         /* enable parity symbol forward */
2761                         fec_oc_reg_mode |= FEC_OC_MODE_PARITY__M;
2762                         /* MVAL disable during parity bytes */
2763                         fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M;
2764                         switch (ext_attr->standard) {
2765                         case DRX_STANDARD_8VSB:
2766                                 rcn_rate = 0x004854D3;
2767                                 break;
2768                         case DRX_STANDARD_ITU_B:
2769                                 fec_oc_reg_mode |= FEC_OC_MODE_TRANSPARENT__M;
2770                                 switch (ext_attr->constellation) {
2771                                 case DRX_CONSTELLATION_QAM256:
2772                                         rcn_rate = 0x008945E7;
2773                                         break;
2774                                 case DRX_CONSTELLATION_QAM64:
2775                                         rcn_rate = 0x005F64D4;
2776                                         break;
2777                                 default:
2778                                         return (DRX_STS_ERROR);
2779                                 }
2780                                 break;
2781                         case DRX_STANDARD_ITU_A:
2782                         case DRX_STANDARD_ITU_C:
2783                                 /* insert_rs_byte = true -> coef = 188/188 -> 1, RS bits are in MPEG output */
2784                                 rcn_rate =
2785                                     (frac28
2786                                      (max_bit_rate,
2787                                       (u32) (common_attr->sys_clock_freq / 8))) /
2788                                     188;
2789                                 break;
2790                         default:
2791                                 return (DRX_STS_ERROR);
2792                         }       /* ext_attr->standard */
2793                 } else {        /* insert_rs_byte == false */
2794
2795                         /* disable parity symbol forward */
2796                         fec_oc_reg_mode &= (~FEC_OC_MODE_PARITY__M);
2797                         /* MVAL enable during parity bytes */
2798                         fec_oc_reg_ipr_mode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M);
2799                         switch (ext_attr->standard) {
2800                         case DRX_STANDARD_8VSB:
2801                                 rcn_rate = 0x0041605C;
2802                                 break;
2803                         case DRX_STANDARD_ITU_B:
2804                                 fec_oc_reg_mode &= (~FEC_OC_MODE_TRANSPARENT__M);
2805                                 switch (ext_attr->constellation) {
2806                                 case DRX_CONSTELLATION_QAM256:
2807                                         rcn_rate = 0x0082D6A0;
2808                                         break;
2809                                 case DRX_CONSTELLATION_QAM64:
2810                                         rcn_rate = 0x005AEC1A;
2811                                         break;
2812                                 default:
2813                                         return (DRX_STS_ERROR);
2814                                 }
2815                                 break;
2816                         case DRX_STANDARD_ITU_A:
2817                         case DRX_STANDARD_ITU_C:
2818                                 /* insert_rs_byte = false -> coef = 188/204, RS bits not in MPEG output */
2819                                 rcn_rate =
2820                                     (frac28
2821                                      (max_bit_rate,
2822                                       (u32) (common_attr->sys_clock_freq / 8))) /
2823                                     204;
2824                                 break;
2825                         default:
2826                                 return (DRX_STS_ERROR);
2827                         }       /* ext_attr->standard */
2828                 }
2829
2830                 if (cfg_data->enable_parallel == true) {        /* MPEG data output is paralel -> clear ipr_mode[0] */
2831                         fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M));
2832                 } else {        /* MPEG data output is serial -> set ipr_mode[0] */
2833                         fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M;
2834                 }
2835
2836                 /* Control slective inversion of output bits */
2837                 if (cfg_data->invert_data == true) {
2838                         fec_oc_reg_ipr_invert |= invert_data_mask;
2839                 } else {
2840                         fec_oc_reg_ipr_invert &= (~(invert_data_mask));
2841                 }
2842
2843                 if (cfg_data->invert_err == true) {
2844                         fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MERR__M;
2845                 } else {
2846                         fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MERR__M));
2847                 }
2848
2849                 if (cfg_data->invert_str == true) {
2850                         fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MSTRT__M;
2851                 } else {
2852                         fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MSTRT__M));
2853                 }
2854
2855                 if (cfg_data->invert_val == true) {
2856                         fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MVAL__M;
2857                 } else {
2858                         fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MVAL__M));
2859                 }
2860
2861                 if (cfg_data->invert_clk == true) {
2862                         fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MCLK__M;
2863                 } else {
2864                         fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MCLK__M));
2865                 }
2866
2867                 if (cfg_data->static_clk == true) {     /* Static mode */
2868                         u32 dto_rate = 0;
2869                         u32 bit_rate = 0;
2870                         u16 fec_oc_dto_burst_len = 0;
2871                         u16 fec_oc_dto_period = 0;
2872
2873                         fec_oc_dto_burst_len = FEC_OC_DTO_BURST_LEN__PRE;
2874
2875                         switch (ext_attr->standard) {
2876                         case DRX_STANDARD_8VSB:
2877                                 fec_oc_dto_period = 4;
2878                                 if (cfg_data->insert_rs_byte == true) {
2879                                         fec_oc_dto_burst_len = 208;
2880                                 }
2881                                 break;
2882                         case DRX_STANDARD_ITU_A:
2883                                 {
2884                                         u32 symbol_rate_th = 6400000;
2885                                         if (cfg_data->insert_rs_byte == true) {
2886                                                 fec_oc_dto_burst_len = 204;
2887                                                 symbol_rate_th = 5900000;
2888                                         }
2889                                         if (ext_attr->curr_symbol_rate >=
2890                                             symbol_rate_th) {
2891                                                 fec_oc_dto_period = 0;
2892                                         } else {
2893                                                 fec_oc_dto_period = 1;
2894                                         }
2895                                 }
2896                                 break;
2897                         case DRX_STANDARD_ITU_B:
2898                                 fec_oc_dto_period = 1;
2899                                 if (cfg_data->insert_rs_byte == true) {
2900                                         fec_oc_dto_burst_len = 128;
2901                                 }
2902                                 break;
2903                         case DRX_STANDARD_ITU_C:
2904                                 fec_oc_dto_period = 1;
2905                                 if (cfg_data->insert_rs_byte == true) {
2906                                         fec_oc_dto_burst_len = 204;
2907                                 }
2908                                 break;
2909                         default:
2910                                 return (DRX_STS_ERROR);
2911                         }
2912                         bit_rate =
2913                             common_attr->sys_clock_freq * 1000 / (fec_oc_dto_period +
2914                                                                2);
2915                         dto_rate =
2916                             frac28(bit_rate, common_attr->sys_clock_freq * 1000);
2917                         dto_rate >>= 3;
2918                         WR16(dev_addr, FEC_OC_DTO_RATE_HI__A,
2919                              (u16) ((dto_rate >> 16) & FEC_OC_DTO_RATE_HI__M));
2920                         WR16(dev_addr, FEC_OC_DTO_RATE_LO__A,
2921                              (u16) (dto_rate & FEC_OC_DTO_RATE_LO_RATE_LO__M));
2922                         WR16(dev_addr, FEC_OC_DTO_MODE__A,
2923                              FEC_OC_DTO_MODE_DYNAMIC__M |
2924                              FEC_OC_DTO_MODE_OFFSET_ENABLE__M);
2925                         WR16(dev_addr, FEC_OC_FCT_MODE__A,
2926                              FEC_OC_FCT_MODE_RAT_ENA__M |
2927                              FEC_OC_FCT_MODE_VIRT_ENA__M);
2928                         WR16(dev_addr, FEC_OC_DTO_BURST_LEN__A,
2929                              fec_oc_dto_burst_len);
2930                         if (ext_attr->mpeg_output_clock_rate !=
2931                             DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO)
2932                                 fec_oc_dto_period =
2933                                     ext_attr->mpeg_output_clock_rate - 1;
2934                         WR16(dev_addr, FEC_OC_DTO_PERIOD__A, fec_oc_dto_period);
2935                 } else {        /* Dynamic mode */
2936
2937                         WR16(dev_addr, FEC_OC_DTO_MODE__A,
2938                              FEC_OC_DTO_MODE_DYNAMIC__M);
2939                         WR16(dev_addr, FEC_OC_FCT_MODE__A, 0);
2940                 }
2941
2942                 WR32(dev_addr, FEC_OC_RCN_CTL_RATE_LO__A, rcn_rate);
2943
2944                 /* Write appropriate registers with requested configuration */
2945                 WR16(dev_addr, FEC_OC_MODE__A, fec_oc_reg_mode);
2946                 WR16(dev_addr, FEC_OC_IPR_MODE__A, fec_oc_reg_ipr_mode);
2947                 WR16(dev_addr, FEC_OC_IPR_INVERT__A, fec_oc_reg_ipr_invert);
2948
2949                 /* enabling for both parallel and serial now */
2950                 /*  Write magic word to enable pdr reg write */
2951                 WR16(dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA);
2952                 /*  Set MPEG TS pads to outputmode */
2953                 WR16(dev_addr, SIO_PDR_MSTRT_CFG__A, 0x0013);
2954                 WR16(dev_addr, SIO_PDR_MERR_CFG__A, 0x0013);
2955                 WR16(dev_addr, SIO_PDR_MCLK_CFG__A,
2956                      MPEG_OUTPUT_CLK_DRIVE_STRENGTH << SIO_PDR_MCLK_CFG_DRIVE__B
2957                      | 0x03 << SIO_PDR_MCLK_CFG_MODE__B);
2958                 WR16(dev_addr, SIO_PDR_MVAL_CFG__A, 0x0013);
2959                 sio_pdr_md_cfg =
2960                     MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH <<
2961                     SIO_PDR_MD0_CFG_DRIVE__B | 0x03 << SIO_PDR_MD0_CFG_MODE__B;
2962                 WR16(dev_addr, SIO_PDR_MD0_CFG__A, sio_pdr_md_cfg);
2963                 if (cfg_data->enable_parallel == true) {        /* MPEG data output is paralel -> set MD1 to MD7 to output mode */
2964                         sio_pdr_md_cfg =
2965                             MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH <<
2966                             SIO_PDR_MD0_CFG_DRIVE__B | 0x03 <<
2967                             SIO_PDR_MD0_CFG_MODE__B;
2968                         WR16(dev_addr, SIO_PDR_MD0_CFG__A, sio_pdr_md_cfg);
2969                         WR16(dev_addr, SIO_PDR_MD1_CFG__A, sio_pdr_md_cfg);
2970                         WR16(dev_addr, SIO_PDR_MD2_CFG__A, sio_pdr_md_cfg);
2971                         WR16(dev_addr, SIO_PDR_MD3_CFG__A, sio_pdr_md_cfg);
2972                         WR16(dev_addr, SIO_PDR_MD4_CFG__A, sio_pdr_md_cfg);
2973                         WR16(dev_addr, SIO_PDR_MD5_CFG__A, sio_pdr_md_cfg);
2974                         WR16(dev_addr, SIO_PDR_MD6_CFG__A, sio_pdr_md_cfg);
2975                         WR16(dev_addr, SIO_PDR_MD7_CFG__A, sio_pdr_md_cfg);
2976                 } else {        /* MPEG data output is serial -> set MD1 to MD7 to tri-state */
2977                         WR16(dev_addr, SIO_PDR_MD1_CFG__A, 0x0000);
2978                         WR16(dev_addr, SIO_PDR_MD2_CFG__A, 0x0000);
2979                         WR16(dev_addr, SIO_PDR_MD3_CFG__A, 0x0000);
2980                         WR16(dev_addr, SIO_PDR_MD4_CFG__A, 0x0000);
2981                         WR16(dev_addr, SIO_PDR_MD5_CFG__A, 0x0000);
2982                         WR16(dev_addr, SIO_PDR_MD6_CFG__A, 0x0000);
2983                         WR16(dev_addr, SIO_PDR_MD7_CFG__A, 0x0000);
2984                 }
2985                 /*  Enable Monitor Bus output over MPEG pads and ctl input */
2986                 WR16(dev_addr, SIO_PDR_MON_CFG__A, 0x0000);
2987                 /*  Write nomagic word to enable pdr reg write */
2988                 WR16(dev_addr, SIO_TOP_COMM_KEY__A, 0x0000);
2989         } else {
2990                 /*  Write magic word to enable pdr reg write */
2991                 WR16(dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA);
2992                 /*  Set MPEG TS pads to inputmode */
2993                 WR16(dev_addr, SIO_PDR_MSTRT_CFG__A, 0x0000);
2994                 WR16(dev_addr, SIO_PDR_MERR_CFG__A, 0x0000);
2995                 WR16(dev_addr, SIO_PDR_MCLK_CFG__A, 0x0000);
2996                 WR16(dev_addr, SIO_PDR_MVAL_CFG__A, 0x0000);
2997                 WR16(dev_addr, SIO_PDR_MD0_CFG__A, 0x0000);
2998                 WR16(dev_addr, SIO_PDR_MD1_CFG__A, 0x0000);
2999                 WR16(dev_addr, SIO_PDR_MD2_CFG__A, 0x0000);
3000                 WR16(dev_addr, SIO_PDR_MD3_CFG__A, 0x0000);
3001                 WR16(dev_addr, SIO_PDR_MD4_CFG__A, 0x0000);
3002                 WR16(dev_addr, SIO_PDR_MD5_CFG__A, 0x0000);
3003                 WR16(dev_addr, SIO_PDR_MD6_CFG__A, 0x0000);
3004                 WR16(dev_addr, SIO_PDR_MD7_CFG__A, 0x0000);
3005                 /* Enable Monitor Bus output over MPEG pads and ctl input */
3006                 WR16(dev_addr, SIO_PDR_MON_CFG__A, 0x0000);
3007                 /* Write nomagic word to enable pdr reg write */
3008                 WR16(dev_addr, SIO_TOP_COMM_KEY__A, 0x0000);
3009         }
3010
3011         /* save values for restore after re-acquire */
3012         common_attr->mpeg_cfg.enable_mpeg_output = cfg_data->enable_mpeg_output;
3013         common_attr->mpeg_cfg.insert_rs_byte = cfg_data->insert_rs_byte;
3014         common_attr->mpeg_cfg.enable_parallel = cfg_data->enable_parallel;
3015         common_attr->mpeg_cfg.invert_data = cfg_data->invert_data;
3016         common_attr->mpeg_cfg.invert_err = cfg_data->invert_err;
3017         common_attr->mpeg_cfg.invert_str = cfg_data->invert_str;
3018         common_attr->mpeg_cfg.invert_val = cfg_data->invert_val;
3019         common_attr->mpeg_cfg.invert_clk = cfg_data->invert_clk;
3020         common_attr->mpeg_cfg.static_clk = cfg_data->static_clk;
3021         common_attr->mpeg_cfg.bitrate = cfg_data->bitrate;
3022
3023         return (DRX_STS_OK);
3024 rw_error:
3025         return (DRX_STS_ERROR);
3026 }
3027
3028 /*----------------------------------------------------------------------------*/
3029
3030 /**
3031 * \fn int ctrl_get_cfg_mpeg_output()
3032 * \brief Get MPEG output configuration of the device.
3033 * \param devmod  Pointer to demodulator instance.
3034 * \param cfg_data Pointer to MPEG output configuaration struct.
3035 * \return int.
3036 *
3037 *  Retrieve MPEG output configuartion.
3038 *
3039 */
3040 static int
3041 ctrl_get_cfg_mpeg_output(pdrx_demod_instance_t demod, pdrx_cfg_mpeg_output_t cfg_data)
3042 {
3043         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) (NULL);
3044         pdrx_common_attr_t common_attr = (pdrx_common_attr_t) (NULL);
3045         drx_lock_status_t lock_status = DRX_NOT_LOCKED;
3046         u32 rate_reg = 0;
3047         u32 data64hi = 0;
3048         u32 data64lo = 0;
3049
3050         if (cfg_data == NULL) {
3051                 return (DRX_STS_INVALID_ARG);
3052         }
3053         dev_addr = demod->my_i2c_dev_addr;
3054         common_attr = demod->my_common_attr;
3055
3056         cfg_data->enable_mpeg_output = common_attr->mpeg_cfg.enable_mpeg_output;
3057         cfg_data->insert_rs_byte = common_attr->mpeg_cfg.insert_rs_byte;
3058         cfg_data->enable_parallel = common_attr->mpeg_cfg.enable_parallel;
3059         cfg_data->invert_data = common_attr->mpeg_cfg.invert_data;
3060         cfg_data->invert_err = common_attr->mpeg_cfg.invert_err;
3061         cfg_data->invert_str = common_attr->mpeg_cfg.invert_str;
3062         cfg_data->invert_val = common_attr->mpeg_cfg.invert_val;
3063         cfg_data->invert_clk = common_attr->mpeg_cfg.invert_clk;
3064         cfg_data->static_clk = common_attr->mpeg_cfg.static_clk;
3065         cfg_data->bitrate = 0;
3066
3067         CHK_ERROR(ctrl_lock_status(demod, &lock_status));
3068         if ((lock_status == DRX_LOCKED)) {
3069                 RR32(dev_addr, FEC_OC_RCN_DYN_RATE_LO__A, &rate_reg);
3070                 /* Frcn_rate = rate_reg * Fsys / 2 ^ 25 */
3071                 mult32(rate_reg, common_attr->sys_clock_freq * 1000, &data64hi,
3072                        &data64lo);
3073                 cfg_data->bitrate = (data64hi << 7) | (data64lo >> 25);
3074         }
3075
3076         return (DRX_STS_OK);
3077 rw_error:
3078         return (DRX_STS_ERROR);
3079 }
3080
3081 /*----------------------------------------------------------------------------*/
3082 /* MPEG Output Configuration Functions - end                                  */
3083 /*----------------------------------------------------------------------------*/
3084
3085 /*----------------------------------------------------------------------------*/
3086 /* miscellaneous configuartions - begin                           */
3087 /*----------------------------------------------------------------------------*/
3088
3089 /**
3090 * \fn int set_mpegtei_handling()
3091 * \brief Activate MPEG TEI handling settings.
3092 * \param devmod  Pointer to demodulator instance.
3093 * \return int.
3094 *
3095 * This routine should be called during a set channel of QAM/VSB
3096 *
3097 */
3098 static int set_mpegtei_handling(pdrx_demod_instance_t demod)
3099 {
3100         pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3101         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) (NULL);
3102         u16 fec_oc_dpr_mode = 0;
3103         u16 fec_oc_snc_mode = 0;
3104         u16 fec_oc_ems_mode = 0;
3105
3106         dev_addr = demod->my_i2c_dev_addr;
3107         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
3108
3109         RR16(dev_addr, FEC_OC_DPR_MODE__A, &fec_oc_dpr_mode);
3110         RR16(dev_addr, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode);
3111         RR16(dev_addr, FEC_OC_EMS_MODE__A, &fec_oc_ems_mode);
3112
3113         /* reset to default, allow TEI bit to be changed */
3114         fec_oc_dpr_mode &= (~FEC_OC_DPR_MODE_ERR_DISABLE__M);
3115         fec_oc_snc_mode &= (~(FEC_OC_SNC_MODE_ERROR_CTL__M |
3116                            FEC_OC_SNC_MODE_CORR_DISABLE__M));
3117         fec_oc_ems_mode &= (~FEC_OC_EMS_MODE_MODE__M);
3118
3119         if (ext_attr->disable_te_ihandling == true) {
3120                 /* do not change TEI bit */
3121                 fec_oc_dpr_mode |= FEC_OC_DPR_MODE_ERR_DISABLE__M;
3122                 fec_oc_snc_mode |= FEC_OC_SNC_MODE_CORR_DISABLE__M |
3123                     ((0x2) << (FEC_OC_SNC_MODE_ERROR_CTL__B));
3124                 fec_oc_ems_mode |= ((0x01) << (FEC_OC_EMS_MODE_MODE__B));
3125         }
3126
3127         WR16(dev_addr, FEC_OC_DPR_MODE__A, fec_oc_dpr_mode);
3128         WR16(dev_addr, FEC_OC_SNC_MODE__A, fec_oc_snc_mode);
3129         WR16(dev_addr, FEC_OC_EMS_MODE__A, fec_oc_ems_mode);
3130
3131         return (DRX_STS_OK);
3132 rw_error:
3133         return (DRX_STS_ERROR);
3134 }
3135
3136 /*----------------------------------------------------------------------------*/
3137 /**
3138 * \fn int bit_reverse_mpeg_output()
3139 * \brief Set MPEG output bit-endian settings.
3140 * \param devmod  Pointer to demodulator instance.
3141 * \return int.
3142 *
3143 * This routine should be called during a set channel of QAM/VSB
3144 *
3145 */
3146 static int bit_reverse_mpeg_output(pdrx_demod_instance_t demod)
3147 {
3148         pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3149         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) (NULL);
3150         u16 fec_oc_ipr_mode = 0;
3151
3152         dev_addr = demod->my_i2c_dev_addr;
3153         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
3154
3155         RR16(dev_addr, FEC_OC_IPR_MODE__A, &fec_oc_ipr_mode);
3156
3157         /* reset to default (normal bit order) */
3158         fec_oc_ipr_mode &= (~FEC_OC_IPR_MODE_REVERSE_ORDER__M);
3159
3160         if (ext_attr->bit_reverse_mpeg_outout == true) {
3161                 /* reverse bit order */
3162                 fec_oc_ipr_mode |= FEC_OC_IPR_MODE_REVERSE_ORDER__M;
3163         }
3164
3165         WR16(dev_addr, FEC_OC_IPR_MODE__A, fec_oc_ipr_mode);
3166
3167         return (DRX_STS_OK);
3168 rw_error:
3169         return (DRX_STS_ERROR);
3170 }
3171
3172 /*----------------------------------------------------------------------------*/
3173 /**
3174 * \fn int set_mpeg_output_clock_rate()
3175 * \brief Set MPEG output clock rate.
3176 * \param devmod  Pointer to demodulator instance.
3177 * \return int.
3178 *
3179 * This routine should be called during a set channel of QAM/VSB
3180 *
3181 */
3182 static int set_mpeg_output_clock_rate(pdrx_demod_instance_t demod)
3183 {
3184         pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3185         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) (NULL);
3186
3187         dev_addr = demod->my_i2c_dev_addr;
3188         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
3189
3190         if (ext_attr->mpeg_output_clock_rate != DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO) {
3191                 WR16(dev_addr, FEC_OC_DTO_PERIOD__A,
3192                      ext_attr->mpeg_output_clock_rate - 1);
3193         }
3194
3195         return (DRX_STS_OK);
3196 rw_error:
3197         return (DRX_STS_ERROR);
3198 }
3199
3200 /*----------------------------------------------------------------------------*/
3201 /**
3202 * \fn int set_mpeg_start_width()
3203 * \brief Set MPEG start width.
3204 * \param devmod  Pointer to demodulator instance.
3205 * \return int.
3206 *
3207 * This routine should be called during a set channel of QAM/VSB
3208 *
3209 */
3210 static int set_mpeg_start_width(pdrx_demod_instance_t demod)
3211 {
3212         pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3213         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) (NULL);
3214         u16 fec_oc_comm_mb = 0;
3215         pdrx_common_attr_t common_attr = (pdrx_common_attr_t) NULL;
3216
3217         dev_addr = demod->my_i2c_dev_addr;
3218         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
3219         common_attr = demod->my_common_attr;
3220
3221         if ((common_attr->mpeg_cfg.static_clk == true)
3222             && (common_attr->mpeg_cfg.enable_parallel == false)) {
3223                 RR16(dev_addr, FEC_OC_COMM_MB__A, &fec_oc_comm_mb);
3224                 fec_oc_comm_mb &= ~FEC_OC_COMM_MB_CTL_ON;
3225                 if (ext_attr->mpeg_start_width == DRXJ_MPEG_START_WIDTH_8CLKCYC) {
3226                         fec_oc_comm_mb |= FEC_OC_COMM_MB_CTL_ON;
3227                 }
3228                 WR16(dev_addr, FEC_OC_COMM_MB__A, fec_oc_comm_mb);
3229         }
3230
3231         return (DRX_STS_OK);
3232 rw_error:
3233         return (DRX_STS_ERROR);
3234 }
3235
3236 /*----------------------------------------------------------------------------*/
3237 /**
3238 * \fn int ctrl_set_cfg_mpeg_output_misc()
3239 * \brief Set miscellaneous configuartions
3240 * \param devmod  Pointer to demodulator instance.
3241 * \param cfg_data pDRXJCfgMisc_t
3242 * \return int.
3243 *
3244 *  This routine can be used to set configuartion options that are DRXJ
3245 *  specific and/or added to the requirements at a late stage.
3246 *
3247 */
3248 static int
3249 ctrl_set_cfg_mpeg_output_misc(pdrx_demod_instance_t demod,
3250                          p_drxj_cfg_mpeg_output_misc_t cfg_data)
3251 {
3252         pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3253
3254         if (cfg_data == NULL) {
3255                 return (DRX_STS_INVALID_ARG);
3256         }
3257
3258         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
3259
3260         /*
3261            Set disable TEI bit handling flag.
3262            TEI must be left untouched by device in case of BER measurements using
3263            external equipment that is unable to ignore the TEI bit in the TS.
3264            Default will false (enable TEI bit handling).
3265            Reverse output bit order. Default is false (msb on MD7 (parallel) or out first (serial)).
3266            Set clock rate. Default is auto that is derived from symbol rate.
3267            The flags and values will also be used to set registers during a set channel.
3268          */
3269         ext_attr->disable_te_ihandling = cfg_data->disable_tei_handling;
3270         ext_attr->bit_reverse_mpeg_outout = cfg_data->bit_reverse_mpeg_outout;
3271         ext_attr->mpeg_output_clock_rate = cfg_data->mpeg_output_clock_rate;
3272         ext_attr->mpeg_start_width = cfg_data->mpeg_start_width;
3273         /* Don't care what the active standard is, activate setting immediatly */
3274         CHK_ERROR(set_mpegtei_handling(demod));
3275         CHK_ERROR(bit_reverse_mpeg_output(demod));
3276         CHK_ERROR(set_mpeg_output_clock_rate(demod));
3277         CHK_ERROR(set_mpeg_start_width(demod));
3278
3279         return (DRX_STS_OK);
3280 rw_error:
3281         return (DRX_STS_ERROR);
3282 }
3283
3284 /*----------------------------------------------------------------------------*/
3285
3286 /**
3287 * \fn int ctrl_get_cfg_mpeg_output_misc()
3288 * \brief Get miscellaneous configuartions.
3289 * \param devmod  Pointer to demodulator instance.
3290 * \param cfg_data Pointer to DRXJCfgMisc_t.
3291 * \return int.
3292 *
3293 *  This routine can be used to retreive the current setting of the configuartion
3294 *  options that are DRXJ specific and/or added to the requirements at a
3295 *  late stage.
3296 *
3297 */
3298 static int
3299 ctrl_get_cfg_mpeg_output_misc(pdrx_demod_instance_t demod,
3300                          p_drxj_cfg_mpeg_output_misc_t cfg_data)
3301 {
3302         pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3303         u16 data = 0;
3304
3305         if (cfg_data == NULL) {
3306                 return (DRX_STS_INVALID_ARG);
3307         }
3308
3309         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
3310         cfg_data->disable_tei_handling = ext_attr->disable_te_ihandling;
3311         cfg_data->bit_reverse_mpeg_outout = ext_attr->bit_reverse_mpeg_outout;
3312         cfg_data->mpeg_start_width = ext_attr->mpeg_start_width;
3313         if (ext_attr->mpeg_output_clock_rate != DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO) {
3314                 cfg_data->mpeg_output_clock_rate = ext_attr->mpeg_output_clock_rate;
3315         } else {
3316                 RR16(demod->my_i2c_dev_addr, FEC_OC_DTO_PERIOD__A, &data);
3317                 cfg_data->mpeg_output_clock_rate =
3318                     (drxj_mpeg_output_clock_rate_t) (data + 1);
3319         }
3320
3321         return (DRX_STS_OK);
3322 rw_error:
3323         return (DRX_STS_ERROR);
3324 }
3325
3326 /*----------------------------------------------------------------------------*/
3327
3328 /**
3329 * \fn int ctrl_get_cfg_hw_cfg()
3330 * \brief Get HW configuartions.
3331 * \param devmod  Pointer to demodulator instance.
3332 * \param cfg_data Pointer to Bool.
3333 * \return int.
3334 *
3335 *  This routine can be used to retreive the current setting of the configuartion
3336 *  options that are DRXJ specific and/or added to the requirements at a
3337 *  late stage.
3338 *
3339 */
3340 static int
3341 ctrl_get_cfg_hw_cfg(pdrx_demod_instance_t demod, p_drxj_cfg_hw_cfg_t cfg_data)
3342 {
3343         u16 data = 0;
3344         pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3345
3346         if (cfg_data == NULL) {
3347                 return (DRX_STS_INVALID_ARG);
3348         }
3349
3350         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
3351         WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA);
3352         RR16(demod->my_i2c_dev_addr, SIO_PDR_OHW_CFG__A, &data);
3353         WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000);
3354
3355         cfg_data->i2c_speed = (drxji2c_speed_t) ((data >> 6) & 0x1);
3356         cfg_data->xtal_freq = (drxj_xtal_freq_t) (data & 0x3);
3357
3358         return (DRX_STS_OK);
3359 rw_error:
3360         return (DRX_STS_ERROR);
3361 }
3362
3363 /*----------------------------------------------------------------------------*/
3364 /* miscellaneous configuartions - end                             */
3365 /*----------------------------------------------------------------------------*/
3366
3367 /*----------------------------------------------------------------------------*/
3368 /* UIO Configuration Functions - begin                                        */
3369 /*----------------------------------------------------------------------------*/
3370 /**
3371 * \fn int ctrl_set_uio_cfg()
3372 * \brief Configure modus oprandi UIO.
3373 * \param demod Pointer to demodulator instance.
3374 * \param uio_cfg Pointer to a configuration setting for a certain UIO.
3375 * \return int.
3376 */
3377 static int ctrl_set_uio_cfg(pdrx_demod_instance_t demod, pdrxuio_cfg_t uio_cfg)
3378 {
3379         pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3380
3381         if ((uio_cfg == NULL) || (demod == NULL)) {
3382                 return DRX_STS_INVALID_ARG;
3383         }
3384         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
3385
3386         /*  Write magic word to enable pdr reg write               */
3387         WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
3388         switch (uio_cfg->uio) {
3389       /*====================================================================*/
3390         case DRX_UIO1:
3391                 /* DRX_UIO1: SMA_TX UIO-1 */
3392                 if (ext_attr->has_smatx != true)
3393                         return DRX_STS_ERROR;
3394                 switch (uio_cfg->mode) {
3395                 case DRX_UIO_MODE_FIRMWARE_SMA: /* falltrough */
3396                 case DRX_UIO_MODE_FIRMWARE_SAW: /* falltrough */
3397                 case DRX_UIO_MODE_READWRITE:
3398                         ext_attr->uio_sma_tx_mode = uio_cfg->mode;
3399                         break;
3400                 case DRX_UIO_MODE_DISABLE:
3401                         ext_attr->uio_sma_tx_mode = uio_cfg->mode;
3402                         /* pad configuration register is set 0 - input mode */
3403                         WR16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, 0);
3404                         break;
3405                 default:
3406                         return DRX_STS_INVALID_ARG;
3407                 }               /* switch ( uio_cfg->mode ) */
3408                 break;
3409       /*====================================================================*/
3410         case DRX_UIO2:
3411                 /* DRX_UIO2: SMA_RX UIO-2 */
3412                 if (ext_attr->has_smarx != true)
3413                         return DRX_STS_ERROR;
3414                 switch (uio_cfg->mode) {
3415                 case DRX_UIO_MODE_FIRMWARE0:    /* falltrough */
3416                 case DRX_UIO_MODE_READWRITE:
3417                         ext_attr->uio_sma_rx_mode = uio_cfg->mode;
3418                         break;
3419                 case DRX_UIO_MODE_DISABLE:
3420                         ext_attr->uio_sma_rx_mode = uio_cfg->mode;
3421                         /* pad configuration register is set 0 - input mode */
3422                         WR16(demod->my_i2c_dev_addr, SIO_PDR_SMA_RX_CFG__A, 0);
3423                         break;
3424                 default:
3425                         return DRX_STS_INVALID_ARG;
3426                         break;
3427                 }               /* switch ( uio_cfg->mode ) */
3428                 break;
3429       /*====================================================================*/
3430         case DRX_UIO3:
3431                 /* DRX_UIO3: GPIO UIO-3 */
3432                 if (ext_attr->has_gpio != true)
3433                         return DRX_STS_ERROR;
3434                 switch (uio_cfg->mode) {
3435                 case DRX_UIO_MODE_FIRMWARE0:    /* falltrough */
3436                 case DRX_UIO_MODE_READWRITE:
3437                         ext_attr->uio_gpio_mode = uio_cfg->mode;
3438                         break;
3439                 case DRX_UIO_MODE_DISABLE:
3440                         ext_attr->uio_gpio_mode = uio_cfg->mode;
3441                         /* pad configuration register is set 0 - input mode */
3442                         WR16(demod->my_i2c_dev_addr, SIO_PDR_GPIO_CFG__A, 0);
3443                         break;
3444                 default:
3445                         return DRX_STS_INVALID_ARG;
3446                         break;
3447                 }               /* switch ( uio_cfg->mode ) */
3448                 break;
3449       /*====================================================================*/
3450         case DRX_UIO4:
3451                 /* DRX_UIO4: IRQN UIO-4 */
3452                 if (ext_attr->has_irqn != true)
3453                         return DRX_STS_ERROR;
3454                 switch (uio_cfg->mode) {
3455                 case DRX_UIO_MODE_READWRITE:
3456                         ext_attr->uio_irqn_mode = uio_cfg->mode;
3457                         break;
3458                 case DRX_UIO_MODE_DISABLE:
3459                         /* pad configuration register is set 0 - input mode */
3460                         WR16(demod->my_i2c_dev_addr, SIO_PDR_IRQN_CFG__A, 0);
3461                         ext_attr->uio_irqn_mode = uio_cfg->mode;
3462                         break;
3463                 case DRX_UIO_MODE_FIRMWARE0:    /* falltrough */
3464                 default:
3465                         return DRX_STS_INVALID_ARG;
3466                         break;
3467                 }               /* switch ( uio_cfg->mode ) */
3468                 break;
3469       /*====================================================================*/
3470         default:
3471                 return DRX_STS_INVALID_ARG;
3472         }                       /* switch ( uio_cfg->uio ) */
3473
3474         /*  Write magic word to disable pdr reg write               */
3475         WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000);
3476
3477         return (DRX_STS_OK);
3478 rw_error:
3479         return (DRX_STS_ERROR);
3480 }
3481
3482 /*============================================================================*/
3483 /**
3484 * \fn int CtrlGetuio_cfg()
3485 * \brief Get modus oprandi UIO.
3486 * \param demod Pointer to demodulator instance.
3487 * \param uio_cfg Pointer to a configuration setting for a certain UIO.
3488 * \return int.
3489 */
3490 static int CtrlGetuio_cfg(pdrx_demod_instance_t demod, pdrxuio_cfg_t uio_cfg)
3491 {
3492
3493         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
3494         pdrxuio_mode_t uio_mode[4] = { NULL };
3495         bool *uio_available[4] = { NULL };
3496
3497         ext_attr = demod->my_ext_attr;
3498
3499         uio_mode[DRX_UIO1] = &ext_attr->uio_sma_tx_mode;
3500         uio_mode[DRX_UIO2] = &ext_attr->uio_sma_rx_mode;
3501         uio_mode[DRX_UIO3] = &ext_attr->uio_gpio_mode;
3502         uio_mode[DRX_UIO4] = &ext_attr->uio_irqn_mode;
3503
3504         uio_available[DRX_UIO1] = &ext_attr->has_smatx;
3505         uio_available[DRX_UIO2] = &ext_attr->has_smarx;
3506         uio_available[DRX_UIO3] = &ext_attr->has_gpio;
3507         uio_available[DRX_UIO4] = &ext_attr->has_irqn;
3508
3509         if (uio_cfg == NULL) {
3510                 return DRX_STS_INVALID_ARG;
3511         }
3512
3513         if ((uio_cfg->uio > DRX_UIO4) || (uio_cfg->uio < DRX_UIO1)) {
3514                 return DRX_STS_INVALID_ARG;
3515         }
3516
3517         if (*uio_available[uio_cfg->uio] == false) {
3518                 return DRX_STS_ERROR;
3519         }
3520
3521         uio_cfg->mode = *uio_mode[uio_cfg->uio];
3522
3523         return DRX_STS_OK;
3524 }
3525
3526 /**
3527 * \fn int ctrl_uio_write()
3528 * \brief Write to a UIO.
3529 * \param demod Pointer to demodulator instance.
3530 * \param uio_data Pointer to data container for a certain UIO.
3531 * \return int.
3532 */
3533 static int
3534 ctrl_uio_write(pdrx_demod_instance_t demod, pdrxuio_data_t uio_data)
3535 {
3536         pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3537         u16 pin_cfg_value = 0;
3538         u16 value = 0;
3539
3540         if ((uio_data == NULL) || (demod == NULL)) {
3541                 return DRX_STS_INVALID_ARG;
3542         }
3543
3544         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
3545
3546         /*  Write magic word to enable pdr reg write               */
3547         WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
3548         switch (uio_data->uio) {
3549       /*====================================================================*/
3550         case DRX_UIO1:
3551                 /* DRX_UIO1: SMA_TX UIO-1 */
3552                 if (ext_attr->has_smatx != true)
3553                         return DRX_STS_ERROR;
3554                 if ((ext_attr->uio_sma_tx_mode != DRX_UIO_MODE_READWRITE)
3555                     && (ext_attr->uio_sma_tx_mode != DRX_UIO_MODE_FIRMWARE_SAW)) {
3556                         return DRX_STS_ERROR;
3557                 }
3558                 pin_cfg_value = 0;
3559                 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
3560                 pin_cfg_value |= 0x0113;
3561                 /* io_pad_cfg_mode output mode is drive always */
3562                 /* io_pad_cfg_drive is set to power 2 (23 mA) */
3563
3564                 /* write to io pad configuration register - output mode */
3565                 WR16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, pin_cfg_value);
3566
3567                 /* use corresponding bit in io data output registar */
3568                 RR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, &value);
3569                 if (uio_data->value == false) {
3570                         value &= 0x7FFF;        /* write zero to 15th bit - 1st UIO */
3571                 } else {
3572                         value |= 0x8000;        /* write one to 15th bit - 1st UIO */
3573                 }
3574                 /* write back to io data output register */
3575                 WR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value);
3576                 break;
3577    /*======================================================================*/
3578         case DRX_UIO2:
3579                 /* DRX_UIO2: SMA_RX UIO-2 */
3580                 if (ext_attr->has_smarx != true)
3581                         return DRX_STS_ERROR;
3582                 if (ext_attr->uio_sma_rx_mode != DRX_UIO_MODE_READWRITE) {
3583                         return DRX_STS_ERROR;
3584                 }
3585                 pin_cfg_value = 0;
3586                 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
3587                 pin_cfg_value |= 0x0113;
3588                 /* io_pad_cfg_mode output mode is drive always */
3589                 /* io_pad_cfg_drive is set to power 2 (23 mA) */
3590
3591                 /* write to io pad configuration register - output mode */
3592                 WR16(demod->my_i2c_dev_addr, SIO_PDR_SMA_RX_CFG__A, pin_cfg_value);
3593
3594                 /* use corresponding bit in io data output registar */
3595                 RR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, &value);
3596                 if (uio_data->value == false) {
3597                         value &= 0xBFFF;        /* write zero to 14th bit - 2nd UIO */
3598                 } else {
3599                         value |= 0x4000;        /* write one to 14th bit - 2nd UIO */
3600                 }
3601                 /* write back to io data output register */
3602                 WR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value);
3603                 break;
3604    /*====================================================================*/
3605         case DRX_UIO3:
3606                 /* DRX_UIO3: ASEL UIO-3 */
3607                 if (ext_attr->has_gpio != true)
3608                         return DRX_STS_ERROR;
3609                 if (ext_attr->uio_gpio_mode != DRX_UIO_MODE_READWRITE) {
3610                         return DRX_STS_ERROR;
3611                 }
3612                 pin_cfg_value = 0;
3613                 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
3614                 pin_cfg_value |= 0x0113;
3615                 /* io_pad_cfg_mode output mode is drive always */
3616                 /* io_pad_cfg_drive is set to power 2 (23 mA) */
3617
3618                 /* write to io pad configuration register - output mode */
3619                 WR16(demod->my_i2c_dev_addr, SIO_PDR_GPIO_CFG__A, pin_cfg_value);
3620
3621                 /* use corresponding bit in io data output registar */
3622                 RR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_HI__A, &value);
3623                 if (uio_data->value == false) {
3624                         value &= 0xFFFB;        /* write zero to 2nd bit - 3rd UIO */
3625                 } else {
3626                         value |= 0x0004;        /* write one to 2nd bit - 3rd UIO */
3627                 }
3628                 /* write back to io data output register */
3629                 WR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_HI__A, value);
3630                 break;
3631    /*=====================================================================*/
3632         case DRX_UIO4:
3633                 /* DRX_UIO4: IRQN UIO-4 */
3634                 if (ext_attr->has_irqn != true)
3635                         return DRX_STS_ERROR;
3636
3637                 if (ext_attr->uio_irqn_mode != DRX_UIO_MODE_READWRITE) {
3638                         return DRX_STS_ERROR;
3639                 }
3640                 pin_cfg_value = 0;
3641                 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
3642                 pin_cfg_value |= 0x0113;
3643                 /* io_pad_cfg_mode output mode is drive always */
3644                 /* io_pad_cfg_drive is set to power 2 (23 mA) */
3645
3646                 /* write to io pad configuration register - output mode */
3647                 WR16(demod->my_i2c_dev_addr, SIO_PDR_IRQN_CFG__A, pin_cfg_value);
3648
3649                 /* use corresponding bit in io data output registar */
3650                 RR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, &value);
3651                 if (uio_data->value == false) {
3652                         value &= 0xEFFF;        /* write zero to 12th bit - 4th UIO */
3653                 } else {
3654                         value |= 0x1000;        /* write one to 12th bit - 4th UIO */
3655                 }
3656                 /* write back to io data output register */
3657                 WR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value);
3658                 break;
3659       /*=====================================================================*/
3660         default:
3661                 return DRX_STS_INVALID_ARG;
3662         }                       /* switch ( uio_data->uio ) */
3663
3664         /*  Write magic word to disable pdr reg write               */
3665         WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000);
3666
3667         return (DRX_STS_OK);
3668 rw_error:
3669         return (DRX_STS_ERROR);
3670 }
3671
3672 /**
3673 *\fn int ctrl_uio_read
3674 *\brief Read from a UIO.
3675 * \param demod Pointer to demodulator instance.
3676 * \param uio_data Pointer to data container for a certain UIO.
3677 * \return int.
3678 */
3679 static int ctrl_uio_read(pdrx_demod_instance_t demod, pdrxuio_data_t uio_data)
3680 {
3681         pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3682         u16 pin_cfg_value = 0;
3683         u16 value = 0;
3684
3685         if ((uio_data == NULL) || (demod == NULL)) {
3686                 return DRX_STS_INVALID_ARG;
3687         }
3688
3689         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
3690
3691         /*  Write magic word to enable pdr reg write               */
3692         WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
3693         switch (uio_data->uio) {
3694       /*====================================================================*/
3695         case DRX_UIO1:
3696                 /* DRX_UIO1: SMA_TX UIO-1 */
3697                 if (ext_attr->has_smatx != true)
3698                         return DRX_STS_ERROR;
3699
3700                 if (ext_attr->uio_sma_tx_mode != DRX_UIO_MODE_READWRITE) {
3701                         return DRX_STS_ERROR;
3702                 }
3703                 pin_cfg_value = 0;
3704                 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
3705                 pin_cfg_value |= 0x0110;
3706                 /* io_pad_cfg_mode output mode is drive always */
3707                 /* io_pad_cfg_drive is set to power 2 (23 mA) */
3708
3709                 /* write to io pad configuration register - input mode */
3710                 WR16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, pin_cfg_value);
3711
3712                 RR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_IN_LO__A, &value);
3713                 if ((value & 0x8000) != 0) {    /* check 15th bit - 1st UIO */
3714                         uio_data->value = true;
3715                 } else {
3716                         uio_data->value = false;
3717                 }
3718                 break;
3719    /*======================================================================*/
3720         case DRX_UIO2:
3721                 /* DRX_UIO2: SMA_RX UIO-2 */
3722                 if (ext_attr->has_smarx != true)
3723                         return DRX_STS_ERROR;
3724
3725                 if (ext_attr->uio_sma_rx_mode != DRX_UIO_MODE_READWRITE) {
3726                         return DRX_STS_ERROR;
3727                 }
3728                 pin_cfg_value = 0;
3729                 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
3730                 pin_cfg_value |= 0x0110;
3731                 /* io_pad_cfg_mode output mode is drive always */
3732                 /* io_pad_cfg_drive is set to power 2 (23 mA) */
3733
3734                 /* write to io pad configuration register - input mode */
3735                 WR16(demod->my_i2c_dev_addr, SIO_PDR_SMA_RX_CFG__A, pin_cfg_value);
3736
3737                 RR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_IN_LO__A, &value);
3738
3739                 if ((value & 0x4000) != 0) {    /* check 14th bit - 2nd UIO */
3740                         uio_data->value = true;
3741                 } else {
3742                         uio_data->value = false;
3743                 }
3744                 break;
3745    /*=====================================================================*/
3746         case DRX_UIO3:
3747                 /* DRX_UIO3: GPIO UIO-3 */
3748                 if (ext_attr->has_gpio != true)
3749                         return DRX_STS_ERROR;
3750
3751                 if (ext_attr->uio_gpio_mode != DRX_UIO_MODE_READWRITE) {
3752                         return DRX_STS_ERROR;
3753                 }
3754                 pin_cfg_value = 0;
3755                 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
3756                 pin_cfg_value |= 0x0110;
3757                 /* io_pad_cfg_mode output mode is drive always */
3758                 /* io_pad_cfg_drive is set to power 2 (23 mA) */
3759
3760                 /* write to io pad configuration register - input mode */
3761                 WR16(demod->my_i2c_dev_addr, SIO_PDR_GPIO_CFG__A, pin_cfg_value);
3762
3763                 /* read io input data registar */
3764                 RR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_IN_HI__A, &value);
3765                 if ((value & 0x0004) != 0) {    /* check 2nd bit - 3rd UIO */
3766                         uio_data->value = true;
3767                 } else {
3768                         uio_data->value = false;
3769                 }
3770                 break;
3771    /*=====================================================================*/
3772         case DRX_UIO4:
3773                 /* DRX_UIO4: IRQN UIO-4 */
3774                 if (ext_attr->has_irqn != true)
3775                         return DRX_STS_ERROR;
3776
3777                 if (ext_attr->uio_irqn_mode != DRX_UIO_MODE_READWRITE) {
3778                         return DRX_STS_ERROR;
3779                 }
3780                 pin_cfg_value = 0;
3781                 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
3782                 pin_cfg_value |= 0x0110;
3783                 /* io_pad_cfg_mode output mode is drive always */
3784                 /* io_pad_cfg_drive is set to power 2 (23 mA) */
3785
3786                 /* write to io pad configuration register - input mode */
3787                 WR16(demod->my_i2c_dev_addr, SIO_PDR_IRQN_CFG__A, pin_cfg_value);
3788
3789                 /* read io input data registar */
3790                 RR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_IN_LO__A, &value);
3791                 if ((value & 0x1000) != 0) {    /* check 12th bit - 4th UIO */
3792                         uio_data->value = true;
3793                 } else {
3794                         uio_data->value = false;
3795                 }
3796                 break;
3797       /*====================================================================*/
3798         default:
3799                 return DRX_STS_INVALID_ARG;
3800         }                       /* switch ( uio_data->uio ) */
3801
3802         /*  Write magic word to disable pdr reg write               */
3803         WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000);
3804
3805         return (DRX_STS_OK);
3806 rw_error:
3807         return (DRX_STS_ERROR);
3808 }
3809
3810 /*---------------------------------------------------------------------------*/
3811 /* UIO Configuration Functions - end                                         */
3812 /*---------------------------------------------------------------------------*/
3813
3814 /*----------------------------------------------------------------------------*/
3815 /* I2C Bridge Functions - begin                                               */
3816 /*----------------------------------------------------------------------------*/
3817 /**
3818 * \fn int ctrl_i2c_bridge()
3819 * \brief Open or close the I2C switch to tuner.
3820 * \param demod Pointer to demodulator instance.
3821 * \param bridge_closed Pointer to bool indication if bridge is closed not.
3822 * \return int.
3823
3824 */
3825 static int
3826 ctrl_i2c_bridge(pdrx_demod_instance_t demod, bool *bridge_closed)
3827 {
3828         drxj_hi_cmd_t hi_cmd;
3829         u16 result = 0;
3830
3831         /* check arguments */
3832         if (bridge_closed == NULL) {
3833                 return (DRX_STS_INVALID_ARG);
3834         }
3835
3836         hi_cmd.cmd = SIO_HI_RA_RAM_CMD_BRDCTRL;
3837         hi_cmd.param1 = SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY;
3838         if (*bridge_closed == true) {
3839                 hi_cmd.param2 = SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED;
3840         } else {
3841                 hi_cmd.param2 = SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN;
3842         }
3843
3844         return hi_command(demod->my_i2c_dev_addr, &hi_cmd, &result);
3845 }
3846
3847 /*----------------------------------------------------------------------------*/
3848 /* I2C Bridge Functions - end                                                 */
3849 /*----------------------------------------------------------------------------*/
3850
3851 /*----------------------------------------------------------------------------*/
3852 /* Smart antenna Functions - begin                                            */
3853 /*----------------------------------------------------------------------------*/
3854 /**
3855 * \fn int smart_ant_init()
3856 * \brief Initialize Smart Antenna.
3857 * \param pointer to drx_demod_instance_t.
3858 * \return int.
3859 *
3860 */
3861 static int smart_ant_init(pdrx_demod_instance_t demod)
3862 {
3863         u16 data = 0;
3864         pdrxj_data_t ext_attr = NULL;
3865         struct i2c_device_addr *dev_addr = NULL;
3866         drxuio_cfg_t uio_cfg = { DRX_UIO1, DRX_UIO_MODE_FIRMWARE_SMA };
3867
3868         dev_addr = demod->my_i2c_dev_addr;
3869         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
3870
3871         /*  Write magic word to enable pdr reg write               */
3872         WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
3873         /* init smart antenna */
3874         RR16(dev_addr, SIO_SA_TX_COMMAND__A, &data);
3875         if (ext_attr->smart_ant_inverted)
3876                 WR16(dev_addr, SIO_SA_TX_COMMAND__A,
3877                      (data | SIO_SA_TX_COMMAND_TX_INVERT__M)
3878                      | SIO_SA_TX_COMMAND_TX_ENABLE__M);
3879         else
3880                 WR16(dev_addr, SIO_SA_TX_COMMAND__A,
3881                      (data & (~SIO_SA_TX_COMMAND_TX_INVERT__M))
3882                      | SIO_SA_TX_COMMAND_TX_ENABLE__M);
3883
3884         /* config SMA_TX pin to smart antenna mode */
3885         CHK_ERROR(ctrl_set_uio_cfg(demod, &uio_cfg));
3886         WR16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, 0x13);
3887         WR16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_GPIO_FNC__A, 0x03);
3888
3889         /*  Write magic word to disable pdr reg write               */
3890         WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000);
3891
3892         return (DRX_STS_OK);
3893 rw_error:
3894         return (DRX_STS_ERROR);
3895 }
3896
3897 /**
3898 * \fn int ctrl_set_cfg_smart_ant()
3899 * \brief Set Smart Antenna.
3900 * \param pointer to drxj_cfg_smart_ant_t.
3901 * \return int.
3902 *
3903 */
3904 static int
3905 ctrl_set_cfg_smart_ant(pdrx_demod_instance_t demod, p_drxj_cfg_smart_ant_t smart_ant)
3906 {
3907         pdrxj_data_t ext_attr = NULL;
3908         struct i2c_device_addr *dev_addr = NULL;
3909         u16 data = 0;
3910         u32 start_time = 0;
3911         static bool bit_inverted;
3912
3913         dev_addr = demod->my_i2c_dev_addr;
3914         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
3915
3916         /* check arguments */
3917         if (smart_ant == NULL) {
3918                 return (DRX_STS_INVALID_ARG);
3919         }
3920
3921         if (bit_inverted != ext_attr->smart_ant_inverted
3922             || ext_attr->uio_sma_tx_mode != DRX_UIO_MODE_FIRMWARE_SMA) {
3923                 CHK_ERROR(smart_ant_init(demod));
3924                 bit_inverted = ext_attr->smart_ant_inverted;
3925         }
3926
3927         /*  Write magic word to enable pdr reg write               */
3928         WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
3929
3930         switch (smart_ant->io) {
3931         case DRXJ_SMT_ANT_OUTPUT:
3932                 /* enable Tx if Mode B (input) is supported */
3933                 /*
3934                    RR16( dev_addr, SIO_SA_TX_COMMAND__A, &data );
3935                    WR16( dev_addr, SIO_SA_TX_COMMAND__A, data | SIO_SA_TX_COMMAND_TX_ENABLE__M );
3936                  */
3937                 start_time = drxbsp_hst_clock();
3938                 do {
3939                         RR16(dev_addr, SIO_SA_TX_STATUS__A, &data);
3940                 } while ((data & SIO_SA_TX_STATUS_BUSY__M)
3941                          && ((drxbsp_hst_clock() - start_time) <
3942                              DRXJ_MAX_WAITTIME));
3943
3944                 if (data & SIO_SA_TX_STATUS_BUSY__M) {
3945                         return (DRX_STS_ERROR);
3946                 }
3947
3948                 /* write to smart antenna configuration register */
3949                 WR16(dev_addr, SIO_SA_TX_DATA0__A, 0x9200
3950                      | ((smart_ant->ctrl_data & 0x0001) << 8)
3951                      | ((smart_ant->ctrl_data & 0x0002) << 10)
3952                      | ((smart_ant->ctrl_data & 0x0004) << 12)
3953                     );
3954                 WR16(dev_addr, SIO_SA_TX_DATA1__A, 0x4924
3955                      | ((smart_ant->ctrl_data & 0x0008) >> 2)
3956                      | ((smart_ant->ctrl_data & 0x0010))
3957                      | ((smart_ant->ctrl_data & 0x0020) << 2)
3958                      | ((smart_ant->ctrl_data & 0x0040) << 4)
3959                      | ((smart_ant->ctrl_data & 0x0080) << 6)
3960                     );
3961                 WR16(dev_addr, SIO_SA_TX_DATA2__A, 0x2492
3962                      | ((smart_ant->ctrl_data & 0x0100) >> 8)
3963                      | ((smart_ant->ctrl_data & 0x0200) >> 6)
3964                      | ((smart_ant->ctrl_data & 0x0400) >> 4)
3965                      | ((smart_ant->ctrl_data & 0x0800) >> 2)
3966                      | ((smart_ant->ctrl_data & 0x1000))
3967                      | ((smart_ant->ctrl_data & 0x2000) << 2)
3968                     );
3969                 WR16(dev_addr, SIO_SA_TX_DATA3__A, 0xff8d);
3970
3971                 /* trigger the sending */
3972                 WR16(dev_addr, SIO_SA_TX_LENGTH__A, 56);
3973
3974                 break;
3975         case DRXJ_SMT_ANT_INPUT:
3976                 /* disable Tx if Mode B (input) is supported */
3977                 /*
3978                    RR16( dev_addr, SIO_SA_TX_COMMAND__A, &data );
3979                    WR16( dev_addr, SIO_SA_TX_COMMAND__A, data & (~SIO_SA_TX_COMMAND_TX_ENABLE__M) );
3980                  */
3981         default:
3982                 return (DRX_STS_INVALID_ARG);
3983         }
3984         /*  Write magic word to enable pdr reg write               */
3985         WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000);
3986
3987         return (DRX_STS_OK);
3988 rw_error:
3989         return (DRX_STS_ERROR);
3990 }
3991
3992 static int scu_command(struct i2c_device_addr *dev_addr, p_drxjscu_cmd_t cmd)
3993 {
3994         u16 cur_cmd = 0;
3995         u32 start_time = 0;
3996
3997         /* Check param */
3998         if (cmd == NULL)
3999                 return (DRX_STS_INVALID_ARG);
4000
4001         /* Wait until SCU command interface is ready to receive command */
4002         RR16(dev_addr, SCU_RAM_COMMAND__A, &cur_cmd);
4003         if (cur_cmd != DRX_SCU_READY) {
4004                 return (DRX_STS_ERROR);
4005         }
4006
4007         switch (cmd->parameter_len) {
4008         case 5:
4009                 WR16(dev_addr, SCU_RAM_PARAM_4__A, *(cmd->parameter + 4));      /* fallthrough */
4010         case 4:
4011                 WR16(dev_addr, SCU_RAM_PARAM_3__A, *(cmd->parameter + 3));      /* fallthrough */
4012         case 3:
4013                 WR16(dev_addr, SCU_RAM_PARAM_2__A, *(cmd->parameter + 2));      /* fallthrough */
4014         case 2:
4015                 WR16(dev_addr, SCU_RAM_PARAM_1__A, *(cmd->parameter + 1));      /* fallthrough */
4016         case 1:
4017                 WR16(dev_addr, SCU_RAM_PARAM_0__A, *(cmd->parameter + 0));      /* fallthrough */
4018         case 0:
4019                 /* do nothing */
4020                 break;
4021         default:
4022                 /* this number of parameters is not supported */
4023                 return (DRX_STS_ERROR);
4024         }
4025         WR16(dev_addr, SCU_RAM_COMMAND__A, cmd->command);
4026
4027         /* Wait until SCU has processed command */
4028         start_time = drxbsp_hst_clock();
4029         do {
4030                 RR16(dev_addr, SCU_RAM_COMMAND__A, &cur_cmd);
4031         } while (!(cur_cmd == DRX_SCU_READY)
4032                  && ((drxbsp_hst_clock() - start_time) < DRXJ_MAX_WAITTIME));
4033
4034         if (cur_cmd != DRX_SCU_READY) {
4035                 return (DRX_STS_ERROR);
4036         }
4037
4038         /* read results */
4039         if ((cmd->result_len > 0) && (cmd->result != NULL)) {
4040                 s16 err;
4041
4042                 switch (cmd->result_len) {
4043                 case 4:
4044                         RR16(dev_addr, SCU_RAM_PARAM_3__A, cmd->result + 3);    /* fallthrough */
4045                 case 3:
4046                         RR16(dev_addr, SCU_RAM_PARAM_2__A, cmd->result + 2);    /* fallthrough */
4047                 case 2:
4048                         RR16(dev_addr, SCU_RAM_PARAM_1__A, cmd->result + 1);    /* fallthrough */
4049                 case 1:
4050                         RR16(dev_addr, SCU_RAM_PARAM_0__A, cmd->result + 0);    /* fallthrough */
4051                 case 0:
4052                         /* do nothing */
4053                         break;
4054                 default:
4055                         /* this number of parameters is not supported */
4056                         return (DRX_STS_ERROR);
4057                 }
4058
4059                 /* Check if an error was reported by SCU */
4060                 err = cmd->result[0];
4061
4062                 /* check a few fixed error codes */
4063                 if ((err == (s16) SCU_RAM_PARAM_0_RESULT_UNKSTD)
4064                     || (err == (s16) SCU_RAM_PARAM_0_RESULT_UNKCMD)
4065                     || (err == (s16) SCU_RAM_PARAM_0_RESULT_INVPAR)
4066                     || (err == (s16) SCU_RAM_PARAM_0_RESULT_SIZE)
4067                     ) {
4068                         return DRX_STS_INVALID_ARG;
4069                 }
4070                 /* here it is assumed that negative means error, and positive no error */
4071                 else if (err < 0) {
4072                         return DRX_STS_ERROR;
4073                 } else {
4074                         return DRX_STS_OK;
4075                 }
4076         }
4077
4078         return (DRX_STS_OK);
4079
4080 rw_error:
4081         return (DRX_STS_ERROR);
4082 }
4083
4084 /**
4085 * \fn int DRXJ_DAP_SCUAtomicReadWriteBlock()
4086 * \brief Basic access routine for SCU atomic read or write access
4087 * \param dev_addr  pointer to i2c dev address
4088 * \param addr     destination/source address
4089 * \param datasize size of data buffer in bytes
4090 * \param data     pointer to data buffer
4091 * \return int
4092 * \retval DRX_STS_OK Succes
4093 * \retval DRX_STS_ERROR Timeout, I2C error, illegal bank
4094 *
4095 */
4096 #define ADDR_AT_SCU_SPACE(x) ((x - 0x82E000) * 2)
4097 static
4098 int drxj_dap_scu_atomic_read_write_block(struct i2c_device_addr *dev_addr, dr_xaddr_t addr, u16 datasize,       /* max 30 bytes because the limit of SCU parameter */
4099                                               u8 *data, bool read_flag)
4100 {
4101         drxjscu_cmd_t scu_cmd;
4102         u16 set_param_parameters[15];
4103         u16 cmd_result[15];
4104
4105         /* Parameter check */
4106         if ((data == NULL) ||
4107             (dev_addr == NULL) || ((datasize % 2) != 0) || ((datasize / 2) > 16)
4108             ) {
4109                 return (DRX_STS_INVALID_ARG);
4110         }
4111
4112         set_param_parameters[1] = (u16) ADDR_AT_SCU_SPACE(addr);
4113         if (read_flag) {                /* read */
4114                 set_param_parameters[0] = ((~(0x0080)) & datasize);
4115                 scu_cmd.parameter_len = 2;
4116                 scu_cmd.result_len = datasize / 2 + 2;
4117         } else {
4118                 int i = 0;
4119
4120                 set_param_parameters[0] = 0x0080 | datasize;
4121                 for (i = 0; i < (datasize / 2); i++) {
4122                         set_param_parameters[i + 2] =
4123                             (data[2 * i] | (data[(2 * i) + 1] << 8));
4124                 }
4125                 scu_cmd.parameter_len = datasize / 2 + 2;
4126                 scu_cmd.result_len = 1;
4127         }
4128
4129         scu_cmd.command =
4130             SCU_RAM_COMMAND_STANDARD_TOP |
4131             SCU_RAM_COMMAND_CMD_AUX_SCU_ATOMIC_ACCESS;
4132         scu_cmd.result = cmd_result;
4133         scu_cmd.parameter = set_param_parameters;
4134         CHK_ERROR(scu_command(dev_addr, &scu_cmd));
4135
4136         if (read_flag == true) {
4137                 int i = 0;
4138                 /* read data from buffer */
4139                 for (i = 0; i < (datasize / 2); i++) {
4140                         data[2 * i] = (u8) (scu_cmd.result[i + 2] & 0xFF);
4141                         data[(2 * i) + 1] = (u8) (scu_cmd.result[i + 2] >> 8);
4142                 }
4143         }
4144
4145         return DRX_STS_OK;
4146
4147 rw_error:
4148         return (DRX_STS_ERROR);
4149
4150 }
4151
4152 /*============================================================================*/
4153
4154 /**
4155 * \fn int DRXJ_DAP_AtomicReadReg16()
4156 * \brief Atomic read of 16 bits words
4157 */
4158 static
4159 int drxj_dap_scu_atomic_read_reg16(struct i2c_device_addr *dev_addr,
4160                                          dr_xaddr_t addr,
4161                                          u16 *data, dr_xflags_t flags)
4162 {
4163         u8 buf[2];
4164         int rc = DRX_STS_ERROR;
4165         u16 word = 0;
4166
4167         if (!data) {
4168                 return DRX_STS_INVALID_ARG;
4169         }
4170
4171         rc = drxj_dap_scu_atomic_read_write_block(dev_addr, addr, 2, buf, true);
4172
4173         word = (u16) (buf[0] + (buf[1] << 8));
4174
4175         *data = word;
4176
4177         return rc;
4178 }
4179
4180 /*============================================================================*/
4181 /**
4182 * \fn int drxj_dap_scu_atomic_write_reg16()
4183 * \brief Atomic read of 16 bits words
4184 */
4185 static
4186 int drxj_dap_scu_atomic_write_reg16(struct i2c_device_addr *dev_addr,
4187                                           dr_xaddr_t addr,
4188                                           u16 data, dr_xflags_t flags)
4189 {
4190         u8 buf[2];
4191         int rc = DRX_STS_ERROR;
4192
4193         buf[0] = (u8) (data & 0xff);
4194         buf[1] = (u8) ((data >> 8) & 0xff);
4195
4196         rc = drxj_dap_scu_atomic_read_write_block(dev_addr, addr, 2, buf, false);
4197
4198         return rc;
4199 }
4200
4201 static int
4202 ctrl_i2c_write_read(pdrx_demod_instance_t demod, pdrxi2c_data_t i2c_data)
4203 {
4204         return (DRX_STS_FUNC_NOT_AVAILABLE);
4205 }
4206
4207 int
4208 tuner_i2c_write_read(struct tuner_instance *tuner,
4209                   struct i2c_device_addr *w_dev_addr,
4210                   u16 w_count,
4211                   u8 *wData,
4212                   struct i2c_device_addr *r_dev_addr, u16 r_count, u8 *r_data)
4213 {
4214         pdrx_demod_instance_t demod;
4215         drxi2c_data_t i2c_data =
4216             { 2, w_dev_addr, w_count, wData, r_dev_addr, r_count, r_data };
4217
4218         demod = (pdrx_demod_instance_t) (tuner->my_common_attr->myUser_data);
4219
4220         return (ctrl_i2c_write_read(demod, &i2c_data));
4221 }
4222
4223 /* -------------------------------------------------------------------------- */
4224 /**
4225 * \brief Measure result of ADC synchronisation
4226 * \param demod demod instance
4227 * \param count (returned) count
4228 * \return int.
4229 * \retval DRX_STS_OK    Success
4230 * \retval DRX_STS_ERROR Failure: I2C error
4231 *
4232 */
4233 static int adc_sync_measurement(pdrx_demod_instance_t demod, u16 *count)
4234 {
4235         u16 data = 0;
4236         struct i2c_device_addr *dev_addr = NULL;
4237
4238         dev_addr = demod->my_i2c_dev_addr;
4239
4240         /* Start measurement */
4241         WR16(dev_addr, IQM_AF_COMM_EXEC__A, IQM_AF_COMM_EXEC_ACTIVE);
4242         WR16(dev_addr, IQM_AF_START_LOCK__A, 1);
4243
4244         /* Wait at least 3*128*(1/sysclk) <<< 1 millisec */
4245         CHK_ERROR(drxbsp_hst_sleep(1));
4246
4247         *count = 0;
4248         RR16(dev_addr, IQM_AF_PHASE0__A, &data);
4249         if (data == 127) {
4250                 *count = *count + 1;
4251         }
4252         RR16(dev_addr, IQM_AF_PHASE1__A, &data);
4253         if (data == 127) {
4254                 *count = *count + 1;
4255         }
4256         RR16(dev_addr, IQM_AF_PHASE2__A, &data);
4257         if (data == 127) {
4258                 *count = *count + 1;
4259         }
4260
4261         return (DRX_STS_OK);
4262 rw_error:
4263         return (DRX_STS_ERROR);
4264 }
4265
4266 /**
4267 * \brief Synchronize analog and digital clock domains
4268 * \param demod demod instance
4269 * \return int.
4270 * \retval DRX_STS_OK    Success
4271 * \retval DRX_STS_ERROR Failure: I2C error or failure to synchronize
4272 *
4273 * An IQM reset will also reset the results of this synchronization.
4274 * After an IQM reset this routine needs to be called again.
4275 *
4276 */
4277
4278 static int adc_synchronization(pdrx_demod_instance_t demod)
4279 {
4280         u16 count = 0;
4281         struct i2c_device_addr *dev_addr = NULL;
4282
4283         dev_addr = demod->my_i2c_dev_addr;
4284
4285         CHK_ERROR(adc_sync_measurement(demod, &count));
4286
4287         if (count == 1) {
4288                 /* Try sampling on a diffrent edge */
4289                 u16 clk_neg = 0;
4290
4291                 RR16(dev_addr, IQM_AF_CLKNEG__A, &clk_neg);
4292
4293                 clk_neg ^= IQM_AF_CLKNEG_CLKNEGDATA__M;
4294                 WR16(dev_addr, IQM_AF_CLKNEG__A, clk_neg);
4295
4296                 CHK_ERROR(adc_sync_measurement(demod, &count));
4297         }
4298
4299         if (count < 2) {
4300                 /* TODO: implement fallback scenarios */
4301                 return (DRX_STS_ERROR);
4302         }
4303
4304         return (DRX_STS_OK);
4305 rw_error:
4306         return (DRX_STS_ERROR);
4307 }
4308
4309 /**
4310 * \brief Configure IQM AF registers
4311 * \param demod instance of demodulator.
4312 * \param active
4313 * \return int.
4314 */
4315 static int iqm_set_af(pdrx_demod_instance_t demod, bool active)
4316 {
4317         u16 data = 0;
4318         struct i2c_device_addr *dev_addr = NULL;
4319         pdrxj_data_t ext_attr = NULL;
4320
4321         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
4322         dev_addr = demod->my_i2c_dev_addr;
4323
4324         /* Configure IQM */
4325         RR16(dev_addr, IQM_AF_STDBY__A, &data);
4326         if (!active) {
4327                 data &= ((~IQM_AF_STDBY_STDBY_ADC_A2_ACTIVE)
4328                          & (~IQM_AF_STDBY_STDBY_AMP_A2_ACTIVE)
4329                          & (~IQM_AF_STDBY_STDBY_PD_A2_ACTIVE)
4330                          & (~IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE)
4331                          & (~IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE)
4332                     );
4333         } else {                /* active */
4334
4335                 data |= (IQM_AF_STDBY_STDBY_ADC_A2_ACTIVE
4336                          | IQM_AF_STDBY_STDBY_AMP_A2_ACTIVE
4337                          | IQM_AF_STDBY_STDBY_PD_A2_ACTIVE
4338                          | IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE
4339                          | IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE);
4340         }
4341         WR16(dev_addr, IQM_AF_STDBY__A, data);
4342
4343         return (DRX_STS_OK);
4344 rw_error:
4345         return (DRX_STS_ERROR);
4346 }
4347
4348 /* -------------------------------------------------------------------------- */
4349 static int
4350 ctrl_set_cfg_atv_output(pdrx_demod_instance_t demod, p_drxj_cfg_atv_output_t output_cfg);
4351
4352 /**
4353 * \brief set configuration of pin-safe mode
4354 * \param demod instance of demodulator.
4355 * \param enable boolean; true: activate pin-safe mode, false: de-activate p.s.m.
4356 * \return int.
4357 */
4358 static int
4359 ctrl_set_cfg_pdr_safe_mode(pdrx_demod_instance_t demod, bool *enable)
4360 {
4361         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
4362         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
4363         pdrx_common_attr_t common_attr = (pdrx_common_attr_t) NULL;
4364
4365         if (enable == NULL) {
4366                 return (DRX_STS_INVALID_ARG);
4367         }
4368
4369         dev_addr = demod->my_i2c_dev_addr;
4370         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
4371         common_attr = demod->my_common_attr;
4372
4373         /*  Write magic word to enable pdr reg write  */
4374         WR16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
4375
4376         if (*enable == true) {
4377                 bool bridge_enabled = false;
4378
4379                 /* MPEG pins to input */
4380                 WR16(dev_addr, SIO_PDR_MSTRT_CFG__A, DRXJ_PIN_SAFE_MODE);
4381                 WR16(dev_addr, SIO_PDR_MERR_CFG__A, DRXJ_PIN_SAFE_MODE);
4382                 WR16(dev_addr, SIO_PDR_MCLK_CFG__A, DRXJ_PIN_SAFE_MODE);
4383                 WR16(dev_addr, SIO_PDR_MVAL_CFG__A, DRXJ_PIN_SAFE_MODE);
4384                 WR16(dev_addr, SIO_PDR_MD0_CFG__A, DRXJ_PIN_SAFE_MODE);
4385                 WR16(dev_addr, SIO_PDR_MD1_CFG__A, DRXJ_PIN_SAFE_MODE);
4386                 WR16(dev_addr, SIO_PDR_MD2_CFG__A, DRXJ_PIN_SAFE_MODE);
4387                 WR16(dev_addr, SIO_PDR_MD3_CFG__A, DRXJ_PIN_SAFE_MODE);
4388                 WR16(dev_addr, SIO_PDR_MD4_CFG__A, DRXJ_PIN_SAFE_MODE);
4389                 WR16(dev_addr, SIO_PDR_MD5_CFG__A, DRXJ_PIN_SAFE_MODE);
4390                 WR16(dev_addr, SIO_PDR_MD6_CFG__A, DRXJ_PIN_SAFE_MODE);
4391                 WR16(dev_addr, SIO_PDR_MD7_CFG__A, DRXJ_PIN_SAFE_MODE);
4392
4393                 /* PD_I2C_SDA2 Bridge off, Port2 Inactive
4394                    PD_I2C_SCL2 Bridge off, Port2 Inactive */
4395                 CHK_ERROR(ctrl_i2c_bridge(demod, &bridge_enabled));
4396                 WR16(dev_addr, SIO_PDR_I2C_SDA2_CFG__A, DRXJ_PIN_SAFE_MODE);
4397                 WR16(dev_addr, SIO_PDR_I2C_SCL2_CFG__A, DRXJ_PIN_SAFE_MODE);
4398
4399                 /*  PD_GPIO     Store and set to input
4400                    PD_VSYNC    Store and set to input
4401                    PD_SMA_RX   Store and set to input
4402                    PD_SMA_TX   Store and set to input */
4403                 RR16(dev_addr, SIO_PDR_GPIO_CFG__A,
4404                      &ext_attr->pdr_safe_restore_val_gpio);
4405                 RR16(dev_addr, SIO_PDR_VSYNC_CFG__A,
4406                      &ext_attr->pdr_safe_restore_val_v_sync);
4407                 RR16(dev_addr, SIO_PDR_SMA_RX_CFG__A,
4408                      &ext_attr->pdr_safe_restore_val_sma_rx);
4409                 RR16(dev_addr, SIO_PDR_SMA_TX_CFG__A,
4410                      &ext_attr->pdr_safe_restore_val_sma_tx);
4411                 WR16(dev_addr, SIO_PDR_GPIO_CFG__A, DRXJ_PIN_SAFE_MODE);
4412                 WR16(dev_addr, SIO_PDR_VSYNC_CFG__A, DRXJ_PIN_SAFE_MODE);
4413                 WR16(dev_addr, SIO_PDR_SMA_RX_CFG__A, DRXJ_PIN_SAFE_MODE);
4414                 WR16(dev_addr, SIO_PDR_SMA_TX_CFG__A, DRXJ_PIN_SAFE_MODE);
4415
4416                 /*  PD_RF_AGC   Analog DAC outputs, cannot be set to input or tristate!
4417                    PD_IF_AGC   Analog DAC outputs, cannot be set to input or tristate! */
4418                 CHK_ERROR(iqm_set_af(demod, false));
4419
4420                 /*  PD_CVBS     Analog DAC output, standby mode
4421                    PD_SIF      Analog DAC output, standby mode */
4422                 WR16(dev_addr, ATV_TOP_STDBY__A,
4423                      (ATV_TOP_STDBY_SIF_STDBY_STANDBY &
4424                       (~ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE)));
4425
4426                 /*  PD_I2S_CL   Input
4427                    PD_I2S_DA   Input
4428                    PD_I2S_WS   Input */
4429                 WR16(dev_addr, SIO_PDR_I2S_CL_CFG__A, DRXJ_PIN_SAFE_MODE);
4430                 WR16(dev_addr, SIO_PDR_I2S_DA_CFG__A, DRXJ_PIN_SAFE_MODE);
4431                 WR16(dev_addr, SIO_PDR_I2S_WS_CFG__A, DRXJ_PIN_SAFE_MODE);
4432         } else {
4433                 /* No need to restore MPEG pins;
4434                    is done in SetStandard/SetChannel */
4435
4436                 /* PD_I2C_SDA2 Port2 active
4437                    PD_I2C_SCL2 Port2 active */
4438                 WR16(dev_addr, SIO_PDR_I2C_SDA2_CFG__A,
4439                      SIO_PDR_I2C_SDA2_CFG__PRE);
4440                 WR16(dev_addr, SIO_PDR_I2C_SCL2_CFG__A,
4441                      SIO_PDR_I2C_SCL2_CFG__PRE);
4442
4443                 /*  PD_GPIO     Restore
4444                    PD_VSYNC    Restore
4445                    PD_SMA_RX   Restore
4446                    PD_SMA_TX   Restore */
4447                 WR16(dev_addr, SIO_PDR_GPIO_CFG__A,
4448                      ext_attr->pdr_safe_restore_val_gpio);
4449                 WR16(dev_addr, SIO_PDR_VSYNC_CFG__A,
4450                      ext_attr->pdr_safe_restore_val_v_sync);
4451                 WR16(dev_addr, SIO_PDR_SMA_RX_CFG__A,
4452                      ext_attr->pdr_safe_restore_val_sma_rx);
4453                 WR16(dev_addr, SIO_PDR_SMA_TX_CFG__A,
4454                      ext_attr->pdr_safe_restore_val_sma_tx);
4455
4456                 /*  PD_RF_AGC, PD_IF_AGC
4457                    No need to restore; will be restored in SetStandard/SetChannel */
4458
4459                 /*  PD_CVBS, PD_SIF
4460                    No need to restore; will be restored in SetStandard/SetChannel */
4461
4462                 /*  PD_I2S_CL, PD_I2S_DA, PD_I2S_WS
4463                    Should be restored via DRX_CTRL_SET_AUD */
4464         }
4465
4466         /*  Write magic word to disable pdr reg write */
4467         WR16(dev_addr, SIO_TOP_COMM_KEY__A, 0x0000);
4468         ext_attr->pdr_safe_mode = *enable;
4469
4470         return (DRX_STS_OK);
4471
4472 rw_error:
4473         return (DRX_STS_ERROR);
4474 }
4475
4476 /* -------------------------------------------------------------------------- */
4477
4478 /**
4479 * \brief get configuration of pin-safe mode
4480 * \param demod instance of demodulator.
4481 * \param enable boolean indicating whether pin-safe mode is active
4482 * \return int.
4483 */
4484 static int
4485 ctrl_get_cfg_pdr_safe_mode(pdrx_demod_instance_t demod, bool *enabled)
4486 {
4487         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
4488
4489         if (enabled == NULL) {
4490                 return (DRX_STS_INVALID_ARG);
4491         }
4492
4493         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
4494         *enabled = ext_attr->pdr_safe_mode;
4495
4496         return (DRX_STS_OK);
4497 }
4498
4499 /**
4500 * \brief Verifies whether microcode can be loaded.
4501 * \param demod Demodulator instance.
4502 * \return int.
4503 */
4504 static int ctrl_validate_u_code(pdrx_demod_instance_t demod)
4505 {
4506         u32 mc_dev, mc_patch;
4507         u16 ver_type;
4508
4509         /* Check device.
4510          *  Disallow microcode if:
4511          *   - MC has version record AND
4512          *   - device ID in version record is not 0 AND
4513          *   - product ID in version record's device ID does not
4514          *     match DRXJ1 product IDs - 0x393 or 0x394
4515          */
4516         DRX_GET_MCVERTYPE(demod, ver_type);
4517         DRX_GET_MCDEV(demod, mc_dev);
4518         DRX_GET_MCPATCH(demod, mc_patch);
4519
4520         if (DRX_ISMCVERTYPE(ver_type)) {
4521                 if ((mc_dev != 0) &&
4522                     (((mc_dev >> 16) & 0xFFF) != 0x393) &&
4523                     (((mc_dev >> 16) & 0xFFF) != 0x394)) {
4524                         /* Microcode is marked for another device - error */
4525                         return DRX_STS_INVALID_ARG;
4526                 } else if (mc_patch != 0) {
4527                         /* Patch not allowed because there is no ROM */
4528                         return DRX_STS_INVALID_ARG;
4529                 }
4530         }
4531
4532         /* Everything else: OK */
4533         return DRX_STS_OK;
4534 }
4535
4536 /*============================================================================*/
4537 /*==                      END AUXILIARY FUNCTIONS                           ==*/
4538 /*============================================================================*/
4539
4540 /*============================================================================*/
4541 /*============================================================================*/
4542 /*==                8VSB & QAM COMMON DATAPATH FUNCTIONS                    ==*/
4543 /*============================================================================*/
4544 /*============================================================================*/
4545 /**
4546 * \fn int init_agc ()
4547 * \brief Initialize AGC for all standards.
4548 * \param demod instance of demodulator.
4549 * \param channel pointer to channel data.
4550 * \return int.
4551 */
4552 static int init_agc(pdrx_demod_instance_t demod)
4553 {
4554         struct i2c_device_addr *dev_addr = NULL;
4555         pdrx_common_attr_t common_attr = NULL;
4556         pdrxj_data_t ext_attr = NULL;
4557         p_drxj_cfg_agc_t p_agc_rf_settings = NULL;
4558         p_drxj_cfg_agc_t p_agc_if_settings = NULL;
4559         u16 ingain_tgt_max = 0;
4560         u16 clp_dir_to = 0;
4561         u16 sns_sum_max = 0;
4562         u16 clp_sum_max = 0;
4563         u16 sns_dir_to = 0;
4564         u16 ki_innergain_min = 0;
4565         u16 agc_ki = 0;
4566         u16 ki_max = 0;
4567         u16 if_iaccu_hi_tgt_min = 0;
4568         u16 data = 0;
4569         u16 agc_kiDgain = 0;
4570         u16 ki_min = 0;
4571         u16 clp_ctrl_mode = 0;
4572         u16 agc_rf = 0;
4573         u16 agc_if = 0;
4574         dev_addr = demod->my_i2c_dev_addr;
4575         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
4576         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
4577
4578         switch (ext_attr->standard) {
4579         case DRX_STANDARD_8VSB:
4580                 clp_sum_max = 1023;
4581                 clp_dir_to = (u16) (-9);
4582                 sns_sum_max = 1023;
4583                 sns_dir_to = (u16) (-9);
4584                 ki_innergain_min = (u16) (-32768);
4585                 ki_max = 0x032C;
4586                 agc_kiDgain = 0xC;
4587                 if_iaccu_hi_tgt_min = 2047;
4588                 ki_min = 0x0117;
4589                 ingain_tgt_max = 16383;
4590                 clp_ctrl_mode = 0;
4591                 WR16(dev_addr, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff);
4592                 WR16(dev_addr, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0);
4593                 WR16(dev_addr, SCU_RAM_AGC_CLP_SUM__A, 0);
4594                 WR16(dev_addr, SCU_RAM_AGC_CLP_CYCCNT__A, 0);
4595                 WR16(dev_addr, SCU_RAM_AGC_CLP_DIR_WD__A, 0);
4596                 WR16(dev_addr, SCU_RAM_AGC_CLP_DIR_STP__A, 1);
4597                 WR16(dev_addr, SCU_RAM_AGC_SNS_SUM__A, 0);
4598                 WR16(dev_addr, SCU_RAM_AGC_SNS_CYCCNT__A, 0);
4599                 WR16(dev_addr, SCU_RAM_AGC_SNS_DIR_WD__A, 0);
4600                 WR16(dev_addr, SCU_RAM_AGC_SNS_DIR_STP__A, 1);
4601                 WR16(dev_addr, SCU_RAM_AGC_INGAIN__A, 1024);
4602                 WR16(dev_addr, SCU_RAM_VSB_AGC_POW_TGT__A, 22600);
4603                 WR16(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, 13200);
4604                 p_agc_if_settings = &(ext_attr->vsb_if_agc_cfg);
4605                 p_agc_rf_settings = &(ext_attr->vsb_rf_agc_cfg);
4606                 break;
4607 #ifndef DRXJ_VSB_ONLY
4608         case DRX_STANDARD_ITU_A:
4609         case DRX_STANDARD_ITU_C:
4610         case DRX_STANDARD_ITU_B:
4611                 ingain_tgt_max = 5119;
4612                 clp_sum_max = 1023;
4613                 clp_dir_to = (u16) (-5);
4614                 sns_sum_max = 127;
4615                 sns_dir_to = (u16) (-3);
4616                 ki_innergain_min = 0;
4617                 ki_max = 0x0657;
4618                 if_iaccu_hi_tgt_min = 2047;
4619                 agc_kiDgain = 0x7;
4620                 ki_min = 0x0117;
4621                 clp_ctrl_mode = 0;
4622                 WR16(dev_addr, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff);
4623                 WR16(dev_addr, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0);
4624                 WR16(dev_addr, SCU_RAM_AGC_CLP_SUM__A, 0);
4625                 WR16(dev_addr, SCU_RAM_AGC_CLP_CYCCNT__A, 0);
4626                 WR16(dev_addr, SCU_RAM_AGC_CLP_DIR_WD__A, 0);
4627                 WR16(dev_addr, SCU_RAM_AGC_CLP_DIR_STP__A, 1);
4628                 WR16(dev_addr, SCU_RAM_AGC_SNS_SUM__A, 0);
4629                 WR16(dev_addr, SCU_RAM_AGC_SNS_CYCCNT__A, 0);
4630                 WR16(dev_addr, SCU_RAM_AGC_SNS_DIR_WD__A, 0);
4631                 WR16(dev_addr, SCU_RAM_AGC_SNS_DIR_STP__A, 1);
4632                 p_agc_if_settings = &(ext_attr->qam_if_agc_cfg);
4633                 p_agc_rf_settings = &(ext_attr->qam_rf_agc_cfg);
4634                 WR16(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, p_agc_if_settings->top);
4635
4636                 RR16(dev_addr, SCU_RAM_AGC_KI__A, &agc_ki);
4637                 agc_ki &= 0xf000;
4638                 WR16(dev_addr, SCU_RAM_AGC_KI__A, agc_ki);
4639                 break;
4640 #endif
4641 #ifndef DRXJ_DIGITAL_ONLY
4642         case DRX_STANDARD_FM:
4643                 clp_sum_max = 1023;
4644                 sns_sum_max = 1023;
4645                 ki_innergain_min = (u16) (-32768);
4646                 if_iaccu_hi_tgt_min = 2047;
4647                 agc_kiDgain = 0x7;
4648                 ki_min = 0x0225;
4649                 ki_max = 0x0547;
4650                 clp_dir_to = (u16) (-9);
4651                 sns_dir_to = (u16) (-9);
4652                 ingain_tgt_max = 9000;
4653                 clp_ctrl_mode = 1;
4654                 p_agc_if_settings = &(ext_attr->atv_if_agc_cfg);
4655                 p_agc_rf_settings = &(ext_attr->atv_rf_agc_cfg);
4656                 WR16(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, p_agc_if_settings->top);
4657                 break;
4658         case DRX_STANDARD_NTSC:
4659         case DRX_STANDARD_PAL_SECAM_BG:
4660         case DRX_STANDARD_PAL_SECAM_DK:
4661         case DRX_STANDARD_PAL_SECAM_I:
4662                 clp_sum_max = 1023;
4663                 sns_sum_max = 1023;
4664                 ki_innergain_min = (u16) (-32768);
4665                 if_iaccu_hi_tgt_min = 2047;
4666                 agc_kiDgain = 0x7;
4667                 ki_min = 0x0225;
4668                 ki_max = 0x0547;
4669                 clp_dir_to = (u16) (-9);
4670                 ingain_tgt_max = 9000;
4671                 p_agc_if_settings = &(ext_attr->atv_if_agc_cfg);
4672                 p_agc_rf_settings = &(ext_attr->atv_rf_agc_cfg);
4673                 sns_dir_to = (u16) (-9);
4674                 clp_ctrl_mode = 1;
4675                 WR16(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, p_agc_if_settings->top);
4676                 break;
4677         case DRX_STANDARD_PAL_SECAM_L:
4678         case DRX_STANDARD_PAL_SECAM_LP:
4679                 clp_sum_max = 1023;
4680                 sns_sum_max = 1023;
4681                 ki_innergain_min = (u16) (-32768);
4682                 if_iaccu_hi_tgt_min = 2047;
4683                 agc_kiDgain = 0x7;
4684                 ki_min = 0x0225;
4685                 ki_max = 0x0547;
4686                 clp_dir_to = (u16) (-9);
4687                 sns_dir_to = (u16) (-9);
4688                 ingain_tgt_max = 9000;
4689                 clp_ctrl_mode = 1;
4690                 p_agc_if_settings = &(ext_attr->atv_if_agc_cfg);
4691                 p_agc_rf_settings = &(ext_attr->atv_rf_agc_cfg);
4692                 WR16(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, p_agc_if_settings->top);
4693                 break;
4694 #endif
4695         default:
4696                 return (DRX_STS_INVALID_ARG);
4697         }
4698
4699         /* for new AGC interface */
4700         WR16(dev_addr, SCU_RAM_AGC_INGAIN_TGT_MIN__A, p_agc_if_settings->top);
4701         WR16(dev_addr, SCU_RAM_AGC_INGAIN__A, p_agc_if_settings->top);  /* Gain fed from inner to outer AGC */
4702         WR16(dev_addr, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingain_tgt_max);
4703         WR16(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, if_iaccu_hi_tgt_min);
4704         WR16(dev_addr, SCU_RAM_AGC_IF_IACCU_HI__A, 0);  /* set to p_agc_settings->top before */
4705         WR16(dev_addr, SCU_RAM_AGC_IF_IACCU_LO__A, 0);
4706         WR16(dev_addr, SCU_RAM_AGC_RF_IACCU_HI__A, 0);
4707         WR16(dev_addr, SCU_RAM_AGC_RF_IACCU_LO__A, 0);
4708         WR16(dev_addr, SCU_RAM_AGC_RF_MAX__A, 32767);
4709         WR16(dev_addr, SCU_RAM_AGC_CLP_SUM_MAX__A, clp_sum_max);
4710         WR16(dev_addr, SCU_RAM_AGC_SNS_SUM_MAX__A, sns_sum_max);
4711         WR16(dev_addr, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, ki_innergain_min);
4712         WR16(dev_addr, SCU_RAM_AGC_FAST_SNS_CTRL_DELAY__A, 50);
4713         WR16(dev_addr, SCU_RAM_AGC_KI_CYCLEN__A, 500);
4714         WR16(dev_addr, SCU_RAM_AGC_SNS_CYCLEN__A, 500);
4715         WR16(dev_addr, SCU_RAM_AGC_KI_MAXMINGAIN_TH__A, 20);
4716         WR16(dev_addr, SCU_RAM_AGC_KI_MIN__A, ki_min);
4717         WR16(dev_addr, SCU_RAM_AGC_KI_MAX__A, ki_max);
4718         WR16(dev_addr, SCU_RAM_AGC_KI_RED__A, 0);
4719         WR16(dev_addr, SCU_RAM_AGC_CLP_SUM_MIN__A, 8);
4720         WR16(dev_addr, SCU_RAM_AGC_CLP_CYCLEN__A, 500);
4721         WR16(dev_addr, SCU_RAM_AGC_CLP_DIR_TO__A, clp_dir_to);
4722         WR16(dev_addr, SCU_RAM_AGC_SNS_SUM_MIN__A, 8);
4723         WR16(dev_addr, SCU_RAM_AGC_SNS_DIR_TO__A, sns_dir_to);
4724         WR16(dev_addr, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, 50);
4725         WR16(dev_addr, SCU_RAM_AGC_CLP_CTRL_MODE__A, clp_ctrl_mode);
4726
4727         agc_rf = 0x800 + p_agc_rf_settings->cut_off_current;
4728         if (common_attr->tuner_rf_agc_pol == true) {
4729                 agc_rf = 0x87ff - agc_rf;
4730         }
4731
4732         agc_if = 0x800;
4733         if (common_attr->tuner_if_agc_pol == true) {
4734                 agc_rf = 0x87ff - agc_rf;
4735         }
4736
4737         WR16(dev_addr, IQM_AF_AGC_RF__A, agc_rf);
4738         WR16(dev_addr, IQM_AF_AGC_IF__A, agc_if);
4739
4740         /* Set/restore Ki DGAIN factor */
4741         RR16(dev_addr, SCU_RAM_AGC_KI__A, &data);
4742         data &= ~SCU_RAM_AGC_KI_DGAIN__M;
4743         data |= (agc_kiDgain << SCU_RAM_AGC_KI_DGAIN__B);
4744         WR16(dev_addr, SCU_RAM_AGC_KI__A, data);
4745
4746         return (DRX_STS_OK);
4747 rw_error:
4748         return (DRX_STS_ERROR);
4749 }
4750
4751 /**
4752 * \fn int set_frequency ()
4753 * \brief Set frequency shift.
4754 * \param demod instance of demodulator.
4755 * \param channel pointer to channel data.
4756 * \param tuner_freq_offset residual frequency from tuner.
4757 * \return int.
4758 */
4759 static int
4760 set_frequency(pdrx_demod_instance_t demod,
4761              pdrx_channel_t channel, s32 tuner_freq_offset)
4762 {
4763         struct i2c_device_addr *dev_addr = NULL;
4764         pdrx_common_attr_t common_attr = NULL;
4765         s32 sampling_frequency = 0;
4766         s32 frequency_shift = 0;
4767         s32 if_freq_actual = 0;
4768         s32 rf_freq_residual = 0;
4769         s32 adc_freq = 0;
4770         s32 intermediate_freq = 0;
4771         u32 iqm_fs_rate_ofs = 0;
4772         pdrxj_data_t ext_attr = NULL;
4773         bool adc_flip = true;
4774         bool select_pos_image = false;
4775         bool rf_mirror = false;
4776         bool tuner_mirror = true;
4777         bool image_to_select = true;
4778         s32 fm_frequency_shift = 0;
4779
4780         dev_addr = demod->my_i2c_dev_addr;
4781         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
4782         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
4783         rf_freq_residual = -1 * tuner_freq_offset;
4784         rf_mirror = (ext_attr->mirror == DRX_MIRROR_YES) ? true : false;
4785         tuner_mirror = demod->my_common_attr->mirror_freq_spect ? false : true;
4786         /*
4787            Program frequency shifter
4788            No need to account for mirroring on RF
4789          */
4790         switch (ext_attr->standard) {
4791         case DRX_STANDARD_ITU_A:        /* fallthrough */
4792         case DRX_STANDARD_ITU_C:        /* fallthrough */
4793         case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
4794         case DRX_STANDARD_8VSB:
4795                 select_pos_image = true;
4796                 break;
4797         case DRX_STANDARD_FM:
4798                 /* After IQM FS sound carrier must appear at 4 Mhz in spect.
4799                    Sound carrier is already 3Mhz above centre frequency due
4800                    to tuner setting so now add an extra shift of 1MHz... */
4801                 fm_frequency_shift = 1000;
4802         case DRX_STANDARD_ITU_B:        /* fallthrough */
4803         case DRX_STANDARD_NTSC: /* fallthrough */
4804         case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
4805         case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
4806         case DRX_STANDARD_PAL_SECAM_I:  /* fallthrough */
4807         case DRX_STANDARD_PAL_SECAM_L:
4808                 select_pos_image = false;
4809                 break;
4810         default:
4811                 return (DRX_STS_INVALID_ARG);
4812         }
4813         intermediate_freq = demod->my_common_attr->intermediate_freq;
4814         sampling_frequency = demod->my_common_attr->sys_clock_freq / 3;
4815         if (tuner_mirror == true) {
4816                 /* tuner doesn't mirror */
4817                 if_freq_actual =
4818                     intermediate_freq + rf_freq_residual + fm_frequency_shift;
4819         } else {
4820                 /* tuner mirrors */
4821                 if_freq_actual =
4822                     intermediate_freq - rf_freq_residual - fm_frequency_shift;
4823         }
4824         if (if_freq_actual > sampling_frequency / 2) {
4825                 /* adc mirrors */
4826                 adc_freq = sampling_frequency - if_freq_actual;
4827                 adc_flip = true;
4828         } else {
4829                 /* adc doesn't mirror */
4830                 adc_freq = if_freq_actual;
4831                 adc_flip = false;
4832         }
4833
4834         frequency_shift = adc_freq;
4835         image_to_select =
4836             (bool) (rf_mirror ^ tuner_mirror ^ adc_flip ^ select_pos_image);
4837         iqm_fs_rate_ofs = frac28(frequency_shift, sampling_frequency);
4838
4839         if (image_to_select)
4840                 iqm_fs_rate_ofs = ~iqm_fs_rate_ofs + 1;
4841
4842         /* Program frequency shifter with tuner offset compensation */
4843         /* frequency_shift += tuner_freq_offset; TODO */
4844         WR32(dev_addr, IQM_FS_RATE_OFS_LO__A, iqm_fs_rate_ofs);
4845         ext_attr->iqm_fs_rate_ofs = iqm_fs_rate_ofs;
4846         ext_attr->pos_image = (bool) (rf_mirror ^ tuner_mirror ^ select_pos_image);
4847
4848         return (DRX_STS_OK);
4849 rw_error:
4850         return (DRX_STS_ERROR);
4851 }
4852
4853 /**
4854 * \fn int get_sig_strength()
4855 * \brief Retrieve signal strength for VSB and QAM.
4856 * \param demod Pointer to demod instance
4857 * \param u16-t Pointer to signal strength data; range 0, .. , 100.
4858 * \return int.
4859 * \retval DRX_STS_OK sig_strength contains valid data.
4860 * \retval DRX_STS_INVALID_ARG sig_strength is NULL.
4861 * \retval DRX_STS_ERROR Erroneous data, sig_strength contains invalid data.
4862 */
4863 #define DRXJ_AGC_TOP    0x2800
4864 #define DRXJ_AGC_SNS    0x1600
4865 #define DRXJ_RFAGC_MAX  0x3fff
4866 #define DRXJ_RFAGC_MIN  0x800
4867
4868 static int get_sig_strength(pdrx_demod_instance_t demod, u16 *sig_strength)
4869 {
4870         u16 rf_gain = 0;
4871         u16 if_gain = 0;
4872         u16 if_agc_sns = 0;
4873         u16 if_agc_top = 0;
4874         u16 rf_agc_max = 0;
4875         u16 rf_agc_min = 0;
4876         pdrxj_data_t ext_attr = NULL;
4877         struct i2c_device_addr *dev_addr = NULL;
4878
4879         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
4880         dev_addr = demod->my_i2c_dev_addr;
4881
4882         RR16(dev_addr, IQM_AF_AGC_IF__A, &if_gain);
4883         if_gain &= IQM_AF_AGC_IF__M;
4884         RR16(dev_addr, IQM_AF_AGC_RF__A, &rf_gain);
4885         rf_gain &= IQM_AF_AGC_RF__M;
4886
4887         if_agc_sns = DRXJ_AGC_SNS;
4888         if_agc_top = DRXJ_AGC_TOP;
4889         rf_agc_max = DRXJ_RFAGC_MAX;
4890         rf_agc_min = DRXJ_RFAGC_MIN;
4891
4892         if (if_gain > if_agc_top) {
4893                 if (rf_gain > rf_agc_max)
4894                         *sig_strength = 100;
4895                 else if (rf_gain > rf_agc_min) {
4896                         CHK_ZERO(rf_agc_max - rf_agc_min);
4897                         *sig_strength =
4898                             75 + 25 * (rf_gain - rf_agc_min) / (rf_agc_max -
4899                                                              rf_agc_min);
4900                 } else
4901                         *sig_strength = 75;
4902         } else if (if_gain > if_agc_sns) {
4903                 CHK_ZERO(if_agc_top - if_agc_sns);
4904                 *sig_strength =
4905                     20 + 55 * (if_gain - if_agc_sns) / (if_agc_top - if_agc_sns);
4906         } else {
4907                 CHK_ZERO(if_agc_sns);
4908                 *sig_strength = (20 * if_gain / if_agc_sns);
4909         }
4910
4911         return (DRX_STS_OK);
4912 rw_error:
4913         return (DRX_STS_ERROR);
4914 }
4915
4916 /**
4917 * \fn int get_acc_pkt_err()
4918 * \brief Retrieve signal strength for VSB and QAM.
4919 * \param demod Pointer to demod instance
4920 * \param packet_err Pointer to packet error
4921 * \return int.
4922 * \retval DRX_STS_OK sig_strength contains valid data.
4923 * \retval DRX_STS_INVALID_ARG sig_strength is NULL.
4924 * \retval DRX_STS_ERROR Erroneous data, sig_strength contains invalid data.
4925 */
4926 #ifdef DRXJ_SIGNAL_ACCUM_ERR
4927 static int get_acc_pkt_err(pdrx_demod_instance_t demod, u16 *packet_err)
4928 {
4929         static u16 pkt_err;
4930         static u16 last_pkt_err;
4931         u16 data = 0;
4932         pdrxj_data_t ext_attr = NULL;
4933         struct i2c_device_addr *dev_addr = NULL;
4934
4935         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
4936         dev_addr = demod->my_i2c_dev_addr;
4937
4938         RR16(dev_addr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, &data);
4939         if (ext_attr->reset_pkt_err_acc == true) {
4940                 last_pkt_err = data;
4941                 pkt_err = 0;
4942                 ext_attr->reset_pkt_err_acc = false;
4943         }
4944
4945         if (data < last_pkt_err) {
4946                 pkt_err += 0xffff - last_pkt_err;
4947                 pkt_err += data;
4948         } else {
4949                 pkt_err += (data - last_pkt_err);
4950         }
4951         *packet_err = pkt_err;
4952         last_pkt_err = data;
4953
4954         return (DRX_STS_OK);
4955 rw_error:
4956         return (DRX_STS_ERROR);
4957 }
4958 #endif
4959
4960 /**
4961 * \fn int ResetAccPktErr()
4962 * \brief Reset Accumulating packet error count.
4963 * \param demod Pointer to demod instance
4964 * \return int.
4965 * \retval DRX_STS_OK.
4966 * \retval DRX_STS_ERROR Erroneous data.
4967 */
4968 static int ctrl_set_cfg_reset_pkt_err(pdrx_demod_instance_t demod)
4969 {
4970 #ifdef DRXJ_SIGNAL_ACCUM_ERR
4971         pdrxj_data_t ext_attr = NULL;
4972         u16 packet_error = 0;
4973
4974         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
4975         ext_attr->reset_pkt_err_acc = true;
4976         /* call to reset counter */
4977         CHK_ERROR(get_acc_pkt_err(demod, &packet_error));
4978
4979         return (DRX_STS_OK);
4980 rw_error:
4981 #endif
4982         return (DRX_STS_ERROR);
4983 }
4984
4985 /**
4986 * \fn static short get_str_freq_offset()
4987 * \brief Get symbol rate offset in QAM & 8VSB mode
4988 * \return Error code
4989 */
4990 static int get_str_freq_offset(pdrx_demod_instance_t demod, s32 *str_freq)
4991 {
4992         u32 symbol_frequency_ratio = 0;
4993         u32 symbol_nom_frequency_ratio = 0;
4994
4995         enum drx_standard standard = DRX_STANDARD_UNKNOWN;
4996         struct i2c_device_addr *dev_addr = NULL;
4997         pdrxj_data_t ext_attr = NULL;
4998
4999         dev_addr = demod->my_i2c_dev_addr;
5000         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
5001         standard = ext_attr->standard;
5002
5003         ARR32(dev_addr, IQM_RC_RATE_LO__A, &symbol_frequency_ratio);
5004         symbol_nom_frequency_ratio = ext_attr->iqm_rc_rate_ofs;
5005
5006         if (symbol_frequency_ratio > symbol_nom_frequency_ratio)
5007                 *str_freq =
5008                     -1 *
5009                     frac_times1e6((symbol_frequency_ratio -
5010                                   symbol_nom_frequency_ratio),
5011                                  (symbol_frequency_ratio + (1 << 23)));
5012         else
5013                 *str_freq =
5014                     frac_times1e6((symbol_nom_frequency_ratio -
5015                                   symbol_frequency_ratio),
5016                                  (symbol_frequency_ratio + (1 << 23)));
5017
5018         return (DRX_STS_OK);
5019 rw_error:
5020         return (DRX_STS_ERROR);
5021 }
5022
5023 /**
5024 * \fn static short get_ctl_freq_offset
5025 * \brief Get the value of ctl_freq in QAM & ATSC mode
5026 * \return Error code
5027 */
5028 static int get_ctl_freq_offset(pdrx_demod_instance_t demod, s32 *ctl_freq)
5029 {
5030         s32 sampling_frequency = 0;
5031         s32 current_frequency = 0;
5032         s32 nominal_frequency = 0;
5033         s32 carrier_frequency_shift = 0;
5034         s32 sign = 1;
5035         u32 data64hi = 0;
5036         u32 data64lo = 0;
5037         pdrxj_data_t ext_attr = NULL;
5038         pdrx_common_attr_t common_attr = NULL;
5039         struct i2c_device_addr *dev_addr = NULL;
5040
5041         dev_addr = demod->my_i2c_dev_addr;
5042         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
5043         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
5044
5045         sampling_frequency = common_attr->sys_clock_freq / 3;
5046
5047         /* both registers are sign extended */
5048         nominal_frequency = ext_attr->iqm_fs_rate_ofs;
5049         ARR32(dev_addr, IQM_FS_RATE_LO__A, (u32 *) &current_frequency);
5050
5051         if (ext_attr->pos_image == true) {
5052                 /* negative image */
5053                 carrier_frequency_shift = nominal_frequency - current_frequency;
5054         } else {
5055                 /* positive image */
5056                 carrier_frequency_shift = current_frequency - nominal_frequency;
5057         }
5058
5059         /* carrier Frequency Shift In Hz */
5060         if (carrier_frequency_shift < 0) {
5061                 sign = -1;
5062                 carrier_frequency_shift *= sign;
5063         }
5064
5065         /* *ctl_freq = carrier_frequency_shift * 50.625e6 / (1 << 28); */
5066         mult32(carrier_frequency_shift, sampling_frequency, &data64hi, &data64lo);
5067         *ctl_freq =
5068             (s32) ((((data64lo >> 28) & 0xf) | (data64hi << 4)) * sign);
5069
5070         return (DRX_STS_OK);
5071 rw_error:
5072         return (DRX_STS_ERROR);
5073 }
5074
5075 /*============================================================================*/
5076
5077 /**
5078 * \fn int set_agc_rf ()
5079 * \brief Configure RF AGC
5080 * \param demod instance of demodulator.
5081 * \param agc_settings AGC configuration structure
5082 * \return int.
5083 */
5084 static int
5085 set_agc_rf(pdrx_demod_instance_t demod, p_drxj_cfg_agc_t agc_settings, bool atomic)
5086 {
5087         struct i2c_device_addr *dev_addr = NULL;
5088         pdrxj_data_t ext_attr = NULL;
5089         p_drxj_cfg_agc_t p_agc_settings = NULL;
5090         pdrx_common_attr_t common_attr = NULL;
5091         drx_write_reg16func_t scu_wr16 = NULL;
5092         drx_read_reg16func_t scu_rr16 = NULL;
5093
5094         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
5095         dev_addr = demod->my_i2c_dev_addr;
5096         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
5097
5098         if (atomic) {
5099                 scu_rr16 = drxj_dap_scu_atomic_read_reg16;
5100                 scu_wr16 = drxj_dap_scu_atomic_write_reg16;
5101         } else {
5102                 scu_rr16 = DRXJ_DAP.read_reg16func;
5103                 scu_wr16 = DRXJ_DAP.write_reg16func;
5104         }
5105
5106         /* Configure AGC only if standard is currently active */
5107         if ((ext_attr->standard == agc_settings->standard) ||
5108             (DRXJ_ISQAMSTD(ext_attr->standard) &&
5109              DRXJ_ISQAMSTD(agc_settings->standard)) ||
5110             (DRXJ_ISATVSTD(ext_attr->standard) &&
5111              DRXJ_ISATVSTD(agc_settings->standard))) {
5112                 u16 data = 0;
5113
5114                 switch (agc_settings->ctrl_mode) {
5115                 case DRX_AGC_CTRL_AUTO:
5116
5117                         /* Enable RF AGC DAC */
5118                         RR16(dev_addr, IQM_AF_STDBY__A, &data);
5119                         data |= IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE;
5120                         WR16(dev_addr, IQM_AF_STDBY__A, data);
5121
5122                         /* Enable SCU RF AGC loop */
5123                         CHK_ERROR((*scu_rr16)
5124                                   (dev_addr, SCU_RAM_AGC_KI__A, &data, 0));
5125                         data &= ~SCU_RAM_AGC_KI_RF__M;
5126                         if (ext_attr->standard == DRX_STANDARD_8VSB) {
5127                                 data |= (2 << SCU_RAM_AGC_KI_RF__B);
5128                         } else if (DRXJ_ISQAMSTD(ext_attr->standard)) {
5129                                 data |= (5 << SCU_RAM_AGC_KI_RF__B);
5130                         } else {
5131                                 data |= (4 << SCU_RAM_AGC_KI_RF__B);
5132                         }
5133
5134                         if (common_attr->tuner_rf_agc_pol) {
5135                                 data |= SCU_RAM_AGC_KI_INV_RF_POL__M;
5136                         } else {
5137                                 data &= ~SCU_RAM_AGC_KI_INV_RF_POL__M;
5138                         }
5139                         CHK_ERROR((*scu_wr16)
5140                                   (dev_addr, SCU_RAM_AGC_KI__A, data, 0));
5141
5142                         /* Set speed ( using complementary reduction value ) */
5143                         CHK_ERROR((*scu_rr16)
5144                                   (dev_addr, SCU_RAM_AGC_KI_RED__A, &data, 0));
5145                         data &= ~SCU_RAM_AGC_KI_RED_RAGC_RED__M;
5146                         CHK_ERROR((*scu_wr16) (dev_addr, SCU_RAM_AGC_KI_RED__A,
5147                                               (~
5148                                                (agc_settings->
5149                                                 speed <<
5150                                                 SCU_RAM_AGC_KI_RED_RAGC_RED__B)
5151 & SCU_RAM_AGC_KI_RED_RAGC_RED__M)
5152                                               | data, 0));
5153
5154                         if (agc_settings->standard == DRX_STANDARD_8VSB)
5155                                 p_agc_settings = &(ext_attr->vsb_if_agc_cfg);
5156                         else if (DRXJ_ISQAMSTD(agc_settings->standard))
5157                                 p_agc_settings = &(ext_attr->qam_if_agc_cfg);
5158                         else if (DRXJ_ISATVSTD(agc_settings->standard))
5159                                 p_agc_settings = &(ext_attr->atv_if_agc_cfg);
5160                         else
5161                                 return (DRX_STS_INVALID_ARG);
5162
5163                         /* Set TOP, only if IF-AGC is in AUTO mode */
5164                         if (p_agc_settings->ctrl_mode == DRX_AGC_CTRL_AUTO) {
5165                                 CHK_ERROR((*scu_wr16)
5166                                           (dev_addr,
5167                                            SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A,
5168                                            agc_settings->top, 0));
5169                                 CHK_ERROR((*scu_wr16)
5170                                           (dev_addr,
5171                                            SCU_RAM_AGC_IF_IACCU_HI_TGT__A,
5172                                            agc_settings->top, 0));
5173                         }
5174
5175                         /* Cut-Off current */
5176                         CHK_ERROR((*scu_wr16)
5177                                   (dev_addr, SCU_RAM_AGC_RF_IACCU_HI_CO__A,
5178                                    agc_settings->cut_off_current, 0));
5179                         break;
5180                 case DRX_AGC_CTRL_USER:
5181
5182                         /* Enable RF AGC DAC */
5183                         RR16(dev_addr, IQM_AF_STDBY__A, &data);
5184                         data |= IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE;
5185                         WR16(dev_addr, IQM_AF_STDBY__A, data);
5186
5187                         /* Disable SCU RF AGC loop */
5188                         CHK_ERROR((*scu_rr16)
5189                                   (dev_addr, SCU_RAM_AGC_KI__A, &data, 0));
5190                         data &= ~SCU_RAM_AGC_KI_RF__M;
5191                         if (common_attr->tuner_rf_agc_pol) {
5192                                 data |= SCU_RAM_AGC_KI_INV_RF_POL__M;
5193                         } else {
5194                                 data &= ~SCU_RAM_AGC_KI_INV_RF_POL__M;
5195                         }
5196                         CHK_ERROR((*scu_wr16)
5197                                   (dev_addr, SCU_RAM_AGC_KI__A, data, 0));
5198
5199                         /* Write value to output pin */
5200                         CHK_ERROR((*scu_wr16)
5201                                   (dev_addr, SCU_RAM_AGC_RF_IACCU_HI__A,
5202                                    agc_settings->output_level, 0));
5203                         break;
5204                 case DRX_AGC_CTRL_OFF:
5205
5206                         /* Disable RF AGC DAC */
5207                         RR16(dev_addr, IQM_AF_STDBY__A, &data);
5208                         data &= (~IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE);
5209                         WR16(dev_addr, IQM_AF_STDBY__A, data);
5210
5211                         /* Disable SCU RF AGC loop */
5212                         CHK_ERROR((*scu_rr16)
5213                                   (dev_addr, SCU_RAM_AGC_KI__A, &data, 0));
5214                         data &= ~SCU_RAM_AGC_KI_RF__M;
5215                         CHK_ERROR((*scu_wr16)
5216                                   (dev_addr, SCU_RAM_AGC_KI__A, data, 0));
5217                         break;
5218                 default:
5219                         return (DRX_STS_INVALID_ARG);
5220                 }               /* switch ( agcsettings->ctrl_mode ) */
5221         }
5222
5223         /* Store rf agc settings */
5224         switch (agc_settings->standard) {
5225         case DRX_STANDARD_8VSB:
5226                 ext_attr->vsb_rf_agc_cfg = *agc_settings;
5227                 break;
5228 #ifndef DRXJ_VSB_ONLY
5229         case DRX_STANDARD_ITU_A:
5230         case DRX_STANDARD_ITU_B:
5231         case DRX_STANDARD_ITU_C:
5232                 ext_attr->qam_rf_agc_cfg = *agc_settings;
5233                 break;
5234 #endif
5235 #ifndef DRXJ_DIGITAL_ONLY
5236         case DRX_STANDARD_PAL_SECAM_BG:
5237         case DRX_STANDARD_PAL_SECAM_DK:
5238         case DRX_STANDARD_PAL_SECAM_I:
5239         case DRX_STANDARD_PAL_SECAM_L:
5240         case DRX_STANDARD_PAL_SECAM_LP:
5241         case DRX_STANDARD_NTSC:
5242         case DRX_STANDARD_FM:
5243                 ext_attr->atv_rf_agc_cfg = *agc_settings;
5244                 break;
5245 #endif
5246         default:
5247                 return (DRX_STS_ERROR);
5248         }
5249
5250         return (DRX_STS_OK);
5251 rw_error:
5252         return (DRX_STS_ERROR);
5253 }
5254
5255 /**
5256 * \fn int get_agc_rf ()
5257 * \brief get configuration of RF AGC
5258 * \param demod instance of demodulator.
5259 * \param agc_settings AGC configuration structure
5260 * \return int.
5261 */
5262 static int
5263 get_agc_rf(pdrx_demod_instance_t demod, p_drxj_cfg_agc_t agc_settings)
5264 {
5265         struct i2c_device_addr *dev_addr = NULL;
5266         pdrxj_data_t ext_attr = NULL;
5267         enum drx_standard standard = DRX_STANDARD_UNKNOWN;
5268
5269         dev_addr = demod->my_i2c_dev_addr;
5270         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
5271
5272         /* Return stored AGC settings */
5273         standard = agc_settings->standard;
5274         switch (agc_settings->standard) {
5275         case DRX_STANDARD_8VSB:
5276                 *agc_settings = ext_attr->vsb_rf_agc_cfg;
5277                 break;
5278 #ifndef DRXJ_VSB_ONLY
5279         case DRX_STANDARD_ITU_A:
5280         case DRX_STANDARD_ITU_B:
5281         case DRX_STANDARD_ITU_C:
5282                 *agc_settings = ext_attr->qam_rf_agc_cfg;
5283                 break;
5284 #endif
5285 #ifndef DRXJ_DIGITAL_ONLY
5286         case DRX_STANDARD_PAL_SECAM_BG:
5287         case DRX_STANDARD_PAL_SECAM_DK:
5288         case DRX_STANDARD_PAL_SECAM_I:
5289         case DRX_STANDARD_PAL_SECAM_L:
5290         case DRX_STANDARD_PAL_SECAM_LP:
5291         case DRX_STANDARD_NTSC:
5292         case DRX_STANDARD_FM:
5293                 *agc_settings = ext_attr->atv_rf_agc_cfg;
5294                 break;
5295 #endif
5296         default:
5297                 return (DRX_STS_ERROR);
5298         }
5299         agc_settings->standard = standard;
5300
5301         /* Get AGC output only if standard is currently active. */
5302         if ((ext_attr->standard == agc_settings->standard) ||
5303             (DRXJ_ISQAMSTD(ext_attr->standard) &&
5304              DRXJ_ISQAMSTD(agc_settings->standard)) ||
5305             (DRXJ_ISATVSTD(ext_attr->standard) &&
5306              DRXJ_ISATVSTD(agc_settings->standard))) {
5307                 SARR16(dev_addr, SCU_RAM_AGC_RF_IACCU_HI__A,
5308                        &(agc_settings->output_level));
5309         }
5310
5311         return (DRX_STS_OK);
5312 rw_error:
5313         return (DRX_STS_ERROR);
5314 }
5315
5316 /**
5317 * \fn int set_agc_if ()
5318 * \brief Configure If AGC
5319 * \param demod instance of demodulator.
5320 * \param agc_settings AGC configuration structure
5321 * \return int.
5322 */
5323 static int
5324 set_agc_if(pdrx_demod_instance_t demod, p_drxj_cfg_agc_t agc_settings, bool atomic)
5325 {
5326         struct i2c_device_addr *dev_addr = NULL;
5327         pdrxj_data_t ext_attr = NULL;
5328         p_drxj_cfg_agc_t p_agc_settings = NULL;
5329         pdrx_common_attr_t common_attr = NULL;
5330         drx_write_reg16func_t scu_wr16 = NULL;
5331         drx_read_reg16func_t scu_rr16 = NULL;
5332
5333         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
5334         dev_addr = demod->my_i2c_dev_addr;
5335         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
5336
5337         if (atomic) {
5338                 scu_rr16 = drxj_dap_scu_atomic_read_reg16;
5339                 scu_wr16 = drxj_dap_scu_atomic_write_reg16;
5340         } else {
5341                 scu_rr16 = DRXJ_DAP.read_reg16func;
5342                 scu_wr16 = DRXJ_DAP.write_reg16func;
5343         }
5344
5345         /* Configure AGC only if standard is currently active */
5346         if ((ext_attr->standard == agc_settings->standard) ||
5347             (DRXJ_ISQAMSTD(ext_attr->standard) &&
5348              DRXJ_ISQAMSTD(agc_settings->standard)) ||
5349             (DRXJ_ISATVSTD(ext_attr->standard) &&
5350              DRXJ_ISATVSTD(agc_settings->standard))) {
5351                 u16 data = 0;
5352
5353                 switch (agc_settings->ctrl_mode) {
5354                 case DRX_AGC_CTRL_AUTO:
5355                         /* Enable IF AGC DAC */
5356                         RR16(dev_addr, IQM_AF_STDBY__A, &data);
5357                         data |= IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE;
5358                         WR16(dev_addr, IQM_AF_STDBY__A, data);
5359
5360                         /* Enable SCU IF AGC loop */
5361                         CHK_ERROR((*scu_rr16)
5362                                   (dev_addr, SCU_RAM_AGC_KI__A, &data, 0));
5363                         data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
5364                         data &= ~SCU_RAM_AGC_KI_IF__M;
5365                         if (ext_attr->standard == DRX_STANDARD_8VSB) {
5366                                 data |= (3 << SCU_RAM_AGC_KI_IF__B);
5367                         } else if (DRXJ_ISQAMSTD(ext_attr->standard)) {
5368                                 data |= (6 << SCU_RAM_AGC_KI_IF__B);
5369                         } else {
5370                                 data |= (5 << SCU_RAM_AGC_KI_IF__B);
5371                         }
5372
5373                         if (common_attr->tuner_if_agc_pol) {
5374                                 data |= SCU_RAM_AGC_KI_INV_IF_POL__M;
5375                         } else {
5376                                 data &= ~SCU_RAM_AGC_KI_INV_IF_POL__M;
5377                         }
5378                         CHK_ERROR((*scu_wr16)
5379                                   (dev_addr, SCU_RAM_AGC_KI__A, data, 0));
5380
5381                         /* Set speed (using complementary reduction value) */
5382                         CHK_ERROR((*scu_rr16)
5383                                   (dev_addr, SCU_RAM_AGC_KI_RED__A, &data, 0));
5384                         data &= ~SCU_RAM_AGC_KI_RED_IAGC_RED__M;
5385                         CHK_ERROR((*scu_wr16) (dev_addr, SCU_RAM_AGC_KI_RED__A,
5386                                               (~
5387                                                (agc_settings->
5388                                                 speed <<
5389                                                 SCU_RAM_AGC_KI_RED_IAGC_RED__B)
5390 & SCU_RAM_AGC_KI_RED_IAGC_RED__M)
5391                                               | data, 0));
5392
5393                         if (agc_settings->standard == DRX_STANDARD_8VSB)
5394                                 p_agc_settings = &(ext_attr->vsb_rf_agc_cfg);
5395                         else if (DRXJ_ISQAMSTD(agc_settings->standard))
5396                                 p_agc_settings = &(ext_attr->qam_rf_agc_cfg);
5397                         else if (DRXJ_ISATVSTD(agc_settings->standard))
5398                                 p_agc_settings = &(ext_attr->atv_rf_agc_cfg);
5399                         else
5400                                 return (DRX_STS_INVALID_ARG);
5401
5402                         /* Restore TOP */
5403                         if (p_agc_settings->ctrl_mode == DRX_AGC_CTRL_AUTO) {
5404                                 CHK_ERROR((*scu_wr16)
5405                                           (dev_addr,
5406                                            SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A,
5407                                            p_agc_settings->top, 0));
5408                                 CHK_ERROR((*scu_wr16)
5409                                           (dev_addr,
5410                                            SCU_RAM_AGC_IF_IACCU_HI_TGT__A,
5411                                            p_agc_settings->top, 0));
5412                         } else {
5413                                 CHK_ERROR((*scu_wr16)
5414                                           (dev_addr,
5415                                            SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A,
5416                                            0, 0));
5417                                 CHK_ERROR((*scu_wr16)
5418                                           (dev_addr,
5419                                            SCU_RAM_AGC_IF_IACCU_HI_TGT__A, 0,
5420                                            0));
5421                         }
5422                         break;
5423
5424                 case DRX_AGC_CTRL_USER:
5425
5426                         /* Enable IF AGC DAC */
5427                         RR16(dev_addr, IQM_AF_STDBY__A, &data);
5428                         data |= IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE;
5429                         WR16(dev_addr, IQM_AF_STDBY__A, data);
5430
5431                         /* Disable SCU IF AGC loop */
5432                         CHK_ERROR((*scu_rr16)
5433                                   (dev_addr, SCU_RAM_AGC_KI__A, &data, 0));
5434                         data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
5435                         data |= SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
5436                         if (common_attr->tuner_if_agc_pol) {
5437                                 data |= SCU_RAM_AGC_KI_INV_IF_POL__M;
5438                         } else {
5439                                 data &= ~SCU_RAM_AGC_KI_INV_IF_POL__M;
5440                         }
5441                         CHK_ERROR((*scu_wr16)
5442                                   (dev_addr, SCU_RAM_AGC_KI__A, data, 0));
5443
5444                         /* Write value to output pin */
5445                         CHK_ERROR((*scu_wr16)
5446                                   (dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A,
5447                                    agc_settings->output_level, 0));
5448                         break;
5449
5450                 case DRX_AGC_CTRL_OFF:
5451
5452                         /* Disable If AGC DAC */
5453                         RR16(dev_addr, IQM_AF_STDBY__A, &data);
5454                         data &= (~IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE);
5455                         WR16(dev_addr, IQM_AF_STDBY__A, data);
5456
5457                         /* Disable SCU IF AGC loop */
5458                         CHK_ERROR((*scu_rr16)
5459                                   (dev_addr, SCU_RAM_AGC_KI__A, &data, 0));
5460                         data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
5461                         data |= SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
5462                         CHK_ERROR((*scu_wr16)
5463                                   (dev_addr, SCU_RAM_AGC_KI__A, data, 0));
5464                         break;
5465                 default:
5466                         return (DRX_STS_INVALID_ARG);
5467                 }               /* switch ( agcsettings->ctrl_mode ) */
5468
5469                 /* always set the top to support configurations without if-loop */
5470                 CHK_ERROR((*scu_wr16) (dev_addr,
5471                                       SCU_RAM_AGC_INGAIN_TGT_MIN__A,
5472                                       agc_settings->top, 0));
5473         }
5474
5475         /* Store if agc settings */
5476         switch (agc_settings->standard) {
5477         case DRX_STANDARD_8VSB:
5478                 ext_attr->vsb_if_agc_cfg = *agc_settings;
5479                 break;
5480 #ifndef DRXJ_VSB_ONLY
5481         case DRX_STANDARD_ITU_A:
5482         case DRX_STANDARD_ITU_B:
5483         case DRX_STANDARD_ITU_C:
5484                 ext_attr->qam_if_agc_cfg = *agc_settings;
5485                 break;
5486 #endif
5487 #ifndef DRXJ_DIGITAL_ONLY
5488         case DRX_STANDARD_PAL_SECAM_BG:
5489         case DRX_STANDARD_PAL_SECAM_DK:
5490         case DRX_STANDARD_PAL_SECAM_I:
5491         case DRX_STANDARD_PAL_SECAM_L:
5492         case DRX_STANDARD_PAL_SECAM_LP:
5493         case DRX_STANDARD_NTSC:
5494         case DRX_STANDARD_FM:
5495                 ext_attr->atv_if_agc_cfg = *agc_settings;
5496                 break;
5497 #endif
5498         default:
5499                 return (DRX_STS_ERROR);
5500         }
5501
5502         return (DRX_STS_OK);
5503 rw_error:
5504         return (DRX_STS_ERROR);
5505 }
5506
5507 /**
5508 * \fn int get_agc_if ()
5509 * \brief get configuration of If AGC
5510 * \param demod instance of demodulator.
5511 * \param agc_settings AGC configuration structure
5512 * \return int.
5513 */
5514 static int
5515 get_agc_if(pdrx_demod_instance_t demod, p_drxj_cfg_agc_t agc_settings)
5516 {
5517         struct i2c_device_addr *dev_addr = NULL;
5518         pdrxj_data_t ext_attr = NULL;
5519         enum drx_standard standard = DRX_STANDARD_UNKNOWN;
5520
5521         dev_addr = demod->my_i2c_dev_addr;
5522         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
5523
5524         /* Return stored ATV AGC settings */
5525         standard = agc_settings->standard;
5526         switch (agc_settings->standard) {
5527         case DRX_STANDARD_8VSB:
5528                 *agc_settings = ext_attr->vsb_if_agc_cfg;
5529                 break;
5530 #ifndef DRXJ_VSB_ONLY
5531         case DRX_STANDARD_ITU_A:
5532         case DRX_STANDARD_ITU_B:
5533         case DRX_STANDARD_ITU_C:
5534                 *agc_settings = ext_attr->qam_if_agc_cfg;
5535                 break;
5536 #endif
5537 #ifndef DRXJ_DIGITAL_ONLY
5538         case DRX_STANDARD_PAL_SECAM_BG:
5539         case DRX_STANDARD_PAL_SECAM_DK:
5540         case DRX_STANDARD_PAL_SECAM_I:
5541         case DRX_STANDARD_PAL_SECAM_L:
5542         case DRX_STANDARD_PAL_SECAM_LP:
5543         case DRX_STANDARD_NTSC:
5544         case DRX_STANDARD_FM:
5545                 *agc_settings = ext_attr->atv_if_agc_cfg;
5546                 break;
5547 #endif
5548         default:
5549                 return (DRX_STS_ERROR);
5550         }
5551         agc_settings->standard = standard;
5552
5553         /* Get AGC output only if standard is currently active */
5554         if ((ext_attr->standard == agc_settings->standard) ||
5555             (DRXJ_ISQAMSTD(ext_attr->standard) &&
5556              DRXJ_ISQAMSTD(agc_settings->standard)) ||
5557             (DRXJ_ISATVSTD(ext_attr->standard) &&
5558              DRXJ_ISATVSTD(agc_settings->standard))) {
5559                 /* read output level */
5560                 SARR16(dev_addr, SCU_RAM_AGC_IF_IACCU_HI__A,
5561                        &(agc_settings->output_level));
5562         }
5563
5564         return (DRX_STS_OK);
5565 rw_error:
5566         return (DRX_STS_ERROR);
5567 }
5568
5569 /**
5570 * \fn int set_iqm_af ()
5571 * \brief Configure IQM AF registers
5572 * \param demod instance of demodulator.
5573 * \param active
5574 * \return int.
5575 */
5576 static int set_iqm_af(pdrx_demod_instance_t demod, bool active)
5577 {
5578         u16 data = 0;
5579         struct i2c_device_addr *dev_addr = NULL;
5580
5581         dev_addr = demod->my_i2c_dev_addr;
5582
5583         /* Configure IQM */
5584         RR16(dev_addr, IQM_AF_STDBY__A, &data);
5585         if (!active) {
5586                 data &= ((~IQM_AF_STDBY_STDBY_ADC_A2_ACTIVE)
5587                          & (~IQM_AF_STDBY_STDBY_AMP_A2_ACTIVE)
5588                          & (~IQM_AF_STDBY_STDBY_PD_A2_ACTIVE)
5589                          & (~IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE)
5590                          & (~IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE)
5591                     );
5592         } else {                /* active */
5593
5594                 data |= (IQM_AF_STDBY_STDBY_ADC_A2_ACTIVE
5595                          | IQM_AF_STDBY_STDBY_AMP_A2_ACTIVE
5596                          | IQM_AF_STDBY_STDBY_PD_A2_ACTIVE
5597                          | IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE
5598                          | IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE);
5599         }
5600         WR16(dev_addr, IQM_AF_STDBY__A, data);
5601
5602         return (DRX_STS_OK);
5603 rw_error:
5604         return (DRX_STS_ERROR);
5605 }
5606
5607 /*============================================================================*/
5608 /*==              END 8VSB & QAM COMMON DATAPATH FUNCTIONS                  ==*/
5609 /*============================================================================*/
5610
5611 /*============================================================================*/
5612 /*============================================================================*/
5613 /*==                       8VSB DATAPATH FUNCTIONS                          ==*/
5614 /*============================================================================*/
5615 /*============================================================================*/
5616
5617 /**
5618 * \fn int power_down_vsb ()
5619 * \brief Powr down QAM related blocks.
5620 * \param demod instance of demodulator.
5621 * \param channel pointer to channel data.
5622 * \return int.
5623 */
5624 static int power_down_vsb(pdrx_demod_instance_t demod, bool primary)
5625 {
5626         struct i2c_device_addr *dev_addr = NULL;
5627         drxjscu_cmd_t cmd_scu = { /* command     */ 0,
5628                 /* parameter_len */ 0,
5629                 /* result_len    */ 0,
5630                 /* *parameter   */ NULL,
5631                 /* *result      */ NULL
5632         };
5633         u16 cmd_result = 0;
5634         pdrxj_data_t ext_attr = NULL;
5635         drx_cfg_mpeg_output_t cfg_mpeg_output;
5636
5637         dev_addr = demod->my_i2c_dev_addr;
5638         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
5639         /*
5640            STOP demodulator
5641            reset of FEC and VSB HW
5642          */
5643         cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB |
5644             SCU_RAM_COMMAND_CMD_DEMOD_STOP;
5645         cmd_scu.parameter_len = 0;
5646         cmd_scu.result_len = 1;
5647         cmd_scu.parameter = NULL;
5648         cmd_scu.result = &cmd_result;
5649         CHK_ERROR(scu_command(dev_addr, &cmd_scu));
5650
5651         /* stop all comm_exec */
5652         WR16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP);
5653         WR16(dev_addr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_STOP);
5654         if (primary == true) {
5655                 WR16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP);
5656                 CHK_ERROR(set_iqm_af(demod, false));
5657         } else {
5658                 WR16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP);
5659                 WR16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP);
5660                 WR16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP);
5661                 WR16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP);
5662                 WR16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP);
5663         }
5664
5665         cfg_mpeg_output.enable_mpeg_output = false;
5666         CHK_ERROR(ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output));
5667
5668         return (DRX_STS_OK);
5669 rw_error:
5670         return (DRX_STS_ERROR);
5671 }
5672
5673 /**
5674 * \fn int set_vsb_leak_n_gain ()
5675 * \brief Set ATSC demod.
5676 * \param demod instance of demodulator.
5677 * \return int.
5678 */
5679 static int set_vsb_leak_n_gain(pdrx_demod_instance_t demod)
5680 {
5681         struct i2c_device_addr *dev_addr = NULL;
5682
5683         const u8 vsb_ffe_leak_gain_ram0[] = {
5684                 DRXJ_16TO8(0x8),        /* FFETRAINLKRATIO1  */
5685                 DRXJ_16TO8(0x8),        /* FFETRAINLKRATIO2  */
5686                 DRXJ_16TO8(0x8),        /* FFETRAINLKRATIO3  */
5687                 DRXJ_16TO8(0xf),        /* FFETRAINLKRATIO4  */
5688                 DRXJ_16TO8(0xf),        /* FFETRAINLKRATIO5  */
5689                 DRXJ_16TO8(0xf),        /* FFETRAINLKRATIO6  */
5690                 DRXJ_16TO8(0xf),        /* FFETRAINLKRATIO7  */
5691                 DRXJ_16TO8(0xf),        /* FFETRAINLKRATIO8  */
5692                 DRXJ_16TO8(0xf),        /* FFETRAINLKRATIO9  */
5693                 DRXJ_16TO8(0x8),        /* FFETRAINLKRATIO10  */
5694                 DRXJ_16TO8(0x8),        /* FFETRAINLKRATIO11 */
5695                 DRXJ_16TO8(0x8),        /* FFETRAINLKRATIO12 */
5696                 DRXJ_16TO8(0x10),       /* FFERCA1TRAINLKRATIO1 */
5697                 DRXJ_16TO8(0x10),       /* FFERCA1TRAINLKRATIO2 */
5698                 DRXJ_16TO8(0x10),       /* FFERCA1TRAINLKRATIO3 */
5699                 DRXJ_16TO8(0x20),       /* FFERCA1TRAINLKRATIO4 */
5700                 DRXJ_16TO8(0x20),       /* FFERCA1TRAINLKRATIO5 */
5701                 DRXJ_16TO8(0x20),       /* FFERCA1TRAINLKRATIO6 */
5702                 DRXJ_16TO8(0x20),       /* FFERCA1TRAINLKRATIO7 */
5703                 DRXJ_16TO8(0x20),       /* FFERCA1TRAINLKRATIO8 */
5704                 DRXJ_16TO8(0x20),       /* FFERCA1TRAINLKRATIO9 */
5705                 DRXJ_16TO8(0x10),       /* FFERCA1TRAINLKRATIO10 */
5706                 DRXJ_16TO8(0x10),       /* FFERCA1TRAINLKRATIO11 */
5707                 DRXJ_16TO8(0x10),       /* FFERCA1TRAINLKRATIO12 */
5708                 DRXJ_16TO8(0x10),       /* FFERCA1DATALKRATIO1 */
5709                 DRXJ_16TO8(0x10),       /* FFERCA1DATALKRATIO2 */
5710                 DRXJ_16TO8(0x10),       /* FFERCA1DATALKRATIO3 */
5711                 DRXJ_16TO8(0x20),       /* FFERCA1DATALKRATIO4 */
5712                 DRXJ_16TO8(0x20),       /* FFERCA1DATALKRATIO5 */
5713                 DRXJ_16TO8(0x20),       /* FFERCA1DATALKRATIO6 */
5714                 DRXJ_16TO8(0x20),       /* FFERCA1DATALKRATIO7 */
5715                 DRXJ_16TO8(0x20),       /* FFERCA1DATALKRATIO8 */
5716                 DRXJ_16TO8(0x20),       /* FFERCA1DATALKRATIO9 */
5717                 DRXJ_16TO8(0x10),       /* FFERCA1DATALKRATIO10 */
5718                 DRXJ_16TO8(0x10),       /* FFERCA1DATALKRATIO11 */
5719                 DRXJ_16TO8(0x10),       /* FFERCA1DATALKRATIO12 */
5720                 DRXJ_16TO8(0x10),       /* FFERCA2TRAINLKRATIO1 */
5721                 DRXJ_16TO8(0x10),       /* FFERCA2TRAINLKRATIO2 */
5722                 DRXJ_16TO8(0x10),       /* FFERCA2TRAINLKRATIO3 */
5723                 DRXJ_16TO8(0x20),       /* FFERCA2TRAINLKRATIO4 */
5724                 DRXJ_16TO8(0x20),       /* FFERCA2TRAINLKRATIO5 */
5725                 DRXJ_16TO8(0x20),       /* FFERCA2TRAINLKRATIO6 */
5726                 DRXJ_16TO8(0x20),       /* FFERCA2TRAINLKRATIO7 */
5727                 DRXJ_16TO8(0x20),       /* FFERCA2TRAINLKRATIO8 */
5728                 DRXJ_16TO8(0x20),       /* FFERCA2TRAINLKRATIO9 */
5729                 DRXJ_16TO8(0x10),       /* FFERCA2TRAINLKRATIO10 */
5730                 DRXJ_16TO8(0x10),       /* FFERCA2TRAINLKRATIO11 */
5731                 DRXJ_16TO8(0x10),       /* FFERCA2TRAINLKRATIO12 */
5732                 DRXJ_16TO8(0x10),       /* FFERCA2DATALKRATIO1 */
5733                 DRXJ_16TO8(0x10),       /* FFERCA2DATALKRATIO2 */
5734                 DRXJ_16TO8(0x10),       /* FFERCA2DATALKRATIO3 */
5735                 DRXJ_16TO8(0x20),       /* FFERCA2DATALKRATIO4 */
5736                 DRXJ_16TO8(0x20),       /* FFERCA2DATALKRATIO5 */
5737                 DRXJ_16TO8(0x20),       /* FFERCA2DATALKRATIO6 */
5738                 DRXJ_16TO8(0x20),       /* FFERCA2DATALKRATIO7 */
5739                 DRXJ_16TO8(0x20),       /* FFERCA2DATALKRATIO8 */
5740                 DRXJ_16TO8(0x20),       /* FFERCA2DATALKRATIO9 */
5741                 DRXJ_16TO8(0x10),       /* FFERCA2DATALKRATIO10 */
5742                 DRXJ_16TO8(0x10),       /* FFERCA2DATALKRATIO11 */
5743                 DRXJ_16TO8(0x10),       /* FFERCA2DATALKRATIO12 */
5744                 DRXJ_16TO8(0x07),       /* FFEDDM1TRAINLKRATIO1 */
5745                 DRXJ_16TO8(0x07),       /* FFEDDM1TRAINLKRATIO2 */
5746                 DRXJ_16TO8(0x07),       /* FFEDDM1TRAINLKRATIO3 */
5747                 DRXJ_16TO8(0x0e),       /* FFEDDM1TRAINLKRATIO4 */
5748                 DRXJ_16TO8(0x0e),       /* FFEDDM1TRAINLKRATIO5 */
5749                 DRXJ_16TO8(0x0e),       /* FFEDDM1TRAINLKRATIO6 */
5750                 DRXJ_16TO8(0x0e),       /* FFEDDM1TRAINLKRATIO7 */
5751                 DRXJ_16TO8(0x0e),       /* FFEDDM1TRAINLKRATIO8 */
5752                 DRXJ_16TO8(0x0e),       /* FFEDDM1TRAINLKRATIO9 */
5753                 DRXJ_16TO8(0x07),       /* FFEDDM1TRAINLKRATIO10 */
5754                 DRXJ_16TO8(0x07),       /* FFEDDM1TRAINLKRATIO11 */
5755                 DRXJ_16TO8(0x07),       /* FFEDDM1TRAINLKRATIO12 */
5756                 DRXJ_16TO8(0x07),       /* FFEDDM1DATALKRATIO1 */
5757                 DRXJ_16TO8(0x07),       /* FFEDDM1DATALKRATIO2 */
5758                 DRXJ_16TO8(0x07),       /* FFEDDM1DATALKRATIO3 */
5759                 DRXJ_16TO8(0x0e),       /* FFEDDM1DATALKRATIO4 */
5760                 DRXJ_16TO8(0x0e),       /* FFEDDM1DATALKRATIO5 */
5761                 DRXJ_16TO8(0x0e),       /* FFEDDM1DATALKRATIO6 */
5762                 DRXJ_16TO8(0x0e),       /* FFEDDM1DATALKRATIO7 */
5763                 DRXJ_16TO8(0x0e),       /* FFEDDM1DATALKRATIO8 */
5764                 DRXJ_16TO8(0x0e),       /* FFEDDM1DATALKRATIO9 */
5765                 DRXJ_16TO8(0x07),       /* FFEDDM1DATALKRATIO10 */
5766                 DRXJ_16TO8(0x07),       /* FFEDDM1DATALKRATIO11 */
5767                 DRXJ_16TO8(0x07),       /* FFEDDM1DATALKRATIO12 */
5768                 DRXJ_16TO8(0x06),       /* FFEDDM2TRAINLKRATIO1 */
5769                 DRXJ_16TO8(0x06),       /* FFEDDM2TRAINLKRATIO2 */
5770                 DRXJ_16TO8(0x06),       /* FFEDDM2TRAINLKRATIO3 */
5771                 DRXJ_16TO8(0x0c),       /* FFEDDM2TRAINLKRATIO4 */
5772                 DRXJ_16TO8(0x0c),       /* FFEDDM2TRAINLKRATIO5 */
5773                 DRXJ_16TO8(0x0c),       /* FFEDDM2TRAINLKRATIO6 */
5774                 DRXJ_16TO8(0x0c),       /* FFEDDM2TRAINLKRATIO7 */
5775                 DRXJ_16TO8(0x0c),       /* FFEDDM2TRAINLKRATIO8 */
5776                 DRXJ_16TO8(0x0c),       /* FFEDDM2TRAINLKRATIO9 */
5777                 DRXJ_16TO8(0x06),       /* FFEDDM2TRAINLKRATIO10 */
5778                 DRXJ_16TO8(0x06),       /* FFEDDM2TRAINLKRATIO11 */
5779                 DRXJ_16TO8(0x06),       /* FFEDDM2TRAINLKRATIO12 */
5780                 DRXJ_16TO8(0x06),       /* FFEDDM2DATALKRATIO1 */
5781                 DRXJ_16TO8(0x06),       /* FFEDDM2DATALKRATIO2 */
5782                 DRXJ_16TO8(0x06),       /* FFEDDM2DATALKRATIO3 */
5783                 DRXJ_16TO8(0x0c),       /* FFEDDM2DATALKRATIO4 */
5784                 DRXJ_16TO8(0x0c),       /* FFEDDM2DATALKRATIO5 */
5785                 DRXJ_16TO8(0x0c),       /* FFEDDM2DATALKRATIO6 */
5786                 DRXJ_16TO8(0x0c),       /* FFEDDM2DATALKRATIO7 */
5787                 DRXJ_16TO8(0x0c),       /* FFEDDM2DATALKRATIO8 */
5788                 DRXJ_16TO8(0x0c),       /* FFEDDM2DATALKRATIO9 */
5789                 DRXJ_16TO8(0x06),       /* FFEDDM2DATALKRATIO10 */
5790                 DRXJ_16TO8(0x06),       /* FFEDDM2DATALKRATIO11 */
5791                 DRXJ_16TO8(0x06),       /* FFEDDM2DATALKRATIO12 */
5792                 DRXJ_16TO8(0x2020),     /* FIRTRAINGAIN1 */
5793                 DRXJ_16TO8(0x2020),     /* FIRTRAINGAIN2 */
5794                 DRXJ_16TO8(0x2020),     /* FIRTRAINGAIN3 */
5795                 DRXJ_16TO8(0x4040),     /* FIRTRAINGAIN4 */
5796                 DRXJ_16TO8(0x4040),     /* FIRTRAINGAIN5 */
5797                 DRXJ_16TO8(0x4040),     /* FIRTRAINGAIN6 */
5798                 DRXJ_16TO8(0x4040),     /* FIRTRAINGAIN7 */
5799                 DRXJ_16TO8(0x4040),     /* FIRTRAINGAIN8 */
5800                 DRXJ_16TO8(0x4040),     /* FIRTRAINGAIN9 */
5801                 DRXJ_16TO8(0x2020),     /* FIRTRAINGAIN10 */
5802                 DRXJ_16TO8(0x2020),     /* FIRTRAINGAIN11 */
5803                 DRXJ_16TO8(0x2020),     /* FIRTRAINGAIN12 */
5804                 DRXJ_16TO8(0x0808),     /* FIRRCA1GAIN1 */
5805                 DRXJ_16TO8(0x0808),     /* FIRRCA1GAIN2 */
5806                 DRXJ_16TO8(0x0808),     /* FIRRCA1GAIN3 */
5807                 DRXJ_16TO8(0x1010),     /* FIRRCA1GAIN4 */
5808                 DRXJ_16TO8(0x1010),     /* FIRRCA1GAIN5 */
5809                 DRXJ_16TO8(0x1010),     /* FIRRCA1GAIN6 */
5810                 DRXJ_16TO8(0x1010),     /* FIRRCA1GAIN7 */
5811                 DRXJ_16TO8(0x1010)      /* FIRRCA1GAIN8 */
5812         };
5813
5814         const u8 vsb_ffe_leak_gain_ram1[] = {
5815                 DRXJ_16TO8(0x1010),     /* FIRRCA1GAIN9 */
5816                 DRXJ_16TO8(0x0808),     /* FIRRCA1GAIN10 */
5817                 DRXJ_16TO8(0x0808),     /* FIRRCA1GAIN11 */
5818                 DRXJ_16TO8(0x0808),     /* FIRRCA1GAIN12 */
5819                 DRXJ_16TO8(0x0808),     /* FIRRCA2GAIN1 */
5820                 DRXJ_16TO8(0x0808),     /* FIRRCA2GAIN2 */
5821                 DRXJ_16TO8(0x0808),     /* FIRRCA2GAIN3 */
5822                 DRXJ_16TO8(0x1010),     /* FIRRCA2GAIN4 */
5823                 DRXJ_16TO8(0x1010),     /* FIRRCA2GAIN5 */
5824                 DRXJ_16TO8(0x1010),     /* FIRRCA2GAIN6 */
5825                 DRXJ_16TO8(0x1010),     /* FIRRCA2GAIN7 */
5826                 DRXJ_16TO8(0x1010),     /* FIRRCA2GAIN8 */
5827                 DRXJ_16TO8(0x1010),     /* FIRRCA2GAIN9 */
5828                 DRXJ_16TO8(0x0808),     /* FIRRCA2GAIN10 */
5829                 DRXJ_16TO8(0x0808),     /* FIRRCA2GAIN11 */
5830                 DRXJ_16TO8(0x0808),     /* FIRRCA2GAIN12 */
5831                 DRXJ_16TO8(0x0303),     /* FIRDDM1GAIN1 */
5832                 DRXJ_16TO8(0x0303),     /* FIRDDM1GAIN2 */
5833                 DRXJ_16TO8(0x0303),     /* FIRDDM1GAIN3 */
5834                 DRXJ_16TO8(0x0606),     /* FIRDDM1GAIN4 */
5835                 DRXJ_16TO8(0x0606),     /* FIRDDM1GAIN5 */
5836                 DRXJ_16TO8(0x0606),     /* FIRDDM1GAIN6 */
5837                 DRXJ_16TO8(0x0606),     /* FIRDDM1GAIN7 */
5838                 DRXJ_16TO8(0x0606),     /* FIRDDM1GAIN8 */
5839                 DRXJ_16TO8(0x0606),     /* FIRDDM1GAIN9 */
5840                 DRXJ_16TO8(0x0303),     /* FIRDDM1GAIN10 */
5841                 DRXJ_16TO8(0x0303),     /* FIRDDM1GAIN11 */
5842                 DRXJ_16TO8(0x0303),     /* FIRDDM1GAIN12 */
5843                 DRXJ_16TO8(0x0303),     /* FIRDDM2GAIN1 */
5844                 DRXJ_16TO8(0x0303),     /* FIRDDM2GAIN2 */
5845                 DRXJ_16TO8(0x0303),     /* FIRDDM2GAIN3 */
5846                 DRXJ_16TO8(0x0505),     /* FIRDDM2GAIN4 */
5847                 DRXJ_16TO8(0x0505),     /* FIRDDM2GAIN5 */
5848                 DRXJ_16TO8(0x0505),     /* FIRDDM2GAIN6 */
5849                 DRXJ_16TO8(0x0505),     /* FIRDDM2GAIN7 */
5850                 DRXJ_16TO8(0x0505),     /* FIRDDM2GAIN8 */
5851                 DRXJ_16TO8(0x0505),     /* FIRDDM2GAIN9 */
5852                 DRXJ_16TO8(0x0303),     /* FIRDDM2GAIN10 */
5853                 DRXJ_16TO8(0x0303),     /* FIRDDM2GAIN11 */
5854                 DRXJ_16TO8(0x0303),     /* FIRDDM2GAIN12 */
5855                 DRXJ_16TO8(0x001f),     /* DFETRAINLKRATIO */
5856                 DRXJ_16TO8(0x01ff),     /* DFERCA1TRAINLKRATIO */
5857                 DRXJ_16TO8(0x01ff),     /* DFERCA1DATALKRATIO */
5858                 DRXJ_16TO8(0x004f),     /* DFERCA2TRAINLKRATIO */
5859                 DRXJ_16TO8(0x004f),     /* DFERCA2DATALKRATIO */
5860                 DRXJ_16TO8(0x01ff),     /* DFEDDM1TRAINLKRATIO */
5861                 DRXJ_16TO8(0x01ff),     /* DFEDDM1DATALKRATIO */
5862                 DRXJ_16TO8(0x0352),     /* DFEDDM2TRAINLKRATIO */
5863                 DRXJ_16TO8(0x0352),     /* DFEDDM2DATALKRATIO */
5864                 DRXJ_16TO8(0x0000),     /* DFETRAINGAIN */
5865                 DRXJ_16TO8(0x2020),     /* DFERCA1GAIN */
5866                 DRXJ_16TO8(0x1010),     /* DFERCA2GAIN */
5867                 DRXJ_16TO8(0x1818),     /* DFEDDM1GAIN */
5868                 DRXJ_16TO8(0x1212)      /* DFEDDM2GAIN */
5869         };
5870
5871         dev_addr = demod->my_i2c_dev_addr;
5872         WRB(dev_addr, VSB_SYSCTRL_RAM0_FFETRAINLKRATIO1__A,
5873             sizeof(vsb_ffe_leak_gain_ram0), ((u8 *) vsb_ffe_leak_gain_ram0));
5874         WRB(dev_addr, VSB_SYSCTRL_RAM1_FIRRCA1GAIN9__A,
5875             sizeof(vsb_ffe_leak_gain_ram1), ((u8 *) vsb_ffe_leak_gain_ram1));
5876
5877         return (DRX_STS_OK);
5878 rw_error:
5879         return (DRX_STS_ERROR);
5880 }
5881
5882 /**
5883 * \fn int set_vsb()
5884 * \brief Set 8VSB demod.
5885 * \param demod instance of demodulator.
5886 * \return int.
5887 *
5888 */
5889 static int set_vsb(pdrx_demod_instance_t demod)
5890 {
5891         struct i2c_device_addr *dev_addr = NULL;
5892         u16 cmd_result = 0;
5893         u16 cmd_param = 0;
5894         pdrx_common_attr_t common_attr = NULL;
5895         drxjscu_cmd_t cmd_scu;
5896         pdrxj_data_t ext_attr = NULL;
5897         const u8 vsb_taps_re[] = {
5898                 DRXJ_16TO8(-2), /* re0  */
5899                 DRXJ_16TO8(4),  /* re1  */
5900                 DRXJ_16TO8(1),  /* re2  */
5901                 DRXJ_16TO8(-4), /* re3  */
5902                 DRXJ_16TO8(1),  /* re4  */
5903                 DRXJ_16TO8(4),  /* re5  */
5904                 DRXJ_16TO8(-3), /* re6  */
5905                 DRXJ_16TO8(-3), /* re7  */
5906                 DRXJ_16TO8(6),  /* re8  */
5907                 DRXJ_16TO8(1),  /* re9  */
5908                 DRXJ_16TO8(-9), /* re10 */
5909                 DRXJ_16TO8(3),  /* re11 */
5910                 DRXJ_16TO8(12), /* re12 */
5911                 DRXJ_16TO8(-9), /* re13 */
5912                 DRXJ_16TO8(-15),        /* re14 */
5913                 DRXJ_16TO8(17), /* re15 */
5914                 DRXJ_16TO8(19), /* re16 */
5915                 DRXJ_16TO8(-29),        /* re17 */
5916                 DRXJ_16TO8(-22),        /* re18 */
5917                 DRXJ_16TO8(45), /* re19 */
5918                 DRXJ_16TO8(25), /* re20 */
5919                 DRXJ_16TO8(-70),        /* re21 */
5920                 DRXJ_16TO8(-28),        /* re22 */
5921                 DRXJ_16TO8(111),        /* re23 */
5922                 DRXJ_16TO8(30), /* re24 */
5923                 DRXJ_16TO8(-201),       /* re25 */
5924                 DRXJ_16TO8(-31),        /* re26 */
5925                 DRXJ_16TO8(629) /* re27 */
5926         };
5927
5928         dev_addr = demod->my_i2c_dev_addr;
5929         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
5930         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
5931
5932         /* stop all comm_exec */
5933         WR16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP);
5934         WR16(dev_addr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_STOP);
5935         WR16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP);
5936         WR16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP);
5937         WR16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP);
5938         WR16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP);
5939         WR16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP);
5940
5941         /* reset demodulator */
5942         cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB
5943             | SCU_RAM_COMMAND_CMD_DEMOD_RESET;
5944         cmd_scu.parameter_len = 0;
5945         cmd_scu.result_len = 1;
5946         cmd_scu.parameter = NULL;
5947         cmd_scu.result = &cmd_result;
5948         CHK_ERROR(scu_command(dev_addr, &cmd_scu));
5949
5950         WR16(dev_addr, IQM_AF_DCF_BYPASS__A, 1);
5951         WR16(dev_addr, IQM_FS_ADJ_SEL__A, IQM_FS_ADJ_SEL_B_VSB);
5952         WR16(dev_addr, IQM_RC_ADJ_SEL__A, IQM_RC_ADJ_SEL_B_VSB);
5953         ext_attr->iqm_rc_rate_ofs = 0x00AD0D79;
5954         WR32(dev_addr, IQM_RC_RATE_OFS_LO__A, ext_attr->iqm_rc_rate_ofs);
5955         WR16(dev_addr, VSB_TOP_CFAGC_GAINSHIFT__A, 4);
5956         WR16(dev_addr, VSB_TOP_CYGN1TRK__A, 1);
5957
5958         WR16(dev_addr, IQM_RC_CROUT_ENA__A, 1);
5959         WR16(dev_addr, IQM_RC_STRETCH__A, 28);
5960         WR16(dev_addr, IQM_RT_ACTIVE__A, 0);
5961         WR16(dev_addr, IQM_CF_SYMMETRIC__A, 0);
5962         WR16(dev_addr, IQM_CF_MIDTAP__A, 3);
5963         WR16(dev_addr, IQM_CF_OUT_ENA__A, IQM_CF_OUT_ENA_VSB__M);
5964         WR16(dev_addr, IQM_CF_SCALE__A, 1393);
5965         WR16(dev_addr, IQM_CF_SCALE_SH__A, 0);
5966         WR16(dev_addr, IQM_CF_POW_MEAS_LEN__A, 1);
5967
5968         WRB(dev_addr, IQM_CF_TAP_RE0__A, sizeof(vsb_taps_re),
5969             ((u8 *) vsb_taps_re));
5970         WRB(dev_addr, IQM_CF_TAP_IM0__A, sizeof(vsb_taps_re),
5971             ((u8 *) vsb_taps_re));
5972
5973         WR16(dev_addr, VSB_TOP_BNTHRESH__A, 330);       /* set higher threshold */
5974         WR16(dev_addr, VSB_TOP_CLPLASTNUM__A, 90);      /* burst detection on   */
5975         WR16(dev_addr, VSB_TOP_SNRTH_RCA1__A, 0x0042);  /* drop thresholds by 1 dB */
5976         WR16(dev_addr, VSB_TOP_SNRTH_RCA2__A, 0x0053);  /* drop thresholds by 2 dB */
5977         WR16(dev_addr, VSB_TOP_EQCTRL__A, 0x1); /* cma on               */
5978         WR16(dev_addr, SCU_RAM_GPIO__A, 0);     /* GPIO               */
5979
5980         /* Initialize the FEC Subsystem */
5981         WR16(dev_addr, FEC_TOP_ANNEX__A, FEC_TOP_ANNEX_D);
5982         {
5983                 u16 fec_oc_snc_mode = 0;
5984                 RR16(dev_addr, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode);
5985                 /* output data even when not locked */
5986                 WR16(dev_addr, FEC_OC_SNC_MODE__A,
5987                      fec_oc_snc_mode | FEC_OC_SNC_MODE_UNLOCK_ENABLE__M);
5988         }
5989
5990         /* set clip */
5991         WR16(dev_addr, IQM_AF_CLP_LEN__A, 0);
5992         WR16(dev_addr, IQM_AF_CLP_TH__A, 470);
5993         WR16(dev_addr, IQM_AF_SNS_LEN__A, 0);
5994         WR16(dev_addr, VSB_TOP_SNRTH_PT__A, 0xD4);
5995         /* no transparent, no A&C framing; parity is set in mpegoutput */
5996         {
5997                 u16 fec_oc_reg_mode = 0;
5998                 RR16(dev_addr, FEC_OC_MODE__A, &fec_oc_reg_mode);
5999                 WR16(dev_addr, FEC_OC_MODE__A, fec_oc_reg_mode &
6000                      (~(FEC_OC_MODE_TRANSPARENT__M
6001                         | FEC_OC_MODE_CLEAR__M | FEC_OC_MODE_RETAIN_FRAMING__M)
6002                      ));
6003         }
6004
6005         WR16(dev_addr, FEC_DI_TIMEOUT_LO__A, 0);        /* timeout counter for restarting */
6006         WR16(dev_addr, FEC_DI_TIMEOUT_HI__A, 3);
6007         WR16(dev_addr, FEC_RS_MODE__A, 0);      /* bypass disabled */
6008         /* initialize RS packet error measurement parameters */
6009         WR16(dev_addr, FEC_RS_MEASUREMENT_PERIOD__A, FEC_RS_MEASUREMENT_PERIOD);
6010         WR16(dev_addr, FEC_RS_MEASUREMENT_PRESCALE__A,
6011              FEC_RS_MEASUREMENT_PRESCALE);
6012
6013         /* init measurement period of MER/SER */
6014         WR16(dev_addr, VSB_TOP_MEASUREMENT_PERIOD__A,
6015              VSB_TOP_MEASUREMENT_PERIOD);
6016         WR32(dev_addr, SCU_RAM_FEC_ACCUM_CW_CORRECTED_LO__A, 0);
6017         WR16(dev_addr, SCU_RAM_FEC_MEAS_COUNT__A, 0);
6018         WR16(dev_addr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0);
6019
6020         WR16(dev_addr, VSB_TOP_CKGN1TRK__A, 128);
6021         /* B-Input to ADC, PGA+filter in standby */
6022         if (ext_attr->has_lna == false) {
6023                 WR16(dev_addr, IQM_AF_AMUX__A, 0x02);
6024         };
6025
6026         /* turn on IQMAF. It has to be in front of setAgc**() */
6027         CHK_ERROR(set_iqm_af(demod, true));
6028         CHK_ERROR(adc_synchronization(demod));
6029
6030         CHK_ERROR(init_agc(demod));
6031         CHK_ERROR(set_agc_if(demod, &(ext_attr->vsb_if_agc_cfg), false));
6032         CHK_ERROR(set_agc_rf(demod, &(ext_attr->vsb_rf_agc_cfg), false));
6033         {
6034                 /* TODO fix this, store a drxj_cfg_afe_gain_t structure in drxj_data_t instead
6035                    of only the gain */
6036                 drxj_cfg_afe_gain_t vsb_pga_cfg = { DRX_STANDARD_8VSB, 0 };
6037
6038                 vsb_pga_cfg.gain = ext_attr->vsb_pga_cfg;
6039                 CHK_ERROR(ctrl_set_cfg_afe_gain(demod, &vsb_pga_cfg));
6040         }
6041         CHK_ERROR(ctrl_set_cfg_pre_saw(demod, &(ext_attr->vsb_pre_saw_cfg)));
6042
6043         /* Mpeg output has to be in front of FEC active */
6044         CHK_ERROR(set_mpegtei_handling(demod));
6045         CHK_ERROR(bit_reverse_mpeg_output(demod));
6046         CHK_ERROR(set_mpeg_start_width(demod));
6047         {
6048                 /* TODO: move to set_standard after hardware reset value problem is solved */
6049                 /* Configure initial MPEG output */
6050                 drx_cfg_mpeg_output_t cfg_mpeg_output;
6051                 cfg_mpeg_output.enable_mpeg_output = true;
6052                 cfg_mpeg_output.insert_rs_byte = common_attr->mpeg_cfg.insert_rs_byte;
6053                 cfg_mpeg_output.enable_parallel =
6054                     common_attr->mpeg_cfg.enable_parallel;
6055                 cfg_mpeg_output.invert_data = common_attr->mpeg_cfg.invert_data;
6056                 cfg_mpeg_output.invert_err = common_attr->mpeg_cfg.invert_err;
6057                 cfg_mpeg_output.invert_str = common_attr->mpeg_cfg.invert_str;
6058                 cfg_mpeg_output.invert_val = common_attr->mpeg_cfg.invert_val;
6059                 cfg_mpeg_output.invert_clk = common_attr->mpeg_cfg.invert_clk;
6060                 cfg_mpeg_output.static_clk = common_attr->mpeg_cfg.static_clk;
6061                 cfg_mpeg_output.bitrate = common_attr->mpeg_cfg.bitrate;
6062                 CHK_ERROR(ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output));
6063         }
6064
6065         /* TBD: what parameters should be set */
6066         cmd_param = 0x00;       /* Default mode AGC on, etc */
6067         cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB
6068             | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM;
6069         cmd_scu.parameter_len = 1;
6070         cmd_scu.result_len = 1;
6071         cmd_scu.parameter = &cmd_param;
6072         cmd_scu.result = &cmd_result;
6073         CHK_ERROR(scu_command(dev_addr, &cmd_scu));
6074
6075         WR16(dev_addr, VSB_TOP_BEAGC_GAINSHIFT__A, 0x0004);
6076         WR16(dev_addr, VSB_TOP_SNRTH_PT__A, 0x00D2);
6077         WR16(dev_addr, VSB_TOP_SYSSMTRNCTRL__A, VSB_TOP_SYSSMTRNCTRL__PRE
6078              | VSB_TOP_SYSSMTRNCTRL_NCOTIMEOUTCNTEN__M);
6079         WR16(dev_addr, VSB_TOP_BEDETCTRL__A, 0x142);
6080         WR16(dev_addr, VSB_TOP_LBAGCREFLVL__A, 640);
6081         WR16(dev_addr, VSB_TOP_CYGN1ACQ__A, 4);
6082         WR16(dev_addr, VSB_TOP_CYGN1TRK__A, 2);
6083         WR16(dev_addr, VSB_TOP_CYGN2TRK__A, 3);
6084
6085         /* start demodulator */
6086         cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB
6087             | SCU_RAM_COMMAND_CMD_DEMOD_START;
6088         cmd_scu.parameter_len = 0;
6089         cmd_scu.result_len = 1;
6090         cmd_scu.parameter = NULL;
6091         cmd_scu.result = &cmd_result;
6092         CHK_ERROR(scu_command(dev_addr, &cmd_scu));
6093
6094         WR16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_ACTIVE);
6095         WR16(dev_addr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_ACTIVE);
6096         WR16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE);
6097
6098         return (DRX_STS_OK);
6099 rw_error:
6100         return (DRX_STS_ERROR);
6101 }
6102
6103 /**
6104 * \fn static short get_vsb_post_rs_pck_err(struct i2c_device_addr *dev_addr, u16 *PckErrs)
6105 * \brief Get the values of packet error in 8VSB mode
6106 * \return Error code
6107 */
6108 static int get_vsb_post_rs_pck_err(struct i2c_device_addr *dev_addr, u16 *pck_errs)
6109 {
6110         u16 data = 0;
6111         u16 period = 0;
6112         u16 prescale = 0;
6113         u16 packet_errorsMant = 0;
6114         u16 packet_errorsExp = 0;
6115
6116         RR16(dev_addr, FEC_RS_NR_FAILURES__A, &data);
6117         packet_errorsMant = data & FEC_RS_NR_FAILURES_FIXED_MANT__M;
6118         packet_errorsExp = (data & FEC_RS_NR_FAILURES_EXP__M)
6119             >> FEC_RS_NR_FAILURES_EXP__B;
6120         period = FEC_RS_MEASUREMENT_PERIOD;
6121         prescale = FEC_RS_MEASUREMENT_PRESCALE;
6122         /* packet error rate = (error packet number) per second */
6123         /* 77.3 us is time for per packet */
6124         CHK_ZERO(period * prescale);
6125         *pck_errs =
6126             (u16) frac_times1e6(packet_errorsMant * (1 << packet_errorsExp),
6127                                  (period * prescale * 77));
6128
6129         return (DRX_STS_OK);
6130 rw_error:
6131         return (DRX_STS_ERROR);
6132 }
6133
6134 /**
6135 * \fn static short GetVSBBer(struct i2c_device_addr *dev_addr, u32 *ber)
6136 * \brief Get the values of ber in VSB mode
6137 * \return Error code
6138 */
6139 static int get_vs_bpost_viterbi_ber(struct i2c_device_addr *dev_addr, u32 *ber)
6140 {
6141         u16 data = 0;
6142         u16 period = 0;
6143         u16 prescale = 0;
6144         u16 bit_errors_mant = 0;
6145         u16 bit_errors_exp = 0;
6146
6147         RR16(dev_addr, FEC_RS_NR_BIT_ERRORS__A, &data);
6148         period = FEC_RS_MEASUREMENT_PERIOD;
6149         prescale = FEC_RS_MEASUREMENT_PRESCALE;
6150
6151         bit_errors_mant = data & FEC_RS_NR_BIT_ERRORS_FIXED_MANT__M;
6152         bit_errors_exp = (data & FEC_RS_NR_BIT_ERRORS_EXP__M)
6153             >> FEC_RS_NR_BIT_ERRORS_EXP__B;
6154
6155         if (((bit_errors_mant << bit_errors_exp) >> 3) > 68700)
6156                 *ber = 26570;
6157         else {
6158                 CHK_ZERO(period * prescale);
6159                 *ber =
6160                     frac_times1e6(bit_errors_mant <<
6161                                  ((bit_errors_exp >
6162                                    2) ? (bit_errors_exp - 3) : bit_errors_exp),
6163                                  period * prescale * 207 *
6164                                  ((bit_errors_exp > 2) ? 1 : 8));
6165         }
6166
6167         return (DRX_STS_OK);
6168 rw_error:
6169         return (DRX_STS_ERROR);
6170 }
6171
6172 /**
6173 * \fn static short get_vs_bpre_viterbi_ber(struct i2c_device_addr *dev_addr, u32 *ber)
6174 * \brief Get the values of ber in VSB mode
6175 * \return Error code
6176 */
6177 static int get_vs_bpre_viterbi_ber(struct i2c_device_addr *dev_addr, u32 *ber)
6178 {
6179         u16 data = 0;
6180
6181         RR16(dev_addr, VSB_TOP_NR_SYM_ERRS__A, &data);
6182         *ber =
6183             frac_times1e6(data,
6184                          VSB_TOP_MEASUREMENT_PERIOD * SYMBOLS_PER_SEGMENT);
6185
6186         return (DRX_STS_OK);
6187 rw_error:
6188         return (DRX_STS_ERROR);
6189 }
6190
6191 /**
6192 * \fn static short get_vsb_symb_err(struct i2c_device_addr *dev_addr, u32 *ber)
6193 * \brief Get the values of ber in VSB mode
6194 * \return Error code
6195 */
6196 static int get_vsb_symb_err(struct i2c_device_addr *dev_addr, u32 *ser)
6197 {
6198         u16 data = 0;
6199         u16 period = 0;
6200         u16 prescale = 0;
6201         u16 symb_errors_mant = 0;
6202         u16 symb_errors_exp = 0;
6203
6204         RR16(dev_addr, FEC_RS_NR_SYMBOL_ERRORS__A, &data);
6205         period = FEC_RS_MEASUREMENT_PERIOD;
6206         prescale = FEC_RS_MEASUREMENT_PRESCALE;
6207
6208         symb_errors_mant = data & FEC_RS_NR_SYMBOL_ERRORS_FIXED_MANT__M;
6209         symb_errors_exp = (data & FEC_RS_NR_SYMBOL_ERRORS_EXP__M)
6210             >> FEC_RS_NR_SYMBOL_ERRORS_EXP__B;
6211
6212         CHK_ZERO(period * prescale);
6213         *ser = (u32) frac_times1e6((symb_errors_mant << symb_errors_exp) * 1000,
6214                                     (period * prescale * 77318));
6215
6216         return (DRX_STS_OK);
6217 rw_error:
6218         return (DRX_STS_ERROR);
6219 }
6220
6221 /**
6222 * \fn static int get_vsbmer(struct i2c_device_addr *dev_addr, u16 *mer)
6223 * \brief Get the values of MER
6224 * \return Error code
6225 */
6226 static int get_vsbmer(struct i2c_device_addr *dev_addr, u16 *mer)
6227 {
6228         u16 data_hi = 0;
6229
6230         RR16(dev_addr, VSB_TOP_ERR_ENERGY_H__A, &data_hi);
6231         *mer =
6232             (u16) (log1_times100(21504) - log1_times100((data_hi << 6) / 52));
6233
6234         return (DRX_STS_OK);
6235 rw_error:
6236         return (DRX_STS_ERROR);
6237 }
6238
6239 /*============================================================================*/
6240 /**
6241 * \fn int ctrl_get_vsb_constel()
6242 * \brief Retreive a VSB constellation point via I2C.
6243 * \param demod Pointer to demodulator instance.
6244 * \param complex_nr Pointer to the structure in which to store the
6245                    constellation point.
6246 * \return int.
6247 */
6248 static int
6249 ctrl_get_vsb_constel(pdrx_demod_instance_t demod, pdrx_complex_t complex_nr)
6250 {
6251         struct i2c_device_addr *dev_addr = NULL;
6252                                        /**< device address                    */
6253         u16 vsb_top_comm_mb = 0;               /**< VSB SL MB configuration           */
6254         u16 vsb_top_comm_mbInit = 0;    /**< VSB SL MB intial configuration    */
6255         u16 re = 0;                    /**< constellation Re part             */
6256         u32 data = 0;
6257
6258         /* read device info */
6259         dev_addr = demod->my_i2c_dev_addr;
6260
6261         /* TODO: */
6262         /* Monitor bus grabbing is an open external interface issue  */
6263         /* Needs to be checked when external interface PG is updated */
6264
6265         /* Configure MB (Monitor bus) */
6266         RR16(dev_addr, VSB_TOP_COMM_MB__A, &vsb_top_comm_mbInit);
6267         /* set observe flag & MB mux */
6268         vsb_top_comm_mb = (vsb_top_comm_mbInit |
6269                         VSB_TOP_COMM_MB_OBS_OBS_ON |
6270                         VSB_TOP_COMM_MB_MUX_OBS_VSB_TCMEQ_2);
6271         WR16(dev_addr, VSB_TOP_COMM_MB__A, vsb_top_comm_mb);
6272
6273         /* Enable MB grabber in the FEC OC */
6274         WR16(dev_addr, FEC_OC_OCR_MODE__A, FEC_OC_OCR_MODE_GRAB_ENABLE__M);
6275
6276         /* Disable MB grabber in the FEC OC */
6277         WR16(dev_addr, FEC_OC_OCR_MODE__A, 0x0);
6278
6279         /* read data */
6280         RR32(dev_addr, FEC_OC_OCR_GRAB_RD1__A, &data);
6281         re = (u16) (((data >> 10) & 0x300) | ((data >> 2) & 0xff));
6282         if (re & 0x0200) {
6283                 re |= 0xfc00;
6284         }
6285         complex_nr->re = re;
6286         complex_nr->im = 0;
6287
6288         /* Restore MB (Monitor bus) */
6289         WR16(dev_addr, VSB_TOP_COMM_MB__A, vsb_top_comm_mbInit);
6290
6291         return (DRX_STS_OK);
6292 rw_error:
6293         return (DRX_STS_ERROR);
6294 }
6295
6296 /*============================================================================*/
6297 /*==                     END 8VSB DATAPATH FUNCTIONS                        ==*/
6298 /*============================================================================*/
6299
6300 /*============================================================================*/
6301 /*============================================================================*/
6302 /*==                       QAM DATAPATH FUNCTIONS                           ==*/
6303 /*============================================================================*/
6304 /*============================================================================*/
6305
6306 /**
6307 * \fn int power_down_qam ()
6308 * \brief Powr down QAM related blocks.
6309 * \param demod instance of demodulator.
6310 * \param channel pointer to channel data.
6311 * \return int.
6312 */
6313 static int power_down_qam(pdrx_demod_instance_t demod, bool primary)
6314 {
6315         drxjscu_cmd_t cmd_scu = { /* command      */ 0,
6316                 /* parameter_len */ 0,
6317                 /* result_len    */ 0,
6318                 /* *parameter   */ NULL,
6319                 /* *result      */ NULL
6320         };
6321         u16 cmd_result = 0;
6322         struct i2c_device_addr *dev_addr = NULL;
6323         pdrxj_data_t ext_attr = NULL;
6324         drx_cfg_mpeg_output_t cfg_mpeg_output;
6325
6326         dev_addr = demod->my_i2c_dev_addr;
6327         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
6328
6329         /*
6330            STOP demodulator
6331            resets IQM, QAM and FEC HW blocks
6332          */
6333         /* stop all comm_exec */
6334         WR16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP);
6335         WR16(dev_addr, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP);
6336
6337         cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
6338             SCU_RAM_COMMAND_CMD_DEMOD_STOP;
6339         cmd_scu.parameter_len = 0;
6340         cmd_scu.result_len = 1;
6341         cmd_scu.parameter = NULL;
6342         cmd_scu.result = &cmd_result;
6343         CHK_ERROR(scu_command(dev_addr, &cmd_scu));
6344
6345         if (primary == true) {
6346                 WR16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP);
6347                 CHK_ERROR(set_iqm_af(demod, false));
6348         } else {
6349                 WR16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP);
6350                 WR16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP);
6351                 WR16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP);
6352                 WR16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP);
6353                 WR16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP);
6354         }
6355
6356         cfg_mpeg_output.enable_mpeg_output = false;
6357         CHK_ERROR(ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output));
6358
6359         return (DRX_STS_OK);
6360 rw_error:
6361         return (DRX_STS_ERROR);
6362 }
6363
6364 /*============================================================================*/
6365
6366 /**
6367 * \fn int set_qam_measurement ()
6368 * \brief Setup of the QAM Measuremnt intervals for signal quality
6369 * \param demod instance of demod.
6370 * \param constellation current constellation.
6371 * \return int.
6372 *
6373 *  NOTE:
6374 *  Take into account that for certain settings the errorcounters can overflow.
6375 *  The implementation does not check this.
6376 *
6377 *  TODO: overriding the ext_attr->fec_bits_desired by constellation dependent
6378 *  constants to get a measurement period of approx. 1 sec. Remove fec_bits_desired
6379 *  field ?
6380 *
6381 */
6382 #ifndef DRXJ_VSB_ONLY
6383 static int
6384 set_qam_measurement(pdrx_demod_instance_t demod,
6385                   enum drx_modulation constellation, u32 symbol_rate)
6386 {
6387         struct i2c_device_addr *dev_addr = NULL;        /* device address for I2C writes */
6388         pdrxj_data_t ext_attr = NULL;   /* Global data container for DRXJ specif data */
6389         u32 fec_bits_desired = 0;       /* BER accounting period */
6390         u16 fec_rs_plen = 0;    /* defines RS BER measurement period */
6391         u16 fec_rs_prescale = 0;        /* ReedSolomon Measurement Prescale */
6392         u32 fec_rs_period = 0;  /* Value for corresponding I2C register */
6393         u32 fec_rs_bit_cnt = 0; /* Actual precise amount of bits */
6394         u32 fec_oc_snc_fail_period = 0; /* Value for corresponding I2C register */
6395         u32 qam_vd_period = 0;  /* Value for corresponding I2C register */
6396         u32 qam_vd_bit_cnt = 0; /* Actual precise amount of bits */
6397         u16 fec_vd_plen = 0;    /* no of trellis symbols: VD SER measur period */
6398         u16 qam_vd_prescale = 0;        /* Viterbi Measurement Prescale */
6399
6400         dev_addr = demod->my_i2c_dev_addr;
6401         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
6402
6403         fec_bits_desired = ext_attr->fec_bits_desired;
6404         fec_rs_prescale = ext_attr->fec_rs_prescale;
6405
6406         switch (constellation) {
6407         case DRX_CONSTELLATION_QAM16:
6408                 fec_bits_desired = 4 * symbol_rate;
6409                 break;
6410         case DRX_CONSTELLATION_QAM32:
6411                 fec_bits_desired = 5 * symbol_rate;
6412                 break;
6413         case DRX_CONSTELLATION_QAM64:
6414                 fec_bits_desired = 6 * symbol_rate;
6415                 break;
6416         case DRX_CONSTELLATION_QAM128:
6417                 fec_bits_desired = 7 * symbol_rate;
6418                 break;
6419         case DRX_CONSTELLATION_QAM256:
6420                 fec_bits_desired = 8 * symbol_rate;
6421                 break;
6422         default:
6423                 return (DRX_STS_INVALID_ARG);
6424         }
6425
6426         /* Parameters for Reed-Solomon Decoder */
6427         /* fecrs_period = (int)ceil(FEC_BITS_DESIRED/(fecrs_prescale*plen)) */
6428         /* rs_bit_cnt   = fecrs_period*fecrs_prescale*plen                  */
6429         /*     result is within 32 bit arithmetic ->                        */
6430         /*     no need for mult or frac functions                           */
6431
6432         /* TODO: use constant instead of calculation and remove the fec_rs_plen in ext_attr */
6433         switch (ext_attr->standard) {
6434         case DRX_STANDARD_ITU_A:
6435         case DRX_STANDARD_ITU_C:
6436                 fec_rs_plen = 204 * 8;
6437                 break;
6438         case DRX_STANDARD_ITU_B:
6439                 fec_rs_plen = 128 * 7;
6440                 break;
6441         default:
6442                 return (DRX_STS_INVALID_ARG);
6443         }
6444
6445         ext_attr->fec_rs_plen = fec_rs_plen;    /* for getSigQual */
6446         fec_rs_bit_cnt = fec_rs_prescale * fec_rs_plen; /* temp storage   */
6447         CHK_ZERO(fec_rs_bit_cnt);
6448         fec_rs_period = fec_bits_desired / fec_rs_bit_cnt + 1;  /* ceil */
6449         if (ext_attr->standard != DRX_STANDARD_ITU_B)
6450                 fec_oc_snc_fail_period = fec_rs_period;
6451
6452         /* limit to max 16 bit value (I2C register width) if needed */
6453         if (fec_rs_period > 0xFFFF)
6454                 fec_rs_period = 0xFFFF;
6455
6456         /* write corresponding registers */
6457         switch (ext_attr->standard) {
6458         case DRX_STANDARD_ITU_A:
6459         case DRX_STANDARD_ITU_C:
6460                 break;
6461         case DRX_STANDARD_ITU_B:
6462                 switch (constellation) {
6463                 case DRX_CONSTELLATION_QAM64:
6464                         fec_rs_period = 31581;
6465                         fec_oc_snc_fail_period = 17932;
6466                         break;
6467                 case DRX_CONSTELLATION_QAM256:
6468                         fec_rs_period = 45446;
6469                         fec_oc_snc_fail_period = 25805;
6470                         break;
6471                 default:
6472                         return (DRX_STS_INVALID_ARG);
6473                 }
6474                 break;
6475         default:
6476                 return (DRX_STS_INVALID_ARG);
6477         }
6478
6479         WR16(dev_addr, FEC_OC_SNC_FAIL_PERIOD__A, (u16) fec_oc_snc_fail_period);
6480         WR16(dev_addr, FEC_RS_MEASUREMENT_PERIOD__A, (u16) fec_rs_period);
6481         WR16(dev_addr, FEC_RS_MEASUREMENT_PRESCALE__A, fec_rs_prescale);
6482         ext_attr->fec_rs_period = (u16) fec_rs_period;
6483         ext_attr->fec_rs_prescale = fec_rs_prescale;
6484         WR32(dev_addr, SCU_RAM_FEC_ACCUM_CW_CORRECTED_LO__A, 0);
6485         WR16(dev_addr, SCU_RAM_FEC_MEAS_COUNT__A, 0);
6486         WR16(dev_addr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0);
6487
6488         if (ext_attr->standard == DRX_STANDARD_ITU_B) {
6489                 /* Parameters for Viterbi Decoder */
6490                 /* qamvd_period = (int)ceil(FEC_BITS_DESIRED/                      */
6491                 /*                    (qamvd_prescale*plen*(qam_constellation+1))) */
6492                 /* vd_bit_cnt   = qamvd_period*qamvd_prescale*plen                 */
6493                 /*     result is within 32 bit arithmetic ->                       */
6494                 /*     no need for mult or frac functions                          */
6495
6496                 /* a(8 bit) * b(8 bit) = 16 bit result => mult32 not needed */
6497                 fec_vd_plen = ext_attr->fec_vd_plen;
6498                 qam_vd_prescale = ext_attr->qam_vd_prescale;
6499                 qam_vd_bit_cnt = qam_vd_prescale * fec_vd_plen; /* temp storage */
6500
6501                 switch (constellation) {
6502                 case DRX_CONSTELLATION_QAM64:
6503                         /* a(16 bit) * b(4 bit) = 20 bit result => mult32 not needed */
6504                         qam_vd_period =
6505                             qam_vd_bit_cnt * (QAM_TOP_CONSTELLATION_QAM64 + 1)
6506                             * (QAM_TOP_CONSTELLATION_QAM64 + 1);
6507                         break;
6508                 case DRX_CONSTELLATION_QAM256:
6509                         /* a(16 bit) * b(5 bit) = 21 bit result => mult32 not needed */
6510                         qam_vd_period =
6511                             qam_vd_bit_cnt * (QAM_TOP_CONSTELLATION_QAM256 + 1)
6512                             * (QAM_TOP_CONSTELLATION_QAM256 + 1);
6513                         break;
6514                 default:
6515                         return (DRX_STS_INVALID_ARG);
6516                 }
6517                 CHK_ZERO(qam_vd_period);
6518                 qam_vd_period = fec_bits_desired / qam_vd_period;
6519                 /* limit to max 16 bit value (I2C register width) if needed */
6520                 if (qam_vd_period > 0xFFFF)
6521                         qam_vd_period = 0xFFFF;
6522
6523                 /* a(16 bit) * b(16 bit) = 32 bit result => mult32 not needed */
6524                 qam_vd_bit_cnt *= qam_vd_period;
6525
6526                 WR16(dev_addr, QAM_VD_MEASUREMENT_PERIOD__A,
6527                      (u16) qam_vd_period);
6528                 WR16(dev_addr, QAM_VD_MEASUREMENT_PRESCALE__A, qam_vd_prescale);
6529                 ext_attr->qam_vd_period = (u16) qam_vd_period;
6530                 ext_attr->qam_vd_prescale = qam_vd_prescale;
6531         }
6532
6533         return (DRX_STS_OK);
6534 rw_error:
6535         return (DRX_STS_ERROR);
6536 }
6537
6538 /*============================================================================*/
6539
6540 /**
6541 * \fn int set_qam16 ()
6542 * \brief QAM16 specific setup
6543 * \param demod instance of demod.
6544 * \return int.
6545 */
6546 static int set_qam16(pdrx_demod_instance_t demod)
6547 {
6548         struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
6549         const u8 qam_dq_qual_fun[] = {
6550                 DRXJ_16TO8(2),  /* fun0  */
6551                 DRXJ_16TO8(2),  /* fun1  */
6552                 DRXJ_16TO8(2),  /* fun2  */
6553                 DRXJ_16TO8(2),  /* fun3  */
6554                 DRXJ_16TO8(3),  /* fun4  */
6555                 DRXJ_16TO8(3),  /* fun5  */
6556         };
6557         const u8 qam_eq_cma_rad[] = {
6558                 DRXJ_16TO8(13517),      /* RAD0  */
6559                 DRXJ_16TO8(13517),      /* RAD1  */
6560                 DRXJ_16TO8(13517),      /* RAD2  */
6561                 DRXJ_16TO8(13517),      /* RAD3  */
6562                 DRXJ_16TO8(13517),      /* RAD4  */
6563                 DRXJ_16TO8(13517),      /* RAD5  */
6564         };
6565
6566         WRB(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun),
6567             ((u8 *) qam_dq_qual_fun));
6568         WRB(dev_addr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qam_eq_cma_rad),
6569             ((u8 *) qam_eq_cma_rad));
6570
6571         WR16(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 140);
6572         WR16(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 50);
6573         WR16(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 120);
6574         WR16(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 230);
6575         WR16(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 95);
6576         WR16(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 105);
6577
6578         WR16(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
6579         WR16(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 56);
6580         WR16(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3);
6581
6582         WR16(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 16);
6583         WR16(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 220);
6584         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 25);
6585         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 6);
6586         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) (-24));
6587         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) (-65));
6588         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) (-127));
6589
6590         WR16(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15);
6591         WR16(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
6592         WR16(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2);
6593         WR16(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20);
6594         WR16(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255);
6595         WR16(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2);
6596         WR16(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 10);
6597         WR16(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
6598         WR16(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12);
6599         WR16(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
6600         WR16(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
6601         WR16(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12);
6602         WR16(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
6603         WR16(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
6604         WR16(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16);
6605         WR16(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 32);
6606         WR16(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 240);
6607         WR16(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
6608         WR16(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15);
6609         WR16(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 32);
6610
6611         WR16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 40960);
6612
6613         return (DRX_STS_OK);
6614 rw_error:
6615         return (DRX_STS_ERROR);
6616 }
6617
6618 /*============================================================================*/
6619
6620 /**
6621 * \fn int set_qam32 ()
6622 * \brief QAM32 specific setup
6623 * \param demod instance of demod.
6624 * \return int.
6625 */
6626 static int set_qam32(pdrx_demod_instance_t demod)
6627 {
6628         struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
6629         const u8 qam_dq_qual_fun[] = {
6630                 DRXJ_16TO8(3),  /* fun0  */
6631                 DRXJ_16TO8(3),  /* fun1  */
6632                 DRXJ_16TO8(3),  /* fun2  */
6633                 DRXJ_16TO8(3),  /* fun3  */
6634                 DRXJ_16TO8(4),  /* fun4  */
6635                 DRXJ_16TO8(4),  /* fun5  */
6636         };
6637         const u8 qam_eq_cma_rad[] = {
6638                 DRXJ_16TO8(6707),       /* RAD0  */
6639                 DRXJ_16TO8(6707),       /* RAD1  */
6640                 DRXJ_16TO8(6707),       /* RAD2  */
6641                 DRXJ_16TO8(6707),       /* RAD3  */
6642                 DRXJ_16TO8(6707),       /* RAD4  */
6643                 DRXJ_16TO8(6707),       /* RAD5  */
6644         };
6645
6646         WRB(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun),
6647             ((u8 *) qam_dq_qual_fun));
6648         WRB(dev_addr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qam_eq_cma_rad),
6649             ((u8 *) qam_eq_cma_rad));
6650
6651         WR16(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 90);
6652         WR16(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 50);
6653         WR16(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 100);
6654         WR16(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 170);
6655         WR16(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 80);
6656         WR16(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 100);
6657
6658         WR16(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
6659         WR16(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 56);
6660         WR16(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3);
6661
6662         WR16(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 12);
6663         WR16(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 140);
6664         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) (-8));
6665         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) (-16));
6666         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) (-26));
6667         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) (-56));
6668         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) (-86));
6669
6670         WR16(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15);
6671         WR16(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
6672         WR16(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2);
6673         WR16(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20);
6674         WR16(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255);
6675         WR16(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2);
6676         WR16(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 10);
6677         WR16(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
6678         WR16(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12);
6679         WR16(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
6680         WR16(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
6681         WR16(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12);
6682         WR16(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
6683         WR16(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
6684         WR16(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16);
6685         WR16(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 32);
6686         WR16(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 176);
6687         WR16(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
6688         WR16(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15);
6689         WR16(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 8);
6690
6691         WR16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 20480);
6692
6693         return (DRX_STS_OK);
6694 rw_error:
6695         return (DRX_STS_ERROR);
6696 }
6697
6698 /*============================================================================*/
6699
6700 /**
6701 * \fn int set_qam64 ()
6702 * \brief QAM64 specific setup
6703 * \param demod instance of demod.
6704 * \return int.
6705 */
6706 static int set_qam64(pdrx_demod_instance_t demod)
6707 {
6708         struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
6709         const u8 qam_dq_qual_fun[] = {  /* this is hw reset value. no necessary to re-write */
6710                 DRXJ_16TO8(4),  /* fun0  */
6711                 DRXJ_16TO8(4),  /* fun1  */
6712                 DRXJ_16TO8(4),  /* fun2  */
6713                 DRXJ_16TO8(4),  /* fun3  */
6714                 DRXJ_16TO8(6),  /* fun4  */
6715                 DRXJ_16TO8(6),  /* fun5  */
6716         };
6717         const u8 qam_eq_cma_rad[] = {
6718                 DRXJ_16TO8(13336),      /* RAD0  */
6719                 DRXJ_16TO8(12618),      /* RAD1  */
6720                 DRXJ_16TO8(11988),      /* RAD2  */
6721                 DRXJ_16TO8(13809),      /* RAD3  */
6722                 DRXJ_16TO8(13809),      /* RAD4  */
6723                 DRXJ_16TO8(15609),      /* RAD5  */
6724         };
6725
6726         WRB(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun),
6727             ((u8 *) qam_dq_qual_fun));
6728         WRB(dev_addr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qam_eq_cma_rad),
6729             ((u8 *) qam_eq_cma_rad));
6730
6731         WR16(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 105);
6732         WR16(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 60);
6733         WR16(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 100);
6734         WR16(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 195);
6735         WR16(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 80);
6736         WR16(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 84);
6737
6738         WR16(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
6739         WR16(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 32);
6740         WR16(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3);
6741
6742         WR16(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 12);
6743         WR16(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 141);
6744         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 7);
6745         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 0);
6746         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) (-15));
6747         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) (-45));
6748         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) (-80));
6749
6750         WR16(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15);
6751         WR16(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
6752         WR16(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2);
6753         WR16(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 30);
6754         WR16(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255);
6755         WR16(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2);
6756         WR16(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 15);
6757         WR16(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 80);
6758         WR16(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12);
6759         WR16(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
6760         WR16(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
6761         WR16(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12);
6762         WR16(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
6763         WR16(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
6764         WR16(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16);
6765         WR16(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 48);
6766         WR16(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 160);
6767         WR16(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
6768         WR16(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15);
6769         WR16(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 32);
6770
6771         WR16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 43008);
6772
6773         return (DRX_STS_OK);
6774 rw_error:
6775         return (DRX_STS_ERROR);
6776 }
6777
6778 /*============================================================================*/
6779
6780 /**
6781 * \fn int set_qam128 ()
6782 * \brief QAM128 specific setup
6783 * \param demod: instance of demod.
6784 * \return int.
6785 */
6786 static int set_qam128(pdrx_demod_instance_t demod)
6787 {
6788         struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
6789         const u8 qam_dq_qual_fun[] = {
6790                 DRXJ_16TO8(6),  /* fun0  */
6791                 DRXJ_16TO8(6),  /* fun1  */
6792                 DRXJ_16TO8(6),  /* fun2  */
6793                 DRXJ_16TO8(6),  /* fun3  */
6794                 DRXJ_16TO8(9),  /* fun4  */
6795                 DRXJ_16TO8(9),  /* fun5  */
6796         };
6797         const u8 qam_eq_cma_rad[] = {
6798                 DRXJ_16TO8(6164),       /* RAD0  */
6799                 DRXJ_16TO8(6598),       /* RAD1  */
6800                 DRXJ_16TO8(6394),       /* RAD2  */
6801                 DRXJ_16TO8(6409),       /* RAD3  */
6802                 DRXJ_16TO8(6656),       /* RAD4  */
6803                 DRXJ_16TO8(7238),       /* RAD5  */
6804         };
6805
6806         WRB(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun),
6807             ((u8 *) qam_dq_qual_fun));
6808         WRB(dev_addr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qam_eq_cma_rad),
6809             ((u8 *) qam_eq_cma_rad));
6810
6811         WR16(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 50);
6812         WR16(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 60);
6813         WR16(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 100);
6814         WR16(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 140);
6815         WR16(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 80);
6816         WR16(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 100);
6817
6818         WR16(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
6819         WR16(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 32);
6820         WR16(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3);
6821
6822         WR16(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 8);
6823         WR16(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 65);
6824         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 5);
6825         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 3);
6826         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) (-1));
6827         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, 12);
6828         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) (-23));
6829
6830         WR16(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15);
6831         WR16(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
6832         WR16(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2);
6833         WR16(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 40);
6834         WR16(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255);
6835         WR16(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2);
6836         WR16(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 20);
6837         WR16(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 80);
6838         WR16(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12);
6839         WR16(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
6840         WR16(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
6841         WR16(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12);
6842         WR16(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
6843         WR16(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
6844         WR16(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16);
6845         WR16(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 32);
6846         WR16(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 144);
6847         WR16(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
6848         WR16(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15);
6849         WR16(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 16);
6850
6851         WR16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 20992);
6852
6853         return (DRX_STS_OK);
6854 rw_error:
6855         return (DRX_STS_ERROR);
6856 }
6857
6858 /*============================================================================*/
6859
6860 /**
6861 * \fn int set_qam256 ()
6862 * \brief QAM256 specific setup
6863 * \param demod: instance of demod.
6864 * \return int.
6865 */
6866 static int set_qam256(pdrx_demod_instance_t demod)
6867 {
6868         struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
6869         const u8 qam_dq_qual_fun[] = {
6870                 DRXJ_16TO8(8),  /* fun0  */
6871                 DRXJ_16TO8(8),  /* fun1  */
6872                 DRXJ_16TO8(8),  /* fun2  */
6873                 DRXJ_16TO8(8),  /* fun3  */
6874                 DRXJ_16TO8(12), /* fun4  */
6875                 DRXJ_16TO8(12), /* fun5  */
6876         };
6877         const u8 qam_eq_cma_rad[] = {
6878                 DRXJ_16TO8(12345),      /* RAD0  */
6879                 DRXJ_16TO8(12345),      /* RAD1  */
6880                 DRXJ_16TO8(13626),      /* RAD2  */
6881                 DRXJ_16TO8(12931),      /* RAD3  */
6882                 DRXJ_16TO8(14719),      /* RAD4  */
6883                 DRXJ_16TO8(15356),      /* RAD5  */
6884         };
6885
6886         WRB(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun),
6887             ((u8 *) qam_dq_qual_fun));
6888         WRB(dev_addr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qam_eq_cma_rad),
6889             ((u8 *) qam_eq_cma_rad));
6890
6891         WR16(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 50);
6892         WR16(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 60);
6893         WR16(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 100);
6894         WR16(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 150);
6895         WR16(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 80);
6896         WR16(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 110);
6897
6898         WR16(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
6899         WR16(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 16);
6900         WR16(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3);
6901
6902         WR16(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 8);
6903         WR16(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 74);
6904         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 18);
6905         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 13);
6906         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, 7);
6907         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, 0);
6908         WR16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) (-8));
6909
6910         WR16(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15);
6911         WR16(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
6912         WR16(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2);
6913         WR16(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 50);
6914         WR16(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255);
6915         WR16(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2);
6916         WR16(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 25);
6917         WR16(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 80);
6918         WR16(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12);
6919         WR16(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
6920         WR16(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
6921         WR16(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12);
6922         WR16(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
6923         WR16(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
6924         WR16(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16);
6925         WR16(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 48);
6926         WR16(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 80);
6927         WR16(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
6928         WR16(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15);
6929         WR16(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 16);
6930
6931         WR16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 43520);
6932
6933         return (DRX_STS_OK);
6934 rw_error:
6935         return (DRX_STS_ERROR);
6936 }
6937
6938 /*============================================================================*/
6939 #define QAM_SET_OP_ALL 0x1
6940 #define QAM_SET_OP_CONSTELLATION 0x2
6941 #define QAM_SET_OP_SPECTRUM 0X4
6942
6943 /**
6944 * \fn int set_qam ()
6945 * \brief Set QAM demod.
6946 * \param demod:   instance of demod.
6947 * \param channel: pointer to channel data.
6948 * \return int.
6949 */
6950 static int
6951 set_qam(pdrx_demod_instance_t demod,
6952        pdrx_channel_t channel, s32 tuner_freq_offset, u32 op)
6953 {
6954         struct i2c_device_addr *dev_addr = NULL;
6955         pdrxj_data_t ext_attr = NULL;
6956         pdrx_common_attr_t common_attr = NULL;
6957         u16 cmd_result = 0;
6958         u32 adc_frequency = 0;
6959         u32 iqm_rc_rate = 0;
6960         u16 lc_symbol_freq = 0;
6961         u16 iqm_rc_stretch = 0;
6962         u16 set_env_parameters = 0;
6963         u16 set_param_parameters[2] = { 0 };
6964         drxjscu_cmd_t cmd_scu = { /* command      */ 0,
6965                 /* parameter_len */ 0,
6966                 /* result_len    */ 0,
6967                 /* parameter    */ NULL,
6968                 /* result       */ NULL
6969         };
6970         const u8 qam_a_taps[] = {
6971                 DRXJ_16TO8(-1), /* re0  */
6972                 DRXJ_16TO8(1),  /* re1  */
6973                 DRXJ_16TO8(1),  /* re2  */
6974                 DRXJ_16TO8(-1), /* re3  */
6975                 DRXJ_16TO8(-1), /* re4  */
6976                 DRXJ_16TO8(2),  /* re5  */
6977                 DRXJ_16TO8(1),  /* re6  */
6978                 DRXJ_16TO8(-2), /* re7  */
6979                 DRXJ_16TO8(0),  /* re8  */
6980                 DRXJ_16TO8(3),  /* re9  */
6981                 DRXJ_16TO8(-1), /* re10 */
6982                 DRXJ_16TO8(-3), /* re11 */
6983                 DRXJ_16TO8(4),  /* re12 */
6984                 DRXJ_16TO8(1),  /* re13 */
6985                 DRXJ_16TO8(-8), /* re14 */
6986                 DRXJ_16TO8(4),  /* re15 */
6987                 DRXJ_16TO8(13), /* re16 */
6988                 DRXJ_16TO8(-13),        /* re17 */
6989                 DRXJ_16TO8(-19),        /* re18 */
6990                 DRXJ_16TO8(28), /* re19 */
6991                 DRXJ_16TO8(25), /* re20 */
6992                 DRXJ_16TO8(-53),        /* re21 */
6993                 DRXJ_16TO8(-31),        /* re22 */
6994                 DRXJ_16TO8(96), /* re23 */
6995                 DRXJ_16TO8(37), /* re24 */
6996                 DRXJ_16TO8(-190),       /* re25 */
6997                 DRXJ_16TO8(-40),        /* re26 */
6998                 DRXJ_16TO8(619) /* re27 */
6999         };
7000         const u8 qam_b64_taps[] = {
7001                 DRXJ_16TO8(0),  /* re0  */
7002                 DRXJ_16TO8(-2), /* re1  */
7003                 DRXJ_16TO8(1),  /* re2  */
7004                 DRXJ_16TO8(2),  /* re3  */
7005                 DRXJ_16TO8(-2), /* re4  */
7006                 DRXJ_16TO8(0),  /* re5  */
7007                 DRXJ_16TO8(4),  /* re6  */
7008                 DRXJ_16TO8(-2), /* re7  */
7009                 DRXJ_16TO8(-4), /* re8  */
7010                 DRXJ_16TO8(4),  /* re9  */
7011                 DRXJ_16TO8(3),  /* re10 */
7012                 DRXJ_16TO8(-6), /* re11 */
7013                 DRXJ_16TO8(0),  /* re12 */
7014                 DRXJ_16TO8(6),  /* re13 */
7015                 DRXJ_16TO8(-5), /* re14 */
7016                 DRXJ_16TO8(-3), /* re15 */
7017                 DRXJ_16TO8(11), /* re16 */
7018                 DRXJ_16TO8(-4), /* re17 */
7019                 DRXJ_16TO8(-19),        /* re18 */
7020                 DRXJ_16TO8(19), /* re19 */
7021                 DRXJ_16TO8(28), /* re20 */
7022                 DRXJ_16TO8(-45),        /* re21 */
7023                 DRXJ_16TO8(-36),        /* re22 */
7024                 DRXJ_16TO8(90), /* re23 */
7025                 DRXJ_16TO8(42), /* re24 */
7026                 DRXJ_16TO8(-185),       /* re25 */
7027                 DRXJ_16TO8(-46),        /* re26 */
7028                 DRXJ_16TO8(614) /* re27 */
7029         };
7030         const u8 qam_b256_taps[] = {
7031                 DRXJ_16TO8(-2), /* re0  */
7032                 DRXJ_16TO8(4),  /* re1  */
7033                 DRXJ_16TO8(1),  /* re2  */
7034                 DRXJ_16TO8(-4), /* re3  */
7035                 DRXJ_16TO8(0),  /* re4  */
7036                 DRXJ_16TO8(4),  /* re5  */
7037                 DRXJ_16TO8(-2), /* re6  */
7038                 DRXJ_16TO8(-4), /* re7  */
7039                 DRXJ_16TO8(5),  /* re8  */
7040                 DRXJ_16TO8(2),  /* re9  */
7041                 DRXJ_16TO8(-8), /* re10 */
7042                 DRXJ_16TO8(2),  /* re11 */
7043                 DRXJ_16TO8(11), /* re12 */
7044                 DRXJ_16TO8(-8), /* re13 */
7045                 DRXJ_16TO8(-15),        /* re14 */
7046                 DRXJ_16TO8(16), /* re15 */
7047                 DRXJ_16TO8(19), /* re16 */
7048                 DRXJ_16TO8(-27),        /* re17 */
7049                 DRXJ_16TO8(-22),        /* re18 */
7050                 DRXJ_16TO8(44), /* re19 */
7051                 DRXJ_16TO8(26), /* re20 */
7052                 DRXJ_16TO8(-69),        /* re21 */
7053                 DRXJ_16TO8(-28),        /* re22 */
7054                 DRXJ_16TO8(110),        /* re23 */
7055                 DRXJ_16TO8(31), /* re24 */
7056                 DRXJ_16TO8(-201),       /* re25 */
7057                 DRXJ_16TO8(-32),        /* re26 */
7058                 DRXJ_16TO8(628) /* re27 */
7059         };
7060         const u8 qam_c_taps[] = {
7061                 DRXJ_16TO8(-3), /* re0  */
7062                 DRXJ_16TO8(3),  /* re1  */
7063                 DRXJ_16TO8(2),  /* re2  */
7064                 DRXJ_16TO8(-4), /* re3  */
7065                 DRXJ_16TO8(0),  /* re4  */
7066                 DRXJ_16TO8(4),  /* re5  */
7067                 DRXJ_16TO8(-1), /* re6  */
7068                 DRXJ_16TO8(-4), /* re7  */
7069                 DRXJ_16TO8(3),  /* re8  */
7070                 DRXJ_16TO8(3),  /* re9  */
7071                 DRXJ_16TO8(-5), /* re10 */
7072                 DRXJ_16TO8(0),  /* re11 */
7073                 DRXJ_16TO8(9),  /* re12 */
7074                 DRXJ_16TO8(-4), /* re13 */
7075                 DRXJ_16TO8(-12),        /* re14 */
7076                 DRXJ_16TO8(10), /* re15 */
7077                 DRXJ_16TO8(16), /* re16 */
7078                 DRXJ_16TO8(-21),        /* re17 */
7079                 DRXJ_16TO8(-20),        /* re18 */
7080                 DRXJ_16TO8(37), /* re19 */
7081                 DRXJ_16TO8(25), /* re20 */
7082                 DRXJ_16TO8(-62),        /* re21 */
7083                 DRXJ_16TO8(-28),        /* re22 */
7084                 DRXJ_16TO8(105),        /* re23 */
7085                 DRXJ_16TO8(31), /* re24 */
7086                 DRXJ_16TO8(-197),       /* re25 */
7087                 DRXJ_16TO8(-33),        /* re26 */
7088                 DRXJ_16TO8(626) /* re27 */
7089         };
7090
7091         dev_addr = demod->my_i2c_dev_addr;
7092         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
7093         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
7094
7095         if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
7096                 if (ext_attr->standard == DRX_STANDARD_ITU_B) {
7097                         switch (channel->constellation) {
7098                         case DRX_CONSTELLATION_QAM256:
7099                                 iqm_rc_rate = 0x00AE3562;
7100                                 lc_symbol_freq =
7101                                     QAM_LC_SYMBOL_FREQ_FREQ_QAM_B_256;
7102                                 channel->symbolrate = 5360537;
7103                                 iqm_rc_stretch = IQM_RC_STRETCH_QAM_B_256;
7104                                 break;
7105                         case DRX_CONSTELLATION_QAM64:
7106                                 iqm_rc_rate = 0x00C05A0E;
7107                                 lc_symbol_freq = 409;
7108                                 channel->symbolrate = 5056941;
7109                                 iqm_rc_stretch = IQM_RC_STRETCH_QAM_B_64;
7110                                 break;
7111                         default:
7112                                 return (DRX_STS_INVALID_ARG);
7113                         }
7114                 } else {
7115                         adc_frequency = (common_attr->sys_clock_freq * 1000) / 3;
7116                         CHK_ZERO(channel->symbolrate);
7117                         iqm_rc_rate =
7118                             (adc_frequency / channel->symbolrate) * (1 << 21) +
7119                             (frac28
7120                              ((adc_frequency % channel->symbolrate),
7121                               channel->symbolrate) >> 7) - (1 << 23);
7122                         lc_symbol_freq =
7123                             (u16) (frac28
7124                                      (channel->symbolrate +
7125                                       (adc_frequency >> 13),
7126                                       adc_frequency) >> 16);
7127                         if (lc_symbol_freq > 511)
7128                                 lc_symbol_freq = 511;
7129
7130                         iqm_rc_stretch = 21;
7131                 }
7132
7133                 if (ext_attr->standard == DRX_STANDARD_ITU_A) {
7134                         set_env_parameters = QAM_TOP_ANNEX_A;   /* annex             */
7135                         set_param_parameters[0] = channel->constellation;       /* constellation     */
7136                         set_param_parameters[1] = DRX_INTERLEAVEMODE_I12_J17;   /* interleave mode   */
7137                 } else if (ext_attr->standard == DRX_STANDARD_ITU_B) {
7138                         set_env_parameters = QAM_TOP_ANNEX_B;   /* annex             */
7139                         set_param_parameters[0] = channel->constellation;       /* constellation     */
7140                         set_param_parameters[1] = channel->interleavemode;      /* interleave mode   */
7141                 } else if (ext_attr->standard == DRX_STANDARD_ITU_C) {
7142                         set_env_parameters = QAM_TOP_ANNEX_C;   /* annex             */
7143                         set_param_parameters[0] = channel->constellation;       /* constellation     */
7144                         set_param_parameters[1] = DRX_INTERLEAVEMODE_I12_J17;   /* interleave mode   */
7145                 } else {
7146                         return (DRX_STS_INVALID_ARG);
7147                 }
7148         }
7149
7150         if (op & QAM_SET_OP_ALL) {
7151                 /*
7152                    STEP 1: reset demodulator
7153                    resets IQM, QAM and FEC HW blocks
7154                    resets SCU variables
7155                  */
7156                 /* stop all comm_exec */
7157                 WR16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP);
7158                 WR16(dev_addr, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP);
7159                 WR16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP);
7160                 WR16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP);
7161                 WR16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP);
7162                 WR16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP);
7163                 WR16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP);
7164
7165                 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
7166                     SCU_RAM_COMMAND_CMD_DEMOD_RESET;
7167                 cmd_scu.parameter_len = 0;
7168                 cmd_scu.result_len = 1;
7169                 cmd_scu.parameter = NULL;
7170                 cmd_scu.result = &cmd_result;
7171                 CHK_ERROR(scu_command(dev_addr, &cmd_scu));
7172         }
7173
7174         if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
7175                 /*
7176                    STEP 2: configure demodulator
7177                    -set env
7178                    -set params (resets IQM,QAM,FEC HW; initializes some SCU variables )
7179                  */
7180                 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
7181                     SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV;
7182                 cmd_scu.parameter_len = 1;
7183                 cmd_scu.result_len = 1;
7184                 cmd_scu.parameter = &set_env_parameters;
7185                 cmd_scu.result = &cmd_result;
7186                 CHK_ERROR(scu_command(dev_addr, &cmd_scu));
7187
7188                 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
7189                     SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM;
7190                 cmd_scu.parameter_len = 2;
7191                 cmd_scu.result_len = 1;
7192                 cmd_scu.parameter = set_param_parameters;
7193                 cmd_scu.result = &cmd_result;
7194                 CHK_ERROR(scu_command(dev_addr, &cmd_scu));
7195                 /* set symbol rate */
7196                 WR32(dev_addr, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate);
7197                 ext_attr->iqm_rc_rate_ofs = iqm_rc_rate;
7198                 CHK_ERROR(set_qam_measurement
7199                           (demod, channel->constellation, channel->symbolrate));
7200         }
7201         /* STEP 3: enable the system in a mode where the ADC provides valid signal
7202            setup constellation independent registers */
7203         /* from qam_cmd.py script (qam_driver_b) */
7204         /* TODO: remove re-writes of HW reset values */
7205         if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_SPECTRUM)) {
7206                 CHK_ERROR(set_frequency(demod, channel, tuner_freq_offset));
7207         }
7208
7209         if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
7210
7211                 WR16(dev_addr, QAM_LC_SYMBOL_FREQ__A, lc_symbol_freq);
7212                 WR16(dev_addr, IQM_RC_STRETCH__A, iqm_rc_stretch);
7213         }
7214
7215         if (op & QAM_SET_OP_ALL) {
7216                 if (ext_attr->has_lna == false) {
7217                         WR16(dev_addr, IQM_AF_AMUX__A, 0x02);
7218                 }
7219                 WR16(dev_addr, IQM_CF_SYMMETRIC__A, 0);
7220                 WR16(dev_addr, IQM_CF_MIDTAP__A, 3);
7221                 WR16(dev_addr, IQM_CF_OUT_ENA__A, IQM_CF_OUT_ENA_QAM__M);
7222
7223                 WR16(dev_addr, SCU_RAM_QAM_WR_RSV_0__A, 0x5f);  /* scu temporary shut down agc */
7224
7225                 WR16(dev_addr, IQM_AF_SYNC_SEL__A, 3);
7226                 WR16(dev_addr, IQM_AF_CLP_LEN__A, 0);
7227                 WR16(dev_addr, IQM_AF_CLP_TH__A, 448);
7228                 WR16(dev_addr, IQM_AF_SNS_LEN__A, 0);
7229                 WR16(dev_addr, IQM_AF_PDREF__A, 4);
7230                 WR16(dev_addr, IQM_AF_STDBY__A, 0x10);
7231                 WR16(dev_addr, IQM_AF_PGA_GAIN__A, 11);
7232
7233                 WR16(dev_addr, IQM_CF_POW_MEAS_LEN__A, 1);
7234                 WR16(dev_addr, IQM_CF_SCALE_SH__A, IQM_CF_SCALE_SH__PRE);       /*! reset default val ! */
7235
7236                 WR16(dev_addr, QAM_SY_TIMEOUT__A, QAM_SY_TIMEOUT__PRE); /*! reset default val ! */
7237                 if (ext_attr->standard == DRX_STANDARD_ITU_B) {
7238                         WR16(dev_addr, QAM_SY_SYNC_LWM__A, QAM_SY_SYNC_LWM__PRE);       /*! reset default val ! */
7239                         WR16(dev_addr, QAM_SY_SYNC_AWM__A, QAM_SY_SYNC_AWM__PRE);       /*! reset default val ! */
7240                         WR16(dev_addr, QAM_SY_SYNC_HWM__A, QAM_SY_SYNC_HWM__PRE);       /*! reset default val ! */
7241                 } else {
7242                         switch (channel->constellation) {
7243                         case DRX_CONSTELLATION_QAM16:
7244                         case DRX_CONSTELLATION_QAM64:
7245                         case DRX_CONSTELLATION_QAM256:
7246                                 WR16(dev_addr, QAM_SY_SYNC_LWM__A, 0x03);
7247                                 WR16(dev_addr, QAM_SY_SYNC_AWM__A, 0x04);
7248                                 WR16(dev_addr, QAM_SY_SYNC_HWM__A, QAM_SY_SYNC_HWM__PRE);       /*! reset default val ! */
7249                                 break;
7250                         case DRX_CONSTELLATION_QAM32:
7251                         case DRX_CONSTELLATION_QAM128:
7252                                 WR16(dev_addr, QAM_SY_SYNC_LWM__A, 0x03);
7253                                 WR16(dev_addr, QAM_SY_SYNC_AWM__A, 0x05);
7254                                 WR16(dev_addr, QAM_SY_SYNC_HWM__A, 0x06);
7255                                 break;
7256                         default:
7257                                 return (DRX_STS_ERROR);
7258                         }       /* switch */
7259                 }
7260
7261                 WR16(dev_addr, QAM_LC_MODE__A, QAM_LC_MODE__PRE);       /*! reset default val ! */
7262                 WR16(dev_addr, QAM_LC_RATE_LIMIT__A, 3);
7263                 WR16(dev_addr, QAM_LC_LPF_FACTORP__A, 4);
7264                 WR16(dev_addr, QAM_LC_LPF_FACTORI__A, 4);
7265                 WR16(dev_addr, QAM_LC_MODE__A, 7);
7266                 WR16(dev_addr, QAM_LC_QUAL_TAB0__A, 1);
7267                 WR16(dev_addr, QAM_LC_QUAL_TAB1__A, 1);
7268                 WR16(dev_addr, QAM_LC_QUAL_TAB2__A, 1);
7269                 WR16(dev_addr, QAM_LC_QUAL_TAB3__A, 1);
7270                 WR16(dev_addr, QAM_LC_QUAL_TAB4__A, 2);
7271                 WR16(dev_addr, QAM_LC_QUAL_TAB5__A, 2);
7272                 WR16(dev_addr, QAM_LC_QUAL_TAB6__A, 2);
7273                 WR16(dev_addr, QAM_LC_QUAL_TAB8__A, 2);
7274                 WR16(dev_addr, QAM_LC_QUAL_TAB9__A, 2);
7275                 WR16(dev_addr, QAM_LC_QUAL_TAB10__A, 2);
7276                 WR16(dev_addr, QAM_LC_QUAL_TAB12__A, 2);
7277                 WR16(dev_addr, QAM_LC_QUAL_TAB15__A, 3);
7278                 WR16(dev_addr, QAM_LC_QUAL_TAB16__A, 3);
7279                 WR16(dev_addr, QAM_LC_QUAL_TAB20__A, 4);
7280                 WR16(dev_addr, QAM_LC_QUAL_TAB25__A, 4);
7281
7282                 WR16(dev_addr, IQM_FS_ADJ_SEL__A, 1);
7283                 WR16(dev_addr, IQM_RC_ADJ_SEL__A, 1);
7284                 WR16(dev_addr, IQM_CF_ADJ_SEL__A, 1);
7285                 WR16(dev_addr, IQM_CF_POW_MEAS_LEN__A, 0);
7286                 WR16(dev_addr, SCU_RAM_GPIO__A, 0);
7287
7288                 /* No more resets of the IQM, current standard correctly set =>
7289                    now AGCs can be configured. */
7290                 /* turn on IQMAF. It has to be in front of setAgc**() */
7291                 CHK_ERROR(set_iqm_af(demod, true));
7292                 CHK_ERROR(adc_synchronization(demod));
7293
7294                 CHK_ERROR(init_agc(demod));
7295                 CHK_ERROR(set_agc_if(demod, &(ext_attr->qam_if_agc_cfg), false));
7296                 CHK_ERROR(set_agc_rf(demod, &(ext_attr->qam_rf_agc_cfg), false));
7297                 {
7298                         /* TODO fix this, store a drxj_cfg_afe_gain_t structure in drxj_data_t instead
7299                            of only the gain */
7300                         drxj_cfg_afe_gain_t qam_pga_cfg = { DRX_STANDARD_ITU_B, 0 };
7301
7302                         qam_pga_cfg.gain = ext_attr->qam_pga_cfg;
7303                         CHK_ERROR(ctrl_set_cfg_afe_gain(demod, &qam_pga_cfg));
7304                 }
7305                 CHK_ERROR(ctrl_set_cfg_pre_saw(demod, &(ext_attr->qam_pre_saw_cfg)));
7306         }
7307
7308         if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
7309                 if (ext_attr->standard == DRX_STANDARD_ITU_A) {
7310                         WRB(dev_addr, IQM_CF_TAP_RE0__A, sizeof(qam_a_taps),
7311                             ((u8 *) qam_a_taps));
7312                         WRB(dev_addr, IQM_CF_TAP_IM0__A, sizeof(qam_a_taps),
7313                             ((u8 *) qam_a_taps));
7314                 } else if (ext_attr->standard == DRX_STANDARD_ITU_B) {
7315                         switch (channel->constellation) {
7316                         case DRX_CONSTELLATION_QAM64:
7317                                 WRB(dev_addr, IQM_CF_TAP_RE0__A,
7318                                     sizeof(qam_b64_taps), ((u8 *) qam_b64_taps));
7319                                 WRB(dev_addr, IQM_CF_TAP_IM0__A,
7320                                     sizeof(qam_b64_taps), ((u8 *) qam_b64_taps));
7321                                 break;
7322                         case DRX_CONSTELLATION_QAM256:
7323                                 WRB(dev_addr, IQM_CF_TAP_RE0__A,
7324                                     sizeof(qam_b256_taps),
7325                                     ((u8 *) qam_b256_taps));
7326                                 WRB(dev_addr, IQM_CF_TAP_IM0__A,
7327                                     sizeof(qam_b256_taps),
7328                                     ((u8 *) qam_b256_taps));
7329                                 break;
7330                         default:
7331                                 return (DRX_STS_ERROR);
7332                         }
7333                 } else if (ext_attr->standard == DRX_STANDARD_ITU_C) {
7334                         WRB(dev_addr, IQM_CF_TAP_RE0__A, sizeof(qam_c_taps),
7335                             ((u8 *) qam_c_taps));
7336                         WRB(dev_addr, IQM_CF_TAP_IM0__A, sizeof(qam_c_taps),
7337                             ((u8 *) qam_c_taps));
7338                 }
7339
7340                 /* SETP 4: constellation specific setup */
7341                 switch (channel->constellation) {
7342                 case DRX_CONSTELLATION_QAM16:
7343                         CHK_ERROR(set_qam16(demod));
7344                         break;
7345                 case DRX_CONSTELLATION_QAM32:
7346                         CHK_ERROR(set_qam32(demod));
7347                         break;
7348                 case DRX_CONSTELLATION_QAM64:
7349                         CHK_ERROR(set_qam64(demod));
7350                         break;
7351                 case DRX_CONSTELLATION_QAM128:
7352                         CHK_ERROR(set_qam128(demod));
7353                         break;
7354                 case DRX_CONSTELLATION_QAM256:
7355                         CHK_ERROR(set_qam256(demod));
7356                         break;
7357                 default:
7358                         return (DRX_STS_ERROR);
7359                 }               /* switch */
7360         }
7361
7362         if ((op & QAM_SET_OP_ALL)) {
7363                 WR16(dev_addr, IQM_CF_SCALE_SH__A, 0);
7364
7365                 /* Mpeg output has to be in front of FEC active */
7366                 CHK_ERROR(set_mpegtei_handling(demod));
7367                 CHK_ERROR(bit_reverse_mpeg_output(demod));
7368                 CHK_ERROR(set_mpeg_start_width(demod));
7369                 {
7370                         /* TODO: move to set_standard after hardware reset value problem is solved */
7371                         /* Configure initial MPEG output */
7372                         drx_cfg_mpeg_output_t cfg_mpeg_output;
7373
7374                         cfg_mpeg_output.enable_mpeg_output = true;
7375                         cfg_mpeg_output.insert_rs_byte =
7376                             common_attr->mpeg_cfg.insert_rs_byte;
7377                         cfg_mpeg_output.enable_parallel =
7378                             common_attr->mpeg_cfg.enable_parallel;
7379                         cfg_mpeg_output.invert_data =
7380                             common_attr->mpeg_cfg.invert_data;
7381                         cfg_mpeg_output.invert_err = common_attr->mpeg_cfg.invert_err;
7382                         cfg_mpeg_output.invert_str = common_attr->mpeg_cfg.invert_str;
7383                         cfg_mpeg_output.invert_val = common_attr->mpeg_cfg.invert_val;
7384                         cfg_mpeg_output.invert_clk = common_attr->mpeg_cfg.invert_clk;
7385                         cfg_mpeg_output.static_clk = common_attr->mpeg_cfg.static_clk;
7386                         cfg_mpeg_output.bitrate = common_attr->mpeg_cfg.bitrate;
7387                         CHK_ERROR(ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output));
7388                 }
7389         }
7390
7391         if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
7392
7393                 /* STEP 5: start QAM demodulator (starts FEC, QAM and IQM HW) */
7394                 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
7395                     SCU_RAM_COMMAND_CMD_DEMOD_START;
7396                 cmd_scu.parameter_len = 0;
7397                 cmd_scu.result_len = 1;
7398                 cmd_scu.parameter = NULL;
7399                 cmd_scu.result = &cmd_result;
7400                 CHK_ERROR(scu_command(dev_addr, &cmd_scu));
7401         }
7402
7403         WR16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_ACTIVE);
7404         WR16(dev_addr, QAM_COMM_EXEC__A, QAM_COMM_EXEC_ACTIVE);
7405         WR16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE);
7406
7407         return (DRX_STS_OK);
7408 rw_error:
7409         return (DRX_STS_ERROR);
7410 }
7411
7412 /*============================================================================*/
7413 static int
7414 ctrl_get_qam_sig_quality(pdrx_demod_instance_t demod, pdrx_sig_quality_t sig_quality);
7415 static int qam_flip_spec(pdrx_demod_instance_t demod, pdrx_channel_t channel)
7416 {
7417         u32 iqm_fs_rate_ofs = 0;
7418         u32 iqm_fs_rate_lo = 0;
7419         u16 qam_ctl_ena = 0;
7420         u16 data = 0;
7421         u16 equ_mode = 0;
7422         u16 fsm_state = 0;
7423         int i = 0;
7424         int ofsofs = 0;
7425         struct i2c_device_addr *dev_addr = NULL;
7426         pdrxj_data_t ext_attr = NULL;
7427
7428         dev_addr = demod->my_i2c_dev_addr;
7429         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
7430
7431         /* Silence the controlling of lc, equ, and the acquisition state machine */
7432         RR16(dev_addr, SCU_RAM_QAM_CTL_ENA__A, &qam_ctl_ena);
7433         WR16(dev_addr, SCU_RAM_QAM_CTL_ENA__A, qam_ctl_ena
7434              & ~(SCU_RAM_QAM_CTL_ENA_ACQ__M
7435                  | SCU_RAM_QAM_CTL_ENA_EQU__M | SCU_RAM_QAM_CTL_ENA_LC__M));
7436
7437         /* freeze the frequency control loop */
7438         WR16(dev_addr, QAM_LC_CF__A, 0);
7439         WR16(dev_addr, QAM_LC_CF1__A, 0);
7440
7441         ARR32(dev_addr, IQM_FS_RATE_OFS_LO__A, &iqm_fs_rate_ofs);
7442         ARR32(dev_addr, IQM_FS_RATE_LO__A, &iqm_fs_rate_lo);
7443         ofsofs = iqm_fs_rate_lo - iqm_fs_rate_ofs;
7444         iqm_fs_rate_ofs = ~iqm_fs_rate_ofs + 1;
7445         iqm_fs_rate_ofs -= 2 * ofsofs;
7446
7447         /* freeze dq/fq updating */
7448         RR16(dev_addr, QAM_DQ_MODE__A, &data);
7449         data = (data & 0xfff9);
7450         WR16(dev_addr, QAM_DQ_MODE__A, data);
7451         WR16(dev_addr, QAM_FQ_MODE__A, data);
7452
7453         /* lc_cp / _ci / _ca */
7454         WR16(dev_addr, QAM_LC_CI__A, 0);
7455         WR16(dev_addr, QAM_LC_EP__A, 0);
7456         WR16(dev_addr, QAM_FQ_LA_FACTOR__A, 0);
7457
7458         /* flip the spec */
7459         WR32(dev_addr, IQM_FS_RATE_OFS_LO__A, iqm_fs_rate_ofs);
7460         ext_attr->iqm_fs_rate_ofs = iqm_fs_rate_ofs;
7461         ext_attr->pos_image = (ext_attr->pos_image) ? false : true;
7462
7463         /* freeze dq/fq updating */
7464         RR16(dev_addr, QAM_DQ_MODE__A, &data);
7465         equ_mode = data;
7466         data = (data & 0xfff9);
7467         WR16(dev_addr, QAM_DQ_MODE__A, data);
7468         WR16(dev_addr, QAM_FQ_MODE__A, data);
7469
7470         for (i = 0; i < 28; i++) {
7471                 RR16(dev_addr, QAM_DQ_TAP_IM_EL0__A + (2 * i), &data);
7472                 WR16(dev_addr, QAM_DQ_TAP_IM_EL0__A + (2 * i), -data);
7473         }
7474
7475         for (i = 0; i < 24; i++) {
7476                 RR16(dev_addr, QAM_FQ_TAP_IM_EL0__A + (2 * i), &data);
7477                 WR16(dev_addr, QAM_FQ_TAP_IM_EL0__A + (2 * i), -data);
7478         }
7479
7480         data = equ_mode;
7481         WR16(dev_addr, QAM_DQ_MODE__A, data);
7482         WR16(dev_addr, QAM_FQ_MODE__A, data);
7483
7484         WR16(dev_addr, SCU_RAM_QAM_FSM_STATE_TGT__A, 4);
7485
7486         i = 0;
7487         while ((fsm_state != 4) && (i++ < 100)) {
7488                 RR16(dev_addr, SCU_RAM_QAM_FSM_STATE__A, &fsm_state);
7489         }
7490         WR16(dev_addr, SCU_RAM_QAM_CTL_ENA__A, (qam_ctl_ena | 0x0016));
7491
7492         return (DRX_STS_OK);
7493 rw_error:
7494         return (DRX_STS_ERROR);
7495
7496 }
7497
7498 #define  NO_LOCK        0x0
7499 #define  DEMOD_LOCKED   0x1
7500 #define  SYNC_FLIPPED   0x2
7501 #define  SPEC_MIRRORED  0x4
7502 /**
7503 * \fn int qam64auto ()
7504 * \brief auto do sync pattern switching and mirroring.
7505 * \param demod:   instance of demod.
7506 * \param channel: pointer to channel data.
7507 * \param tuner_freq_offset: tuner frequency offset.
7508 * \param lock_status: pointer to lock status.
7509 * \return int.
7510 */
7511 static int
7512 qam64auto(pdrx_demod_instance_t demod,
7513           pdrx_channel_t channel,
7514           s32 tuner_freq_offset, pdrx_lock_status_t lock_status)
7515 {
7516         drx_sig_quality_t sig_quality;
7517         u16 data = 0;
7518         u32 state = NO_LOCK;
7519         u32 start_time = 0;
7520         u32 d_locked_time = 0;
7521         pdrxj_data_t ext_attr = NULL;
7522         u32 timeout_ofs = 0;
7523
7524         /* external attributes for storing aquired channel constellation */
7525         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
7526         *lock_status = DRX_NOT_LOCKED;
7527         start_time = drxbsp_hst_clock();
7528         state = NO_LOCK;
7529         do {
7530                 CHK_ERROR(ctrl_lock_status(demod, lock_status));
7531
7532                 switch (state) {
7533                 case NO_LOCK:
7534                         if (*lock_status == DRXJ_DEMOD_LOCK) {
7535                                 CHK_ERROR(ctrl_get_qam_sig_quality
7536                                           (demod, &sig_quality));
7537                                 if (sig_quality.MER > 208) {
7538                                         state = DEMOD_LOCKED;
7539                                         /* some delay to see if fec_lock possible TODO find the right value */
7540                                         timeout_ofs += DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME;        /* see something, waiting longer */
7541                                         d_locked_time = drxbsp_hst_clock();
7542                                 }
7543                         }
7544                         break;
7545                 case DEMOD_LOCKED:
7546                         if ((*lock_status == DRXJ_DEMOD_LOCK) &&        /* still demod_lock in 150ms */
7547                             ((drxbsp_hst_clock() - d_locked_time) >
7548                              DRXJ_QAM_FEC_LOCK_WAITTIME)) {
7549                                 RR16(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A,
7550                                      &data);
7551                                 WR16(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A,
7552                                      data | 0x1);
7553                                 state = SYNC_FLIPPED;
7554                                 drxbsp_hst_sleep(10);
7555                         }
7556                         break;
7557                 case SYNC_FLIPPED:
7558                         if (*lock_status == DRXJ_DEMOD_LOCK) {
7559                                 if (channel->mirror == DRX_MIRROR_AUTO) {
7560                                         /* flip sync pattern back */
7561                                         RR16(demod->my_i2c_dev_addr,
7562                                              QAM_SY_TIMEOUT__A, &data);
7563                                         WR16(demod->my_i2c_dev_addr,
7564                                              QAM_SY_TIMEOUT__A, data & 0xFFFE);
7565                                         /* flip spectrum */
7566                                         ext_attr->mirror = DRX_MIRROR_YES;
7567                                         CHK_ERROR(qam_flip_spec(demod, channel));
7568                                         state = SPEC_MIRRORED;
7569                                         /* reset timer TODO: still need 500ms? */
7570                                         start_time = d_locked_time =
7571                                             drxbsp_hst_clock();
7572                                         timeout_ofs = 0;
7573                                 } else {        /* no need to wait lock */
7574
7575                                         start_time =
7576                                             drxbsp_hst_clock() -
7577                                             DRXJ_QAM_MAX_WAITTIME - timeout_ofs;
7578                                 }
7579                         }
7580                         break;
7581                 case SPEC_MIRRORED:
7582                         if ((*lock_status == DRXJ_DEMOD_LOCK) &&        /* still demod_lock in 150ms */
7583                             ((drxbsp_hst_clock() - d_locked_time) >
7584                              DRXJ_QAM_FEC_LOCK_WAITTIME)) {
7585                                 CHK_ERROR(ctrl_get_qam_sig_quality
7586                                           (demod, &sig_quality));
7587                                 if (sig_quality.MER > 208) {
7588                                         RR16(demod->my_i2c_dev_addr,
7589                                              QAM_SY_TIMEOUT__A, &data);
7590                                         WR16(demod->my_i2c_dev_addr,
7591                                              QAM_SY_TIMEOUT__A, data | 0x1);
7592                                         /* no need to wait lock */
7593                                         start_time =
7594                                             drxbsp_hst_clock() -
7595                                             DRXJ_QAM_MAX_WAITTIME - timeout_ofs;
7596                                 }
7597                         }
7598                         break;
7599                 default:
7600                         break;
7601                 }
7602                 drxbsp_hst_sleep(10);
7603         } while
7604             ((*lock_status != DRX_LOCKED) &&
7605              (*lock_status != DRX_NEVER_LOCK) &&
7606              ((drxbsp_hst_clock() - start_time) <
7607               (DRXJ_QAM_MAX_WAITTIME + timeout_ofs))
7608             );
7609         /* Returning control to apllication ... */
7610
7611         return (DRX_STS_OK);
7612 rw_error:
7613         return (DRX_STS_ERROR);
7614 }
7615
7616 /**
7617 * \fn int qam256auto ()
7618 * \brief auto do sync pattern switching and mirroring.
7619 * \param demod:   instance of demod.
7620 * \param channel: pointer to channel data.
7621 * \param tuner_freq_offset: tuner frequency offset.
7622 * \param lock_status: pointer to lock status.
7623 * \return int.
7624 */
7625 static int
7626 qam256auto(pdrx_demod_instance_t demod,
7627            pdrx_channel_t channel,
7628            s32 tuner_freq_offset, pdrx_lock_status_t lock_status)
7629 {
7630         drx_sig_quality_t sig_quality;
7631         u32 state = NO_LOCK;
7632         u32 start_time = 0;
7633         u32 d_locked_time = 0;
7634         pdrxj_data_t ext_attr = NULL;
7635         u32 timeout_ofs = DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME;
7636
7637         /* external attributes for storing aquired channel constellation */
7638         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
7639         *lock_status = DRX_NOT_LOCKED;
7640         start_time = drxbsp_hst_clock();
7641         state = NO_LOCK;
7642         do {
7643                 CHK_ERROR(ctrl_lock_status(demod, lock_status));
7644                 switch (state) {
7645                 case NO_LOCK:
7646                         if (*lock_status == DRXJ_DEMOD_LOCK) {
7647                                 CHK_ERROR(ctrl_get_qam_sig_quality
7648                                           (demod, &sig_quality));
7649                                 if (sig_quality.MER > 268) {
7650                                         state = DEMOD_LOCKED;
7651                                         timeout_ofs += DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME;        /* see something, wait longer */
7652                                         d_locked_time = drxbsp_hst_clock();
7653                                 }
7654                         }
7655                         break;
7656                 case DEMOD_LOCKED:
7657                         if (*lock_status == DRXJ_DEMOD_LOCK) {
7658                                 if ((channel->mirror == DRX_MIRROR_AUTO) &&
7659                                     ((drxbsp_hst_clock() - d_locked_time) >
7660                                      DRXJ_QAM_FEC_LOCK_WAITTIME)) {
7661                                         ext_attr->mirror = DRX_MIRROR_YES;
7662                                         CHK_ERROR(qam_flip_spec(demod, channel));
7663                                         state = SPEC_MIRRORED;
7664                                         /* reset timer TODO: still need 300ms? */
7665                                         start_time = drxbsp_hst_clock();
7666                                         timeout_ofs = -DRXJ_QAM_MAX_WAITTIME / 2;
7667                                 }
7668                         }
7669                         break;
7670                 case SPEC_MIRRORED:
7671                         break;
7672                 default:
7673                         break;
7674                 }
7675                 drxbsp_hst_sleep(10);
7676         } while
7677             ((*lock_status < DRX_LOCKED) &&
7678              (*lock_status != DRX_NEVER_LOCK) &&
7679              ((drxbsp_hst_clock() - start_time) <
7680               (DRXJ_QAM_MAX_WAITTIME + timeout_ofs)));
7681
7682         return (DRX_STS_OK);
7683 rw_error:
7684         return (DRX_STS_ERROR);
7685 }
7686
7687 /**
7688 * \fn int set_qamChannel ()
7689 * \brief Set QAM channel according to the requested constellation.
7690 * \param demod:   instance of demod.
7691 * \param channel: pointer to channel data.
7692 * \return int.
7693 */
7694 static int
7695 set_qamChannel(pdrx_demod_instance_t demod,
7696               pdrx_channel_t channel, s32 tuner_freq_offset)
7697 {
7698         drx_lock_status_t lock_status = DRX_NOT_LOCKED;
7699         pdrxj_data_t ext_attr = NULL;
7700         bool auto_flag = false;
7701
7702         /* external attributes for storing aquired channel constellation */
7703         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
7704
7705         /* set QAM channel constellation */
7706         switch (channel->constellation) {
7707         case DRX_CONSTELLATION_QAM16:
7708         case DRX_CONSTELLATION_QAM32:
7709         case DRX_CONSTELLATION_QAM64:
7710         case DRX_CONSTELLATION_QAM128:
7711         case DRX_CONSTELLATION_QAM256:
7712                 ext_attr->constellation = channel->constellation;
7713                 if (channel->mirror == DRX_MIRROR_AUTO) {
7714                         ext_attr->mirror = DRX_MIRROR_NO;
7715                 } else {
7716                         ext_attr->mirror = channel->mirror;
7717                 }
7718                 CHK_ERROR(set_qam
7719                           (demod, channel, tuner_freq_offset, QAM_SET_OP_ALL));
7720
7721                 if ((ext_attr->standard == DRX_STANDARD_ITU_B) &&
7722                     (channel->constellation == DRX_CONSTELLATION_QAM64)) {
7723                         CHK_ERROR(qam64auto
7724                                   (demod, channel, tuner_freq_offset,
7725                                    &lock_status));
7726                 }
7727
7728                 if ((ext_attr->standard == DRX_STANDARD_ITU_B) &&
7729                     (channel->mirror == DRX_MIRROR_AUTO) &&
7730                     (channel->constellation == DRX_CONSTELLATION_QAM256)) {
7731                         CHK_ERROR(qam256auto
7732                                   (demod, channel, tuner_freq_offset,
7733                                    &lock_status));
7734                 }
7735                 break;
7736         case DRX_CONSTELLATION_AUTO:    /* for channel scan */
7737                 if (ext_attr->standard == DRX_STANDARD_ITU_B) {
7738                         auto_flag = true;
7739                         /* try to lock default QAM constellation: QAM64 */
7740                         channel->constellation = DRX_CONSTELLATION_QAM256;
7741                         ext_attr->constellation = DRX_CONSTELLATION_QAM256;
7742                         if (channel->mirror == DRX_MIRROR_AUTO) {
7743                                 ext_attr->mirror = DRX_MIRROR_NO;
7744                         } else {
7745                                 ext_attr->mirror = channel->mirror;
7746                         }
7747                         CHK_ERROR(set_qam
7748                                   (demod, channel, tuner_freq_offset,
7749                                    QAM_SET_OP_ALL));
7750                         CHK_ERROR(qam256auto
7751                                   (demod, channel, tuner_freq_offset,
7752                                    &lock_status));
7753
7754                         if (lock_status < DRX_LOCKED) {
7755                                 /* QAM254 not locked -> try to lock QAM64 constellation */
7756                                 channel->constellation =
7757                                     DRX_CONSTELLATION_QAM64;
7758                                 ext_attr->constellation =
7759                                     DRX_CONSTELLATION_QAM64;
7760                                 if (channel->mirror == DRX_MIRROR_AUTO) {
7761                                         ext_attr->mirror = DRX_MIRROR_NO;
7762                                 } else {
7763                                         ext_attr->mirror = channel->mirror;
7764                                 }
7765                                 {
7766                                         u16 qam_ctl_ena = 0;
7767                                         RR16(demod->my_i2c_dev_addr,
7768                                              SCU_RAM_QAM_CTL_ENA__A,
7769                                              &qam_ctl_ena);
7770                                         WR16(demod->my_i2c_dev_addr,
7771                                              SCU_RAM_QAM_CTL_ENA__A,
7772                                              qam_ctl_ena &
7773                                              ~SCU_RAM_QAM_CTL_ENA_ACQ__M);
7774                                         WR16(demod->my_i2c_dev_addr, SCU_RAM_QAM_FSM_STATE_TGT__A, 0x2);        /* force to rate hunting */
7775
7776                                         CHK_ERROR(set_qam
7777                                                   (demod, channel,
7778                                                    tuner_freq_offset,
7779                                                    QAM_SET_OP_CONSTELLATION));
7780                                         WR16(demod->my_i2c_dev_addr,
7781                                              SCU_RAM_QAM_CTL_ENA__A, qam_ctl_ena);
7782                                 }
7783                                 CHK_ERROR(qam64auto
7784                                           (demod, channel, tuner_freq_offset,
7785                                            &lock_status));
7786                         }
7787                         channel->constellation = DRX_CONSTELLATION_AUTO;
7788                 } else if (ext_attr->standard == DRX_STANDARD_ITU_C) {
7789                         channel->constellation = DRX_CONSTELLATION_QAM64;
7790                         ext_attr->constellation = DRX_CONSTELLATION_QAM64;
7791                         auto_flag = true;
7792
7793                         if (channel->mirror == DRX_MIRROR_AUTO) {
7794                                 ext_attr->mirror = DRX_MIRROR_NO;
7795                         } else {
7796                                 ext_attr->mirror = channel->mirror;
7797                         }
7798                         {
7799                                 u16 qam_ctl_ena = 0;
7800                                 RR16(demod->my_i2c_dev_addr,
7801                                      SCU_RAM_QAM_CTL_ENA__A, &qam_ctl_ena);
7802                                 WR16(demod->my_i2c_dev_addr,
7803                                      SCU_RAM_QAM_CTL_ENA__A,
7804                                      qam_ctl_ena & ~SCU_RAM_QAM_CTL_ENA_ACQ__M);
7805                                 WR16(demod->my_i2c_dev_addr, SCU_RAM_QAM_FSM_STATE_TGT__A, 0x2);        /* force to rate hunting */
7806
7807                                 CHK_ERROR(set_qam
7808                                           (demod, channel, tuner_freq_offset,
7809                                            QAM_SET_OP_CONSTELLATION));
7810                                 WR16(demod->my_i2c_dev_addr,
7811                                      SCU_RAM_QAM_CTL_ENA__A, qam_ctl_ena);
7812                         }
7813                         CHK_ERROR(qam64auto
7814                                   (demod, channel, tuner_freq_offset,
7815                                    &lock_status));
7816                         channel->constellation = DRX_CONSTELLATION_AUTO;
7817                 } else {
7818                         channel->constellation = DRX_CONSTELLATION_AUTO;
7819                         return (DRX_STS_INVALID_ARG);
7820                 }
7821                 break;
7822         default:
7823                 return (DRX_STS_INVALID_ARG);
7824         }
7825
7826         return (DRX_STS_OK);
7827 rw_error:
7828         /* restore starting value */
7829         if (auto_flag)
7830                 channel->constellation = DRX_CONSTELLATION_AUTO;
7831         return (DRX_STS_ERROR);
7832 }
7833
7834 /*============================================================================*/
7835
7836 /**
7837 * \fn static short GetQAMRSErr_count(struct i2c_device_addr *dev_addr)
7838 * \brief Get RS error count in QAM mode (used for post RS BER calculation)
7839 * \return Error code
7840 *
7841 * precondition: measurement period & measurement prescale must be set
7842 *
7843 */
7844 static int
7845 GetQAMRSErr_count(struct i2c_device_addr *dev_addr, p_drxjrs_errors_t rs_errors)
7846 {
7847         u16 nr_bit_errors = 0,
7848             nr_symbol_errors = 0,
7849             nr_packet_errors = 0, nr_failures = 0, nr_snc_par_fail_count = 0;
7850
7851         /* check arguments */
7852         if (dev_addr == NULL) {
7853                 return (DRX_STS_INVALID_ARG);
7854         }
7855
7856         /* all reported errors are received in the  */
7857         /* most recently finished measurment period */
7858         /*   no of pre RS bit errors */
7859         RR16(dev_addr, FEC_RS_NR_BIT_ERRORS__A, &nr_bit_errors);
7860         /*   no of symbol errors      */
7861         RR16(dev_addr, FEC_RS_NR_SYMBOL_ERRORS__A, &nr_symbol_errors);
7862         /*   no of packet errors      */
7863         RR16(dev_addr, FEC_RS_NR_PACKET_ERRORS__A, &nr_packet_errors);
7864         /*   no of failures to decode */
7865         RR16(dev_addr, FEC_RS_NR_FAILURES__A, &nr_failures);
7866         /*   no of post RS bit erros  */
7867         RR16(dev_addr, FEC_OC_SNC_FAIL_COUNT__A, &nr_snc_par_fail_count);
7868         /* TODO: NOTE */
7869         /* These register values are fetched in non-atomic fashion           */
7870         /* It is possible that the read values contain unrelated information */
7871
7872         rs_errors->nr_bit_errors = nr_bit_errors & FEC_RS_NR_BIT_ERRORS__M;
7873         rs_errors->nr_symbol_errors = nr_symbol_errors & FEC_RS_NR_SYMBOL_ERRORS__M;
7874         rs_errors->nr_packet_errors = nr_packet_errors & FEC_RS_NR_PACKET_ERRORS__M;
7875         rs_errors->nr_failures = nr_failures & FEC_RS_NR_FAILURES__M;
7876         rs_errors->nr_snc_par_fail_count =
7877             nr_snc_par_fail_count & FEC_OC_SNC_FAIL_COUNT__M;
7878
7879         return (DRX_STS_OK);
7880 rw_error:
7881         return (DRX_STS_ERROR);
7882 }
7883
7884 /*============================================================================*/
7885
7886 /**
7887 * \fn int ctrl_get_qam_sig_quality()
7888 * \brief Retreive QAM signal quality from device.
7889 * \param devmod Pointer to demodulator instance.
7890 * \param sig_quality Pointer to signal quality data.
7891 * \return int.
7892 * \retval DRX_STS_OK sig_quality contains valid data.
7893 * \retval DRX_STS_INVALID_ARG sig_quality is NULL.
7894 * \retval DRX_STS_ERROR Erroneous data, sig_quality contains invalid data.
7895
7896 *  Pre-condition: Device must be started and in lock.
7897 */
7898 static int
7899 ctrl_get_qam_sig_quality(pdrx_demod_instance_t demod, pdrx_sig_quality_t sig_quality)
7900 {
7901         struct i2c_device_addr *dev_addr = NULL;
7902         pdrxj_data_t ext_attr = NULL;
7903         enum drx_modulation constellation = DRX_CONSTELLATION_UNKNOWN;
7904         DRXJrs_errors_t measuredrs_errors = { 0, 0, 0, 0, 0 };
7905
7906         u32 pre_bit_err_rs = 0; /* pre RedSolomon Bit Error Rate */
7907         u32 post_bit_err_rs = 0;        /* post RedSolomon Bit Error Rate */
7908         u32 pkt_errs = 0;       /* no of packet errors in RS */
7909         u16 qam_sl_err_power = 0;       /* accumulated error between raw and sliced symbols */
7910         u16 qsym_err_vd = 0;    /* quadrature symbol errors in QAM_VD */
7911         u16 fec_oc_period = 0;  /* SNC sync failure measurement period */
7912         u16 fec_rs_prescale = 0;        /* ReedSolomon Measurement Prescale */
7913         u16 fec_rs_period = 0;  /* Value for corresponding I2C register */
7914         /* calculation constants */
7915         u32 rs_bit_cnt = 0;     /* RedSolomon Bit Count */
7916         u32 qam_sl_sig_power = 0;       /* used for MER, depends of QAM constellation */
7917         /* intermediate results */
7918         u32 e = 0;              /* exponent value used for QAM BER/SER */
7919         u32 m = 0;              /* mantisa value used for QAM BER/SER */
7920         u32 ber_cnt = 0;        /* BER count */
7921         /* signal quality info */
7922         u32 qam_sl_mer = 0;     /* QAM MER */
7923         u32 qam_pre_rs_ber = 0; /* Pre RedSolomon BER */
7924         u32 qam_post_rs_ber = 0;        /* Post RedSolomon BER */
7925         u32 qam_vd_ser = 0;     /* ViterbiDecoder SER */
7926         u16 qam_vd_prescale = 0;        /* Viterbi Measurement Prescale */
7927         u16 qam_vd_period = 0;  /* Viterbi Measurement period */
7928         u32 vd_bit_cnt = 0;     /* ViterbiDecoder Bit Count */
7929
7930         /* get device basic information */
7931         dev_addr = demod->my_i2c_dev_addr;
7932         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
7933         constellation = ext_attr->constellation;
7934
7935         /* read the physical registers */
7936         /*   Get the RS error data */
7937         CHK_ERROR(GetQAMRSErr_count(dev_addr, &measuredrs_errors));
7938         /* get the register value needed for MER */
7939         RR16(dev_addr, QAM_SL_ERR_POWER__A, &qam_sl_err_power);
7940         /* get the register value needed for post RS BER */
7941         RR16(dev_addr, FEC_OC_SNC_FAIL_PERIOD__A, &fec_oc_period);
7942
7943         /* get constants needed for signal quality calculation */
7944         fec_rs_period = ext_attr->fec_rs_period;
7945         fec_rs_prescale = ext_attr->fec_rs_prescale;
7946         rs_bit_cnt = fec_rs_period * fec_rs_prescale * ext_attr->fec_rs_plen;
7947         qam_vd_period = ext_attr->qam_vd_period;
7948         qam_vd_prescale = ext_attr->qam_vd_prescale;
7949         vd_bit_cnt = qam_vd_period * qam_vd_prescale * ext_attr->fec_vd_plen;
7950
7951         /* DRXJ_QAM_SL_SIG_POWER_QAMxxx  * 4     */
7952         switch (constellation) {
7953         case DRX_CONSTELLATION_QAM16:
7954                 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM16 << 2;
7955                 break;
7956         case DRX_CONSTELLATION_QAM32:
7957                 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM32 << 2;
7958                 break;
7959         case DRX_CONSTELLATION_QAM64:
7960                 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM64 << 2;
7961                 break;
7962         case DRX_CONSTELLATION_QAM128:
7963                 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM128 << 2;
7964                 break;
7965         case DRX_CONSTELLATION_QAM256:
7966                 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM256 << 2;
7967                 break;
7968         default:
7969                 return (DRX_STS_ERROR);
7970         }
7971
7972         /* ------------------------------ */
7973         /* MER Calculation                */
7974         /* ------------------------------ */
7975         /* MER is good if it is above 27.5 for QAM256 or 21.5 for QAM64 */
7976
7977         /* 10.0*log10(qam_sl_sig_power * 4.0 / qam_sl_err_power); */
7978         if (qam_sl_err_power == 0)
7979                 qam_sl_mer = 0;
7980         else
7981                 qam_sl_mer =
7982                     log1_times100(qam_sl_sig_power) -
7983                     log1_times100((u32) qam_sl_err_power);
7984
7985         /* ----------------------------------------- */
7986         /* Pre Viterbi Symbol Error Rate Calculation */
7987         /* ----------------------------------------- */
7988         /* pre viterbi SER is good if it is bellow 0.025 */
7989
7990         /* get the register value */
7991         /*   no of quadrature symbol errors */
7992         RR16(dev_addr, QAM_VD_NR_QSYM_ERRORS__A, &qsym_err_vd);
7993         /* Extract the Exponent and the Mantisa  */
7994         /* of number of quadrature symbol errors */
7995         e = (qsym_err_vd & QAM_VD_NR_QSYM_ERRORS_EXP__M) >>
7996             QAM_VD_NR_QSYM_ERRORS_EXP__B;
7997         m = (qsym_err_vd & QAM_VD_NR_SYMBOL_ERRORS_FIXED_MANT__M) >>
7998             QAM_VD_NR_SYMBOL_ERRORS_FIXED_MANT__B;
7999
8000         if ((m << e) >> 3 > 549752) {   /* the max of frac_times1e6 */
8001                 qam_vd_ser = 500000;    /* clip BER 0.5 */
8002         } else {
8003                 qam_vd_ser =
8004                     frac_times1e6(m << ((e > 2) ? (e - 3) : e),
8005                                  vd_bit_cnt * ((e > 2) ? 1 : 8) / 8);
8006         }
8007
8008         /* --------------------------------------- */
8009         /* pre and post RedSolomon BER Calculation */
8010         /* --------------------------------------- */
8011         /* pre RS BER is good if it is below 3.5e-4 */
8012
8013         /* get the register values */
8014         pre_bit_err_rs = (u32) measuredrs_errors.nr_bit_errors;
8015         pkt_errs = post_bit_err_rs = (u32) measuredrs_errors.nr_snc_par_fail_count;
8016
8017         /* Extract the Exponent and the Mantisa of the */
8018         /* pre Reed-Solomon bit error count            */
8019         e = (pre_bit_err_rs & FEC_RS_NR_BIT_ERRORS_EXP__M) >>
8020             FEC_RS_NR_BIT_ERRORS_EXP__B;
8021         m = (pre_bit_err_rs & FEC_RS_NR_BIT_ERRORS_FIXED_MANT__M) >>
8022             FEC_RS_NR_BIT_ERRORS_FIXED_MANT__B;
8023
8024         ber_cnt = m << e;
8025
8026         /*qam_pre_rs_ber = frac_times1e6( ber_cnt, rs_bit_cnt ); */
8027         if (m > (rs_bit_cnt >> (e + 1)) || (rs_bit_cnt >> e) == 0) {
8028                 qam_pre_rs_ber = 500000;        /* clip BER 0.5 */
8029         } else {
8030                 qam_pre_rs_ber = frac_times1e6(m, rs_bit_cnt >> e);
8031         }
8032
8033         /* post RS BER = 1000000* (11.17 * FEC_OC_SNC_FAIL_COUNT__A) /  */
8034         /*               (1504.0 * FEC_OC_SNC_FAIL_PERIOD__A)  */
8035         /*
8036            => c = (1000000*100*11.17)/1504 =
8037            post RS BER = (( c* FEC_OC_SNC_FAIL_COUNT__A) /
8038            (100 * FEC_OC_SNC_FAIL_PERIOD__A)
8039            *100 and /100 is for more precision.
8040            => (20 bits * 12 bits) /(16 bits * 7 bits)  => safe in 32 bits computation
8041
8042            Precision errors still possible.
8043          */
8044         e = post_bit_err_rs * 742686;
8045         m = fec_oc_period * 100;
8046         if (fec_oc_period == 0)
8047                 qam_post_rs_ber = 0xFFFFFFFF;
8048         else
8049                 qam_post_rs_ber = e / m;
8050
8051         /* fill signal quality data structure */
8052         sig_quality->MER = ((u16) qam_sl_mer);
8053         if (ext_attr->standard == DRX_STANDARD_ITU_B) {
8054                 sig_quality->pre_viterbi_ber = qam_vd_ser;
8055         } else {
8056                 sig_quality->pre_viterbi_ber = qam_pre_rs_ber;
8057         }
8058         sig_quality->post_viterbi_ber = qam_pre_rs_ber;
8059         sig_quality->post_reed_solomon_ber = qam_post_rs_ber;
8060         sig_quality->scale_factor_ber = ((u32) 1000000);
8061 #ifdef DRXJ_SIGNAL_ACCUM_ERR
8062         CHK_ERROR(get_acc_pkt_err(demod, &sig_quality->packet_error));
8063 #else
8064         sig_quality->packet_error = ((u16) pkt_errs);
8065 #endif
8066
8067         return (DRX_STS_OK);
8068 rw_error:
8069         return (DRX_STS_ERROR);
8070 }
8071
8072 /**
8073 * \fn int ctrl_get_qam_constel()
8074 * \brief Retreive a QAM constellation point via I2C.
8075 * \param demod Pointer to demodulator instance.
8076 * \param complex_nr Pointer to the structure in which to store the
8077                    constellation point.
8078 * \return int.
8079 */
8080 static int
8081 ctrl_get_qam_constel(pdrx_demod_instance_t demod, pdrx_complex_t complex_nr)
8082 {
8083         u16 fec_oc_ocr_mode = 0;
8084                               /**< FEC OCR grabber configuration        */
8085         u16 qam_sl_comm_mb = 0;/**< QAM SL MB configuration              */
8086         u16 qam_sl_comm_mbInit = 0;
8087                               /**< QAM SL MB intial configuration       */
8088         u16 im = 0;           /**< constellation Im part                */
8089         u16 re = 0;           /**< constellation Re part                */
8090         u32 data = 0;
8091         struct i2c_device_addr *dev_addr = NULL;
8092                                      /**< device address */
8093
8094         /* read device info */
8095         dev_addr = demod->my_i2c_dev_addr;
8096
8097         /* TODO: */
8098         /* Monitor bus grabbing is an open external interface issue  */
8099         /* Needs to be checked when external interface PG is updated */
8100
8101         /* Configure MB (Monitor bus) */
8102         RR16(dev_addr, QAM_SL_COMM_MB__A, &qam_sl_comm_mbInit);
8103         /* set observe flag & MB mux */
8104         qam_sl_comm_mb = qam_sl_comm_mbInit & (~(QAM_SL_COMM_MB_OBS__M +
8105                                            QAM_SL_COMM_MB_MUX_OBS__M));
8106         qam_sl_comm_mb |= (QAM_SL_COMM_MB_OBS_ON +
8107                         QAM_SL_COMM_MB_MUX_OBS_CONST_CORR);
8108         WR16(dev_addr, QAM_SL_COMM_MB__A, qam_sl_comm_mb);
8109
8110         /* Enable MB grabber in the FEC OC */
8111         fec_oc_ocr_mode = (/* output select:  observe bus */
8112                                (FEC_OC_OCR_MODE_MB_SELECT__M &
8113                                 (0x0 << FEC_OC_OCR_MODE_MB_SELECT__B)) |
8114                                /* grabber enable: on          */
8115                                (FEC_OC_OCR_MODE_GRAB_ENABLE__M &
8116                                 (0x1 << FEC_OC_OCR_MODE_GRAB_ENABLE__B)) |
8117                                /* grabber select: observe bus */
8118                                (FEC_OC_OCR_MODE_GRAB_SELECT__M &
8119                                 (0x0 << FEC_OC_OCR_MODE_GRAB_SELECT__B)) |
8120                                /* grabber mode:   continuous  */
8121                                (FEC_OC_OCR_MODE_GRAB_COUNTED__M &
8122                                 (0x0 << FEC_OC_OCR_MODE_GRAB_COUNTED__B)));
8123         WR16(dev_addr, FEC_OC_OCR_MODE__A, fec_oc_ocr_mode);
8124
8125         /* Disable MB grabber in the FEC OC */
8126         WR16(dev_addr, FEC_OC_OCR_MODE__A, 0x00);
8127
8128         /* read data */
8129         RR32(dev_addr, FEC_OC_OCR_GRAB_RD0__A, &data);
8130         re = (u16) (data & FEC_OC_OCR_GRAB_RD0__M);
8131         im = (u16) ((data >> 16) & FEC_OC_OCR_GRAB_RD1__M);
8132
8133         /* TODO: */
8134         /* interpret data (re & im) according to the Monitor bus mapping ?? */
8135
8136         /* sign extension, 10th bit is sign bit */
8137         if ((re & 0x0200) == 0x0200) {
8138                 re |= 0xFC00;
8139         }
8140         if ((im & 0x0200) == 0x0200) {
8141                 im |= 0xFC00;
8142         }
8143         complex_nr->re = ((s16) re);
8144         complex_nr->im = ((s16) im);
8145
8146         /* Restore MB (Monitor bus) */
8147         WR16(dev_addr, QAM_SL_COMM_MB__A, qam_sl_comm_mbInit);
8148
8149         return (DRX_STS_OK);
8150 rw_error:
8151         return (DRX_STS_ERROR);
8152 }
8153 #endif /* #ifndef DRXJ_VSB_ONLY */
8154
8155 /*============================================================================*/
8156 /*==                     END QAM DATAPATH FUNCTIONS                         ==*/
8157 /*============================================================================*/
8158
8159 /*============================================================================*/
8160 /*============================================================================*/
8161 /*==                       ATV DATAPATH FUNCTIONS                           ==*/
8162 /*============================================================================*/
8163 /*============================================================================*/
8164
8165 /*
8166    Implementation notes.
8167
8168    NTSC/FM AGCs
8169
8170       Four AGCs are used for NTSC:
8171       (1) RF (used to attenuate the input signal in case of to much power)
8172       (2) IF (used to attenuate the input signal in case of to much power)
8173       (3) Video AGC (used to amplify the output signal in case input to low)
8174       (4) SIF AGC (used to amplify the output signal in case input to low)
8175
8176       Video AGC is coupled to RF and IF. SIF AGC is not coupled. It is assumed
8177       that the coupling between Video AGC and the RF and IF AGCs also works in
8178       favor of the SIF AGC.
8179
8180       Three AGCs are used for FM:
8181       (1) RF (used to attenuate the input signal in case of to much power)
8182       (2) IF (used to attenuate the input signal in case of to much power)
8183       (3) SIF AGC (used to amplify the output signal in case input to low)
8184
8185       The SIF AGC is now coupled to the RF/IF AGCs.
8186       The SIF AGC is needed for both SIF ouput and the internal SIF signal to
8187       the AUD block.
8188
8189       RF and IF AGCs DACs are part of AFE, Video and SIF AGC DACs are part of
8190       the ATV block. The AGC control algorithms are all implemented in
8191       microcode.
8192
8193    ATV SETTINGS
8194
8195       (Shadow settings will not be used for now, they will be implemented
8196        later on because of the schedule)
8197
8198       Several HW/SCU "settings" can be used for ATV. The standard selection
8199       will reset most of these settings. To avoid that the end user apllication
8200       has to perform these settings each time the ATV or FM standards is
8201       selected the driver will shadow these settings. This enables the end user
8202       to perform the settings only once after a drx_open(). The driver must
8203       write the shadow settings to HW/SCU incase:
8204          ( setstandard FM/ATV) ||
8205          ( settings have changed && FM/ATV standard is active)
8206       The shadow settings will be stored in the device specific data container.
8207       A set of flags will be defined to flag changes in shadow settings.
8208       A routine will be implemented to write all changed shadow settings to
8209       HW/SCU.
8210
8211       The "settings" will consist of: AGC settings, filter settings etc.
8212
8213       Disadvantage of use of shadow settings:
8214       Direct changes in HW/SCU registers will not be reflected in the
8215       shadow settings and these changes will be overwritten during a next
8216       update. This can happen during evaluation. This will not be a problem
8217       for normal customer usage.
8218 */
8219 /* -------------------------------------------------------------------------- */
8220
8221 /**
8222 * \brief Get array index for atv coef (ext_attr->atvTopCoefX[index])
8223 * \param standard
8224 * \param pointer to index
8225 * \return int.
8226 *
8227 */
8228 static int atv_equ_coef_index(enum drx_standard standard, int *index)
8229 {
8230         switch (standard) {
8231         case DRX_STANDARD_PAL_SECAM_BG:
8232                 *index = (int)DRXJ_COEF_IDX_BG;
8233                 break;
8234         case DRX_STANDARD_PAL_SECAM_DK:
8235                 *index = (int)DRXJ_COEF_IDX_DK;
8236                 break;
8237         case DRX_STANDARD_PAL_SECAM_I:
8238                 *index = (int)DRXJ_COEF_IDX_I;
8239                 break;
8240         case DRX_STANDARD_PAL_SECAM_L:
8241                 *index = (int)DRXJ_COEF_IDX_L;
8242                 break;
8243         case DRX_STANDARD_PAL_SECAM_LP:
8244                 *index = (int)DRXJ_COEF_IDX_LP;
8245                 break;
8246         case DRX_STANDARD_NTSC:
8247                 *index = (int)DRXJ_COEF_IDX_MN;
8248                 break;
8249         case DRX_STANDARD_FM:
8250                 *index = (int)DRXJ_COEF_IDX_FM;
8251                 break;
8252         default:
8253                 *index = (int)DRXJ_COEF_IDX_MN; /* still return a valid index */
8254                 return DRX_STS_ERROR;
8255                 break;
8256         }
8257
8258         return DRX_STS_OK;
8259 }
8260
8261 /* -------------------------------------------------------------------------- */
8262 /**
8263 * \fn int atv_update_config ()
8264 * \brief Flush changes in ATV shadow registers to physical registers.
8265 * \param demod instance of demodulator
8266 * \param force_update don't look at standard or change flags, flush all.
8267 * \return int.
8268 *
8269 */
8270 static int
8271 atv_update_config(pdrx_demod_instance_t demod, bool force_update)
8272 {
8273         struct i2c_device_addr *dev_addr = NULL;
8274         pdrxj_data_t ext_attr = NULL;
8275
8276         dev_addr = demod->my_i2c_dev_addr;
8277         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
8278
8279         /* equalizer coefficients */
8280         if (force_update ||
8281             ((ext_attr->atv_cfg_changed_flags & DRXJ_ATV_CHANGED_COEF) != 0)) {
8282                 int index = 0;
8283
8284                 CHK_ERROR(atv_equ_coef_index(ext_attr->standard, &index));
8285                 WR16(dev_addr, ATV_TOP_EQU0__A, ext_attr->atv_top_equ0[index]);
8286                 WR16(dev_addr, ATV_TOP_EQU1__A, ext_attr->atv_top_equ1[index]);
8287                 WR16(dev_addr, ATV_TOP_EQU2__A, ext_attr->atv_top_equ2[index]);
8288                 WR16(dev_addr, ATV_TOP_EQU3__A, ext_attr->atv_top_equ3[index]);
8289         }
8290
8291         /* bypass fast carrier recovery */
8292         if (force_update) {
8293                 u16 data = 0;
8294
8295                 RR16(dev_addr, IQM_RT_ROT_BP__A, &data);
8296                 data &= (~((u16) IQM_RT_ROT_BP_ROT_OFF__M));
8297                 if (ext_attr->phase_correction_bypass) {
8298                         data |= IQM_RT_ROT_BP_ROT_OFF_OFF;
8299                 } else {
8300                         data |= IQM_RT_ROT_BP_ROT_OFF_ACTIVE;
8301                 }
8302                 WR16(dev_addr, IQM_RT_ROT_BP__A, data);
8303         }
8304
8305         /* peak filter setting */
8306         if (force_update ||
8307             ((ext_attr->atv_cfg_changed_flags & DRXJ_ATV_CHANGED_PEAK_FLT) != 0)) {
8308                 WR16(dev_addr, ATV_TOP_VID_PEAK__A, ext_attr->atv_top_vid_peak);
8309         }
8310
8311         /* noise filter setting */
8312         if (force_update ||
8313             ((ext_attr->atv_cfg_changed_flags & DRXJ_ATV_CHANGED_NOISE_FLT) != 0)) {
8314                 WR16(dev_addr, ATV_TOP_NOISE_TH__A, ext_attr->atv_top_noise_th);
8315         }
8316
8317         /* SIF attenuation */
8318         if (force_update ||
8319             ((ext_attr->atv_cfg_changed_flags & DRXJ_ATV_CHANGED_SIF_ATT) != 0)) {
8320                 u16 attenuation = 0;
8321
8322                 switch (ext_attr->sif_attenuation) {
8323                 case DRXJ_SIF_ATTENUATION_0DB:
8324                         attenuation = ATV_TOP_AF_SIF_ATT_0DB;
8325                         break;
8326                 case DRXJ_SIF_ATTENUATION_3DB:
8327                         attenuation = ATV_TOP_AF_SIF_ATT_M3DB;
8328                         break;
8329                 case DRXJ_SIF_ATTENUATION_6DB:
8330                         attenuation = ATV_TOP_AF_SIF_ATT_M6DB;
8331                         break;
8332                 case DRXJ_SIF_ATTENUATION_9DB:
8333                         attenuation = ATV_TOP_AF_SIF_ATT_M9DB;
8334                         break;
8335                 default:
8336                         return DRX_STS_ERROR;
8337                         break;
8338                 }
8339                 WR16(dev_addr, ATV_TOP_AF_SIF_ATT__A, attenuation);
8340         }
8341
8342         /* SIF & CVBS enable */
8343         if (force_update ||
8344             ((ext_attr->atv_cfg_changed_flags & DRXJ_ATV_CHANGED_OUTPUT) != 0)) {
8345                 u16 data = 0;
8346
8347                 RR16(dev_addr, ATV_TOP_STDBY__A, &data);
8348                 if (ext_attr->enable_cvbs_output) {
8349                         data |= ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE;
8350                 } else {
8351                         data &= (~ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE);
8352                 }
8353
8354                 if (ext_attr->enable_sif_output) {
8355                         data &= (~ATV_TOP_STDBY_SIF_STDBY_STANDBY);
8356                 } else {
8357                         data |= ATV_TOP_STDBY_SIF_STDBY_STANDBY;
8358                 }
8359                 WR16(dev_addr, ATV_TOP_STDBY__A, data);
8360         }
8361
8362         ext_attr->atv_cfg_changed_flags = 0;
8363
8364         return (DRX_STS_OK);
8365 rw_error:
8366         return (DRX_STS_ERROR);
8367 }
8368
8369 /* -------------------------------------------------------------------------- */
8370 /**
8371 * \fn int ctrl_set_cfg_atv_output()
8372 * \brief Configure ATV ouputs
8373 * \param demod instance of demodulator
8374 * \param output_cfg output configuaration
8375 * \return int.
8376 *
8377 */
8378 static int
8379 ctrl_set_cfg_atv_output(pdrx_demod_instance_t demod, p_drxj_cfg_atv_output_t output_cfg)
8380 {
8381         pdrxj_data_t ext_attr = NULL;
8382
8383         /* Check arguments */
8384         if (output_cfg == NULL) {
8385                 return (DRX_STS_INVALID_ARG);
8386         }
8387
8388         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
8389         if (output_cfg->enable_sif_output) {
8390                 switch (output_cfg->sif_attenuation) {
8391                 case DRXJ_SIF_ATTENUATION_0DB:  /* fallthrough */
8392                 case DRXJ_SIF_ATTENUATION_3DB:  /* fallthrough */
8393                 case DRXJ_SIF_ATTENUATION_6DB:  /* fallthrough */
8394                 case DRXJ_SIF_ATTENUATION_9DB:
8395                         /* Do nothing */
8396                         break;
8397                 default:
8398                         return DRX_STS_INVALID_ARG;
8399                         break;
8400                 }
8401
8402                 if (ext_attr->sif_attenuation != output_cfg->sif_attenuation) {
8403                         ext_attr->sif_attenuation = output_cfg->sif_attenuation;
8404                         ext_attr->atv_cfg_changed_flags |= DRXJ_ATV_CHANGED_SIF_ATT;
8405                 }
8406         }
8407
8408         if (ext_attr->enable_cvbs_output != output_cfg->enable_cvbs_output) {
8409                 ext_attr->enable_cvbs_output = output_cfg->enable_cvbs_output;
8410                 ext_attr->atv_cfg_changed_flags |= DRXJ_ATV_CHANGED_OUTPUT;
8411         }
8412
8413         if (ext_attr->enable_sif_output != output_cfg->enable_sif_output) {
8414                 ext_attr->enable_sif_output = output_cfg->enable_sif_output;
8415                 ext_attr->atv_cfg_changed_flags |= DRXJ_ATV_CHANGED_OUTPUT;
8416         }
8417
8418         CHK_ERROR(atv_update_config(demod, false));
8419
8420         return (DRX_STS_OK);
8421 rw_error:
8422         return (DRX_STS_ERROR);
8423 }
8424
8425 /* -------------------------------------------------------------------------- */
8426 #ifndef DRXJ_DIGITAL_ONLY
8427 /**
8428 * \fn int ctrl_set_cfg_atv_equ_coef()
8429 * \brief Set ATV equalizer coefficients
8430 * \param demod instance of demodulator
8431 * \param coef  the equalizer coefficients
8432 * \return int.
8433 *
8434 */
8435 static int
8436 ctrl_set_cfg_atv_equ_coef(pdrx_demod_instance_t demod, p_drxj_cfg_atv_equ_coef_t coef)
8437 {
8438         pdrxj_data_t ext_attr = NULL;
8439         int index;
8440
8441         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
8442
8443         /* current standard needs to be an ATV standard */
8444         if (!DRXJ_ISATVSTD(ext_attr->standard)) {
8445                 return DRX_STS_ERROR;
8446         }
8447
8448         /* Check arguments */
8449         if ((coef == NULL) ||
8450             (coef->coef0 > (ATV_TOP_EQU0_EQU_C0__M / 2)) ||
8451             (coef->coef1 > (ATV_TOP_EQU1_EQU_C1__M / 2)) ||
8452             (coef->coef2 > (ATV_TOP_EQU2_EQU_C2__M / 2)) ||
8453             (coef->coef3 > (ATV_TOP_EQU3_EQU_C3__M / 2)) ||
8454             (coef->coef0 < ((s16) ~(ATV_TOP_EQU0_EQU_C0__M >> 1))) ||
8455             (coef->coef1 < ((s16) ~(ATV_TOP_EQU1_EQU_C1__M >> 1))) ||
8456             (coef->coef2 < ((s16) ~(ATV_TOP_EQU2_EQU_C2__M >> 1))) ||
8457             (coef->coef3 < ((s16) ~(ATV_TOP_EQU3_EQU_C3__M >> 1)))) {
8458                 return (DRX_STS_INVALID_ARG);
8459         }
8460
8461         CHK_ERROR(atv_equ_coef_index(ext_attr->standard, &index));
8462         ext_attr->atv_top_equ0[index] = coef->coef0;
8463         ext_attr->atv_top_equ1[index] = coef->coef1;
8464         ext_attr->atv_top_equ2[index] = coef->coef2;
8465         ext_attr->atv_top_equ3[index] = coef->coef3;
8466         ext_attr->atv_cfg_changed_flags |= DRXJ_ATV_CHANGED_COEF;
8467
8468         CHK_ERROR(atv_update_config(demod, false));
8469
8470         return (DRX_STS_OK);
8471 rw_error:
8472         return (DRX_STS_ERROR);
8473 }
8474
8475 /* -------------------------------------------------------------------------- */
8476 /**
8477 * \fn int ctrl_get_cfg_atv_equ_coef()
8478 * \brief Get ATV equ coef settings
8479 * \param demod instance of demodulator
8480 * \param coef The ATV equ coefficients
8481 * \return int.
8482 *
8483 * The values are read from the shadow registers maintained by the drxdriver
8484 * If registers are manipulated outside of the drxdriver scope the reported
8485 * settings will not reflect these changes because of the use of shadow
8486 * regitsers.
8487 *
8488 */
8489 static int
8490 ctrl_get_cfg_atv_equ_coef(pdrx_demod_instance_t demod, p_drxj_cfg_atv_equ_coef_t coef)
8491 {
8492         pdrxj_data_t ext_attr = NULL;
8493         int index = 0;
8494
8495         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
8496
8497         /* current standard needs to be an ATV standard */
8498         if (!DRXJ_ISATVSTD(ext_attr->standard)) {
8499                 return DRX_STS_ERROR;
8500         }
8501
8502         /* Check arguments */
8503         if (coef == NULL) {
8504                 return DRX_STS_INVALID_ARG;
8505         }
8506
8507         CHK_ERROR(atv_equ_coef_index(ext_attr->standard, &index));
8508         coef->coef0 = ext_attr->atv_top_equ0[index];
8509         coef->coef1 = ext_attr->atv_top_equ1[index];
8510         coef->coef2 = ext_attr->atv_top_equ2[index];
8511         coef->coef3 = ext_attr->atv_top_equ3[index];
8512
8513         return (DRX_STS_OK);
8514 rw_error:
8515         return (DRX_STS_ERROR);
8516 }
8517
8518 /* -------------------------------------------------------------------------- */
8519 /**
8520 * \fn int ctrl_set_cfg_atv_misc()
8521 * \brief Set misc. settings for ATV.
8522 * \param demod instance of demodulator
8523 * \param
8524 * \return int.
8525 *
8526 */
8527 static int
8528 ctrl_set_cfg_atv_misc(pdrx_demod_instance_t demod, p_drxj_cfg_atv_misc_t settings)
8529 {
8530         pdrxj_data_t ext_attr = NULL;
8531
8532         /* Check arguments */
8533         if ((settings == NULL) ||
8534             ((settings->peak_filter) < (s16) (-8)) ||
8535             ((settings->peak_filter) > (s16) (15)) ||
8536             ((settings->noise_filter) > 15)) {
8537                 return (DRX_STS_INVALID_ARG);
8538         }
8539         /* if */
8540         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
8541
8542         if (settings->peak_filter != ext_attr->atv_top_vid_peak) {
8543                 ext_attr->atv_top_vid_peak = settings->peak_filter;
8544                 ext_attr->atv_cfg_changed_flags |= DRXJ_ATV_CHANGED_PEAK_FLT;
8545         }
8546
8547         if (settings->noise_filter != ext_attr->atv_top_noise_th) {
8548                 ext_attr->atv_top_noise_th = settings->noise_filter;
8549                 ext_attr->atv_cfg_changed_flags |= DRXJ_ATV_CHANGED_NOISE_FLT;
8550         }
8551
8552         CHK_ERROR(atv_update_config(demod, false));
8553
8554         return (DRX_STS_OK);
8555 rw_error:
8556         return (DRX_STS_ERROR);
8557 }
8558
8559 /* -------------------------------------------------------------------------- */
8560 /**
8561 * \fn int  ctrl_get_cfg_atv_misc()
8562 * \brief Get misc settings of ATV.
8563 * \param demod instance of demodulator
8564 * \param settings misc. ATV settings
8565 * \return int.
8566 *
8567 * The values are read from the shadow registers maintained by the drxdriver
8568 * If registers are manipulated outside of the drxdriver scope the reported
8569 * settings will not reflect these changes because of the use of shadow
8570 * regitsers.
8571 */
8572 static int
8573 ctrl_get_cfg_atv_misc(pdrx_demod_instance_t demod, p_drxj_cfg_atv_misc_t settings)
8574 {
8575         pdrxj_data_t ext_attr = NULL;
8576
8577         /* Check arguments */
8578         if (settings == NULL) {
8579                 return DRX_STS_INVALID_ARG;
8580         }
8581
8582         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
8583
8584         settings->peak_filter = ext_attr->atv_top_vid_peak;
8585         settings->noise_filter = ext_attr->atv_top_noise_th;
8586
8587         return (DRX_STS_OK);
8588 }
8589
8590 /* -------------------------------------------------------------------------- */
8591
8592 /* -------------------------------------------------------------------------- */
8593 /**
8594 * \fn int  ctrl_get_cfg_atv_output()
8595 * \brief
8596 * \param demod instance of demodulator
8597 * \param output_cfg output configuaration
8598 * \return int.
8599 *
8600 */
8601 static int
8602 ctrl_get_cfg_atv_output(pdrx_demod_instance_t demod, p_drxj_cfg_atv_output_t output_cfg)
8603 {
8604         u16 data = 0;
8605
8606         /* Check arguments */
8607         if (output_cfg == NULL) {
8608                 return DRX_STS_INVALID_ARG;
8609         }
8610
8611         RR16(demod->my_i2c_dev_addr, ATV_TOP_STDBY__A, &data);
8612         if (data & ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE) {
8613                 output_cfg->enable_cvbs_output = true;
8614         } else {
8615                 output_cfg->enable_cvbs_output = false;
8616         }
8617
8618         if (data & ATV_TOP_STDBY_SIF_STDBY_STANDBY) {
8619                 output_cfg->enable_sif_output = false;
8620         } else {
8621                 output_cfg->enable_sif_output = true;
8622                 RR16(demod->my_i2c_dev_addr, ATV_TOP_AF_SIF_ATT__A, &data);
8623                 output_cfg->sif_attenuation = (drxjsif_attenuation_t) data;
8624         }
8625
8626         return (DRX_STS_OK);
8627 rw_error:
8628         return (DRX_STS_ERROR);
8629 }
8630
8631 /* -------------------------------------------------------------------------- */
8632 /**
8633 * \fn int  ctrl_get_cfg_atv_agc_status()
8634 * \brief
8635 * \param demod instance of demodulator
8636 * \param agc_status agc status
8637 * \return int.
8638 *
8639 */
8640 static int
8641 ctrl_get_cfg_atv_agc_status(pdrx_demod_instance_t demod,
8642                        p_drxj_cfg_atv_agc_status_t agc_status)
8643 {
8644         struct i2c_device_addr *dev_addr = NULL;
8645         pdrxj_data_t ext_attr = NULL;
8646         u16 data = 0;
8647         u32 tmp = 0;
8648
8649         /* Check arguments */
8650         if (agc_status == NULL) {
8651                 return DRX_STS_INVALID_ARG;
8652         }
8653
8654         dev_addr = demod->my_i2c_dev_addr;
8655         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
8656
8657         /*
8658            RFgain = (IQM_AF_AGC_RF__A * 26.75)/1000 (uA)
8659            = ((IQM_AF_AGC_RF__A * 27) - (0.25*IQM_AF_AGC_RF__A))/1000
8660
8661            IQM_AF_AGC_RF__A * 27 is 20 bits worst case.
8662          */
8663         RR16(dev_addr, IQM_AF_AGC_RF__A, &data);
8664         tmp = ((u32) data) * 27 - ((u32) (data >> 2));  /* nA */
8665         agc_status->rf_agc_gain = (u16) (tmp / 1000);   /* uA */
8666         /* rounding */
8667         if (tmp % 1000 >= 500) {
8668                 (agc_status->rf_agc_gain)++;
8669         }
8670
8671         /*
8672            IFgain = (IQM_AF_AGC_IF__A * 26.75)/1000 (uA)
8673            = ((IQM_AF_AGC_IF__A * 27) - (0.25*IQM_AF_AGC_IF__A))/1000
8674
8675            IQM_AF_AGC_IF__A * 27 is 20 bits worst case.
8676          */
8677         RR16(dev_addr, IQM_AF_AGC_IF__A, &data);
8678         tmp = ((u32) data) * 27 - ((u32) (data >> 2));  /* nA */
8679         agc_status->if_agc_gain = (u16) (tmp / 1000);   /* uA */
8680         /* rounding */
8681         if (tmp % 1000 >= 500) {
8682                 (agc_status->if_agc_gain)++;
8683         }
8684
8685         /*
8686            videoGain = (ATV_TOP_SFR_VID_GAIN__A/16 -150)* 0.05 (dB)
8687            = (ATV_TOP_SFR_VID_GAIN__A/16 -150)/20 (dB)
8688            = 10*(ATV_TOP_SFR_VID_GAIN__A/16 -150)/20 (in 0.1 dB)
8689            = (ATV_TOP_SFR_VID_GAIN__A/16 -150)/2 (in 0.1 dB)
8690            = (ATV_TOP_SFR_VID_GAIN__A/32) - 75 (in 0.1 dB)
8691          */
8692
8693         SARR16(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, &data);
8694         /* dividing by 32 inclusive rounding */
8695         data >>= 4;
8696         if ((data & 1) != 0) {
8697                 data++;
8698         }
8699         data >>= 1;
8700         agc_status->video_agc_gain = ((s16) data) - 75; /* 0.1 dB */
8701
8702         /*
8703            audioGain = (SCU_RAM_ATV_SIF_GAIN__A -8)* 0.05 (dB)
8704            = (SCU_RAM_ATV_SIF_GAIN__A -8)/20 (dB)
8705            = 10*(SCU_RAM_ATV_SIF_GAIN__A -8)/20 (in 0.1 dB)
8706            = (SCU_RAM_ATV_SIF_GAIN__A -8)/2 (in 0.1 dB)
8707            = (SCU_RAM_ATV_SIF_GAIN__A/2) - 4 (in 0.1 dB)
8708          */
8709
8710         SARR16(dev_addr, SCU_RAM_ATV_SIF_GAIN__A, &data);
8711         data &= SCU_RAM_ATV_SIF_GAIN__M;
8712         /* dividing by 2 inclusive rounding */
8713         if ((data & 1) != 0) {
8714                 data++;
8715         }
8716         data >>= 1;
8717         agc_status->audio_agc_gain = ((s16) data) - 4;  /* 0.1 dB */
8718
8719         /* Loop gain's */
8720         SARR16(dev_addr, SCU_RAM_AGC_KI__A, &data);
8721         agc_status->video_agc_loop_gain =
8722             ((data & SCU_RAM_AGC_KI_DGAIN__M) >> SCU_RAM_AGC_KI_DGAIN__B);
8723         agc_status->rf_agc_loop_gain =
8724             ((data & SCU_RAM_AGC_KI_RF__M) >> SCU_RAM_AGC_KI_RF__B);
8725         agc_status->if_agc_loop_gain =
8726             ((data & SCU_RAM_AGC_KI_IF__M) >> SCU_RAM_AGC_KI_IF__B);
8727
8728         return (DRX_STS_OK);
8729 rw_error:
8730         return (DRX_STS_ERROR);
8731 }
8732
8733 /* -------------------------------------------------------------------------- */
8734
8735 /**
8736 * \fn int power_up_atv ()
8737 * \brief Power up ATV.
8738 * \param demod instance of demodulator
8739 * \param standard either NTSC or FM (sub strandard for ATV )
8740 * \return int.
8741 *
8742 * * Starts ATV and IQM
8743 * * AUdio already started during standard init for ATV.
8744 */
8745 static int power_up_atv(pdrx_demod_instance_t demod, enum drx_standard standard)
8746 {
8747         struct i2c_device_addr *dev_addr = NULL;
8748         pdrxj_data_t ext_attr = NULL;
8749
8750         dev_addr = demod->my_i2c_dev_addr;
8751         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
8752
8753         /* ATV NTSC */
8754         WR16(dev_addr, ATV_COMM_EXEC__A, ATV_COMM_EXEC_ACTIVE);
8755         /* turn on IQM_AF */
8756         CHK_ERROR(set_iqm_af(demod, true));
8757         CHK_ERROR(adc_synchronization(demod));
8758
8759         WR16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_ACTIVE);
8760
8761         /* Audio, already done during set standard */
8762
8763         return (DRX_STS_OK);
8764 rw_error:
8765         return (DRX_STS_ERROR);
8766 }
8767 #endif /* #ifndef DRXJ_DIGITAL_ONLY */
8768
8769 /* -------------------------------------------------------------------------- */
8770
8771 /**
8772 * \fn int power_down_atv ()
8773 * \brief Power down ATV.
8774 * \param demod instance of demodulator
8775 * \param standard either NTSC or FM (sub strandard for ATV )
8776 * \return int.
8777 *
8778 *  Stops and thus resets ATV and IQM block
8779 *  SIF and CVBS ADC are powered down
8780 *  Calls audio power down
8781 */
8782 static int
8783 power_down_atv(pdrx_demod_instance_t demod, enum drx_standard standard, bool primary)
8784 {
8785         struct i2c_device_addr *dev_addr = NULL;
8786         drxjscu_cmd_t cmd_scu = { /* command      */ 0,
8787                 /* parameter_len */ 0,
8788                 /* result_len    */ 0,
8789                 /* *parameter   */ NULL,
8790                 /* *result      */ NULL
8791         };
8792         u16 cmd_result = 0;
8793         pdrxj_data_t ext_attr = NULL;
8794
8795         dev_addr = demod->my_i2c_dev_addr;
8796         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
8797         /* ATV NTSC */
8798
8799         /* Stop ATV SCU (will reset ATV and IQM hardware */
8800         cmd_scu.command = SCU_RAM_COMMAND_STANDARD_ATV |
8801             SCU_RAM_COMMAND_CMD_DEMOD_STOP;
8802         cmd_scu.parameter_len = 0;
8803         cmd_scu.result_len = 1;
8804         cmd_scu.parameter = NULL;
8805         cmd_scu.result = &cmd_result;
8806         CHK_ERROR(scu_command(dev_addr, &cmd_scu));
8807         /* Disable ATV outputs (ATV reset enables CVBS, undo this) */
8808         WR16(dev_addr, ATV_TOP_STDBY__A, (ATV_TOP_STDBY_SIF_STDBY_STANDBY &
8809                                          (~ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE)));
8810
8811         WR16(dev_addr, ATV_COMM_EXEC__A, ATV_COMM_EXEC_STOP);
8812         if (primary == true) {
8813                 WR16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP);
8814                 CHK_ERROR(set_iqm_af(demod, false));
8815         } else {
8816                 WR16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP);
8817                 WR16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP);
8818                 WR16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP);
8819                 WR16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP);
8820                 WR16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP);
8821         }
8822         CHK_ERROR(power_down_aud(demod));
8823
8824         return (DRX_STS_OK);
8825 rw_error:
8826         return (DRX_STS_ERROR);
8827 }
8828
8829 /* -------------------------------------------------------------------------- */
8830 /**
8831 * \fn int set_atv_standard ()
8832 * \brief Set up ATV demodulator.
8833 * \param demod instance of demodulator
8834 * \param standard either NTSC or FM (sub strandard for ATV )
8835 * \return int.
8836 *
8837 * Init all channel independent registers.
8838 * Assuming that IQM, ATV and AUD blocks have been reset and are in STOP mode
8839 *
8840 */
8841 #ifndef DRXJ_DIGITAL_ONLY
8842 #define SCU_RAM_ATV_ENABLE_IIR_WA__A 0x831F6D   /* TODO remove after done with reg import */
8843 static int
8844 set_atv_standard(pdrx_demod_instance_t demod, enum drx_standard *standard)
8845 {
8846 /* TODO: enable alternative for tap settings via external file
8847
8848 something like:
8849 #ifdef   DRXJ_ATV_COEF_FILE
8850 #include DRXJ_ATV_COEF_FILE
8851 #else
8852 ... code defining fixed coef's ...
8853 #endif
8854
8855 Cutsomer must create file "customer_coefs.c.inc" containing
8856 modified copy off the constants below, and define the compiler
8857 switch DRXJ_ATV_COEF_FILE="customer_coefs.c.inc".
8858
8859 Still to check if this will work; DRXJ_16TO8 macro may cause
8860 trouble ?
8861 */
8862         const u8 ntsc_taps_re[] = {
8863                 DRXJ_16TO8(-12),        /* re0  */
8864                 DRXJ_16TO8(-9), /* re1  */
8865                 DRXJ_16TO8(9),  /* re2  */
8866                 DRXJ_16TO8(19), /* re3  */
8867                 DRXJ_16TO8(-4), /* re4  */
8868                 DRXJ_16TO8(-24),        /* re5  */
8869                 DRXJ_16TO8(-6), /* re6  */
8870                 DRXJ_16TO8(16), /* re7  */
8871                 DRXJ_16TO8(6),  /* re8  */
8872                 DRXJ_16TO8(-16),        /* re9  */
8873                 DRXJ_16TO8(-5), /* re10 */
8874                 DRXJ_16TO8(13), /* re11 */
8875                 DRXJ_16TO8(-2), /* re12 */
8876                 DRXJ_16TO8(-20),        /* re13 */
8877                 DRXJ_16TO8(4),  /* re14 */
8878                 DRXJ_16TO8(25), /* re15 */
8879                 DRXJ_16TO8(-6), /* re16 */
8880                 DRXJ_16TO8(-36),        /* re17 */
8881                 DRXJ_16TO8(2),  /* re18 */
8882                 DRXJ_16TO8(38), /* re19 */
8883                 DRXJ_16TO8(-10),        /* re20 */
8884                 DRXJ_16TO8(-48),        /* re21 */
8885                 DRXJ_16TO8(35), /* re22 */
8886                 DRXJ_16TO8(94), /* re23 */
8887                 DRXJ_16TO8(-59),        /* re24 */
8888                 DRXJ_16TO8(-217),       /* re25 */
8889                 DRXJ_16TO8(50), /* re26 */
8890                 DRXJ_16TO8(679) /* re27 */
8891         };
8892         const u8 ntsc_taps_im[] = {
8893                 DRXJ_16TO8(11), /* im0  */
8894                 DRXJ_16TO8(1),  /* im1  */
8895                 DRXJ_16TO8(-10),        /* im2  */
8896                 DRXJ_16TO8(2),  /* im3  */
8897                 DRXJ_16TO8(24), /* im4  */
8898                 DRXJ_16TO8(21), /* im5  */
8899                 DRXJ_16TO8(1),  /* im6  */
8900                 DRXJ_16TO8(-4), /* im7  */
8901                 DRXJ_16TO8(7),  /* im8  */
8902                 DRXJ_16TO8(14), /* im9  */
8903                 DRXJ_16TO8(27), /* im10 */
8904                 DRXJ_16TO8(42), /* im11 */
8905                 DRXJ_16TO8(22), /* im12 */
8906                 DRXJ_16TO8(-20),        /* im13 */
8907                 DRXJ_16TO8(2),  /* im14 */
8908                 DRXJ_16TO8(98), /* im15 */
8909                 DRXJ_16TO8(122),        /* im16 */
8910                 DRXJ_16TO8(0),  /* im17 */
8911                 DRXJ_16TO8(-85),        /* im18 */
8912                 DRXJ_16TO8(51), /* im19 */
8913                 DRXJ_16TO8(247),        /* im20 */
8914                 DRXJ_16TO8(192),        /* im21 */
8915                 DRXJ_16TO8(-55),        /* im22 */
8916                 DRXJ_16TO8(-95),        /* im23 */
8917                 DRXJ_16TO8(217),        /* im24 */
8918                 DRXJ_16TO8(544),        /* im25 */
8919                 DRXJ_16TO8(553),        /* im26 */
8920                 DRXJ_16TO8(302) /* im27 */
8921         };
8922         const u8 bg_taps_re[] = {
8923                 DRXJ_16TO8(-18),        /* re0  */
8924                 DRXJ_16TO8(18), /* re1  */
8925                 DRXJ_16TO8(19), /* re2  */
8926                 DRXJ_16TO8(-26),        /* re3  */
8927                 DRXJ_16TO8(-20),        /* re4  */
8928                 DRXJ_16TO8(36), /* re5  */
8929                 DRXJ_16TO8(5),  /* re6  */
8930                 DRXJ_16TO8(-51),        /* re7  */
8931                 DRXJ_16TO8(15), /* re8  */
8932                 DRXJ_16TO8(45), /* re9  */
8933                 DRXJ_16TO8(-46),        /* re10 */
8934                 DRXJ_16TO8(-24),        /* re11 */
8935                 DRXJ_16TO8(71), /* re12 */
8936                 DRXJ_16TO8(-17),        /* re13 */
8937                 DRXJ_16TO8(-83),        /* re14 */
8938                 DRXJ_16TO8(74), /* re15 */
8939                 DRXJ_16TO8(75), /* re16 */
8940                 DRXJ_16TO8(-134),       /* re17 */
8941                 DRXJ_16TO8(-40),        /* re18 */
8942                 DRXJ_16TO8(191),        /* re19 */
8943                 DRXJ_16TO8(-11),        /* re20 */
8944                 DRXJ_16TO8(-233),       /* re21 */
8945                 DRXJ_16TO8(74), /* re22 */
8946                 DRXJ_16TO8(271),        /* re23 */
8947                 DRXJ_16TO8(-132),       /* re24 */
8948                 DRXJ_16TO8(-341),       /* re25 */
8949                 DRXJ_16TO8(172),        /* re26 */
8950                 DRXJ_16TO8(801) /* re27 */
8951         };
8952         const u8 bg_taps_im[] = {
8953                 DRXJ_16TO8(-24),        /* im0  */
8954                 DRXJ_16TO8(-10),        /* im1  */
8955                 DRXJ_16TO8(9),  /* im2  */
8956                 DRXJ_16TO8(-5), /* im3  */
8957                 DRXJ_16TO8(-51),        /* im4  */
8958                 DRXJ_16TO8(-17),        /* im5  */
8959                 DRXJ_16TO8(31), /* im6  */
8960                 DRXJ_16TO8(-48),        /* im7  */
8961                 DRXJ_16TO8(-95),        /* im8  */
8962                 DRXJ_16TO8(25), /* im9  */
8963                 DRXJ_16TO8(37), /* im10 */
8964                 DRXJ_16TO8(-123),       /* im11 */
8965                 DRXJ_16TO8(-77),        /* im12 */
8966                 DRXJ_16TO8(94), /* im13 */
8967                 DRXJ_16TO8(-10),        /* im14 */
8968                 DRXJ_16TO8(-149),       /* im15 */
8969                 DRXJ_16TO8(10), /* im16 */
8970                 DRXJ_16TO8(108),        /* im17 */
8971                 DRXJ_16TO8(-49),        /* im18 */
8972                 DRXJ_16TO8(-59),        /* im19 */
8973                 DRXJ_16TO8(90), /* im20 */
8974                 DRXJ_16TO8(73), /* im21 */
8975                 DRXJ_16TO8(55), /* im22 */
8976                 DRXJ_16TO8(148),        /* im23 */
8977                 DRXJ_16TO8(86), /* im24 */
8978                 DRXJ_16TO8(146),        /* im25 */
8979                 DRXJ_16TO8(687),        /* im26 */
8980                 DRXJ_16TO8(877) /* im27 */
8981         };
8982         const u8 dk_i_l_lp_taps_re[] = {
8983                 DRXJ_16TO8(-23),        /* re0  */
8984                 DRXJ_16TO8(9),  /* re1  */
8985                 DRXJ_16TO8(16), /* re2  */
8986                 DRXJ_16TO8(-26),        /* re3  */
8987                 DRXJ_16TO8(-3), /* re4  */
8988                 DRXJ_16TO8(13), /* re5  */
8989                 DRXJ_16TO8(-19),        /* re6  */
8990                 DRXJ_16TO8(-3), /* re7  */
8991                 DRXJ_16TO8(13), /* re8  */
8992                 DRXJ_16TO8(-26),        /* re9  */
8993                 DRXJ_16TO8(-4), /* re10 */
8994                 DRXJ_16TO8(28), /* re11 */
8995                 DRXJ_16TO8(-15),        /* re12 */
8996                 DRXJ_16TO8(-14),        /* re13 */
8997                 DRXJ_16TO8(10), /* re14 */
8998                 DRXJ_16TO8(1),  /* re15 */
8999                 DRXJ_16TO8(39), /* re16 */
9000                 DRXJ_16TO8(-18),        /* re17 */
9001                 DRXJ_16TO8(-90),        /* re18 */
9002                 DRXJ_16TO8(109),        /* re19 */
9003                 DRXJ_16TO8(113),        /* re20 */
9004                 DRXJ_16TO8(-235),       /* re21 */
9005                 DRXJ_16TO8(-49),        /* re22 */
9006                 DRXJ_16TO8(359),        /* re23 */
9007                 DRXJ_16TO8(-79),        /* re24 */
9008                 DRXJ_16TO8(-459),       /* re25 */
9009                 DRXJ_16TO8(206),        /* re26 */
9010                 DRXJ_16TO8(894) /* re27 */
9011         };
9012         const u8 dk_i_l_lp_taps_im[] = {
9013                 DRXJ_16TO8(-8), /* im0  */
9014                 DRXJ_16TO8(-20),        /* im1  */
9015                 DRXJ_16TO8(17), /* im2  */
9016                 DRXJ_16TO8(-14),        /* im3  */
9017                 DRXJ_16TO8(-52),        /* im4  */
9018                 DRXJ_16TO8(4),  /* im5  */
9019                 DRXJ_16TO8(9),  /* im6  */
9020                 DRXJ_16TO8(-62),        /* im7  */
9021                 DRXJ_16TO8(-47),        /* im8  */
9022                 DRXJ_16TO8(0),  /* im9  */
9023                 DRXJ_16TO8(-20),        /* im10 */
9024                 DRXJ_16TO8(-48),        /* im11 */
9025                 DRXJ_16TO8(-65),        /* im12 */
9026                 DRXJ_16TO8(-23),        /* im13 */
9027                 DRXJ_16TO8(44), /* im14 */
9028                 DRXJ_16TO8(-60),        /* im15 */
9029                 DRXJ_16TO8(-113),       /* im16 */
9030                 DRXJ_16TO8(92), /* im17 */
9031                 DRXJ_16TO8(81), /* im18 */
9032                 DRXJ_16TO8(-125),       /* im19 */
9033                 DRXJ_16TO8(28), /* im20 */
9034                 DRXJ_16TO8(182),        /* im21 */
9035                 DRXJ_16TO8(35), /* im22 */
9036                 DRXJ_16TO8(94), /* im23 */
9037                 DRXJ_16TO8(180),        /* im24 */
9038                 DRXJ_16TO8(134),        /* im25 */
9039                 DRXJ_16TO8(657),        /* im26 */
9040                 DRXJ_16TO8(1023)        /* im27 */
9041         };
9042         const u8 fm_taps_re[] = {
9043                 DRXJ_16TO8(0),  /* re0  */
9044                 DRXJ_16TO8(0),  /* re1  */
9045                 DRXJ_16TO8(0),  /* re2  */
9046                 DRXJ_16TO8(0),  /* re3  */
9047                 DRXJ_16TO8(0),  /* re4  */
9048                 DRXJ_16TO8(0),  /* re5  */
9049                 DRXJ_16TO8(0),  /* re6  */
9050                 DRXJ_16TO8(0),  /* re7  */
9051                 DRXJ_16TO8(0),  /* re8  */
9052                 DRXJ_16TO8(0),  /* re9  */
9053                 DRXJ_16TO8(0),  /* re10 */
9054                 DRXJ_16TO8(0),  /* re11 */
9055                 DRXJ_16TO8(0),  /* re12 */
9056                 DRXJ_16TO8(0),  /* re13 */
9057                 DRXJ_16TO8(0),  /* re14 */
9058                 DRXJ_16TO8(0),  /* re15 */
9059                 DRXJ_16TO8(0),  /* re16 */
9060                 DRXJ_16TO8(0),  /* re17 */
9061                 DRXJ_16TO8(0),  /* re18 */
9062                 DRXJ_16TO8(0),  /* re19 */
9063                 DRXJ_16TO8(0),  /* re20 */
9064                 DRXJ_16TO8(0),  /* re21 */
9065                 DRXJ_16TO8(0),  /* re22 */
9066                 DRXJ_16TO8(0),  /* re23 */
9067                 DRXJ_16TO8(0),  /* re24 */
9068                 DRXJ_16TO8(0),  /* re25 */
9069                 DRXJ_16TO8(0),  /* re26 */
9070                 DRXJ_16TO8(0)   /* re27 */
9071         };
9072         const u8 fm_taps_im[] = {
9073                 DRXJ_16TO8(-6), /* im0  */
9074                 DRXJ_16TO8(2),  /* im1  */
9075                 DRXJ_16TO8(14), /* im2  */
9076                 DRXJ_16TO8(-38),        /* im3  */
9077                 DRXJ_16TO8(58), /* im4  */
9078                 DRXJ_16TO8(-62),        /* im5  */
9079                 DRXJ_16TO8(42), /* im6  */
9080                 DRXJ_16TO8(0),  /* im7  */
9081                 DRXJ_16TO8(-45),        /* im8  */
9082                 DRXJ_16TO8(73), /* im9  */
9083                 DRXJ_16TO8(-65),        /* im10 */
9084                 DRXJ_16TO8(23), /* im11 */
9085                 DRXJ_16TO8(34), /* im12 */
9086                 DRXJ_16TO8(-77),        /* im13 */
9087                 DRXJ_16TO8(80), /* im14 */
9088                 DRXJ_16TO8(-39),        /* im15 */
9089                 DRXJ_16TO8(-25),        /* im16 */
9090                 DRXJ_16TO8(78), /* im17 */
9091                 DRXJ_16TO8(-90),        /* im18 */
9092                 DRXJ_16TO8(52), /* im19 */
9093                 DRXJ_16TO8(16), /* im20 */
9094                 DRXJ_16TO8(-77),        /* im21 */
9095                 DRXJ_16TO8(97), /* im22 */
9096                 DRXJ_16TO8(-62),        /* im23 */
9097                 DRXJ_16TO8(-8), /* im24 */
9098                 DRXJ_16TO8(75), /* im25 */
9099                 DRXJ_16TO8(-100),       /* im26 */
9100                 DRXJ_16TO8(70)  /* im27 */
9101         };
9102
9103         struct i2c_device_addr *dev_addr = NULL;
9104         drxjscu_cmd_t cmd_scu = { /* command      */ 0,
9105                 /* parameter_len */ 0,
9106                 /* result_len    */ 0,
9107                 /* *parameter   */ NULL,
9108                 /* *result      */ NULL
9109         };
9110         u16 cmd_result = 0;
9111         u16 cmd_param = 0;
9112 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
9113         drxu_code_info_t ucode_info;
9114         pdrx_common_attr_t common_attr = NULL;
9115 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
9116         pdrxj_data_t ext_attr = NULL;
9117
9118         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
9119         dev_addr = demod->my_i2c_dev_addr;
9120
9121 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
9122         common_attr = demod->my_common_attr;
9123
9124         /* Check if audio microcode is already uploaded */
9125         if (!(ext_attr->flag_aud_mc_uploaded)) {
9126                 ucode_info.mc_data = common_attr->microcode;
9127                 ucode_info.mc_size = common_attr->microcode_size;
9128
9129                 /* Upload only audio microcode */
9130                 CHK_ERROR(ctrl_u_codeUpload
9131                           (demod, &ucode_info, UCODE_UPLOAD, true));
9132
9133                 if (common_attr->verify_microcode == true) {
9134                         CHK_ERROR(ctrl_u_codeUpload
9135                                   (demod, &ucode_info, UCODE_VERIFY, true));
9136                 }
9137
9138                 /* Prevent uploading audio microcode again */
9139                 ext_attr->flag_aud_mc_uploaded = true;
9140         }
9141 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
9142
9143         WR16(dev_addr, ATV_COMM_EXEC__A, ATV_COMM_EXEC_STOP);
9144         WR16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP);
9145         WR16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP);
9146         WR16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP);
9147         WR16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP);
9148         WR16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP);
9149         /* Reset ATV SCU */
9150         cmd_scu.command = SCU_RAM_COMMAND_STANDARD_ATV |
9151             SCU_RAM_COMMAND_CMD_DEMOD_RESET;
9152         cmd_scu.parameter_len = 0;
9153         cmd_scu.result_len = 1;
9154         cmd_scu.parameter = NULL;
9155         cmd_scu.result = &cmd_result;
9156         CHK_ERROR(scu_command(dev_addr, &cmd_scu));
9157
9158         WR16(dev_addr, ATV_TOP_MOD_CONTROL__A, ATV_TOP_MOD_CONTROL__PRE);
9159
9160         /* TODO remove AUTO/OFF patches after ucode fix. */
9161         switch (*standard) {
9162         case DRX_STANDARD_NTSC:
9163                 /* NTSC */
9164                 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_MN;
9165
9166                 WR16(dev_addr, IQM_RT_LO_INCR__A, IQM_RT_LO_INCR_MN);
9167                 WR16(dev_addr, IQM_CF_MIDTAP__A, IQM_CF_MIDTAP_RE__M);
9168                 WRB(dev_addr, IQM_CF_TAP_RE0__A, sizeof(ntsc_taps_re),
9169                     ((u8 *) ntsc_taps_re));
9170                 WRB(dev_addr, IQM_CF_TAP_IM0__A, sizeof(ntsc_taps_im),
9171                     ((u8 *) ntsc_taps_im));
9172
9173                 WR16(dev_addr, ATV_TOP_CR_AMP_TH__A, ATV_TOP_CR_AMP_TH_MN);
9174                 WR16(dev_addr, ATV_TOP_CR_CONT__A,
9175                      (ATV_TOP_CR_CONT_CR_P_MN |
9176                       ATV_TOP_CR_CONT_CR_D_MN | ATV_TOP_CR_CONT_CR_I_MN));
9177                 WR16(dev_addr, ATV_TOP_CR_OVM_TH__A, ATV_TOP_CR_OVM_TH_MN);
9178                 WR16(dev_addr, ATV_TOP_STD__A, (ATV_TOP_STD_MODE_MN |
9179                                                ATV_TOP_STD_VID_POL_MN));
9180                 WR16(dev_addr, ATV_TOP_VID_AMP__A, ATV_TOP_VID_AMP_MN);
9181
9182                 WR16(dev_addr, SCU_RAM_ATV_AGC_MODE__A,
9183                      (SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_FM |
9184                       SCU_RAM_ATV_AGC_MODE_FAST_VAGC_EN_FAGC_ENABLE));
9185                 WR16(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000);
9186                 WR16(dev_addr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000);
9187                 WR16(dev_addr, SCU_RAM_ATV_AMS_MAX_REF__A,
9188                      SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_BG_MN);
9189                 ext_attr->phase_correction_bypass = false;
9190                 ext_attr->enable_cvbs_output = true;
9191                 break;
9192         case DRX_STANDARD_FM:
9193                 /* FM */
9194                 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_FM;
9195
9196                 WR16(dev_addr, IQM_RT_LO_INCR__A, 2994);
9197                 WR16(dev_addr, IQM_CF_MIDTAP__A, 0);
9198                 WRB(dev_addr, IQM_CF_TAP_RE0__A, sizeof(fm_taps_re),
9199                     ((u8 *) fm_taps_re));
9200                 WRB(dev_addr, IQM_CF_TAP_IM0__A, sizeof(fm_taps_im),
9201                     ((u8 *) fm_taps_im));
9202                 WR16(dev_addr, ATV_TOP_STD__A, (ATV_TOP_STD_MODE_FM |
9203                                                ATV_TOP_STD_VID_POL_FM));
9204                 WR16(dev_addr, ATV_TOP_MOD_CONTROL__A, 0);
9205                 WR16(dev_addr, ATV_TOP_CR_CONT__A, 0);
9206
9207                 WR16(dev_addr, SCU_RAM_ATV_AGC_MODE__A,
9208                      (SCU_RAM_ATV_AGC_MODE_VAGC_VEL_AGC_SLOW |
9209                       SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_FM));
9210                 WR16(dev_addr, IQM_RT_ROT_BP__A, IQM_RT_ROT_BP_ROT_OFF_OFF);
9211                 ext_attr->phase_correction_bypass = true;
9212                 ext_attr->enable_cvbs_output = false;
9213                 break;
9214         case DRX_STANDARD_PAL_SECAM_BG:
9215                 /* PAL/SECAM B/G */
9216                 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_B;
9217
9218                 WR16(dev_addr, IQM_RT_LO_INCR__A, 1820);        /* TODO check with IS */
9219                 WR16(dev_addr, IQM_CF_MIDTAP__A, IQM_CF_MIDTAP_RE__M);
9220                 WRB(dev_addr, IQM_CF_TAP_RE0__A, sizeof(bg_taps_re),
9221                     ((u8 *) bg_taps_re));
9222                 WRB(dev_addr, IQM_CF_TAP_IM0__A, sizeof(bg_taps_im),
9223                     ((u8 *) bg_taps_im));
9224                 WR16(dev_addr, ATV_TOP_VID_AMP__A, ATV_TOP_VID_AMP_BG);
9225                 WR16(dev_addr, ATV_TOP_CR_AMP_TH__A, ATV_TOP_CR_AMP_TH_BG);
9226                 WR16(dev_addr, ATV_TOP_CR_CONT__A,
9227                      (ATV_TOP_CR_CONT_CR_P_BG |
9228                       ATV_TOP_CR_CONT_CR_D_BG | ATV_TOP_CR_CONT_CR_I_BG));
9229                 WR16(dev_addr, ATV_TOP_CR_OVM_TH__A, ATV_TOP_CR_OVM_TH_BG);
9230                 WR16(dev_addr, ATV_TOP_STD__A, (ATV_TOP_STD_MODE_BG |
9231                                                ATV_TOP_STD_VID_POL_BG));
9232                 WR16(dev_addr, SCU_RAM_ATV_AGC_MODE__A,
9233                      (SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_FM |
9234                       SCU_RAM_ATV_AGC_MODE_FAST_VAGC_EN_FAGC_ENABLE));
9235                 WR16(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000);
9236                 WR16(dev_addr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000);
9237                 WR16(dev_addr, SCU_RAM_ATV_AMS_MAX_REF__A,
9238                      SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_BG_MN);
9239                 ext_attr->phase_correction_bypass = false;
9240                 ext_attr->atv_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
9241                 ext_attr->enable_cvbs_output = true;
9242                 break;
9243         case DRX_STANDARD_PAL_SECAM_DK:
9244                 /* PAL/SECAM D/K */
9245                 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_DK;
9246
9247                 WR16(dev_addr, IQM_RT_LO_INCR__A, 2225);        /* TODO check with IS */
9248                 WR16(dev_addr, IQM_CF_MIDTAP__A, IQM_CF_MIDTAP_RE__M);
9249                 WRB(dev_addr, IQM_CF_TAP_RE0__A, sizeof(dk_i_l_lp_taps_re),
9250                     ((u8 *) dk_i_l_lp_taps_re));
9251                 WRB(dev_addr, IQM_CF_TAP_IM0__A, sizeof(dk_i_l_lp_taps_im),
9252                     ((u8 *) dk_i_l_lp_taps_im));
9253                 WR16(dev_addr, ATV_TOP_CR_AMP_TH__A, ATV_TOP_CR_AMP_TH_DK);
9254                 WR16(dev_addr, ATV_TOP_VID_AMP__A, ATV_TOP_VID_AMP_DK);
9255                 WR16(dev_addr, ATV_TOP_CR_CONT__A,
9256                      (ATV_TOP_CR_CONT_CR_P_DK |
9257                       ATV_TOP_CR_CONT_CR_D_DK | ATV_TOP_CR_CONT_CR_I_DK));
9258                 WR16(dev_addr, ATV_TOP_CR_OVM_TH__A, ATV_TOP_CR_OVM_TH_DK);
9259                 WR16(dev_addr, ATV_TOP_STD__A, (ATV_TOP_STD_MODE_DK |
9260                                                ATV_TOP_STD_VID_POL_DK));
9261                 WR16(dev_addr, SCU_RAM_ATV_AGC_MODE__A,
9262                      (SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_FM |
9263                       SCU_RAM_ATV_AGC_MODE_FAST_VAGC_EN_FAGC_ENABLE));
9264                 WR16(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000);
9265                 WR16(dev_addr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000);
9266                 WR16(dev_addr, SCU_RAM_ATV_AMS_MAX_REF__A,
9267                      SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_DK);
9268                 ext_attr->phase_correction_bypass = false;
9269                 ext_attr->atv_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
9270                 ext_attr->enable_cvbs_output = true;
9271                 break;
9272         case DRX_STANDARD_PAL_SECAM_I:
9273                 /* PAL/SECAM I   */
9274                 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_I;
9275
9276                 WR16(dev_addr, IQM_RT_LO_INCR__A, 2225);        /* TODO check with IS */
9277                 WR16(dev_addr, IQM_CF_MIDTAP__A, IQM_CF_MIDTAP_RE__M);
9278                 WRB(dev_addr, IQM_CF_TAP_RE0__A, sizeof(dk_i_l_lp_taps_re),
9279                     ((u8 *) dk_i_l_lp_taps_re));
9280                 WRB(dev_addr, IQM_CF_TAP_IM0__A, sizeof(dk_i_l_lp_taps_im),
9281                     ((u8 *) dk_i_l_lp_taps_im));
9282                 WR16(dev_addr, ATV_TOP_CR_AMP_TH__A, ATV_TOP_CR_AMP_TH_I);
9283                 WR16(dev_addr, ATV_TOP_VID_AMP__A, ATV_TOP_VID_AMP_I);
9284                 WR16(dev_addr, ATV_TOP_CR_CONT__A,
9285                      (ATV_TOP_CR_CONT_CR_P_I |
9286                       ATV_TOP_CR_CONT_CR_D_I | ATV_TOP_CR_CONT_CR_I_I));
9287                 WR16(dev_addr, ATV_TOP_CR_OVM_TH__A, ATV_TOP_CR_OVM_TH_I);
9288                 WR16(dev_addr, ATV_TOP_STD__A, (ATV_TOP_STD_MODE_I |
9289                                                ATV_TOP_STD_VID_POL_I));
9290                 WR16(dev_addr, SCU_RAM_ATV_AGC_MODE__A,
9291                      (SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_FM |
9292                       SCU_RAM_ATV_AGC_MODE_FAST_VAGC_EN_FAGC_ENABLE));
9293                 WR16(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000);
9294                 WR16(dev_addr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000);
9295                 WR16(dev_addr, SCU_RAM_ATV_AMS_MAX_REF__A,
9296                      SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_I);
9297                 ext_attr->phase_correction_bypass = false;
9298                 ext_attr->atv_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
9299                 ext_attr->enable_cvbs_output = true;
9300                 break;
9301         case DRX_STANDARD_PAL_SECAM_L:
9302                 /* PAL/SECAM L with negative modulation */
9303                 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_L;
9304
9305                 WR16(dev_addr, IQM_RT_LO_INCR__A, 2225);        /* TODO check with IS */
9306                 WR16(dev_addr, ATV_TOP_VID_AMP__A, ATV_TOP_VID_AMP_L);
9307                 WR16(dev_addr, IQM_CF_MIDTAP__A, IQM_CF_MIDTAP_RE__M);
9308                 WRB(dev_addr, IQM_CF_TAP_RE0__A, sizeof(dk_i_l_lp_taps_re),
9309                     ((u8 *) dk_i_l_lp_taps_re));
9310                 WRB(dev_addr, IQM_CF_TAP_IM0__A, sizeof(dk_i_l_lp_taps_im),
9311                     ((u8 *) dk_i_l_lp_taps_im));
9312                 WR16(dev_addr, ATV_TOP_CR_AMP_TH__A, 0x2);      /* TODO check with IS */
9313                 WR16(dev_addr, ATV_TOP_CR_CONT__A,
9314                      (ATV_TOP_CR_CONT_CR_P_L |
9315                       ATV_TOP_CR_CONT_CR_D_L | ATV_TOP_CR_CONT_CR_I_L));
9316                 WR16(dev_addr, ATV_TOP_CR_OVM_TH__A, ATV_TOP_CR_OVM_TH_L);
9317                 WR16(dev_addr, ATV_TOP_STD__A, (ATV_TOP_STD_MODE_L |
9318                                                ATV_TOP_STD_VID_POL_L));
9319                 WR16(dev_addr, SCU_RAM_ATV_AGC_MODE__A,
9320                      (SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_AM |
9321                       SCU_RAM_ATV_AGC_MODE_BP_EN_BPC_ENABLE |
9322                       SCU_RAM_ATV_AGC_MODE_VAGC_VEL_AGC_SLOW));
9323                 WR16(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000);
9324                 WR16(dev_addr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000);
9325                 WR16(dev_addr, SCU_RAM_ATV_AMS_MAX_REF__A,
9326                      SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_LLP);
9327                 ext_attr->phase_correction_bypass = false;
9328                 ext_attr->atv_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_USER;
9329                 ext_attr->atv_if_agc_cfg.output_level = ext_attr->atv_rf_agc_cfg.top;
9330                 ext_attr->enable_cvbs_output = true;
9331                 break;
9332         case DRX_STANDARD_PAL_SECAM_LP:
9333                 /* PAL/SECAM L with positive modulation */
9334                 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_LP;
9335
9336                 WR16(dev_addr, ATV_TOP_VID_AMP__A, ATV_TOP_VID_AMP_LP);
9337                 WR16(dev_addr, IQM_RT_LO_INCR__A, 2225);        /* TODO check with IS */
9338                 WR16(dev_addr, IQM_CF_MIDTAP__A, IQM_CF_MIDTAP_RE__M);
9339                 WRB(dev_addr, IQM_CF_TAP_RE0__A, sizeof(dk_i_l_lp_taps_re),
9340                     ((u8 *) dk_i_l_lp_taps_re));
9341                 WRB(dev_addr, IQM_CF_TAP_IM0__A, sizeof(dk_i_l_lp_taps_im),
9342                     ((u8 *) dk_i_l_lp_taps_im));
9343                 WR16(dev_addr, ATV_TOP_CR_AMP_TH__A, 0x2);      /* TODO check with IS */
9344                 WR16(dev_addr, ATV_TOP_CR_CONT__A,
9345                      (ATV_TOP_CR_CONT_CR_P_LP |
9346                       ATV_TOP_CR_CONT_CR_D_LP | ATV_TOP_CR_CONT_CR_I_LP));
9347                 WR16(dev_addr, ATV_TOP_CR_OVM_TH__A, ATV_TOP_CR_OVM_TH_LP);
9348                 WR16(dev_addr, ATV_TOP_STD__A, (ATV_TOP_STD_MODE_LP |
9349                                                ATV_TOP_STD_VID_POL_LP));
9350                 WR16(dev_addr, SCU_RAM_ATV_AGC_MODE__A,
9351                      (SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_AM |
9352                       SCU_RAM_ATV_AGC_MODE_BP_EN_BPC_ENABLE |
9353                       SCU_RAM_ATV_AGC_MODE_VAGC_VEL_AGC_SLOW));
9354                 WR16(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000);
9355                 WR16(dev_addr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000);
9356                 WR16(dev_addr, SCU_RAM_ATV_AMS_MAX_REF__A,
9357                      SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_LLP);
9358                 ext_attr->phase_correction_bypass = false;
9359                 ext_attr->atv_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_USER;
9360                 ext_attr->atv_if_agc_cfg.output_level = ext_attr->atv_rf_agc_cfg.top;
9361                 ext_attr->enable_cvbs_output = true;
9362                 break;
9363         default:
9364                 return (DRX_STS_ERROR);
9365         }
9366
9367         /* Common initializations FM & NTSC & B/G & D/K & I & L & LP */
9368         if (ext_attr->has_lna == false) {
9369                 WR16(dev_addr, IQM_AF_AMUX__A, 0x01);
9370         }
9371
9372         WR16(dev_addr, SCU_RAM_ATV_STANDARD__A, 0x002);
9373         WR16(dev_addr, IQM_AF_CLP_LEN__A, IQM_AF_CLP_LEN_ATV);
9374         WR16(dev_addr, IQM_AF_CLP_TH__A, IQM_AF_CLP_TH_ATV);
9375         WR16(dev_addr, IQM_AF_SNS_LEN__A, IQM_AF_SNS_LEN_ATV);
9376         CHK_ERROR(ctrl_set_cfg_pre_saw(demod, &(ext_attr->atv_pre_saw_cfg)));
9377         WR16(dev_addr, IQM_AF_AGC_IF__A, 10248);
9378
9379         ext_attr->iqm_rc_rate_ofs = 0x00200000L;
9380         WR32(dev_addr, IQM_RC_RATE_OFS_LO__A, ext_attr->iqm_rc_rate_ofs);
9381         WR16(dev_addr, IQM_RC_ADJ_SEL__A, IQM_RC_ADJ_SEL_B_OFF);
9382         WR16(dev_addr, IQM_RC_STRETCH__A, IQM_RC_STRETCH_ATV);
9383
9384         WR16(dev_addr, IQM_RT_ACTIVE__A, IQM_RT_ACTIVE_ACTIVE_RT_ATV_FCR_ON |
9385              IQM_RT_ACTIVE_ACTIVE_CR_ATV_CR_ON);
9386
9387         WR16(dev_addr, IQM_CF_OUT_ENA__A, IQM_CF_OUT_ENA_ATV__M);
9388         WR16(dev_addr, IQM_CF_SYMMETRIC__A, IQM_CF_SYMMETRIC_IM__M);
9389         /* default: SIF in standby */
9390         WR16(dev_addr, ATV_TOP_SYNC_SLICE__A, ATV_TOP_SYNC_SLICE_MN);
9391         WR16(dev_addr, ATV_TOP_MOD_ACCU__A, ATV_TOP_MOD_ACCU__PRE);
9392
9393         WR16(dev_addr, SCU_RAM_ATV_SIF_GAIN__A, 0x080);
9394         WR16(dev_addr, SCU_RAM_ATV_FAGC_TH_RED__A, 10);
9395         WR16(dev_addr, SCU_RAM_ATV_AAGC_CNT__A, 7);
9396         WR16(dev_addr, SCU_RAM_ATV_NAGC_KI_MIN__A, 0x0225);
9397         WR16(dev_addr, SCU_RAM_ATV_NAGC_KI_MAX__A, 0x0547);
9398         WR16(dev_addr, SCU_RAM_ATV_KI_CHANGE_TH__A, 20);
9399         WR16(dev_addr, SCU_RAM_ATV_LOCK__A, 0);
9400
9401         WR16(dev_addr, IQM_RT_DELAY__A, IQM_RT_DELAY__PRE);
9402         WR16(dev_addr, SCU_RAM_ATV_BPC_KI_MIN__A, 531);
9403         WR16(dev_addr, SCU_RAM_ATV_PAGC_KI_MIN__A, 1061);
9404         WR16(dev_addr, SCU_RAM_ATV_BP_REF_MIN__A, 100);
9405         WR16(dev_addr, SCU_RAM_ATV_BP_REF_MAX__A, 260);
9406         WR16(dev_addr, SCU_RAM_ATV_BP_LVL__A, 0);
9407         WR16(dev_addr, SCU_RAM_ATV_AMS_MAX__A, 0);
9408         WR16(dev_addr, SCU_RAM_ATV_AMS_MIN__A, 2047);
9409         WR16(dev_addr, SCU_RAM_GPIO__A, 0);
9410
9411         /* Override reset values with current shadow settings */
9412         CHK_ERROR(atv_update_config(demod, true));
9413
9414         /* Configure/restore AGC settings */
9415         CHK_ERROR(init_agc(demod));
9416         CHK_ERROR(set_agc_if(demod, &(ext_attr->atv_if_agc_cfg), false));
9417         CHK_ERROR(set_agc_rf(demod, &(ext_attr->atv_rf_agc_cfg), false));
9418         CHK_ERROR(ctrl_set_cfg_pre_saw(demod, &(ext_attr->atv_pre_saw_cfg)));
9419
9420         /* Set SCU ATV substandard,assuming this doesn't require running ATV block */
9421         cmd_scu.command = SCU_RAM_COMMAND_STANDARD_ATV |
9422             SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV;
9423         cmd_scu.parameter_len = 1;
9424         cmd_scu.result_len = 1;
9425         cmd_scu.parameter = &cmd_param;
9426         cmd_scu.result = &cmd_result;
9427         CHK_ERROR(scu_command(dev_addr, &cmd_scu));
9428
9429         /* turn the analog work around on/off (must after set_env b/c it is set in mc) */
9430         if (ext_attr->mfx == 0x03) {
9431                 WR16(dev_addr, SCU_RAM_ATV_ENABLE_IIR_WA__A, 0);
9432         } else {
9433                 WR16(dev_addr, SCU_RAM_ATV_ENABLE_IIR_WA__A, 1);
9434                 WR16(dev_addr, SCU_RAM_ATV_IIR_CRIT__A, 225);
9435         }
9436
9437         return (DRX_STS_OK);
9438 rw_error:
9439         return (DRX_STS_ERROR);
9440 }
9441 #endif
9442
9443 /* -------------------------------------------------------------------------- */
9444
9445 #ifndef DRXJ_DIGITAL_ONLY
9446 /**
9447 * \fn int set_atv_channel ()
9448 * \brief Set ATV channel.
9449 * \param demod:   instance of demod.
9450 * \return int.
9451 *
9452 * Not much needs to be done here, only start the SCU for NTSC/FM.
9453 * Mirrored channels are not expected in the RF domain, so IQM FS setting
9454 * doesn't need to be remembered.
9455 * The channel->mirror parameter is therefor ignored.
9456 *
9457 */
9458 static int
9459 set_atv_channel(pdrx_demod_instance_t demod,
9460               s32 tuner_freq_offset,
9461               pdrx_channel_t channel, enum drx_standard standard)
9462 {
9463         drxjscu_cmd_t cmd_scu = { /* command      */ 0,
9464                 /* parameter_len */ 0,
9465                 /* result_len    */ 0,
9466                 /* parameter    */ NULL,
9467                 /* result       */ NULL
9468         };
9469         u16 cmd_result = 0;
9470         pdrxj_data_t ext_attr = NULL;
9471         struct i2c_device_addr *dev_addr = NULL;
9472
9473         dev_addr = demod->my_i2c_dev_addr;
9474         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
9475
9476         /*
9477            Program frequency shifter
9478            No need to account for mirroring on RF
9479          */
9480         if (channel->mirror == DRX_MIRROR_AUTO) {
9481                 ext_attr->mirror = DRX_MIRROR_NO;
9482         } else {
9483                 ext_attr->mirror = channel->mirror;
9484         }
9485
9486         CHK_ERROR(set_frequency(demod, channel, tuner_freq_offset));
9487         WR16(dev_addr, ATV_TOP_CR_FREQ__A, ATV_TOP_CR_FREQ__PRE);
9488
9489         /* Start ATV SCU */
9490         cmd_scu.command = SCU_RAM_COMMAND_STANDARD_ATV |
9491             SCU_RAM_COMMAND_CMD_DEMOD_START;
9492         cmd_scu.parameter_len = 0;
9493         cmd_scu.result_len = 1;
9494         cmd_scu.parameter = NULL;
9495         cmd_scu.result = &cmd_result;
9496         CHK_ERROR(scu_command(dev_addr, &cmd_scu));
9497
9498 /*   if ( (ext_attr->standard == DRX_STANDARD_FM) && (ext_attr->flagSetAUDdone == true) )
9499    {
9500       ext_attr->detectedRDS = (bool)false;
9501    }*/
9502
9503         return (DRX_STS_OK);
9504 rw_error:
9505         return (DRX_STS_ERROR);
9506 }
9507 #endif
9508
9509 /* -------------------------------------------------------------------------- */
9510
9511 /**
9512 * \fn int get_atv_channel ()
9513 * \brief Set ATV channel.
9514 * \param demod:   instance of demod.
9515 * \param channel: pointer to channel data.
9516 * \param standard: NTSC or FM.
9517 * \return int.
9518 *
9519 * Covers NTSC, PAL/SECAM - B/G, D/K, I, L, LP and FM.
9520 * Computes the frequency offset in te RF domain and adds it to
9521 * channel->frequency. Determines the value for channel->bandwidth.
9522 *
9523 */
9524 #ifndef DRXJ_DIGITAL_ONLY
9525 static int
9526 get_atv_channel(pdrx_demod_instance_t demod,
9527               pdrx_channel_t channel, enum drx_standard standard)
9528 {
9529         s32 offset = 0;
9530         struct i2c_device_addr *dev_addr = NULL;
9531         pdrxj_data_t ext_attr = NULL;
9532
9533         dev_addr = demod->my_i2c_dev_addr;
9534         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
9535
9536         /* Bandwidth */
9537         channel->bandwidth = ((pdrxj_data_t) demod->my_ext_attr)->curr_bandwidth;
9538
9539         switch (standard) {
9540         case DRX_STANDARD_NTSC:
9541         case DRX_STANDARD_PAL_SECAM_BG:
9542         case DRX_STANDARD_PAL_SECAM_DK:
9543         case DRX_STANDARD_PAL_SECAM_I:
9544         case DRX_STANDARD_PAL_SECAM_L:
9545                 {
9546                         u16 measured_offset = 0;
9547
9548                         /* get measured frequency offset */
9549                         RR16(dev_addr, ATV_TOP_CR_FREQ__A, &measured_offset);
9550                         /* Signed 8 bit register => sign extension needed */
9551                         if ((measured_offset & 0x0080) != 0) {
9552                                 /* sign extension */
9553                                 measured_offset |= 0xFF80;
9554                         }
9555                         offset +=
9556                             (s32) (((s16) measured_offset) * 10);
9557                         break;
9558                 }
9559         case DRX_STANDARD_PAL_SECAM_LP:
9560                 {
9561                         u16 measured_offset = 0;
9562
9563                         /* get measured frequency offset */
9564                         RR16(dev_addr, ATV_TOP_CR_FREQ__A, &measured_offset);
9565                         /* Signed 8 bit register => sign extension needed */
9566                         if ((measured_offset & 0x0080) != 0) {
9567                                 /* sign extension */
9568                                 measured_offset |= 0xFF80;
9569                         }
9570                         offset -=
9571                             (s32) (((s16) measured_offset) * 10);
9572                 }
9573                 break;
9574         case DRX_STANDARD_FM:
9575                 /* TODO: compute offset using AUD_DSP_RD_FM_DC_LEVEL_A__A and
9576                    AUD_DSP_RD_FM_DC_LEVEL_B__A. For now leave frequency as is.
9577                  */
9578                 /* No bandwidth know for FM */
9579                 channel->bandwidth = DRX_BANDWIDTH_UNKNOWN;
9580                 break;
9581         default:
9582                 return (DRX_STS_ERROR);
9583         }
9584
9585         channel->frequency -= offset;
9586
9587         return (DRX_STS_OK);
9588 rw_error:
9589         return (DRX_STS_ERROR);
9590 }
9591
9592 /* -------------------------------------------------------------------------- */
9593 /**
9594 * \fn int get_atv_sig_strength()
9595 * \brief Retrieve signal strength for ATV & FM.
9596 * \param devmod Pointer to demodulator instance.
9597 * \param sig_quality Pointer to signal strength data; range 0, .. , 100.
9598 * \return int.
9599 * \retval DRX_STS_OK sig_strength contains valid data.
9600 * \retval DRX_STS_ERROR Erroneous data, sig_strength equals 0.
9601 *
9602 * Taking into account:
9603 *  * digital gain
9604 *  * IF gain      (not implemented yet, waiting for IF gain control by ucode)
9605 *  * RF gain
9606 *
9607 * All weights (digital, if, rf) must add up to 100.
9608 *
9609 * TODO: ? dynamically adapt weights in case RF and/or IF agc of drxj
9610 *         is not used ?
9611 */
9612 static int
9613 get_atv_sig_strength(pdrx_demod_instance_t demod, u16 *sig_strength)
9614 {
9615         struct i2c_device_addr *dev_addr = NULL;
9616         pdrxj_data_t ext_attr = NULL;
9617
9618         /* All weights must add up to 100 (%)
9619            TODO: change weights when IF ctrl is available */
9620         u32 digital_weight = 50;        /* 0 .. 100 */
9621         u32 rf_weight = 50;     /* 0 .. 100 */
9622         u32 if_weight = 0;      /* 0 .. 100 */
9623
9624         u16 digital_curr_gain = 0;
9625         u32 digital_max_gain = 0;
9626         u32 digital_min_gain = 0;
9627         u16 rf_curr_gain = 0;
9628         u32 rf_max_gain = 0x800;        /* taken from ucode */
9629         u32 rf_min_gain = 0x7fff;
9630         u16 if_curr_gain = 0;
9631         u32 if_max_gain = 0x800;        /* taken from ucode */
9632         u32 if_min_gain = 0x7fff;
9633
9634         u32 digital_strength = 0;       /* 0.. 100 */
9635         u32 rf_strength = 0;    /* 0.. 100 */
9636         u32 if_strength = 0;    /* 0.. 100 */
9637
9638         dev_addr = demod->my_i2c_dev_addr;
9639         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
9640
9641         *sig_strength = 0;
9642
9643         switch (ext_attr->standard) {
9644         case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
9645         case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
9646         case DRX_STANDARD_PAL_SECAM_I:  /* fallthrough */
9647         case DRX_STANDARD_PAL_SECAM_L:  /* fallthrough */
9648         case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
9649         case DRX_STANDARD_NTSC:
9650                 SARR16(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, &digital_curr_gain);
9651                 digital_max_gain = 22512;       /* taken from ucode */
9652                 digital_min_gain = 2400;        /* taken from ucode */
9653                 break;
9654         case DRX_STANDARD_FM:
9655                 SARR16(dev_addr, SCU_RAM_ATV_SIF_GAIN__A, &digital_curr_gain);
9656                 digital_max_gain = 0x4ff;       /* taken from ucode */
9657                 digital_min_gain = 0;   /* taken from ucode */
9658                 break;
9659         default:
9660                 return (DRX_STS_ERROR);
9661                 break;
9662         }
9663         RR16(dev_addr, IQM_AF_AGC_RF__A, &rf_curr_gain);
9664         RR16(dev_addr, IQM_AF_AGC_IF__A, &if_curr_gain);
9665
9666         /* clipping */
9667         if (digital_curr_gain >= digital_max_gain)
9668                 digital_curr_gain = (u16) digital_max_gain;
9669         if (digital_curr_gain <= digital_min_gain)
9670                 digital_curr_gain = (u16) digital_min_gain;
9671         if (if_curr_gain <= if_max_gain)
9672                 if_curr_gain = (u16) if_max_gain;
9673         if (if_curr_gain >= if_min_gain)
9674                 if_curr_gain = (u16) if_min_gain;
9675         if (rf_curr_gain <= rf_max_gain)
9676                 rf_curr_gain = (u16) rf_max_gain;
9677         if (rf_curr_gain >= rf_min_gain)
9678                 rf_curr_gain = (u16) rf_min_gain;
9679
9680         /* TODO: use SCU_RAM_ATV_RAGC_HR__A to shift max and min in case
9681            of clipping at ADC */
9682
9683         /* Compute signal strength (in %) per "gain domain" */
9684
9685         /* Digital gain  */
9686         /* TODO: ADC clipping not handled */
9687         digital_strength = (100 * (digital_max_gain - (u32) digital_curr_gain)) /
9688             (digital_max_gain - digital_min_gain);
9689
9690         /* TODO: IF gain not implemented yet in microcode, check after impl. */
9691         if_strength = (100 * ((u32) if_curr_gain - if_max_gain)) /
9692             (if_min_gain - if_max_gain);
9693
9694         /* Rf gain */
9695         /* TODO: ADC clipping not handled */
9696         rf_strength = (100 * ((u32) rf_curr_gain - rf_max_gain)) /
9697             (rf_min_gain - rf_max_gain);
9698
9699         /* Compute a weighted signal strength (in %) */
9700         *sig_strength = (u16) (digital_weight * digital_strength +
9701                                 rf_weight * rf_strength + if_weight * if_strength);
9702         *sig_strength /= 100;
9703
9704         return (DRX_STS_OK);
9705 rw_error:
9706         return (DRX_STS_ERROR);
9707 }
9708
9709 /* -------------------------------------------------------------------------- */
9710 /**
9711 * \fn int atv_sig_quality()
9712 * \brief Retrieve signal quality indication for ATV.
9713 * \param devmod Pointer to demodulator instance.
9714 * \param sig_quality Pointer to signal quality structure.
9715 * \return int.
9716 * \retval DRX_STS_OK sig_quality contains valid data.
9717 * \retval DRX_STS_ERROR Erroneous data, sig_quality indicator equals 0.
9718 *
9719 *
9720 */
9721 static int
9722 atv_sig_quality(pdrx_demod_instance_t demod, pdrx_sig_quality_t sig_quality)
9723 {
9724         struct i2c_device_addr *dev_addr = NULL;
9725         u16 quality_indicator = 0;
9726
9727         dev_addr = demod->my_i2c_dev_addr;
9728
9729         /* defined values for fields not used */
9730         sig_quality->MER = 0;
9731         sig_quality->pre_viterbi_ber = 0;
9732         sig_quality->post_viterbi_ber = 0;
9733         sig_quality->scale_factor_ber = 1;
9734         sig_quality->packet_error = 0;
9735         sig_quality->post_reed_solomon_ber = 0;
9736
9737         /*
9738            Mapping:
9739            0x000..0x080: strong signal  => 80% .. 100%
9740            0x080..0x700: weak signal    => 30% .. 80%
9741            0x700..0x7ff: no signal      => 0%  .. 30%
9742          */
9743
9744         SARR16(dev_addr, SCU_RAM_ATV_CR_LOCK__A, &quality_indicator);
9745         quality_indicator &= SCU_RAM_ATV_CR_LOCK_CR_LOCK__M;
9746         if (quality_indicator <= 0x80) {
9747                 sig_quality->indicator =
9748                     80 + ((20 * (0x80 - quality_indicator)) / 0x80);
9749         } else if (quality_indicator <= 0x700) {
9750                 sig_quality->indicator = 30 +
9751                     ((50 * (0x700 - quality_indicator)) / (0x700 - 0x81));
9752         } else {
9753                 sig_quality->indicator =
9754                     (30 * (0x7FF - quality_indicator)) / (0x7FF - 0x701);
9755         }
9756
9757         return (DRX_STS_OK);
9758 rw_error:
9759         return (DRX_STS_ERROR);
9760 }
9761 #endif /* DRXJ_DIGITAL_ONLY */
9762
9763 /*============================================================================*/
9764 /*==                     END ATV DATAPATH FUNCTIONS                         ==*/
9765 /*============================================================================*/
9766
9767 #ifndef DRXJ_EXCLUDE_AUDIO
9768 /*===========================================================================*/
9769 /*===========================================================================*/
9770 /*==                      AUDIO DATAPATH FUNCTIONS                         ==*/
9771 /*===========================================================================*/
9772 /*===========================================================================*/
9773
9774 /*
9775 * \brief Power up AUD.
9776 * \param demod instance of demodulator
9777 * \return int.
9778 *
9779 */
9780 static int power_up_aud(pdrx_demod_instance_t demod, bool set_standard)
9781 {
9782         drx_aud_standard_t aud_standard = DRX_AUD_STANDARD_AUTO;
9783         struct i2c_device_addr *dev_addr = NULL;
9784
9785         dev_addr = demod->my_i2c_dev_addr;
9786
9787         WR16(dev_addr, AUD_TOP_COMM_EXEC__A, AUD_TOP_COMM_EXEC_ACTIVE);
9788         /* setup TR interface: R/W mode, fifosize=8 */
9789         WR16(dev_addr, AUD_TOP_TR_MDE__A, 8);
9790         WR16(dev_addr, AUD_COMM_EXEC__A, AUD_COMM_EXEC_ACTIVE);
9791
9792         if (set_standard == true) {
9793                 CHK_ERROR(aud_ctrl_set_standard(demod, &aud_standard));
9794         }
9795
9796         return DRX_STS_OK;
9797 rw_error:
9798         return DRX_STS_ERROR;
9799 }
9800
9801 /*============================================================================*/
9802
9803 /**
9804 * \brief Power up AUD.
9805 * \param demod instance of demodulator
9806 * \return int.
9807 *
9808 */
9809 static int power_down_aud(pdrx_demod_instance_t demod)
9810 {
9811         struct i2c_device_addr *dev_addr = NULL;
9812         pdrxj_data_t ext_attr = NULL;
9813
9814         dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
9815         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
9816
9817         WR16(dev_addr, AUD_COMM_EXEC__A, AUD_COMM_EXEC_STOP);
9818
9819         ext_attr->aud_data.audio_is_active = false;
9820
9821         return DRX_STS_OK;
9822 rw_error:
9823         return DRX_STS_ERROR;
9824 }
9825
9826 /*============================================================================*/
9827 /**
9828 * \brief Get Modus data from audio RAM
9829 * \param demod instance of demodulator
9830 * \param pointer to modus
9831 * \return int.
9832 *
9833 */
9834 static int aud_get_modus(pdrx_demod_instance_t demod, u16 *modus)
9835 {
9836         struct i2c_device_addr *dev_addr = NULL;
9837         pdrxj_data_t ext_attr = NULL;
9838
9839         u16 r_modus = 0;
9840         u16 r_modusHi = 0;
9841         u16 r_modusLo = 0;
9842
9843         if (modus == NULL) {
9844                 return DRX_STS_INVALID_ARG;
9845         }
9846
9847         dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
9848         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
9849
9850         /* power up */
9851         if (ext_attr->aud_data.audio_is_active == false) {
9852                 CHK_ERROR(power_up_aud(demod, true));
9853                 ext_attr->aud_data.audio_is_active = true;
9854         }
9855
9856         /* Modus register is combined in to RAM location */
9857         RR16(dev_addr, AUD_DEM_RAM_MODUS_HI__A, &r_modusHi);
9858         RR16(dev_addr, AUD_DEM_RAM_MODUS_LO__A, &r_modusLo);
9859
9860         r_modus = ((r_modusHi << 12) & AUD_DEM_RAM_MODUS_HI__M)
9861             | (((r_modusLo & AUD_DEM_RAM_MODUS_LO__M)));
9862
9863         *modus = r_modus;
9864
9865         return DRX_STS_OK;
9866 rw_error:
9867         return DRX_STS_ERROR;
9868
9869 }
9870
9871 /*============================================================================*/
9872 /**
9873 * \brief Get audio RDS dat
9874 * \param demod instance of demodulator
9875 * \param pointer to drx_cfg_aud_rds_t
9876 * \return int.
9877 *
9878 */
9879 static int
9880 aud_ctrl_get_cfg_rds(pdrx_demod_instance_t demod, pdrx_cfg_aud_rds_t status)
9881 {
9882         struct i2c_device_addr *addr = NULL;
9883         pdrxj_data_t ext_attr = NULL;
9884
9885         u16 r_rds_array_cnt_init = 0;
9886         u16 r_rds_array_cnt_check = 0;
9887         u16 r_rds_data = 0;
9888         u16 rds_data_cnt = 0;
9889
9890         addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
9891         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
9892
9893         if (status == NULL) {
9894                 return DRX_STS_INVALID_ARG;
9895         }
9896
9897         /* power up */
9898         if (ext_attr->aud_data.audio_is_active == false) {
9899                 CHK_ERROR(power_up_aud(demod, true));
9900                 ext_attr->aud_data.audio_is_active = true;
9901         }
9902
9903         status->valid = false;
9904
9905         RR16(addr, AUD_DEM_RD_RDS_ARRAY_CNT__A, &r_rds_array_cnt_init);
9906
9907         if (r_rds_array_cnt_init ==
9908             AUD_DEM_RD_RDS_ARRAY_CNT_RDS_ARRAY_CT_RDS_DATA_NOT_VALID) {
9909                 /* invalid data */
9910                 return DRX_STS_OK;
9911         }
9912
9913         if (ext_attr->aud_data.rds_data_counter == r_rds_array_cnt_init) {
9914                 /* no new data */
9915                 return DRX_STS_OK;
9916         }
9917
9918         /* RDS is detected, as long as FM radio is selected assume
9919            RDS will be available                                    */
9920         ext_attr->aud_data.rds_data_present = true;
9921
9922         /* new data */
9923         /* read the data */
9924         for (rds_data_cnt = 0; rds_data_cnt < AUD_RDS_ARRAY_SIZE; rds_data_cnt++) {
9925                 RR16(addr, AUD_DEM_RD_RDS_DATA__A, &r_rds_data);
9926                 status->data[rds_data_cnt] = r_rds_data;
9927         }
9928
9929         RR16(addr, AUD_DEM_RD_RDS_ARRAY_CNT__A, &r_rds_array_cnt_check);
9930
9931         if (r_rds_array_cnt_check == r_rds_array_cnt_init) {
9932                 status->valid = true;
9933                 ext_attr->aud_data.rds_data_counter = r_rds_array_cnt_check;
9934         }
9935
9936         return DRX_STS_OK;
9937 rw_error:
9938         return DRX_STS_ERROR;
9939 }
9940
9941 /*============================================================================*/
9942 /**
9943 * \brief Get the current audio carrier detection status
9944 * \param demod instance of demodulator
9945 * \param pointer to aud_ctrl_get_status
9946 * \return int.
9947 *
9948 */
9949 static int
9950 aud_ctrl_get_carrier_detect_status(pdrx_demod_instance_t demod, pdrx_aud_status_t status)
9951 {
9952         pdrxj_data_t ext_attr = NULL;
9953         struct i2c_device_addr *dev_addr = NULL;
9954
9955         u16 r_data = 0;
9956
9957         if (status == NULL) {
9958                 return DRX_STS_INVALID_ARG;
9959         }
9960
9961         dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
9962         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
9963
9964         /* power up */
9965         if (ext_attr->aud_data.audio_is_active == false) {
9966                 CHK_ERROR(power_up_aud(demod, true));
9967                 ext_attr->aud_data.audio_is_active = true;
9968         }
9969
9970         /* initialize the variables */
9971         status->carrier_a = false;
9972         status->carrier_b = false;
9973         status->nicam_status = DRX_AUD_NICAM_NOT_DETECTED;
9974         status->sap = false;
9975         status->stereo = false;
9976
9977         /* read stereo sound mode indication */
9978         RR16(dev_addr, AUD_DEM_RD_STATUS__A, &r_data);
9979
9980         /* carrier a detected */
9981         if ((r_data & AUD_DEM_RD_STATUS_STAT_CARR_A__M) ==
9982             AUD_DEM_RD_STATUS_STAT_CARR_A_DETECTED) {
9983                 status->carrier_a = true;
9984         }
9985
9986         /* carrier b detected */
9987         if ((r_data & AUD_DEM_RD_STATUS_STAT_CARR_B__M) ==
9988             AUD_DEM_RD_STATUS_STAT_CARR_B_DETECTED) {
9989                 status->carrier_b = true;
9990         }
9991         /* nicam detected */
9992         if ((r_data & AUD_DEM_RD_STATUS_STAT_NICAM__M) ==
9993             AUD_DEM_RD_STATUS_STAT_NICAM_NICAM_DETECTED) {
9994                 if ((r_data & AUD_DEM_RD_STATUS_BAD_NICAM__M) ==
9995                     AUD_DEM_RD_STATUS_BAD_NICAM_OK) {
9996                         status->nicam_status = DRX_AUD_NICAM_DETECTED;
9997                 } else {
9998                         status->nicam_status = DRX_AUD_NICAM_BAD;
9999                 }
10000         }
10001
10002         /* audio mode bilingual or SAP detected */
10003         if ((r_data & AUD_DEM_RD_STATUS_STAT_BIL_OR_SAP__M) ==
10004             AUD_DEM_RD_STATUS_STAT_BIL_OR_SAP_SAP) {
10005                 status->sap = true;
10006         }
10007
10008         /* stereo detected */
10009         if ((r_data & AUD_DEM_RD_STATUS_STAT_STEREO__M) ==
10010             AUD_DEM_RD_STATUS_STAT_STEREO_STEREO) {
10011                 status->stereo = true;
10012         }
10013
10014         return DRX_STS_OK;
10015 rw_error:
10016         return DRX_STS_ERROR;
10017 }
10018
10019 /*============================================================================*/
10020 /**
10021 * \brief Get the current audio status parameters
10022 * \param demod instance of demodulator
10023 * \param pointer to aud_ctrl_get_status
10024 * \return int.
10025 *
10026 */
10027 static int
10028 aud_ctrl_get_status(pdrx_demod_instance_t demod, pdrx_aud_status_t status)
10029 {
10030         pdrxj_data_t ext_attr = NULL;
10031         struct i2c_device_addr *dev_addr = NULL;
10032         drx_cfg_aud_rds_t rds = { false, {0} };
10033         u16 r_data = 0;
10034
10035         if (status == NULL) {
10036                 return DRX_STS_INVALID_ARG;
10037         }
10038
10039         dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
10040         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
10041
10042         /* carrier detection */
10043         CHK_ERROR(aud_ctrl_get_carrier_detect_status(demod, status));
10044
10045         /* rds data */
10046         status->rds = false;
10047         CHK_ERROR(aud_ctrl_get_cfg_rds(demod, &rds));
10048         status->rds = ext_attr->aud_data.rds_data_present;
10049
10050         /* fm_ident */
10051         RR16(dev_addr, AUD_DSP_RD_FM_IDENT_VALUE__A, &r_data);
10052         r_data >>= AUD_DSP_RD_FM_IDENT_VALUE_FM_IDENT__B;
10053         status->fm_ident = (s8) r_data;
10054
10055         return DRX_STS_OK;
10056 rw_error:
10057         return DRX_STS_ERROR;
10058 }
10059
10060 /*============================================================================*/
10061 /**
10062 * \brief Get the current volume settings
10063 * \param demod instance of demodulator
10064 * \param pointer to drx_cfg_aud_volume_t
10065 * \return int.
10066 *
10067 */
10068 static int
10069 aud_ctrl_get_cfg_volume(pdrx_demod_instance_t demod, pdrx_cfg_aud_volume_t volume)
10070 {
10071         struct i2c_device_addr *dev_addr = NULL;
10072         pdrxj_data_t ext_attr = NULL;
10073
10074         u16 r_volume = 0;
10075         u16 r_avc = 0;
10076         u16 r_strength_left = 0;
10077         u16 r_strength_right = 0;
10078
10079         if (volume == NULL) {
10080                 return DRX_STS_INVALID_ARG;
10081         }
10082
10083         dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
10084         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
10085
10086         /* power up */
10087         if (ext_attr->aud_data.audio_is_active == false) {
10088                 CHK_ERROR(power_up_aud(demod, true));
10089                 ext_attr->aud_data.audio_is_active = true;
10090         }
10091
10092         /* volume */
10093         volume->mute = ext_attr->aud_data.volume.mute;
10094         RR16(dev_addr, AUD_DSP_WR_VOLUME__A, &r_volume);
10095         if (r_volume == 0) {
10096                 volume->mute = true;
10097                 volume->volume = ext_attr->aud_data.volume.volume;
10098         } else {
10099                 volume->mute = false;
10100                 volume->volume = ((r_volume & AUD_DSP_WR_VOLUME_VOL_MAIN__M) >>
10101                                   AUD_DSP_WR_VOLUME_VOL_MAIN__B) -
10102                     AUD_VOLUME_ZERO_DB;
10103                 if (volume->volume < AUD_VOLUME_DB_MIN) {
10104                         volume->volume = AUD_VOLUME_DB_MIN;
10105                 }
10106                 if (volume->volume > AUD_VOLUME_DB_MAX) {
10107                         volume->volume = AUD_VOLUME_DB_MAX;
10108                 }
10109         }
10110
10111         /* automatic volume control */
10112         RR16(dev_addr, AUD_DSP_WR_AVC__A, &r_avc);
10113
10114         if ((r_avc & AUD_DSP_WR_AVC_AVC_ON__M) == AUD_DSP_WR_AVC_AVC_ON_OFF)
10115         {
10116                 volume->avc_mode = DRX_AUD_AVC_OFF;
10117         } else {
10118                 switch (r_avc & AUD_DSP_WR_AVC_AVC_DECAY__M) {
10119                 case AUD_DSP_WR_AVC_AVC_DECAY_20_MSEC:
10120                         volume->avc_mode = DRX_AUD_AVC_DECAYTIME_20MS;
10121                         break;
10122                 case AUD_DSP_WR_AVC_AVC_DECAY_8_SEC:
10123                         volume->avc_mode = DRX_AUD_AVC_DECAYTIME_8S;
10124                         break;
10125                 case AUD_DSP_WR_AVC_AVC_DECAY_4_SEC:
10126                         volume->avc_mode = DRX_AUD_AVC_DECAYTIME_4S;
10127                         break;
10128                 case AUD_DSP_WR_AVC_AVC_DECAY_2_SEC:
10129                         volume->avc_mode = DRX_AUD_AVC_DECAYTIME_2S;
10130                         break;
10131                 default:
10132                         return DRX_STS_ERROR;
10133                         break;
10134                 }
10135         }
10136
10137         /* max attenuation */
10138         switch (r_avc & AUD_DSP_WR_AVC_AVC_MAX_ATT__M) {
10139         case AUD_DSP_WR_AVC_AVC_MAX_ATT_12DB:
10140                 volume->avc_max_atten = DRX_AUD_AVC_MAX_ATTEN_12DB;
10141                 break;
10142         case AUD_DSP_WR_AVC_AVC_MAX_ATT_18DB:
10143                 volume->avc_max_atten = DRX_AUD_AVC_MAX_ATTEN_18DB;
10144                 break;
10145         case AUD_DSP_WR_AVC_AVC_MAX_ATT_24DB:
10146                 volume->avc_max_atten = DRX_AUD_AVC_MAX_ATTEN_24DB;
10147                 break;
10148         default:
10149                 return DRX_STS_ERROR;
10150                 break;
10151         }
10152
10153         /* max gain */
10154         switch (r_avc & AUD_DSP_WR_AVC_AVC_MAX_GAIN__M) {
10155         case AUD_DSP_WR_AVC_AVC_MAX_GAIN_0DB:
10156                 volume->avc_max_gain = DRX_AUD_AVC_MAX_GAIN_0DB;
10157                 break;
10158         case AUD_DSP_WR_AVC_AVC_MAX_GAIN_6DB:
10159                 volume->avc_max_gain = DRX_AUD_AVC_MAX_GAIN_6DB;
10160                 break;
10161         case AUD_DSP_WR_AVC_AVC_MAX_GAIN_12DB:
10162                 volume->avc_max_gain = DRX_AUD_AVC_MAX_GAIN_12DB;
10163                 break;
10164         default:
10165                 return DRX_STS_ERROR;
10166                 break;
10167         }
10168
10169         /* reference level */
10170         volume->avc_ref_level = (u16) ((r_avc & AUD_DSP_WR_AVC_AVC_REF_LEV__M) >>
10171                                        AUD_DSP_WR_AVC_AVC_REF_LEV__B);
10172
10173         /* read qpeak registers and calculate strength of left and right carrier */
10174         /* quasi peaks formula: QP(dB) = 20 * log( AUD_DSP_RD_QPEAKx / Q(0dB) */
10175         /* Q(0dB) represents QP value of 0dB (hex value 0x4000) */
10176         /* left carrier */
10177
10178         /* QP vaues */
10179         /* left carrier */
10180         RR16(dev_addr, AUD_DSP_RD_QPEAK_L__A, &r_strength_left);
10181         volume->strength_left = (((s16) log1_times100(r_strength_left)) -
10182                                 AUD_CARRIER_STRENGTH_QP_0DB_LOG10T100) / 5;
10183
10184         /* right carrier */
10185         RR16(dev_addr, AUD_DSP_RD_QPEAK_R__A, &r_strength_right);
10186         volume->strength_right = (((s16) log1_times100(r_strength_right)) -
10187                                  AUD_CARRIER_STRENGTH_QP_0DB_LOG10T100) / 5;
10188
10189         return DRX_STS_OK;
10190 rw_error:
10191         return DRX_STS_ERROR;
10192 }
10193
10194 /*============================================================================*/
10195 /**
10196 * \brief Set the current volume settings
10197 * \param demod instance of demodulator
10198 * \param pointer to drx_cfg_aud_volume_t
10199 * \return int.
10200 *
10201 */
10202 static int
10203 aud_ctrl_set_cfg_volume(pdrx_demod_instance_t demod, pdrx_cfg_aud_volume_t volume)
10204 {
10205         struct i2c_device_addr *dev_addr = NULL;
10206         pdrxj_data_t ext_attr = NULL;
10207
10208         u16 w_volume = 0;
10209         u16 w_avc = 0;
10210
10211         if (volume == NULL) {
10212                 return DRX_STS_INVALID_ARG;
10213         }
10214
10215         dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
10216         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
10217
10218         /* power up */
10219         if (ext_attr->aud_data.audio_is_active == false) {
10220                 CHK_ERROR(power_up_aud(demod, true));
10221                 ext_attr->aud_data.audio_is_active = true;
10222         }
10223
10224         /* volume */
10225         /* volume range from -60 to 12 (expressed in dB) */
10226         if ((volume->volume < AUD_VOLUME_DB_MIN) ||
10227             (volume->volume > AUD_VOLUME_DB_MAX)) {
10228                 return DRX_STS_INVALID_ARG;
10229         }
10230
10231         RR16(dev_addr, AUD_DSP_WR_VOLUME__A, &w_volume);
10232
10233         /* clear the volume mask */
10234         w_volume &= (u16) ~AUD_DSP_WR_VOLUME_VOL_MAIN__M;
10235         if (volume->mute == true) {
10236                 /* mute */
10237                 /* mute overrules volume */
10238                 w_volume |= (u16) (0);
10239
10240         } else {
10241                 w_volume |= (u16) ((volume->volume + AUD_VOLUME_ZERO_DB) <<
10242                                     AUD_DSP_WR_VOLUME_VOL_MAIN__B);
10243         }
10244
10245         WR16(dev_addr, AUD_DSP_WR_VOLUME__A, w_volume);
10246
10247         /* automatic volume control */
10248         RR16(dev_addr, AUD_DSP_WR_AVC__A, &w_avc);
10249
10250         /* clear masks that require writing */
10251         w_avc &= (u16) ~AUD_DSP_WR_AVC_AVC_ON__M;
10252         w_avc &= (u16) ~AUD_DSP_WR_AVC_AVC_DECAY__M;
10253
10254         if (volume->avc_mode == DRX_AUD_AVC_OFF) {
10255                 w_avc |= (AUD_DSP_WR_AVC_AVC_ON_OFF);
10256         } else {
10257
10258                 w_avc |= (AUD_DSP_WR_AVC_AVC_ON_ON);
10259
10260                 /* avc decay */
10261                 switch (volume->avc_mode) {
10262                 case DRX_AUD_AVC_DECAYTIME_20MS:
10263                         w_avc |= AUD_DSP_WR_AVC_AVC_DECAY_20_MSEC;
10264                         break;
10265                 case DRX_AUD_AVC_DECAYTIME_8S:
10266                         w_avc |= AUD_DSP_WR_AVC_AVC_DECAY_8_SEC;
10267                         break;
10268                 case DRX_AUD_AVC_DECAYTIME_4S:
10269                         w_avc |= AUD_DSP_WR_AVC_AVC_DECAY_4_SEC;
10270                         break;
10271                 case DRX_AUD_AVC_DECAYTIME_2S:
10272                         w_avc |= AUD_DSP_WR_AVC_AVC_DECAY_2_SEC;
10273                         break;
10274                 default:
10275                         return DRX_STS_INVALID_ARG;
10276                 }
10277         }
10278
10279         /* max attenuation */
10280         w_avc &= (u16) ~AUD_DSP_WR_AVC_AVC_MAX_ATT__M;
10281         switch (volume->avc_max_atten) {
10282         case DRX_AUD_AVC_MAX_ATTEN_12DB:
10283                 w_avc |= AUD_DSP_WR_AVC_AVC_MAX_ATT_12DB;
10284                 break;
10285         case DRX_AUD_AVC_MAX_ATTEN_18DB:
10286                 w_avc |= AUD_DSP_WR_AVC_AVC_MAX_ATT_18DB;
10287                 break;
10288         case DRX_AUD_AVC_MAX_ATTEN_24DB:
10289                 w_avc |= AUD_DSP_WR_AVC_AVC_MAX_ATT_24DB;
10290                 break;
10291         default:
10292                 return DRX_STS_INVALID_ARG;
10293         }
10294
10295         /* max gain */
10296         w_avc &= (u16) ~AUD_DSP_WR_AVC_AVC_MAX_GAIN__M;
10297         switch (volume->avc_max_gain) {
10298         case DRX_AUD_AVC_MAX_GAIN_0DB:
10299                 w_avc |= AUD_DSP_WR_AVC_AVC_MAX_GAIN_0DB;
10300                 break;
10301         case DRX_AUD_AVC_MAX_GAIN_6DB:
10302                 w_avc |= AUD_DSP_WR_AVC_AVC_MAX_GAIN_6DB;
10303                 break;
10304         case DRX_AUD_AVC_MAX_GAIN_12DB:
10305                 w_avc |= AUD_DSP_WR_AVC_AVC_MAX_GAIN_12DB;
10306                 break;
10307         default:
10308                 return DRX_STS_INVALID_ARG;
10309         }
10310
10311         /* avc reference level */
10312         if (volume->avc_ref_level > AUD_MAX_AVC_REF_LEVEL) {
10313                 return DRX_STS_INVALID_ARG;
10314         }
10315
10316         w_avc &= (u16) ~AUD_DSP_WR_AVC_AVC_REF_LEV__M;
10317         w_avc |= (u16) (volume->avc_ref_level << AUD_DSP_WR_AVC_AVC_REF_LEV__B);
10318
10319         WR16(dev_addr, AUD_DSP_WR_AVC__A, w_avc);
10320
10321         /* all done, store config in data structure */
10322         ext_attr->aud_data.volume = *volume;
10323
10324         return DRX_STS_OK;
10325 rw_error:
10326         return DRX_STS_ERROR;
10327 }
10328
10329 /*============================================================================*/
10330 /**
10331 * \brief Get the I2S settings
10332 * \param demod instance of demodulator
10333 * \param pointer to drx_cfg_i2s_output_t
10334 * \return int.
10335 *
10336 */
10337 static int
10338 aud_ctrl_get_cfg_output_i2s(pdrx_demod_instance_t demod, pdrx_cfg_i2s_output_t output)
10339 {
10340         struct i2c_device_addr *dev_addr = NULL;
10341         pdrxj_data_t ext_attr = NULL;
10342
10343         u16 w_i2s_config = 0;
10344         u16 r_i2s_freq = 0;
10345
10346         if (output == NULL) {
10347                 return DRX_STS_INVALID_ARG;
10348         }
10349
10350         dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
10351         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
10352
10353         /* power up */
10354         if (ext_attr->aud_data.audio_is_active == false) {
10355                 CHK_ERROR(power_up_aud(demod, true));
10356                 ext_attr->aud_data.audio_is_active = true;
10357         }
10358
10359         RR16(dev_addr, AUD_DEM_RAM_I2S_CONFIG2__A, &w_i2s_config);
10360         RR16(dev_addr, AUD_DSP_WR_I2S_OUT_FS__A, &r_i2s_freq);
10361
10362         /* I2S mode */
10363         switch (w_i2s_config & AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST__M) {
10364         case AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST_MASTER:
10365                 output->mode = DRX_I2S_MODE_MASTER;
10366                 break;
10367         case AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST_SLAVE:
10368                 output->mode = DRX_I2S_MODE_SLAVE;
10369                 break;
10370         default:
10371                 return DRX_STS_ERROR;
10372         }
10373
10374         /* I2S format */
10375         switch (w_i2s_config & AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE__M) {
10376         case AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE_DELAY:
10377                 output->format = DRX_I2S_FORMAT_WS_ADVANCED;
10378                 break;
10379         case AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE_NO_DELAY:
10380                 output->format = DRX_I2S_FORMAT_WS_WITH_DATA;
10381                 break;
10382         default:
10383                 return DRX_STS_ERROR;
10384         }
10385
10386         /* I2S word length */
10387         switch (w_i2s_config & AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN__M) {
10388         case AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN_BIT_16:
10389                 output->word_length = DRX_I2S_WORDLENGTH_16;
10390                 break;
10391         case AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN_BIT_32:
10392                 output->word_length = DRX_I2S_WORDLENGTH_32;
10393                 break;
10394         default:
10395                 return DRX_STS_ERROR;
10396         }
10397
10398         /* I2S polarity */
10399         switch (w_i2s_config & AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL__M) {
10400         case AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL_LEFT_HIGH:
10401                 output->polarity = DRX_I2S_POLARITY_LEFT;
10402                 break;
10403         case AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL_LEFT_LOW:
10404                 output->polarity = DRX_I2S_POLARITY_RIGHT;
10405                 break;
10406         default:
10407                 return DRX_STS_ERROR;
10408         }
10409
10410         /* I2S output enabled */
10411         if ((w_i2s_config & AUD_DEM_WR_I2S_CONFIG2_I2S_ENABLE__M)
10412             == AUD_DEM_WR_I2S_CONFIG2_I2S_ENABLE_ENABLE) {
10413                 output->output_enable = true;
10414         } else {
10415                 output->output_enable = false;
10416         }
10417
10418         if (r_i2s_freq > 0) {
10419                 output->frequency = 6144UL * 48000 / r_i2s_freq;
10420                 if (output->word_length == DRX_I2S_WORDLENGTH_16) {
10421                         output->frequency *= 2;
10422                 }
10423         } else {
10424                 output->frequency = AUD_I2S_FREQUENCY_MAX;
10425         }
10426
10427         return DRX_STS_OK;
10428 rw_error:
10429         return DRX_STS_ERROR;
10430 }
10431
10432 /*============================================================================*/
10433 /**
10434 * \brief Set the I2S settings
10435 * \param demod instance of demodulator
10436 * \param pointer to drx_cfg_i2s_output_t
10437 * \return int.
10438 *
10439 */
10440 static int
10441 aud_ctrl_set_cfg_output_i2s(pdrx_demod_instance_t demod, pdrx_cfg_i2s_output_t output)
10442 {
10443         struct i2c_device_addr *dev_addr = NULL;
10444         pdrxj_data_t ext_attr = NULL;
10445
10446         u16 w_i2s_config = 0;
10447         u16 w_i2s_pads_data_da = 0;
10448         u16 w_i2s_pads_data_cl = 0;
10449         u16 w_i2s_pads_data_ws = 0;
10450         u32 w_i2s_freq = 0;
10451
10452         if (output == NULL) {
10453                 return DRX_STS_INVALID_ARG;
10454         }
10455
10456         dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
10457         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
10458
10459         /* power up */
10460         if (ext_attr->aud_data.audio_is_active == false) {
10461                 CHK_ERROR(power_up_aud(demod, true));
10462                 ext_attr->aud_data.audio_is_active = true;
10463         }
10464
10465         RR16(dev_addr, AUD_DEM_RAM_I2S_CONFIG2__A, &w_i2s_config);
10466
10467         /* I2S mode */
10468         w_i2s_config &= (u16) ~AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST__M;
10469
10470         switch (output->mode) {
10471         case DRX_I2S_MODE_MASTER:
10472                 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST_MASTER;
10473                 break;
10474         case DRX_I2S_MODE_SLAVE:
10475                 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST_SLAVE;
10476                 break;
10477         default:
10478                 return DRX_STS_INVALID_ARG;
10479         }
10480
10481         /* I2S format */
10482         w_i2s_config &= (u16) ~AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE__M;
10483
10484         switch (output->format) {
10485         case DRX_I2S_FORMAT_WS_ADVANCED:
10486                 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE_DELAY;
10487                 break;
10488         case DRX_I2S_FORMAT_WS_WITH_DATA:
10489                 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE_NO_DELAY;
10490                 break;
10491         default:
10492                 return DRX_STS_INVALID_ARG;
10493         }
10494
10495         /* I2S word length */
10496         w_i2s_config &= (u16) ~AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN__M;
10497
10498         switch (output->word_length) {
10499         case DRX_I2S_WORDLENGTH_16:
10500                 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN_BIT_16;
10501                 break;
10502         case DRX_I2S_WORDLENGTH_32:
10503                 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN_BIT_32;
10504                 break;
10505         default:
10506                 return DRX_STS_INVALID_ARG;
10507         }
10508
10509         /* I2S polarity */
10510         w_i2s_config &= (u16) ~AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL__M;
10511         switch (output->polarity) {
10512         case DRX_I2S_POLARITY_LEFT:
10513                 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL_LEFT_HIGH;
10514                 break;
10515         case DRX_I2S_POLARITY_RIGHT:
10516                 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL_LEFT_LOW;
10517                 break;
10518         default:
10519                 return DRX_STS_INVALID_ARG;
10520         }
10521
10522         /* I2S output enabled */
10523         w_i2s_config &= (u16) ~AUD_DEM_WR_I2S_CONFIG2_I2S_ENABLE__M;
10524         if (output->output_enable == true) {
10525                 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_ENABLE_ENABLE;
10526         } else {
10527                 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_ENABLE_DISABLE;
10528         }
10529
10530         /*
10531            I2S frequency
10532
10533            w_i2s_freq = 6144 * 48000 * nrbits / ( 32 * frequency )
10534
10535            16bit: 6144 * 48000 / ( 2 * freq ) = ( 6144 * 48000 / freq ) / 2
10536            32bit: 6144 * 48000 / freq         = ( 6144 * 48000 / freq )
10537          */
10538         if ((output->frequency > AUD_I2S_FREQUENCY_MAX) ||
10539             output->frequency < AUD_I2S_FREQUENCY_MIN) {
10540                 return DRX_STS_INVALID_ARG;
10541         }
10542
10543         w_i2s_freq = (6144UL * 48000UL) + (output->frequency >> 1);
10544         w_i2s_freq /= output->frequency;
10545
10546         if (output->word_length == DRX_I2S_WORDLENGTH_16) {
10547                 w_i2s_freq *= 2;
10548         }
10549
10550         WR16(dev_addr, AUD_DEM_WR_I2S_CONFIG2__A, w_i2s_config);
10551         WR16(dev_addr, AUD_DSP_WR_I2S_OUT_FS__A, (u16) w_i2s_freq);
10552
10553         /* configure I2S output pads for master or slave mode */
10554         WR16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
10555
10556         if (output->mode == DRX_I2S_MODE_MASTER) {
10557                 w_i2s_pads_data_da = SIO_PDR_I2S_DA_CFG_MODE__MASTER |
10558                     SIO_PDR_I2S_DA_CFG_DRIVE__MASTER;
10559                 w_i2s_pads_data_cl = SIO_PDR_I2S_CL_CFG_MODE__MASTER |
10560                     SIO_PDR_I2S_CL_CFG_DRIVE__MASTER;
10561                 w_i2s_pads_data_ws = SIO_PDR_I2S_WS_CFG_MODE__MASTER |
10562                     SIO_PDR_I2S_WS_CFG_DRIVE__MASTER;
10563         } else {
10564                 w_i2s_pads_data_da = SIO_PDR_I2S_DA_CFG_MODE__SLAVE |
10565                     SIO_PDR_I2S_DA_CFG_DRIVE__SLAVE;
10566                 w_i2s_pads_data_cl = SIO_PDR_I2S_CL_CFG_MODE__SLAVE |
10567                     SIO_PDR_I2S_CL_CFG_DRIVE__SLAVE;
10568                 w_i2s_pads_data_ws = SIO_PDR_I2S_WS_CFG_MODE__SLAVE |
10569                     SIO_PDR_I2S_WS_CFG_DRIVE__SLAVE;
10570         }
10571
10572         WR16(dev_addr, SIO_PDR_I2S_DA_CFG__A, w_i2s_pads_data_da);
10573         WR16(dev_addr, SIO_PDR_I2S_CL_CFG__A, w_i2s_pads_data_cl);
10574         WR16(dev_addr, SIO_PDR_I2S_WS_CFG__A, w_i2s_pads_data_ws);
10575
10576         WR16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY__PRE);
10577
10578         /* all done, store config in data structure */
10579         ext_attr->aud_data.i2sdata = *output;
10580
10581         return DRX_STS_OK;
10582 rw_error:
10583         return DRX_STS_ERROR;
10584 }
10585
10586 /*============================================================================*/
10587 /**
10588 * \brief Get the Automatic Standard Select (ASS)
10589 *        and Automatic Sound Change (ASC)
10590 * \param demod instance of demodulator
10591 * \param pointer to pDRXAudAutoSound_t
10592 * \return int.
10593 *
10594 */
10595 static int
10596 aud_ctrl_get_cfg_auto_sound(pdrx_demod_instance_t demod,
10597                        pdrx_cfg_aud_auto_sound_t auto_sound)
10598 {
10599         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
10600         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
10601
10602         u16 r_modus = 0;
10603
10604         if (auto_sound == NULL) {
10605                 return DRX_STS_INVALID_ARG;
10606         }
10607
10608         dev_addr = demod->my_i2c_dev_addr;
10609         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
10610
10611         /* power up */
10612         if (ext_attr->aud_data.audio_is_active == false) {
10613                 CHK_ERROR(power_up_aud(demod, true));
10614                 ext_attr->aud_data.audio_is_active = true;
10615         }
10616
10617         CHK_ERROR(aud_get_modus(demod, &r_modus));
10618
10619         switch (r_modus & (AUD_DEM_WR_MODUS_MOD_ASS__M |
10620                           AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG__M)) {
10621         case AUD_DEM_WR_MODUS_MOD_ASS_OFF | AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_DISABLED:
10622         case AUD_DEM_WR_MODUS_MOD_ASS_OFF | AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_ENABLED:
10623                 *auto_sound =
10624                     DRX_AUD_AUTO_SOUND_OFF;
10625                 break;
10626         case AUD_DEM_WR_MODUS_MOD_ASS_ON | AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_ENABLED:
10627                 *auto_sound =
10628                     DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_ON;
10629                 break;
10630         case AUD_DEM_WR_MODUS_MOD_ASS_ON | AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_DISABLED:
10631                 *auto_sound =
10632                     DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_OFF;
10633                 break;
10634         default:
10635                 return DRX_STS_ERROR;
10636         }
10637
10638         return DRX_STS_OK;
10639 rw_error:
10640         return DRX_STS_ERROR;
10641 }
10642
10643 /*============================================================================*/
10644 /**
10645 * \brief Set the Automatic Standard Select (ASS)
10646 *        and Automatic Sound Change (ASC)
10647 * \param demod instance of demodulator
10648 * \param pointer to pDRXAudAutoSound_t
10649 * \return int.
10650 *
10651 */
10652 static int
10653 aud_ctr_setl_cfg_auto_sound(pdrx_demod_instance_t demod,
10654                        pdrx_cfg_aud_auto_sound_t auto_sound)
10655 {
10656         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
10657         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
10658
10659         u16 r_modus = 0;
10660         u16 w_modus = 0;
10661
10662         if (auto_sound == NULL) {
10663                 return DRX_STS_INVALID_ARG;
10664         }
10665
10666         dev_addr = demod->my_i2c_dev_addr;
10667         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
10668
10669         /* power up */
10670         if (ext_attr->aud_data.audio_is_active == false) {
10671                 CHK_ERROR(power_up_aud(demod, true));
10672                 ext_attr->aud_data.audio_is_active = true;
10673         }
10674
10675         CHK_ERROR(aud_get_modus(demod, &r_modus));
10676
10677         w_modus = r_modus;
10678         /* clear ASS & ASC bits */
10679         w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_ASS__M;
10680         w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG__M;
10681
10682         switch (*auto_sound) {
10683         case DRX_AUD_AUTO_SOUND_OFF:
10684                 w_modus |= AUD_DEM_WR_MODUS_MOD_ASS_OFF;
10685                 w_modus |= AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_DISABLED;
10686                 break;
10687         case DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_ON:
10688                 w_modus |= AUD_DEM_WR_MODUS_MOD_ASS_ON;
10689                 w_modus |= AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_ENABLED;
10690                 break;
10691         case DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_OFF:
10692                 w_modus |= AUD_DEM_WR_MODUS_MOD_ASS_ON;
10693                 w_modus |= AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_DISABLED;
10694                 break;
10695         default:
10696                 return DRX_STS_INVALID_ARG;
10697         }
10698
10699         if (w_modus != r_modus) {
10700                 WR16(dev_addr, AUD_DEM_WR_MODUS__A, w_modus);
10701         }
10702         /* copy to data structure */
10703         ext_attr->aud_data.auto_sound = *auto_sound;
10704
10705         return DRX_STS_OK;
10706 rw_error:
10707         return DRX_STS_ERROR;
10708 }
10709
10710 /*============================================================================*/
10711 /**
10712 * \brief Get the Automatic Standard Select thresholds
10713 * \param demod instance of demodulator
10714 * \param pointer to pDRXAudASSThres_t
10715 * \return int.
10716 *
10717 */
10718 static int
10719 aud_ctrl_get_cfg_ass_thres(pdrx_demod_instance_t demod, pdrx_cfg_aud_ass_thres_t thres)
10720 {
10721         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
10722         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
10723
10724         u16 thres_a2 = 0;
10725         u16 thres_btsc = 0;
10726         u16 thres_nicam = 0;
10727
10728         if (thres == NULL) {
10729                 return DRX_STS_INVALID_ARG;
10730         }
10731
10732         dev_addr = demod->my_i2c_dev_addr;
10733         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
10734
10735         /* power up */
10736         if (ext_attr->aud_data.audio_is_active == false) {
10737                 CHK_ERROR(power_up_aud(demod, true));
10738                 ext_attr->aud_data.audio_is_active = true;
10739         }
10740
10741         RR16(dev_addr, AUD_DEM_RAM_A2_THRSHLD__A, &thres_a2);
10742         RR16(dev_addr, AUD_DEM_RAM_BTSC_THRSHLD__A, &thres_btsc);
10743         RR16(dev_addr, AUD_DEM_RAM_NICAM_THRSHLD__A, &thres_nicam);
10744
10745         thres->a2 = thres_a2;
10746         thres->btsc = thres_btsc;
10747         thres->nicam = thres_nicam;
10748
10749         return DRX_STS_OK;
10750 rw_error:
10751         return DRX_STS_ERROR;
10752 }
10753
10754 /*============================================================================*/
10755 /**
10756 * \brief Get the Automatic Standard Select thresholds
10757 * \param demod instance of demodulator
10758 * \param pointer to pDRXAudASSThres_t
10759 * \return int.
10760 *
10761 */
10762 static int
10763 aud_ctrl_set_cfg_ass_thres(pdrx_demod_instance_t demod, pdrx_cfg_aud_ass_thres_t thres)
10764 {
10765         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
10766         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
10767
10768         if (thres == NULL) {
10769                 return DRX_STS_INVALID_ARG;
10770         }
10771
10772         dev_addr = demod->my_i2c_dev_addr;
10773         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
10774
10775         /* power up */
10776         if (ext_attr->aud_data.audio_is_active == false) {
10777                 CHK_ERROR(power_up_aud(demod, true));
10778                 ext_attr->aud_data.audio_is_active = true;
10779         }
10780
10781         WR16(dev_addr, AUD_DEM_WR_A2_THRSHLD__A, thres->a2);
10782         WR16(dev_addr, AUD_DEM_WR_BTSC_THRSHLD__A, thres->btsc);
10783         WR16(dev_addr, AUD_DEM_WR_NICAM_THRSHLD__A, thres->nicam);
10784
10785         /* update DRXK data structure with hardware values */
10786         ext_attr->aud_data.ass_thresholds = *thres;
10787
10788         return DRX_STS_OK;
10789 rw_error:
10790         return DRX_STS_ERROR;
10791 }
10792
10793 /*============================================================================*/
10794 /**
10795 * \brief Get Audio Carrier settings
10796 * \param demod instance of demodulator
10797 * \param pointer to pdrx_aud_carrier_t
10798 * \return int.
10799 *
10800 */
10801 static int
10802 aud_ctrl_get_cfg_carrier(pdrx_demod_instance_t demod, pdrx_cfg_aud_carriers_t carriers)
10803 {
10804         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
10805         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
10806
10807         u16 w_modus = 0;
10808
10809         u16 dco_a_hi = 0;
10810         u16 dco_a_lo = 0;
10811         u16 dco_b_hi = 0;
10812         u16 dco_b_lo = 0;
10813
10814         u32 valA = 0;
10815         u32 valB = 0;
10816
10817         u16 dc_lvl_a = 0;
10818         u16 dc_lvl_b = 0;
10819
10820         u16 cm_thes_a = 0;
10821         u16 cm_thes_b = 0;
10822
10823         if (carriers == NULL) {
10824                 return DRX_STS_INVALID_ARG;
10825         }
10826
10827         dev_addr = demod->my_i2c_dev_addr;
10828         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
10829
10830         /* power up */
10831         if (ext_attr->aud_data.audio_is_active == false) {
10832                 CHK_ERROR(power_up_aud(demod, true));
10833                 ext_attr->aud_data.audio_is_active = true;
10834         }
10835
10836         CHK_ERROR(aud_get_modus(demod, &w_modus));
10837
10838         /* Behaviour of primary audio channel */
10839         switch (w_modus & (AUD_DEM_WR_MODUS_MOD_CM_A__M)) {
10840         case AUD_DEM_WR_MODUS_MOD_CM_A_MUTE:
10841                 carriers->a.opt = DRX_NO_CARRIER_MUTE;
10842                 break;
10843         case AUD_DEM_WR_MODUS_MOD_CM_A_NOISE:
10844                 carriers->a.opt = DRX_NO_CARRIER_NOISE;
10845                 break;
10846         default:
10847                 return DRX_STS_ERROR;
10848                 break;
10849         }
10850
10851         /* Behaviour of secondary audio channel */
10852         switch (w_modus & (AUD_DEM_WR_MODUS_MOD_CM_B__M)) {
10853         case AUD_DEM_WR_MODUS_MOD_CM_B_MUTE:
10854                 carriers->b.opt = DRX_NO_CARRIER_MUTE;
10855                 break;
10856         case AUD_DEM_WR_MODUS_MOD_CM_B_NOISE:
10857                 carriers->b.opt = DRX_NO_CARRIER_NOISE;
10858                 break;
10859         default:
10860                 return DRX_STS_ERROR;
10861                 break;
10862         }
10863
10864         /* frequency adjustment for primary & secondary audio channel */
10865         RR16(dev_addr, AUD_DEM_RAM_DCO_A_HI__A, &dco_a_hi);
10866         RR16(dev_addr, AUD_DEM_RAM_DCO_A_LO__A, &dco_a_lo);
10867         RR16(dev_addr, AUD_DEM_RAM_DCO_B_HI__A, &dco_b_hi);
10868         RR16(dev_addr, AUD_DEM_RAM_DCO_B_LO__A, &dco_b_lo);
10869
10870         valA = (((u32) dco_a_hi) << 12) | ((u32) dco_a_lo & 0xFFF);
10871         valB = (((u32) dco_b_hi) << 12) | ((u32) dco_b_lo & 0xFFF);
10872
10873         /* Multiply by 20250 * 1>>24  ~= 2 / 1657 */
10874         carriers->a.dco = DRX_S24TODRXFREQ(valA) * 2L / 1657L;
10875         carriers->b.dco = DRX_S24TODRXFREQ(valB) * 2L / 1657L;
10876
10877         /* DC level of the incoming FM signal on the primary
10878            & seconday sound channel */
10879         RR16(dev_addr, AUD_DSP_RD_FM_DC_LEVEL_A__A, &dc_lvl_a);
10880         RR16(dev_addr, AUD_DSP_RD_FM_DC_LEVEL_B__A, &dc_lvl_b);
10881
10882         /* offset (kHz) = (dcLvl / 322) */
10883         carriers->a.shift = (DRX_U16TODRXFREQ(dc_lvl_a) / 322L);
10884         carriers->b.shift = (DRX_U16TODRXFREQ(dc_lvl_b) / 322L);
10885
10886         /* Carrier detetcion threshold for primary & secondary channel */
10887         RR16(dev_addr, AUD_DEM_RAM_CM_A_THRSHLD__A, &cm_thes_a);
10888         RR16(dev_addr, AUD_DEM_RAM_CM_B_THRSHLD__A, &cm_thes_b);
10889
10890         carriers->a.thres = cm_thes_a;
10891         carriers->b.thres = cm_thes_b;
10892
10893         return DRX_STS_OK;
10894 rw_error:
10895         return DRX_STS_ERROR;
10896 }
10897
10898 /*============================================================================*/
10899 /**
10900 * \brief Set Audio Carrier settings
10901 * \param demod instance of demodulator
10902 * \param pointer to pdrx_aud_carrier_t
10903 * \return int.
10904 *
10905 */
10906 static int
10907 aud_ctrl_set_cfg_carrier(pdrx_demod_instance_t demod, pdrx_cfg_aud_carriers_t carriers)
10908 {
10909         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
10910         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
10911
10912         u16 w_modus = 0;
10913         u16 r_modus = 0;
10914
10915         u16 dco_a_hi = 0;
10916         u16 dco_a_lo = 0;
10917         u16 dco_b_hi = 0;
10918         u16 dco_b_lo = 0;
10919
10920         s32 valA = 0;
10921         s32 valB = 0;
10922
10923         if (carriers == NULL) {
10924                 return DRX_STS_INVALID_ARG;
10925         }
10926
10927         dev_addr = demod->my_i2c_dev_addr;
10928         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
10929
10930         /* power up */
10931         if (ext_attr->aud_data.audio_is_active == false) {
10932                 CHK_ERROR(power_up_aud(demod, true));
10933                 ext_attr->aud_data.audio_is_active = true;
10934         }
10935
10936         CHK_ERROR(aud_get_modus(demod, &r_modus));
10937
10938         w_modus = r_modus;
10939         w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_CM_A__M;
10940         /* Behaviour of primary audio channel */
10941         switch (carriers->a.opt) {
10942         case DRX_NO_CARRIER_MUTE:
10943                 w_modus |= AUD_DEM_WR_MODUS_MOD_CM_A_MUTE;
10944                 break;
10945         case DRX_NO_CARRIER_NOISE:
10946                 w_modus |= AUD_DEM_WR_MODUS_MOD_CM_A_NOISE;
10947                 break;
10948         default:
10949                 return DRX_STS_INVALID_ARG;
10950                 break;
10951         }
10952
10953         /* Behaviour of secondary audio channel */
10954         w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_CM_B__M;
10955         switch (carriers->b.opt) {
10956         case DRX_NO_CARRIER_MUTE:
10957                 w_modus |= AUD_DEM_WR_MODUS_MOD_CM_B_MUTE;
10958                 break;
10959         case DRX_NO_CARRIER_NOISE:
10960                 w_modus |= AUD_DEM_WR_MODUS_MOD_CM_B_NOISE;
10961                 break;
10962         default:
10963                 return DRX_STS_INVALID_ARG;
10964                 break;
10965         }
10966
10967         /* now update the modus register */
10968         if (w_modus != r_modus) {
10969                 WR16(dev_addr, AUD_DEM_WR_MODUS__A, w_modus);
10970         }
10971
10972         /* frequency adjustment for primary & secondary audio channel */
10973         valA = (s32) ((carriers->a.dco) * 1657L / 2);
10974         valB = (s32) ((carriers->b.dco) * 1657L / 2);
10975
10976         dco_a_hi = (u16) ((valA >> 12) & 0xFFF);
10977         dco_a_lo = (u16) (valA & 0xFFF);
10978         dco_b_hi = (u16) ((valB >> 12) & 0xFFF);
10979         dco_b_lo = (u16) (valB & 0xFFF);
10980
10981         WR16(dev_addr, AUD_DEM_WR_DCO_A_HI__A, dco_a_hi);
10982         WR16(dev_addr, AUD_DEM_WR_DCO_A_LO__A, dco_a_lo);
10983         WR16(dev_addr, AUD_DEM_WR_DCO_B_HI__A, dco_b_hi);
10984         WR16(dev_addr, AUD_DEM_WR_DCO_B_LO__A, dco_b_lo);
10985
10986         /* Carrier detetcion threshold for primary & secondary channel */
10987         WR16(dev_addr, AUD_DEM_WR_CM_A_THRSHLD__A, carriers->a.thres);
10988         WR16(dev_addr, AUD_DEM_WR_CM_B_THRSHLD__A, carriers->b.thres);
10989
10990         /* update DRXK data structure */
10991         ext_attr->aud_data.carriers = *carriers;
10992
10993         return DRX_STS_OK;
10994 rw_error:
10995         return DRX_STS_ERROR;
10996 }
10997
10998 /*============================================================================*/
10999 /**
11000 * \brief Get I2S Source, I2S matrix and FM matrix
11001 * \param demod instance of demodulator
11002 * \param pointer to pDRXAudmixer_t
11003 * \return int.
11004 *
11005 */
11006 static int
11007 aud_ctrl_get_cfg_mixer(pdrx_demod_instance_t demod, pdrx_cfg_aud_mixer_t mixer)
11008 {
11009         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11010         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11011
11012         u16 src_i2s_matr = 0;
11013         u16 fm_matr = 0;
11014
11015         if (mixer == NULL) {
11016                 return DRX_STS_INVALID_ARG;
11017         }
11018
11019         dev_addr = demod->my_i2c_dev_addr;
11020         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
11021
11022         /* power up */
11023         if (ext_attr->aud_data.audio_is_active == false) {
11024                 CHK_ERROR(power_up_aud(demod, true));
11025                 ext_attr->aud_data.audio_is_active = true;
11026         }
11027
11028         /* Source Selctor */
11029         RR16(dev_addr, AUD_DSP_WR_SRC_I2S_MATR__A, &src_i2s_matr);
11030
11031         switch (src_i2s_matr & AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S__M) {
11032         case AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_MONO:
11033                 mixer->source_i2s = DRX_AUD_SRC_MONO;
11034                 break;
11035         case AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_AB:
11036                 mixer->source_i2s = DRX_AUD_SRC_STEREO_OR_AB;
11037                 break;
11038         case AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_A:
11039                 mixer->source_i2s = DRX_AUD_SRC_STEREO_OR_A;
11040                 break;
11041         case AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_B:
11042                 mixer->source_i2s = DRX_AUD_SRC_STEREO_OR_B;
11043                 break;
11044         default:
11045                 return DRX_STS_ERROR;
11046         }
11047
11048         /* Matrix */
11049         switch (src_i2s_matr & AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S__M) {
11050         case AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_MONO:
11051                 mixer->matrix_i2s = DRX_AUD_I2S_MATRIX_MONO;
11052                 break;
11053         case AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_STEREO:
11054                 mixer->matrix_i2s = DRX_AUD_I2S_MATRIX_STEREO;
11055                 break;
11056         case AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_SOUND_A:
11057                 mixer->matrix_i2s = DRX_AUD_I2S_MATRIX_A_MONO;
11058                 break;
11059         case AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_SOUND_B:
11060                 mixer->matrix_i2s = DRX_AUD_I2S_MATRIX_B_MONO;
11061                 break;
11062         default:
11063                 return DRX_STS_ERROR;
11064         }
11065
11066         /* FM Matrix */
11067         RR16(dev_addr, AUD_DEM_WR_FM_MATRIX__A, &fm_matr);
11068         switch (fm_matr & AUD_DEM_WR_FM_MATRIX__M) {
11069         case AUD_DEM_WR_FM_MATRIX_NO_MATRIX:
11070                 mixer->matrix_fm = DRX_AUD_FM_MATRIX_NO_MATRIX;
11071                 break;
11072         case AUD_DEM_WR_FM_MATRIX_GERMAN_MATRIX:
11073                 mixer->matrix_fm = DRX_AUD_FM_MATRIX_GERMAN;
11074                 break;
11075         case AUD_DEM_WR_FM_MATRIX_KOREAN_MATRIX:
11076                 mixer->matrix_fm = DRX_AUD_FM_MATRIX_KOREAN;
11077                 break;
11078         case AUD_DEM_WR_FM_MATRIX_SOUND_A:
11079                 mixer->matrix_fm = DRX_AUD_FM_MATRIX_SOUND_A;
11080                 break;
11081         case AUD_DEM_WR_FM_MATRIX_SOUND_B:
11082                 mixer->matrix_fm = DRX_AUD_FM_MATRIX_SOUND_B;
11083                 break;
11084         default:
11085                 return DRX_STS_ERROR;
11086         }
11087
11088         return DRX_STS_OK;
11089 rw_error:
11090         return DRX_STS_ERROR;
11091 }
11092
11093 /*============================================================================*/
11094 /**
11095 * \brief Set I2S Source, I2S matrix and FM matrix
11096 * \param demod instance of demodulator
11097 * \param pointer to DRXAudmixer_t
11098 * \return int.
11099 *
11100 */
11101 static int
11102 aud_ctrl_set_cfg_mixer(pdrx_demod_instance_t demod, pdrx_cfg_aud_mixer_t mixer)
11103 {
11104         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11105         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11106
11107         u16 src_i2s_matr = 0;
11108         u16 fm_matr = 0;
11109
11110         if (mixer == NULL) {
11111                 return DRX_STS_INVALID_ARG;
11112         }
11113
11114         dev_addr = demod->my_i2c_dev_addr;
11115         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
11116
11117         /* power up */
11118         if (ext_attr->aud_data.audio_is_active == false) {
11119                 CHK_ERROR(power_up_aud(demod, true));
11120                 ext_attr->aud_data.audio_is_active = true;
11121         }
11122
11123         /* Source Selctor */
11124         RR16(dev_addr, AUD_DSP_WR_SRC_I2S_MATR__A, &src_i2s_matr);
11125         src_i2s_matr &= (u16) ~AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S__M;
11126
11127         switch (mixer->source_i2s) {
11128         case DRX_AUD_SRC_MONO:
11129                 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_MONO;
11130                 break;
11131         case DRX_AUD_SRC_STEREO_OR_AB:
11132                 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_AB;
11133                 break;
11134         case DRX_AUD_SRC_STEREO_OR_A:
11135                 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_A;
11136                 break;
11137         case DRX_AUD_SRC_STEREO_OR_B:
11138                 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_B;
11139                 break;
11140         default:
11141                 return DRX_STS_INVALID_ARG;
11142         }
11143
11144         /* Matrix */
11145         src_i2s_matr &= (u16) ~AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S__M;
11146         switch (mixer->matrix_i2s) {
11147         case DRX_AUD_I2S_MATRIX_MONO:
11148                 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_MONO;
11149                 break;
11150         case DRX_AUD_I2S_MATRIX_STEREO:
11151                 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_STEREO;
11152                 break;
11153         case DRX_AUD_I2S_MATRIX_A_MONO:
11154                 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_SOUND_A;
11155                 break;
11156         case DRX_AUD_I2S_MATRIX_B_MONO:
11157                 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_SOUND_B;
11158                 break;
11159         default:
11160                 return DRX_STS_INVALID_ARG;
11161         }
11162         /* write the result */
11163         WR16(dev_addr, AUD_DSP_WR_SRC_I2S_MATR__A, src_i2s_matr);
11164
11165         /* FM Matrix */
11166         RR16(dev_addr, AUD_DEM_WR_FM_MATRIX__A, &fm_matr);
11167         fm_matr &= (u16) ~AUD_DEM_WR_FM_MATRIX__M;
11168         switch (mixer->matrix_fm) {
11169         case DRX_AUD_FM_MATRIX_NO_MATRIX:
11170                 fm_matr |= AUD_DEM_WR_FM_MATRIX_NO_MATRIX;
11171                 break;
11172         case DRX_AUD_FM_MATRIX_GERMAN:
11173                 fm_matr |= AUD_DEM_WR_FM_MATRIX_GERMAN_MATRIX;
11174                 break;
11175         case DRX_AUD_FM_MATRIX_KOREAN:
11176                 fm_matr |= AUD_DEM_WR_FM_MATRIX_KOREAN_MATRIX;
11177                 break;
11178         case DRX_AUD_FM_MATRIX_SOUND_A:
11179                 fm_matr |= AUD_DEM_WR_FM_MATRIX_SOUND_A;
11180                 break;
11181         case DRX_AUD_FM_MATRIX_SOUND_B:
11182                 fm_matr |= AUD_DEM_WR_FM_MATRIX_SOUND_B;
11183                 break;
11184         default:
11185                 return DRX_STS_INVALID_ARG;
11186         }
11187
11188         /* Only write if ASS is off */
11189         if (ext_attr->aud_data.auto_sound == DRX_AUD_AUTO_SOUND_OFF) {
11190                 WR16(dev_addr, AUD_DEM_WR_FM_MATRIX__A, fm_matr);
11191         }
11192
11193         /* update the data structure with hardware state */
11194         ext_attr->aud_data.mixer = *mixer;
11195
11196         return DRX_STS_OK;
11197 rw_error:
11198         return DRX_STS_ERROR;
11199 }
11200
11201 /*============================================================================*/
11202 /**
11203 * \brief Set AV Sync settings
11204 * \param demod instance of demodulator
11205 * \param pointer to DRXICfgAVSync_t
11206 * \return int.
11207 *
11208 */
11209 static int
11210 aud_ctrl_set_cfg_av_sync(pdrx_demod_instance_t demod, pdrx_cfg_aud_av_sync_t av_sync)
11211 {
11212         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11213         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11214
11215         u16 w_aud_vid_sync = 0;
11216
11217         if (av_sync == NULL) {
11218                 return DRX_STS_INVALID_ARG;
11219         }
11220
11221         dev_addr = demod->my_i2c_dev_addr;
11222         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
11223
11224         /* power up */
11225         if (ext_attr->aud_data.audio_is_active == false) {
11226                 CHK_ERROR(power_up_aud(demod, true));
11227                 ext_attr->aud_data.audio_is_active = true;
11228         }
11229
11230         /* audio/video synchronisation */
11231         RR16(dev_addr, AUD_DSP_WR_AV_SYNC__A, &w_aud_vid_sync);
11232
11233         w_aud_vid_sync &= (u16) ~AUD_DSP_WR_AV_SYNC_AV_ON__M;
11234
11235         if (*av_sync == DRX_AUD_AVSYNC_OFF) {
11236                 w_aud_vid_sync |= AUD_DSP_WR_AV_SYNC_AV_ON_DISABLE;
11237         } else {
11238                 w_aud_vid_sync |= AUD_DSP_WR_AV_SYNC_AV_ON_ENABLE;
11239         }
11240
11241         w_aud_vid_sync &= (u16) ~AUD_DSP_WR_AV_SYNC_AV_STD_SEL__M;
11242
11243         switch (*av_sync) {
11244         case DRX_AUD_AVSYNC_NTSC:
11245                 w_aud_vid_sync |= AUD_DSP_WR_AV_SYNC_AV_STD_SEL_NTSC;
11246                 break;
11247         case DRX_AUD_AVSYNC_MONOCHROME:
11248                 w_aud_vid_sync |= AUD_DSP_WR_AV_SYNC_AV_STD_SEL_MONOCHROME;
11249                 break;
11250         case DRX_AUD_AVSYNC_PAL_SECAM:
11251                 w_aud_vid_sync |= AUD_DSP_WR_AV_SYNC_AV_STD_SEL_PAL_SECAM;
11252                 break;
11253         case DRX_AUD_AVSYNC_OFF:
11254                 /* OK */
11255                 break;
11256         default:
11257                 return DRX_STS_INVALID_ARG;
11258         }
11259
11260         WR16(dev_addr, AUD_DSP_WR_AV_SYNC__A, w_aud_vid_sync);
11261         return DRX_STS_OK;
11262 rw_error:
11263         return DRX_STS_ERROR;
11264 }
11265
11266 /*============================================================================*/
11267 /**
11268 * \brief Get AV Sync settings
11269 * \param demod instance of demodulator
11270 * \param pointer to DRXICfgAVSync_t
11271 * \return int.
11272 *
11273 */
11274 static int
11275 aud_ctrl_get_cfg_av_sync(pdrx_demod_instance_t demod, pdrx_cfg_aud_av_sync_t av_sync)
11276 {
11277         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11278         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11279
11280         u16 w_aud_vid_sync = 0;
11281
11282         if (av_sync == NULL) {
11283                 return DRX_STS_INVALID_ARG;
11284         }
11285
11286         dev_addr = demod->my_i2c_dev_addr;
11287         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
11288
11289         /* power up */
11290         if (ext_attr->aud_data.audio_is_active == false) {
11291                 CHK_ERROR(power_up_aud(demod, true));
11292                 ext_attr->aud_data.audio_is_active = true;
11293         }
11294
11295         /* audio/video synchronisation */
11296         RR16(dev_addr, AUD_DSP_WR_AV_SYNC__A, &w_aud_vid_sync);
11297
11298         if ((w_aud_vid_sync & AUD_DSP_WR_AV_SYNC_AV_ON__M) ==
11299             AUD_DSP_WR_AV_SYNC_AV_ON_DISABLE) {
11300                 *av_sync = DRX_AUD_AVSYNC_OFF;
11301                 return DRX_STS_OK;
11302         }
11303
11304         switch (w_aud_vid_sync & AUD_DSP_WR_AV_SYNC_AV_STD_SEL__M) {
11305         case AUD_DSP_WR_AV_SYNC_AV_STD_SEL_NTSC:
11306                 *av_sync = DRX_AUD_AVSYNC_NTSC;
11307                 break;
11308         case AUD_DSP_WR_AV_SYNC_AV_STD_SEL_MONOCHROME:
11309                 *av_sync = DRX_AUD_AVSYNC_MONOCHROME;
11310                 break;
11311         case AUD_DSP_WR_AV_SYNC_AV_STD_SEL_PAL_SECAM:
11312                 *av_sync = DRX_AUD_AVSYNC_PAL_SECAM;
11313                 break;
11314         default:
11315                 return DRX_STS_ERROR;
11316         }
11317
11318         return DRX_STS_OK;
11319 rw_error:
11320         return DRX_STS_ERROR;
11321 }
11322
11323 /*============================================================================*/
11324 /**
11325 * \brief Get deviation mode
11326 * \param demod instance of demodulator
11327 * \param pointer to drx_cfg_aud_deviation_t
11328 * \return int.
11329 *
11330 */
11331 static int
11332 aud_ctrl_get_cfg_dev(pdrx_demod_instance_t demod, pdrx_cfg_aud_deviation_t dev)
11333 {
11334         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11335         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11336
11337         u16 r_modus = 0;
11338
11339         if (dev == NULL) {
11340                 return DRX_STS_INVALID_ARG;
11341         }
11342
11343         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
11344         dev_addr = demod->my_i2c_dev_addr;
11345
11346         CHK_ERROR(aud_get_modus(demod, &r_modus));
11347
11348         switch (r_modus & AUD_DEM_WR_MODUS_MOD_HDEV_A__M) {
11349         case AUD_DEM_WR_MODUS_MOD_HDEV_A_NORMAL:
11350                 *dev = DRX_AUD_DEVIATION_NORMAL;
11351                 break;
11352         case AUD_DEM_WR_MODUS_MOD_HDEV_A_HIGH_DEVIATION:
11353                 *dev = DRX_AUD_DEVIATION_HIGH;
11354                 break;
11355         default:
11356                 return DRX_STS_ERROR;
11357         }
11358
11359         return DRX_STS_OK;
11360 rw_error:
11361         return DRX_STS_ERROR;
11362 }
11363
11364 /*============================================================================*/
11365 /**
11366 * \brief Get deviation mode
11367 * \param demod instance of demodulator
11368 * \param pointer to drx_cfg_aud_deviation_t
11369 * \return int.
11370 *
11371 */
11372 static int
11373 aud_ctrl_set_cfg_dev(pdrx_demod_instance_t demod, pdrx_cfg_aud_deviation_t dev)
11374 {
11375         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11376         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11377
11378         u16 w_modus = 0;
11379         u16 r_modus = 0;
11380
11381         if (dev == NULL) {
11382                 return DRX_STS_INVALID_ARG;
11383         }
11384
11385         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
11386         dev_addr = demod->my_i2c_dev_addr;
11387
11388         CHK_ERROR(aud_get_modus(demod, &r_modus));
11389
11390         w_modus = r_modus;
11391
11392         w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_HDEV_A__M;
11393
11394         switch (*dev) {
11395         case DRX_AUD_DEVIATION_NORMAL:
11396                 w_modus |= AUD_DEM_WR_MODUS_MOD_HDEV_A_NORMAL;
11397                 break;
11398         case DRX_AUD_DEVIATION_HIGH:
11399                 w_modus |= AUD_DEM_WR_MODUS_MOD_HDEV_A_HIGH_DEVIATION;
11400                 break;
11401         default:
11402                 return DRX_STS_INVALID_ARG;
11403         }
11404
11405         /* now update the modus register */
11406         if (w_modus != r_modus) {
11407                 WR16(dev_addr, AUD_DEM_WR_MODUS__A, w_modus);
11408         }
11409         /* store in drxk data struct */
11410         ext_attr->aud_data.deviation = *dev;
11411
11412         return DRX_STS_OK;
11413 rw_error:
11414         return DRX_STS_ERROR;
11415 }
11416
11417 /*============================================================================*/
11418 /**
11419 * \brief Get Prescaler settings
11420 * \param demod instance of demodulator
11421 * \param pointer to drx_cfg_aud_prescale_t
11422 * \return int.
11423 *
11424 */
11425 static int
11426 aud_ctrl_get_cfg_prescale(pdrx_demod_instance_t demod, pdrx_cfg_aud_prescale_t presc)
11427 {
11428         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11429         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11430
11431         u16 r_max_fm_deviation = 0;
11432         u16 r_nicam_prescaler = 0;
11433
11434         if (presc == NULL) {
11435                 return DRX_STS_INVALID_ARG;
11436         }
11437
11438         dev_addr = demod->my_i2c_dev_addr;
11439         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
11440
11441         /* power up */
11442         if (ext_attr->aud_data.audio_is_active == false) {
11443                 CHK_ERROR(power_up_aud(demod, true));
11444                 ext_attr->aud_data.audio_is_active = true;
11445         }
11446
11447         /* read register data */
11448         RR16(dev_addr, AUD_DSP_WR_NICAM_PRESC__A, &r_nicam_prescaler);
11449         RR16(dev_addr, AUD_DSP_WR_FM_PRESC__A, &r_max_fm_deviation);
11450
11451         /* calculate max FM deviation */
11452         r_max_fm_deviation >>= AUD_DSP_WR_FM_PRESC_FM_AM_PRESC__B;
11453         if (r_max_fm_deviation > 0) {
11454                 presc->fm_deviation = 3600UL + (r_max_fm_deviation >> 1);
11455                 presc->fm_deviation /= r_max_fm_deviation;
11456         } else {
11457                 presc->fm_deviation = 380;      /* kHz */
11458         }
11459
11460         /* calculate NICAM gain from pre-scaler */
11461         /*
11462            nicam_gain   = 20 * ( log10( preScaler / 16) )
11463            = ( 100log10( preScaler ) - 100log10( 16 ) ) / 5
11464
11465            because log1_times100() cannot return negative numbers
11466            = ( 100log10( 10 * preScaler ) - 100log10( 10 * 16) ) / 5
11467
11468            for 0.1dB resolution:
11469
11470            nicam_gain   = 200 * ( log10( preScaler / 16) )
11471            = 2 * ( 100log10( 10 * preScaler ) - 100log10( 10 * 16) )
11472            = ( 100log10( 10 * preScaler^2 ) - 100log10( 10 * 16^2 ) )
11473
11474          */
11475         r_nicam_prescaler >>= 8;
11476         if (r_nicam_prescaler <= 1) {
11477                 presc->nicam_gain = -241;
11478         } else {
11479
11480                 presc->nicam_gain = (s16) (((s32)
11481                                              (log1_times100
11482                                               (10 * r_nicam_prescaler *
11483                                                r_nicam_prescaler)) - (s32)
11484                                              (log1_times100(10 * 16 * 16))));
11485         }
11486
11487         return DRX_STS_OK;
11488 rw_error:
11489         return DRX_STS_ERROR;
11490 }
11491
11492 /*============================================================================*/
11493 /**
11494 * \brief Set Prescaler settings
11495 * \param demod instance of demodulator
11496 * \param pointer to drx_cfg_aud_prescale_t
11497 * \return int.
11498 *
11499 */
11500 static int
11501 aud_ctrl_set_cfg_prescale(pdrx_demod_instance_t demod, pdrx_cfg_aud_prescale_t presc)
11502 {
11503         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11504         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11505
11506         u16 w_max_fm_deviation = 0;
11507         u16 nicam_prescaler;
11508
11509         if (presc == NULL) {
11510                 return DRX_STS_INVALID_ARG;
11511         }
11512
11513         dev_addr = demod->my_i2c_dev_addr;
11514         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
11515
11516         /* power up */
11517         if (ext_attr->aud_data.audio_is_active == false) {
11518                 CHK_ERROR(power_up_aud(demod, true));
11519                 ext_attr->aud_data.audio_is_active = true;
11520         }
11521
11522         /* setting of max FM deviation */
11523         w_max_fm_deviation = (u16) (frac(3600UL, presc->fm_deviation, 0));
11524         w_max_fm_deviation <<= AUD_DSP_WR_FM_PRESC_FM_AM_PRESC__B;
11525         if (w_max_fm_deviation >=
11526             AUD_DSP_WR_FM_PRESC_FM_AM_PRESC_28_KHZ_FM_DEVIATION) {
11527                 w_max_fm_deviation =
11528                     AUD_DSP_WR_FM_PRESC_FM_AM_PRESC_28_KHZ_FM_DEVIATION;
11529         }
11530
11531         /* NICAM Prescaler */
11532         if ((presc->nicam_gain >= -241) && (presc->nicam_gain <= 180)) {
11533                 /* calculation
11534
11535                    prescaler = 16 * 10^( gd_b / 20 )
11536
11537                    minval of gd_b = -20*log( 16 ) = -24.1dB
11538
11539                    negative numbers not allowed for d_b2lin_times100, so
11540
11541                    prescaler = 16 * 10^( gd_b / 20 )
11542                    = 10^( (gd_b / 20) + log10(16) )
11543                    = 10^( (gd_b + 20log10(16)) / 20 )
11544
11545                    in 0.1dB
11546
11547                    = 10^( G0.1dB + 200log10(16)) / 200 )
11548
11549                  */
11550                 nicam_prescaler = (u16)
11551                     ((d_b2lin_times100(presc->nicam_gain + 241UL) + 50UL) / 100UL);
11552
11553                 /* clip result */
11554                 if (nicam_prescaler > 127) {
11555                         nicam_prescaler = 127;
11556                 }
11557
11558                 /* shift before writing to register */
11559                 nicam_prescaler <<= 8;
11560         } else {
11561                 return (DRX_STS_INVALID_ARG);
11562         }
11563         /* end of setting NICAM Prescaler */
11564
11565         WR16(dev_addr, AUD_DSP_WR_NICAM_PRESC__A, nicam_prescaler);
11566         WR16(dev_addr, AUD_DSP_WR_FM_PRESC__A, w_max_fm_deviation);
11567
11568         ext_attr->aud_data.prescale = *presc;
11569
11570         return DRX_STS_OK;
11571 rw_error:
11572         return DRX_STS_ERROR;
11573 }
11574
11575 /*============================================================================*/
11576 /**
11577 * \brief Beep
11578 * \param demod instance of demodulator
11579 * \param pointer to drx_aud_beep_t
11580 * \return int.
11581 *
11582 */
11583 static int aud_ctrl_beep(pdrx_demod_instance_t demod, pdrx_aud_beep_t beep)
11584 {
11585         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11586         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11587
11588         u16 the_beep = 0;
11589         u16 volume = 0;
11590         u32 frequency = 0;
11591
11592         if (beep == NULL) {
11593                 return DRX_STS_INVALID_ARG;
11594         }
11595
11596         dev_addr = demod->my_i2c_dev_addr;
11597         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
11598
11599         /* power up */
11600         if (ext_attr->aud_data.audio_is_active == false) {
11601                 CHK_ERROR(power_up_aud(demod, true));
11602                 ext_attr->aud_data.audio_is_active = true;
11603         }
11604
11605         if ((beep->volume > 0) || (beep->volume < -127)) {
11606                 return DRX_STS_INVALID_ARG;
11607         }
11608
11609         if (beep->frequency > 3000) {
11610                 return DRX_STS_INVALID_ARG;
11611         }
11612
11613         volume = (u16) beep->volume + 127;
11614         the_beep |= volume << AUD_DSP_WR_BEEPER_BEEP_VOLUME__B;
11615
11616         frequency = ((u32) beep->frequency) * 23 / 500;
11617         if (frequency > AUD_DSP_WR_BEEPER_BEEP_FREQUENCY__M) {
11618                 frequency = AUD_DSP_WR_BEEPER_BEEP_FREQUENCY__M;
11619         }
11620         the_beep |= (u16) frequency;
11621
11622         if (beep->mute == true) {
11623                 the_beep = 0;
11624         }
11625
11626         WR16(dev_addr, AUD_DSP_WR_BEEPER__A, the_beep);
11627
11628         return DRX_STS_OK;
11629 rw_error:
11630         return DRX_STS_ERROR;
11631 }
11632
11633 /*============================================================================*/
11634 /**
11635 * \brief Set an audio standard
11636 * \param demod instance of demodulator
11637 * \param pointer to drx_aud_standard_t
11638 * \return int.
11639 *
11640 */
11641 static int
11642 aud_ctrl_set_standard(pdrx_demod_instance_t demod, pdrx_aud_standard_t standard)
11643 {
11644         struct i2c_device_addr *dev_addr = NULL;
11645         pdrxj_data_t ext_attr = NULL;
11646         enum drx_standard current_standard = DRX_STANDARD_UNKNOWN;
11647
11648         u16 w_standard = 0;
11649         u16 w_modus = 0;
11650         u16 r_modus = 0;
11651
11652         bool mute_buffer = false;
11653         s16 volume_buffer = 0;
11654         u16 w_volume = 0;
11655
11656         if (standard == NULL) {
11657                 return DRX_STS_INVALID_ARG;
11658         }
11659
11660         dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
11661         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
11662
11663         /* power up */
11664         if (ext_attr->aud_data.audio_is_active == false) {
11665                 CHK_ERROR(power_up_aud(demod, false));
11666                 ext_attr->aud_data.audio_is_active = true;
11667         }
11668
11669         /* reset RDS data availability flag */
11670         ext_attr->aud_data.rds_data_present = false;
11671
11672         /* we need to mute from here to avoid noise during standard switching */
11673         mute_buffer = ext_attr->aud_data.volume.mute;
11674         volume_buffer = ext_attr->aud_data.volume.volume;
11675
11676         ext_attr->aud_data.volume.mute = true;
11677         /* restore data structure from DRX ExtAttr, call volume first to mute */
11678         CHK_ERROR(aud_ctrl_set_cfg_volume(demod, &ext_attr->aud_data.volume));
11679         CHK_ERROR(aud_ctrl_set_cfg_carrier(demod, &ext_attr->aud_data.carriers));
11680         CHK_ERROR(aud_ctrl_set_cfg_ass_thres
11681                   (demod, &ext_attr->aud_data.ass_thresholds));
11682         CHK_ERROR(aud_ctr_setl_cfg_auto_sound(demod, &ext_attr->aud_data.auto_sound));
11683         CHK_ERROR(aud_ctrl_set_cfg_mixer(demod, &ext_attr->aud_data.mixer));
11684         CHK_ERROR(aud_ctrl_set_cfg_av_sync(demod, &ext_attr->aud_data.av_sync));
11685         CHK_ERROR(aud_ctrl_set_cfg_output_i2s(demod, &ext_attr->aud_data.i2sdata));
11686
11687         /* get prescaler from presets */
11688         CHK_ERROR(aud_ctrl_set_cfg_prescale(demod, &ext_attr->aud_data.prescale));
11689
11690         CHK_ERROR(aud_get_modus(demod, &r_modus));
11691
11692         w_modus = r_modus;
11693
11694         switch (*standard) {
11695         case DRX_AUD_STANDARD_AUTO:
11696                 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_AUTO;
11697                 break;
11698         case DRX_AUD_STANDARD_BTSC:
11699                 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_BTSC_STEREO;
11700                 if (ext_attr->aud_data.btsc_detect == DRX_BTSC_MONO_AND_SAP) {
11701                         w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_BTSC_SAP;
11702                 }
11703                 break;
11704         case DRX_AUD_STANDARD_A2:
11705                 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_M_KOREA;
11706                 break;
11707         case DRX_AUD_STANDARD_EIAJ:
11708                 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_EIA_J;
11709                 break;
11710         case DRX_AUD_STANDARD_FM_STEREO:
11711                 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_FM_RADIO;
11712                 break;
11713         case DRX_AUD_STANDARD_BG_FM:
11714                 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_BG_FM;
11715                 break;
11716         case DRX_AUD_STANDARD_D_K1:
11717                 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_D_K1;
11718                 break;
11719         case DRX_AUD_STANDARD_D_K2:
11720                 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_D_K2;
11721                 break;
11722         case DRX_AUD_STANDARD_D_K3:
11723                 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_D_K3;
11724                 break;
11725         case DRX_AUD_STANDARD_BG_NICAM_FM:
11726                 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_BG_NICAM_FM;
11727                 break;
11728         case DRX_AUD_STANDARD_L_NICAM_AM:
11729                 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_L_NICAM_AM;
11730                 break;
11731         case DRX_AUD_STANDARD_I_NICAM_FM:
11732                 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_I_NICAM_FM;
11733                 break;
11734         case DRX_AUD_STANDARD_D_K_NICAM_FM:
11735                 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_D_K_NICAM_FM;
11736                 break;
11737         case DRX_AUD_STANDARD_UNKNOWN:
11738                 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_AUTO;
11739                 break;
11740         default:
11741                 return DRX_STS_ERROR;
11742         }
11743
11744         if (*standard == DRX_AUD_STANDARD_AUTO) {
11745                 /* we need the current standard here */
11746                 current_standard = ext_attr->standard;
11747
11748                 w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_6_5MHZ__M;
11749
11750                 if ((current_standard == DRX_STANDARD_PAL_SECAM_L) ||
11751                     (current_standard == DRX_STANDARD_PAL_SECAM_LP)) {
11752                         w_modus |= (AUD_DEM_WR_MODUS_MOD_6_5MHZ_SECAM);
11753                 } else {
11754                         w_modus |= (AUD_DEM_WR_MODUS_MOD_6_5MHZ_D_K);
11755                 }
11756
11757                 w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_4_5MHZ__M;
11758                 if (current_standard == DRX_STANDARD_NTSC) {
11759                         w_modus |= (AUD_DEM_WR_MODUS_MOD_4_5MHZ_M_BTSC);
11760
11761                 } else {        /* non USA, ignore standard M to save time */
11762
11763                         w_modus |= (AUD_DEM_WR_MODUS_MOD_4_5MHZ_CHROMA);
11764                 }
11765
11766         }
11767
11768         w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_FMRADIO__M;
11769
11770         /* just get hardcoded deemphasis and activate here */
11771         if (ext_attr->aud_data.deemph == DRX_AUD_FM_DEEMPH_50US) {
11772                 w_modus |= (AUD_DEM_WR_MODUS_MOD_FMRADIO_EU_50U);
11773         } else {
11774                 w_modus |= (AUD_DEM_WR_MODUS_MOD_FMRADIO_US_75U);
11775         }
11776
11777         w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_BTSC__M;
11778         if (ext_attr->aud_data.btsc_detect == DRX_BTSC_STEREO) {
11779                 w_modus |= (AUD_DEM_WR_MODUS_MOD_BTSC_BTSC_STEREO);
11780         } else {                /* DRX_BTSC_MONO_AND_SAP */
11781
11782                 w_modus |= (AUD_DEM_WR_MODUS_MOD_BTSC_BTSC_SAP);
11783         }
11784
11785         if (w_modus != r_modus) {
11786                 WR16(dev_addr, AUD_DEM_WR_MODUS__A, w_modus);
11787         }
11788
11789         WR16(dev_addr, AUD_DEM_WR_STANDARD_SEL__A, w_standard);
11790
11791    /**************************************************************************/
11792         /* NOT calling aud_ctrl_set_cfg_volume to avoid interfering standard          */
11793         /* detection, need to keep things very minimal here, but keep audio       */
11794         /* buffers intact                                                         */
11795    /**************************************************************************/
11796         ext_attr->aud_data.volume.mute = mute_buffer;
11797         if (ext_attr->aud_data.volume.mute == false) {
11798                 w_volume |= (u16) ((volume_buffer + AUD_VOLUME_ZERO_DB) <<
11799                                     AUD_DSP_WR_VOLUME_VOL_MAIN__B);
11800                 WR16(dev_addr, AUD_DSP_WR_VOLUME__A, w_volume);
11801         }
11802
11803         /* write standard selected */
11804         ext_attr->aud_data.audio_standard = *standard;
11805
11806         return DRX_STS_OK;
11807 rw_error:
11808         return DRX_STS_ERROR;
11809 }
11810
11811 /*============================================================================*/
11812 /**
11813 * \brief Get the current audio standard
11814 * \param demod instance of demodulator
11815 * \param pointer to drx_aud_standard_t
11816 * \return int.
11817 *
11818 */
11819 static int
11820 aud_ctrl_get_standard(pdrx_demod_instance_t demod, pdrx_aud_standard_t standard)
11821 {
11822         struct i2c_device_addr *dev_addr = NULL;
11823         pdrxj_data_t ext_attr = NULL;
11824
11825         u16 r_data = 0;
11826
11827         if (standard == NULL) {
11828                 return DRX_STS_INVALID_ARG;
11829         }
11830
11831         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
11832         dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
11833
11834         /* power up */
11835         if (ext_attr->aud_data.audio_is_active == false) {
11836                 CHK_ERROR(power_up_aud(demod, true));
11837                 ext_attr->aud_data.audio_is_active = true;
11838         }
11839
11840         *standard = DRX_AUD_STANDARD_UNKNOWN;
11841
11842         RR16(dev_addr, AUD_DEM_RD_STANDARD_RES__A, &r_data);
11843
11844         /* return OK if the detection is not ready yet */
11845         if (r_data >= AUD_DEM_RD_STANDARD_RES_STD_RESULT_DETECTION_STILL_ACTIVE) {
11846                 *standard = DRX_AUD_STANDARD_NOT_READY;
11847                 return DRX_STS_OK;
11848         }
11849
11850         /* detection done, return correct standard */
11851         switch (r_data) {
11852                 /* no standard detected */
11853         case AUD_DEM_RD_STANDARD_RES_STD_RESULT_NO_SOUND_STANDARD:
11854                 *standard = DRX_AUD_STANDARD_UNKNOWN;
11855                 break;
11856                 /* standard is KOREA(A2) */
11857         case AUD_DEM_RD_STANDARD_RES_STD_RESULT_NTSC_M_DUAL_CARRIER_FM:
11858                 *standard = DRX_AUD_STANDARD_A2;
11859                 break;
11860                 /* standard is EIA-J (Japan) */
11861         case AUD_DEM_RD_STANDARD_RES_STD_RESULT_NTSC_EIA_J:
11862                 *standard = DRX_AUD_STANDARD_EIAJ;
11863                 break;
11864                 /* standard is BTSC-stereo */
11865         case AUD_DEM_RD_STANDARD_RES_STD_RESULT_BTSC_STEREO:
11866                 *standard = DRX_AUD_STANDARD_BTSC;
11867                 break;
11868                 /* standard is BTSC-mono (SAP) */
11869         case AUD_DEM_RD_STANDARD_RES_STD_RESULT_BTSC_MONO_SAP:
11870                 *standard = DRX_AUD_STANDARD_BTSC;
11871                 break;
11872                 /* standard is FM radio */
11873         case AUD_DEM_RD_STANDARD_RES_STD_RESULT_FM_RADIO:
11874                 *standard = DRX_AUD_STANDARD_FM_STEREO;
11875                 break;
11876                 /* standard is BG FM */
11877         case AUD_DEM_RD_STANDARD_RES_STD_RESULT_B_G_DUAL_CARRIER_FM:
11878                 *standard = DRX_AUD_STANDARD_BG_FM;
11879                 break;
11880                 /* standard is DK-1 FM */
11881         case AUD_DEM_RD_STANDARD_RES_STD_RESULT_D_K1_DUAL_CARRIER_FM:
11882                 *standard = DRX_AUD_STANDARD_D_K1;
11883                 break;
11884                 /* standard is DK-2 FM */
11885         case AUD_DEM_RD_STANDARD_RES_STD_RESULT_D_K2_DUAL_CARRIER_FM:
11886                 *standard = DRX_AUD_STANDARD_D_K2;
11887                 break;
11888                 /* standard is DK-3 FM */
11889         case AUD_DEM_RD_STANDARD_RES_STD_RESULT_D_K3_DUAL_CARRIER_FM:
11890                 *standard = DRX_AUD_STANDARD_D_K3;
11891                 break;
11892                 /* standard is BG-NICAM FM */
11893         case AUD_DEM_RD_STANDARD_RES_STD_RESULT_B_G_NICAM_FM:
11894                 *standard = DRX_AUD_STANDARD_BG_NICAM_FM;
11895                 break;
11896                 /* standard is L-NICAM AM */
11897         case AUD_DEM_RD_STANDARD_RES_STD_RESULT_L_NICAM_AM:
11898                 *standard = DRX_AUD_STANDARD_L_NICAM_AM;
11899                 break;
11900                 /* standard is I-NICAM FM */
11901         case AUD_DEM_RD_STANDARD_RES_STD_RESULT_I_NICAM_FM:
11902                 *standard = DRX_AUD_STANDARD_I_NICAM_FM;
11903                 break;
11904                 /* standard is DK-NICAM FM */
11905         case AUD_DEM_RD_STANDARD_RES_STD_RESULT_D_K_NICAM_FM:
11906                 *standard = DRX_AUD_STANDARD_D_K_NICAM_FM;
11907                 break;
11908         default:
11909                 *standard = DRX_AUD_STANDARD_UNKNOWN;
11910         }
11911
11912         return DRX_STS_OK;
11913 rw_error:
11914         return DRX_STS_ERROR;
11915
11916 }
11917
11918 /*============================================================================*/
11919 /**
11920 * \brief Retreive lock status in case of FM standard
11921 * \param demod instance of demodulator
11922 * \param pointer to lock status
11923 * \return int.
11924 *
11925 */
11926 static int
11927 fm_lock_status(pdrx_demod_instance_t demod, pdrx_lock_status_t lock_stat)
11928 {
11929         drx_aud_status_t status;
11930
11931         /* Check detection of audio carriers */
11932         CHK_ERROR(aud_ctrl_get_carrier_detect_status(demod, &status));
11933
11934         /* locked if either primary or secondary carrier is detected */
11935         if ((status.carrier_a == true) || (status.carrier_b == true)) {
11936                 *lock_stat = DRX_LOCKED;
11937         } else {
11938                 *lock_stat = DRX_NOT_LOCKED;
11939         }
11940
11941         return (DRX_STS_OK);
11942
11943 rw_error:
11944         return (DRX_STS_ERROR);
11945 }
11946
11947 /*============================================================================*/
11948 /**
11949 * \brief retreive signal quality in case of FM standard
11950 * \param demod instance of demodulator
11951 * \param pointer to signal quality
11952 * \return int.
11953 *
11954 * Only the quality indicator field is will be supplied.
11955 * This will either be 0% or 100%, nothing in between.
11956 *
11957 */
11958 static int
11959 fm_sig_quality(pdrx_demod_instance_t demod, pdrx_sig_quality_t sig_quality)
11960 {
11961         drx_lock_status_t lock_status = DRX_NOT_LOCKED;
11962
11963         CHK_ERROR(fm_lock_status(demod, &lock_status));
11964         if (lock_status == DRX_LOCKED) {
11965                 sig_quality->indicator = 100;
11966         } else {
11967                 sig_quality->indicator = 0;
11968         }
11969
11970         return (DRX_STS_OK);
11971
11972 rw_error:
11973         return (DRX_STS_ERROR);
11974 }
11975
11976 #endif
11977
11978 /*===========================================================================*/
11979 /*==                    END AUDIO DATAPATH FUNCTIONS                       ==*/
11980 /*===========================================================================*/
11981
11982 /*============================================================================*/
11983 /*============================================================================*/
11984 /*==                       OOB DATAPATH FUNCTIONS                           ==*/
11985 /*============================================================================*/
11986 /*============================================================================*/
11987 #ifndef DRXJ_DIGITAL_ONLY
11988 /**
11989 * \fn int get_oob_lock_status ()
11990 * \brief Get OOB lock status.
11991 * \param dev_addr I2C address
11992   \      oob_lock OOB lock status.
11993 * \return int.
11994 *
11995 * Gets OOB lock status
11996 *
11997 */
11998 static int
11999 get_oob_lock_status(pdrx_demod_instance_t demod,
12000                  struct i2c_device_addr *dev_addr, pdrx_lock_status_t oob_lock)
12001 {
12002         drxjscu_cmd_t scu_cmd;
12003         u16 cmd_result[2];
12004         u16 oob_lock_state;
12005
12006         *oob_lock = DRX_NOT_LOCKED;
12007
12008         scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB |
12009             SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK;
12010         scu_cmd.result_len = 2;
12011         scu_cmd.result = cmd_result;
12012         scu_cmd.parameter_len = 0;
12013
12014         CHK_ERROR(scu_command(dev_addr, &scu_cmd));
12015
12016         if (scu_cmd.result[1] < 0x4000) {
12017                 /* 0x00 NOT LOCKED */
12018                 *oob_lock = DRX_NOT_LOCKED;
12019         } else if (scu_cmd.result[1] < 0x8000) {
12020                 /* 0x40 DEMOD LOCKED */
12021                 *oob_lock = DRXJ_OOB_SYNC_LOCK;
12022         } else if (scu_cmd.result[1] < 0xC000) {
12023                 /* 0x80 DEMOD + OOB LOCKED (system lock) */
12024                 oob_lock_state = scu_cmd.result[1] & 0x00FF;
12025
12026                 if (oob_lock_state & 0x0008) {
12027                         *oob_lock = DRXJ_OOB_SYNC_LOCK;
12028                 } else if ((oob_lock_state & 0x0002) && (oob_lock_state & 0x0001)) {
12029                         *oob_lock = DRXJ_OOB_AGC_LOCK;
12030                 }
12031         } else {
12032                 /* 0xC0 NEVER LOCKED (system will never be able to lock to the signal) */
12033                 *oob_lock = DRX_NEVER_LOCK;
12034         }
12035
12036         /* *oob_lock = scu_cmd.result[1]; */
12037
12038         return (DRX_STS_OK);
12039 rw_error:
12040         return (DRX_STS_ERROR);
12041 }
12042
12043 /**
12044 * \fn int get_oob_symbol_rate_offset ()
12045 * \brief Get OOB Symbol rate offset. Unit is [ppm]
12046 * \param dev_addr I2C address
12047 * \      Symbol Rate Offset OOB parameter.
12048 * \return int.
12049 *
12050 * Gets OOB frequency offset
12051 *
12052 */
12053 static int
12054 get_oob_symbol_rate_offset(struct i2c_device_addr *dev_addr, s32 *symbol_rate_offset)
12055 {
12056 /*  offset = -{(timing_offset/2^19)*(symbol_rate/12,656250MHz)}*10^6 [ppm]  */
12057 /*  offset = -{(timing_offset/2^19)*(symbol_rate/12656250)}*10^6 [ppm]  */
12058 /*  after reconfiguration: */
12059 /*  offset = -{(timing_offset*symbol_rate)/(2^19*12656250)}*10^6 [ppm]  */
12060 /*  shift symbol rate left by 5 without lossing information */
12061 /*  offset = -{(timing_offset*(symbol_rate * 2^-5))/(2^14*12656250)}*10^6 [ppm]*/
12062 /*  shift 10^6 left by 6 without loosing information */
12063 /*  offset = -{(timing_offset*(symbol_rate * 2^-5))/(2^8*12656250)}*15625 [ppm]*/
12064 /*  trim 12656250/15625 = 810 */
12065 /*  offset = -{(timing_offset*(symbol_rate * 2^-5))/(2^8*810)} [ppm]  */
12066 /*  offset = -[(symbol_rate * 2^-5)*(timing_offset)/(2^8)]/810 [ppm]  */
12067         s32 timing_offset = 0;
12068         u32 unsigned_timing_offset = 0;
12069         s32 division_factor = 810;
12070         u16 data = 0;
12071         u32 symbol_rate = 0;
12072         bool negative = false;
12073
12074         *symbol_rate_offset = 0;
12075         /* read data rate */
12076         SARR16(dev_addr, SCU_RAM_ORX_RF_RX_DATA_RATE__A, &data);
12077         switch (data & SCU_RAM_ORX_RF_RX_DATA_RATE__M) {
12078         case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC:
12079         case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC:
12080         case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC_ALT:
12081         case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC_ALT:
12082                 symbol_rate = 1024000;  /* bps */
12083                 break;
12084         case SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_REGSPEC:
12085         case SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_INVSPEC:
12086                 symbol_rate = 772000;   /* bps */
12087                 break;
12088         case SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_REGSPEC:
12089         case SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_INVSPEC:
12090                 symbol_rate = 1544000;  /* bps */
12091                 break;
12092         default:
12093                 return (DRX_STS_ERROR);
12094         }
12095
12096         RR16(dev_addr, ORX_CON_CTI_DTI_R__A, &data);
12097         /* convert data to positive and keep information about sign */
12098         if ((data & 0x8000) == 0x8000) {
12099                 if (data == 0x8000)
12100                         unsigned_timing_offset = 32768;
12101                 else
12102                         unsigned_timing_offset = 0x00007FFF & (u32) (-data);
12103                 negative = true;
12104         } else
12105                 unsigned_timing_offset = (u32) data;
12106
12107         symbol_rate = symbol_rate >> 5;
12108         unsigned_timing_offset = (unsigned_timing_offset * symbol_rate);
12109         unsigned_timing_offset = frac(unsigned_timing_offset, 256, FRAC_ROUND);
12110         unsigned_timing_offset = frac(unsigned_timing_offset,
12111                                     division_factor, FRAC_ROUND);
12112         if (negative)
12113                 timing_offset = (s32) unsigned_timing_offset;
12114         else
12115                 timing_offset = -(s32) unsigned_timing_offset;
12116
12117         *symbol_rate_offset = timing_offset;
12118
12119         return (DRX_STS_OK);
12120 rw_error:
12121         return (DRX_STS_ERROR);
12122 }
12123
12124 /**
12125 * \fn int get_oob_freq_offset ()
12126 * \brief Get OOB lock status.
12127 * \param dev_addr I2C address
12128 * \      freq_offset OOB frequency offset.
12129 * \return int.
12130 *
12131 * Gets OOB frequency offset
12132 *
12133 */
12134 static int
12135 get_oob_freq_offset(pdrx_demod_instance_t demod, s32 *freq_offset)
12136 {
12137         u16 data = 0;
12138         u16 rot = 0;
12139         u16 symbol_rateReg = 0;
12140         u32 symbol_rate = 0;
12141         s32 coarse_freq_offset = 0;
12142         s32 fine_freq_offset = 0;
12143         s32 fine_sign = 1;
12144         s32 coarse_sign = 1;
12145         u32 data64hi = 0;
12146         u32 data64lo = 0;
12147         u32 temp_freq_offset = 0;
12148         pdrx_common_attr_t common_attr = (pdrx_common_attr_t) (NULL);
12149         struct i2c_device_addr *dev_addr = NULL;
12150
12151         /* check arguments */
12152         if ((demod == NULL) || (freq_offset == NULL)) {
12153                 return DRX_STS_INVALID_ARG;
12154         }
12155
12156         dev_addr = demod->my_i2c_dev_addr;
12157         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
12158
12159         *freq_offset = 0;
12160
12161         /* read sign (spectrum inversion) */
12162         RR16(dev_addr, ORX_FWP_IQM_FRQ_W__A, &rot);
12163
12164         /* read frequency offset */
12165         SARR16(dev_addr, SCU_RAM_ORX_FRQ_OFFSET__A, &data);
12166         /* find COARSE frequency offset */
12167         /* coarse_freq_offset = ( 25312500Hz*FRQ_OFFSET >> 21 ); */
12168         if (data & 0x8000) {
12169                 data = (0xffff - data + 1);
12170                 coarse_sign = -1;
12171         }
12172         mult32(data, (common_attr->sys_clock_freq * 1000) / 6, &data64hi,
12173                &data64lo);
12174         temp_freq_offset = (((data64lo >> 21) & 0x7ff) | (data64hi << 11));
12175
12176         /* get value in KHz */
12177         coarse_freq_offset = coarse_sign * frac(temp_freq_offset, 1000, FRAC_ROUND);    /* KHz */
12178         /* read data rate */
12179         SARR16(dev_addr, SCU_RAM_ORX_RF_RX_DATA_RATE__A, &symbol_rateReg);
12180         switch (symbol_rateReg & SCU_RAM_ORX_RF_RX_DATA_RATE__M) {
12181         case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC:
12182         case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC:
12183         case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC_ALT:
12184         case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC_ALT:
12185                 symbol_rate = 1024000;
12186                 break;
12187         case SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_REGSPEC:
12188         case SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_INVSPEC:
12189                 symbol_rate = 772000;
12190                 break;
12191         case SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_REGSPEC:
12192         case SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_INVSPEC:
12193                 symbol_rate = 1544000;
12194                 break;
12195         default:
12196                 return (DRX_STS_ERROR);
12197         }
12198
12199         /* find FINE frequency offset */
12200         /* fine_freq_offset = ( (CORRECTION_VALUE*symbol_rate) >> 18 ); */
12201         RR16(dev_addr, ORX_CON_CPH_FRQ_R__A, &data);
12202         /* at least 5 MSB are 0 so first divide with 2^5 without information loss */
12203         fine_freq_offset = (symbol_rate >> 5);
12204         if (data & 0x8000) {
12205                 fine_freq_offset *= 0xffff - data + 1;  /* Hz */
12206                 fine_sign = -1;
12207         } else {
12208                 fine_freq_offset *= data;       /* Hz */
12209         }
12210         /* Left to divide with 8192 (2^13) */
12211         fine_freq_offset = frac(fine_freq_offset, 8192, FRAC_ROUND);
12212         /* and to divide with 1000 to get KHz */
12213         fine_freq_offset = fine_sign * frac(fine_freq_offset, 1000, FRAC_ROUND);        /* KHz */
12214
12215         if ((rot & 0x8000) == 0x8000)
12216                 *freq_offset = -(coarse_freq_offset + fine_freq_offset);
12217         else
12218                 *freq_offset = (coarse_freq_offset + fine_freq_offset);
12219
12220         return (DRX_STS_OK);
12221 rw_error:
12222         return (DRX_STS_ERROR);
12223 }
12224
12225 /**
12226 * \fn int get_oob_frequency ()
12227 * \brief Get OOB frequency (Unit:KHz).
12228 * \param dev_addr I2C address
12229 * \      frequency OOB frequency parameters.
12230 * \return int.
12231 *
12232 * Gets OOB frequency
12233 *
12234 */
12235 static int
12236 get_oob_frequency(pdrx_demod_instance_t demod, s32 *frequency)
12237 {
12238         u16 data = 0;
12239         s32 freq_offset = 0;
12240         s32 freq = 0;
12241         struct i2c_device_addr *dev_addr = NULL;
12242
12243         dev_addr = demod->my_i2c_dev_addr;
12244
12245         *frequency = 0;         /* KHz */
12246
12247         SARR16(dev_addr, SCU_RAM_ORX_RF_RX_FREQUENCY_VALUE__A, &data);
12248
12249         freq = (s32) ((s32) data * 50 + 50000L);
12250
12251         CHK_ERROR(get_oob_freq_offset(demod, &freq_offset));
12252
12253         *frequency = freq + freq_offset;
12254
12255         return (DRX_STS_OK);
12256 rw_error:
12257         return (DRX_STS_ERROR);
12258 }
12259
12260 /**
12261 * \fn int get_oobmer ()
12262 * \brief Get OOB MER.
12263 * \param dev_addr I2C address
12264   \      MER OOB parameter in dB.
12265 * \return int.
12266 *
12267 * Gets OOB MER. Table for MER is in Programming guide.
12268 *
12269 */
12270 static int get_oobmer(struct i2c_device_addr *dev_addr, u32 *mer)
12271 {
12272         u16 data = 0;
12273
12274         *mer = 0;
12275         /* READ MER */
12276         RR16(dev_addr, ORX_EQU_MER_MER_R__A, &data);
12277         switch (data) {
12278         case 0:         /* fall through */
12279         case 1:
12280                 *mer = 39;
12281                 break;
12282         case 2:
12283                 *mer = 33;
12284                 break;
12285         case 3:
12286                 *mer = 29;
12287                 break;
12288         case 4:
12289                 *mer = 27;
12290                 break;
12291         case 5:
12292                 *mer = 25;
12293                 break;
12294         case 6:
12295                 *mer = 23;
12296                 break;
12297         case 7:
12298                 *mer = 22;
12299                 break;
12300         case 8:
12301                 *mer = 21;
12302                 break;
12303         case 9:
12304                 *mer = 20;
12305                 break;
12306         case 10:
12307                 *mer = 19;
12308                 break;
12309         case 11:
12310                 *mer = 18;
12311                 break;
12312         case 12:
12313                 *mer = 17;
12314                 break;
12315         case 13:                /* fall through */
12316         case 14:
12317                 *mer = 16;
12318                 break;
12319         case 15:                /* fall through */
12320         case 16:
12321                 *mer = 15;
12322                 break;
12323         case 17:                /* fall through */
12324         case 18:
12325                 *mer = 14;
12326                 break;
12327         case 19:                /* fall through */
12328         case 20:
12329                 *mer = 13;
12330                 break;
12331         case 21:                /* fall through */
12332         case 22:
12333                 *mer = 12;
12334                 break;
12335         case 23:                /* fall through */
12336         case 24:                /* fall through */
12337         case 25:
12338                 *mer = 11;
12339                 break;
12340         case 26:                /* fall through */
12341         case 27:                /* fall through */
12342         case 28:
12343                 *mer = 10;
12344                 break;
12345         case 29:                /* fall through */
12346         case 30:                /* fall through */
12347         case 31:                /* fall through */
12348         case 32:
12349                 *mer = 9;
12350                 break;
12351         case 33:                /* fall through */
12352         case 34:                /* fall through */
12353         case 35:                /* fall through */
12354         case 36:
12355                 *mer = 8;
12356                 break;
12357         case 37:                /* fall through */
12358         case 38:                /* fall through */
12359         case 39:                /* fall through */
12360         case 40:
12361                 *mer = 7;
12362                 break;
12363         case 41:                /* fall through */
12364         case 42:                /* fall through */
12365         case 43:                /* fall through */
12366         case 44:                /* fall through */
12367         case 45:
12368                 *mer = 6;
12369                 break;
12370         case 46:                /* fall through */
12371         case 47:                /* fall through */
12372         case 48:                /* fall through */
12373         case 49:                /* fall through */
12374         case 50:                /* fall through */
12375                 *mer = 5;
12376                 break;
12377         case 51:                /* fall through */
12378         case 52:                /* fall through */
12379         case 53:                /* fall through */
12380         case 54:                /* fall through */
12381         case 55:                /* fall through */
12382         case 56:                /* fall through */
12383         case 57:
12384                 *mer = 4;
12385                 break;
12386         case 58:                /* fall through */
12387         case 59:                /* fall through */
12388         case 60:                /* fall through */
12389         case 61:                /* fall through */
12390         case 62:                /* fall through */
12391         case 63:
12392                 *mer = 0;
12393                 break;
12394         default:
12395                 *mer = 0;
12396                 break;
12397         }
12398         return (DRX_STS_OK);
12399 rw_error:
12400         return (DRX_STS_ERROR);
12401 }
12402 #endif /*#ifndef DRXJ_DIGITAL_ONLY */
12403
12404 /**
12405 * \fn int set_orx_nsu_aox()
12406 * \brief Configure OrxNsuAox for OOB
12407 * \param demod instance of demodulator.
12408 * \param active
12409 * \return int.
12410 */
12411 static int set_orx_nsu_aox(pdrx_demod_instance_t demod, bool active)
12412 {
12413         u16 data = 0;
12414         struct i2c_device_addr *dev_addr = NULL;
12415         pdrxj_data_t ext_attr = NULL;
12416
12417         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
12418         dev_addr = demod->my_i2c_dev_addr;
12419
12420         /* Configure NSU_AOX */
12421         RR16(dev_addr, ORX_NSU_AOX_STDBY_W__A, &data);
12422         if (!active) {
12423                 data &= ((~ORX_NSU_AOX_STDBY_W_STDBYADC_A2_ON)
12424                          & (~ORX_NSU_AOX_STDBY_W_STDBYAMP_A2_ON)
12425                          & (~ORX_NSU_AOX_STDBY_W_STDBYBIAS_A2_ON)
12426                          & (~ORX_NSU_AOX_STDBY_W_STDBYPLL_A2_ON)
12427                          & (~ORX_NSU_AOX_STDBY_W_STDBYPD_A2_ON)
12428                          & (~ORX_NSU_AOX_STDBY_W_STDBYTAGC_IF_A2_ON)
12429                          & (~ORX_NSU_AOX_STDBY_W_STDBYTAGC_RF_A2_ON)
12430                          & (~ORX_NSU_AOX_STDBY_W_STDBYFLT_A2_ON)
12431                     );
12432         } else {                /* active */
12433
12434                 data |= (ORX_NSU_AOX_STDBY_W_STDBYADC_A2_ON
12435                          | ORX_NSU_AOX_STDBY_W_STDBYAMP_A2_ON
12436                          | ORX_NSU_AOX_STDBY_W_STDBYBIAS_A2_ON
12437                          | ORX_NSU_AOX_STDBY_W_STDBYPLL_A2_ON
12438                          | ORX_NSU_AOX_STDBY_W_STDBYPD_A2_ON
12439                          | ORX_NSU_AOX_STDBY_W_STDBYTAGC_IF_A2_ON
12440                          | ORX_NSU_AOX_STDBY_W_STDBYTAGC_RF_A2_ON
12441                          | ORX_NSU_AOX_STDBY_W_STDBYFLT_A2_ON);
12442         }
12443         WR16(dev_addr, ORX_NSU_AOX_STDBY_W__A, data);
12444
12445         return (DRX_STS_OK);
12446 rw_error:
12447         return (DRX_STS_ERROR);
12448 }
12449
12450 /**
12451 * \fn int ctrl_set_oob()
12452 * \brief Set OOB channel to be used.
12453 * \param demod instance of demodulator
12454 * \param oob_param OOB parameters for channel setting.
12455 * \frequency should be in KHz
12456 * \return int.
12457 *
12458 * Accepts  only. Returns error otherwise.
12459 * Demapper value is written after scu_command START
12460 * because START command causes COMM_EXEC transition
12461 * from 0 to 1 which causes all registers to be
12462 * overwritten with initial value
12463 *
12464 */
12465
12466 /* Nyquist filter impulse response */
12467 #define IMPULSE_COSINE_ALPHA_0_3    {-3, -4, -1, 6, 10, 7, -5, -20, -25, -10, 29, 79, 123, 140} /*sqrt raised-cosine filter with alpha=0.3 */
12468 #define IMPULSE_COSINE_ALPHA_0_5    { 2, 0, -2, -2, 2, 5, 2, -10, -20, -14, 20, 74, 125, 145}   /*sqrt raised-cosine filter with alpha=0.5 */
12469 #define IMPULSE_COSINE_ALPHA_RO_0_5 { 0, 0, 1, 2, 3, 0, -7, -15, -16,  0, 34, 77, 114, 128}     /*full raised-cosine filter with alpha=0.5 (receiver only) */
12470
12471 /* Coefficients for the nyquist fitler (total: 27 taps) */
12472 #define NYQFILTERLEN 27
12473
12474 static int ctrl_set_oob(pdrx_demod_instance_t demod, p_drxoob_t oob_param)
12475 {
12476 #ifndef DRXJ_DIGITAL_ONLY
12477         drxoob_downstream_standard_t standard = DRX_OOB_MODE_A;
12478         s32 freq = 0;   /* KHz */
12479         struct i2c_device_addr *dev_addr = NULL;
12480         pdrxj_data_t ext_attr = NULL;
12481         u16 i = 0;
12482         bool mirror_freq_spectOOB = false;
12483         u16 trk_filter_value = 0;
12484         drxjscu_cmd_t scu_cmd;
12485         u16 set_param_parameters[3];
12486         u16 cmd_result[2] = { 0, 0 };
12487         s16 nyquist_coeffs[4][(NYQFILTERLEN + 1) / 2] = {
12488                 IMPULSE_COSINE_ALPHA_0_3,       /* Target Mode 0 */
12489                 IMPULSE_COSINE_ALPHA_0_3,       /* Target Mode 1 */
12490                 IMPULSE_COSINE_ALPHA_0_5,       /* Target Mode 2 */
12491                 IMPULSE_COSINE_ALPHA_RO_0_5     /* Target Mode 3 */
12492         };
12493         u8 mode_val[4] = { 2, 2, 0, 1 };
12494         u8 pfi_coeffs[4][6] = {
12495                 {DRXJ_16TO8(-92), DRXJ_16TO8(-108), DRXJ_16TO8(100)},   /* TARGET_MODE = 0:     PFI_A = -23/32; PFI_B = -54/32;  PFI_C = 25/32; fg = 0.5 MHz (Att=26dB) */
12496                 {DRXJ_16TO8(-64), DRXJ_16TO8(-80), DRXJ_16TO8(80)},     /* TARGET_MODE = 1:     PFI_A = -16/32; PFI_B = -40/32;  PFI_C = 20/32; fg = 1.0 MHz (Att=28dB) */
12497                 {DRXJ_16TO8(-80), DRXJ_16TO8(-98), DRXJ_16TO8(92)},     /* TARGET_MODE = 2, 3:  PFI_A = -20/32; PFI_B = -49/32;  PFI_C = 23/32; fg = 0.8 MHz (Att=25dB) */
12498                 {DRXJ_16TO8(-80), DRXJ_16TO8(-98), DRXJ_16TO8(92)}      /* TARGET_MODE = 2, 3:  PFI_A = -20/32; PFI_B = -49/32;  PFI_C = 23/32; fg = 0.8 MHz (Att=25dB) */
12499         };
12500         u16 mode_index;
12501
12502         dev_addr = demod->my_i2c_dev_addr;
12503         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
12504         mirror_freq_spectOOB = ext_attr->mirror_freq_spectOOB;
12505
12506         /* Check parameters */
12507         if (oob_param == NULL) {
12508                 /* power off oob module  */
12509                 scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB
12510                     | SCU_RAM_COMMAND_CMD_DEMOD_STOP;
12511                 scu_cmd.parameter_len = 0;
12512                 scu_cmd.result_len = 1;
12513                 scu_cmd.result = cmd_result;
12514                 CHK_ERROR(scu_command(dev_addr, &scu_cmd));
12515                 CHK_ERROR(set_orx_nsu_aox(demod, false));
12516                 WR16(dev_addr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_STOP);
12517
12518                 ext_attr->oob_power_on = false;
12519                 return (DRX_STS_OK);
12520         }
12521
12522         standard = oob_param->standard;
12523
12524         freq = oob_param->frequency;
12525         if ((freq < 70000) || (freq > 130000))
12526                 return (DRX_STS_ERROR);
12527         freq = (freq - 50000) / 50;
12528
12529         {
12530                 u16 index = 0;
12531                 u16 remainder = 0;
12532                 u16 *trk_filtercfg = ext_attr->oob_trk_filter_cfg;
12533
12534                 index = (u16) ((freq - 400) / 200);
12535                 remainder = (u16) ((freq - 400) % 200);
12536                 trk_filter_value =
12537                     trk_filtercfg[index] - (trk_filtercfg[index] -
12538                                            trk_filtercfg[index +
12539                                                         1]) / 10 * remainder /
12540                     20;
12541         }
12542
12543    /*********/
12544         /* Stop  */
12545    /*********/
12546         WR16(dev_addr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_STOP);
12547         scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB
12548             | SCU_RAM_COMMAND_CMD_DEMOD_STOP;
12549         scu_cmd.parameter_len = 0;
12550         scu_cmd.result_len = 1;
12551         scu_cmd.result = cmd_result;
12552         CHK_ERROR(scu_command(dev_addr, &scu_cmd));
12553    /*********/
12554         /* Reset */
12555    /*********/
12556         scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB
12557             | SCU_RAM_COMMAND_CMD_DEMOD_RESET;
12558         scu_cmd.parameter_len = 0;
12559         scu_cmd.result_len = 1;
12560         scu_cmd.result = cmd_result;
12561         CHK_ERROR(scu_command(dev_addr, &scu_cmd));
12562    /***********/
12563         /* SET_ENV */
12564    /***********/
12565         /* set frequency, spectrum inversion and data rate */
12566         scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB
12567             | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV;
12568         scu_cmd.parameter_len = 3;
12569         /* 1-data rate;2-frequency */
12570         switch (oob_param->standard) {
12571         case DRX_OOB_MODE_A:
12572                 if (
12573                            /* signal is transmitted inverted */
12574                            ((oob_param->spectrum_inverted == true) &
12575                             /* and tuner is not mirroring the signal */
12576                             (mirror_freq_spectOOB == false)) |
12577                            /* or */
12578                            /* signal is transmitted noninverted */
12579                            ((oob_param->spectrum_inverted == false) &
12580                             /* and tuner is mirroring the signal */
12581                             (mirror_freq_spectOOB == true))
12582                     )
12583                         set_param_parameters[0] =
12584                             SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC;
12585                 else
12586                         set_param_parameters[0] =
12587                             SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC;
12588                 break;
12589         case DRX_OOB_MODE_B_GRADE_A:
12590                 if (
12591                            /* signal is transmitted inverted */
12592                            ((oob_param->spectrum_inverted == true) &
12593                             /* and tuner is not mirroring the signal */
12594                             (mirror_freq_spectOOB == false)) |
12595                            /* or */
12596                            /* signal is transmitted noninverted */
12597                            ((oob_param->spectrum_inverted == false) &
12598                             /* and tuner is mirroring the signal */
12599                             (mirror_freq_spectOOB == true))
12600                     )
12601                         set_param_parameters[0] =
12602                             SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_INVSPEC;
12603                 else
12604                         set_param_parameters[0] =
12605                             SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_REGSPEC;
12606                 break;
12607         case DRX_OOB_MODE_B_GRADE_B:
12608         default:
12609                 if (
12610                            /* signal is transmitted inverted */
12611                            ((oob_param->spectrum_inverted == true) &
12612                             /* and tuner is not mirroring the signal */
12613                             (mirror_freq_spectOOB == false)) |
12614                            /* or */
12615                            /* signal is transmitted noninverted */
12616                            ((oob_param->spectrum_inverted == false) &
12617                             /* and tuner is mirroring the signal */
12618                             (mirror_freq_spectOOB == true))
12619                     )
12620                         set_param_parameters[0] =
12621                             SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_INVSPEC;
12622                 else
12623                         set_param_parameters[0] =
12624                             SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_REGSPEC;
12625                 break;
12626         }
12627         set_param_parameters[1] = (u16) (freq & 0xFFFF);
12628         set_param_parameters[2] = trk_filter_value;
12629         scu_cmd.parameter = set_param_parameters;
12630         scu_cmd.result_len = 1;
12631         scu_cmd.result = cmd_result;
12632         mode_index = mode_val[(set_param_parameters[0] & 0xC0) >> 6];
12633         CHK_ERROR(scu_command(dev_addr, &scu_cmd));
12634
12635         WR16(dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA);    /*  Write magic word to enable pdr reg write  */
12636         WR16(dev_addr, SIO_PDR_OOB_CRX_CFG__A,
12637              OOB_CRX_DRIVE_STRENGTH << SIO_PDR_OOB_CRX_CFG_DRIVE__B
12638              | 0x03 << SIO_PDR_OOB_CRX_CFG_MODE__B);
12639         WR16(dev_addr, SIO_PDR_OOB_DRX_CFG__A,
12640              OOB_DRX_DRIVE_STRENGTH << SIO_PDR_OOB_DRX_CFG_DRIVE__B
12641              | 0x03 << SIO_PDR_OOB_DRX_CFG_MODE__B);
12642         WR16(dev_addr, SIO_TOP_COMM_KEY__A, 0x0000);    /*  Write magic word to disable pdr reg write */
12643
12644         WR16(dev_addr, ORX_TOP_COMM_KEY__A, 0);
12645         WR16(dev_addr, ORX_FWP_AAG_LEN_W__A, 16000);
12646         WR16(dev_addr, ORX_FWP_AAG_THR_W__A, 40);
12647
12648         /* ddc */
12649         WR16(dev_addr, ORX_DDC_OFO_SET_W__A, ORX_DDC_OFO_SET_W__PRE);
12650
12651         /* nsu */
12652         WR16(dev_addr, ORX_NSU_AOX_LOPOW_W__A, ext_attr->oob_lo_pow);
12653
12654         /* initialization for target mode */
12655         WR16(dev_addr, SCU_RAM_ORX_TARGET_MODE__A,
12656              SCU_RAM_ORX_TARGET_MODE_2048KBPS_SQRT);
12657         WR16(dev_addr, SCU_RAM_ORX_FREQ_GAIN_CORR__A,
12658              SCU_RAM_ORX_FREQ_GAIN_CORR_2048KBPS);
12659
12660         /* Reset bits for timing and freq. recovery */
12661         WR16(dev_addr, SCU_RAM_ORX_RST_CPH__A, 0x0001);
12662         WR16(dev_addr, SCU_RAM_ORX_RST_CTI__A, 0x0002);
12663         WR16(dev_addr, SCU_RAM_ORX_RST_KRN__A, 0x0004);
12664         WR16(dev_addr, SCU_RAM_ORX_RST_KRP__A, 0x0008);
12665
12666         /* AGN_LOCK = {2048>>3, -2048, 8, -8, 0, 1}; */
12667         WR16(dev_addr, SCU_RAM_ORX_AGN_LOCK_TH__A, 2048 >> 3);
12668         WR16(dev_addr, SCU_RAM_ORX_AGN_LOCK_TOTH__A, (u16) (-2048));
12669         WR16(dev_addr, SCU_RAM_ORX_AGN_ONLOCK_TTH__A, 8);
12670         WR16(dev_addr, SCU_RAM_ORX_AGN_UNLOCK_TTH__A, (u16) (-8));
12671         WR16(dev_addr, SCU_RAM_ORX_AGN_LOCK_MASK__A, 1);
12672
12673         /* DGN_LOCK = {10, -2048, 8, -8, 0, 1<<1}; */
12674         WR16(dev_addr, SCU_RAM_ORX_DGN_LOCK_TH__A, 10);
12675         WR16(dev_addr, SCU_RAM_ORX_DGN_LOCK_TOTH__A, (u16) (-2048));
12676         WR16(dev_addr, SCU_RAM_ORX_DGN_ONLOCK_TTH__A, 8);
12677         WR16(dev_addr, SCU_RAM_ORX_DGN_UNLOCK_TTH__A, (u16) (-8));
12678         WR16(dev_addr, SCU_RAM_ORX_DGN_LOCK_MASK__A, 1 << 1);
12679
12680         /* FRQ_LOCK = {15,-2048, 8, -8, 0, 1<<2}; */
12681         WR16(dev_addr, SCU_RAM_ORX_FRQ_LOCK_TH__A, 17);
12682         WR16(dev_addr, SCU_RAM_ORX_FRQ_LOCK_TOTH__A, (u16) (-2048));
12683         WR16(dev_addr, SCU_RAM_ORX_FRQ_ONLOCK_TTH__A, 8);
12684         WR16(dev_addr, SCU_RAM_ORX_FRQ_UNLOCK_TTH__A, (u16) (-8));
12685         WR16(dev_addr, SCU_RAM_ORX_FRQ_LOCK_MASK__A, 1 << 2);
12686
12687         /* PHA_LOCK = {5000, -2048, 8, -8, 0, 1<<3}; */
12688         WR16(dev_addr, SCU_RAM_ORX_PHA_LOCK_TH__A, 3000);
12689         WR16(dev_addr, SCU_RAM_ORX_PHA_LOCK_TOTH__A, (u16) (-2048));
12690         WR16(dev_addr, SCU_RAM_ORX_PHA_ONLOCK_TTH__A, 8);
12691         WR16(dev_addr, SCU_RAM_ORX_PHA_UNLOCK_TTH__A, (u16) (-8));
12692         WR16(dev_addr, SCU_RAM_ORX_PHA_LOCK_MASK__A, 1 << 3);
12693
12694         /* TIM_LOCK = {300,      -2048, 8, -8, 0, 1<<4}; */
12695         WR16(dev_addr, SCU_RAM_ORX_TIM_LOCK_TH__A, 400);
12696         WR16(dev_addr, SCU_RAM_ORX_TIM_LOCK_TOTH__A, (u16) (-2048));
12697         WR16(dev_addr, SCU_RAM_ORX_TIM_ONLOCK_TTH__A, 8);
12698         WR16(dev_addr, SCU_RAM_ORX_TIM_UNLOCK_TTH__A, (u16) (-8));
12699         WR16(dev_addr, SCU_RAM_ORX_TIM_LOCK_MASK__A, 1 << 4);
12700
12701         /* EQU_LOCK = {20,      -2048, 8, -8, 0, 1<<5}; */
12702         WR16(dev_addr, SCU_RAM_ORX_EQU_LOCK_TH__A, 20);
12703         WR16(dev_addr, SCU_RAM_ORX_EQU_LOCK_TOTH__A, (u16) (-2048));
12704         WR16(dev_addr, SCU_RAM_ORX_EQU_ONLOCK_TTH__A, 4);
12705         WR16(dev_addr, SCU_RAM_ORX_EQU_UNLOCK_TTH__A, (u16) (-4));
12706         WR16(dev_addr, SCU_RAM_ORX_EQU_LOCK_MASK__A, 1 << 5);
12707
12708         /* PRE-Filter coefficients (PFI) */
12709         WRB(dev_addr, ORX_FWP_PFI_A_W__A, sizeof(pfi_coeffs[mode_index]),
12710             ((u8 *) pfi_coeffs[mode_index]));
12711         WR16(dev_addr, ORX_TOP_MDE_W__A, mode_index);
12712
12713         /* NYQUIST-Filter coefficients (NYQ) */
12714         for (i = 0; i < (NYQFILTERLEN + 1) / 2; i++) {
12715                 WR16(dev_addr, ORX_FWP_NYQ_ADR_W__A, i);
12716                 WR16(dev_addr, ORX_FWP_NYQ_COF_RW__A,
12717                      nyquist_coeffs[mode_index][i]);
12718         }
12719         WR16(dev_addr, ORX_FWP_NYQ_ADR_W__A, 31);
12720         WR16(dev_addr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_ACTIVE);
12721    /*********/
12722         /* Start */
12723    /*********/
12724         scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB
12725             | SCU_RAM_COMMAND_CMD_DEMOD_START;
12726         scu_cmd.parameter_len = 0;
12727         scu_cmd.result_len = 1;
12728         scu_cmd.result = cmd_result;
12729         CHK_ERROR(scu_command(dev_addr, &scu_cmd));
12730
12731         CHK_ERROR(set_orx_nsu_aox(demod, true));
12732         WR16(dev_addr, ORX_NSU_AOX_STHR_W__A, ext_attr->oob_pre_saw);
12733
12734         ext_attr->oob_power_on = true;
12735
12736         return (DRX_STS_OK);
12737 rw_error:
12738 #endif
12739         return (DRX_STS_ERROR);
12740 }
12741
12742 /**
12743 * \fn int ctrl_get_oob()
12744 * \brief Set modulation standard to be used.
12745 * \param demod instance of demodulator
12746 * \param oob_status OOB status parameters.
12747 * \return int.
12748 */
12749 static int
12750 ctrl_get_oob(pdrx_demod_instance_t demod, pdrxoob_status_t oob_status)
12751 {
12752 #ifndef DRXJ_DIGITAL_ONLY
12753         struct i2c_device_addr *dev_addr = NULL;
12754         pdrxj_data_t ext_attr = NULL;
12755         u16 data = 0;
12756
12757         dev_addr = demod->my_i2c_dev_addr;
12758         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
12759
12760         /* check arguments */
12761         if (oob_status == NULL) {
12762                 return (DRX_STS_INVALID_ARG);
12763         }
12764
12765         if (ext_attr->oob_power_on == false)
12766                 return (DRX_STS_ERROR);
12767
12768         RR16(dev_addr, ORX_DDC_OFO_SET_W__A, &data);
12769         RR16(dev_addr, ORX_NSU_TUN_RFGAIN_W__A, &data);
12770         RR16(dev_addr, ORX_FWP_AAG_THR_W__A, &data);
12771         SARR16(dev_addr, SCU_RAM_ORX_DGN_KI__A, &data);
12772         RR16(dev_addr, ORX_FWP_SRC_DGN_W__A, &data);
12773
12774         CHK_ERROR(get_oob_lock_status(demod, dev_addr, &oob_status->lock));
12775         CHK_ERROR(get_oob_frequency(demod, &oob_status->frequency));
12776         CHK_ERROR(get_oobmer(dev_addr, &oob_status->mer));
12777         CHK_ERROR(get_oob_symbol_rate_offset
12778                   (dev_addr, &oob_status->symbol_rate_offset));
12779
12780         return (DRX_STS_OK);
12781 rw_error:
12782 #endif
12783         return (DRX_STS_ERROR);
12784 }
12785
12786 /**
12787 * \fn int ctrl_set_cfg_oob_pre_saw()
12788 * \brief Configure PreSAW treshold value
12789 * \param cfg_data Pointer to configuration parameter
12790 * \return Error code
12791 */
12792 #ifndef DRXJ_DIGITAL_ONLY
12793 static int
12794 ctrl_set_cfg_oob_pre_saw(pdrx_demod_instance_t demod, u16 *cfg_data)
12795 {
12796         struct i2c_device_addr *dev_addr = NULL;
12797         pdrxj_data_t ext_attr = NULL;
12798
12799         if (cfg_data == NULL) {
12800                 return (DRX_STS_INVALID_ARG);
12801         }
12802         dev_addr = demod->my_i2c_dev_addr;
12803         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
12804
12805         WR16(dev_addr, ORX_NSU_AOX_STHR_W__A, *cfg_data);
12806         ext_attr->oob_pre_saw = *cfg_data;
12807         return (DRX_STS_OK);
12808 rw_error:
12809         return (DRX_STS_ERROR);
12810 }
12811 #endif
12812
12813 /**
12814 * \fn int ctrl_get_cfg_oob_pre_saw()
12815 * \brief Configure PreSAW treshold value
12816 * \param cfg_data Pointer to configuration parameter
12817 * \return Error code
12818 */
12819 #ifndef DRXJ_DIGITAL_ONLY
12820 static int
12821 ctrl_get_cfg_oob_pre_saw(pdrx_demod_instance_t demod, u16 *cfg_data)
12822 {
12823         pdrxj_data_t ext_attr = NULL;
12824
12825         if (cfg_data == NULL) {
12826                 return (DRX_STS_INVALID_ARG);
12827         }
12828         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
12829
12830         *cfg_data = ext_attr->oob_pre_saw;
12831
12832         return (DRX_STS_OK);
12833 }
12834 #endif
12835
12836 /**
12837 * \fn int ctrl_set_cfg_oob_lo_power()
12838 * \brief Configure LO Power value
12839 * \param cfg_data Pointer to p_drxj_cfg_oob_lo_power_t
12840 * \return Error code
12841 */
12842 #ifndef DRXJ_DIGITAL_ONLY
12843 static int
12844 ctrl_set_cfg_oob_lo_power(pdrx_demod_instance_t demod, p_drxj_cfg_oob_lo_power_t cfg_data)
12845 {
12846         struct i2c_device_addr *dev_addr = NULL;
12847         pdrxj_data_t ext_attr = NULL;
12848
12849         if (cfg_data == NULL) {
12850                 return (DRX_STS_INVALID_ARG);
12851         }
12852         dev_addr = demod->my_i2c_dev_addr;
12853         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
12854
12855         WR16(dev_addr, ORX_NSU_AOX_LOPOW_W__A, *cfg_data);
12856         ext_attr->oob_lo_pow = *cfg_data;
12857         return (DRX_STS_OK);
12858 rw_error:
12859         return (DRX_STS_ERROR);
12860 }
12861 #endif
12862
12863 /**
12864 * \fn int ctrl_get_cfg_oob_lo_power()
12865 * \brief Configure LO Power value
12866 * \param cfg_data Pointer to p_drxj_cfg_oob_lo_power_t
12867 * \return Error code
12868 */
12869 #ifndef DRXJ_DIGITAL_ONLY
12870 static int
12871 ctrl_get_cfg_oob_lo_power(pdrx_demod_instance_t demod, p_drxj_cfg_oob_lo_power_t cfg_data)
12872 {
12873         pdrxj_data_t ext_attr = NULL;
12874
12875         if (cfg_data == NULL) {
12876                 return (DRX_STS_INVALID_ARG);
12877         }
12878         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
12879
12880         *cfg_data = ext_attr->oob_lo_pow;
12881
12882         return (DRX_STS_OK);
12883 }
12884 #endif
12885 /*============================================================================*/
12886 /*==                     END OOB DATAPATH FUNCTIONS                         ==*/
12887 /*============================================================================*/
12888
12889 /*=============================================================================
12890   ===== MC command related functions ==========================================
12891   ===========================================================================*/
12892
12893 /*=============================================================================
12894   ===== ctrl_set_channel() ==========================================================
12895   ===========================================================================*/
12896 /**
12897 * \fn int ctrl_set_channel()
12898 * \brief Select a new transmission channel.
12899 * \param demod instance of demod.
12900 * \param channel Pointer to channel data.
12901 * \return int.
12902 *
12903 * In case the tuner module is not used and in case of NTSC/FM the pogrammer
12904 * must tune the tuner to the centre frequency of the NTSC/FM channel.
12905 *
12906 */
12907 static int
12908 ctrl_set_channel(pdrx_demod_instance_t demod, pdrx_channel_t channel)
12909 {
12910
12911         s32 tuner_set_freq = 0;
12912         s32 tuner_get_freq = 0;
12913         s32 tuner_freq_offset = 0;
12914         s32 intermediate_freq = 0;
12915         pdrxj_data_t ext_attr = NULL;
12916         struct i2c_device_addr *dev_addr = NULL;
12917         enum drx_standard standard = DRX_STANDARD_UNKNOWN;
12918         u32 tuner_mode = 0;
12919         pdrx_common_attr_t common_attr = NULL;
12920         bool bridge_closed = false;
12921 #ifndef DRXJ_VSB_ONLY
12922         u32 min_symbol_rate = 0;
12923         u32 max_symbol_rate = 0;
12924         int bandwidth_temp = 0;
12925         int bandwidth = 0;
12926 #endif
12927    /*== check arguments ======================================================*/
12928         if ((demod == NULL) || (channel == NULL)) {
12929                 return DRX_STS_INVALID_ARG;
12930         }
12931
12932         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
12933         dev_addr = demod->my_i2c_dev_addr;
12934         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
12935         standard = ext_attr->standard;
12936
12937         /* check valid standards */
12938         switch (standard) {
12939         case DRX_STANDARD_8VSB:
12940 #ifndef DRXJ_VSB_ONLY
12941         case DRX_STANDARD_ITU_A:
12942         case DRX_STANDARD_ITU_B:
12943         case DRX_STANDARD_ITU_C:
12944 #endif /* DRXJ_VSB_ONLY */
12945 #ifndef DRXJ_DIGITAL_ONLY
12946         case DRX_STANDARD_NTSC:
12947         case DRX_STANDARD_FM:
12948         case DRX_STANDARD_PAL_SECAM_BG:
12949         case DRX_STANDARD_PAL_SECAM_DK:
12950         case DRX_STANDARD_PAL_SECAM_I:
12951         case DRX_STANDARD_PAL_SECAM_L:
12952         case DRX_STANDARD_PAL_SECAM_LP:
12953 #endif /* DRXJ_DIGITAL_ONLY */
12954                 break;
12955         case DRX_STANDARD_UNKNOWN:
12956         default:
12957                 return (DRX_STS_INVALID_ARG);
12958         }
12959
12960         /* check bandwidth QAM annex B, NTSC and 8VSB */
12961         if ((standard == DRX_STANDARD_ITU_B) ||
12962             (standard == DRX_STANDARD_8VSB) ||
12963             (standard == DRX_STANDARD_NTSC)) {
12964                 switch (channel->bandwidth) {
12965                 case DRX_BANDWIDTH_6MHZ:
12966                 case DRX_BANDWIDTH_UNKNOWN:     /* fall through */
12967                         channel->bandwidth = DRX_BANDWIDTH_6MHZ;
12968                         break;
12969                 case DRX_BANDWIDTH_8MHZ:        /* fall through */
12970                 case DRX_BANDWIDTH_7MHZ:        /* fall through */
12971                 default:
12972                         return (DRX_STS_INVALID_ARG);
12973                 }
12974         }
12975 #ifndef DRXJ_DIGITAL_ONLY
12976         if (standard == DRX_STANDARD_PAL_SECAM_BG) {
12977                 switch (channel->bandwidth) {
12978                 case DRX_BANDWIDTH_7MHZ:        /* fall through */
12979                 case DRX_BANDWIDTH_8MHZ:
12980                         /* ok */
12981                         break;
12982                 case DRX_BANDWIDTH_6MHZ:        /* fall through */
12983                 case DRX_BANDWIDTH_UNKNOWN:     /* fall through */
12984                 default:
12985                         return (DRX_STS_INVALID_ARG);
12986                 }
12987         }
12988         /* check bandwidth PAL/SECAM  */
12989         if ((standard == DRX_STANDARD_PAL_SECAM_BG) ||
12990             (standard == DRX_STANDARD_PAL_SECAM_DK) ||
12991             (standard == DRX_STANDARD_PAL_SECAM_I) ||
12992             (standard == DRX_STANDARD_PAL_SECAM_L) ||
12993             (standard == DRX_STANDARD_PAL_SECAM_LP)) {
12994                 switch (channel->bandwidth) {
12995                 case DRX_BANDWIDTH_8MHZ:
12996                 case DRX_BANDWIDTH_UNKNOWN:     /* fall through */
12997                         channel->bandwidth = DRX_BANDWIDTH_8MHZ;
12998                         break;
12999                 case DRX_BANDWIDTH_6MHZ:        /* fall through */
13000                 case DRX_BANDWIDTH_7MHZ:        /* fall through */
13001                 default:
13002                         return (DRX_STS_INVALID_ARG);
13003                 }
13004         }
13005 #endif
13006
13007         /* For QAM annex A and annex C:
13008            -check symbolrate and constellation
13009            -derive bandwidth from symbolrate (input bandwidth is ignored)
13010          */
13011 #ifndef DRXJ_VSB_ONLY
13012         if ((standard == DRX_STANDARD_ITU_A) ||
13013             (standard == DRX_STANDARD_ITU_C)) {
13014                 drxuio_cfg_t uio_cfg = { DRX_UIO1, DRX_UIO_MODE_FIRMWARE_SAW };
13015                 int bw_rolloff_factor = 0;
13016
13017                 bw_rolloff_factor = (standard == DRX_STANDARD_ITU_A) ? 115 : 113;
13018                 min_symbol_rate = DRXJ_QAM_SYMBOLRATE_MIN;
13019                 max_symbol_rate = DRXJ_QAM_SYMBOLRATE_MAX;
13020                 /* config SMA_TX pin to SAW switch mode */
13021                 CHK_ERROR(ctrl_set_uio_cfg(demod, &uio_cfg));
13022
13023                 if (channel->symbolrate < min_symbol_rate ||
13024                     channel->symbolrate > max_symbol_rate) {
13025                         return (DRX_STS_INVALID_ARG);
13026                 }
13027
13028                 switch (channel->constellation) {
13029                 case DRX_CONSTELLATION_QAM16:   /* fall through */
13030                 case DRX_CONSTELLATION_QAM32:   /* fall through */
13031                 case DRX_CONSTELLATION_QAM64:   /* fall through */
13032                 case DRX_CONSTELLATION_QAM128:  /* fall through */
13033                 case DRX_CONSTELLATION_QAM256:
13034                         bandwidth_temp = channel->symbolrate * bw_rolloff_factor;
13035                         bandwidth = bandwidth_temp / 100;
13036
13037                         if ((bandwidth_temp % 100) >= 50) {
13038                                 bandwidth++;
13039                         }
13040
13041                         if (bandwidth <= 6100000) {
13042                                 channel->bandwidth = DRX_BANDWIDTH_6MHZ;
13043                         } else if ((bandwidth > 6100000)
13044                                    && (bandwidth <= 7100000)) {
13045                                 channel->bandwidth = DRX_BANDWIDTH_7MHZ;
13046                         } else if (bandwidth > 7100000) {
13047                                 channel->bandwidth = DRX_BANDWIDTH_8MHZ;
13048                         }
13049                         break;
13050                 default:
13051                         return (DRX_STS_INVALID_ARG);
13052                 }
13053         }
13054
13055         /* For QAM annex B:
13056            -check constellation
13057          */
13058         if (standard == DRX_STANDARD_ITU_B) {
13059                 switch (channel->constellation) {
13060                 case DRX_CONSTELLATION_AUTO:
13061                 case DRX_CONSTELLATION_QAM256:
13062                 case DRX_CONSTELLATION_QAM64:
13063                         break;
13064                 default:
13065                         return (DRX_STS_INVALID_ARG);
13066                 }
13067
13068                 switch (channel->interleavemode) {
13069                 case DRX_INTERLEAVEMODE_I128_J1:
13070                 case DRX_INTERLEAVEMODE_I128_J1_V2:
13071                 case DRX_INTERLEAVEMODE_I128_J2:
13072                 case DRX_INTERLEAVEMODE_I64_J2:
13073                 case DRX_INTERLEAVEMODE_I128_J3:
13074                 case DRX_INTERLEAVEMODE_I32_J4:
13075                 case DRX_INTERLEAVEMODE_I128_J4:
13076                 case DRX_INTERLEAVEMODE_I16_J8:
13077                 case DRX_INTERLEAVEMODE_I128_J5:
13078                 case DRX_INTERLEAVEMODE_I8_J16:
13079                 case DRX_INTERLEAVEMODE_I128_J6:
13080                 case DRX_INTERLEAVEMODE_I128_J7:
13081                 case DRX_INTERLEAVEMODE_I128_J8:
13082                 case DRX_INTERLEAVEMODE_I12_J17:
13083                 case DRX_INTERLEAVEMODE_I5_J4:
13084                 case DRX_INTERLEAVEMODE_B52_M240:
13085                 case DRX_INTERLEAVEMODE_B52_M720:
13086                 case DRX_INTERLEAVEMODE_UNKNOWN:
13087                 case DRX_INTERLEAVEMODE_AUTO:
13088                         break;
13089                 default:
13090                         return (DRX_STS_INVALID_ARG);
13091                 }
13092         }
13093
13094         if ((ext_attr->uio_sma_tx_mode) == DRX_UIO_MODE_FIRMWARE_SAW) {
13095                 /* SAW SW, user UIO is used for switchable SAW */
13096                 drxuio_data_t uio1 = { DRX_UIO1, false };
13097
13098                 switch (channel->bandwidth) {
13099                 case DRX_BANDWIDTH_8MHZ:
13100                         uio1.value = true;
13101                         break;
13102                 case DRX_BANDWIDTH_7MHZ:
13103                         uio1.value = false;
13104                         break;
13105                 case DRX_BANDWIDTH_6MHZ:
13106                         uio1.value = false;
13107                         break;
13108                 case DRX_BANDWIDTH_UNKNOWN:
13109                 default:
13110                         return (DRX_STS_INVALID_ARG);
13111                 }
13112
13113                 CHK_ERROR(ctrl_uio_write(demod, &uio1));
13114         }
13115 #endif /* DRXJ_VSB_ONLY */
13116         WR16(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
13117    /*== Tune, fast mode ======================================================*/
13118         if (demod->my_tuner != NULL) {
13119                 /* Determine tuner mode and freq to tune to ... */
13120                 switch (standard) {
13121 #ifndef DRXJ_DIGITAL_ONLY
13122                 case DRX_STANDARD_NTSC: /* fallthrough */
13123                 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
13124                 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
13125                 case DRX_STANDARD_PAL_SECAM_I:  /* fallthrough */
13126                 case DRX_STANDARD_PAL_SECAM_L:  /* fallthrough */
13127                 case DRX_STANDARD_PAL_SECAM_LP:
13128                         /* expecting center frequency, not picture carrier so no
13129                            conversion .... */
13130                         tuner_mode |= TUNER_MODE_ANALOG;
13131                         tuner_set_freq = channel->frequency;
13132                         break;
13133                 case DRX_STANDARD_FM:
13134                         /* center frequency (equals sound carrier) as input,
13135                            tune to edge of SAW */
13136                         tuner_mode |= TUNER_MODE_ANALOG;
13137                         tuner_set_freq =
13138                             channel->frequency + DRXJ_FM_CARRIER_FREQ_OFFSET;
13139                         break;
13140 #endif
13141                 case DRX_STANDARD_8VSB: /* fallthrough */
13142 #ifndef DRXJ_VSB_ONLY
13143                 case DRX_STANDARD_ITU_A:        /* fallthrough */
13144                 case DRX_STANDARD_ITU_B:        /* fallthrough */
13145                 case DRX_STANDARD_ITU_C:
13146 #endif
13147                         tuner_mode |= TUNER_MODE_DIGITAL;
13148                         tuner_set_freq = channel->frequency;
13149                         break;
13150                 case DRX_STANDARD_UNKNOWN:
13151                 default:
13152                         return (DRX_STS_ERROR);
13153                 }               /* switch(standard) */
13154
13155                 tuner_mode |= TUNER_MODE_SWITCH;
13156                 switch (channel->bandwidth) {
13157                 case DRX_BANDWIDTH_8MHZ:
13158                         tuner_mode |= TUNER_MODE_8MHZ;
13159                         break;
13160                 case DRX_BANDWIDTH_7MHZ:
13161                         tuner_mode |= TUNER_MODE_7MHZ;
13162                         break;
13163                 case DRX_BANDWIDTH_6MHZ:
13164                         tuner_mode |= TUNER_MODE_6MHZ;
13165                         break;
13166                 default:
13167                         /* TODO: for FM which bandwidth to use ?
13168                            also check offset from centre frequency ?
13169                            For now using 6MHz.
13170                          */
13171                         tuner_mode |= TUNER_MODE_6MHZ;
13172                         break;
13173                         /* return (DRX_STS_INVALID_ARG); */
13174                 }
13175
13176                 /* store bandwidth for GetChannel() */
13177                 ext_attr->curr_bandwidth = channel->bandwidth;
13178                 ext_attr->curr_symbol_rate = channel->symbolrate;
13179                 ext_attr->frequency = tuner_set_freq;
13180                 if (common_attr->tuner_port_nr == 1) {
13181                         /* close tuner bridge */
13182                         bridge_closed = true;
13183                         CHK_ERROR(ctrl_i2c_bridge(demod, &bridge_closed));
13184                         /* set tuner frequency */
13185                 }
13186
13187                 CHK_ERROR(drxbsp_tuner_set_frequency(demod->my_tuner,
13188                                                     tuner_mode, tuner_set_freq));
13189                 if (common_attr->tuner_port_nr == 1) {
13190                         /* open tuner bridge */
13191                         bridge_closed = false;
13192                         CHK_ERROR(ctrl_i2c_bridge(demod, &bridge_closed));
13193                 }
13194
13195                 /* Get actual frequency set by tuner and compute offset */
13196                 CHK_ERROR(drxbsp_tuner_get_frequency(demod->my_tuner,
13197                                                     0,
13198                                                     &tuner_get_freq,
13199                                                     &intermediate_freq));
13200                 tuner_freq_offset = tuner_get_freq - tuner_set_freq;
13201                 common_attr->intermediate_freq = intermediate_freq;
13202         } else {
13203                 /* no tuner instance defined, use fixed intermediate frequency */
13204                 tuner_freq_offset = 0;
13205                 intermediate_freq = demod->my_common_attr->intermediate_freq;
13206         }                       /* if ( demod->my_tuner != NULL ) */
13207
13208    /*== Setup demod for specific standard ====================================*/
13209         switch (standard) {
13210         case DRX_STANDARD_8VSB:
13211                 if (channel->mirror == DRX_MIRROR_AUTO) {
13212                         ext_attr->mirror = DRX_MIRROR_NO;
13213                 } else {
13214                         ext_attr->mirror = channel->mirror;
13215                 }
13216                 CHK_ERROR(set_vsb(demod));
13217                 CHK_ERROR(set_frequency(demod, channel, tuner_freq_offset));
13218                 break;
13219 #ifndef DRXJ_DIGITAL_ONLY
13220         case DRX_STANDARD_NTSC: /* fallthrough */
13221         case DRX_STANDARD_FM:   /* fallthrough */
13222         case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
13223         case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
13224         case DRX_STANDARD_PAL_SECAM_I:  /* fallthrough */
13225         case DRX_STANDARD_PAL_SECAM_L:  /* fallthrough */
13226         case DRX_STANDARD_PAL_SECAM_LP:
13227                 if (channel->mirror == DRX_MIRROR_AUTO) {
13228                         ext_attr->mirror = DRX_MIRROR_NO;
13229                 } else {
13230                         ext_attr->mirror = channel->mirror;
13231                 }
13232                 CHK_ERROR(set_atv_channel(demod,
13233                                         tuner_freq_offset, channel, standard));
13234                 break;
13235 #endif
13236 #ifndef DRXJ_VSB_ONLY
13237         case DRX_STANDARD_ITU_A:        /* fallthrough */
13238         case DRX_STANDARD_ITU_B:        /* fallthrough */
13239         case DRX_STANDARD_ITU_C:
13240                 CHK_ERROR(set_qamChannel(demod, channel, tuner_freq_offset));
13241                 break;
13242 #endif
13243         case DRX_STANDARD_UNKNOWN:
13244         default:
13245                 return (DRX_STS_ERROR);
13246         }
13247
13248    /*== Re-tune, slow mode ===================================================*/
13249         if (demod->my_tuner != NULL) {
13250                 /* tune to slow mode */
13251                 tuner_mode &= ~TUNER_MODE_SWITCH;
13252                 tuner_mode |= TUNER_MODE_LOCK;
13253
13254                 if (common_attr->tuner_port_nr == 1) {
13255                         /* close tuner bridge */
13256                         bridge_closed = true;
13257                         CHK_ERROR(ctrl_i2c_bridge(demod, &bridge_closed));
13258                 }
13259
13260                 /* set tuner frequency */
13261                 CHK_ERROR(drxbsp_tuner_set_frequency(demod->my_tuner,
13262                                                     tuner_mode, tuner_set_freq));
13263                 if (common_attr->tuner_port_nr == 1) {
13264                         /* open tuner bridge */
13265                         bridge_closed = false;
13266                         CHK_ERROR(ctrl_i2c_bridge(demod, &bridge_closed));
13267                 }
13268         }
13269
13270         /* if ( demod->my_tuner !=NULL ) */
13271         /* flag the packet error counter reset */
13272         ext_attr->reset_pkt_err_acc = true;
13273
13274         return (DRX_STS_OK);
13275 rw_error:
13276         return (DRX_STS_ERROR);
13277 }
13278
13279 /*=============================================================================
13280   ===== ctrl_get_channel() ==========================================================
13281   ===========================================================================*/
13282 /**
13283 * \fn int ctrl_get_channel()
13284 * \brief Retreive parameters of current transmission channel.
13285 * \param demod   Pointer to demod instance.
13286 * \param channel Pointer to channel data.
13287 * \return int.
13288 */
13289 static int
13290 ctrl_get_channel(pdrx_demod_instance_t demod, pdrx_channel_t channel)
13291 {
13292         struct i2c_device_addr *dev_addr = NULL;
13293         pdrxj_data_t ext_attr = NULL;
13294         drx_lock_status_t lock_status = DRX_NOT_LOCKED;
13295         enum drx_standard standard = DRX_STANDARD_UNKNOWN;
13296         pdrx_common_attr_t common_attr = NULL;
13297         s32 intermediate_freq = 0;
13298         s32 ctl_freq_offset = 0;
13299         u32 iqm_rc_rateLo = 0;
13300         u32 adc_frequency = 0;
13301 #ifndef DRXJ_VSB_ONLY
13302         int bandwidth_temp = 0;
13303         int bandwidth = 0;
13304 #endif
13305
13306         /* check arguments */
13307         if ((demod == NULL) || (channel == NULL)) {
13308                 return DRX_STS_INVALID_ARG;
13309         }
13310
13311         dev_addr = demod->my_i2c_dev_addr;
13312         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
13313         standard = ext_attr->standard;
13314         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
13315
13316         /* initialize channel fields */
13317         channel->mirror = DRX_MIRROR_UNKNOWN;
13318         channel->hierarchy = DRX_HIERARCHY_UNKNOWN;
13319         channel->priority = DRX_PRIORITY_UNKNOWN;
13320         channel->coderate = DRX_CODERATE_UNKNOWN;
13321         channel->guard = DRX_GUARD_UNKNOWN;
13322         channel->fftmode = DRX_FFTMODE_UNKNOWN;
13323         channel->classification = DRX_CLASSIFICATION_UNKNOWN;
13324         channel->bandwidth = DRX_BANDWIDTH_UNKNOWN;
13325         channel->constellation = DRX_CONSTELLATION_UNKNOWN;
13326         channel->symbolrate = 0;
13327         channel->interleavemode = DRX_INTERLEAVEMODE_UNKNOWN;
13328         channel->carrier = DRX_CARRIER_UNKNOWN;
13329         channel->framemode = DRX_FRAMEMODE_UNKNOWN;
13330 /*   channel->interleaver       = DRX_INTERLEAVER_UNKNOWN;*/
13331         channel->ldpc = DRX_LDPC_UNKNOWN;
13332
13333         if (demod->my_tuner != NULL) {
13334                 s32 tuner_freq_offset = 0;
13335                 bool tuner_mirror = common_attr->mirror_freq_spect ? false : true;
13336
13337                 /* Get frequency from tuner */
13338                 CHK_ERROR(drxbsp_tuner_get_frequency(demod->my_tuner,
13339                                                     0,
13340                                                     &(channel->frequency),
13341                                                     &intermediate_freq));
13342                 tuner_freq_offset = channel->frequency - ext_attr->frequency;
13343                 if (tuner_mirror == true) {
13344                         /* positive image */
13345                         channel->frequency += tuner_freq_offset;
13346                 } else {
13347                         /* negative image */
13348                         channel->frequency -= tuner_freq_offset;
13349                 }
13350
13351                 /* Handle sound carrier offset in RF domain */
13352                 if (standard == DRX_STANDARD_FM) {
13353                         channel->frequency -= DRXJ_FM_CARRIER_FREQ_OFFSET;
13354                 }
13355         } else {
13356                 intermediate_freq = common_attr->intermediate_freq;
13357         }
13358
13359         /* check lock status */
13360         CHK_ERROR(ctrl_lock_status(demod, &lock_status));
13361         if ((lock_status == DRX_LOCKED) || (lock_status == DRXJ_DEMOD_LOCK)) {
13362                 ARR32(dev_addr, IQM_RC_RATE_LO__A, &iqm_rc_rateLo);
13363                 adc_frequency = (common_attr->sys_clock_freq * 1000) / 3;
13364
13365                 channel->symbolrate =
13366                     frac28(adc_frequency, (iqm_rc_rateLo + (1 << 23))) >> 7;
13367
13368                 switch (standard) {
13369                 case DRX_STANDARD_8VSB:
13370                         channel->bandwidth = DRX_BANDWIDTH_6MHZ;
13371                         /* get the channel frequency */
13372                         CHK_ERROR(get_ctl_freq_offset(demod, &ctl_freq_offset));
13373                         channel->frequency -= ctl_freq_offset;
13374                         /* get the channel constellation */
13375                         channel->constellation = DRX_CONSTELLATION_AUTO;
13376                         break;
13377 #ifndef DRXJ_VSB_ONLY
13378                 case DRX_STANDARD_ITU_A:
13379                 case DRX_STANDARD_ITU_B:
13380                 case DRX_STANDARD_ITU_C:
13381                         {
13382                                 /* get the channel frequency */
13383                                 CHK_ERROR(get_ctl_freq_offset
13384                                           (demod, &ctl_freq_offset));
13385                                 channel->frequency -= ctl_freq_offset;
13386
13387                                 if (standard == DRX_STANDARD_ITU_B) {
13388                                         channel->bandwidth = DRX_BANDWIDTH_6MHZ;
13389                                 } else {
13390                                         /* annex A & C */
13391
13392                                         u32 roll_off = 113;     /* default annex C */
13393
13394                                         if (standard == DRX_STANDARD_ITU_A) {
13395                                                 roll_off = 115;
13396                                         }
13397
13398                                         bandwidth_temp =
13399                                             channel->symbolrate * roll_off;
13400                                         bandwidth = bandwidth_temp / 100;
13401
13402                                         if ((bandwidth_temp % 100) >= 50) {
13403                                                 bandwidth++;
13404                                         }
13405
13406                                         if (bandwidth <= 6000000) {
13407                                                 channel->bandwidth =
13408                                                     DRX_BANDWIDTH_6MHZ;
13409                                         } else if ((bandwidth > 6000000)
13410                                                    && (bandwidth <= 7000000)) {
13411                                                 channel->bandwidth =
13412                                                     DRX_BANDWIDTH_7MHZ;
13413                                         } else if (bandwidth > 7000000) {
13414                                                 channel->bandwidth =
13415                                                     DRX_BANDWIDTH_8MHZ;
13416                                         }
13417                                 }       /* if (standard == DRX_STANDARD_ITU_B) */
13418
13419                                 {
13420                                         drxjscu_cmd_t cmd_scu =
13421                                             { /* command      */ 0,
13422                                                 /* parameter_len */ 0,
13423                                                 /* result_len    */ 0,
13424                                                 /* parameter    */ NULL,
13425                                                 /* result       */ NULL
13426                                         };
13427                                         u16 cmd_result[3] = { 0, 0, 0 };
13428
13429                                         cmd_scu.command =
13430                                             SCU_RAM_COMMAND_STANDARD_QAM |
13431                                             SCU_RAM_COMMAND_CMD_DEMOD_GET_PARAM;
13432                                         cmd_scu.parameter_len = 0;
13433                                         cmd_scu.result_len = 3;
13434                                         cmd_scu.parameter = NULL;
13435                                         cmd_scu.result = cmd_result;
13436                                         CHK_ERROR(scu_command(dev_addr, &cmd_scu));
13437
13438                                         channel->interleavemode =
13439                                             (enum drx_interleave_mode) (cmd_scu.
13440                                                                     result[2]);
13441                                 }
13442
13443                                 switch (ext_attr->constellation) {
13444                                 case DRX_CONSTELLATION_QAM256:
13445                                         channel->constellation =
13446                                             DRX_CONSTELLATION_QAM256;
13447                                         break;
13448                                 case DRX_CONSTELLATION_QAM128:
13449                                         channel->constellation =
13450                                             DRX_CONSTELLATION_QAM128;
13451                                         break;
13452                                 case DRX_CONSTELLATION_QAM64:
13453                                         channel->constellation =
13454                                             DRX_CONSTELLATION_QAM64;
13455                                         break;
13456                                 case DRX_CONSTELLATION_QAM32:
13457                                         channel->constellation =
13458                                             DRX_CONSTELLATION_QAM32;
13459                                         break;
13460                                 case DRX_CONSTELLATION_QAM16:
13461                                         channel->constellation =
13462                                             DRX_CONSTELLATION_QAM16;
13463                                         break;
13464                                 default:
13465                                         channel->constellation =
13466                                             DRX_CONSTELLATION_UNKNOWN;
13467                                         return (DRX_STS_ERROR);
13468                                 }
13469                         }
13470                         break;
13471 #endif
13472 #ifndef DRXJ_DIGITAL_ONLY
13473                 case DRX_STANDARD_NTSC: /* fall trough */
13474                 case DRX_STANDARD_PAL_SECAM_BG:
13475                 case DRX_STANDARD_PAL_SECAM_DK:
13476                 case DRX_STANDARD_PAL_SECAM_I:
13477                 case DRX_STANDARD_PAL_SECAM_L:
13478                 case DRX_STANDARD_PAL_SECAM_LP:
13479                 case DRX_STANDARD_FM:
13480                         CHK_ERROR(get_atv_channel(demod, channel, standard));
13481                         break;
13482 #endif
13483                 case DRX_STANDARD_UNKNOWN:      /* fall trough */
13484                 default:
13485                         return (DRX_STS_ERROR);
13486                 }               /* switch ( standard ) */
13487
13488                 if (lock_status == DRX_LOCKED) {
13489                         channel->mirror = ext_attr->mirror;
13490                 }
13491         }
13492         /* if ( lock_status == DRX_LOCKED ) */
13493         return (DRX_STS_OK);
13494 rw_error:
13495         return (DRX_STS_ERROR);
13496 }
13497
13498 /*=============================================================================
13499   ===== SigQuality() ==========================================================
13500   ===========================================================================*/
13501
13502 static u16
13503 mer2indicator(u16 mer, u16 min_mer, u16 threshold_mer, u16 max_mer)
13504 {
13505         u16 indicator = 0;
13506
13507         if (mer < min_mer) {
13508                 indicator = 0;
13509         } else if (mer < threshold_mer) {
13510                 if ((threshold_mer - min_mer) != 0) {
13511                         indicator =
13512                             25 * (mer - min_mer) / (threshold_mer - min_mer);
13513                 }
13514         } else if (mer < max_mer) {
13515                 if ((max_mer - threshold_mer) != 0) {
13516                         indicator =
13517                             25 + 75 * (mer - threshold_mer) / (max_mer -
13518                                                               threshold_mer);
13519                 } else {
13520                         indicator = 25;
13521                 }
13522         } else {
13523                 indicator = 100;
13524         }
13525
13526         return indicator;
13527 }
13528
13529 /**
13530 * \fn int ctrl_sig_quality()
13531 * \brief Retreive signal quality form device.
13532 * \param devmod Pointer to demodulator instance.
13533 * \param sig_quality Pointer to signal quality data.
13534 * \return int.
13535 * \retval DRX_STS_OK sig_quality contains valid data.
13536 * \retval DRX_STS_INVALID_ARG sig_quality is NULL.
13537 * \retval DRX_STS_ERROR Erroneous data, sig_quality contains invalid data.
13538
13539 */
13540 static int
13541 ctrl_sig_quality(pdrx_demod_instance_t demod, pdrx_sig_quality_t sig_quality)
13542 {
13543         struct i2c_device_addr *dev_addr = NULL;
13544         pdrxj_data_t ext_attr = NULL;
13545         enum drx_standard standard = DRX_STANDARD_UNKNOWN;
13546         drx_lock_status_t lock_status = DRX_NOT_LOCKED;
13547         u16 min_mer = 0;
13548         u16 max_mer = 0;
13549         u16 threshold_mer = 0;
13550
13551         /* Check arguments */
13552         if ((sig_quality == NULL) || (demod == NULL)) {
13553                 return (DRX_STS_INVALID_ARG);
13554         }
13555
13556         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
13557         standard = ext_attr->standard;
13558
13559         /* get basic information */
13560         dev_addr = demod->my_i2c_dev_addr;
13561         CHK_ERROR(ctrl_lock_status(demod, &lock_status));
13562         switch (standard) {
13563         case DRX_STANDARD_8VSB:
13564 #ifdef DRXJ_SIGNAL_ACCUM_ERR
13565                 CHK_ERROR(get_acc_pkt_err(demod, &sig_quality->packet_error));
13566 #else
13567                 CHK_ERROR(get_vsb_post_rs_pck_err
13568                           (dev_addr, &sig_quality->packet_error));
13569 #endif
13570                 if (lock_status != DRXJ_DEMOD_LOCK && lock_status != DRX_LOCKED) {
13571                         sig_quality->post_viterbi_ber = 500000;
13572                         sig_quality->MER = 20;
13573                         sig_quality->pre_viterbi_ber = 0;
13574                 } else {
13575                         /* PostViterbi is compute in steps of 10^(-6) */
13576                         CHK_ERROR(get_vs_bpre_viterbi_ber
13577                                   (dev_addr, &sig_quality->pre_viterbi_ber));
13578                         CHK_ERROR(get_vs_bpost_viterbi_ber
13579                                   (dev_addr, &sig_quality->post_viterbi_ber));
13580                         CHK_ERROR(get_vsbmer(dev_addr, &sig_quality->MER));
13581                 }
13582                 min_mer = 20;
13583                 max_mer = 360;
13584                 threshold_mer = 145;
13585                 sig_quality->post_reed_solomon_ber = 0;
13586                 sig_quality->scale_factor_ber = 1000000;
13587                 sig_quality->indicator =
13588                     mer2indicator(sig_quality->MER, min_mer, threshold_mer,
13589                                   max_mer);
13590                 break;
13591 #ifndef DRXJ_VSB_ONLY
13592         case DRX_STANDARD_ITU_A:
13593         case DRX_STANDARD_ITU_B:
13594         case DRX_STANDARD_ITU_C:
13595                 CHK_ERROR(ctrl_get_qam_sig_quality(demod, sig_quality));
13596                 if (lock_status != DRXJ_DEMOD_LOCK && lock_status != DRX_LOCKED) {
13597                         switch (ext_attr->constellation) {
13598                         case DRX_CONSTELLATION_QAM256:
13599                                 sig_quality->MER = 210;
13600                                 break;
13601                         case DRX_CONSTELLATION_QAM128:
13602                                 sig_quality->MER = 180;
13603                                 break;
13604                         case DRX_CONSTELLATION_QAM64:
13605                                 sig_quality->MER = 150;
13606                                 break;
13607                         case DRX_CONSTELLATION_QAM32:
13608                                 sig_quality->MER = 120;
13609                                 break;
13610                         case DRX_CONSTELLATION_QAM16:
13611                                 sig_quality->MER = 90;
13612                                 break;
13613                         default:
13614                                 sig_quality->MER = 0;
13615                                 return (DRX_STS_ERROR);
13616                         }
13617                 }
13618
13619                 switch (ext_attr->constellation) {
13620                 case DRX_CONSTELLATION_QAM256:
13621                         min_mer = 210;
13622                         threshold_mer = 270;
13623                         max_mer = 380;
13624                         break;
13625                 case DRX_CONSTELLATION_QAM64:
13626                         min_mer = 150;
13627                         threshold_mer = 210;
13628                         max_mer = 380;
13629                         break;
13630                 case DRX_CONSTELLATION_QAM128:
13631                 case DRX_CONSTELLATION_QAM32:
13632                 case DRX_CONSTELLATION_QAM16:
13633                         break;
13634                 default:
13635                         return (DRX_STS_ERROR);
13636                 }
13637                 sig_quality->indicator =
13638                     mer2indicator(sig_quality->MER, min_mer, threshold_mer,
13639                                   max_mer);
13640                 break;
13641 #endif
13642 #ifndef DRXJ_DIGITAL_ONLY
13643         case DRX_STANDARD_PAL_SECAM_BG:
13644         case DRX_STANDARD_PAL_SECAM_DK:
13645         case DRX_STANDARD_PAL_SECAM_I:
13646         case DRX_STANDARD_PAL_SECAM_L:
13647         case DRX_STANDARD_PAL_SECAM_LP:
13648         case DRX_STANDARD_NTSC:
13649                 CHK_ERROR(atv_sig_quality(demod, sig_quality));
13650                 break;
13651         case DRX_STANDARD_FM:
13652                 CHK_ERROR(fm_sig_quality(demod, sig_quality));
13653                 break;
13654 #endif
13655         default:
13656                 return (DRX_STS_ERROR);
13657         }
13658
13659         return (DRX_STS_OK);
13660 rw_error:
13661         return (DRX_STS_ERROR);
13662 }
13663
13664 /*============================================================================*/
13665
13666 /**
13667 * \fn int ctrl_lock_status()
13668 * \brief Retreive lock status .
13669 * \param dev_addr Pointer to demodulator device address.
13670 * \param lock_stat Pointer to lock status structure.
13671 * \return int.
13672 *
13673 */
13674 static int
13675 ctrl_lock_status(pdrx_demod_instance_t demod, pdrx_lock_status_t lock_stat)
13676 {
13677         enum drx_standard standard = DRX_STANDARD_UNKNOWN;
13678         pdrxj_data_t ext_attr = NULL;
13679         struct i2c_device_addr *dev_addr = NULL;
13680         drxjscu_cmd_t cmd_scu = { /* command      */ 0,
13681                 /* parameter_len */ 0,
13682                 /* result_len    */ 0,
13683                 /* *parameter   */ NULL,
13684                 /* *result      */ NULL
13685         };
13686         u16 cmd_result[2] = { 0, 0 };
13687         u16 demod_lock = SCU_RAM_PARAM_1_RES_DEMOD_GET_LOCK_DEMOD_LOCKED;
13688
13689         /* check arguments */
13690         if ((demod == NULL) || (lock_stat == NULL)) {
13691                 return (DRX_STS_INVALID_ARG);
13692         }
13693
13694         dev_addr = demod->my_i2c_dev_addr;
13695         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
13696         standard = ext_attr->standard;
13697
13698         *lock_stat = DRX_NOT_LOCKED;
13699
13700         /* define the SCU command code */
13701         switch (standard) {
13702         case DRX_STANDARD_8VSB:
13703                 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB |
13704                     SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK;
13705                 demod_lock |= 0x6;
13706                 break;
13707 #ifndef DRXJ_VSB_ONLY
13708         case DRX_STANDARD_ITU_A:
13709         case DRX_STANDARD_ITU_B:
13710         case DRX_STANDARD_ITU_C:
13711                 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
13712                     SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK;
13713                 break;
13714 #endif
13715 #ifndef DRXJ_DIGITAL_ONLY
13716         case DRX_STANDARD_NTSC:
13717         case DRX_STANDARD_PAL_SECAM_BG:
13718         case DRX_STANDARD_PAL_SECAM_DK:
13719         case DRX_STANDARD_PAL_SECAM_I:
13720         case DRX_STANDARD_PAL_SECAM_L:
13721         case DRX_STANDARD_PAL_SECAM_LP:
13722                 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_ATV |
13723                     SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK;
13724                 break;
13725         case DRX_STANDARD_FM:
13726                 return fm_lock_status(demod, lock_stat);
13727 #endif
13728         case DRX_STANDARD_UNKNOWN:      /* fallthrough */
13729         default:
13730                 return (DRX_STS_ERROR);
13731         }
13732
13733         /* define the SCU command paramters and execute the command */
13734         cmd_scu.parameter_len = 0;
13735         cmd_scu.result_len = 2;
13736         cmd_scu.parameter = NULL;
13737         cmd_scu.result = cmd_result;
13738         CHK_ERROR(scu_command(dev_addr, &cmd_scu));
13739
13740         /* set the lock status */
13741         if (cmd_scu.result[1] < demod_lock) {
13742                 /* 0x0000 NOT LOCKED */
13743                 *lock_stat = DRX_NOT_LOCKED;
13744         } else if (cmd_scu.result[1] < SCU_RAM_PARAM_1_RES_DEMOD_GET_LOCK_LOCKED) {
13745                 *lock_stat = DRXJ_DEMOD_LOCK;
13746         } else if (cmd_scu.result[1] <
13747                    SCU_RAM_PARAM_1_RES_DEMOD_GET_LOCK_NEVER_LOCK) {
13748                 /* 0x8000 DEMOD + FEC LOCKED (system lock) */
13749                 *lock_stat = DRX_LOCKED;
13750         } else {
13751                 /* 0xC000 NEVER LOCKED */
13752                 /* (system will never be able to lock to the signal) */
13753                 *lock_stat = DRX_NEVER_LOCK;
13754         }
13755
13756         return (DRX_STS_OK);
13757 rw_error:
13758         return (DRX_STS_ERROR);
13759 }
13760
13761 /*============================================================================*/
13762
13763 /**
13764 * \fn int ctrl_constel()
13765 * \brief Retreive a constellation point via I2C.
13766 * \param demod Pointer to demodulator instance.
13767 * \param complex_nr Pointer to the structure in which to store the
13768                    constellation point.
13769 * \return int.
13770 */
13771 static int
13772 ctrl_constel(pdrx_demod_instance_t demod, pdrx_complex_t complex_nr)
13773 {
13774         enum drx_standard standard = DRX_STANDARD_UNKNOWN;
13775                                                      /**< active standard */
13776
13777         /* check arguments */
13778         if ((demod == NULL) || (complex_nr == NULL)) {
13779                 return (DRX_STS_INVALID_ARG);
13780         }
13781
13782         /* read device info */
13783         standard = ((pdrxj_data_t) demod->my_ext_attr)->standard;
13784
13785         /* Read constellation point  */
13786         switch (standard) {
13787         case DRX_STANDARD_8VSB:
13788                 CHK_ERROR(ctrl_get_vsb_constel(demod, complex_nr));
13789                 break;
13790 #ifndef DRXJ_VSB_ONLY
13791         case DRX_STANDARD_ITU_A:        /* fallthrough */
13792         case DRX_STANDARD_ITU_B:        /* fallthrough */
13793         case DRX_STANDARD_ITU_C:
13794                 CHK_ERROR(ctrl_get_qam_constel(demod, complex_nr));
13795                 break;
13796 #endif
13797         case DRX_STANDARD_UNKNOWN:
13798         default:
13799                 return (DRX_STS_ERROR);
13800         }
13801
13802         return (DRX_STS_OK);
13803 rw_error:
13804         return (DRX_STS_ERROR);
13805 }
13806
13807 /*============================================================================*/
13808
13809 /**
13810 * \fn int ctrl_set_standard()
13811 * \brief Set modulation standard to be used.
13812 * \param standard Modulation standard.
13813 * \return int.
13814 *
13815 * Setup stuff for the desired demodulation standard.
13816 * Disable and power down the previous selected demodulation standard
13817 *
13818 */
13819 static int
13820 ctrl_set_standard(pdrx_demod_instance_t demod, enum drx_standard *standard)
13821 {
13822         pdrxj_data_t ext_attr = NULL;
13823         enum drx_standard prev_standard;
13824
13825         /* check arguments */
13826         if ((standard == NULL) || (demod == NULL)) {
13827                 return (DRX_STS_INVALID_ARG);
13828         }
13829
13830         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
13831         prev_standard = ext_attr->standard;
13832
13833         /*
13834            Stop and power down previous standard
13835          */
13836         switch (prev_standard) {
13837 #ifndef DRXJ_VSB_ONLY
13838         case DRX_STANDARD_ITU_A:        /* fallthrough */
13839         case DRX_STANDARD_ITU_B:        /* fallthrough */
13840         case DRX_STANDARD_ITU_C:
13841                 CHK_ERROR(power_down_qam(demod, false));
13842                 break;
13843 #endif
13844         case DRX_STANDARD_8VSB:
13845                 CHK_ERROR(power_down_vsb(demod, false));
13846                 break;
13847 #ifndef DRXJ_DIGITAL_ONLY
13848         case DRX_STANDARD_NTSC: /* fallthrough */
13849         case DRX_STANDARD_FM:   /* fallthrough */
13850         case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
13851         case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
13852         case DRX_STANDARD_PAL_SECAM_I:  /* fallthrough */
13853         case DRX_STANDARD_PAL_SECAM_L:  /* fallthrough */
13854         case DRX_STANDARD_PAL_SECAM_LP:
13855                 CHK_ERROR(power_down_atv(demod, prev_standard, false));
13856                 break;
13857 #endif
13858         case DRX_STANDARD_UNKNOWN:
13859                 /* Do nothing */
13860                 break;
13861         case DRX_STANDARD_AUTO: /* fallthrough */
13862         default:
13863                 return (DRX_STS_INVALID_ARG);
13864         }
13865
13866         /*
13867            Initialize channel independent registers
13868            Power up new standard
13869          */
13870         ext_attr->standard = *standard;
13871
13872         switch (*standard) {
13873 #ifndef DRXJ_VSB_ONLY
13874         case DRX_STANDARD_ITU_A:        /* fallthrough */
13875         case DRX_STANDARD_ITU_B:        /* fallthrough */
13876         case DRX_STANDARD_ITU_C:
13877                 DUMMY_READ();
13878                 break;
13879 #endif
13880         case DRX_STANDARD_8VSB:
13881                 CHK_ERROR(set_vsb_leak_n_gain(demod));
13882                 break;
13883 #ifndef DRXJ_DIGITAL_ONLY
13884         case DRX_STANDARD_NTSC: /* fallthrough */
13885         case DRX_STANDARD_FM:   /* fallthrough */
13886         case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
13887         case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
13888         case DRX_STANDARD_PAL_SECAM_I:  /* fallthrough */
13889         case DRX_STANDARD_PAL_SECAM_L:  /* fallthrough */
13890         case DRX_STANDARD_PAL_SECAM_LP:
13891                 CHK_ERROR(set_atv_standard(demod, standard));
13892                 CHK_ERROR(power_up_atv(demod, *standard));
13893                 break;
13894 #endif
13895         default:
13896                 ext_attr->standard = DRX_STANDARD_UNKNOWN;
13897                 return (DRX_STS_INVALID_ARG);
13898                 break;
13899         }
13900
13901         return (DRX_STS_OK);
13902 rw_error:
13903         /* Don't know what the standard is now ... try again */
13904         ext_attr->standard = DRX_STANDARD_UNKNOWN;
13905         return (DRX_STS_ERROR);
13906 }
13907
13908 /*============================================================================*/
13909
13910 /**
13911 * \fn int ctrl_get_standard()
13912 * \brief Get modulation standard currently used to demodulate.
13913 * \param standard Modulation standard.
13914 * \return int.
13915 *
13916 * Returns 8VSB, NTSC, QAM only.
13917 *
13918 */
13919 static int
13920 ctrl_get_standard(pdrx_demod_instance_t demod, enum drx_standard *standard)
13921 {
13922         pdrxj_data_t ext_attr = NULL;
13923         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
13924
13925         /* check arguments */
13926         if (standard == NULL) {
13927                 return (DRX_STS_INVALID_ARG);
13928         }
13929         (*standard) = ext_attr->standard;
13930         DUMMY_READ();
13931
13932         return (DRX_STS_OK);
13933 rw_error:
13934         return (DRX_STS_ERROR);
13935 }
13936
13937 /*============================================================================*/
13938
13939 /**
13940 * \fn int ctrl_get_cfg_symbol_clock_offset()
13941 * \brief Get frequency offsets of STR.
13942 * \param pointer to s32.
13943 * \return int.
13944 *
13945 */
13946 static int
13947 ctrl_get_cfg_symbol_clock_offset(pdrx_demod_instance_t demod, s32 *rate_offset)
13948 {
13949         enum drx_standard standard = DRX_STANDARD_UNKNOWN;
13950         struct i2c_device_addr *dev_addr = NULL;
13951         pdrxj_data_t ext_attr = NULL;
13952
13953         /* check arguments */
13954         if (rate_offset == NULL) {
13955                 return (DRX_STS_INVALID_ARG);
13956         }
13957
13958         dev_addr = demod->my_i2c_dev_addr;
13959         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
13960         standard = ext_attr->standard;
13961
13962         switch (standard) {
13963         case DRX_STANDARD_8VSB: /* fallthrough */
13964 #ifndef DRXJ_VSB_ONLY
13965         case DRX_STANDARD_ITU_A:        /* fallthrough */
13966         case DRX_STANDARD_ITU_B:        /* fallthrough */
13967         case DRX_STANDARD_ITU_C:
13968 #endif
13969                 CHK_ERROR(get_str_freq_offset(demod, rate_offset));
13970                 break;
13971         case DRX_STANDARD_NTSC:
13972         case DRX_STANDARD_UNKNOWN:
13973         default:
13974                 return (DRX_STS_INVALID_ARG);
13975         }
13976
13977         return (DRX_STS_OK);
13978 rw_error:
13979         return (DRX_STS_ERROR);
13980 }
13981
13982 /*============================================================================*/
13983
13984 /**
13985 * \fn int ctrl_power_mode()
13986 * \brief Set the power mode of the device to the specified power mode
13987 * \param demod Pointer to demodulator instance.
13988 * \param mode  Pointer to new power mode.
13989 * \return int.
13990 * \retval DRX_STS_OK          Success
13991 * \retval DRX_STS_ERROR       I2C error or other failure
13992 * \retval DRX_STS_INVALID_ARG Invalid mode argument.
13993 *
13994 *
13995 */
13996 static int
13997 ctrl_power_mode(pdrx_demod_instance_t demod, pdrx_power_mode_t mode)
13998 {
13999         pdrx_common_attr_t common_attr = (pdrx_common_attr_t) NULL;
14000         pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
14001         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
14002         u16 sio_cc_pwd_mode = 0;
14003
14004         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
14005         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
14006         dev_addr = demod->my_i2c_dev_addr;
14007
14008         /* Check arguments */
14009         if (mode == NULL) {
14010                 return (DRX_STS_INVALID_ARG);
14011         }
14012
14013         /* If already in requested power mode, do nothing */
14014         if (common_attr->current_power_mode == *mode) {
14015                 return (DRX_STS_OK);
14016         }
14017
14018         switch (*mode) {
14019         case DRX_POWER_UP:
14020         case DRXJ_POWER_DOWN_MAIN_PATH:
14021                 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_NONE;
14022                 break;
14023         case DRXJ_POWER_DOWN_CORE:
14024                 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_CLOCK;
14025                 break;
14026         case DRXJ_POWER_DOWN_PLL:
14027                 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_PLL;
14028                 break;
14029         case DRX_POWER_DOWN:
14030                 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC;
14031                 break;
14032         default:
14033                 /* Unknow sleep mode */
14034                 return (DRX_STS_INVALID_ARG);
14035                 break;
14036         }
14037
14038         /* Check if device needs to be powered up */
14039         if ((common_attr->current_power_mode != DRX_POWER_UP)) {
14040                 CHK_ERROR(power_up_device(demod));
14041         }
14042
14043         if ((*mode == DRX_POWER_UP)) {
14044                 /* Restore analog & pin configuartion */
14045         } else {
14046                 /* Power down to requested mode */
14047                 /* Backup some register settings */
14048                 /* Set pins with possible pull-ups connected to them in input mode */
14049                 /* Analog power down */
14050                 /* ADC power down */
14051                 /* Power down device */
14052                 /* stop all comm_exec */
14053                 /*
14054                    Stop and power down previous standard
14055                  */
14056
14057                 switch (ext_attr->standard) {
14058                 case DRX_STANDARD_ITU_A:
14059                 case DRX_STANDARD_ITU_B:
14060                 case DRX_STANDARD_ITU_C:
14061                         CHK_ERROR(power_down_qam(demod, true));
14062                         break;
14063                 case DRX_STANDARD_8VSB:
14064                         CHK_ERROR(power_down_vsb(demod, true));
14065                         break;
14066                 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
14067                 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
14068                 case DRX_STANDARD_PAL_SECAM_I:  /* fallthrough */
14069                 case DRX_STANDARD_PAL_SECAM_L:  /* fallthrough */
14070                 case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
14071                 case DRX_STANDARD_NTSC: /* fallthrough */
14072                 case DRX_STANDARD_FM:
14073                         CHK_ERROR(power_down_atv(demod, ext_attr->standard, true));
14074                         break;
14075                 case DRX_STANDARD_UNKNOWN:
14076                         /* Do nothing */
14077                         break;
14078                 case DRX_STANDARD_AUTO: /* fallthrough */
14079                 default:
14080                         return (DRX_STS_ERROR);
14081                 }
14082
14083                 if (*mode != DRXJ_POWER_DOWN_MAIN_PATH) {
14084                         WR16(dev_addr, SIO_CC_PWD_MODE__A, sio_cc_pwd_mode);
14085                         WR16(dev_addr, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
14086
14087                         /* Initialize HI, wakeup key especially before put IC to sleep */
14088                         CHK_ERROR(init_hi(demod));
14089
14090                         ext_attr->hi_cfg_ctrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
14091                         CHK_ERROR(hi_cfg_command(demod));
14092                 }
14093         }
14094
14095         common_attr->current_power_mode = *mode;
14096
14097         return (DRX_STS_OK);
14098 rw_error:
14099         return (DRX_STS_ERROR);
14100 }
14101
14102 /*============================================================================*/
14103
14104 /**
14105 * \fn int ctrl_version()
14106 * \brief Report version of microcode and if possible version of device
14107 * \param demod Pointer to demodulator instance.
14108 * \param version_list Pointer to pointer of linked list of versions.
14109 * \return int.
14110 *
14111 * Using static structures so no allocation of memory is needed.
14112 * Filling in all the fields each time, cause you don't know if they are
14113 * changed by the application.
14114 *
14115 * For device:
14116 * Major version number will be last two digits of family number.
14117 * Minor number will be full respin number
14118 * Patch will be metal fix number+1
14119 * Examples:
14120 * DRX3942J A2 => number: 42.1.2 text: "DRX3942J:A2"
14121 * DRX3933J B1 => number: 33.2.1 text: "DRX3933J:B1"
14122 *
14123 */
14124 static int
14125 ctrl_version(pdrx_demod_instance_t demod, p_drx_version_list_t *version_list)
14126 {
14127         pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
14128         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) (NULL);
14129         pdrx_common_attr_t common_attr = (pdrx_common_attr_t) (NULL);
14130         u16 ucode_major_minor = 0;      /* BCD Ma:Ma:Ma:Mi */
14131         u16 ucode_patch = 0;    /* BCD Pa:Pa:Pa:Pa */
14132         u16 major = 0;
14133         u16 minor = 0;
14134         u16 patch = 0;
14135         u16 idx = 0;
14136         u32 jtag = 0;
14137         u16 subtype = 0;
14138         u16 mfx = 0;
14139         u16 bid = 0;
14140         u16 key = 0;
14141
14142         static char ucode_name[] = "Microcode";
14143         static char device_name[] = "Device";
14144
14145         dev_addr = demod->my_i2c_dev_addr;
14146         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
14147         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
14148
14149         /* Microcode version *************************************** */
14150
14151         ext_attr->v_version[0].module_type = DRX_MODULE_MICROCODE;
14152         ext_attr->v_version[0].module_name = ucode_name;
14153         ext_attr->v_version[0].v_string = ext_attr->v_text[0];
14154
14155         if (common_attr->is_opened == true) {
14156                 SARR16(dev_addr, SCU_RAM_VERSION_HI__A, &ucode_major_minor);
14157                 SARR16(dev_addr, SCU_RAM_VERSION_LO__A, &ucode_patch);
14158
14159                 /* Translate BCD to numbers and string */
14160                 /* TODO: The most significant Ma and Pa will be ignored, check with spec */
14161                 minor = (ucode_major_minor & 0xF);
14162                 ucode_major_minor >>= 4;
14163                 major = (ucode_major_minor & 0xF);
14164                 ucode_major_minor >>= 4;
14165                 major += (10 * (ucode_major_minor & 0xF));
14166                 patch = (ucode_patch & 0xF);
14167                 ucode_patch >>= 4;
14168                 patch += (10 * (ucode_patch & 0xF));
14169                 ucode_patch >>= 4;
14170                 patch += (100 * (ucode_patch & 0xF));
14171         } else {
14172                 /* No microcode uploaded, No Rom existed, set version to 0.0.0 */
14173                 patch = 0;
14174                 minor = 0;
14175                 major = 0;
14176         }
14177         ext_attr->v_version[0].v_major = major;
14178         ext_attr->v_version[0].v_minor = minor;
14179         ext_attr->v_version[0].v_patch = patch;
14180
14181         if (major / 10 != 0) {
14182                 ext_attr->v_version[0].v_string[idx++] =
14183                     ((char)(major / 10)) + '0';
14184                 major %= 10;
14185         }
14186         ext_attr->v_version[0].v_string[idx++] = ((char)major) + '0';
14187         ext_attr->v_version[0].v_string[idx++] = '.';
14188         ext_attr->v_version[0].v_string[idx++] = ((char)minor) + '0';
14189         ext_attr->v_version[0].v_string[idx++] = '.';
14190         if (patch / 100 != 0) {
14191                 ext_attr->v_version[0].v_string[idx++] =
14192                     ((char)(patch / 100)) + '0';
14193                 patch %= 100;
14194         }
14195         if (patch / 10 != 0) {
14196                 ext_attr->v_version[0].v_string[idx++] =
14197                     ((char)(patch / 10)) + '0';
14198                 patch %= 10;
14199         }
14200         ext_attr->v_version[0].v_string[idx++] = ((char)patch) + '0';
14201         ext_attr->v_version[0].v_string[idx] = '\0';
14202
14203         ext_attr->v_list_elements[0].version = &(ext_attr->v_version[0]);
14204         ext_attr->v_list_elements[0].next = &(ext_attr->v_list_elements[1]);
14205
14206         /* Device version *************************************** */
14207         /* Check device id */
14208         RR16(dev_addr, SIO_TOP_COMM_KEY__A, &key);
14209         WR16(dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA);
14210         RR32(dev_addr, SIO_TOP_JTAGID_LO__A, &jtag);
14211         RR16(dev_addr, SIO_PDR_UIO_IN_HI__A, &bid);
14212         WR16(dev_addr, SIO_TOP_COMM_KEY__A, key);
14213
14214         ext_attr->v_version[1].module_type = DRX_MODULE_DEVICE;
14215         ext_attr->v_version[1].module_name = device_name;
14216         ext_attr->v_version[1].v_string = ext_attr->v_text[1];
14217         ext_attr->v_version[1].v_string[0] = 'D';
14218         ext_attr->v_version[1].v_string[1] = 'R';
14219         ext_attr->v_version[1].v_string[2] = 'X';
14220         ext_attr->v_version[1].v_string[3] = '3';
14221         ext_attr->v_version[1].v_string[4] = '9';
14222         ext_attr->v_version[1].v_string[7] = 'J';
14223         ext_attr->v_version[1].v_string[8] = ':';
14224         ext_attr->v_version[1].v_string[11] = '\0';
14225
14226         /* DRX39xxJ type Ax */
14227         /* TODO semantics of mfx and spin are unclear */
14228         subtype = (u16) ((jtag >> 12) & 0xFF);
14229         mfx = (u16) (jtag >> 29);
14230         ext_attr->v_version[1].v_minor = 1;
14231         if (mfx == 0x03) {
14232                 ext_attr->v_version[1].v_patch = mfx + 2;
14233         } else {
14234                 ext_attr->v_version[1].v_patch = mfx + 1;
14235         }
14236         ext_attr->v_version[1].v_string[6] = ((char)(subtype & 0xF)) + '0';
14237         ext_attr->v_version[1].v_major = (subtype & 0x0F);
14238         subtype >>= 4;
14239         ext_attr->v_version[1].v_string[5] = ((char)(subtype & 0xF)) + '0';
14240         ext_attr->v_version[1].v_major += 10 * subtype;
14241         ext_attr->v_version[1].v_string[9] = 'A';
14242         if (mfx == 0x03) {
14243                 ext_attr->v_version[1].v_string[10] = ((char)(mfx & 0xF)) + '2';
14244         } else {
14245                 ext_attr->v_version[1].v_string[10] = ((char)(mfx & 0xF)) + '1';
14246         }
14247
14248         ext_attr->v_list_elements[1].version = &(ext_attr->v_version[1]);
14249         ext_attr->v_list_elements[1].next = (p_drx_version_list_t) (NULL);
14250
14251         *version_list = &(ext_attr->v_list_elements[0]);
14252
14253         return (DRX_STS_OK);
14254
14255 rw_error:
14256         *version_list = (p_drx_version_list_t) (NULL);
14257         return (DRX_STS_ERROR);
14258
14259 }
14260
14261 /*============================================================================*/
14262
14263 /**
14264 * \fn int ctrl_probe_device()
14265 * \brief Probe device, check if it is present
14266 * \param demod Pointer to demodulator instance.
14267 * \return int.
14268 * \retval DRX_STS_OK    a drx39xxj device has been detected.
14269 * \retval DRX_STS_ERROR no drx39xxj device detected.
14270 *
14271 * This funtion can be caled before open() and after close().
14272 *
14273 */
14274
14275 static int ctrl_probe_device(pdrx_demod_instance_t demod)
14276 {
14277         drx_power_mode_t org_power_mode = DRX_POWER_UP;
14278         int ret_status = DRX_STS_OK;
14279         pdrx_common_attr_t common_attr = (pdrx_common_attr_t) (NULL);
14280
14281         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
14282
14283         if (common_attr->is_opened == false
14284             || common_attr->current_power_mode != DRX_POWER_UP) {
14285                 struct i2c_device_addr *dev_addr = NULL;
14286                 drx_power_mode_t power_mode = DRX_POWER_UP;
14287                 u32 jtag = 0;
14288
14289                 dev_addr = demod->my_i2c_dev_addr;
14290
14291                 /* Remeber original power mode */
14292                 org_power_mode = common_attr->current_power_mode;
14293
14294                 if (demod->my_common_attr->is_opened == false) {
14295                         CHK_ERROR(power_up_device(demod));
14296                         common_attr->current_power_mode = DRX_POWER_UP;
14297                 } else {
14298                         /* Wake-up device, feedback from device */
14299                         CHK_ERROR(ctrl_power_mode(demod, &power_mode));
14300                 }
14301                 /* Initialize HI, wakeup key especially */
14302                 CHK_ERROR(init_hi(demod));
14303
14304                 /* Check device id */
14305                 RR32(dev_addr, SIO_TOP_JTAGID_LO__A, &jtag);
14306                 jtag = (jtag >> 12) & 0xFFFF;
14307                 switch (jtag) {
14308                 case 0x3931:    /* fallthrough */
14309                 case 0x3932:    /* fallthrough */
14310                 case 0x3933:    /* fallthrough */
14311                 case 0x3934:    /* fallthrough */
14312                 case 0x3941:    /* fallthrough */
14313                 case 0x3942:    /* fallthrough */
14314                 case 0x3943:    /* fallthrough */
14315                 case 0x3944:    /* fallthrough */
14316                 case 0x3945:    /* fallthrough */
14317                 case 0x3946:
14318                         /* ok , do nothing */
14319                         break;
14320                 default:
14321                         ret_status = DRX_STS_ERROR;
14322                         break;
14323                 }
14324
14325                 /* Device was not opened, return to orginal powermode,
14326                    feedback from device */
14327                 CHK_ERROR(ctrl_power_mode(demod, &org_power_mode));
14328         } else {
14329                 /* dummy read to make this function fail in case device
14330                    suddenly disappears after a succesful drx_open */
14331                 DUMMY_READ();
14332         }
14333
14334         return (ret_status);
14335
14336 rw_error:
14337         common_attr->current_power_mode = org_power_mode;
14338         return (DRX_STS_ERROR);
14339 }
14340
14341 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
14342 /*============================================================================*/
14343
14344 /**
14345 * \fn int is_mc_block_audio()
14346 * \brief Check if MC block is Audio or not Audio.
14347 * \param addr        Pointer to demodulator instance.
14348 * \param audioUpload true  if MC block is Audio
14349                      false if MC block not Audio
14350 * \return bool.
14351 */
14352 bool is_mc_block_audio(u32 addr)
14353 {
14354         if ((addr == AUD_XFP_PRAM_4K__A) || (addr == AUD_XDFP_PRAM_4K__A)) {
14355                 return (true);
14356         }
14357         return (false);
14358 }
14359
14360 /*============================================================================*/
14361
14362 /**
14363 * \fn int ctrl_u_codeUpload()
14364 * \brief Handle Audio or !Audio part of microcode upload.
14365 * \param demod          Pointer to demodulator instance.
14366 * \param mc_info         Pointer to information about microcode data.
14367 * \param action         Either UCODE_UPLOAD or UCODE_VERIFY.
14368 * \param upload_audio_mc  true  if Audio MC need to be uploaded.
14369                         false if !Audio MC need to be uploaded.
14370 * \return int.
14371 */
14372 static int
14373 ctrl_u_codeUpload(pdrx_demod_instance_t demod,
14374                 p_drxu_code_info_t mc_info,
14375                 drxu_code_action_t action, bool upload_audio_mc)
14376 {
14377         u16 i = 0;
14378         u16 mc_nr_of_blks = 0;
14379         u16 mc_magic_word = 0;
14380         u8 *mc_data = (u8 *) (NULL);
14381         struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) (NULL);
14382         pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
14383
14384         dev_addr = demod->my_i2c_dev_addr;
14385         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
14386
14387         /* Check arguments */
14388         if ((mc_info == NULL) ||
14389             (mc_info->mc_data == NULL) || (mc_info->mc_size == 0)) {
14390                 return DRX_STS_INVALID_ARG;
14391         }
14392
14393         mc_data = mc_info->mc_data;
14394
14395         /* Check data */
14396         mc_magic_word = u_code_read16(mc_data);
14397         mc_data += sizeof(u16);
14398         mc_nr_of_blks = u_code_read16(mc_data);
14399         mc_data += sizeof(u16);
14400
14401         if ((mc_magic_word != DRXJ_UCODE_MAGIC_WORD) || (mc_nr_of_blks == 0)) {
14402                 /* wrong endianess or wrong data ? */
14403                 return DRX_STS_INVALID_ARG;
14404         }
14405
14406         /* Process microcode blocks */
14407         for (i = 0; i < mc_nr_of_blks; i++) {
14408                 drxu_code_block_hdr_t block_hdr;
14409                 u16 mc_block_nr_bytes = 0;
14410
14411                 /* Process block header */
14412                 block_hdr.addr = u_code_read32(mc_data);
14413                 mc_data += sizeof(u32);
14414                 block_hdr.size = u_code_read16(mc_data);
14415                 mc_data += sizeof(u16);
14416                 block_hdr.flags = u_code_read16(mc_data);
14417                 mc_data += sizeof(u16);
14418                 block_hdr.CRC = u_code_read16(mc_data);
14419                 mc_data += sizeof(u16);
14420
14421                 /* Check block header on:
14422                    - no data
14423                    - data larger then 64Kb
14424                    - if CRC enabled check CRC
14425                  */
14426                 if ((block_hdr.size == 0) ||
14427                     (block_hdr.size > 0x7FFF) ||
14428                     (((block_hdr.flags & DRXJ_UCODE_CRC_FLAG) != 0) &&
14429                      (block_hdr.CRC != u_code_compute_crc(mc_data, block_hdr.size)))
14430                     ) {
14431                         /* Wrong data ! */
14432                         return DRX_STS_INVALID_ARG;
14433                 }
14434
14435                 mc_block_nr_bytes = block_hdr.size * sizeof(u16);
14436
14437                 /* Perform the desired action */
14438                 /* Check which part of MC need to be uploaded - Audio or not Audio */
14439                 if (is_mc_block_audio(block_hdr.addr) == upload_audio_mc) {
14440                         switch (action) {
14441             /*===================================================================*/
14442                         case UCODE_UPLOAD:
14443                                 {
14444                                         /* Upload microcode */
14445                                         if (demod->my_access_funct->
14446                                             write_block_func(dev_addr,
14447                                                            (dr_xaddr_t) block_hdr.
14448                                                            addr, mc_block_nr_bytes,
14449                                                            mc_data,
14450                                                            0x0000) !=
14451                                             DRX_STS_OK) {
14452                                                 return (DRX_STS_ERROR);
14453                                         }
14454                                 };
14455                                 break;
14456
14457             /*===================================================================*/
14458                         case UCODE_VERIFY:
14459                                 {
14460                                         int result = 0;
14461                                         u8 mc_dataBuffer
14462                                             [DRXJ_UCODE_MAX_BUF_SIZE];
14463                                         u32 bytes_to_compare = 0;
14464                                         u32 bytes_left_to_compare = 0;
14465                                         dr_xaddr_t curr_addr = (dr_xaddr_t) 0;
14466                                         u8 *curr_ptr = NULL;
14467
14468                                         bytes_left_to_compare = mc_block_nr_bytes;
14469                                         curr_addr = block_hdr.addr;
14470                                         curr_ptr = mc_data;
14471
14472                                         while (bytes_left_to_compare != 0) {
14473                                                 if (bytes_left_to_compare >
14474                                                     ((u32)
14475                                                      DRXJ_UCODE_MAX_BUF_SIZE)) {
14476                                                         bytes_to_compare =
14477                                                             ((u32)
14478                                                              DRXJ_UCODE_MAX_BUF_SIZE);
14479                                                 } else {
14480                                                         bytes_to_compare =
14481                                                             bytes_left_to_compare;
14482                                                 }
14483
14484                                                 if (demod->my_access_funct->
14485                                                     read_block_func(dev_addr,
14486                                                                   curr_addr,
14487                                                                   (u16)
14488                                                                   bytes_to_compare,
14489                                                                   (u8 *)
14490                                                                   mc_dataBuffer,
14491                                                                   0x0000) !=
14492                                                     DRX_STS_OK) {
14493                                                         return (DRX_STS_ERROR);
14494                                                 }
14495
14496                                                 result =
14497                                                     drxbsp_hst_memcmp(curr_ptr,
14498                                                                       mc_dataBuffer,
14499                                                                       bytes_to_compare);
14500
14501                                                 if (result != 0) {
14502                                                         return (DRX_STS_ERROR);
14503                                                 };
14504
14505                                                 curr_addr +=
14506                                                     ((dr_xaddr_t)
14507                                                      (bytes_to_compare / 2));
14508                                                 curr_ptr =
14509                                                     &(curr_ptr[bytes_to_compare]);
14510                                                 bytes_left_to_compare -=
14511                                                     ((u32) bytes_to_compare);
14512                                         }       /* while( bytes_to_compare > DRXJ_UCODE_MAX_BUF_SIZE ) */
14513                                 };
14514                                 break;
14515
14516             /*===================================================================*/
14517                         default:
14518                                 return DRX_STS_INVALID_ARG;
14519                                 break;
14520
14521                         }       /* switch ( action ) */
14522                 }
14523
14524                 /* if( is_mc_block_audio( block_hdr.addr ) == upload_audio_mc ) */
14525                 /* Next block */
14526                 mc_data += mc_block_nr_bytes;
14527         }                       /* for( i = 0 ; i<mc_nr_of_blks ; i++ ) */
14528
14529         if (upload_audio_mc == false) {
14530                 ext_attr->flag_aud_mc_uploaded = false;
14531         }
14532
14533         return (DRX_STS_OK);
14534 }
14535 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
14536
14537 /*============================================================================*/
14538 /*== CTRL Set/Get Config related functions ===================================*/
14539 /*============================================================================*/
14540
14541 /*===== SigStrength() =========================================================*/
14542 /**
14543 * \fn int ctrl_sig_strength()
14544 * \brief Retrieve signal strength.
14545 * \param devmod Pointer to demodulator instance.
14546 * \param sig_quality Pointer to signal strength data; range 0, .. , 100.
14547 * \return int.
14548 * \retval DRX_STS_OK sig_strength contains valid data.
14549 * \retval DRX_STS_INVALID_ARG sig_strength is NULL.
14550 * \retval DRX_STS_ERROR Erroneous data, sig_strength contains invalid data.
14551
14552 */
14553 static int
14554 ctrl_sig_strength(pdrx_demod_instance_t demod, u16 *sig_strength)
14555 {
14556         pdrxj_data_t ext_attr = NULL;
14557         enum drx_standard standard = DRX_STANDARD_UNKNOWN;
14558
14559         /* Check arguments */
14560         if ((sig_strength == NULL) || (demod == NULL)) {
14561                 return (DRX_STS_INVALID_ARG);
14562         }
14563
14564         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
14565         standard = ext_attr->standard;
14566         *sig_strength = 0;
14567
14568         /* Signal strength indication for each standard */
14569         switch (standard) {
14570         case DRX_STANDARD_8VSB: /* fallthrough */
14571 #ifndef DRXJ_VSB_ONLY
14572         case DRX_STANDARD_ITU_A:        /* fallthrough */
14573         case DRX_STANDARD_ITU_B:        /* fallthrough */
14574         case DRX_STANDARD_ITU_C:
14575 #endif
14576                 CHK_ERROR(get_sig_strength(demod, sig_strength));
14577                 break;
14578 #ifndef DRXJ_DIGITAL_ONLY
14579         case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
14580         case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
14581         case DRX_STANDARD_PAL_SECAM_I:  /* fallthrough */
14582         case DRX_STANDARD_PAL_SECAM_L:  /* fallthrough */
14583         case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
14584         case DRX_STANDARD_NTSC: /* fallthrough */
14585         case DRX_STANDARD_FM:
14586                 CHK_ERROR(get_atv_sig_strength(demod, sig_strength));
14587                 break;
14588 #endif
14589         case DRX_STANDARD_UNKNOWN:      /* fallthrough */
14590         default:
14591                 return (DRX_STS_INVALID_ARG);
14592         }
14593
14594         /* TODO */
14595         /* find out if signal strength is calculated in the same way for all standards */
14596         return (DRX_STS_OK);
14597 rw_error:
14598         return (DRX_STS_ERROR);
14599 }
14600
14601 /*============================================================================*/
14602 /**
14603 * \fn int ctrl_get_cfg_oob_misc()
14604 * \brief Get current state information of OOB.
14605 * \param pointer to drxj_cfg_oob_misc_t.
14606 * \return int.
14607 *
14608 */
14609 #ifndef DRXJ_DIGITAL_ONLY
14610 static int
14611 ctrl_get_cfg_oob_misc(pdrx_demod_instance_t demod, p_drxj_cfg_oob_misc_t misc)
14612 {
14613         struct i2c_device_addr *dev_addr = NULL;
14614         u16 lock = 0U;
14615         u16 state = 0U;
14616         u16 data = 0U;
14617         u16 digital_agc_mant = 0U;
14618         u16 digital_agc_exp = 0U;
14619
14620         /* check arguments */
14621         if (misc == NULL) {
14622                 return (DRX_STS_INVALID_ARG);
14623         }
14624         dev_addr = demod->my_i2c_dev_addr;
14625
14626         /* TODO */
14627         /* check if the same registers are used for all standards (QAM/VSB/ATV) */
14628         RR16(dev_addr, ORX_NSU_TUN_IFGAIN_W__A, &misc->agc.IFAGC);
14629         RR16(dev_addr, ORX_NSU_TUN_RFGAIN_W__A, &misc->agc.RFAGC);
14630         RR16(dev_addr, ORX_FWP_SRC_DGN_W__A, &data);
14631
14632         digital_agc_mant = data & ORX_FWP_SRC_DGN_W_MANT__M;
14633         digital_agc_exp = (data & ORX_FWP_SRC_DGN_W_EXP__M)
14634             >> ORX_FWP_SRC_DGN_W_EXP__B;
14635         misc->agc.digital_agc = digital_agc_mant << digital_agc_exp;
14636
14637         SARR16(dev_addr, SCU_RAM_ORX_SCU_LOCK__A, &lock);
14638
14639         misc->ana_gain_lock = ((lock & 0x0001) ? true : false);
14640         misc->dig_gain_lock = ((lock & 0x0002) ? true : false);
14641         misc->freq_lock = ((lock & 0x0004) ? true : false);
14642         misc->phase_lock = ((lock & 0x0008) ? true : false);
14643         misc->sym_timing_lock = ((lock & 0x0010) ? true : false);
14644         misc->eq_lock = ((lock & 0x0020) ? true : false);
14645
14646         SARR16(dev_addr, SCU_RAM_ORX_SCU_STATE__A, &state);
14647         misc->state = (state >> 8) & 0xff;
14648
14649         return (DRX_STS_OK);
14650 rw_error:
14651         return (DRX_STS_ERROR);
14652 }
14653 #endif
14654
14655 /**
14656 * \fn int ctrl_get_cfg_vsb_misc()
14657 * \brief Get current state information of OOB.
14658 * \param pointer to drxj_cfg_oob_misc_t.
14659 * \return int.
14660 *
14661 */
14662 static int
14663 ctrl_get_cfg_vsb_misc(pdrx_demod_instance_t demod, p_drxj_cfg_vsb_misc_t misc)
14664 {
14665         struct i2c_device_addr *dev_addr = NULL;
14666
14667         /* check arguments */
14668         if (misc == NULL) {
14669                 return (DRX_STS_INVALID_ARG);
14670         }
14671         dev_addr = demod->my_i2c_dev_addr;
14672
14673         CHK_ERROR(get_vsb_symb_err(dev_addr, &misc->symb_error));
14674
14675         return (DRX_STS_OK);
14676 rw_error:
14677         return (DRX_STS_ERROR);
14678 }
14679
14680 /*============================================================================*/
14681
14682 /**
14683 * \fn int ctrl_set_cfg_agc_if()
14684 * \brief Set IF AGC.
14685 * \param demod demod instance
14686 * \param agc_settings If agc configuration
14687 * \return int.
14688 *
14689 * Check arguments
14690 * Dispatch handling to standard specific function.
14691 *
14692 */
14693 static int
14694 ctrl_set_cfg_agc_if(pdrx_demod_instance_t demod, p_drxj_cfg_agc_t agc_settings)
14695 {
14696         /* check arguments */
14697         if (agc_settings == NULL) {
14698                 return (DRX_STS_INVALID_ARG);
14699         }
14700
14701         switch (agc_settings->ctrl_mode) {
14702         case DRX_AGC_CTRL_AUTO: /* fallthrough */
14703         case DRX_AGC_CTRL_USER: /* fallthrough */
14704         case DRX_AGC_CTRL_OFF:  /* fallthrough */
14705                 break;
14706         default:
14707                 return (DRX_STS_INVALID_ARG);
14708         }
14709
14710         /* Distpatch */
14711         switch (agc_settings->standard) {
14712         case DRX_STANDARD_8VSB: /* fallthrough */
14713 #ifndef DRXJ_VSB_ONLY
14714         case DRX_STANDARD_ITU_A:        /* fallthrough */
14715         case DRX_STANDARD_ITU_B:        /* fallthrough */
14716         case DRX_STANDARD_ITU_C:
14717 #endif
14718 #ifndef DRXJ_DIGITAL_ONLY
14719         case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
14720         case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
14721         case DRX_STANDARD_PAL_SECAM_I:  /* fallthrough */
14722         case DRX_STANDARD_PAL_SECAM_L:  /* fallthrough */
14723         case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
14724         case DRX_STANDARD_NTSC: /* fallthrough */
14725         case DRX_STANDARD_FM:
14726 #endif
14727                 return set_agc_if(demod, agc_settings, true);
14728         case DRX_STANDARD_UNKNOWN:
14729         default:
14730                 return (DRX_STS_INVALID_ARG);
14731         }
14732
14733         return (DRX_STS_OK);
14734 }
14735
14736 /*============================================================================*/
14737
14738 /**
14739 * \fn int ctrl_get_cfg_agc_if()
14740 * \brief Retrieve IF AGC settings.
14741 * \param demod demod instance
14742 * \param agc_settings If agc configuration
14743 * \return int.
14744 *
14745 * Check arguments
14746 * Dispatch handling to standard specific function.
14747 *
14748 */
14749 static int
14750 ctrl_get_cfg_agc_if(pdrx_demod_instance_t demod, p_drxj_cfg_agc_t agc_settings)
14751 {
14752         /* check arguments */
14753         if (agc_settings == NULL) {
14754                 return (DRX_STS_INVALID_ARG);
14755         }
14756
14757         /* Distpatch */
14758         switch (agc_settings->standard) {
14759         case DRX_STANDARD_8VSB: /* fallthrough */
14760 #ifndef DRXJ_VSB_ONLY
14761         case DRX_STANDARD_ITU_A:        /* fallthrough */
14762         case DRX_STANDARD_ITU_B:        /* fallthrough */
14763         case DRX_STANDARD_ITU_C:
14764 #endif
14765 #ifndef DRXJ_DIGITAL_ONLY
14766         case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
14767         case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
14768         case DRX_STANDARD_PAL_SECAM_I:  /* fallthrough */
14769         case DRX_STANDARD_PAL_SECAM_L:  /* fallthrough */
14770         case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
14771         case DRX_STANDARD_NTSC: /* fallthrough */
14772         case DRX_STANDARD_FM:
14773 #endif
14774                 return get_agc_if(demod, agc_settings);
14775         case DRX_STANDARD_UNKNOWN:
14776         default:
14777                 return (DRX_STS_INVALID_ARG);
14778         }
14779
14780         return (DRX_STS_OK);
14781 }
14782
14783 /*============================================================================*/
14784
14785 /**
14786 * \fn int ctrl_set_cfg_agc_rf()
14787 * \brief Set RF AGC.
14788 * \param demod demod instance
14789 * \param agc_settings rf agc configuration
14790 * \return int.
14791 *
14792 * Check arguments
14793 * Dispatch handling to standard specific function.
14794 *
14795 */
14796 static int
14797 ctrl_set_cfg_agc_rf(pdrx_demod_instance_t demod, p_drxj_cfg_agc_t agc_settings)
14798 {
14799         /* check arguments */
14800         if (agc_settings == NULL) {
14801                 return (DRX_STS_INVALID_ARG);
14802         }
14803
14804         switch (agc_settings->ctrl_mode) {
14805         case DRX_AGC_CTRL_AUTO: /* fallthrough */
14806         case DRX_AGC_CTRL_USER: /* fallthrough */
14807         case DRX_AGC_CTRL_OFF:
14808                 break;
14809         default:
14810                 return (DRX_STS_INVALID_ARG);
14811         }
14812
14813         /* Distpatch */
14814         switch (agc_settings->standard) {
14815         case DRX_STANDARD_8VSB: /* fallthrough */
14816 #ifndef DRXJ_VSB_ONLY
14817         case DRX_STANDARD_ITU_A:        /* fallthrough */
14818         case DRX_STANDARD_ITU_B:        /* fallthrough */
14819         case DRX_STANDARD_ITU_C:
14820 #endif
14821 #ifndef DRXJ_DIGITAL_ONLY
14822         case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
14823         case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
14824         case DRX_STANDARD_PAL_SECAM_I:  /* fallthrough */
14825         case DRX_STANDARD_PAL_SECAM_L:  /* fallthrough */
14826         case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
14827         case DRX_STANDARD_NTSC: /* fallthrough */
14828         case DRX_STANDARD_FM:
14829 #endif
14830                 return set_agc_rf(demod, agc_settings, true);
14831         case DRX_STANDARD_UNKNOWN:
14832         default:
14833                 return (DRX_STS_INVALID_ARG);
14834         }
14835
14836         return (DRX_STS_OK);
14837 }
14838
14839 /*============================================================================*/
14840
14841 /**
14842 * \fn int ctrl_get_cfg_agc_rf()
14843 * \brief Retrieve RF AGC settings.
14844 * \param demod demod instance
14845 * \param agc_settings Rf agc configuration
14846 * \return int.
14847 *
14848 * Check arguments
14849 * Dispatch handling to standard specific function.
14850 *
14851 */
14852 static int
14853 ctrl_get_cfg_agc_rf(pdrx_demod_instance_t demod, p_drxj_cfg_agc_t agc_settings)
14854 {
14855         /* check arguments */
14856         if (agc_settings == NULL) {
14857                 return (DRX_STS_INVALID_ARG);
14858         }
14859
14860         /* Distpatch */
14861         switch (agc_settings->standard) {
14862         case DRX_STANDARD_8VSB: /* fallthrough */
14863 #ifndef DRXJ_VSB_ONLY
14864         case DRX_STANDARD_ITU_A:        /* fallthrough */
14865         case DRX_STANDARD_ITU_B:        /* fallthrough */
14866         case DRX_STANDARD_ITU_C:
14867 #endif
14868 #ifndef DRXJ_DIGITAL_ONLY
14869         case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
14870         case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
14871         case DRX_STANDARD_PAL_SECAM_I:  /* fallthrough */
14872         case DRX_STANDARD_PAL_SECAM_L:  /* fallthrough */
14873         case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
14874         case DRX_STANDARD_NTSC: /* fallthrough */
14875         case DRX_STANDARD_FM:
14876 #endif
14877                 return get_agc_rf(demod, agc_settings);
14878         case DRX_STANDARD_UNKNOWN:
14879         default:
14880                 return (DRX_STS_INVALID_ARG);
14881         }
14882
14883         return (DRX_STS_OK);
14884 }
14885
14886 /*============================================================================*/
14887
14888 /**
14889 * \fn int ctrl_get_cfg_agc_internal()
14890 * \brief Retrieve internal AGC value.
14891 * \param demod demod instance
14892 * \param u16
14893 * \return int.
14894 *
14895 * Check arguments
14896 * Dispatch handling to standard specific function.
14897 *
14898 */
14899 static int
14900 ctrl_get_cfg_agc_internal(pdrx_demod_instance_t demod, u16 *agc_internal)
14901 {
14902         struct i2c_device_addr *dev_addr = NULL;
14903         drx_lock_status_t lock_status = DRX_NOT_LOCKED;
14904         pdrxj_data_t ext_attr = NULL;
14905         u16 iqm_cf_scale_sh = 0;
14906         u16 iqm_cf_power = 0;
14907         u16 iqm_cf_amp = 0;
14908         u16 iqm_cf_gain = 0;
14909
14910         /* check arguments */
14911         if (agc_internal == NULL) {
14912                 return (DRX_STS_INVALID_ARG);
14913         }
14914         dev_addr = demod->my_i2c_dev_addr;
14915         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
14916
14917         CHK_ERROR(ctrl_lock_status(demod, &lock_status));
14918         if (lock_status != DRXJ_DEMOD_LOCK && lock_status != DRX_LOCKED) {
14919                 *agc_internal = 0;
14920                 return DRX_STS_OK;
14921         }
14922
14923         /* Distpatch */
14924         switch (ext_attr->standard) {
14925         case DRX_STANDARD_8VSB:
14926                 iqm_cf_gain = 57;
14927                 break;
14928 #ifndef DRXJ_VSB_ONLY
14929         case DRX_STANDARD_ITU_A:
14930         case DRX_STANDARD_ITU_B:
14931         case DRX_STANDARD_ITU_C:
14932                 switch (ext_attr->constellation) {
14933                 case DRX_CONSTELLATION_QAM256:
14934                 case DRX_CONSTELLATION_QAM128:
14935                 case DRX_CONSTELLATION_QAM32:
14936                 case DRX_CONSTELLATION_QAM16:
14937                         iqm_cf_gain = 57;
14938                         break;
14939                 case DRX_CONSTELLATION_QAM64:
14940                         iqm_cf_gain = 56;
14941                         break;
14942                 default:
14943                         return (DRX_STS_ERROR);
14944                 }
14945                 break;
14946 #endif
14947         default:
14948                 return (DRX_STS_INVALID_ARG);
14949         }
14950
14951         RR16(dev_addr, IQM_CF_POW__A, &iqm_cf_power);
14952         RR16(dev_addr, IQM_CF_SCALE_SH__A, &iqm_cf_scale_sh);
14953         RR16(dev_addr, IQM_CF_AMP__A, &iqm_cf_amp);
14954         /* IQM_CF_PWR_CORRECTION_dB = 3;
14955            P5dB =10*log10(IQM_CF_POW)+12-6*9-IQM_CF_PWR_CORRECTION_dB; */
14956         /* P4dB = P5dB -20*log10(IQM_CF_AMP)-6*10
14957            -IQM_CF_Gain_dB-18+6*(27-IQM_CF_SCALE_SH*2-10)
14958            +6*7+10*log10(1+0.115/4); */
14959         /* PadcdB = P4dB +3 -6 +60; dBmV */
14960         *agc_internal = (u16) (log1_times100(iqm_cf_power)
14961                                 - 2 * log1_times100(iqm_cf_amp)
14962                                 - iqm_cf_gain - 120 * iqm_cf_scale_sh + 781);
14963
14964         return (DRX_STS_OK);
14965 rw_error:
14966         return (DRX_STS_ERROR);
14967 }
14968
14969 /*============================================================================*/
14970
14971 /**
14972 * \fn int ctrl_set_cfg_pre_saw()
14973 * \brief Set Pre-saw reference.
14974 * \param demod demod instance
14975 * \param u16 *
14976 * \return int.
14977 *
14978 * Check arguments
14979 * Dispatch handling to standard specific function.
14980 *
14981 */
14982 static int
14983 ctrl_set_cfg_pre_saw(pdrx_demod_instance_t demod, p_drxj_cfg_pre_saw_t pre_saw)
14984 {
14985         struct i2c_device_addr *dev_addr = NULL;
14986         pdrxj_data_t ext_attr = NULL;
14987
14988         dev_addr = demod->my_i2c_dev_addr;
14989         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
14990
14991         /* check arguments */
14992         if ((pre_saw == NULL) || (pre_saw->reference > IQM_AF_PDREF__M)
14993             ) {
14994                 return (DRX_STS_INVALID_ARG);
14995         }
14996
14997         /* Only if standard is currently active */
14998         if ((ext_attr->standard == pre_saw->standard) ||
14999             (DRXJ_ISQAMSTD(ext_attr->standard) &&
15000              DRXJ_ISQAMSTD(pre_saw->standard)) ||
15001             (DRXJ_ISATVSTD(ext_attr->standard) &&
15002              DRXJ_ISATVSTD(pre_saw->standard))) {
15003                 WR16(dev_addr, IQM_AF_PDREF__A, pre_saw->reference);
15004         }
15005
15006         /* Store pre-saw settings */
15007         switch (pre_saw->standard) {
15008         case DRX_STANDARD_8VSB:
15009                 ext_attr->vsb_pre_saw_cfg = *pre_saw;
15010                 break;
15011 #ifndef DRXJ_VSB_ONLY
15012         case DRX_STANDARD_ITU_A:        /* fallthrough */
15013         case DRX_STANDARD_ITU_B:        /* fallthrough */
15014         case DRX_STANDARD_ITU_C:
15015                 ext_attr->qam_pre_saw_cfg = *pre_saw;
15016                 break;
15017 #endif
15018 #ifndef DRXJ_DIGITAL_ONLY
15019         case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
15020         case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
15021         case DRX_STANDARD_PAL_SECAM_I:  /* fallthrough */
15022         case DRX_STANDARD_PAL_SECAM_L:  /* fallthrough */
15023         case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
15024         case DRX_STANDARD_NTSC: /* fallthrough */
15025         case DRX_STANDARD_FM:
15026                 ext_attr->atv_pre_saw_cfg = *pre_saw;
15027                 break;
15028 #endif
15029         default:
15030                 return (DRX_STS_INVALID_ARG);
15031         }
15032
15033         return (DRX_STS_OK);
15034 rw_error:
15035         return (DRX_STS_ERROR);
15036 }
15037
15038 /*============================================================================*/
15039
15040 /**
15041 * \fn int ctrl_set_cfg_afe_gain()
15042 * \brief Set AFE Gain.
15043 * \param demod demod instance
15044 * \param u16 *
15045 * \return int.
15046 *
15047 * Check arguments
15048 * Dispatch handling to standard specific function.
15049 *
15050 */
15051 static int
15052 ctrl_set_cfg_afe_gain(pdrx_demod_instance_t demod, p_drxj_cfg_afe_gain_t afe_gain)
15053 {
15054         struct i2c_device_addr *dev_addr = NULL;
15055         pdrxj_data_t ext_attr = NULL;
15056         u8 gain = 0;
15057
15058         /* check arguments */
15059         if (afe_gain == NULL) {
15060                 return (DRX_STS_INVALID_ARG);
15061         }
15062
15063         dev_addr = demod->my_i2c_dev_addr;
15064         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
15065
15066         switch (afe_gain->standard) {
15067         case DRX_STANDARD_8VSB: /* fallthrough */
15068 #ifndef DRXJ_VSB_ONLY
15069         case DRX_STANDARD_ITU_A:        /* fallthrough */
15070         case DRX_STANDARD_ITU_B:        /* fallthrough */
15071         case DRX_STANDARD_ITU_C:
15072 #endif
15073                 /* Do nothing */
15074                 break;
15075         default:
15076                 return (DRX_STS_INVALID_ARG);
15077         }
15078
15079         /* TODO PGA gain is also written by microcode (at least by QAM and VSB)
15080            So I (PJ) think interface requires choice between auto, user mode */
15081
15082         if (afe_gain->gain >= 329)
15083                 gain = 15;
15084         else if (afe_gain->gain <= 147)
15085                 gain = 0;
15086         else
15087                 gain = (afe_gain->gain - 140 + 6) / 13;
15088
15089         /* Only if standard is currently active */
15090         if (ext_attr->standard == afe_gain->standard)
15091                 WR16(dev_addr, IQM_AF_PGA_GAIN__A, gain);
15092
15093         /* Store AFE Gain settings */
15094         switch (afe_gain->standard) {
15095         case DRX_STANDARD_8VSB:
15096                 ext_attr->vsb_pga_cfg = gain * 13 + 140;
15097                 break;
15098 #ifndef DRXJ_VSB_ONLY
15099         case DRX_STANDARD_ITU_A:        /* fallthrough */
15100         case DRX_STANDARD_ITU_B:        /* fallthrough */
15101         case DRX_STANDARD_ITU_C:
15102                 ext_attr->qam_pga_cfg = gain * 13 + 140;
15103                 break;
15104 #endif
15105         default:
15106                 return (DRX_STS_ERROR);
15107         }
15108
15109         return (DRX_STS_OK);
15110 rw_error:
15111         return (DRX_STS_ERROR);
15112 }
15113
15114 /*============================================================================*/
15115
15116 /**
15117 * \fn int ctrl_get_cfg_pre_saw()
15118 * \brief Get Pre-saw reference setting.
15119 * \param demod demod instance
15120 * \param u16 *
15121 * \return int.
15122 *
15123 * Check arguments
15124 * Dispatch handling to standard specific function.
15125 *
15126 */
15127 static int
15128 ctrl_get_cfg_pre_saw(pdrx_demod_instance_t demod, p_drxj_cfg_pre_saw_t pre_saw)
15129 {
15130         struct i2c_device_addr *dev_addr = NULL;
15131         pdrxj_data_t ext_attr = NULL;
15132
15133         /* check arguments */
15134         if (pre_saw == NULL) {
15135                 return (DRX_STS_INVALID_ARG);
15136         }
15137
15138         dev_addr = demod->my_i2c_dev_addr;
15139         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
15140
15141         switch (pre_saw->standard) {
15142         case DRX_STANDARD_8VSB:
15143                 *pre_saw = ext_attr->vsb_pre_saw_cfg;
15144                 break;
15145 #ifndef DRXJ_VSB_ONLY
15146         case DRX_STANDARD_ITU_A:        /* fallthrough */
15147         case DRX_STANDARD_ITU_B:        /* fallthrough */
15148         case DRX_STANDARD_ITU_C:
15149                 *pre_saw = ext_attr->qam_pre_saw_cfg;
15150                 break;
15151 #endif
15152 #ifndef DRXJ_DIGITAL_ONLY
15153         case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
15154         case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
15155         case DRX_STANDARD_PAL_SECAM_I:  /* fallthrough */
15156         case DRX_STANDARD_PAL_SECAM_L:  /* fallthrough */
15157         case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
15158         case DRX_STANDARD_NTSC:
15159                 ext_attr->atv_pre_saw_cfg.standard = DRX_STANDARD_NTSC;
15160                 *pre_saw = ext_attr->atv_pre_saw_cfg;
15161                 break;
15162         case DRX_STANDARD_FM:
15163                 ext_attr->atv_pre_saw_cfg.standard = DRX_STANDARD_FM;
15164                 *pre_saw = ext_attr->atv_pre_saw_cfg;
15165                 break;
15166 #endif
15167         default:
15168                 return (DRX_STS_INVALID_ARG);
15169         }
15170
15171         return (DRX_STS_OK);
15172 }
15173
15174 /*============================================================================*/
15175
15176 /**
15177 * \fn int ctrl_get_cfg_afe_gain()
15178 * \brief Get AFE Gain.
15179 * \param demod demod instance
15180 * \param u16 *
15181 * \return int.
15182 *
15183 * Check arguments
15184 * Dispatch handling to standard specific function.
15185 *
15186 */
15187 static int
15188 ctrl_get_cfg_afe_gain(pdrx_demod_instance_t demod, p_drxj_cfg_afe_gain_t afe_gain)
15189 {
15190         struct i2c_device_addr *dev_addr = NULL;
15191         pdrxj_data_t ext_attr = NULL;
15192
15193         /* check arguments */
15194         if (afe_gain == NULL) {
15195                 return (DRX_STS_INVALID_ARG);
15196         }
15197
15198         dev_addr = demod->my_i2c_dev_addr;
15199         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
15200
15201         switch (afe_gain->standard) {
15202         case DRX_STANDARD_8VSB:
15203                 afe_gain->gain = ext_attr->vsb_pga_cfg;
15204                 break;
15205 #ifndef DRXJ_VSB_ONLY
15206         case DRX_STANDARD_ITU_A:        /* fallthrough */
15207         case DRX_STANDARD_ITU_B:        /* fallthrough */
15208         case DRX_STANDARD_ITU_C:
15209                 afe_gain->gain = ext_attr->qam_pga_cfg;
15210                 break;
15211 #endif
15212         default:
15213                 return (DRX_STS_INVALID_ARG);
15214         }
15215
15216         return (DRX_STS_OK);
15217 }
15218
15219 /*============================================================================*/
15220
15221 /**
15222 * \fn int ctrl_get_fec_meas_seq_count()
15223 * \brief Get FEC measurement sequnce number.
15224 * \param demod demod instance
15225 * \param u16 *
15226 * \return int.
15227 *
15228 * Check arguments
15229 * Dispatch handling to standard specific function.
15230 *
15231 */
15232 static int
15233 ctrl_get_fec_meas_seq_count(pdrx_demod_instance_t demod, u16 *fec_meas_seq_count)
15234 {
15235         /* check arguments */
15236         if (fec_meas_seq_count == NULL) {
15237                 return (DRX_STS_INVALID_ARG);
15238         }
15239
15240         RR16(demod->my_i2c_dev_addr, SCU_RAM_FEC_MEAS_COUNT__A, fec_meas_seq_count);
15241
15242         return (DRX_STS_OK);
15243 rw_error:
15244         return (DRX_STS_ERROR);
15245 }
15246
15247 /*============================================================================*/
15248
15249 /**
15250 * \fn int ctrl_get_accum_cr_rs_cw_err()
15251 * \brief Get accumulative corrected RS codeword number.
15252 * \param demod demod instance
15253 * \param u32 *
15254 * \return int.
15255 *
15256 * Check arguments
15257 * Dispatch handling to standard specific function.
15258 *
15259 */
15260 static int
15261 ctrl_get_accum_cr_rs_cw_err(pdrx_demod_instance_t demod, u32 *accum_cr_rs_cw_err)
15262 {
15263         if (accum_cr_rs_cw_err == NULL) {
15264                 return (DRX_STS_INVALID_ARG);
15265         }
15266
15267         RR32(demod->my_i2c_dev_addr, SCU_RAM_FEC_ACCUM_CW_CORRECTED_LO__A,
15268              accum_cr_rs_cw_err);
15269
15270         return (DRX_STS_OK);
15271 rw_error:
15272         return (DRX_STS_ERROR);
15273 }
15274
15275 /**
15276 * \fn int ctrl_set_cfg()
15277 * \brief Set 'some' configuration of the device.
15278 * \param devmod Pointer to demodulator instance.
15279 * \param config Pointer to configuration parameters (type and data).
15280 * \return int.
15281
15282 */
15283 static int ctrl_set_cfg(pdrx_demod_instance_t demod, pdrx_cfg_t config)
15284 {
15285         if (config == NULL) {
15286                 return (DRX_STS_INVALID_ARG);
15287         }
15288
15289         DUMMY_READ();
15290         switch (config->cfg_type) {
15291         case DRX_CFG_MPEG_OUTPUT:
15292                 return ctrl_set_cfg_mpeg_output(demod,
15293                                             (pdrx_cfg_mpeg_output_t) config->
15294                                             cfg_data);
15295         case DRX_CFG_PINS_SAFE_MODE:
15296                 return ctrl_set_cfg_pdr_safe_mode(demod, (bool *) config->cfg_data);
15297         case DRXJ_CFG_AGC_RF:
15298                 return ctrl_set_cfg_agc_rf(demod, (p_drxj_cfg_agc_t) config->cfg_data);
15299         case DRXJ_CFG_AGC_IF:
15300                 return ctrl_set_cfg_agc_if(demod, (p_drxj_cfg_agc_t) config->cfg_data);
15301         case DRXJ_CFG_PRE_SAW:
15302                 return ctrl_set_cfg_pre_saw(demod,
15303                                         (p_drxj_cfg_pre_saw_t) config->cfg_data);
15304         case DRXJ_CFG_AFE_GAIN:
15305                 return ctrl_set_cfg_afe_gain(demod,
15306                                          (p_drxj_cfg_afe_gain_t) config->cfg_data);
15307         case DRXJ_CFG_SMART_ANT:
15308                 return ctrl_set_cfg_smart_ant(demod,
15309                                           (p_drxj_cfg_smart_ant_t) (config->
15310                                                                 cfg_data));
15311         case DRXJ_CFG_RESET_PACKET_ERR:
15312                 return ctrl_set_cfg_reset_pkt_err(demod);
15313 #ifndef DRXJ_DIGITAL_ONLY
15314         case DRXJ_CFG_OOB_PRE_SAW:
15315                 return ctrl_set_cfg_oob_pre_saw(demod, (u16 *) (config->cfg_data));
15316         case DRXJ_CFG_OOB_LO_POW:
15317                 return ctrl_set_cfg_oob_lo_power(demod,
15318                                             (p_drxj_cfg_oob_lo_power_t) (config->
15319                                                                     cfg_data));
15320         case DRXJ_CFG_ATV_MISC:
15321                 return ctrl_set_cfg_atv_misc(demod,
15322                                          (p_drxj_cfg_atv_misc_t) config->cfg_data);
15323         case DRXJ_CFG_ATV_EQU_COEF:
15324                 return ctrl_set_cfg_atv_equ_coef(demod,
15325                                             (p_drxj_cfg_atv_equ_coef_t) config->
15326                                             cfg_data);
15327         case DRXJ_CFG_ATV_OUTPUT:
15328                 return ctrl_set_cfg_atv_output(demod,
15329                                            (p_drxj_cfg_atv_output_t) config->
15330                                            cfg_data);
15331 #endif
15332         case DRXJ_CFG_MPEG_OUTPUT_MISC:
15333                 return ctrl_set_cfg_mpeg_output_misc(demod,
15334                                                 (p_drxj_cfg_mpeg_output_misc_t)
15335                                                 config->cfg_data);
15336 #ifndef DRXJ_EXCLUDE_AUDIO
15337         case DRX_CFG_AUD_VOLUME:
15338                 return aud_ctrl_set_cfg_volume(demod,
15339                                            (pdrx_cfg_aud_volume_t) config->
15340                                            cfg_data);
15341         case DRX_CFG_I2S_OUTPUT:
15342                 return aud_ctrl_set_cfg_output_i2s(demod,
15343                                               (pdrx_cfg_i2s_output_t) config->
15344                                               cfg_data);
15345         case DRX_CFG_AUD_AUTOSOUND:
15346                 return aud_ctr_setl_cfg_auto_sound(demod, (pdrx_cfg_aud_auto_sound_t)
15347                                               config->cfg_data);
15348         case DRX_CFG_AUD_ASS_THRES:
15349                 return aud_ctrl_set_cfg_ass_thres(demod, (pdrx_cfg_aud_ass_thres_t)
15350                                              config->cfg_data);
15351         case DRX_CFG_AUD_CARRIER:
15352                 return aud_ctrl_set_cfg_carrier(demod,
15353                                             (pdrx_cfg_aud_carriers_t) config->
15354                                             cfg_data);
15355         case DRX_CFG_AUD_DEVIATION:
15356                 return aud_ctrl_set_cfg_dev(demod,
15357                                         (pdrx_cfg_aud_deviation_t) config->
15358                                         cfg_data);
15359         case DRX_CFG_AUD_PRESCALE:
15360                 return aud_ctrl_set_cfg_prescale(demod,
15361                                              (pdrx_cfg_aud_prescale_t) config->
15362                                              cfg_data);
15363         case DRX_CFG_AUD_MIXER:
15364                 return aud_ctrl_set_cfg_mixer(demod,
15365                                           (pdrx_cfg_aud_mixer_t) config->cfg_data);
15366         case DRX_CFG_AUD_AVSYNC:
15367                 return aud_ctrl_set_cfg_av_sync(demod,
15368                                            (pdrx_cfg_aud_av_sync_t) config->
15369                                            cfg_data);
15370
15371 #endif
15372         default:
15373                 return (DRX_STS_INVALID_ARG);
15374         }
15375
15376         return (DRX_STS_OK);
15377 rw_error:
15378         return (DRX_STS_ERROR);
15379 }
15380
15381 /*============================================================================*/
15382
15383 /**
15384 * \fn int ctrl_get_cfg()
15385 * \brief Get 'some' configuration of the device.
15386 * \param devmod Pointer to demodulator instance.
15387 * \param config Pointer to configuration parameters (type and data).
15388 * \return int.
15389 */
15390
15391 static int ctrl_get_cfg(pdrx_demod_instance_t demod, pdrx_cfg_t config)
15392 {
15393         if (config == NULL) {
15394                 return (DRX_STS_INVALID_ARG);
15395         }
15396
15397         DUMMY_READ();
15398
15399         switch (config->cfg_type) {
15400         case DRX_CFG_MPEG_OUTPUT:
15401                 return ctrl_get_cfg_mpeg_output(demod,
15402                                             (pdrx_cfg_mpeg_output_t) config->
15403                                             cfg_data);
15404         case DRX_CFG_PINS_SAFE_MODE:
15405                 return ctrl_get_cfg_pdr_safe_mode(demod, (bool *) config->cfg_data);
15406         case DRXJ_CFG_AGC_RF:
15407                 return ctrl_get_cfg_agc_rf(demod, (p_drxj_cfg_agc_t) config->cfg_data);
15408         case DRXJ_CFG_AGC_IF:
15409                 return ctrl_get_cfg_agc_if(demod, (p_drxj_cfg_agc_t) config->cfg_data);
15410         case DRXJ_CFG_AGC_INTERNAL:
15411                 return ctrl_get_cfg_agc_internal(demod, (u16 *) config->cfg_data);
15412         case DRXJ_CFG_PRE_SAW:
15413                 return ctrl_get_cfg_pre_saw(demod,
15414                                         (p_drxj_cfg_pre_saw_t) config->cfg_data);
15415         case DRXJ_CFG_AFE_GAIN:
15416                 return ctrl_get_cfg_afe_gain(demod,
15417                                          (p_drxj_cfg_afe_gain_t) config->cfg_data);
15418         case DRXJ_CFG_ACCUM_CR_RS_CW_ERR:
15419                 return ctrl_get_accum_cr_rs_cw_err(demod, (u32 *) config->cfg_data);
15420         case DRXJ_CFG_FEC_MERS_SEQ_COUNT:
15421                 return ctrl_get_fec_meas_seq_count(demod, (u16 *) config->cfg_data);
15422         case DRXJ_CFG_VSB_MISC:
15423                 return ctrl_get_cfg_vsb_misc(demod,
15424                                          (p_drxj_cfg_vsb_misc_t) config->cfg_data);
15425         case DRXJ_CFG_SYMBOL_CLK_OFFSET:
15426                 return ctrl_get_cfg_symbol_clock_offset(demod,
15427                                                    (s32 *) config->cfg_data);
15428 #ifndef DRXJ_DIGITAL_ONLY
15429         case DRXJ_CFG_OOB_MISC:
15430                 return ctrl_get_cfg_oob_misc(demod,
15431                                          (p_drxj_cfg_oob_misc_t) config->cfg_data);
15432         case DRXJ_CFG_OOB_PRE_SAW:
15433                 return ctrl_get_cfg_oob_pre_saw(demod, (u16 *) (config->cfg_data));
15434         case DRXJ_CFG_OOB_LO_POW:
15435                 return ctrl_get_cfg_oob_lo_power(demod,
15436                                             (p_drxj_cfg_oob_lo_power_t) (config->
15437                                                                     cfg_data));
15438         case DRXJ_CFG_ATV_EQU_COEF:
15439                 return ctrl_get_cfg_atv_equ_coef(demod,
15440                                             (p_drxj_cfg_atv_equ_coef_t) config->
15441                                             cfg_data);
15442         case DRXJ_CFG_ATV_MISC:
15443                 return ctrl_get_cfg_atv_misc(demod,
15444                                          (p_drxj_cfg_atv_misc_t) config->cfg_data);
15445         case DRXJ_CFG_ATV_OUTPUT:
15446                 return ctrl_get_cfg_atv_output(demod,
15447                                            (p_drxj_cfg_atv_output_t) config->
15448                                            cfg_data);
15449         case DRXJ_CFG_ATV_AGC_STATUS:
15450                 return ctrl_get_cfg_atv_agc_status(demod,
15451                                               (p_drxj_cfg_atv_agc_status_t) config->
15452                                               cfg_data);
15453 #endif
15454         case DRXJ_CFG_MPEG_OUTPUT_MISC:
15455                 return ctrl_get_cfg_mpeg_output_misc(demod,
15456                                                 (p_drxj_cfg_mpeg_output_misc_t)
15457                                                 config->cfg_data);
15458         case DRXJ_CFG_HW_CFG:
15459                 return ctrl_get_cfg_hw_cfg(demod,
15460                                        (p_drxj_cfg_hw_cfg_t) config->cfg_data);
15461 #ifndef DRXJ_EXCLUDE_AUDIO
15462         case DRX_CFG_AUD_VOLUME:
15463                 return aud_ctrl_get_cfg_volume(demod,
15464                                            (pdrx_cfg_aud_volume_t) config->
15465                                            cfg_data);
15466         case DRX_CFG_I2S_OUTPUT:
15467                 return aud_ctrl_get_cfg_output_i2s(demod,
15468                                               (pdrx_cfg_i2s_output_t) config->
15469                                               cfg_data);
15470
15471         case DRX_CFG_AUD_RDS:
15472                 return aud_ctrl_get_cfg_rds(demod,
15473                                         (pdrx_cfg_aud_rds_t) config->cfg_data);
15474         case DRX_CFG_AUD_AUTOSOUND:
15475                 return aud_ctrl_get_cfg_auto_sound(demod,
15476                                               (pdrx_cfg_aud_auto_sound_t) config->
15477                                               cfg_data);
15478         case DRX_CFG_AUD_ASS_THRES:
15479                 return aud_ctrl_get_cfg_ass_thres(demod,
15480                                              (pdrx_cfg_aud_ass_thres_t) config->
15481                                              cfg_data);
15482         case DRX_CFG_AUD_CARRIER:
15483                 return aud_ctrl_get_cfg_carrier(demod,
15484                                             (pdrx_cfg_aud_carriers_t) config->
15485                                             cfg_data);
15486         case DRX_CFG_AUD_DEVIATION:
15487                 return aud_ctrl_get_cfg_dev(demod,
15488                                         (pdrx_cfg_aud_deviation_t) config->
15489                                         cfg_data);
15490         case DRX_CFG_AUD_PRESCALE:
15491                 return aud_ctrl_get_cfg_prescale(demod,
15492                                              (pdrx_cfg_aud_prescale_t) config->
15493                                              cfg_data);
15494         case DRX_CFG_AUD_MIXER:
15495                 return aud_ctrl_get_cfg_mixer(demod,
15496                                           (pdrx_cfg_aud_mixer_t) config->cfg_data);
15497         case DRX_CFG_AUD_AVSYNC:
15498                 return aud_ctrl_get_cfg_av_sync(demod,
15499                                            (pdrx_cfg_aud_av_sync_t) config->
15500                                            cfg_data);
15501 #endif
15502
15503         default:
15504                 return (DRX_STS_INVALID_ARG);
15505         }
15506
15507         return (DRX_STS_OK);
15508 rw_error:
15509         return (DRX_STS_ERROR);
15510 }
15511
15512 /*=============================================================================
15513 ===== EXPORTED FUNCTIONS ====================================================*/
15514 /**
15515 * \fn drxj_open()
15516 * \brief Open the demod instance, configure device, configure drxdriver
15517 * \return Status_t Return status.
15518 *
15519 * drxj_open() can be called with a NULL ucode image => no ucode upload.
15520 * This means that drxj_open() must NOT contain SCU commands or, in general,
15521 * rely on SCU or AUD ucode to be present.
15522 *
15523 */
15524 int drxj_open(pdrx_demod_instance_t demod)
15525 {
15526         struct i2c_device_addr *dev_addr = NULL;
15527         pdrxj_data_t ext_attr = NULL;
15528         pdrx_common_attr_t common_attr = NULL;
15529         u32 driver_version = 0;
15530         drxu_code_info_t ucode_info;
15531         drx_cfg_mpeg_output_t cfg_mpeg_output;
15532
15533         /* Check arguments */
15534         if (demod->my_ext_attr == NULL) {
15535                 return (DRX_STS_INVALID_ARG);
15536         }
15537
15538         dev_addr = demod->my_i2c_dev_addr;
15539         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
15540         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
15541
15542         CHK_ERROR(power_up_device(demod));
15543         common_attr->current_power_mode = DRX_POWER_UP;
15544
15545         /* has to be in front of setIqmAf and setOrxNsuAox */
15546         CHK_ERROR(get_device_capabilities(demod));
15547
15548         /* Soft reset of sys- and osc-clockdomain */
15549         WR16(dev_addr, SIO_CC_SOFT_RST__A, (SIO_CC_SOFT_RST_SYS__M |
15550                                            SIO_CC_SOFT_RST_OSC__M));
15551         WR16(dev_addr, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
15552         CHK_ERROR(drxbsp_hst_sleep(1));
15553
15554         /* TODO first make sure that everything keeps working before enabling this */
15555         /* PowerDownAnalogBlocks() */
15556         WR16(dev_addr, ATV_TOP_STDBY__A, (~ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE)
15557              | ATV_TOP_STDBY_SIF_STDBY_STANDBY);
15558
15559         CHK_ERROR(set_iqm_af(demod, false));
15560         CHK_ERROR(set_orx_nsu_aox(demod, false));
15561
15562         CHK_ERROR(init_hi(demod));
15563
15564         /* disable mpegoutput pins */
15565         cfg_mpeg_output.enable_mpeg_output = false;
15566         CHK_ERROR(ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output));
15567         /* Stop AUD Inform SetAudio it will need to do all setting */
15568         CHK_ERROR(power_down_aud(demod));
15569         /* Stop SCU */
15570         WR16(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_STOP);
15571
15572         /* Upload microcode */
15573         if (common_attr->microcode != NULL) {
15574                 /* Dirty trick to use common ucode upload & verify,
15575                    pretend device is already open */
15576                 common_attr->is_opened = true;
15577                 ucode_info.mc_data = common_attr->microcode;
15578                 ucode_info.mc_size = common_attr->microcode_size;
15579
15580 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
15581                 /* Upload microcode without audio part */
15582                 CHK_ERROR(ctrl_u_codeUpload
15583                           (demod, &ucode_info, UCODE_UPLOAD, false));
15584 #else
15585                 CHK_ERROR(drx_ctrl(demod, DRX_CTRL_LOAD_UCODE, &ucode_info));
15586 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
15587                 if (common_attr->verify_microcode == true) {
15588 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
15589                         CHK_ERROR(ctrl_u_codeUpload
15590                                   (demod, &ucode_info, UCODE_VERIFY, false));
15591 #else
15592                         CHK_ERROR(drx_ctrl
15593                                   (demod, DRX_CTRL_VERIFY_UCODE, &ucode_info));
15594 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
15595                 }
15596                 common_attr->is_opened = false;
15597         }
15598
15599         /* Run SCU for a little while to initialize microcode version numbers */
15600         WR16(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
15601
15602         /* Open tuner instance */
15603         if (demod->my_tuner != NULL) {
15604                 demod->my_tuner->my_common_attr->myUser_data = (void *)demod;
15605
15606                 if (common_attr->tuner_port_nr == 1) {
15607                         bool bridge_closed = true;
15608                         CHK_ERROR(ctrl_i2c_bridge(demod, &bridge_closed));
15609                 }
15610
15611                 CHK_ERROR(drxbsp_tuner_open(demod->my_tuner));
15612
15613                 if (common_attr->tuner_port_nr == 1) {
15614                         bool bridge_closed = false;
15615                         CHK_ERROR(ctrl_i2c_bridge(demod, &bridge_closed));
15616                 }
15617                 common_attr->tuner_min_freq_rf =
15618                     ((demod->my_tuner)->my_common_attr->min_freq_rf);
15619                 common_attr->tuner_max_freq_rf =
15620                     ((demod->my_tuner)->my_common_attr->max_freq_rf);
15621         }
15622
15623         /* Initialize scan timeout */
15624         common_attr->scan_demod_lock_timeout = DRXJ_SCAN_TIMEOUT;
15625         common_attr->scan_desired_lock = DRX_LOCKED;
15626
15627         /* Initialize default AFE configuartion for QAM */
15628         if (ext_attr->has_lna) {
15629                 /* IF AGC off, PGA active */
15630 #ifndef DRXJ_VSB_ONLY
15631                 ext_attr->qam_if_agc_cfg.standard = DRX_STANDARD_ITU_B;
15632                 ext_attr->qam_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_OFF;
15633                 ext_attr->qam_pga_cfg = 140 + (11 * 13);
15634 #endif
15635                 ext_attr->vsb_if_agc_cfg.standard = DRX_STANDARD_8VSB;
15636                 ext_attr->vsb_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_OFF;
15637                 ext_attr->vsb_pga_cfg = 140 + (11 * 13);
15638         } else {
15639                 /* IF AGC on, PGA not active */
15640 #ifndef DRXJ_VSB_ONLY
15641                 ext_attr->qam_if_agc_cfg.standard = DRX_STANDARD_ITU_B;
15642                 ext_attr->qam_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
15643                 ext_attr->qam_if_agc_cfg.min_output_level = 0;
15644                 ext_attr->qam_if_agc_cfg.max_output_level = 0x7FFF;
15645                 ext_attr->qam_if_agc_cfg.speed = 3;
15646                 ext_attr->qam_if_agc_cfg.top = 1297;
15647                 ext_attr->qam_pga_cfg = 140;
15648 #endif
15649                 ext_attr->vsb_if_agc_cfg.standard = DRX_STANDARD_8VSB;
15650                 ext_attr->vsb_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
15651                 ext_attr->vsb_if_agc_cfg.min_output_level = 0;
15652                 ext_attr->vsb_if_agc_cfg.max_output_level = 0x7FFF;
15653                 ext_attr->vsb_if_agc_cfg.speed = 3;
15654                 ext_attr->vsb_if_agc_cfg.top = 1024;
15655                 ext_attr->vsb_pga_cfg = 140;
15656         }
15657         /* TODO: remove min_output_level and max_output_level for both QAM and VSB after */
15658         /* mc has not used them */
15659 #ifndef DRXJ_VSB_ONLY
15660         ext_attr->qam_rf_agc_cfg.standard = DRX_STANDARD_ITU_B;
15661         ext_attr->qam_rf_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
15662         ext_attr->qam_rf_agc_cfg.min_output_level = 0;
15663         ext_attr->qam_rf_agc_cfg.max_output_level = 0x7FFF;
15664         ext_attr->qam_rf_agc_cfg.speed = 3;
15665         ext_attr->qam_rf_agc_cfg.top = 9500;
15666         ext_attr->qam_rf_agc_cfg.cut_off_current = 4000;
15667         ext_attr->qam_pre_saw_cfg.standard = DRX_STANDARD_ITU_B;
15668         ext_attr->qam_pre_saw_cfg.reference = 0x07;
15669         ext_attr->qam_pre_saw_cfg.use_pre_saw = true;
15670 #endif
15671         /* Initialize default AFE configuartion for VSB */
15672         ext_attr->vsb_rf_agc_cfg.standard = DRX_STANDARD_8VSB;
15673         ext_attr->vsb_rf_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
15674         ext_attr->vsb_rf_agc_cfg.min_output_level = 0;
15675         ext_attr->vsb_rf_agc_cfg.max_output_level = 0x7FFF;
15676         ext_attr->vsb_rf_agc_cfg.speed = 3;
15677         ext_attr->vsb_rf_agc_cfg.top = 9500;
15678         ext_attr->vsb_rf_agc_cfg.cut_off_current = 4000;
15679         ext_attr->vsb_pre_saw_cfg.standard = DRX_STANDARD_8VSB;
15680         ext_attr->vsb_pre_saw_cfg.reference = 0x07;
15681         ext_attr->vsb_pre_saw_cfg.use_pre_saw = true;
15682
15683 #ifndef DRXJ_DIGITAL_ONLY
15684         /* Initialize default AFE configuartion for ATV */
15685         ext_attr->atv_rf_agc_cfg.standard = DRX_STANDARD_NTSC;
15686         ext_attr->atv_rf_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
15687         ext_attr->atv_rf_agc_cfg.top = 9500;
15688         ext_attr->atv_rf_agc_cfg.cut_off_current = 4000;
15689         ext_attr->atv_rf_agc_cfg.speed = 3;
15690         ext_attr->atv_if_agc_cfg.standard = DRX_STANDARD_NTSC;
15691         ext_attr->atv_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
15692         ext_attr->atv_if_agc_cfg.speed = 3;
15693         ext_attr->atv_if_agc_cfg.top = 2400;
15694         ext_attr->atv_pre_saw_cfg.reference = 0x0007;
15695         ext_attr->atv_pre_saw_cfg.use_pre_saw = true;
15696         ext_attr->atv_pre_saw_cfg.standard = DRX_STANDARD_NTSC;
15697 #endif
15698         ext_attr->standard = DRX_STANDARD_UNKNOWN;
15699
15700         CHK_ERROR(smart_ant_init(demod));
15701
15702         /* Stamp driver version number in SCU data RAM in BCD code
15703            Done to enable field application engineers to retreive drxdriver version
15704            via I2C from SCU RAM
15705          */
15706         driver_version = (VERSION_MAJOR / 100) % 10;
15707         driver_version <<= 4;
15708         driver_version += (VERSION_MAJOR / 10) % 10;
15709         driver_version <<= 4;
15710         driver_version += (VERSION_MAJOR % 10);
15711         driver_version <<= 4;
15712         driver_version += (VERSION_MINOR % 10);
15713         driver_version <<= 4;
15714         driver_version += (VERSION_PATCH / 1000) % 10;
15715         driver_version <<= 4;
15716         driver_version += (VERSION_PATCH / 100) % 10;
15717         driver_version <<= 4;
15718         driver_version += (VERSION_PATCH / 10) % 10;
15719         driver_version <<= 4;
15720         driver_version += (VERSION_PATCH % 10);
15721         WR16(dev_addr, SCU_RAM_DRIVER_VER_HI__A, (u16) (driver_version >> 16));
15722         WR16(dev_addr, SCU_RAM_DRIVER_VER_LO__A,
15723              (u16) (driver_version & 0xFFFF));
15724
15725         /* refresh the audio data structure with default */
15726         ext_attr->aud_data = drxj_default_aud_data_g;
15727
15728         return (DRX_STS_OK);
15729 rw_error:
15730         common_attr->is_opened = false;
15731         return (DRX_STS_ERROR);
15732 }
15733
15734 /*============================================================================*/
15735 /**
15736 * \fn drxj_close()
15737 * \brief Close the demod instance, power down the device
15738 * \return Status_t Return status.
15739 *
15740 */
15741 int drxj_close(pdrx_demod_instance_t demod)
15742 {
15743         struct i2c_device_addr *dev_addr = NULL;
15744         pdrxj_data_t ext_attr = NULL;
15745         pdrx_common_attr_t common_attr = NULL;
15746         drx_power_mode_t power_mode = DRX_POWER_UP;
15747
15748         common_attr = (pdrx_common_attr_t) demod->my_common_attr;
15749         dev_addr = demod->my_i2c_dev_addr;
15750         ext_attr = (pdrxj_data_t) demod->my_ext_attr;
15751
15752         /* power up */
15753         CHK_ERROR(ctrl_power_mode(demod, &power_mode));
15754
15755         if (demod->my_tuner != NULL) {
15756                 /* Check if bridge is used */
15757                 if (common_attr->tuner_port_nr == 1) {
15758                         bool bridge_closed = true;
15759                         CHK_ERROR(ctrl_i2c_bridge(demod, &bridge_closed));
15760                 }
15761                 CHK_ERROR(drxbsp_tuner_close(demod->my_tuner));
15762                 if (common_attr->tuner_port_nr == 1) {
15763                         bool bridge_closed = false;
15764                         CHK_ERROR(ctrl_i2c_bridge(demod, &bridge_closed));
15765                 }
15766         };
15767
15768         WR16(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
15769         power_mode = DRX_POWER_DOWN;
15770         CHK_ERROR(ctrl_power_mode(demod, &power_mode));
15771
15772         return DRX_STS_OK;
15773 rw_error:
15774         return (DRX_STS_ERROR);
15775 }
15776
15777 /*============================================================================*/
15778 /**
15779 * \fn drxj_ctrl()
15780 * \brief DRXJ specific control function
15781 * \return Status_t Return status.
15782 */
15783 int
15784 drxj_ctrl(pdrx_demod_instance_t demod, u32 ctrl, void *ctrl_data)
15785 {
15786         switch (ctrl) {
15787       /*======================================================================*/
15788         case DRX_CTRL_SET_CHANNEL:
15789                 {
15790                         return ctrl_set_channel(demod, (pdrx_channel_t) ctrl_data);
15791                 }
15792                 break;
15793       /*======================================================================*/
15794         case DRX_CTRL_GET_CHANNEL:
15795                 {
15796                         return ctrl_get_channel(demod, (pdrx_channel_t) ctrl_data);
15797                 }
15798                 break;
15799       /*======================================================================*/
15800         case DRX_CTRL_SIG_QUALITY:
15801                 {
15802                         return ctrl_sig_quality(demod,
15803                                               (pdrx_sig_quality_t) ctrl_data);
15804                 }
15805                 break;
15806       /*======================================================================*/
15807         case DRX_CTRL_SIG_STRENGTH:
15808                 {
15809                         return ctrl_sig_strength(demod, (u16 *) ctrl_data);
15810                 }
15811                 break;
15812       /*======================================================================*/
15813         case DRX_CTRL_CONSTEL:
15814                 {
15815                         return ctrl_constel(demod, (pdrx_complex_t) ctrl_data);
15816                 }
15817                 break;
15818       /*======================================================================*/
15819         case DRX_CTRL_SET_CFG:
15820                 {
15821                         return ctrl_set_cfg(demod, (pdrx_cfg_t) ctrl_data);
15822                 }
15823                 break;
15824       /*======================================================================*/
15825         case DRX_CTRL_GET_CFG:
15826                 {
15827                         return ctrl_get_cfg(demod, (pdrx_cfg_t) ctrl_data);
15828                 }
15829                 break;
15830       /*======================================================================*/
15831         case DRX_CTRL_I2C_BRIDGE:
15832                 {
15833                         return ctrl_i2c_bridge(demod, (bool *) ctrl_data);
15834                 }
15835                 break;
15836       /*======================================================================*/
15837         case DRX_CTRL_LOCK_STATUS:
15838                 {
15839                         return ctrl_lock_status(demod,
15840                                               (pdrx_lock_status_t) ctrl_data);
15841                 }
15842                 break;
15843       /*======================================================================*/
15844         case DRX_CTRL_SET_STANDARD:
15845                 {
15846                         return ctrl_set_standard(demod,
15847                                                (enum drx_standard *) ctrl_data);
15848                 }
15849                 break;
15850       /*======================================================================*/
15851         case DRX_CTRL_GET_STANDARD:
15852                 {
15853                         return ctrl_get_standard(demod,
15854                                                (enum drx_standard *) ctrl_data);
15855                 }
15856                 break;
15857       /*======================================================================*/
15858         case DRX_CTRL_POWER_MODE:
15859                 {
15860                         return ctrl_power_mode(demod, (pdrx_power_mode_t) ctrl_data);
15861                 }
15862                 break;
15863       /*======================================================================*/
15864         case DRX_CTRL_VERSION:
15865                 {
15866                         return ctrl_version(demod,
15867                                            (p_drx_version_list_t *) ctrl_data);
15868                 }
15869                 break;
15870       /*======================================================================*/
15871         case DRX_CTRL_PROBE_DEVICE:
15872                 {
15873                         return ctrl_probe_device(demod);
15874                 }
15875                 break;
15876       /*======================================================================*/
15877         case DRX_CTRL_SET_OOB:
15878                 {
15879                         return ctrl_set_oob(demod, (p_drxoob_t) ctrl_data);
15880                 }
15881                 break;
15882       /*======================================================================*/
15883         case DRX_CTRL_GET_OOB:
15884                 {
15885                         return ctrl_get_oob(demod, (pdrxoob_status_t) ctrl_data);
15886                 }
15887                 break;
15888       /*======================================================================*/
15889         case DRX_CTRL_SET_UIO_CFG:
15890                 {
15891                         return ctrl_set_uio_cfg(demod, (pdrxuio_cfg_t) ctrl_data);
15892                 }
15893                 break;
15894       /*======================================================================*/
15895         case DRX_CTRL_GET_UIO_CFG:
15896                 {
15897                         return CtrlGetuio_cfg(demod, (pdrxuio_cfg_t) ctrl_data);
15898                 }
15899                 break;
15900       /*======================================================================*/
15901         case DRX_CTRL_UIO_READ:
15902                 {
15903                         return ctrl_uio_read(demod, (pdrxuio_data_t) ctrl_data);
15904                 }
15905                 break;
15906       /*======================================================================*/
15907         case DRX_CTRL_UIO_WRITE:
15908                 {
15909                         return ctrl_uio_write(demod, (pdrxuio_data_t) ctrl_data);
15910                 }
15911                 break;
15912       /*======================================================================*/
15913         case DRX_CTRL_AUD_SET_STANDARD:
15914                 {
15915                         return aud_ctrl_set_standard(demod,
15916                                                   (pdrx_aud_standard_t) ctrl_data);
15917                 }
15918                 break;
15919       /*======================================================================*/
15920         case DRX_CTRL_AUD_GET_STANDARD:
15921                 {
15922                         return aud_ctrl_get_standard(demod,
15923                                                   (pdrx_aud_standard_t) ctrl_data);
15924                 }
15925                 break;
15926       /*======================================================================*/
15927         case DRX_CTRL_AUD_GET_STATUS:
15928                 {
15929                         return aud_ctrl_get_status(demod,
15930                                                 (pdrx_aud_status_t) ctrl_data);
15931                 }
15932                 break;
15933       /*======================================================================*/
15934         case DRX_CTRL_AUD_BEEP:
15935                 {
15936                         return aud_ctrl_beep(demod, (pdrx_aud_beep_t) ctrl_data);
15937                 }
15938                 break;
15939
15940       /*======================================================================*/
15941         case DRX_CTRL_I2C_READWRITE:
15942                 {
15943                         return ctrl_i2c_write_read(demod,
15944                                                 (pdrxi2c_data_t) ctrl_data);
15945                 }
15946                 break;
15947 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
15948         case DRX_CTRL_LOAD_UCODE:
15949                 {
15950                         return ctrl_u_codeUpload(demod,
15951                                                (p_drxu_code_info_t) ctrl_data,
15952                                                UCODE_UPLOAD, false);
15953                 }
15954                 break;
15955         case DRX_CTRL_VERIFY_UCODE:
15956                 {
15957                         return ctrl_u_codeUpload(demod,
15958                                                (p_drxu_code_info_t) ctrl_data,
15959                                                UCODE_VERIFY, false);
15960                 }
15961                 break;
15962 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
15963         case DRX_CTRL_VALIDATE_UCODE:
15964                 {
15965                         return ctrl_validate_u_code(demod);
15966                 }
15967                 break;
15968         default:
15969                 return (DRX_STS_FUNC_NOT_AVAILABLE);
15970         }
15971         return (DRX_STS_OK);
15972 }
15973
15974 /* END OF FILE */