2 Copyright (c), 2004-2005,2007-2010 Trident Microsystems, Inc.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
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
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.
32 * \file $Id: drxj.c,v 1.637 2010/01/18 17:21:10 dingtao Exp $
34 * \brief DRXJ specific implementation of DRX driver
36 * \author Dragan Savic, Milos Nikolic, Mihajlo Katona, Tao Ding, Paul Janssen
39 /*-----------------------------------------------------------------------------
41 ----------------------------------------------------------------------------*/
47 #include "drxj_options.h"
50 /*============================================================================*/
51 /*=== DEFINES ================================================================*/
52 /*============================================================================*/
55 * \brief Maximum u32 value.
58 #define MAX_U32 ((u32) (0xFFFFFFFFL))
61 /* Customer configurable hardware settings, etc */
62 #ifndef MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH
63 #define MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH 0x02
66 #ifndef MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH
67 #define MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH 0x02
70 #ifndef MPEG_OUTPUT_CLK_DRIVE_STRENGTH
71 #define MPEG_OUTPUT_CLK_DRIVE_STRENGTH 0x06
74 #ifndef OOB_CRX_DRIVE_STRENGTH
75 #define OOB_CRX_DRIVE_STRENGTH 0x02
78 #ifndef OOB_DRX_DRIVE_STRENGTH
79 #define OOB_DRX_DRIVE_STRENGTH 0x02
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 *********************************/
171 #include "drx_driver_version.h"
173 /* #define DRX_DEBUG */
178 /*-----------------------------------------------------------------------------
180 ----------------------------------------------------------------------------*/
182 /*-----------------------------------------------------------------------------
184 ----------------------------------------------------------------------------*/
185 #ifndef DRXJ_WAKE_UP_KEY
186 #define DRXJ_WAKE_UP_KEY (demod->my_i2c_dev_addr->i2c_addr)
190 * \def DRXJ_DEF_I2C_ADDR
191 * \brief Default I2C addres of a demodulator instance.
193 #define DRXJ_DEF_I2C_ADDR (0x52)
196 * \def DRXJ_DEF_DEMOD_DEV_ID
197 * \brief Default device identifier of a demodultor instance.
199 #define DRXJ_DEF_DEMOD_DEV_ID (1)
202 * \def DRXJ_SCAN_TIMEOUT
203 * \brief Timeout value for waiting on demod lock during channel scan (millisec).
205 #define DRXJ_SCAN_TIMEOUT 1000
209 * \brief Name of structure containing all data access protocol functions.
211 #define DRXJ_DAP drx_dap_drxj_funct_g
215 * \brief HI timing delay for I2C timing (in nano seconds)
217 * Used to compute HI_CFG_DIV
219 #define HI_I2C_DELAY 42
222 * \def HI_I2C_BRIDGE_DELAY
223 * \brief HI timing delay for I2C timing (in nano seconds)
225 * Used to compute HI_CFG_BDL
227 #define HI_I2C_BRIDGE_DELAY 750
230 * \brief Time Window for MER and SER Measurement in Units of Segment duration.
232 #define VSB_TOP_MEASUREMENT_PERIOD 64
233 #define SYMBOLS_PER_SEGMENT 832
236 * \brief bit rate and segment rate constants used for SER and BER.
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
248 * \brief Min supported symbolrates.
250 #ifndef DRXJ_QAM_SYMBOLRATE_MIN
251 #define DRXJ_QAM_SYMBOLRATE_MIN (520000)
255 * \brief Max supported symbolrates.
257 #ifndef DRXJ_QAM_SYMBOLRATE_MAX
258 #define DRXJ_QAM_SYMBOLRATE_MAX (7233000)
262 * \def DRXJ_QAM_MAX_WAITTIME
263 * \brief Maximal wait time for QAM auto constellation in ms
265 #ifndef DRXJ_QAM_MAX_WAITTIME
266 #define DRXJ_QAM_MAX_WAITTIME 900
269 #ifndef DRXJ_QAM_FEC_LOCK_WAITTIME
270 #define DRXJ_QAM_FEC_LOCK_WAITTIME 150
273 #ifndef DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME
274 #define DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME 200
278 * \def SCU status and results
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 */
287 * \def DRX_AUD_MAX_DEVIATION
288 * \brief Needed for calculation of prescale feature in AUD
290 #ifndef DRXJ_AUD_MAX_FM_DEVIATION
291 #define DRXJ_AUD_MAX_FM_DEVIATION 100 /* kHz */
295 * \brief Needed for calculation of NICAM prescale feature in AUD
297 #ifndef DRXJ_AUD_MAX_NICAM_PRESCALE
298 #define DRXJ_AUD_MAX_NICAM_PRESCALE (9) /* dB */
302 * \brief Needed for calculation of NICAM prescale feature in AUD
304 #ifndef DRXJ_AUD_MAX_WAITTIME
305 #define DRXJ_AUD_MAX_WAITTIME 250 /* ms */
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)
316 #define DRX_UIO_MODE_FIRMWARE_SMA DRX_UIO_MODE_FIRMWARE0
317 #define DRX_UIO_MODE_FIRMWARE_SAW DRX_UIO_MODE_FIRMWARE1
319 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
320 /*============================================================================*/
321 /*=== MICROCODE RELATED DEFINES ==============================================*/
322 /*============================================================================*/
325 * \def DRXJ_UCODE_MAGIC_WORD
326 * \brief Magic word for checking correct Endianess of microcode data.
330 #ifndef DRXJ_UCODE_MAGIC_WORD
331 #define DRXJ_UCODE_MAGIC_WORD ((((u16)'H')<<8)+((u16)'L'))
335 * \def DRXJ_UCODE_CRC_FLAG
336 * \brief CRC flag in ucode header, flags field.
340 #ifndef DRXJ_UCODE_CRC_FLAG
341 #define DRXJ_UCODE_CRC_FLAG (0x0001)
345 * \def DRXJ_UCODE_COMPRESSION_FLAG
346 * \brief Compression flag in ucode header, flags field.
350 #ifndef DRXJ_UCODE_COMPRESSION_FLAG
351 #define DRXJ_UCODE_COMPRESSION_FLAG (0x0002)
355 * \def DRXJ_UCODE_MAX_BUF_SIZE
356 * \brief Maximum size of buffer used to verify the microcode.Must be an even number.
360 #ifndef DRXJ_UCODE_MAX_BUF_SIZE
361 #define DRXJ_UCODE_MAX_BUF_SIZE (DRXDAP_MAX_RCHUNKSIZE)
363 #if DRXJ_UCODE_MAX_BUF_SIZE & 1
364 #error DRXJ_UCODE_MAX_BUF_SIZE must be an even number
367 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
369 /* Pin safe mode macro */
370 #define DRXJ_PIN_SAFE_MODE 0x0000
371 /*============================================================================*/
372 /*=== GLOBAL VARIABLEs =======================================================*/
373 /*============================================================================*/
378 * \brief Temporary register definitions.
379 * (register definitions that are not yet available in register master)
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 */
387 /******************************************************************************/
389 * \brief RAM location of MODUS registers
391 #define AUD_DEM_RAM_MODUS_HI__A 0x10204A3
392 #define AUD_DEM_RAM_MODUS_HI__M 0xF000
394 #define AUD_DEM_RAM_MODUS_LO__A 0x10204A4
395 #define AUD_DEM_RAM_MODUS_LO__M 0x0FFF
398 * \brief RAM location of I2S config registers
400 #define AUD_DEM_RAM_I2S_CONFIG1__A 0x10204B1
401 #define AUD_DEM_RAM_I2S_CONFIG2__A 0x10204B2
404 * \brief RAM location of DCO config registers
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
412 * \brief RAM location of Threshold registers
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
419 * \brief RAM location of Carrier Threshold registers
421 #define AUD_DEM_RAM_CM_A_THRSHLD__A 0x10204AF
422 #define AUD_DEM_RAM_CM_B_THRSHLD__A 0x10204B0
425 * \brief FM Matrix register fix
427 #ifdef AUD_DEM_WR_FM_MATRIX__A
428 #undef AUD_DEM_WR_FM_MATRIX__A
430 #define AUD_DEM_WR_FM_MATRIX__A 0x105006F
432 /*============================================================================*/
434 * \brief Defines required for audio
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
447 * \brief Needed for calculation of prescale feature in AUD
449 #ifndef DRX_AUD_MAX_FM_DEVIATION
450 #define DRX_AUD_MAX_FM_DEVIATION (100) /* kHz */
454 * \brief Needed for calculation of NICAM prescale feature in AUD
456 #ifndef DRX_AUD_MAX_NICAM_PRESCALE
457 #define DRX_AUD_MAX_NICAM_PRESCALE (9) /* dB */
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
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
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
477 /*============================================================================*/
478 /*=== REGISTER ACCESS MACROS =================================================*/
479 /*============================================================================*/
481 #ifdef DRXJDRIVER_DEBUG
483 #define CHK_ERROR(s) \
485 if ((s) != DRX_STS_OK) \
488 "ERROR[\n file : %s\n line : %d\n]\n", \
489 __FILE__, __LINE__); \
494 #define CHK_ERROR(s) \
496 if ((s) != DRX_STS_OK) { goto rw_error; } \
500 #define CHK_ZERO(s) \
502 if ((s) == 0) return DRX_STS_ERROR; \
505 #define DUMMY_READ() \
508 RR16(demod->my_i2c_dev_addr, SCU_RAM_VERSION_HI__A, &dummy); \
511 #define WR16(dev, addr, val) \
512 CHK_ERROR(DRXJ_DAP.write_reg16func( (dev), (addr), (val), 0) )
514 #define RR16(dev, addr, val) \
515 CHK_ERROR(DRXJ_DAP.read_reg16func( (dev), (addr), (val), 0) )
517 #define WR32(dev, addr, val) \
518 CHK_ERROR(DRXJ_DAP.write_reg32func( (dev), (addr), (val), 0) )
520 #define RR32(dev, addr, val) \
521 CHK_ERROR(DRXJ_DAP.read_reg32func( (dev), (addr), (val), 0) )
523 #define WRB(dev, addr, len, block) \
524 CHK_ERROR(DRXJ_DAP.write_block_func( (dev), (addr), (len), (block), 0) )
526 #define RRB(dev, addr, len, block) \
527 CHK_ERROR(DRXJ_DAP.read_block_func( (dev), (addr), (len), (block), 0) )
529 #define BCWR16(dev, addr, val) \
530 CHK_ERROR(DRXJ_DAP.write_reg16func( (dev), (addr), (val), DRXDAP_FASI_BROADCAST) )
532 #define ARR32(dev, addr, val) \
533 CHK_ERROR(drxj_dap_atomic_read_reg32( (dev), (addr), (val), 0) )
535 #define SARR16(dev, addr, val) \
536 CHK_ERROR(drxj_dap_scu_atomic_read_reg16( (dev), (addr), (val), 0) )
538 #define SAWR16(dev, addr, val) \
539 CHK_ERROR(drxj_dap_scu_atomic_write_reg16( (dev), (addr), (val), 0) )
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)
547 #define DRXJ_16TO8(x) ((u8) (((u16)x) & 0xFF)), \
548 ((u8)((((u16)x)>>8)&0xFF))
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.
554 #define DRXJ_8TO16(x) ((u16) (x[0] | (x[1] << 8)))
556 /*============================================================================*/
557 /*=== MISC DEFINES ===========================================================*/
558 /*============================================================================*/
560 /*============================================================================*/
561 /*=== HI COMMAND RELATED DEFINES =============================================*/
562 /*============================================================================*/
565 * \brief General maximum number of retries for ucode command interfaces
567 #define DRXJ_MAX_RETRIES (100)
569 /*============================================================================*/
570 /*=== STANDARD RELATED MACROS ================================================*/
571 /*============================================================================*/
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) )
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))
586 /*-----------------------------------------------------------------------------
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);
594 /*-----------------------------------------------------------------------------
596 ----------------------------------------------------------------------------*/
598 * DRXJ DAP structures
601 static int drxj_dap_read_block(struct i2c_device_addr *dev_addr,
604 u8 *data, dr_xflags_t flags);
606 static int drxj_dap_read_modify_write_reg8(struct i2c_device_addr *dev_addr,
609 u8 wdata, u8 *rdata);
611 static int drxj_dap_read_modify_write_reg16(struct i2c_device_addr *dev_addr,
614 u16 wdata, u16 *rdata);
616 static int drxj_dap_read_modify_write_reg32(struct i2c_device_addr *dev_addr,
619 u32 wdata, u32 *rdata);
621 static int drxj_dap_read_reg8(struct i2c_device_addr *dev_addr,
623 u8 *data, dr_xflags_t flags);
625 static int drxj_dap_read_reg16(struct i2c_device_addr *dev_addr,
627 u16 *data, dr_xflags_t flags);
629 static int drxj_dap_read_reg32(struct i2c_device_addr *dev_addr,
631 u32 *data, dr_xflags_t flags);
633 static int drxj_dap_write_block(struct i2c_device_addr *dev_addr,
636 u8 *data, dr_xflags_t flags);
638 static int drxj_dap_write_reg8(struct i2c_device_addr *dev_addr,
640 u8 data, dr_xflags_t flags);
642 static int drxj_dap_write_reg16(struct i2c_device_addr *dev_addr,
644 u16 data, dr_xflags_t flags);
646 static int drxj_dap_write_reg32(struct i2c_device_addr *dev_addr,
648 u32 data, dr_xflags_t flags);
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";
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 */
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 */
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 */
682 * /brief The driver functions of the drxj
684 drx_demod_func_t drxj_functions_g = {
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... */
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 */
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 */
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 */
724 /* HI configuration */
725 0, /* hi_cfg_timing_div */
726 0, /* hi_cfg_bridge_delay */
727 0, /* hi_cfg_wake_up_key */
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 */
736 0UL, /* iqm_fs_rate_ofs */
737 false, /* pos_image */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
808 0x0000, /* top (don't care) */
809 0x0000 /* c.o.c. (don't care) */
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 */
818 0x0000, /* top (don't care) */
819 0x0000 /* c.o.c. (don't care) */
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 */
828 0x0000, /* top (don't care) */
829 0x0000 /* c.o.c. (don't care) */
833 { /* qam_pre_saw_cfg */
834 DRX_STANDARD_ITU_B, /* standard */
836 false /* use_pre_saw */
838 { /* vsb_pre_saw_cfg */
839 DRX_STANDARD_8VSB, /* standard */
841 false /* use_pre_saw */
844 /* Version information */
847 "01234567890", /* human readable version microcode */
848 "01234567890" /* human readable version device specific code */
851 { /* drx_version_t for microcode */
859 { /* drx_version_t for device specific code */
869 { /* drx_version_list_t for microcode */
870 (pdrx_version_t) (NULL),
871 (p_drx_version_list_t) (NULL)
873 { /* drx_version_list_t for device specific code */
874 (pdrx_version_t) (NULL),
875 (p_drx_version_list_t) (NULL)
879 false, /* smart_ant_inverted */
880 /* Tracking filter setting for OOB */
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 */
897 /* Pre SAW & Agc configuration for ATV */
899 DRX_STANDARD_NTSC, /* standard */
901 true /* use_pre_saw */
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.) */
911 4000 /* cut-off current */
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.) */
921 0 /* c.o.c. (d.c.) */
923 140, /* ATV PGA config */
924 0, /* curr_symbol_rate */
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 */
933 DRXJ_OOB_LO_POW_MINUS10DB, /* oob_lo_pow */
935 false /* aud_data, only first member */
940 * \var drxj_default_addr_g
941 * \brief Default I2C address and device identifier.
943 struct i2c_device_addr drxj_default_addr_g = {
944 DRXJ_DEF_I2C_ADDR, /* i2c address */
945 DRXJ_DEF_DEMOD_DEV_ID /* device id */
949 * \var drxj_default_comm_attr_g
950 * \brief Default common attributes of a drxj demodulator instance.
952 drx_common_attr_t drxj_default_comm_attr_g = {
953 (u8 *) NULL, /* ucode ptr */
955 true, /* ucode verify switch */
956 {0}, /* version record */
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 */
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 */
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 */
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 */
998 /* Power management */
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 */
1009 { /* current channel (all 0) */
1010 0UL /* channel.frequency */
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 */
1021 * \var drxj_default_demod_g
1022 * \brief Default drxj demodulator instance.
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 */
1034 * \brief Default audio data structure for DRK demodulator instance.
1036 * This structure is DRXK specific.
1039 drx_aud_data_t drxj_default_aud_data_g = {
1040 false, /* audio_is_active */
1041 DRX_AUD_STANDARD_AUTO, /* audio_standard */
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 */
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 */
1063 DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_ON, /* auto_sound */
1064 /* ass_thresholds */
1075 DRX_NO_CARRIER_NOISE, /* opt */
1082 DRX_NO_CARRIER_MUTE, /* opt */
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 */
1094 DRX_AUD_DEVIATION_NORMAL, /* deviation */
1095 DRX_AUD_AVSYNC_OFF, /* av_sync */
1099 DRX_AUD_MAX_FM_DEVIATION, /* fm_deviation */
1100 DRX_AUD_MAX_NICAM_PRESCALE /* nicam_gain */
1102 DRX_AUD_FM_DEEMPH_75US, /* deemph */
1103 DRX_BTSC_STEREO, /* btsc_detect */
1104 0, /* rds_data_counter */
1105 false /* rds_data_present */
1108 /*-----------------------------------------------------------------------------
1110 ----------------------------------------------------------------------------*/
1116 } drxjeq_stat_t, *pdrxjeq_stat_t;
1127 } drxj_hi_cmd_t, *pdrxj_hi_cmd_t;
1129 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
1130 /*============================================================================*/
1131 /*=== MICROCODE RELATED STRUCTURES ===========================================*/
1132 /*============================================================================*/
1137 u16 flags; /* bit[15..2]=reserved,
1138 bit[1]= compression on/off
1139 bit[0]= CRC on/off */
1141 } drxu_code_block_hdr_t, *pdrxu_code_block_hdr_t;
1142 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
1144 /*-----------------------------------------------------------------------------
1146 ----------------------------------------------------------------------------*/
1147 /* Some prototypes */
1149 hi_command(struct i2c_device_addr *dev_addr,
1150 const pdrxj_hi_cmd_t cmd, u16 *result);
1153 ctrl_lock_status(pdrx_demod_instance_t demod, pdrx_lock_status_t lock_stat);
1156 ctrl_power_mode(pdrx_demod_instance_t demod, pdrx_power_mode_t mode);
1158 static int power_down_aud(pdrx_demod_instance_t demod);
1160 #ifndef DRXJ_DIGITAL_ONLY
1161 static int power_up_aud(pdrx_demod_instance_t demod, bool set_standard);
1165 aud_ctrl_set_standard(pdrx_demod_instance_t demod, pdrx_aud_standard_t standard);
1168 ctrl_set_cfg_pre_saw(pdrx_demod_instance_t demod, p_drxj_cfg_pre_saw_t pre_saw);
1171 ctrl_set_cfg_afe_gain(pdrx_demod_instance_t demod, p_drxj_cfg_afe_gain_t afe_gain);
1173 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
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 */
1180 /*============================================================================*/
1181 /*============================================================================*/
1182 /*== HELPER FUNCTIONS ==*/
1183 /*============================================================================*/
1184 /*============================================================================*/
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
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.
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.
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.
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
1222 * Note that the function is type size independent. Any unsigned integer type
1223 * can be substituted for booth_t.
1227 #define DRX_IS_BOOTH_NEGATIVE(__a) (((__a) & (1 << (sizeof(u32) * 8 - 1))) != 0)
1229 static void mult32(u32 a, u32 b, u32 *h, u32 *l)
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));
1241 /* Take the first three bits of operand a for the Booth conversion: */
1242 /* 0, 7: do nothing */
1245 /* 4 : subtract 2b */
1246 /* 5, 6: subtract b */
1247 switch (a >> (sizeof(a) * 8 - 3)) {
1250 *h = *h - DRX_IS_BOOTH_NEGATIVE(b) + (*l < b);
1254 *h = *h - DRX_IS_BOOTH_NEGATIVE(b) + (*l < b);
1258 *h = *h - !DRX_IS_BOOTH_NEGATIVE(b) + !b + (*l <
1266 *h = *h - !DRX_IS_BOOTH_NEGATIVE(b) + !b + (*l <
1276 /*============================================================================*/
1279 * \fn u32 frac28(u32 N, u32 D)
1280 * \brief Compute: (1<<28)*N/D
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.
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.
1292 * Usage condition: ((1<<28)*n)/d < ((1<<32)-1) => (n/d) < 15.999
1294 * N: 0...(1<<28)-1 = 268435454
1298 static u32 frac28(u32 N, u32 D)
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 */
1308 /* division using radix 16, 7 nibbles in the result */
1309 for (i = 0; i < 7; i++) {
1310 Q1 = (Q1 << 4) | R0 / D;
1321 * \fn u32 log1_times100( u32 x)
1322 * \brief Compute: 100*log10(x)
1324 * \return 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
1333 * where y = 2^k and 1<= (x/y) < 2
1336 static u32 log1_times100(u32 x)
1338 static const u8 scale = 15;
1339 static const u8 index_width = 5;
1341 log2lut[n] = (1<<scale) * 200 * log2( 1.0 + ( (1.0/(1<<INDEXWIDTH)) * n ))
1342 0 <= n < ((1<<INDEXWIDTH)+1)
1345 static const u32 log2lut[] = {
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 */
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))
1399 for (k = scale; k < 31; k++) {
1400 if ((x & (((u32) (-1)) << (scale + 1))) == 0)
1406 Now x has binary point between bit[scale] and bit[scale-1]
1407 and 1.0 <= x < 2.0 */
1409 /* correction for divison: log(x) = log(x/y)+log(y) */
1410 y = k * ((((u32) 1) << scale) * 200);
1412 /* remove integer part */
1413 x &= ((((u32) 1) << scale) - 1);
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 ! */
1420 ((d * (log2lut[i + 1] - log2lut[i])) >> (scale - index_width));
1421 /* Conver to log10() */
1422 y /= 108853; /* (log2(10) << scale) */
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.
1438 * \retval ((N/D) * 1000000), 32 bits
1442 static u32 frac_times1e6(u32 N, u32 D)
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.
1454 frac = (((u32) N) * (1000000 >> 4)) / D;
1456 remainder = (((u32) N) * (1000000 >> 4)) % D;
1458 frac += remainder / D;
1459 remainder = remainder % D;
1460 if ((remainder * 2) > D) {
1467 /*============================================================================*/
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
1475 static u32 d_b2lin_times100(u32 gd_b)
1478 u32 nr6d_b_steps = 0;
1480 u32 remainder_fac = 0;
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 */
1488 result = (1 << nr6d_b_steps);
1490 /* calculate remaining factor,
1491 poly approximation of 10^(gd_b/200):
1493 y = 1E-04x2 + 0.0106x + 1.0026
1495 max deviation < 0.005 for range x = [0 ... 60]
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;
1503 /* multiply by remaining factor */
1504 result *= remainder_fac;
1506 /* conversion from 1e-4 to 1e-2 */
1507 return ((result + 50) / 100);
1510 #ifndef DRXJ_DIGITAL_ONLY
1511 #define FRAC_FLOOR 0
1513 #define FRAC_ROUND 2
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
1521 * \retval N/D, 32 bits
1525 static u32 frac(u32 N, u32 D, u16 RC)
1544 while (bit_cnt-- > 0) {
1546 remainder |= ((frac & 0x80000000) >> 31);
1548 if (remainder < D) {
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) */
1562 if ((RC == FRAC_ROUND) && (remainder >= D >> 1)) {
1563 /* remainder is bigger from D/2 -> round the result */
1572 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
1573 /*============================================================================*/
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.
1580 static u16 u_code_read16(u8 *addr)
1582 /* Works fo any host processor */
1586 word = ((u16) addr[0]);
1588 word |= ((u16) addr[1]);
1593 /*============================================================================*/
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.
1600 static u32 u_code_read32(u8 *addr)
1602 /* Works fo any host processor */
1606 word = ((u16) addr[0]);
1608 word |= ((u16) addr[1]);
1610 word |= ((u16) addr[2]);
1612 word |= ((u16) addr[3]);
1617 /*============================================================================*/
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.
1626 static u16 u_code_compute_crc(u8 *block_data, u16 nr_words)
1633 while (i < nr_words) {
1634 crc_word |= (u32) u_code_read16(block_data);
1635 for (j = 0; j < 16; j++) {
1638 crc_word ^= 0x80050000UL;
1639 carry = crc_word & 0x80000000UL;
1642 block_data += (sizeof(u16));
1644 return ((u16) (crc_word >> 16));
1646 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
1649 * \brief Values for NICAM prescaler gain. Computed from dB to integer
1650 * and rounded. For calc used formula: 16*10^(prescaleGain[dB]/20).
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
1660 /*============================================================================*/
1661 /*== END HELPER FUNCTIONS ==*/
1662 /*============================================================================*/
1664 /*============================================================================*/
1665 /*============================================================================*/
1666 /*== DRXJ DAP FUNCTIONS ==*/
1667 /*============================================================================*/
1668 /*============================================================================*/
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.
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.
1683 TODO: check ignoring single/multimaster is ok for AUD access ?
1686 #define DRXJ_ISAUDWRITE(addr) (((((addr)>>16)&1) == 1)?true:false)
1687 #define DRXJ_DAP_AUDTRIF_TIMEOUT 80 /* millisec */
1688 /*============================================================================*/
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.
1695 * \retval true Yes, handled by audio token ring interface
1696 * \retval false No, not handled by audio token ring interface
1700 bool is_handled_by_aud_tr_if(dr_xaddr_t addr)
1702 bool retval = false;
1704 if ((DRXDAP_FASI_ADDR2BLOCK(addr) == 4) &&
1705 (DRXDAP_FASI_ADDR2BANK(addr) > 1) &&
1706 (DRXDAP_FASI_ADDR2BANK(addr) < 6)) {
1713 /*============================================================================*/
1715 static int drxj_dap_read_block(struct i2c_device_addr *dev_addr,
1718 u8 *data, dr_xflags_t flags)
1720 return drx_dap_fasi_funct_g.read_block_func(dev_addr,
1721 addr, datasize, data, flags);
1724 /*============================================================================*/
1726 static int drxj_dap_read_modify_write_reg8(struct i2c_device_addr *dev_addr,
1729 u8 wdata, u8 *rdata)
1731 return drx_dap_fasi_funct_g.read_modify_write_reg8func(dev_addr,
1733 raddr, wdata, rdata);
1736 /*============================================================================*/
1739 * \fn int drxj_dap_rm_write_reg16short
1740 * \brief Read modify write 16 bits audio register using short format only.
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
1747 * \retval DRX_STS_OK Succes
1748 * \retval DRX_STS_ERROR Timeout, I2C error, illegal bank
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.
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,
1762 u16 wdata, u16 *rdata)
1766 if (rdata == NULL) {
1767 return DRX_STS_INVALID_ARG;
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,
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,
1780 if (rc == DRX_STS_OK) {
1782 rc = drx_dap_fasi_funct_g.read_reg16func(dev_addr, raddr, rdata,
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,
1796 /*============================================================================*/
1798 static int drxj_dap_read_modify_write_reg16(struct i2c_device_addr *dev_addr,
1801 u16 wdata, u16 *rdata)
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,
1809 raddr, wdata, rdata);
1811 return drxj_dap_rm_write_reg16short(dev_addr, waddr, raddr, wdata, rdata);
1815 /*============================================================================*/
1817 static int drxj_dap_read_modify_write_reg32(struct i2c_device_addr *dev_addr,
1820 u32 wdata, u32 *rdata)
1822 return drx_dap_fasi_funct_g.read_modify_write_reg32func(dev_addr,
1824 raddr, wdata, rdata);
1827 /*============================================================================*/
1829 static int drxj_dap_read_reg8(struct i2c_device_addr *dev_addr,
1831 u8 *data, dr_xflags_t flags)
1833 return drx_dap_fasi_funct_g.read_reg8func(dev_addr, addr, data, flags);
1836 /*============================================================================*/
1839 * \fn int drxj_dap_read_aud_reg16
1840 * \brief Read 16 bits audio register
1845 * \retval DRX_STS_OK Succes
1846 * \retval DRX_STS_ERROR Timeout, I2C error, illegal bank
1848 * 16 bits register read access via audio token ring interface.
1851 static int drxj_dap_read_aud_reg16(struct i2c_device_addr *dev_addr,
1852 dr_xaddr_t addr, u16 *data)
1854 u32 start_timer = 0;
1855 u32 current_timer = 0;
1856 u32 delta_timer = 0;
1858 int stat = DRX_STS_ERROR;
1860 /* No read possible for bank 3, return with error */
1861 if (DRXDAP_FASI_ADDR2BANK(addr) == 3) {
1862 stat = DRX_STS_INVALID_ARG;
1864 const dr_xaddr_t write_bit = ((dr_xaddr_t) 1) << 16;
1866 /* Force reset write bit */
1867 addr &= (~write_bit);
1870 start_timer = drxbsp_hst_clock();
1872 /* RMW to aud TR IF until request is granted or timeout */
1873 stat = drxj_dap_read_modify_write_reg16(dev_addr,
1875 SIO_HI_RA_RAM_S0_RMWBUF__A,
1876 0x0000, &tr_status);
1878 if (stat != DRX_STS_OK) {
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;
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 ) */
1895 /* Wait for read ready status or timeout */
1896 if (stat == DRX_STS_OK) {
1897 start_timer = drxbsp_hst_clock();
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,
1903 &tr_status, 0x0000);
1904 if (stat != DRX_STS_OK) {
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;
1914 } /* while ( ... ) */
1917 /* if { stat == DRX_STS_OK ) */
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,
1925 /* if { stat == DRX_STS_OK ) */
1929 /*============================================================================*/
1931 static int drxj_dap_read_reg16(struct i2c_device_addr *dev_addr,
1933 u16 *data, dr_xflags_t flags)
1935 int stat = DRX_STS_ERROR;
1938 if ((dev_addr == NULL) || (data == NULL)) {
1939 return DRX_STS_INVALID_ARG;
1942 if (is_handled_by_aud_tr_if(addr)) {
1943 stat = drxj_dap_read_aud_reg16(dev_addr, addr, data);
1945 stat = drx_dap_fasi_funct_g.read_reg16func(dev_addr,
1952 /*============================================================================*/
1954 static int drxj_dap_read_reg32(struct i2c_device_addr *dev_addr,
1956 u32 *data, dr_xflags_t flags)
1958 return drx_dap_fasi_funct_g.read_reg32func(dev_addr, addr, data, flags);
1961 /*============================================================================*/
1963 static int drxj_dap_write_block(struct i2c_device_addr *dev_addr,
1966 u8 *data, dr_xflags_t flags)
1968 return drx_dap_fasi_funct_g.write_block_func(dev_addr,
1969 addr, datasize, data, flags);
1972 /*============================================================================*/
1974 static int drxj_dap_write_reg8(struct i2c_device_addr *dev_addr,
1976 u8 data, dr_xflags_t flags)
1978 return drx_dap_fasi_funct_g.write_reg8func(dev_addr, addr, data, flags);
1981 /*============================================================================*/
1984 * \fn int drxj_dap_write_aud_reg16
1985 * \brief Write 16 bits audio register
1990 * \retval DRX_STS_OK Succes
1991 * \retval DRX_STS_ERROR Timeout, I2C error, illegal bank
1993 * 16 bits register write access via audio token ring interface.
1996 static int drxj_dap_write_aud_reg16(struct i2c_device_addr *dev_addr,
1997 dr_xaddr_t addr, u16 data)
1999 int stat = DRX_STS_ERROR;
2001 /* No write possible for bank 2, return with error */
2002 if (DRXDAP_FASI_ADDR2BANK(addr) == 2) {
2003 stat = DRX_STS_INVALID_ARG;
2005 u32 start_timer = 0;
2006 u32 current_timer = 0;
2007 u32 delta_timer = 0;
2009 const dr_xaddr_t write_bit = ((dr_xaddr_t) 1) << 16;
2011 /* Force write bit */
2013 start_timer = drxbsp_hst_clock();
2015 /* RMW to aud TR IF until request is granted or timeout */
2016 stat = drxj_dap_read_modify_write_reg16(dev_addr,
2018 SIO_HI_RA_RAM_S0_RMWBUF__A,
2020 if (stat != DRX_STS_OK) {
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;
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));
2036 } /* if ( DRXDAP_FASI_ADDR2BANK(addr)!=2 ) */
2041 /*============================================================================*/
2043 static int drxj_dap_write_reg16(struct i2c_device_addr *dev_addr,
2045 u16 data, dr_xflags_t flags)
2047 int stat = DRX_STS_ERROR;
2050 if (dev_addr == NULL) {
2051 return DRX_STS_INVALID_ARG;
2054 if (is_handled_by_aud_tr_if(addr)) {
2055 stat = drxj_dap_write_aud_reg16(dev_addr, addr, data);
2057 stat = drx_dap_fasi_funct_g.write_reg16func(dev_addr,
2064 /*============================================================================*/
2066 static int drxj_dap_write_reg32(struct i2c_device_addr *dev_addr,
2068 u32 data, dr_xflags_t flags)
2070 return drx_dap_fasi_funct_g.write_reg32func(dev_addr, addr, data, flags);
2073 /*============================================================================*/
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
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
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
2092 * \retval DRX_STS_OK Succes
2093 * \retval DRX_STS_ERROR Timeout, I2C error, illegal bank
2097 int drxj_dap_atomic_read_write_block(struct i2c_device_addr *dev_addr,
2100 u8 *data, bool read_flag)
2102 drxj_hi_cmd_t hi_cmd;
2108 /* Parameter check */
2109 if ((data == NULL) ||
2110 (dev_addr == NULL) || ((datasize % 2) != 0) || ((datasize / 2) > 8)
2112 return (DRX_STS_INVALID_ARG);
2115 /* Set up HI parameters to read or write n bytes */
2116 hi_cmd.cmd = SIO_HI_RA_RAM_CMD_ATOMIC_COPY;
2118 (u16) ((DRXDAP_FASI_ADDR2BLOCK(DRXJ_HI_ATOMIC_BUF_START) << 6) +
2119 DRXDAP_FASI_ADDR2BANK(DRXJ_HI_ATOMIC_BUF_START));
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;
2126 hi_cmd.param3 |= DRXJ_HI_ATOMIC_READ;
2128 hi_cmd.param4 = (u16) ((DRXDAP_FASI_ADDR2BLOCK(addr) << 6) +
2129 DRXDAP_FASI_ADDR2BANK(addr));
2130 hi_cmd.param5 = (u16) DRXDAP_FASI_ADDR2OFFSET(addr);
2132 if (read_flag == false) {
2133 /* write data to buffer */
2134 for (i = 0; i < (datasize / 2); i++) {
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),
2144 CHK_ERROR(hi_command(dev_addr, &hi_cmd, &dummy));
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),
2152 data[2 * i] = (u8) (word & 0xFF);
2153 data[(2 * i) + 1] = (u8) (word >> 8);
2160 return (DRX_STS_ERROR);
2164 /*============================================================================*/
2167 * \fn int drxj_dap_atomic_read_reg32()
2168 * \brief Atomic read of 32 bits words
2171 int drxj_dap_atomic_read_reg32(struct i2c_device_addr *dev_addr,
2173 u32 *data, dr_xflags_t flags)
2175 u8 buf[sizeof(*data)];
2176 int rc = DRX_STS_ERROR;
2180 return DRX_STS_INVALID_ARG;
2183 rc = drxj_dap_atomic_read_write_block(dev_addr, addr,
2184 sizeof(*data), buf, true);
2186 word = (u32) buf[3];
2188 word |= (u32) buf[2];
2190 word |= (u32) buf[1];
2192 word |= (u32) buf[0];
2199 /*============================================================================*/
2201 /*============================================================================*/
2202 /*== END DRXJ DAP FUNCTIONS ==*/
2203 /*============================================================================*/
2205 /*============================================================================*/
2206 /*============================================================================*/
2207 /*== HOST INTERFACE FUNCTIONS ==*/
2208 /*============================================================================*/
2209 /*============================================================================*/
2212 * \fn int hi_cfg_command()
2213 * \brief Configure HI with settings stored in the demod structure.
2214 * \param demod Demodulator.
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.
2222 static int hi_cfg_command(const pdrx_demod_instance_t demod)
2224 pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
2225 drxj_hi_cmd_t hi_cmd;
2228 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
2238 CHK_ERROR(hi_command(demod->my_i2c_dev_addr, &hi_cmd, &result));
2240 /* Reset power down flag (set one call only) */
2241 ext_attr->hi_cfg_ctrl &= (~(SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ));
2243 return (DRX_STS_OK);
2246 return (DRX_STS_ERROR);
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.
2257 * Sends command to HI
2261 hi_command(struct i2c_device_addr *dev_addr, const pdrxj_hi_cmd_t cmd, u16 *result)
2265 bool powerdown_cmd = false;
2267 /* Write parameters */
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);
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);
2281 case SIO_HI_RA_RAM_CMD_NULL:
2286 return (DRX_STS_INVALID_ARG);
2291 WR16(dev_addr, SIO_HI_RA_RAM_CMD__A, cmd->cmd);
2293 if ((cmd->cmd) == SIO_HI_RA_RAM_CMD_RESET) {
2294 /* Allow for HI to reset */
2295 drxbsp_hst_sleep(1);
2298 /* Detect power down to ommit reading result */
2299 powerdown_cmd = (bool) ((cmd->cmd == SIO_HI_RA_RAM_CMD_CONFIG) &&
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 */
2307 if (nr_retries > DRXJ_MAX_RETRIES) {
2311 RR16(dev_addr, SIO_HI_RA_RAM_CMD__A, &wait_cmd);
2312 } while (wait_cmd != 0);
2315 RR16(dev_addr, SIO_HI_RA_RAM_RES__A, result);
2318 /* if ( powerdown_cmd == true ) */
2319 return (DRX_STS_OK);
2321 return (DRX_STS_ERROR);
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.
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.
2337 static int init_hi(const pdrx_demod_instance_t demod)
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);
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;
2347 /* PATCH for bug 5003, HI ucode v3.1.0 */
2348 WR16(dev_addr, 0x4301D7, 0x801);
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;
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;
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) /
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;
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;
2380 CHK_ERROR(hi_cfg_command(demod));
2382 return (DRX_STS_OK);
2385 return (DRX_STS_ERROR);
2388 /*============================================================================*/
2389 /*== END HOST INTERFACE FUNCTIONS ==*/
2390 /*============================================================================*/
2392 /*============================================================================*/
2393 /*============================================================================*/
2394 /*== AUXILIARY FUNCTIONS ==*/
2395 /*============================================================================*/
2396 /*============================================================================*/
2399 * \fn int get_device_capabilities()
2400 * \brief Get and store device capabilities.
2401 * \param demod Pointer to demodulator instance.
2403 * \return DRX_STS_OK Success
2404 * \retval DRX_STS_ERROR Failure
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
2414 static int get_device_capabilities(pdrx_demod_instance_t demod)
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;
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;
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);
2431 switch ((sio_pdr_ohw_cfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) {
2433 /* ignore (bypass ?) */
2437 common_attr->osc_clock_freq = 27000;
2441 common_attr->osc_clock_freq = 20250;
2445 common_attr->osc_clock_freq = 4000;
2448 return (DRX_STS_ERROR);
2452 Determine device capabilities
2453 Based on pinning v47
2455 RR32(dev_addr, SIO_TOP_JTAGID_LO__A, &sio_top_jtagid_lo);
2456 ext_attr->mfx = (u8) ((sio_top_jtagid_lo >> 29) & 0xF);
2458 switch ((sio_top_jtagid_lo >> 12) & 0xFF) {
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);
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
2565 /* Unknown device variant */
2566 return (DRX_STS_ERROR);
2570 return (DRX_STS_OK);
2572 return (DRX_STS_ERROR);
2576 * \fn int power_up_device()
2577 * \brief Power up device.
2578 * \param demod Pointer to demodulator instance.
2580 * \return DRX_STS_OK Success
2581 * \retval DRX_STS_ERROR Failure, I2C or max retries reached
2585 #ifndef DRXJ_MAX_RETRIES_POWERUP
2586 #define DRXJ_MAX_RETRIES_POWERUP 10
2589 static int power_up_device(pdrx_demod_instance_t demod)
2591 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) (NULL);
2593 u16 retry_count = 0;
2594 struct i2c_device_addr wake_up_addr;
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) */
2605 drxbsp_i2c_write_read(&wake_up_addr, 1, &data,
2606 (struct i2c_device_addr *) (NULL), 0,
2608 drxbsp_hst_sleep(10);
2610 } while ((drxbsp_i2c_write_read
2611 ((struct i2c_device_addr *) (NULL), 0, (u8 *) (NULL), dev_addr, 1,
2613 != DRX_STS_OK) && (retry_count < DRXJ_MAX_RETRIES_POWERUP));
2615 /* Need some recovery time .... */
2616 drxbsp_hst_sleep(10);
2618 if (retry_count == DRXJ_MAX_RETRIES_POWERUP) {
2619 return (DRX_STS_ERROR);
2622 return (DRX_STS_OK);
2625 /*----------------------------------------------------------------------------*/
2626 /* MPEG Output Configuration Functions - begin */
2627 /*----------------------------------------------------------------------------*/
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.
2635 * Configure MPEG output parameters.
2639 ctrl_set_cfg_mpeg_output(pdrx_demod_instance_t demod, pdrx_cfg_mpeg_output_t cfg_data)
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;
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);
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;
2666 if (cfg_data->enable_mpeg_output == true) {
2667 /* quick and dirty patch to set MPEG incase current std is not
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:
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);
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);
2707 case DRX_STANDARD_ITU_A:
2708 case DRX_STANDARD_ITU_C:
2709 switch (ext_attr->constellation) {
2710 case DRX_CONSTELLATION_QAM256:
2713 case DRX_CONSTELLATION_QAM128:
2716 case DRX_CONSTELLATION_QAM64:
2719 case DRX_CONSTELLATION_QAM32:
2722 case DRX_CONSTELLATION_QAM16:
2726 return (DRX_STS_ERROR);
2727 } /* ext_attr->constellation */
2728 /* max_bit_rate = symbol_rate * nr_bits * coef */
2729 /* coef = 188/204 */
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);
2746 WR16(dev_addr, FEC_OC_RCN_GAIN__A,
2747 FEC_OC_RCN_GAIN__PRE);
2749 WR16(dev_addr, FEC_OC_SNC_LWM__A, 2);
2750 WR16(dev_addr, FEC_OC_SNC_HWM__A, 12);
2754 } /* swtich (standard) */
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;
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;
2774 case DRX_CONSTELLATION_QAM64:
2775 rcn_rate = 0x005F64D4;
2778 return (DRX_STS_ERROR);
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 */
2787 (u32) (common_attr->sys_clock_freq / 8))) /
2791 return (DRX_STS_ERROR);
2792 } /* ext_attr->standard */
2793 } else { /* insert_rs_byte == false */
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;
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;
2809 case DRX_CONSTELLATION_QAM64:
2810 rcn_rate = 0x005AEC1A;
2813 return (DRX_STS_ERROR);
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 */
2822 (u32) (common_attr->sys_clock_freq / 8))) /
2826 return (DRX_STS_ERROR);
2827 } /* ext_attr->standard */
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;
2836 /* Control slective inversion of output bits */
2837 if (cfg_data->invert_data == true) {
2838 fec_oc_reg_ipr_invert |= invert_data_mask;
2840 fec_oc_reg_ipr_invert &= (~(invert_data_mask));
2843 if (cfg_data->invert_err == true) {
2844 fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MERR__M;
2846 fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MERR__M));
2849 if (cfg_data->invert_str == true) {
2850 fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MSTRT__M;
2852 fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MSTRT__M));
2855 if (cfg_data->invert_val == true) {
2856 fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MVAL__M;
2858 fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MVAL__M));
2861 if (cfg_data->invert_clk == true) {
2862 fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MCLK__M;
2864 fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MCLK__M));
2867 if (cfg_data->static_clk == true) { /* Static mode */
2870 u16 fec_oc_dto_burst_len = 0;
2871 u16 fec_oc_dto_period = 0;
2873 fec_oc_dto_burst_len = FEC_OC_DTO_BURST_LEN__PRE;
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;
2882 case DRX_STANDARD_ITU_A:
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;
2889 if (ext_attr->curr_symbol_rate >=
2891 fec_oc_dto_period = 0;
2893 fec_oc_dto_period = 1;
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;
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;
2910 return (DRX_STS_ERROR);
2913 common_attr->sys_clock_freq * 1000 / (fec_oc_dto_period +
2916 frac28(bit_rate, common_attr->sys_clock_freq * 1000);
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)
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 */
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);
2942 WR32(dev_addr, FEC_OC_RCN_CTL_RATE_LO__A, rcn_rate);
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);
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);
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 */
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);
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);
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);
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;
3023 return (DRX_STS_OK);
3025 return (DRX_STS_ERROR);
3028 /*----------------------------------------------------------------------------*/
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.
3037 * Retrieve MPEG output configuartion.
3041 ctrl_get_cfg_mpeg_output(pdrx_demod_instance_t demod, pdrx_cfg_mpeg_output_t cfg_data)
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;
3050 if (cfg_data == NULL) {
3051 return (DRX_STS_INVALID_ARG);
3053 dev_addr = demod->my_i2c_dev_addr;
3054 common_attr = demod->my_common_attr;
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;
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,
3073 cfg_data->bitrate = (data64hi << 7) | (data64lo >> 25);
3076 return (DRX_STS_OK);
3078 return (DRX_STS_ERROR);
3081 /*----------------------------------------------------------------------------*/
3082 /* MPEG Output Configuration Functions - end */
3083 /*----------------------------------------------------------------------------*/
3085 /*----------------------------------------------------------------------------*/
3086 /* miscellaneous configuartions - begin */
3087 /*----------------------------------------------------------------------------*/
3090 * \fn int set_mpegtei_handling()
3091 * \brief Activate MPEG TEI handling settings.
3092 * \param devmod Pointer to demodulator instance.
3095 * This routine should be called during a set channel of QAM/VSB
3098 static int set_mpegtei_handling(pdrx_demod_instance_t demod)
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;
3106 dev_addr = demod->my_i2c_dev_addr;
3107 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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);
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);
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));
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);
3131 return (DRX_STS_OK);
3133 return (DRX_STS_ERROR);
3136 /*----------------------------------------------------------------------------*/
3138 * \fn int bit_reverse_mpeg_output()
3139 * \brief Set MPEG output bit-endian settings.
3140 * \param devmod Pointer to demodulator instance.
3143 * This routine should be called during a set channel of QAM/VSB
3146 static int bit_reverse_mpeg_output(pdrx_demod_instance_t demod)
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;
3152 dev_addr = demod->my_i2c_dev_addr;
3153 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
3155 RR16(dev_addr, FEC_OC_IPR_MODE__A, &fec_oc_ipr_mode);
3157 /* reset to default (normal bit order) */
3158 fec_oc_ipr_mode &= (~FEC_OC_IPR_MODE_REVERSE_ORDER__M);
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;
3165 WR16(dev_addr, FEC_OC_IPR_MODE__A, fec_oc_ipr_mode);
3167 return (DRX_STS_OK);
3169 return (DRX_STS_ERROR);
3172 /*----------------------------------------------------------------------------*/
3174 * \fn int set_mpeg_output_clock_rate()
3175 * \brief Set MPEG output clock rate.
3176 * \param devmod Pointer to demodulator instance.
3179 * This routine should be called during a set channel of QAM/VSB
3182 static int set_mpeg_output_clock_rate(pdrx_demod_instance_t demod)
3184 pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3185 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) (NULL);
3187 dev_addr = demod->my_i2c_dev_addr;
3188 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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);
3195 return (DRX_STS_OK);
3197 return (DRX_STS_ERROR);
3200 /*----------------------------------------------------------------------------*/
3202 * \fn int set_mpeg_start_width()
3203 * \brief Set MPEG start width.
3204 * \param devmod Pointer to demodulator instance.
3207 * This routine should be called during a set channel of QAM/VSB
3210 static int set_mpeg_start_width(pdrx_demod_instance_t demod)
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;
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;
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;
3228 WR16(dev_addr, FEC_OC_COMM_MB__A, fec_oc_comm_mb);
3231 return (DRX_STS_OK);
3233 return (DRX_STS_ERROR);
3236 /*----------------------------------------------------------------------------*/
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
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.
3249 ctrl_set_cfg_mpeg_output_misc(pdrx_demod_instance_t demod,
3250 p_drxj_cfg_mpeg_output_misc_t cfg_data)
3252 pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3254 if (cfg_data == NULL) {
3255 return (DRX_STS_INVALID_ARG);
3258 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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.
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));
3279 return (DRX_STS_OK);
3281 return (DRX_STS_ERROR);
3284 /*----------------------------------------------------------------------------*/
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.
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
3299 ctrl_get_cfg_mpeg_output_misc(pdrx_demod_instance_t demod,
3300 p_drxj_cfg_mpeg_output_misc_t cfg_data)
3302 pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3305 if (cfg_data == NULL) {
3306 return (DRX_STS_INVALID_ARG);
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;
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);
3321 return (DRX_STS_OK);
3323 return (DRX_STS_ERROR);
3326 /*----------------------------------------------------------------------------*/
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.
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
3341 ctrl_get_cfg_hw_cfg(pdrx_demod_instance_t demod, p_drxj_cfg_hw_cfg_t cfg_data)
3344 pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3346 if (cfg_data == NULL) {
3347 return (DRX_STS_INVALID_ARG);
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);
3355 cfg_data->i2c_speed = (drxji2c_speed_t) ((data >> 6) & 0x1);
3356 cfg_data->xtal_freq = (drxj_xtal_freq_t) (data & 0x3);
3358 return (DRX_STS_OK);
3360 return (DRX_STS_ERROR);
3363 /*----------------------------------------------------------------------------*/
3364 /* miscellaneous configuartions - end */
3365 /*----------------------------------------------------------------------------*/
3367 /*----------------------------------------------------------------------------*/
3368 /* UIO Configuration Functions - begin */
3369 /*----------------------------------------------------------------------------*/
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.
3377 static int ctrl_set_uio_cfg(pdrx_demod_instance_t demod, pdrxuio_cfg_t uio_cfg)
3379 pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3381 if ((uio_cfg == NULL) || (demod == NULL)) {
3382 return DRX_STS_INVALID_ARG;
3384 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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 /*====================================================================*/
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;
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);
3406 return DRX_STS_INVALID_ARG;
3407 } /* switch ( uio_cfg->mode ) */
3409 /*====================================================================*/
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;
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);
3425 return DRX_STS_INVALID_ARG;
3427 } /* switch ( uio_cfg->mode ) */
3429 /*====================================================================*/
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;
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);
3445 return DRX_STS_INVALID_ARG;
3447 } /* switch ( uio_cfg->mode ) */
3449 /*====================================================================*/
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;
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;
3463 case DRX_UIO_MODE_FIRMWARE0: /* falltrough */
3465 return DRX_STS_INVALID_ARG;
3467 } /* switch ( uio_cfg->mode ) */
3469 /*====================================================================*/
3471 return DRX_STS_INVALID_ARG;
3472 } /* switch ( uio_cfg->uio ) */
3474 /* Write magic word to disable pdr reg write */
3475 WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000);
3477 return (DRX_STS_OK);
3479 return (DRX_STS_ERROR);
3482 /*============================================================================*/
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.
3490 static int CtrlGetuio_cfg(pdrx_demod_instance_t demod, pdrxuio_cfg_t uio_cfg)
3493 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
3494 pdrxuio_mode_t uio_mode[4] = { NULL };
3495 bool *uio_available[4] = { NULL };
3497 ext_attr = demod->my_ext_attr;
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;
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;
3509 if (uio_cfg == NULL) {
3510 return DRX_STS_INVALID_ARG;
3513 if ((uio_cfg->uio > DRX_UIO4) || (uio_cfg->uio < DRX_UIO1)) {
3514 return DRX_STS_INVALID_ARG;
3517 if (*uio_available[uio_cfg->uio] == false) {
3518 return DRX_STS_ERROR;
3521 uio_cfg->mode = *uio_mode[uio_cfg->uio];
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.
3534 ctrl_uio_write(pdrx_demod_instance_t demod, pdrxuio_data_t uio_data)
3536 pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3537 u16 pin_cfg_value = 0;
3540 if ((uio_data == NULL) || (demod == NULL)) {
3541 return DRX_STS_INVALID_ARG;
3544 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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 /*====================================================================*/
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;
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) */
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);
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 */
3572 value |= 0x8000; /* write one to 15th bit - 1st UIO */
3574 /* write back to io data output register */
3575 WR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value);
3577 /*======================================================================*/
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;
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) */
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);
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 */
3599 value |= 0x4000; /* write one to 14th bit - 2nd UIO */
3601 /* write back to io data output register */
3602 WR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value);
3604 /*====================================================================*/
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;
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) */
3618 /* write to io pad configuration register - output mode */
3619 WR16(demod->my_i2c_dev_addr, SIO_PDR_GPIO_CFG__A, pin_cfg_value);
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 */
3626 value |= 0x0004; /* write one to 2nd bit - 3rd UIO */
3628 /* write back to io data output register */
3629 WR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_HI__A, value);
3631 /*=====================================================================*/
3633 /* DRX_UIO4: IRQN UIO-4 */
3634 if (ext_attr->has_irqn != true)
3635 return DRX_STS_ERROR;
3637 if (ext_attr->uio_irqn_mode != DRX_UIO_MODE_READWRITE) {
3638 return DRX_STS_ERROR;
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) */
3646 /* write to io pad configuration register - output mode */
3647 WR16(demod->my_i2c_dev_addr, SIO_PDR_IRQN_CFG__A, pin_cfg_value);
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 */
3654 value |= 0x1000; /* write one to 12th bit - 4th UIO */
3656 /* write back to io data output register */
3657 WR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value);
3659 /*=====================================================================*/
3661 return DRX_STS_INVALID_ARG;
3662 } /* switch ( uio_data->uio ) */
3664 /* Write magic word to disable pdr reg write */
3665 WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000);
3667 return (DRX_STS_OK);
3669 return (DRX_STS_ERROR);
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.
3679 static int ctrl_uio_read(pdrx_demod_instance_t demod, pdrxuio_data_t uio_data)
3681 pdrxj_data_t ext_attr = (pdrxj_data_t) (NULL);
3682 u16 pin_cfg_value = 0;
3685 if ((uio_data == NULL) || (demod == NULL)) {
3686 return DRX_STS_INVALID_ARG;
3689 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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 /*====================================================================*/
3696 /* DRX_UIO1: SMA_TX UIO-1 */
3697 if (ext_attr->has_smatx != true)
3698 return DRX_STS_ERROR;
3700 if (ext_attr->uio_sma_tx_mode != DRX_UIO_MODE_READWRITE) {
3701 return DRX_STS_ERROR;
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) */
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);
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;
3716 uio_data->value = false;
3719 /*======================================================================*/
3721 /* DRX_UIO2: SMA_RX UIO-2 */
3722 if (ext_attr->has_smarx != true)
3723 return DRX_STS_ERROR;
3725 if (ext_attr->uio_sma_rx_mode != DRX_UIO_MODE_READWRITE) {
3726 return DRX_STS_ERROR;
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) */
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);
3737 RR16(demod->my_i2c_dev_addr, SIO_PDR_UIO_IN_LO__A, &value);
3739 if ((value & 0x4000) != 0) { /* check 14th bit - 2nd UIO */
3740 uio_data->value = true;
3742 uio_data->value = false;
3745 /*=====================================================================*/
3747 /* DRX_UIO3: GPIO UIO-3 */
3748 if (ext_attr->has_gpio != true)
3749 return DRX_STS_ERROR;
3751 if (ext_attr->uio_gpio_mode != DRX_UIO_MODE_READWRITE) {
3752 return DRX_STS_ERROR;
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) */
3760 /* write to io pad configuration register - input mode */
3761 WR16(demod->my_i2c_dev_addr, SIO_PDR_GPIO_CFG__A, pin_cfg_value);
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;
3768 uio_data->value = false;
3771 /*=====================================================================*/
3773 /* DRX_UIO4: IRQN UIO-4 */
3774 if (ext_attr->has_irqn != true)
3775 return DRX_STS_ERROR;
3777 if (ext_attr->uio_irqn_mode != DRX_UIO_MODE_READWRITE) {
3778 return DRX_STS_ERROR;
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) */
3786 /* write to io pad configuration register - input mode */
3787 WR16(demod->my_i2c_dev_addr, SIO_PDR_IRQN_CFG__A, pin_cfg_value);
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;
3794 uio_data->value = false;
3797 /*====================================================================*/
3799 return DRX_STS_INVALID_ARG;
3800 } /* switch ( uio_data->uio ) */
3802 /* Write magic word to disable pdr reg write */
3803 WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000);
3805 return (DRX_STS_OK);
3807 return (DRX_STS_ERROR);
3810 /*---------------------------------------------------------------------------*/
3811 /* UIO Configuration Functions - end */
3812 /*---------------------------------------------------------------------------*/
3814 /*----------------------------------------------------------------------------*/
3815 /* I2C Bridge Functions - begin */
3816 /*----------------------------------------------------------------------------*/
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.
3826 ctrl_i2c_bridge(pdrx_demod_instance_t demod, bool *bridge_closed)
3828 drxj_hi_cmd_t hi_cmd;
3831 /* check arguments */
3832 if (bridge_closed == NULL) {
3833 return (DRX_STS_INVALID_ARG);
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;
3841 hi_cmd.param2 = SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN;
3844 return hi_command(demod->my_i2c_dev_addr, &hi_cmd, &result);
3847 /*----------------------------------------------------------------------------*/
3848 /* I2C Bridge Functions - end */
3849 /*----------------------------------------------------------------------------*/
3851 /*----------------------------------------------------------------------------*/
3852 /* Smart antenna Functions - begin */
3853 /*----------------------------------------------------------------------------*/
3855 * \fn int smart_ant_init()
3856 * \brief Initialize Smart Antenna.
3857 * \param pointer to drx_demod_instance_t.
3861 static int smart_ant_init(pdrx_demod_instance_t demod)
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 };
3868 dev_addr = demod->my_i2c_dev_addr;
3869 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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);
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);
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);
3889 /* Write magic word to disable pdr reg write */
3890 WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000);
3892 return (DRX_STS_OK);
3894 return (DRX_STS_ERROR);
3898 * \fn int ctrl_set_cfg_smart_ant()
3899 * \brief Set Smart Antenna.
3900 * \param pointer to drxj_cfg_smart_ant_t.
3905 ctrl_set_cfg_smart_ant(pdrx_demod_instance_t demod, p_drxj_cfg_smart_ant_t smart_ant)
3907 pdrxj_data_t ext_attr = NULL;
3908 struct i2c_device_addr *dev_addr = NULL;
3911 static bool bit_inverted;
3913 dev_addr = demod->my_i2c_dev_addr;
3914 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
3916 /* check arguments */
3917 if (smart_ant == NULL) {
3918 return (DRX_STS_INVALID_ARG);
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;
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);
3930 switch (smart_ant->io) {
3931 case DRXJ_SMT_ANT_OUTPUT:
3932 /* enable Tx if Mode B (input) is supported */
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 );
3937 start_time = drxbsp_hst_clock();
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));
3944 if (data & SIO_SA_TX_STATUS_BUSY__M) {
3945 return (DRX_STS_ERROR);
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)
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)
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)
3969 WR16(dev_addr, SIO_SA_TX_DATA3__A, 0xff8d);
3971 /* trigger the sending */
3972 WR16(dev_addr, SIO_SA_TX_LENGTH__A, 56);
3975 case DRXJ_SMT_ANT_INPUT:
3976 /* disable Tx if Mode B (input) is supported */
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) );
3982 return (DRX_STS_INVALID_ARG);
3984 /* Write magic word to enable pdr reg write */
3985 WR16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000);
3987 return (DRX_STS_OK);
3989 return (DRX_STS_ERROR);
3992 static int scu_command(struct i2c_device_addr *dev_addr, p_drxjscu_cmd_t cmd)
3999 return (DRX_STS_INVALID_ARG);
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);
4007 switch (cmd->parameter_len) {
4009 WR16(dev_addr, SCU_RAM_PARAM_4__A, *(cmd->parameter + 4)); /* fallthrough */
4011 WR16(dev_addr, SCU_RAM_PARAM_3__A, *(cmd->parameter + 3)); /* fallthrough */
4013 WR16(dev_addr, SCU_RAM_PARAM_2__A, *(cmd->parameter + 2)); /* fallthrough */
4015 WR16(dev_addr, SCU_RAM_PARAM_1__A, *(cmd->parameter + 1)); /* fallthrough */
4017 WR16(dev_addr, SCU_RAM_PARAM_0__A, *(cmd->parameter + 0)); /* fallthrough */
4022 /* this number of parameters is not supported */
4023 return (DRX_STS_ERROR);
4025 WR16(dev_addr, SCU_RAM_COMMAND__A, cmd->command);
4027 /* Wait until SCU has processed command */
4028 start_time = drxbsp_hst_clock();
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));
4034 if (cur_cmd != DRX_SCU_READY) {
4035 return (DRX_STS_ERROR);
4039 if ((cmd->result_len > 0) && (cmd->result != NULL)) {
4042 switch (cmd->result_len) {
4044 RR16(dev_addr, SCU_RAM_PARAM_3__A, cmd->result + 3); /* fallthrough */
4046 RR16(dev_addr, SCU_RAM_PARAM_2__A, cmd->result + 2); /* fallthrough */
4048 RR16(dev_addr, SCU_RAM_PARAM_1__A, cmd->result + 1); /* fallthrough */
4050 RR16(dev_addr, SCU_RAM_PARAM_0__A, cmd->result + 0); /* fallthrough */
4055 /* this number of parameters is not supported */
4056 return (DRX_STS_ERROR);
4059 /* Check if an error was reported by SCU */
4060 err = cmd->result[0];
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)
4068 return DRX_STS_INVALID_ARG;
4070 /* here it is assumed that negative means error, and positive no error */
4072 return DRX_STS_ERROR;
4078 return (DRX_STS_OK);
4081 return (DRX_STS_ERROR);
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
4092 * \retval DRX_STS_OK Succes
4093 * \retval DRX_STS_ERROR Timeout, I2C error, illegal bank
4096 #define ADDR_AT_SCU_SPACE(x) ((x - 0x82E000) * 2)
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)
4101 drxjscu_cmd_t scu_cmd;
4102 u16 set_param_parameters[15];
4105 /* Parameter check */
4106 if ((data == NULL) ||
4107 (dev_addr == NULL) || ((datasize % 2) != 0) || ((datasize / 2) > 16)
4109 return (DRX_STS_INVALID_ARG);
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;
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));
4125 scu_cmd.parameter_len = datasize / 2 + 2;
4126 scu_cmd.result_len = 1;
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));
4136 if (read_flag == true) {
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);
4148 return (DRX_STS_ERROR);
4152 /*============================================================================*/
4155 * \fn int DRXJ_DAP_AtomicReadReg16()
4156 * \brief Atomic read of 16 bits words
4159 int drxj_dap_scu_atomic_read_reg16(struct i2c_device_addr *dev_addr,
4161 u16 *data, dr_xflags_t flags)
4164 int rc = DRX_STS_ERROR;
4168 return DRX_STS_INVALID_ARG;
4171 rc = drxj_dap_scu_atomic_read_write_block(dev_addr, addr, 2, buf, true);
4173 word = (u16) (buf[0] + (buf[1] << 8));
4180 /*============================================================================*/
4182 * \fn int drxj_dap_scu_atomic_write_reg16()
4183 * \brief Atomic read of 16 bits words
4186 int drxj_dap_scu_atomic_write_reg16(struct i2c_device_addr *dev_addr,
4188 u16 data, dr_xflags_t flags)
4191 int rc = DRX_STS_ERROR;
4193 buf[0] = (u8) (data & 0xff);
4194 buf[1] = (u8) ((data >> 8) & 0xff);
4196 rc = drxj_dap_scu_atomic_read_write_block(dev_addr, addr, 2, buf, false);
4202 ctrl_i2c_write_read(pdrx_demod_instance_t demod, pdrxi2c_data_t i2c_data)
4204 return (DRX_STS_FUNC_NOT_AVAILABLE);
4208 tuner_i2c_write_read(struct tuner_instance *tuner,
4209 struct i2c_device_addr *w_dev_addr,
4212 struct i2c_device_addr *r_dev_addr, u16 r_count, u8 *r_data)
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 };
4218 demod = (pdrx_demod_instance_t) (tuner->my_common_attr->myUser_data);
4220 return (ctrl_i2c_write_read(demod, &i2c_data));
4223 /* -------------------------------------------------------------------------- */
4225 * \brief Measure result of ADC synchronisation
4226 * \param demod demod instance
4227 * \param count (returned) count
4229 * \retval DRX_STS_OK Success
4230 * \retval DRX_STS_ERROR Failure: I2C error
4233 static int adc_sync_measurement(pdrx_demod_instance_t demod, u16 *count)
4236 struct i2c_device_addr *dev_addr = NULL;
4238 dev_addr = demod->my_i2c_dev_addr;
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);
4244 /* Wait at least 3*128*(1/sysclk) <<< 1 millisec */
4245 CHK_ERROR(drxbsp_hst_sleep(1));
4248 RR16(dev_addr, IQM_AF_PHASE0__A, &data);
4250 *count = *count + 1;
4252 RR16(dev_addr, IQM_AF_PHASE1__A, &data);
4254 *count = *count + 1;
4256 RR16(dev_addr, IQM_AF_PHASE2__A, &data);
4258 *count = *count + 1;
4261 return (DRX_STS_OK);
4263 return (DRX_STS_ERROR);
4267 * \brief Synchronize analog and digital clock domains
4268 * \param demod demod instance
4270 * \retval DRX_STS_OK Success
4271 * \retval DRX_STS_ERROR Failure: I2C error or failure to synchronize
4273 * An IQM reset will also reset the results of this synchronization.
4274 * After an IQM reset this routine needs to be called again.
4278 static int adc_synchronization(pdrx_demod_instance_t demod)
4281 struct i2c_device_addr *dev_addr = NULL;
4283 dev_addr = demod->my_i2c_dev_addr;
4285 CHK_ERROR(adc_sync_measurement(demod, &count));
4288 /* Try sampling on a diffrent edge */
4291 RR16(dev_addr, IQM_AF_CLKNEG__A, &clk_neg);
4293 clk_neg ^= IQM_AF_CLKNEG_CLKNEGDATA__M;
4294 WR16(dev_addr, IQM_AF_CLKNEG__A, clk_neg);
4296 CHK_ERROR(adc_sync_measurement(demod, &count));
4300 /* TODO: implement fallback scenarios */
4301 return (DRX_STS_ERROR);
4304 return (DRX_STS_OK);
4306 return (DRX_STS_ERROR);
4310 * \brief Configure IQM AF registers
4311 * \param demod instance of demodulator.
4315 static int iqm_set_af(pdrx_demod_instance_t demod, bool active)
4318 struct i2c_device_addr *dev_addr = NULL;
4319 pdrxj_data_t ext_attr = NULL;
4321 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
4322 dev_addr = demod->my_i2c_dev_addr;
4325 RR16(dev_addr, IQM_AF_STDBY__A, &data);
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)
4333 } else { /* active */
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);
4341 WR16(dev_addr, IQM_AF_STDBY__A, data);
4343 return (DRX_STS_OK);
4345 return (DRX_STS_ERROR);
4348 /* -------------------------------------------------------------------------- */
4350 ctrl_set_cfg_atv_output(pdrx_demod_instance_t demod, p_drxj_cfg_atv_output_t output_cfg);
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.
4359 ctrl_set_cfg_pdr_safe_mode(pdrx_demod_instance_t demod, bool *enable)
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;
4365 if (enable == NULL) {
4366 return (DRX_STS_INVALID_ARG);
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;
4373 /* Write magic word to enable pdr reg write */
4374 WR16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
4376 if (*enable == true) {
4377 bool bridge_enabled = false;
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);
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);
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);
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));
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)));
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);
4433 /* No need to restore MPEG pins;
4434 is done in SetStandard/SetChannel */
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);
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);
4456 /* PD_RF_AGC, PD_IF_AGC
4457 No need to restore; will be restored in SetStandard/SetChannel */
4460 No need to restore; will be restored in SetStandard/SetChannel */
4462 /* PD_I2S_CL, PD_I2S_DA, PD_I2S_WS
4463 Should be restored via DRX_CTRL_SET_AUD */
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;
4470 return (DRX_STS_OK);
4473 return (DRX_STS_ERROR);
4476 /* -------------------------------------------------------------------------- */
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
4485 ctrl_get_cfg_pdr_safe_mode(pdrx_demod_instance_t demod, bool *enabled)
4487 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
4489 if (enabled == NULL) {
4490 return (DRX_STS_INVALID_ARG);
4493 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
4494 *enabled = ext_attr->pdr_safe_mode;
4496 return (DRX_STS_OK);
4500 * \brief Verifies whether microcode can be loaded.
4501 * \param demod Demodulator instance.
4504 static int ctrl_validate_u_code(pdrx_demod_instance_t demod)
4506 u32 mc_dev, mc_patch;
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
4516 DRX_GET_MCVERTYPE(demod, ver_type);
4517 DRX_GET_MCDEV(demod, mc_dev);
4518 DRX_GET_MCPATCH(demod, mc_patch);
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;
4532 /* Everything else: OK */
4536 /*============================================================================*/
4537 /*== END AUXILIARY FUNCTIONS ==*/
4538 /*============================================================================*/
4540 /*============================================================================*/
4541 /*============================================================================*/
4542 /*== 8VSB & QAM COMMON DATAPATH FUNCTIONS ==*/
4543 /*============================================================================*/
4544 /*============================================================================*/
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.
4552 static int init_agc(pdrx_demod_instance_t demod)
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;
4561 u16 sns_sum_max = 0;
4562 u16 clp_sum_max = 0;
4564 u16 ki_innergain_min = 0;
4567 u16 if_iaccu_hi_tgt_min = 0;
4569 u16 agc_kiDgain = 0;
4571 u16 clp_ctrl_mode = 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;
4578 switch (ext_attr->standard) {
4579 case DRX_STANDARD_8VSB:
4581 clp_dir_to = (u16) (-9);
4583 sns_dir_to = (u16) (-9);
4584 ki_innergain_min = (u16) (-32768);
4587 if_iaccu_hi_tgt_min = 2047;
4589 ingain_tgt_max = 16383;
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);
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;
4613 clp_dir_to = (u16) (-5);
4615 sns_dir_to = (u16) (-3);
4616 ki_innergain_min = 0;
4618 if_iaccu_hi_tgt_min = 2047;
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);
4636 RR16(dev_addr, SCU_RAM_AGC_KI__A, &agc_ki);
4638 WR16(dev_addr, SCU_RAM_AGC_KI__A, agc_ki);
4641 #ifndef DRXJ_DIGITAL_ONLY
4642 case DRX_STANDARD_FM:
4645 ki_innergain_min = (u16) (-32768);
4646 if_iaccu_hi_tgt_min = 2047;
4650 clp_dir_to = (u16) (-9);
4651 sns_dir_to = (u16) (-9);
4652 ingain_tgt_max = 9000;
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);
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:
4664 ki_innergain_min = (u16) (-32768);
4665 if_iaccu_hi_tgt_min = 2047;
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);
4675 WR16(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, p_agc_if_settings->top);
4677 case DRX_STANDARD_PAL_SECAM_L:
4678 case DRX_STANDARD_PAL_SECAM_LP:
4681 ki_innergain_min = (u16) (-32768);
4682 if_iaccu_hi_tgt_min = 2047;
4686 clp_dir_to = (u16) (-9);
4687 sns_dir_to = (u16) (-9);
4688 ingain_tgt_max = 9000;
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);
4696 return (DRX_STS_INVALID_ARG);
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);
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;
4733 if (common_attr->tuner_if_agc_pol == true) {
4734 agc_rf = 0x87ff - agc_rf;
4737 WR16(dev_addr, IQM_AF_AGC_RF__A, agc_rf);
4738 WR16(dev_addr, IQM_AF_AGC_IF__A, agc_if);
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);
4746 return (DRX_STS_OK);
4748 return (DRX_STS_ERROR);
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.
4760 set_frequency(pdrx_demod_instance_t demod,
4761 pdrx_channel_t channel, s32 tuner_freq_offset)
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;
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;
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;
4787 Program frequency shifter
4788 No need to account for mirroring on RF
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;
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;
4811 return (DRX_STS_INVALID_ARG);
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 */
4818 intermediate_freq + rf_freq_residual + fm_frequency_shift;
4822 intermediate_freq - rf_freq_residual - fm_frequency_shift;
4824 if (if_freq_actual > sampling_frequency / 2) {
4826 adc_freq = sampling_frequency - if_freq_actual;
4829 /* adc doesn't mirror */
4830 adc_freq = if_freq_actual;
4834 frequency_shift = adc_freq;
4836 (bool) (rf_mirror ^ tuner_mirror ^ adc_flip ^ select_pos_image);
4837 iqm_fs_rate_ofs = frac28(frequency_shift, sampling_frequency);
4839 if (image_to_select)
4840 iqm_fs_rate_ofs = ~iqm_fs_rate_ofs + 1;
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);
4848 return (DRX_STS_OK);
4850 return (DRX_STS_ERROR);
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.
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.
4863 #define DRXJ_AGC_TOP 0x2800
4864 #define DRXJ_AGC_SNS 0x1600
4865 #define DRXJ_RFAGC_MAX 0x3fff
4866 #define DRXJ_RFAGC_MIN 0x800
4868 static int get_sig_strength(pdrx_demod_instance_t demod, u16 *sig_strength)
4876 pdrxj_data_t ext_attr = NULL;
4877 struct i2c_device_addr *dev_addr = NULL;
4879 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
4880 dev_addr = demod->my_i2c_dev_addr;
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;
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;
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);
4898 75 + 25 * (rf_gain - rf_agc_min) / (rf_agc_max -
4902 } else if (if_gain > if_agc_sns) {
4903 CHK_ZERO(if_agc_top - if_agc_sns);
4905 20 + 55 * (if_gain - if_agc_sns) / (if_agc_top - if_agc_sns);
4907 CHK_ZERO(if_agc_sns);
4908 *sig_strength = (20 * if_gain / if_agc_sns);
4911 return (DRX_STS_OK);
4913 return (DRX_STS_ERROR);
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
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.
4926 #ifdef DRXJ_SIGNAL_ACCUM_ERR
4927 static int get_acc_pkt_err(pdrx_demod_instance_t demod, u16 *packet_err)
4930 static u16 last_pkt_err;
4932 pdrxj_data_t ext_attr = NULL;
4933 struct i2c_device_addr *dev_addr = NULL;
4935 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
4936 dev_addr = demod->my_i2c_dev_addr;
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;
4942 ext_attr->reset_pkt_err_acc = false;
4945 if (data < last_pkt_err) {
4946 pkt_err += 0xffff - last_pkt_err;
4949 pkt_err += (data - last_pkt_err);
4951 *packet_err = pkt_err;
4952 last_pkt_err = data;
4954 return (DRX_STS_OK);
4956 return (DRX_STS_ERROR);
4961 * \fn int ResetAccPktErr()
4962 * \brief Reset Accumulating packet error count.
4963 * \param demod Pointer to demod instance
4965 * \retval DRX_STS_OK.
4966 * \retval DRX_STS_ERROR Erroneous data.
4968 static int ctrl_set_cfg_reset_pkt_err(pdrx_demod_instance_t demod)
4970 #ifdef DRXJ_SIGNAL_ACCUM_ERR
4971 pdrxj_data_t ext_attr = NULL;
4972 u16 packet_error = 0;
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));
4979 return (DRX_STS_OK);
4982 return (DRX_STS_ERROR);
4986 * \fn static short get_str_freq_offset()
4987 * \brief Get symbol rate offset in QAM & 8VSB mode
4988 * \return Error code
4990 static int get_str_freq_offset(pdrx_demod_instance_t demod, s32 *str_freq)
4992 u32 symbol_frequency_ratio = 0;
4993 u32 symbol_nom_frequency_ratio = 0;
4995 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
4996 struct i2c_device_addr *dev_addr = NULL;
4997 pdrxj_data_t ext_attr = NULL;
4999 dev_addr = demod->my_i2c_dev_addr;
5000 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
5001 standard = ext_attr->standard;
5003 ARR32(dev_addr, IQM_RC_RATE_LO__A, &symbol_frequency_ratio);
5004 symbol_nom_frequency_ratio = ext_attr->iqm_rc_rate_ofs;
5006 if (symbol_frequency_ratio > symbol_nom_frequency_ratio)
5009 frac_times1e6((symbol_frequency_ratio -
5010 symbol_nom_frequency_ratio),
5011 (symbol_frequency_ratio + (1 << 23)));
5014 frac_times1e6((symbol_nom_frequency_ratio -
5015 symbol_frequency_ratio),
5016 (symbol_frequency_ratio + (1 << 23)));
5018 return (DRX_STS_OK);
5020 return (DRX_STS_ERROR);
5024 * \fn static short get_ctl_freq_offset
5025 * \brief Get the value of ctl_freq in QAM & ATSC mode
5026 * \return Error code
5028 static int get_ctl_freq_offset(pdrx_demod_instance_t demod, s32 *ctl_freq)
5030 s32 sampling_frequency = 0;
5031 s32 current_frequency = 0;
5032 s32 nominal_frequency = 0;
5033 s32 carrier_frequency_shift = 0;
5037 pdrxj_data_t ext_attr = NULL;
5038 pdrx_common_attr_t common_attr = NULL;
5039 struct i2c_device_addr *dev_addr = NULL;
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;
5045 sampling_frequency = common_attr->sys_clock_freq / 3;
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 *) ¤t_frequency);
5051 if (ext_attr->pos_image == true) {
5052 /* negative image */
5053 carrier_frequency_shift = nominal_frequency - current_frequency;
5055 /* positive image */
5056 carrier_frequency_shift = current_frequency - nominal_frequency;
5059 /* carrier Frequency Shift In Hz */
5060 if (carrier_frequency_shift < 0) {
5062 carrier_frequency_shift *= sign;
5065 /* *ctl_freq = carrier_frequency_shift * 50.625e6 / (1 << 28); */
5066 mult32(carrier_frequency_shift, sampling_frequency, &data64hi, &data64lo);
5068 (s32) ((((data64lo >> 28) & 0xf) | (data64hi << 4)) * sign);
5070 return (DRX_STS_OK);
5072 return (DRX_STS_ERROR);
5075 /*============================================================================*/
5078 * \fn int set_agc_rf ()
5079 * \brief Configure RF AGC
5080 * \param demod instance of demodulator.
5081 * \param agc_settings AGC configuration structure
5085 set_agc_rf(pdrx_demod_instance_t demod, p_drxj_cfg_agc_t agc_settings, bool atomic)
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;
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;
5099 scu_rr16 = drxj_dap_scu_atomic_read_reg16;
5100 scu_wr16 = drxj_dap_scu_atomic_write_reg16;
5102 scu_rr16 = DRXJ_DAP.read_reg16func;
5103 scu_wr16 = DRXJ_DAP.write_reg16func;
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))) {
5114 switch (agc_settings->ctrl_mode) {
5115 case DRX_AGC_CTRL_AUTO:
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);
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);
5131 data |= (4 << SCU_RAM_AGC_KI_RF__B);
5134 if (common_attr->tuner_rf_agc_pol) {
5135 data |= SCU_RAM_AGC_KI_INV_RF_POL__M;
5137 data &= ~SCU_RAM_AGC_KI_INV_RF_POL__M;
5139 CHK_ERROR((*scu_wr16)
5140 (dev_addr, SCU_RAM_AGC_KI__A, data, 0));
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,
5150 SCU_RAM_AGC_KI_RED_RAGC_RED__B)
5151 & SCU_RAM_AGC_KI_RED_RAGC_RED__M)
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);
5161 return (DRX_STS_INVALID_ARG);
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)
5167 SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A,
5168 agc_settings->top, 0));
5169 CHK_ERROR((*scu_wr16)
5171 SCU_RAM_AGC_IF_IACCU_HI_TGT__A,
5172 agc_settings->top, 0));
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));
5180 case DRX_AGC_CTRL_USER:
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);
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;
5194 data &= ~SCU_RAM_AGC_KI_INV_RF_POL__M;
5196 CHK_ERROR((*scu_wr16)
5197 (dev_addr, SCU_RAM_AGC_KI__A, data, 0));
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));
5204 case DRX_AGC_CTRL_OFF:
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);
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));
5219 return (DRX_STS_INVALID_ARG);
5220 } /* switch ( agcsettings->ctrl_mode ) */
5223 /* Store rf agc settings */
5224 switch (agc_settings->standard) {
5225 case DRX_STANDARD_8VSB:
5226 ext_attr->vsb_rf_agc_cfg = *agc_settings;
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;
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;
5247 return (DRX_STS_ERROR);
5250 return (DRX_STS_OK);
5252 return (DRX_STS_ERROR);
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
5263 get_agc_rf(pdrx_demod_instance_t demod, p_drxj_cfg_agc_t agc_settings)
5265 struct i2c_device_addr *dev_addr = NULL;
5266 pdrxj_data_t ext_attr = NULL;
5267 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
5269 dev_addr = demod->my_i2c_dev_addr;
5270 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
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;
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;
5297 return (DRX_STS_ERROR);
5299 agc_settings->standard = standard;
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));
5311 return (DRX_STS_OK);
5313 return (DRX_STS_ERROR);
5317 * \fn int set_agc_if ()
5318 * \brief Configure If AGC
5319 * \param demod instance of demodulator.
5320 * \param agc_settings AGC configuration structure
5324 set_agc_if(pdrx_demod_instance_t demod, p_drxj_cfg_agc_t agc_settings, bool atomic)
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;
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;
5338 scu_rr16 = drxj_dap_scu_atomic_read_reg16;
5339 scu_wr16 = drxj_dap_scu_atomic_write_reg16;
5341 scu_rr16 = DRXJ_DAP.read_reg16func;
5342 scu_wr16 = DRXJ_DAP.write_reg16func;
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))) {
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);
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);
5370 data |= (5 << SCU_RAM_AGC_KI_IF__B);
5373 if (common_attr->tuner_if_agc_pol) {
5374 data |= SCU_RAM_AGC_KI_INV_IF_POL__M;
5376 data &= ~SCU_RAM_AGC_KI_INV_IF_POL__M;
5378 CHK_ERROR((*scu_wr16)
5379 (dev_addr, SCU_RAM_AGC_KI__A, data, 0));
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,
5389 SCU_RAM_AGC_KI_RED_IAGC_RED__B)
5390 & SCU_RAM_AGC_KI_RED_IAGC_RED__M)
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);
5400 return (DRX_STS_INVALID_ARG);
5403 if (p_agc_settings->ctrl_mode == DRX_AGC_CTRL_AUTO) {
5404 CHK_ERROR((*scu_wr16)
5406 SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A,
5407 p_agc_settings->top, 0));
5408 CHK_ERROR((*scu_wr16)
5410 SCU_RAM_AGC_IF_IACCU_HI_TGT__A,
5411 p_agc_settings->top, 0));
5413 CHK_ERROR((*scu_wr16)
5415 SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A,
5417 CHK_ERROR((*scu_wr16)
5419 SCU_RAM_AGC_IF_IACCU_HI_TGT__A, 0,
5424 case DRX_AGC_CTRL_USER:
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);
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;
5439 data &= ~SCU_RAM_AGC_KI_INV_IF_POL__M;
5441 CHK_ERROR((*scu_wr16)
5442 (dev_addr, SCU_RAM_AGC_KI__A, data, 0));
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));
5450 case DRX_AGC_CTRL_OFF:
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);
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));
5466 return (DRX_STS_INVALID_ARG);
5467 } /* switch ( agcsettings->ctrl_mode ) */
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));
5475 /* Store if agc settings */
5476 switch (agc_settings->standard) {
5477 case DRX_STANDARD_8VSB:
5478 ext_attr->vsb_if_agc_cfg = *agc_settings;
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;
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;
5499 return (DRX_STS_ERROR);
5502 return (DRX_STS_OK);
5504 return (DRX_STS_ERROR);
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
5515 get_agc_if(pdrx_demod_instance_t demod, p_drxj_cfg_agc_t agc_settings)
5517 struct i2c_device_addr *dev_addr = NULL;
5518 pdrxj_data_t ext_attr = NULL;
5519 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
5521 dev_addr = demod->my_i2c_dev_addr;
5522 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
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;
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;
5549 return (DRX_STS_ERROR);
5551 agc_settings->standard = standard;
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));
5564 return (DRX_STS_OK);
5566 return (DRX_STS_ERROR);
5570 * \fn int set_iqm_af ()
5571 * \brief Configure IQM AF registers
5572 * \param demod instance of demodulator.
5576 static int set_iqm_af(pdrx_demod_instance_t demod, bool active)
5579 struct i2c_device_addr *dev_addr = NULL;
5581 dev_addr = demod->my_i2c_dev_addr;
5584 RR16(dev_addr, IQM_AF_STDBY__A, &data);
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)
5592 } else { /* active */
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);
5600 WR16(dev_addr, IQM_AF_STDBY__A, data);
5602 return (DRX_STS_OK);
5604 return (DRX_STS_ERROR);
5607 /*============================================================================*/
5608 /*== END 8VSB & QAM COMMON DATAPATH FUNCTIONS ==*/
5609 /*============================================================================*/
5611 /*============================================================================*/
5612 /*============================================================================*/
5613 /*== 8VSB DATAPATH FUNCTIONS ==*/
5614 /*============================================================================*/
5615 /*============================================================================*/
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.
5624 static int power_down_vsb(pdrx_demod_instance_t demod, bool primary)
5626 struct i2c_device_addr *dev_addr = NULL;
5627 drxjscu_cmd_t cmd_scu = { /* command */ 0,
5628 /* parameter_len */ 0,
5630 /* *parameter */ NULL,
5634 pdrxj_data_t ext_attr = NULL;
5635 drx_cfg_mpeg_output_t cfg_mpeg_output;
5637 dev_addr = demod->my_i2c_dev_addr;
5638 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
5641 reset of FEC and VSB HW
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));
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));
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);
5665 cfg_mpeg_output.enable_mpeg_output = false;
5666 CHK_ERROR(ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output));
5668 return (DRX_STS_OK);
5670 return (DRX_STS_ERROR);
5674 * \fn int set_vsb_leak_n_gain ()
5675 * \brief Set ATSC demod.
5676 * \param demod instance of demodulator.
5679 static int set_vsb_leak_n_gain(pdrx_demod_instance_t demod)
5681 struct i2c_device_addr *dev_addr = NULL;
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 */
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 */
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));
5877 return (DRX_STS_OK);
5879 return (DRX_STS_ERROR);
5884 * \brief Set 8VSB demod.
5885 * \param demod instance of demodulator.
5889 static int set_vsb(pdrx_demod_instance_t demod)
5891 struct i2c_device_addr *dev_addr = NULL;
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 */
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;
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);
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));
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);
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);
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));
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 */
5980 /* Initialize the FEC Subsystem */
5981 WR16(dev_addr, FEC_TOP_ANNEX__A, FEC_TOP_ANNEX_D);
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);
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 */
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)
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);
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);
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);
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));
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));
6034 /* TODO fix this, store a drxj_cfg_afe_gain_t structure in drxj_data_t instead
6036 drxj_cfg_afe_gain_t vsb_pga_cfg = { DRX_STANDARD_8VSB, 0 };
6038 vsb_pga_cfg.gain = ext_attr->vsb_pga_cfg;
6039 CHK_ERROR(ctrl_set_cfg_afe_gain(demod, &vsb_pga_cfg));
6041 CHK_ERROR(ctrl_set_cfg_pre_saw(demod, &(ext_attr->vsb_pre_saw_cfg)));
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));
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));
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));
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);
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));
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);
6098 return (DRX_STS_OK);
6100 return (DRX_STS_ERROR);
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
6108 static int get_vsb_post_rs_pck_err(struct i2c_device_addr *dev_addr, u16 *pck_errs)
6113 u16 packet_errorsMant = 0;
6114 u16 packet_errorsExp = 0;
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);
6126 (u16) frac_times1e6(packet_errorsMant * (1 << packet_errorsExp),
6127 (period * prescale * 77));
6129 return (DRX_STS_OK);
6131 return (DRX_STS_ERROR);
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
6139 static int get_vs_bpost_viterbi_ber(struct i2c_device_addr *dev_addr, u32 *ber)
6144 u16 bit_errors_mant = 0;
6145 u16 bit_errors_exp = 0;
6147 RR16(dev_addr, FEC_RS_NR_BIT_ERRORS__A, &data);
6148 period = FEC_RS_MEASUREMENT_PERIOD;
6149 prescale = FEC_RS_MEASUREMENT_PRESCALE;
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;
6155 if (((bit_errors_mant << bit_errors_exp) >> 3) > 68700)
6158 CHK_ZERO(period * prescale);
6160 frac_times1e6(bit_errors_mant <<
6162 2) ? (bit_errors_exp - 3) : bit_errors_exp),
6163 period * prescale * 207 *
6164 ((bit_errors_exp > 2) ? 1 : 8));
6167 return (DRX_STS_OK);
6169 return (DRX_STS_ERROR);
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
6177 static int get_vs_bpre_viterbi_ber(struct i2c_device_addr *dev_addr, u32 *ber)
6181 RR16(dev_addr, VSB_TOP_NR_SYM_ERRS__A, &data);
6184 VSB_TOP_MEASUREMENT_PERIOD * SYMBOLS_PER_SEGMENT);
6186 return (DRX_STS_OK);
6188 return (DRX_STS_ERROR);
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
6196 static int get_vsb_symb_err(struct i2c_device_addr *dev_addr, u32 *ser)
6201 u16 symb_errors_mant = 0;
6202 u16 symb_errors_exp = 0;
6204 RR16(dev_addr, FEC_RS_NR_SYMBOL_ERRORS__A, &data);
6205 period = FEC_RS_MEASUREMENT_PERIOD;
6206 prescale = FEC_RS_MEASUREMENT_PRESCALE;
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;
6212 CHK_ZERO(period * prescale);
6213 *ser = (u32) frac_times1e6((symb_errors_mant << symb_errors_exp) * 1000,
6214 (period * prescale * 77318));
6216 return (DRX_STS_OK);
6218 return (DRX_STS_ERROR);
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
6226 static int get_vsbmer(struct i2c_device_addr *dev_addr, u16 *mer)
6230 RR16(dev_addr, VSB_TOP_ERR_ENERGY_H__A, &data_hi);
6232 (u16) (log1_times100(21504) - log1_times100((data_hi << 6) / 52));
6234 return (DRX_STS_OK);
6236 return (DRX_STS_ERROR);
6239 /*============================================================================*/
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.
6249 ctrl_get_vsb_constel(pdrx_demod_instance_t demod, pdrx_complex_t complex_nr)
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 */
6258 /* read device info */
6259 dev_addr = demod->my_i2c_dev_addr;
6262 /* Monitor bus grabbing is an open external interface issue */
6263 /* Needs to be checked when external interface PG is updated */
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);
6273 /* Enable MB grabber in the FEC OC */
6274 WR16(dev_addr, FEC_OC_OCR_MODE__A, FEC_OC_OCR_MODE_GRAB_ENABLE__M);
6276 /* Disable MB grabber in the FEC OC */
6277 WR16(dev_addr, FEC_OC_OCR_MODE__A, 0x0);
6280 RR32(dev_addr, FEC_OC_OCR_GRAB_RD1__A, &data);
6281 re = (u16) (((data >> 10) & 0x300) | ((data >> 2) & 0xff));
6285 complex_nr->re = re;
6288 /* Restore MB (Monitor bus) */
6289 WR16(dev_addr, VSB_TOP_COMM_MB__A, vsb_top_comm_mbInit);
6291 return (DRX_STS_OK);
6293 return (DRX_STS_ERROR);
6296 /*============================================================================*/
6297 /*== END 8VSB DATAPATH FUNCTIONS ==*/
6298 /*============================================================================*/
6300 /*============================================================================*/
6301 /*============================================================================*/
6302 /*== QAM DATAPATH FUNCTIONS ==*/
6303 /*============================================================================*/
6304 /*============================================================================*/
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.
6313 static int power_down_qam(pdrx_demod_instance_t demod, bool primary)
6315 drxjscu_cmd_t cmd_scu = { /* command */ 0,
6316 /* parameter_len */ 0,
6318 /* *parameter */ NULL,
6322 struct i2c_device_addr *dev_addr = NULL;
6323 pdrxj_data_t ext_attr = NULL;
6324 drx_cfg_mpeg_output_t cfg_mpeg_output;
6326 dev_addr = demod->my_i2c_dev_addr;
6327 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
6331 resets IQM, QAM and FEC HW blocks
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);
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));
6345 if (primary == true) {
6346 WR16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP);
6347 CHK_ERROR(set_iqm_af(demod, false));
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);
6356 cfg_mpeg_output.enable_mpeg_output = false;
6357 CHK_ERROR(ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output));
6359 return (DRX_STS_OK);
6361 return (DRX_STS_ERROR);
6364 /*============================================================================*/
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.
6374 * Take into account that for certain settings the errorcounters can overflow.
6375 * The implementation does not check this.
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
6382 #ifndef DRXJ_VSB_ONLY
6384 set_qam_measurement(pdrx_demod_instance_t demod,
6385 enum drx_modulation constellation, u32 symbol_rate)
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 */
6400 dev_addr = demod->my_i2c_dev_addr;
6401 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
6403 fec_bits_desired = ext_attr->fec_bits_desired;
6404 fec_rs_prescale = ext_attr->fec_rs_prescale;
6406 switch (constellation) {
6407 case DRX_CONSTELLATION_QAM16:
6408 fec_bits_desired = 4 * symbol_rate;
6410 case DRX_CONSTELLATION_QAM32:
6411 fec_bits_desired = 5 * symbol_rate;
6413 case DRX_CONSTELLATION_QAM64:
6414 fec_bits_desired = 6 * symbol_rate;
6416 case DRX_CONSTELLATION_QAM128:
6417 fec_bits_desired = 7 * symbol_rate;
6419 case DRX_CONSTELLATION_QAM256:
6420 fec_bits_desired = 8 * symbol_rate;
6423 return (DRX_STS_INVALID_ARG);
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 */
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;
6438 case DRX_STANDARD_ITU_B:
6439 fec_rs_plen = 128 * 7;
6442 return (DRX_STS_INVALID_ARG);
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;
6452 /* limit to max 16 bit value (I2C register width) if needed */
6453 if (fec_rs_period > 0xFFFF)
6454 fec_rs_period = 0xFFFF;
6456 /* write corresponding registers */
6457 switch (ext_attr->standard) {
6458 case DRX_STANDARD_ITU_A:
6459 case DRX_STANDARD_ITU_C:
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;
6467 case DRX_CONSTELLATION_QAM256:
6468 fec_rs_period = 45446;
6469 fec_oc_snc_fail_period = 25805;
6472 return (DRX_STS_INVALID_ARG);
6476 return (DRX_STS_INVALID_ARG);
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);
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 */
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 */
6501 switch (constellation) {
6502 case DRX_CONSTELLATION_QAM64:
6503 /* a(16 bit) * b(4 bit) = 20 bit result => mult32 not needed */
6505 qam_vd_bit_cnt * (QAM_TOP_CONSTELLATION_QAM64 + 1)
6506 * (QAM_TOP_CONSTELLATION_QAM64 + 1);
6508 case DRX_CONSTELLATION_QAM256:
6509 /* a(16 bit) * b(5 bit) = 21 bit result => mult32 not needed */
6511 qam_vd_bit_cnt * (QAM_TOP_CONSTELLATION_QAM256 + 1)
6512 * (QAM_TOP_CONSTELLATION_QAM256 + 1);
6515 return (DRX_STS_INVALID_ARG);
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;
6523 /* a(16 bit) * b(16 bit) = 32 bit result => mult32 not needed */
6524 qam_vd_bit_cnt *= qam_vd_period;
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;
6533 return (DRX_STS_OK);
6535 return (DRX_STS_ERROR);
6538 /*============================================================================*/
6541 * \fn int set_qam16 ()
6542 * \brief QAM16 specific setup
6543 * \param demod instance of demod.
6546 static int set_qam16(pdrx_demod_instance_t demod)
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 */
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 */
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));
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);
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);
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));
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);
6611 WR16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 40960);
6613 return (DRX_STS_OK);
6615 return (DRX_STS_ERROR);
6618 /*============================================================================*/
6621 * \fn int set_qam32 ()
6622 * \brief QAM32 specific setup
6623 * \param demod instance of demod.
6626 static int set_qam32(pdrx_demod_instance_t demod)
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 */
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 */
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));
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);
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);
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));
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);
6691 WR16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 20480);
6693 return (DRX_STS_OK);
6695 return (DRX_STS_ERROR);
6698 /*============================================================================*/
6701 * \fn int set_qam64 ()
6702 * \brief QAM64 specific setup
6703 * \param demod instance of demod.
6706 static int set_qam64(pdrx_demod_instance_t demod)
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 */
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 */
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));
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);
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);
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));
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);
6771 WR16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 43008);
6773 return (DRX_STS_OK);
6775 return (DRX_STS_ERROR);
6778 /*============================================================================*/
6781 * \fn int set_qam128 ()
6782 * \brief QAM128 specific setup
6783 * \param demod: instance of demod.
6786 static int set_qam128(pdrx_demod_instance_t demod)
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 */
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 */
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));
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);
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);
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));
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);
6851 WR16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 20992);
6853 return (DRX_STS_OK);
6855 return (DRX_STS_ERROR);
6858 /*============================================================================*/
6861 * \fn int set_qam256 ()
6862 * \brief QAM256 specific setup
6863 * \param demod: instance of demod.
6866 static int set_qam256(pdrx_demod_instance_t demod)
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 */
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 */
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));
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);
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);
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));
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);
6931 WR16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 43520);
6933 return (DRX_STS_OK);
6935 return (DRX_STS_ERROR);
6938 /*============================================================================*/
6939 #define QAM_SET_OP_ALL 0x1
6940 #define QAM_SET_OP_CONSTELLATION 0x2
6941 #define QAM_SET_OP_SPECTRUM 0X4
6944 * \fn int set_qam ()
6945 * \brief Set QAM demod.
6946 * \param demod: instance of demod.
6947 * \param channel: pointer to channel data.
6951 set_qam(pdrx_demod_instance_t demod,
6952 pdrx_channel_t channel, s32 tuner_freq_offset, u32 op)
6954 struct i2c_device_addr *dev_addr = NULL;
6955 pdrxj_data_t ext_attr = NULL;
6956 pdrx_common_attr_t common_attr = NULL;
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,
6967 /* parameter */ NULL,
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 */
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 */
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 */
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 */
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;
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;
7101 QAM_LC_SYMBOL_FREQ_FREQ_QAM_B_256;
7102 channel->symbolrate = 5360537;
7103 iqm_rc_stretch = IQM_RC_STRETCH_QAM_B_256;
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;
7112 return (DRX_STS_INVALID_ARG);
7115 adc_frequency = (common_attr->sys_clock_freq * 1000) / 3;
7116 CHK_ZERO(channel->symbolrate);
7118 (adc_frequency / channel->symbolrate) * (1 << 21) +
7120 ((adc_frequency % channel->symbolrate),
7121 channel->symbolrate) >> 7) - (1 << 23);
7124 (channel->symbolrate +
7125 (adc_frequency >> 13),
7126 adc_frequency) >> 16);
7127 if (lc_symbol_freq > 511)
7128 lc_symbol_freq = 511;
7130 iqm_rc_stretch = 21;
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 */
7146 return (DRX_STS_INVALID_ARG);
7150 if (op & QAM_SET_OP_ALL) {
7152 STEP 1: reset demodulator
7153 resets IQM, QAM and FEC HW blocks
7154 resets SCU variables
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);
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));
7174 if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
7176 STEP 2: configure demodulator
7178 -set params (resets IQM,QAM,FEC HW; initializes some SCU variables )
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));
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));
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));
7209 if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
7211 WR16(dev_addr, QAM_LC_SYMBOL_FREQ__A, lc_symbol_freq);
7212 WR16(dev_addr, IQM_RC_STRETCH__A, iqm_rc_stretch);
7215 if (op & QAM_SET_OP_ALL) {
7216 if (ext_attr->has_lna == false) {
7217 WR16(dev_addr, IQM_AF_AMUX__A, 0x02);
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);
7223 WR16(dev_addr, SCU_RAM_QAM_WR_RSV_0__A, 0x5f); /* scu temporary shut down agc */
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);
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 ! */
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 ! */
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 ! */
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);
7257 return (DRX_STS_ERROR);
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);
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);
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));
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));
7298 /* TODO fix this, store a drxj_cfg_afe_gain_t structure in drxj_data_t instead
7300 drxj_cfg_afe_gain_t qam_pga_cfg = { DRX_STANDARD_ITU_B, 0 };
7302 qam_pga_cfg.gain = ext_attr->qam_pga_cfg;
7303 CHK_ERROR(ctrl_set_cfg_afe_gain(demod, &qam_pga_cfg));
7305 CHK_ERROR(ctrl_set_cfg_pre_saw(demod, &(ext_attr->qam_pre_saw_cfg)));
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));
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));
7331 return (DRX_STS_ERROR);
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));
7340 /* SETP 4: constellation specific setup */
7341 switch (channel->constellation) {
7342 case DRX_CONSTELLATION_QAM16:
7343 CHK_ERROR(set_qam16(demod));
7345 case DRX_CONSTELLATION_QAM32:
7346 CHK_ERROR(set_qam32(demod));
7348 case DRX_CONSTELLATION_QAM64:
7349 CHK_ERROR(set_qam64(demod));
7351 case DRX_CONSTELLATION_QAM128:
7352 CHK_ERROR(set_qam128(demod));
7354 case DRX_CONSTELLATION_QAM256:
7355 CHK_ERROR(set_qam256(demod));
7358 return (DRX_STS_ERROR);
7362 if ((op & QAM_SET_OP_ALL)) {
7363 WR16(dev_addr, IQM_CF_SCALE_SH__A, 0);
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));
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;
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));
7391 if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
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));
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);
7407 return (DRX_STS_OK);
7409 return (DRX_STS_ERROR);
7412 /*============================================================================*/
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)
7417 u32 iqm_fs_rate_ofs = 0;
7418 u32 iqm_fs_rate_lo = 0;
7419 u16 qam_ctl_ena = 0;
7425 struct i2c_device_addr *dev_addr = NULL;
7426 pdrxj_data_t ext_attr = NULL;
7428 dev_addr = demod->my_i2c_dev_addr;
7429 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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));
7437 /* freeze the frequency control loop */
7438 WR16(dev_addr, QAM_LC_CF__A, 0);
7439 WR16(dev_addr, QAM_LC_CF1__A, 0);
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;
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);
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);
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;
7463 /* freeze dq/fq updating */
7464 RR16(dev_addr, QAM_DQ_MODE__A, &data);
7466 data = (data & 0xfff9);
7467 WR16(dev_addr, QAM_DQ_MODE__A, data);
7468 WR16(dev_addr, QAM_FQ_MODE__A, data);
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);
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);
7481 WR16(dev_addr, QAM_DQ_MODE__A, data);
7482 WR16(dev_addr, QAM_FQ_MODE__A, data);
7484 WR16(dev_addr, SCU_RAM_QAM_FSM_STATE_TGT__A, 4);
7487 while ((fsm_state != 4) && (i++ < 100)) {
7488 RR16(dev_addr, SCU_RAM_QAM_FSM_STATE__A, &fsm_state);
7490 WR16(dev_addr, SCU_RAM_QAM_CTL_ENA__A, (qam_ctl_ena | 0x0016));
7492 return (DRX_STS_OK);
7494 return (DRX_STS_ERROR);
7499 #define DEMOD_LOCKED 0x1
7500 #define SYNC_FLIPPED 0x2
7501 #define SPEC_MIRRORED 0x4
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.
7512 qam64auto(pdrx_demod_instance_t demod,
7513 pdrx_channel_t channel,
7514 s32 tuner_freq_offset, pdrx_lock_status_t lock_status)
7516 drx_sig_quality_t sig_quality;
7518 u32 state = NO_LOCK;
7520 u32 d_locked_time = 0;
7521 pdrxj_data_t ext_attr = NULL;
7522 u32 timeout_ofs = 0;
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();
7530 CHK_ERROR(ctrl_lock_status(demod, lock_status));
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();
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,
7551 WR16(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A,
7553 state = SYNC_FLIPPED;
7554 drxbsp_hst_sleep(10);
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);
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 =
7573 } else { /* no need to wait lock */
7576 drxbsp_hst_clock() -
7577 DRXJ_QAM_MAX_WAITTIME - timeout_ofs;
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 */
7594 drxbsp_hst_clock() -
7595 DRXJ_QAM_MAX_WAITTIME - timeout_ofs;
7602 drxbsp_hst_sleep(10);
7604 ((*lock_status != DRX_LOCKED) &&
7605 (*lock_status != DRX_NEVER_LOCK) &&
7606 ((drxbsp_hst_clock() - start_time) <
7607 (DRXJ_QAM_MAX_WAITTIME + timeout_ofs))
7609 /* Returning control to apllication ... */
7611 return (DRX_STS_OK);
7613 return (DRX_STS_ERROR);
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.
7626 qam256auto(pdrx_demod_instance_t demod,
7627 pdrx_channel_t channel,
7628 s32 tuner_freq_offset, pdrx_lock_status_t lock_status)
7630 drx_sig_quality_t sig_quality;
7631 u32 state = NO_LOCK;
7633 u32 d_locked_time = 0;
7634 pdrxj_data_t ext_attr = NULL;
7635 u32 timeout_ofs = DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME;
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();
7643 CHK_ERROR(ctrl_lock_status(demod, lock_status));
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();
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;
7675 drxbsp_hst_sleep(10);
7677 ((*lock_status < DRX_LOCKED) &&
7678 (*lock_status != DRX_NEVER_LOCK) &&
7679 ((drxbsp_hst_clock() - start_time) <
7680 (DRXJ_QAM_MAX_WAITTIME + timeout_ofs)));
7682 return (DRX_STS_OK);
7684 return (DRX_STS_ERROR);
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.
7695 set_qamChannel(pdrx_demod_instance_t demod,
7696 pdrx_channel_t channel, s32 tuner_freq_offset)
7698 drx_lock_status_t lock_status = DRX_NOT_LOCKED;
7699 pdrxj_data_t ext_attr = NULL;
7700 bool auto_flag = false;
7702 /* external attributes for storing aquired channel constellation */
7703 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
7716 ext_attr->mirror = channel->mirror;
7719 (demod, channel, tuner_freq_offset, QAM_SET_OP_ALL));
7721 if ((ext_attr->standard == DRX_STANDARD_ITU_B) &&
7722 (channel->constellation == DRX_CONSTELLATION_QAM64)) {
7724 (demod, channel, tuner_freq_offset,
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,
7736 case DRX_CONSTELLATION_AUTO: /* for channel scan */
7737 if (ext_attr->standard == DRX_STANDARD_ITU_B) {
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;
7745 ext_attr->mirror = channel->mirror;
7748 (demod, channel, tuner_freq_offset,
7750 CHK_ERROR(qam256auto
7751 (demod, channel, tuner_freq_offset,
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;
7763 ext_attr->mirror = channel->mirror;
7766 u16 qam_ctl_ena = 0;
7767 RR16(demod->my_i2c_dev_addr,
7768 SCU_RAM_QAM_CTL_ENA__A,
7770 WR16(demod->my_i2c_dev_addr,
7771 SCU_RAM_QAM_CTL_ENA__A,
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 */
7779 QAM_SET_OP_CONSTELLATION));
7780 WR16(demod->my_i2c_dev_addr,
7781 SCU_RAM_QAM_CTL_ENA__A, qam_ctl_ena);
7784 (demod, channel, tuner_freq_offset,
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;
7793 if (channel->mirror == DRX_MIRROR_AUTO) {
7794 ext_attr->mirror = DRX_MIRROR_NO;
7796 ext_attr->mirror = channel->mirror;
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 */
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);
7814 (demod, channel, tuner_freq_offset,
7816 channel->constellation = DRX_CONSTELLATION_AUTO;
7818 channel->constellation = DRX_CONSTELLATION_AUTO;
7819 return (DRX_STS_INVALID_ARG);
7823 return (DRX_STS_INVALID_ARG);
7826 return (DRX_STS_OK);
7828 /* restore starting value */
7830 channel->constellation = DRX_CONSTELLATION_AUTO;
7831 return (DRX_STS_ERROR);
7834 /*============================================================================*/
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
7841 * precondition: measurement period & measurement prescale must be set
7845 GetQAMRSErr_count(struct i2c_device_addr *dev_addr, p_drxjrs_errors_t rs_errors)
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;
7851 /* check arguments */
7852 if (dev_addr == NULL) {
7853 return (DRX_STS_INVALID_ARG);
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);
7869 /* These register values are fetched in non-atomic fashion */
7870 /* It is possible that the read values contain unrelated information */
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;
7879 return (DRX_STS_OK);
7881 return (DRX_STS_ERROR);
7884 /*============================================================================*/
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.
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.
7896 * Pre-condition: Device must be started and in lock.
7899 ctrl_get_qam_sig_quality(pdrx_demod_instance_t demod, pdrx_sig_quality_t sig_quality)
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 };
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 */
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;
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);
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;
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;
7956 case DRX_CONSTELLATION_QAM32:
7957 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM32 << 2;
7959 case DRX_CONSTELLATION_QAM64:
7960 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM64 << 2;
7962 case DRX_CONSTELLATION_QAM128:
7963 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM128 << 2;
7965 case DRX_CONSTELLATION_QAM256:
7966 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM256 << 2;
7969 return (DRX_STS_ERROR);
7972 /* ------------------------------ */
7973 /* MER Calculation */
7974 /* ------------------------------ */
7975 /* MER is good if it is above 27.5 for QAM256 or 21.5 for QAM64 */
7977 /* 10.0*log10(qam_sl_sig_power * 4.0 / qam_sl_err_power); */
7978 if (qam_sl_err_power == 0)
7982 log1_times100(qam_sl_sig_power) -
7983 log1_times100((u32) qam_sl_err_power);
7985 /* ----------------------------------------- */
7986 /* Pre Viterbi Symbol Error Rate Calculation */
7987 /* ----------------------------------------- */
7988 /* pre viterbi SER is good if it is bellow 0.025 */
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;
8000 if ((m << e) >> 3 > 549752) { /* the max of frac_times1e6 */
8001 qam_vd_ser = 500000; /* clip BER 0.5 */
8004 frac_times1e6(m << ((e > 2) ? (e - 3) : e),
8005 vd_bit_cnt * ((e > 2) ? 1 : 8) / 8);
8008 /* --------------------------------------- */
8009 /* pre and post RedSolomon BER Calculation */
8010 /* --------------------------------------- */
8011 /* pre RS BER is good if it is below 3.5e-4 */
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;
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;
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 */
8030 qam_pre_rs_ber = frac_times1e6(m, rs_bit_cnt >> e);
8033 /* post RS BER = 1000000* (11.17 * FEC_OC_SNC_FAIL_COUNT__A) / */
8034 /* (1504.0 * FEC_OC_SNC_FAIL_PERIOD__A) */
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
8042 Precision errors still possible.
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;
8049 qam_post_rs_ber = e / m;
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;
8056 sig_quality->pre_viterbi_ber = qam_pre_rs_ber;
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));
8064 sig_quality->packet_error = ((u16) pkt_errs);
8067 return (DRX_STS_OK);
8069 return (DRX_STS_ERROR);
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.
8081 ctrl_get_qam_constel(pdrx_demod_instance_t demod, pdrx_complex_t complex_nr)
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 */
8091 struct i2c_device_addr *dev_addr = NULL;
8092 /**< device address */
8094 /* read device info */
8095 dev_addr = demod->my_i2c_dev_addr;
8098 /* Monitor bus grabbing is an open external interface issue */
8099 /* Needs to be checked when external interface PG is updated */
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);
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);
8125 /* Disable MB grabber in the FEC OC */
8126 WR16(dev_addr, FEC_OC_OCR_MODE__A, 0x00);
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);
8134 /* interpret data (re & im) according to the Monitor bus mapping ?? */
8136 /* sign extension, 10th bit is sign bit */
8137 if ((re & 0x0200) == 0x0200) {
8140 if ((im & 0x0200) == 0x0200) {
8143 complex_nr->re = ((s16) re);
8144 complex_nr->im = ((s16) im);
8146 /* Restore MB (Monitor bus) */
8147 WR16(dev_addr, QAM_SL_COMM_MB__A, qam_sl_comm_mbInit);
8149 return (DRX_STS_OK);
8151 return (DRX_STS_ERROR);
8153 #endif /* #ifndef DRXJ_VSB_ONLY */
8155 /*============================================================================*/
8156 /*== END QAM DATAPATH FUNCTIONS ==*/
8157 /*============================================================================*/
8159 /*============================================================================*/
8160 /*============================================================================*/
8161 /*== ATV DATAPATH FUNCTIONS ==*/
8162 /*============================================================================*/
8163 /*============================================================================*/
8166 Implementation notes.
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)
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.
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)
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
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
8195 (Shadow settings will not be used for now, they will be implemented
8196 later on because of the schedule)
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
8211 The "settings" will consist of: AGC settings, filter settings etc.
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.
8219 /* -------------------------------------------------------------------------- */
8222 * \brief Get array index for atv coef (ext_attr->atvTopCoefX[index])
8224 * \param pointer to index
8228 static int atv_equ_coef_index(enum drx_standard standard, int *index)
8231 case DRX_STANDARD_PAL_SECAM_BG:
8232 *index = (int)DRXJ_COEF_IDX_BG;
8234 case DRX_STANDARD_PAL_SECAM_DK:
8235 *index = (int)DRXJ_COEF_IDX_DK;
8237 case DRX_STANDARD_PAL_SECAM_I:
8238 *index = (int)DRXJ_COEF_IDX_I;
8240 case DRX_STANDARD_PAL_SECAM_L:
8241 *index = (int)DRXJ_COEF_IDX_L;
8243 case DRX_STANDARD_PAL_SECAM_LP:
8244 *index = (int)DRXJ_COEF_IDX_LP;
8246 case DRX_STANDARD_NTSC:
8247 *index = (int)DRXJ_COEF_IDX_MN;
8249 case DRX_STANDARD_FM:
8250 *index = (int)DRXJ_COEF_IDX_FM;
8253 *index = (int)DRXJ_COEF_IDX_MN; /* still return a valid index */
8254 return DRX_STS_ERROR;
8261 /* -------------------------------------------------------------------------- */
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.
8271 atv_update_config(pdrx_demod_instance_t demod, bool force_update)
8273 struct i2c_device_addr *dev_addr = NULL;
8274 pdrxj_data_t ext_attr = NULL;
8276 dev_addr = demod->my_i2c_dev_addr;
8277 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
8279 /* equalizer coefficients */
8281 ((ext_attr->atv_cfg_changed_flags & DRXJ_ATV_CHANGED_COEF) != 0)) {
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]);
8291 /* bypass fast carrier recovery */
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;
8300 data |= IQM_RT_ROT_BP_ROT_OFF_ACTIVE;
8302 WR16(dev_addr, IQM_RT_ROT_BP__A, data);
8305 /* peak filter setting */
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);
8311 /* noise filter setting */
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);
8317 /* SIF attenuation */
8319 ((ext_attr->atv_cfg_changed_flags & DRXJ_ATV_CHANGED_SIF_ATT) != 0)) {
8320 u16 attenuation = 0;
8322 switch (ext_attr->sif_attenuation) {
8323 case DRXJ_SIF_ATTENUATION_0DB:
8324 attenuation = ATV_TOP_AF_SIF_ATT_0DB;
8326 case DRXJ_SIF_ATTENUATION_3DB:
8327 attenuation = ATV_TOP_AF_SIF_ATT_M3DB;
8329 case DRXJ_SIF_ATTENUATION_6DB:
8330 attenuation = ATV_TOP_AF_SIF_ATT_M6DB;
8332 case DRXJ_SIF_ATTENUATION_9DB:
8333 attenuation = ATV_TOP_AF_SIF_ATT_M9DB;
8336 return DRX_STS_ERROR;
8339 WR16(dev_addr, ATV_TOP_AF_SIF_ATT__A, attenuation);
8342 /* SIF & CVBS enable */
8344 ((ext_attr->atv_cfg_changed_flags & DRXJ_ATV_CHANGED_OUTPUT) != 0)) {
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;
8351 data &= (~ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE);
8354 if (ext_attr->enable_sif_output) {
8355 data &= (~ATV_TOP_STDBY_SIF_STDBY_STANDBY);
8357 data |= ATV_TOP_STDBY_SIF_STDBY_STANDBY;
8359 WR16(dev_addr, ATV_TOP_STDBY__A, data);
8362 ext_attr->atv_cfg_changed_flags = 0;
8364 return (DRX_STS_OK);
8366 return (DRX_STS_ERROR);
8369 /* -------------------------------------------------------------------------- */
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
8379 ctrl_set_cfg_atv_output(pdrx_demod_instance_t demod, p_drxj_cfg_atv_output_t output_cfg)
8381 pdrxj_data_t ext_attr = NULL;
8383 /* Check arguments */
8384 if (output_cfg == NULL) {
8385 return (DRX_STS_INVALID_ARG);
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:
8398 return DRX_STS_INVALID_ARG;
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;
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;
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;
8418 CHK_ERROR(atv_update_config(demod, false));
8420 return (DRX_STS_OK);
8422 return (DRX_STS_ERROR);
8425 /* -------------------------------------------------------------------------- */
8426 #ifndef DRXJ_DIGITAL_ONLY
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
8436 ctrl_set_cfg_atv_equ_coef(pdrx_demod_instance_t demod, p_drxj_cfg_atv_equ_coef_t coef)
8438 pdrxj_data_t ext_attr = NULL;
8441 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
8443 /* current standard needs to be an ATV standard */
8444 if (!DRXJ_ISATVSTD(ext_attr->standard)) {
8445 return DRX_STS_ERROR;
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);
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;
8468 CHK_ERROR(atv_update_config(demod, false));
8470 return (DRX_STS_OK);
8472 return (DRX_STS_ERROR);
8475 /* -------------------------------------------------------------------------- */
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
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
8490 ctrl_get_cfg_atv_equ_coef(pdrx_demod_instance_t demod, p_drxj_cfg_atv_equ_coef_t coef)
8492 pdrxj_data_t ext_attr = NULL;
8495 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
8497 /* current standard needs to be an ATV standard */
8498 if (!DRXJ_ISATVSTD(ext_attr->standard)) {
8499 return DRX_STS_ERROR;
8502 /* Check arguments */
8504 return DRX_STS_INVALID_ARG;
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];
8513 return (DRX_STS_OK);
8515 return (DRX_STS_ERROR);
8518 /* -------------------------------------------------------------------------- */
8520 * \fn int ctrl_set_cfg_atv_misc()
8521 * \brief Set misc. settings for ATV.
8522 * \param demod instance of demodulator
8528 ctrl_set_cfg_atv_misc(pdrx_demod_instance_t demod, p_drxj_cfg_atv_misc_t settings)
8530 pdrxj_data_t ext_attr = NULL;
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);
8540 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
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;
8552 CHK_ERROR(atv_update_config(demod, false));
8554 return (DRX_STS_OK);
8556 return (DRX_STS_ERROR);
8559 /* -------------------------------------------------------------------------- */
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
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
8573 ctrl_get_cfg_atv_misc(pdrx_demod_instance_t demod, p_drxj_cfg_atv_misc_t settings)
8575 pdrxj_data_t ext_attr = NULL;
8577 /* Check arguments */
8578 if (settings == NULL) {
8579 return DRX_STS_INVALID_ARG;
8582 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
8584 settings->peak_filter = ext_attr->atv_top_vid_peak;
8585 settings->noise_filter = ext_attr->atv_top_noise_th;
8587 return (DRX_STS_OK);
8590 /* -------------------------------------------------------------------------- */
8592 /* -------------------------------------------------------------------------- */
8594 * \fn int ctrl_get_cfg_atv_output()
8596 * \param demod instance of demodulator
8597 * \param output_cfg output configuaration
8602 ctrl_get_cfg_atv_output(pdrx_demod_instance_t demod, p_drxj_cfg_atv_output_t output_cfg)
8606 /* Check arguments */
8607 if (output_cfg == NULL) {
8608 return DRX_STS_INVALID_ARG;
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;
8615 output_cfg->enable_cvbs_output = false;
8618 if (data & ATV_TOP_STDBY_SIF_STDBY_STANDBY) {
8619 output_cfg->enable_sif_output = false;
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;
8626 return (DRX_STS_OK);
8628 return (DRX_STS_ERROR);
8631 /* -------------------------------------------------------------------------- */
8633 * \fn int ctrl_get_cfg_atv_agc_status()
8635 * \param demod instance of demodulator
8636 * \param agc_status agc status
8641 ctrl_get_cfg_atv_agc_status(pdrx_demod_instance_t demod,
8642 p_drxj_cfg_atv_agc_status_t agc_status)
8644 struct i2c_device_addr *dev_addr = NULL;
8645 pdrxj_data_t ext_attr = NULL;
8649 /* Check arguments */
8650 if (agc_status == NULL) {
8651 return DRX_STS_INVALID_ARG;
8654 dev_addr = demod->my_i2c_dev_addr;
8655 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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
8661 IQM_AF_AGC_RF__A * 27 is 20 bits worst case.
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 */
8667 if (tmp % 1000 >= 500) {
8668 (agc_status->rf_agc_gain)++;
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
8675 IQM_AF_AGC_IF__A * 27 is 20 bits worst case.
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 */
8681 if (tmp % 1000 >= 500) {
8682 (agc_status->if_agc_gain)++;
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)
8693 SARR16(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, &data);
8694 /* dividing by 32 inclusive rounding */
8696 if ((data & 1) != 0) {
8700 agc_status->video_agc_gain = ((s16) data) - 75; /* 0.1 dB */
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)
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) {
8717 agc_status->audio_agc_gain = ((s16) data) - 4; /* 0.1 dB */
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);
8728 return (DRX_STS_OK);
8730 return (DRX_STS_ERROR);
8733 /* -------------------------------------------------------------------------- */
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 )
8742 * * Starts ATV and IQM
8743 * * AUdio already started during standard init for ATV.
8745 static int power_up_atv(pdrx_demod_instance_t demod, enum drx_standard standard)
8747 struct i2c_device_addr *dev_addr = NULL;
8748 pdrxj_data_t ext_attr = NULL;
8750 dev_addr = demod->my_i2c_dev_addr;
8751 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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));
8759 WR16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_ACTIVE);
8761 /* Audio, already done during set standard */
8763 return (DRX_STS_OK);
8765 return (DRX_STS_ERROR);
8767 #endif /* #ifndef DRXJ_DIGITAL_ONLY */
8769 /* -------------------------------------------------------------------------- */
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 )
8778 * Stops and thus resets ATV and IQM block
8779 * SIF and CVBS ADC are powered down
8780 * Calls audio power down
8783 power_down_atv(pdrx_demod_instance_t demod, enum drx_standard standard, bool primary)
8785 struct i2c_device_addr *dev_addr = NULL;
8786 drxjscu_cmd_t cmd_scu = { /* command */ 0,
8787 /* parameter_len */ 0,
8789 /* *parameter */ NULL,
8793 pdrxj_data_t ext_attr = NULL;
8795 dev_addr = demod->my_i2c_dev_addr;
8796 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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)));
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));
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);
8822 CHK_ERROR(power_down_aud(demod));
8824 return (DRX_STS_OK);
8826 return (DRX_STS_ERROR);
8829 /* -------------------------------------------------------------------------- */
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 )
8837 * Init all channel independent registers.
8838 * Assuming that IQM, ATV and AUD blocks have been reset and are in STOP mode
8841 #ifndef DRXJ_DIGITAL_ONLY
8842 #define SCU_RAM_ATV_ENABLE_IIR_WA__A 0x831F6D /* TODO remove after done with reg import */
8844 set_atv_standard(pdrx_demod_instance_t demod, enum drx_standard *standard)
8846 /* TODO: enable alternative for tap settings via external file
8849 #ifdef DRXJ_ATV_COEF_FILE
8850 #include DRXJ_ATV_COEF_FILE
8852 ... code defining fixed coef's ...
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".
8859 Still to check if this will work; DRXJ_16TO8 macro may cause
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
9103 struct i2c_device_addr *dev_addr = NULL;
9104 drxjscu_cmd_t cmd_scu = { /* command */ 0,
9105 /* parameter_len */ 0,
9107 /* *parameter */ NULL,
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;
9118 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
9119 dev_addr = demod->my_i2c_dev_addr;
9121 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
9122 common_attr = demod->my_common_attr;
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;
9129 /* Upload only audio microcode */
9130 CHK_ERROR(ctrl_u_codeUpload
9131 (demod, &ucode_info, UCODE_UPLOAD, true));
9133 if (common_attr->verify_microcode == true) {
9134 CHK_ERROR(ctrl_u_codeUpload
9135 (demod, &ucode_info, UCODE_VERIFY, true));
9138 /* Prevent uploading audio microcode again */
9139 ext_attr->flag_aud_mc_uploaded = true;
9141 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
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);
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));
9158 WR16(dev_addr, ATV_TOP_MOD_CONTROL__A, ATV_TOP_MOD_CONTROL__PRE);
9160 /* TODO remove AUTO/OFF patches after ucode fix. */
9161 switch (*standard) {
9162 case DRX_STANDARD_NTSC:
9164 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_MN;
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));
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);
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;
9192 case DRX_STANDARD_FM:
9194 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_FM;
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);
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;
9214 case DRX_STANDARD_PAL_SECAM_BG:
9216 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_B;
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;
9243 case DRX_STANDARD_PAL_SECAM_DK:
9245 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_DK;
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;
9272 case DRX_STANDARD_PAL_SECAM_I:
9274 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_I;
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;
9301 case DRX_STANDARD_PAL_SECAM_L:
9302 /* PAL/SECAM L with negative modulation */
9303 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_L;
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;
9332 case DRX_STANDARD_PAL_SECAM_LP:
9333 /* PAL/SECAM L with positive modulation */
9334 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_LP;
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;
9364 return (DRX_STS_ERROR);
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);
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);
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);
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);
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);
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);
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);
9411 /* Override reset values with current shadow settings */
9412 CHK_ERROR(atv_update_config(demod, true));
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)));
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));
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);
9433 WR16(dev_addr, SCU_RAM_ATV_ENABLE_IIR_WA__A, 1);
9434 WR16(dev_addr, SCU_RAM_ATV_IIR_CRIT__A, 225);
9437 return (DRX_STS_OK);
9439 return (DRX_STS_ERROR);
9443 /* -------------------------------------------------------------------------- */
9445 #ifndef DRXJ_DIGITAL_ONLY
9447 * \fn int set_atv_channel ()
9448 * \brief Set ATV channel.
9449 * \param demod: instance of demod.
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.
9459 set_atv_channel(pdrx_demod_instance_t demod,
9460 s32 tuner_freq_offset,
9461 pdrx_channel_t channel, enum drx_standard standard)
9463 drxjscu_cmd_t cmd_scu = { /* command */ 0,
9464 /* parameter_len */ 0,
9466 /* parameter */ NULL,
9470 pdrxj_data_t ext_attr = NULL;
9471 struct i2c_device_addr *dev_addr = NULL;
9473 dev_addr = demod->my_i2c_dev_addr;
9474 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
9477 Program frequency shifter
9478 No need to account for mirroring on RF
9480 if (channel->mirror == DRX_MIRROR_AUTO) {
9481 ext_attr->mirror = DRX_MIRROR_NO;
9483 ext_attr->mirror = channel->mirror;
9486 CHK_ERROR(set_frequency(demod, channel, tuner_freq_offset));
9487 WR16(dev_addr, ATV_TOP_CR_FREQ__A, ATV_TOP_CR_FREQ__PRE);
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));
9498 /* if ( (ext_attr->standard == DRX_STANDARD_FM) && (ext_attr->flagSetAUDdone == true) )
9500 ext_attr->detectedRDS = (bool)false;
9503 return (DRX_STS_OK);
9505 return (DRX_STS_ERROR);
9509 /* -------------------------------------------------------------------------- */
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.
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.
9524 #ifndef DRXJ_DIGITAL_ONLY
9526 get_atv_channel(pdrx_demod_instance_t demod,
9527 pdrx_channel_t channel, enum drx_standard standard)
9530 struct i2c_device_addr *dev_addr = NULL;
9531 pdrxj_data_t ext_attr = NULL;
9533 dev_addr = demod->my_i2c_dev_addr;
9534 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
9537 channel->bandwidth = ((pdrxj_data_t) demod->my_ext_attr)->curr_bandwidth;
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:
9546 u16 measured_offset = 0;
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;
9556 (s32) (((s16) measured_offset) * 10);
9559 case DRX_STANDARD_PAL_SECAM_LP:
9561 u16 measured_offset = 0;
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;
9571 (s32) (((s16) measured_offset) * 10);
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.
9578 /* No bandwidth know for FM */
9579 channel->bandwidth = DRX_BANDWIDTH_UNKNOWN;
9582 return (DRX_STS_ERROR);
9585 channel->frequency -= offset;
9587 return (DRX_STS_OK);
9589 return (DRX_STS_ERROR);
9592 /* -------------------------------------------------------------------------- */
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.
9599 * \retval DRX_STS_OK sig_strength contains valid data.
9600 * \retval DRX_STS_ERROR Erroneous data, sig_strength equals 0.
9602 * Taking into account:
9604 * * IF gain (not implemented yet, waiting for IF gain control by ucode)
9607 * All weights (digital, if, rf) must add up to 100.
9609 * TODO: ? dynamically adapt weights in case RF and/or IF agc of drxj
9613 get_atv_sig_strength(pdrx_demod_instance_t demod, u16 *sig_strength)
9615 struct i2c_device_addr *dev_addr = NULL;
9616 pdrxj_data_t ext_attr = NULL;
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 */
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;
9634 u32 digital_strength = 0; /* 0.. 100 */
9635 u32 rf_strength = 0; /* 0.. 100 */
9636 u32 if_strength = 0; /* 0.. 100 */
9638 dev_addr = demod->my_i2c_dev_addr;
9639 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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 */
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 */
9660 return (DRX_STS_ERROR);
9663 RR16(dev_addr, IQM_AF_AGC_RF__A, &rf_curr_gain);
9664 RR16(dev_addr, IQM_AF_AGC_IF__A, &if_curr_gain);
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;
9680 /* TODO: use SCU_RAM_ATV_RAGC_HR__A to shift max and min in case
9681 of clipping at ADC */
9683 /* Compute signal strength (in %) per "gain domain" */
9686 /* TODO: ADC clipping not handled */
9687 digital_strength = (100 * (digital_max_gain - (u32) digital_curr_gain)) /
9688 (digital_max_gain - digital_min_gain);
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);
9695 /* TODO: ADC clipping not handled */
9696 rf_strength = (100 * ((u32) rf_curr_gain - rf_max_gain)) /
9697 (rf_min_gain - rf_max_gain);
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;
9704 return (DRX_STS_OK);
9706 return (DRX_STS_ERROR);
9709 /* -------------------------------------------------------------------------- */
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.
9716 * \retval DRX_STS_OK sig_quality contains valid data.
9717 * \retval DRX_STS_ERROR Erroneous data, sig_quality indicator equals 0.
9722 atv_sig_quality(pdrx_demod_instance_t demod, pdrx_sig_quality_t sig_quality)
9724 struct i2c_device_addr *dev_addr = NULL;
9725 u16 quality_indicator = 0;
9727 dev_addr = demod->my_i2c_dev_addr;
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;
9739 0x000..0x080: strong signal => 80% .. 100%
9740 0x080..0x700: weak signal => 30% .. 80%
9741 0x700..0x7ff: no signal => 0% .. 30%
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));
9753 sig_quality->indicator =
9754 (30 * (0x7FF - quality_indicator)) / (0x7FF - 0x701);
9757 return (DRX_STS_OK);
9759 return (DRX_STS_ERROR);
9761 #endif /* DRXJ_DIGITAL_ONLY */
9763 /*============================================================================*/
9764 /*== END ATV DATAPATH FUNCTIONS ==*/
9765 /*============================================================================*/
9767 #ifndef DRXJ_EXCLUDE_AUDIO
9768 /*===========================================================================*/
9769 /*===========================================================================*/
9770 /*== AUDIO DATAPATH FUNCTIONS ==*/
9771 /*===========================================================================*/
9772 /*===========================================================================*/
9775 * \brief Power up AUD.
9776 * \param demod instance of demodulator
9780 static int power_up_aud(pdrx_demod_instance_t demod, bool set_standard)
9782 drx_aud_standard_t aud_standard = DRX_AUD_STANDARD_AUTO;
9783 struct i2c_device_addr *dev_addr = NULL;
9785 dev_addr = demod->my_i2c_dev_addr;
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);
9792 if (set_standard == true) {
9793 CHK_ERROR(aud_ctrl_set_standard(demod, &aud_standard));
9798 return DRX_STS_ERROR;
9801 /*============================================================================*/
9804 * \brief Power up AUD.
9805 * \param demod instance of demodulator
9809 static int power_down_aud(pdrx_demod_instance_t demod)
9811 struct i2c_device_addr *dev_addr = NULL;
9812 pdrxj_data_t ext_attr = NULL;
9814 dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
9815 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
9817 WR16(dev_addr, AUD_COMM_EXEC__A, AUD_COMM_EXEC_STOP);
9819 ext_attr->aud_data.audio_is_active = false;
9823 return DRX_STS_ERROR;
9826 /*============================================================================*/
9828 * \brief Get Modus data from audio RAM
9829 * \param demod instance of demodulator
9830 * \param pointer to modus
9834 static int aud_get_modus(pdrx_demod_instance_t demod, u16 *modus)
9836 struct i2c_device_addr *dev_addr = NULL;
9837 pdrxj_data_t ext_attr = NULL;
9843 if (modus == NULL) {
9844 return DRX_STS_INVALID_ARG;
9847 dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
9848 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
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);
9860 r_modus = ((r_modusHi << 12) & AUD_DEM_RAM_MODUS_HI__M)
9861 | (((r_modusLo & AUD_DEM_RAM_MODUS_LO__M)));
9867 return DRX_STS_ERROR;
9871 /*============================================================================*/
9873 * \brief Get audio RDS dat
9874 * \param demod instance of demodulator
9875 * \param pointer to drx_cfg_aud_rds_t
9880 aud_ctrl_get_cfg_rds(pdrx_demod_instance_t demod, pdrx_cfg_aud_rds_t status)
9882 struct i2c_device_addr *addr = NULL;
9883 pdrxj_data_t ext_attr = NULL;
9885 u16 r_rds_array_cnt_init = 0;
9886 u16 r_rds_array_cnt_check = 0;
9888 u16 rds_data_cnt = 0;
9890 addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
9891 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
9893 if (status == NULL) {
9894 return DRX_STS_INVALID_ARG;
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;
9903 status->valid = false;
9905 RR16(addr, AUD_DEM_RD_RDS_ARRAY_CNT__A, &r_rds_array_cnt_init);
9907 if (r_rds_array_cnt_init ==
9908 AUD_DEM_RD_RDS_ARRAY_CNT_RDS_ARRAY_CT_RDS_DATA_NOT_VALID) {
9913 if (ext_attr->aud_data.rds_data_counter == r_rds_array_cnt_init) {
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;
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;
9929 RR16(addr, AUD_DEM_RD_RDS_ARRAY_CNT__A, &r_rds_array_cnt_check);
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;
9938 return DRX_STS_ERROR;
9941 /*============================================================================*/
9943 * \brief Get the current audio carrier detection status
9944 * \param demod instance of demodulator
9945 * \param pointer to aud_ctrl_get_status
9950 aud_ctrl_get_carrier_detect_status(pdrx_demod_instance_t demod, pdrx_aud_status_t status)
9952 pdrxj_data_t ext_attr = NULL;
9953 struct i2c_device_addr *dev_addr = NULL;
9957 if (status == NULL) {
9958 return DRX_STS_INVALID_ARG;
9961 dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
9962 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
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;
9977 /* read stereo sound mode indication */
9978 RR16(dev_addr, AUD_DEM_RD_STATUS__A, &r_data);
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;
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;
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;
9998 status->nicam_status = DRX_AUD_NICAM_BAD;
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;
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;
10016 return DRX_STS_ERROR;
10019 /*============================================================================*/
10021 * \brief Get the current audio status parameters
10022 * \param demod instance of demodulator
10023 * \param pointer to aud_ctrl_get_status
10028 aud_ctrl_get_status(pdrx_demod_instance_t demod, pdrx_aud_status_t status)
10030 pdrxj_data_t ext_attr = NULL;
10031 struct i2c_device_addr *dev_addr = NULL;
10032 drx_cfg_aud_rds_t rds = { false, {0} };
10035 if (status == NULL) {
10036 return DRX_STS_INVALID_ARG;
10039 dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
10040 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
10042 /* carrier detection */
10043 CHK_ERROR(aud_ctrl_get_carrier_detect_status(demod, status));
10046 status->rds = false;
10047 CHK_ERROR(aud_ctrl_get_cfg_rds(demod, &rds));
10048 status->rds = ext_attr->aud_data.rds_data_present;
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;
10057 return DRX_STS_ERROR;
10060 /*============================================================================*/
10062 * \brief Get the current volume settings
10063 * \param demod instance of demodulator
10064 * \param pointer to drx_cfg_aud_volume_t
10069 aud_ctrl_get_cfg_volume(pdrx_demod_instance_t demod, pdrx_cfg_aud_volume_t volume)
10071 struct i2c_device_addr *dev_addr = NULL;
10072 pdrxj_data_t ext_attr = NULL;
10076 u16 r_strength_left = 0;
10077 u16 r_strength_right = 0;
10079 if (volume == NULL) {
10080 return DRX_STS_INVALID_ARG;
10083 dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
10084 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
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;
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;
10106 if (volume->volume > AUD_VOLUME_DB_MAX) {
10107 volume->volume = AUD_VOLUME_DB_MAX;
10111 /* automatic volume control */
10112 RR16(dev_addr, AUD_DSP_WR_AVC__A, &r_avc);
10114 if ((r_avc & AUD_DSP_WR_AVC_AVC_ON__M) == AUD_DSP_WR_AVC_AVC_ON_OFF)
10116 volume->avc_mode = DRX_AUD_AVC_OFF;
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;
10122 case AUD_DSP_WR_AVC_AVC_DECAY_8_SEC:
10123 volume->avc_mode = DRX_AUD_AVC_DECAYTIME_8S;
10125 case AUD_DSP_WR_AVC_AVC_DECAY_4_SEC:
10126 volume->avc_mode = DRX_AUD_AVC_DECAYTIME_4S;
10128 case AUD_DSP_WR_AVC_AVC_DECAY_2_SEC:
10129 volume->avc_mode = DRX_AUD_AVC_DECAYTIME_2S;
10132 return DRX_STS_ERROR;
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;
10142 case AUD_DSP_WR_AVC_AVC_MAX_ATT_18DB:
10143 volume->avc_max_atten = DRX_AUD_AVC_MAX_ATTEN_18DB;
10145 case AUD_DSP_WR_AVC_AVC_MAX_ATT_24DB:
10146 volume->avc_max_atten = DRX_AUD_AVC_MAX_ATTEN_24DB;
10149 return DRX_STS_ERROR;
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;
10158 case AUD_DSP_WR_AVC_AVC_MAX_GAIN_6DB:
10159 volume->avc_max_gain = DRX_AUD_AVC_MAX_GAIN_6DB;
10161 case AUD_DSP_WR_AVC_AVC_MAX_GAIN_12DB:
10162 volume->avc_max_gain = DRX_AUD_AVC_MAX_GAIN_12DB;
10165 return DRX_STS_ERROR;
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);
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) */
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;
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;
10191 return DRX_STS_ERROR;
10194 /*============================================================================*/
10196 * \brief Set the current volume settings
10197 * \param demod instance of demodulator
10198 * \param pointer to drx_cfg_aud_volume_t
10203 aud_ctrl_set_cfg_volume(pdrx_demod_instance_t demod, pdrx_cfg_aud_volume_t volume)
10205 struct i2c_device_addr *dev_addr = NULL;
10206 pdrxj_data_t ext_attr = NULL;
10211 if (volume == NULL) {
10212 return DRX_STS_INVALID_ARG;
10215 dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
10216 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
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;
10231 RR16(dev_addr, AUD_DSP_WR_VOLUME__A, &w_volume);
10233 /* clear the volume mask */
10234 w_volume &= (u16) ~AUD_DSP_WR_VOLUME_VOL_MAIN__M;
10235 if (volume->mute == true) {
10237 /* mute overrules volume */
10238 w_volume |= (u16) (0);
10241 w_volume |= (u16) ((volume->volume + AUD_VOLUME_ZERO_DB) <<
10242 AUD_DSP_WR_VOLUME_VOL_MAIN__B);
10245 WR16(dev_addr, AUD_DSP_WR_VOLUME__A, w_volume);
10247 /* automatic volume control */
10248 RR16(dev_addr, AUD_DSP_WR_AVC__A, &w_avc);
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;
10254 if (volume->avc_mode == DRX_AUD_AVC_OFF) {
10255 w_avc |= (AUD_DSP_WR_AVC_AVC_ON_OFF);
10258 w_avc |= (AUD_DSP_WR_AVC_AVC_ON_ON);
10261 switch (volume->avc_mode) {
10262 case DRX_AUD_AVC_DECAYTIME_20MS:
10263 w_avc |= AUD_DSP_WR_AVC_AVC_DECAY_20_MSEC;
10265 case DRX_AUD_AVC_DECAYTIME_8S:
10266 w_avc |= AUD_DSP_WR_AVC_AVC_DECAY_8_SEC;
10268 case DRX_AUD_AVC_DECAYTIME_4S:
10269 w_avc |= AUD_DSP_WR_AVC_AVC_DECAY_4_SEC;
10271 case DRX_AUD_AVC_DECAYTIME_2S:
10272 w_avc |= AUD_DSP_WR_AVC_AVC_DECAY_2_SEC;
10275 return DRX_STS_INVALID_ARG;
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;
10285 case DRX_AUD_AVC_MAX_ATTEN_18DB:
10286 w_avc |= AUD_DSP_WR_AVC_AVC_MAX_ATT_18DB;
10288 case DRX_AUD_AVC_MAX_ATTEN_24DB:
10289 w_avc |= AUD_DSP_WR_AVC_AVC_MAX_ATT_24DB;
10292 return DRX_STS_INVALID_ARG;
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;
10301 case DRX_AUD_AVC_MAX_GAIN_6DB:
10302 w_avc |= AUD_DSP_WR_AVC_AVC_MAX_GAIN_6DB;
10304 case DRX_AUD_AVC_MAX_GAIN_12DB:
10305 w_avc |= AUD_DSP_WR_AVC_AVC_MAX_GAIN_12DB;
10308 return DRX_STS_INVALID_ARG;
10311 /* avc reference level */
10312 if (volume->avc_ref_level > AUD_MAX_AVC_REF_LEVEL) {
10313 return DRX_STS_INVALID_ARG;
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);
10319 WR16(dev_addr, AUD_DSP_WR_AVC__A, w_avc);
10321 /* all done, store config in data structure */
10322 ext_attr->aud_data.volume = *volume;
10326 return DRX_STS_ERROR;
10329 /*============================================================================*/
10331 * \brief Get the I2S settings
10332 * \param demod instance of demodulator
10333 * \param pointer to drx_cfg_i2s_output_t
10338 aud_ctrl_get_cfg_output_i2s(pdrx_demod_instance_t demod, pdrx_cfg_i2s_output_t output)
10340 struct i2c_device_addr *dev_addr = NULL;
10341 pdrxj_data_t ext_attr = NULL;
10343 u16 w_i2s_config = 0;
10344 u16 r_i2s_freq = 0;
10346 if (output == NULL) {
10347 return DRX_STS_INVALID_ARG;
10350 dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
10351 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
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);
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;
10367 case AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST_SLAVE:
10368 output->mode = DRX_I2S_MODE_SLAVE;
10371 return DRX_STS_ERROR;
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;
10379 case AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE_NO_DELAY:
10380 output->format = DRX_I2S_FORMAT_WS_WITH_DATA;
10383 return DRX_STS_ERROR;
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;
10391 case AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN_BIT_32:
10392 output->word_length = DRX_I2S_WORDLENGTH_32;
10395 return DRX_STS_ERROR;
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;
10403 case AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL_LEFT_LOW:
10404 output->polarity = DRX_I2S_POLARITY_RIGHT;
10407 return DRX_STS_ERROR;
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;
10415 output->output_enable = false;
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;
10424 output->frequency = AUD_I2S_FREQUENCY_MAX;
10429 return DRX_STS_ERROR;
10432 /*============================================================================*/
10434 * \brief Set the I2S settings
10435 * \param demod instance of demodulator
10436 * \param pointer to drx_cfg_i2s_output_t
10441 aud_ctrl_set_cfg_output_i2s(pdrx_demod_instance_t demod, pdrx_cfg_i2s_output_t output)
10443 struct i2c_device_addr *dev_addr = NULL;
10444 pdrxj_data_t ext_attr = NULL;
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;
10452 if (output == NULL) {
10453 return DRX_STS_INVALID_ARG;
10456 dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
10457 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
10465 RR16(dev_addr, AUD_DEM_RAM_I2S_CONFIG2__A, &w_i2s_config);
10468 w_i2s_config &= (u16) ~AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST__M;
10470 switch (output->mode) {
10471 case DRX_I2S_MODE_MASTER:
10472 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST_MASTER;
10474 case DRX_I2S_MODE_SLAVE:
10475 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST_SLAVE;
10478 return DRX_STS_INVALID_ARG;
10482 w_i2s_config &= (u16) ~AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE__M;
10484 switch (output->format) {
10485 case DRX_I2S_FORMAT_WS_ADVANCED:
10486 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE_DELAY;
10488 case DRX_I2S_FORMAT_WS_WITH_DATA:
10489 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE_NO_DELAY;
10492 return DRX_STS_INVALID_ARG;
10495 /* I2S word length */
10496 w_i2s_config &= (u16) ~AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN__M;
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;
10502 case DRX_I2S_WORDLENGTH_32:
10503 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN_BIT_32;
10506 return DRX_STS_INVALID_ARG;
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;
10515 case DRX_I2S_POLARITY_RIGHT:
10516 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL_LEFT_LOW;
10519 return DRX_STS_INVALID_ARG;
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;
10527 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_ENABLE_DISABLE;
10533 w_i2s_freq = 6144 * 48000 * nrbits / ( 32 * frequency )
10535 16bit: 6144 * 48000 / ( 2 * freq ) = ( 6144 * 48000 / freq ) / 2
10536 32bit: 6144 * 48000 / freq = ( 6144 * 48000 / freq )
10538 if ((output->frequency > AUD_I2S_FREQUENCY_MAX) ||
10539 output->frequency < AUD_I2S_FREQUENCY_MIN) {
10540 return DRX_STS_INVALID_ARG;
10543 w_i2s_freq = (6144UL * 48000UL) + (output->frequency >> 1);
10544 w_i2s_freq /= output->frequency;
10546 if (output->word_length == DRX_I2S_WORDLENGTH_16) {
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);
10553 /* configure I2S output pads for master or slave mode */
10554 WR16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
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;
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;
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);
10576 WR16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY__PRE);
10578 /* all done, store config in data structure */
10579 ext_attr->aud_data.i2sdata = *output;
10583 return DRX_STS_ERROR;
10586 /*============================================================================*/
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
10596 aud_ctrl_get_cfg_auto_sound(pdrx_demod_instance_t demod,
10597 pdrx_cfg_aud_auto_sound_t auto_sound)
10599 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
10600 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
10604 if (auto_sound == NULL) {
10605 return DRX_STS_INVALID_ARG;
10608 dev_addr = demod->my_i2c_dev_addr;
10609 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
10617 CHK_ERROR(aud_get_modus(demod, &r_modus));
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:
10624 DRX_AUD_AUTO_SOUND_OFF;
10626 case AUD_DEM_WR_MODUS_MOD_ASS_ON | AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_ENABLED:
10628 DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_ON;
10630 case AUD_DEM_WR_MODUS_MOD_ASS_ON | AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_DISABLED:
10632 DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_OFF;
10635 return DRX_STS_ERROR;
10640 return DRX_STS_ERROR;
10643 /*============================================================================*/
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
10653 aud_ctr_setl_cfg_auto_sound(pdrx_demod_instance_t demod,
10654 pdrx_cfg_aud_auto_sound_t auto_sound)
10656 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
10657 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
10662 if (auto_sound == NULL) {
10663 return DRX_STS_INVALID_ARG;
10666 dev_addr = demod->my_i2c_dev_addr;
10667 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
10675 CHK_ERROR(aud_get_modus(demod, &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;
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;
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;
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;
10696 return DRX_STS_INVALID_ARG;
10699 if (w_modus != r_modus) {
10700 WR16(dev_addr, AUD_DEM_WR_MODUS__A, w_modus);
10702 /* copy to data structure */
10703 ext_attr->aud_data.auto_sound = *auto_sound;
10707 return DRX_STS_ERROR;
10710 /*============================================================================*/
10712 * \brief Get the Automatic Standard Select thresholds
10713 * \param demod instance of demodulator
10714 * \param pointer to pDRXAudASSThres_t
10719 aud_ctrl_get_cfg_ass_thres(pdrx_demod_instance_t demod, pdrx_cfg_aud_ass_thres_t thres)
10721 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
10722 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
10725 u16 thres_btsc = 0;
10726 u16 thres_nicam = 0;
10728 if (thres == NULL) {
10729 return DRX_STS_INVALID_ARG;
10732 dev_addr = demod->my_i2c_dev_addr;
10733 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
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);
10745 thres->a2 = thres_a2;
10746 thres->btsc = thres_btsc;
10747 thres->nicam = thres_nicam;
10751 return DRX_STS_ERROR;
10754 /*============================================================================*/
10756 * \brief Get the Automatic Standard Select thresholds
10757 * \param demod instance of demodulator
10758 * \param pointer to pDRXAudASSThres_t
10763 aud_ctrl_set_cfg_ass_thres(pdrx_demod_instance_t demod, pdrx_cfg_aud_ass_thres_t thres)
10765 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
10766 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
10768 if (thres == NULL) {
10769 return DRX_STS_INVALID_ARG;
10772 dev_addr = demod->my_i2c_dev_addr;
10773 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
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);
10785 /* update DRXK data structure with hardware values */
10786 ext_attr->aud_data.ass_thresholds = *thres;
10790 return DRX_STS_ERROR;
10793 /*============================================================================*/
10795 * \brief Get Audio Carrier settings
10796 * \param demod instance of demodulator
10797 * \param pointer to pdrx_aud_carrier_t
10802 aud_ctrl_get_cfg_carrier(pdrx_demod_instance_t demod, pdrx_cfg_aud_carriers_t carriers)
10804 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
10805 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
10823 if (carriers == NULL) {
10824 return DRX_STS_INVALID_ARG;
10827 dev_addr = demod->my_i2c_dev_addr;
10828 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
10836 CHK_ERROR(aud_get_modus(demod, &w_modus));
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;
10843 case AUD_DEM_WR_MODUS_MOD_CM_A_NOISE:
10844 carriers->a.opt = DRX_NO_CARRIER_NOISE;
10847 return DRX_STS_ERROR;
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;
10856 case AUD_DEM_WR_MODUS_MOD_CM_B_NOISE:
10857 carriers->b.opt = DRX_NO_CARRIER_NOISE;
10860 return DRX_STS_ERROR;
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);
10870 valA = (((u32) dco_a_hi) << 12) | ((u32) dco_a_lo & 0xFFF);
10871 valB = (((u32) dco_b_hi) << 12) | ((u32) dco_b_lo & 0xFFF);
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;
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);
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);
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);
10890 carriers->a.thres = cm_thes_a;
10891 carriers->b.thres = cm_thes_b;
10895 return DRX_STS_ERROR;
10898 /*============================================================================*/
10900 * \brief Set Audio Carrier settings
10901 * \param demod instance of demodulator
10902 * \param pointer to pdrx_aud_carrier_t
10907 aud_ctrl_set_cfg_carrier(pdrx_demod_instance_t demod, pdrx_cfg_aud_carriers_t carriers)
10909 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
10910 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
10923 if (carriers == NULL) {
10924 return DRX_STS_INVALID_ARG;
10927 dev_addr = demod->my_i2c_dev_addr;
10928 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
10936 CHK_ERROR(aud_get_modus(demod, &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;
10945 case DRX_NO_CARRIER_NOISE:
10946 w_modus |= AUD_DEM_WR_MODUS_MOD_CM_A_NOISE;
10949 return DRX_STS_INVALID_ARG;
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;
10959 case DRX_NO_CARRIER_NOISE:
10960 w_modus |= AUD_DEM_WR_MODUS_MOD_CM_B_NOISE;
10963 return DRX_STS_INVALID_ARG;
10967 /* now update the modus register */
10968 if (w_modus != r_modus) {
10969 WR16(dev_addr, AUD_DEM_WR_MODUS__A, w_modus);
10972 /* frequency adjustment for primary & secondary audio channel */
10973 valA = (s32) ((carriers->a.dco) * 1657L / 2);
10974 valB = (s32) ((carriers->b.dco) * 1657L / 2);
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);
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);
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);
10990 /* update DRXK data structure */
10991 ext_attr->aud_data.carriers = *carriers;
10995 return DRX_STS_ERROR;
10998 /*============================================================================*/
11000 * \brief Get I2S Source, I2S matrix and FM matrix
11001 * \param demod instance of demodulator
11002 * \param pointer to pDRXAudmixer_t
11007 aud_ctrl_get_cfg_mixer(pdrx_demod_instance_t demod, pdrx_cfg_aud_mixer_t mixer)
11009 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11010 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11012 u16 src_i2s_matr = 0;
11015 if (mixer == NULL) {
11016 return DRX_STS_INVALID_ARG;
11019 dev_addr = demod->my_i2c_dev_addr;
11020 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
11028 /* Source Selctor */
11029 RR16(dev_addr, AUD_DSP_WR_SRC_I2S_MATR__A, &src_i2s_matr);
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;
11035 case AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_AB:
11036 mixer->source_i2s = DRX_AUD_SRC_STEREO_OR_AB;
11038 case AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_A:
11039 mixer->source_i2s = DRX_AUD_SRC_STEREO_OR_A;
11041 case AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_B:
11042 mixer->source_i2s = DRX_AUD_SRC_STEREO_OR_B;
11045 return DRX_STS_ERROR;
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;
11053 case AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_STEREO:
11054 mixer->matrix_i2s = DRX_AUD_I2S_MATRIX_STEREO;
11056 case AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_SOUND_A:
11057 mixer->matrix_i2s = DRX_AUD_I2S_MATRIX_A_MONO;
11059 case AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_SOUND_B:
11060 mixer->matrix_i2s = DRX_AUD_I2S_MATRIX_B_MONO;
11063 return DRX_STS_ERROR;
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;
11072 case AUD_DEM_WR_FM_MATRIX_GERMAN_MATRIX:
11073 mixer->matrix_fm = DRX_AUD_FM_MATRIX_GERMAN;
11075 case AUD_DEM_WR_FM_MATRIX_KOREAN_MATRIX:
11076 mixer->matrix_fm = DRX_AUD_FM_MATRIX_KOREAN;
11078 case AUD_DEM_WR_FM_MATRIX_SOUND_A:
11079 mixer->matrix_fm = DRX_AUD_FM_MATRIX_SOUND_A;
11081 case AUD_DEM_WR_FM_MATRIX_SOUND_B:
11082 mixer->matrix_fm = DRX_AUD_FM_MATRIX_SOUND_B;
11085 return DRX_STS_ERROR;
11090 return DRX_STS_ERROR;
11093 /*============================================================================*/
11095 * \brief Set I2S Source, I2S matrix and FM matrix
11096 * \param demod instance of demodulator
11097 * \param pointer to DRXAudmixer_t
11102 aud_ctrl_set_cfg_mixer(pdrx_demod_instance_t demod, pdrx_cfg_aud_mixer_t mixer)
11104 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11105 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11107 u16 src_i2s_matr = 0;
11110 if (mixer == NULL) {
11111 return DRX_STS_INVALID_ARG;
11114 dev_addr = demod->my_i2c_dev_addr;
11115 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
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;
11127 switch (mixer->source_i2s) {
11128 case DRX_AUD_SRC_MONO:
11129 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_MONO;
11131 case DRX_AUD_SRC_STEREO_OR_AB:
11132 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_AB;
11134 case DRX_AUD_SRC_STEREO_OR_A:
11135 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_A;
11137 case DRX_AUD_SRC_STEREO_OR_B:
11138 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_B;
11141 return DRX_STS_INVALID_ARG;
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;
11150 case DRX_AUD_I2S_MATRIX_STEREO:
11151 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_STEREO;
11153 case DRX_AUD_I2S_MATRIX_A_MONO:
11154 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_SOUND_A;
11156 case DRX_AUD_I2S_MATRIX_B_MONO:
11157 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_SOUND_B;
11160 return DRX_STS_INVALID_ARG;
11162 /* write the result */
11163 WR16(dev_addr, AUD_DSP_WR_SRC_I2S_MATR__A, src_i2s_matr);
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;
11172 case DRX_AUD_FM_MATRIX_GERMAN:
11173 fm_matr |= AUD_DEM_WR_FM_MATRIX_GERMAN_MATRIX;
11175 case DRX_AUD_FM_MATRIX_KOREAN:
11176 fm_matr |= AUD_DEM_WR_FM_MATRIX_KOREAN_MATRIX;
11178 case DRX_AUD_FM_MATRIX_SOUND_A:
11179 fm_matr |= AUD_DEM_WR_FM_MATRIX_SOUND_A;
11181 case DRX_AUD_FM_MATRIX_SOUND_B:
11182 fm_matr |= AUD_DEM_WR_FM_MATRIX_SOUND_B;
11185 return DRX_STS_INVALID_ARG;
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);
11193 /* update the data structure with hardware state */
11194 ext_attr->aud_data.mixer = *mixer;
11198 return DRX_STS_ERROR;
11201 /*============================================================================*/
11203 * \brief Set AV Sync settings
11204 * \param demod instance of demodulator
11205 * \param pointer to DRXICfgAVSync_t
11210 aud_ctrl_set_cfg_av_sync(pdrx_demod_instance_t demod, pdrx_cfg_aud_av_sync_t av_sync)
11212 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11213 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11215 u16 w_aud_vid_sync = 0;
11217 if (av_sync == NULL) {
11218 return DRX_STS_INVALID_ARG;
11221 dev_addr = demod->my_i2c_dev_addr;
11222 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
11230 /* audio/video synchronisation */
11231 RR16(dev_addr, AUD_DSP_WR_AV_SYNC__A, &w_aud_vid_sync);
11233 w_aud_vid_sync &= (u16) ~AUD_DSP_WR_AV_SYNC_AV_ON__M;
11235 if (*av_sync == DRX_AUD_AVSYNC_OFF) {
11236 w_aud_vid_sync |= AUD_DSP_WR_AV_SYNC_AV_ON_DISABLE;
11238 w_aud_vid_sync |= AUD_DSP_WR_AV_SYNC_AV_ON_ENABLE;
11241 w_aud_vid_sync &= (u16) ~AUD_DSP_WR_AV_SYNC_AV_STD_SEL__M;
11243 switch (*av_sync) {
11244 case DRX_AUD_AVSYNC_NTSC:
11245 w_aud_vid_sync |= AUD_DSP_WR_AV_SYNC_AV_STD_SEL_NTSC;
11247 case DRX_AUD_AVSYNC_MONOCHROME:
11248 w_aud_vid_sync |= AUD_DSP_WR_AV_SYNC_AV_STD_SEL_MONOCHROME;
11250 case DRX_AUD_AVSYNC_PAL_SECAM:
11251 w_aud_vid_sync |= AUD_DSP_WR_AV_SYNC_AV_STD_SEL_PAL_SECAM;
11253 case DRX_AUD_AVSYNC_OFF:
11257 return DRX_STS_INVALID_ARG;
11260 WR16(dev_addr, AUD_DSP_WR_AV_SYNC__A, w_aud_vid_sync);
11263 return DRX_STS_ERROR;
11266 /*============================================================================*/
11268 * \brief Get AV Sync settings
11269 * \param demod instance of demodulator
11270 * \param pointer to DRXICfgAVSync_t
11275 aud_ctrl_get_cfg_av_sync(pdrx_demod_instance_t demod, pdrx_cfg_aud_av_sync_t av_sync)
11277 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11278 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11280 u16 w_aud_vid_sync = 0;
11282 if (av_sync == NULL) {
11283 return DRX_STS_INVALID_ARG;
11286 dev_addr = demod->my_i2c_dev_addr;
11287 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
11295 /* audio/video synchronisation */
11296 RR16(dev_addr, AUD_DSP_WR_AV_SYNC__A, &w_aud_vid_sync);
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;
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;
11308 case AUD_DSP_WR_AV_SYNC_AV_STD_SEL_MONOCHROME:
11309 *av_sync = DRX_AUD_AVSYNC_MONOCHROME;
11311 case AUD_DSP_WR_AV_SYNC_AV_STD_SEL_PAL_SECAM:
11312 *av_sync = DRX_AUD_AVSYNC_PAL_SECAM;
11315 return DRX_STS_ERROR;
11320 return DRX_STS_ERROR;
11323 /*============================================================================*/
11325 * \brief Get deviation mode
11326 * \param demod instance of demodulator
11327 * \param pointer to drx_cfg_aud_deviation_t
11332 aud_ctrl_get_cfg_dev(pdrx_demod_instance_t demod, pdrx_cfg_aud_deviation_t dev)
11334 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11335 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11340 return DRX_STS_INVALID_ARG;
11343 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
11344 dev_addr = demod->my_i2c_dev_addr;
11346 CHK_ERROR(aud_get_modus(demod, &r_modus));
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;
11352 case AUD_DEM_WR_MODUS_MOD_HDEV_A_HIGH_DEVIATION:
11353 *dev = DRX_AUD_DEVIATION_HIGH;
11356 return DRX_STS_ERROR;
11361 return DRX_STS_ERROR;
11364 /*============================================================================*/
11366 * \brief Get deviation mode
11367 * \param demod instance of demodulator
11368 * \param pointer to drx_cfg_aud_deviation_t
11373 aud_ctrl_set_cfg_dev(pdrx_demod_instance_t demod, pdrx_cfg_aud_deviation_t dev)
11375 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11376 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11382 return DRX_STS_INVALID_ARG;
11385 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
11386 dev_addr = demod->my_i2c_dev_addr;
11388 CHK_ERROR(aud_get_modus(demod, &r_modus));
11392 w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_HDEV_A__M;
11395 case DRX_AUD_DEVIATION_NORMAL:
11396 w_modus |= AUD_DEM_WR_MODUS_MOD_HDEV_A_NORMAL;
11398 case DRX_AUD_DEVIATION_HIGH:
11399 w_modus |= AUD_DEM_WR_MODUS_MOD_HDEV_A_HIGH_DEVIATION;
11402 return DRX_STS_INVALID_ARG;
11405 /* now update the modus register */
11406 if (w_modus != r_modus) {
11407 WR16(dev_addr, AUD_DEM_WR_MODUS__A, w_modus);
11409 /* store in drxk data struct */
11410 ext_attr->aud_data.deviation = *dev;
11414 return DRX_STS_ERROR;
11417 /*============================================================================*/
11419 * \brief Get Prescaler settings
11420 * \param demod instance of demodulator
11421 * \param pointer to drx_cfg_aud_prescale_t
11426 aud_ctrl_get_cfg_prescale(pdrx_demod_instance_t demod, pdrx_cfg_aud_prescale_t presc)
11428 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11429 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11431 u16 r_max_fm_deviation = 0;
11432 u16 r_nicam_prescaler = 0;
11434 if (presc == NULL) {
11435 return DRX_STS_INVALID_ARG;
11438 dev_addr = demod->my_i2c_dev_addr;
11439 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
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);
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;
11457 presc->fm_deviation = 380; /* kHz */
11460 /* calculate NICAM gain from pre-scaler */
11462 nicam_gain = 20 * ( log10( preScaler / 16) )
11463 = ( 100log10( preScaler ) - 100log10( 16 ) ) / 5
11465 because log1_times100() cannot return negative numbers
11466 = ( 100log10( 10 * preScaler ) - 100log10( 10 * 16) ) / 5
11468 for 0.1dB resolution:
11470 nicam_gain = 200 * ( log10( preScaler / 16) )
11471 = 2 * ( 100log10( 10 * preScaler ) - 100log10( 10 * 16) )
11472 = ( 100log10( 10 * preScaler^2 ) - 100log10( 10 * 16^2 ) )
11475 r_nicam_prescaler >>= 8;
11476 if (r_nicam_prescaler <= 1) {
11477 presc->nicam_gain = -241;
11480 presc->nicam_gain = (s16) (((s32)
11482 (10 * r_nicam_prescaler *
11483 r_nicam_prescaler)) - (s32)
11484 (log1_times100(10 * 16 * 16))));
11489 return DRX_STS_ERROR;
11492 /*============================================================================*/
11494 * \brief Set Prescaler settings
11495 * \param demod instance of demodulator
11496 * \param pointer to drx_cfg_aud_prescale_t
11501 aud_ctrl_set_cfg_prescale(pdrx_demod_instance_t demod, pdrx_cfg_aud_prescale_t presc)
11503 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11504 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11506 u16 w_max_fm_deviation = 0;
11507 u16 nicam_prescaler;
11509 if (presc == NULL) {
11510 return DRX_STS_INVALID_ARG;
11513 dev_addr = demod->my_i2c_dev_addr;
11514 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
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;
11531 /* NICAM Prescaler */
11532 if ((presc->nicam_gain >= -241) && (presc->nicam_gain <= 180)) {
11535 prescaler = 16 * 10^( gd_b / 20 )
11537 minval of gd_b = -20*log( 16 ) = -24.1dB
11539 negative numbers not allowed for d_b2lin_times100, so
11541 prescaler = 16 * 10^( gd_b / 20 )
11542 = 10^( (gd_b / 20) + log10(16) )
11543 = 10^( (gd_b + 20log10(16)) / 20 )
11547 = 10^( G0.1dB + 200log10(16)) / 200 )
11550 nicam_prescaler = (u16)
11551 ((d_b2lin_times100(presc->nicam_gain + 241UL) + 50UL) / 100UL);
11554 if (nicam_prescaler > 127) {
11555 nicam_prescaler = 127;
11558 /* shift before writing to register */
11559 nicam_prescaler <<= 8;
11561 return (DRX_STS_INVALID_ARG);
11563 /* end of setting NICAM Prescaler */
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);
11568 ext_attr->aud_data.prescale = *presc;
11572 return DRX_STS_ERROR;
11575 /*============================================================================*/
11578 * \param demod instance of demodulator
11579 * \param pointer to drx_aud_beep_t
11583 static int aud_ctrl_beep(pdrx_demod_instance_t demod, pdrx_aud_beep_t beep)
11585 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *) NULL;
11586 pdrxj_data_t ext_attr = (pdrxj_data_t) NULL;
11592 if (beep == NULL) {
11593 return DRX_STS_INVALID_ARG;
11596 dev_addr = demod->my_i2c_dev_addr;
11597 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
11605 if ((beep->volume > 0) || (beep->volume < -127)) {
11606 return DRX_STS_INVALID_ARG;
11609 if (beep->frequency > 3000) {
11610 return DRX_STS_INVALID_ARG;
11613 volume = (u16) beep->volume + 127;
11614 the_beep |= volume << AUD_DSP_WR_BEEPER_BEEP_VOLUME__B;
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;
11620 the_beep |= (u16) frequency;
11622 if (beep->mute == true) {
11626 WR16(dev_addr, AUD_DSP_WR_BEEPER__A, the_beep);
11630 return DRX_STS_ERROR;
11633 /*============================================================================*/
11635 * \brief Set an audio standard
11636 * \param demod instance of demodulator
11637 * \param pointer to drx_aud_standard_t
11642 aud_ctrl_set_standard(pdrx_demod_instance_t demod, pdrx_aud_standard_t standard)
11644 struct i2c_device_addr *dev_addr = NULL;
11645 pdrxj_data_t ext_attr = NULL;
11646 enum drx_standard current_standard = DRX_STANDARD_UNKNOWN;
11648 u16 w_standard = 0;
11652 bool mute_buffer = false;
11653 s16 volume_buffer = 0;
11656 if (standard == NULL) {
11657 return DRX_STS_INVALID_ARG;
11660 dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
11661 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
11669 /* reset RDS data availability flag */
11670 ext_attr->aud_data.rds_data_present = false;
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;
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));
11687 /* get prescaler from presets */
11688 CHK_ERROR(aud_ctrl_set_cfg_prescale(demod, &ext_attr->aud_data.prescale));
11690 CHK_ERROR(aud_get_modus(demod, &r_modus));
11694 switch (*standard) {
11695 case DRX_AUD_STANDARD_AUTO:
11696 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_AUTO;
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;
11704 case DRX_AUD_STANDARD_A2:
11705 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_M_KOREA;
11707 case DRX_AUD_STANDARD_EIAJ:
11708 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_EIA_J;
11710 case DRX_AUD_STANDARD_FM_STEREO:
11711 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_FM_RADIO;
11713 case DRX_AUD_STANDARD_BG_FM:
11714 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_BG_FM;
11716 case DRX_AUD_STANDARD_D_K1:
11717 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_D_K1;
11719 case DRX_AUD_STANDARD_D_K2:
11720 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_D_K2;
11722 case DRX_AUD_STANDARD_D_K3:
11723 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_D_K3;
11725 case DRX_AUD_STANDARD_BG_NICAM_FM:
11726 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_BG_NICAM_FM;
11728 case DRX_AUD_STANDARD_L_NICAM_AM:
11729 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_L_NICAM_AM;
11731 case DRX_AUD_STANDARD_I_NICAM_FM:
11732 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_I_NICAM_FM;
11734 case DRX_AUD_STANDARD_D_K_NICAM_FM:
11735 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_D_K_NICAM_FM;
11737 case DRX_AUD_STANDARD_UNKNOWN:
11738 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_AUTO;
11741 return DRX_STS_ERROR;
11744 if (*standard == DRX_AUD_STANDARD_AUTO) {
11745 /* we need the current standard here */
11746 current_standard = ext_attr->standard;
11748 w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_6_5MHZ__M;
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);
11754 w_modus |= (AUD_DEM_WR_MODUS_MOD_6_5MHZ_D_K);
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);
11761 } else { /* non USA, ignore standard M to save time */
11763 w_modus |= (AUD_DEM_WR_MODUS_MOD_4_5MHZ_CHROMA);
11768 w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_FMRADIO__M;
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);
11774 w_modus |= (AUD_DEM_WR_MODUS_MOD_FMRADIO_US_75U);
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 */
11782 w_modus |= (AUD_DEM_WR_MODUS_MOD_BTSC_BTSC_SAP);
11785 if (w_modus != r_modus) {
11786 WR16(dev_addr, AUD_DEM_WR_MODUS__A, w_modus);
11789 WR16(dev_addr, AUD_DEM_WR_STANDARD_SEL__A, w_standard);
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);
11803 /* write standard selected */
11804 ext_attr->aud_data.audio_standard = *standard;
11808 return DRX_STS_ERROR;
11811 /*============================================================================*/
11813 * \brief Get the current audio standard
11814 * \param demod instance of demodulator
11815 * \param pointer to drx_aud_standard_t
11820 aud_ctrl_get_standard(pdrx_demod_instance_t demod, pdrx_aud_standard_t standard)
11822 struct i2c_device_addr *dev_addr = NULL;
11823 pdrxj_data_t ext_attr = NULL;
11827 if (standard == NULL) {
11828 return DRX_STS_INVALID_ARG;
11831 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
11832 dev_addr = (struct i2c_device_addr *) demod->my_i2c_dev_addr;
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;
11840 *standard = DRX_AUD_STANDARD_UNKNOWN;
11842 RR16(dev_addr, AUD_DEM_RD_STANDARD_RES__A, &r_data);
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;
11850 /* detection done, return correct standard */
11852 /* no standard detected */
11853 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_NO_SOUND_STANDARD:
11854 *standard = DRX_AUD_STANDARD_UNKNOWN;
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;
11860 /* standard is EIA-J (Japan) */
11861 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_NTSC_EIA_J:
11862 *standard = DRX_AUD_STANDARD_EIAJ;
11864 /* standard is BTSC-stereo */
11865 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_BTSC_STEREO:
11866 *standard = DRX_AUD_STANDARD_BTSC;
11868 /* standard is BTSC-mono (SAP) */
11869 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_BTSC_MONO_SAP:
11870 *standard = DRX_AUD_STANDARD_BTSC;
11872 /* standard is FM radio */
11873 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_FM_RADIO:
11874 *standard = DRX_AUD_STANDARD_FM_STEREO;
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;
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;
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;
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;
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;
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;
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;
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;
11909 *standard = DRX_AUD_STANDARD_UNKNOWN;
11914 return DRX_STS_ERROR;
11918 /*============================================================================*/
11920 * \brief Retreive lock status in case of FM standard
11921 * \param demod instance of demodulator
11922 * \param pointer to lock status
11927 fm_lock_status(pdrx_demod_instance_t demod, pdrx_lock_status_t lock_stat)
11929 drx_aud_status_t status;
11931 /* Check detection of audio carriers */
11932 CHK_ERROR(aud_ctrl_get_carrier_detect_status(demod, &status));
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;
11938 *lock_stat = DRX_NOT_LOCKED;
11941 return (DRX_STS_OK);
11944 return (DRX_STS_ERROR);
11947 /*============================================================================*/
11949 * \brief retreive signal quality in case of FM standard
11950 * \param demod instance of demodulator
11951 * \param pointer to signal quality
11954 * Only the quality indicator field is will be supplied.
11955 * This will either be 0% or 100%, nothing in between.
11959 fm_sig_quality(pdrx_demod_instance_t demod, pdrx_sig_quality_t sig_quality)
11961 drx_lock_status_t lock_status = DRX_NOT_LOCKED;
11963 CHK_ERROR(fm_lock_status(demod, &lock_status));
11964 if (lock_status == DRX_LOCKED) {
11965 sig_quality->indicator = 100;
11967 sig_quality->indicator = 0;
11970 return (DRX_STS_OK);
11973 return (DRX_STS_ERROR);
11978 /*===========================================================================*/
11979 /*== END AUDIO DATAPATH FUNCTIONS ==*/
11980 /*===========================================================================*/
11982 /*============================================================================*/
11983 /*============================================================================*/
11984 /*== OOB DATAPATH FUNCTIONS ==*/
11985 /*============================================================================*/
11986 /*============================================================================*/
11987 #ifndef DRXJ_DIGITAL_ONLY
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.
11995 * Gets OOB lock status
11999 get_oob_lock_status(pdrx_demod_instance_t demod,
12000 struct i2c_device_addr *dev_addr, pdrx_lock_status_t oob_lock)
12002 drxjscu_cmd_t scu_cmd;
12004 u16 oob_lock_state;
12006 *oob_lock = DRX_NOT_LOCKED;
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;
12014 CHK_ERROR(scu_command(dev_addr, &scu_cmd));
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;
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;
12032 /* 0xC0 NEVER LOCKED (system will never be able to lock to the signal) */
12033 *oob_lock = DRX_NEVER_LOCK;
12036 /* *oob_lock = scu_cmd.result[1]; */
12038 return (DRX_STS_OK);
12040 return (DRX_STS_ERROR);
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.
12050 * Gets OOB frequency offset
12054 get_oob_symbol_rate_offset(struct i2c_device_addr *dev_addr, s32 *symbol_rate_offset)
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;
12071 u32 symbol_rate = 0;
12072 bool negative = false;
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 */
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 */
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 */
12093 return (DRX_STS_ERROR);
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;
12102 unsigned_timing_offset = 0x00007FFF & (u32) (-data);
12105 unsigned_timing_offset = (u32) data;
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);
12113 timing_offset = (s32) unsigned_timing_offset;
12115 timing_offset = -(s32) unsigned_timing_offset;
12117 *symbol_rate_offset = timing_offset;
12119 return (DRX_STS_OK);
12121 return (DRX_STS_ERROR);
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.
12131 * Gets OOB frequency offset
12135 get_oob_freq_offset(pdrx_demod_instance_t demod, s32 *freq_offset)
12139 u16 symbol_rateReg = 0;
12140 u32 symbol_rate = 0;
12141 s32 coarse_freq_offset = 0;
12142 s32 fine_freq_offset = 0;
12144 s32 coarse_sign = 1;
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;
12151 /* check arguments */
12152 if ((demod == NULL) || (freq_offset == NULL)) {
12153 return DRX_STS_INVALID_ARG;
12156 dev_addr = demod->my_i2c_dev_addr;
12157 common_attr = (pdrx_common_attr_t) demod->my_common_attr;
12161 /* read sign (spectrum inversion) */
12162 RR16(dev_addr, ORX_FWP_IQM_FRQ_W__A, &rot);
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);
12172 mult32(data, (common_attr->sys_clock_freq * 1000) / 6, &data64hi,
12174 temp_freq_offset = (((data64lo >> 21) & 0x7ff) | (data64hi << 11));
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;
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;
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;
12196 return (DRX_STS_ERROR);
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 */
12208 fine_freq_offset *= data; /* Hz */
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 */
12215 if ((rot & 0x8000) == 0x8000)
12216 *freq_offset = -(coarse_freq_offset + fine_freq_offset);
12218 *freq_offset = (coarse_freq_offset + fine_freq_offset);
12220 return (DRX_STS_OK);
12222 return (DRX_STS_ERROR);
12226 * \fn int get_oob_frequency ()
12227 * \brief Get OOB frequency (Unit:KHz).
12228 * \param dev_addr I2C address
12229 * \ frequency OOB frequency parameters.
12232 * Gets OOB frequency
12236 get_oob_frequency(pdrx_demod_instance_t demod, s32 *frequency)
12239 s32 freq_offset = 0;
12241 struct i2c_device_addr *dev_addr = NULL;
12243 dev_addr = demod->my_i2c_dev_addr;
12245 *frequency = 0; /* KHz */
12247 SARR16(dev_addr, SCU_RAM_ORX_RF_RX_FREQUENCY_VALUE__A, &data);
12249 freq = (s32) ((s32) data * 50 + 50000L);
12251 CHK_ERROR(get_oob_freq_offset(demod, &freq_offset));
12253 *frequency = freq + freq_offset;
12255 return (DRX_STS_OK);
12257 return (DRX_STS_ERROR);
12261 * \fn int get_oobmer ()
12262 * \brief Get OOB MER.
12263 * \param dev_addr I2C address
12264 \ MER OOB parameter in dB.
12267 * Gets OOB MER. Table for MER is in Programming guide.
12270 static int get_oobmer(struct i2c_device_addr *dev_addr, u32 *mer)
12276 RR16(dev_addr, ORX_EQU_MER_MER_R__A, &data);
12278 case 0: /* fall through */
12315 case 13: /* fall through */
12319 case 15: /* fall through */
12323 case 17: /* fall through */
12327 case 19: /* fall through */
12331 case 21: /* fall through */
12335 case 23: /* fall through */
12336 case 24: /* fall through */
12340 case 26: /* fall through */
12341 case 27: /* fall through */
12345 case 29: /* fall through */
12346 case 30: /* fall through */
12347 case 31: /* fall through */
12351 case 33: /* fall through */
12352 case 34: /* fall through */
12353 case 35: /* fall through */
12357 case 37: /* fall through */
12358 case 38: /* fall through */
12359 case 39: /* fall through */
12363 case 41: /* fall through */
12364 case 42: /* fall through */
12365 case 43: /* fall through */
12366 case 44: /* fall through */
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 */
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 */
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 */
12398 return (DRX_STS_OK);
12400 return (DRX_STS_ERROR);
12402 #endif /*#ifndef DRXJ_DIGITAL_ONLY */
12405 * \fn int set_orx_nsu_aox()
12406 * \brief Configure OrxNsuAox for OOB
12407 * \param demod instance of demodulator.
12411 static int set_orx_nsu_aox(pdrx_demod_instance_t demod, bool active)
12414 struct i2c_device_addr *dev_addr = NULL;
12415 pdrxj_data_t ext_attr = NULL;
12417 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
12418 dev_addr = demod->my_i2c_dev_addr;
12420 /* Configure NSU_AOX */
12421 RR16(dev_addr, ORX_NSU_AOX_STDBY_W__A, &data);
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)
12432 } else { /* active */
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);
12443 WR16(dev_addr, ORX_NSU_AOX_STDBY_W__A, data);
12445 return (DRX_STS_OK);
12447 return (DRX_STS_ERROR);
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
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
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) */
12471 /* Coefficients for the nyquist fitler (total: 27 taps) */
12472 #define NYQFILTERLEN 27
12474 static int ctrl_set_oob(pdrx_demod_instance_t demod, p_drxoob_t oob_param)
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;
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 */
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) */
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;
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);
12518 ext_attr->oob_power_on = false;
12519 return (DRX_STS_OK);
12522 standard = oob_param->standard;
12524 freq = oob_param->frequency;
12525 if ((freq < 70000) || (freq > 130000))
12526 return (DRX_STS_ERROR);
12527 freq = (freq - 50000) / 50;
12532 u16 *trk_filtercfg = ext_attr->oob_trk_filter_cfg;
12534 index = (u16) ((freq - 400) / 200);
12535 remainder = (u16) ((freq - 400) % 200);
12537 trk_filtercfg[index] - (trk_filtercfg[index] -
12538 trk_filtercfg[index +
12539 1]) / 10 * remainder /
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));
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));
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:
12573 /* signal is transmitted inverted */
12574 ((oob_param->spectrum_inverted == true) &
12575 /* and tuner is not mirroring the signal */
12576 (mirror_freq_spectOOB == false)) |
12578 /* signal is transmitted noninverted */
12579 ((oob_param->spectrum_inverted == false) &
12580 /* and tuner is mirroring the signal */
12581 (mirror_freq_spectOOB == true))
12583 set_param_parameters[0] =
12584 SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC;
12586 set_param_parameters[0] =
12587 SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC;
12589 case DRX_OOB_MODE_B_GRADE_A:
12591 /* signal is transmitted inverted */
12592 ((oob_param->spectrum_inverted == true) &
12593 /* and tuner is not mirroring the signal */
12594 (mirror_freq_spectOOB == false)) |
12596 /* signal is transmitted noninverted */
12597 ((oob_param->spectrum_inverted == false) &
12598 /* and tuner is mirroring the signal */
12599 (mirror_freq_spectOOB == true))
12601 set_param_parameters[0] =
12602 SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_INVSPEC;
12604 set_param_parameters[0] =
12605 SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_REGSPEC;
12607 case DRX_OOB_MODE_B_GRADE_B:
12610 /* signal is transmitted inverted */
12611 ((oob_param->spectrum_inverted == true) &
12612 /* and tuner is not mirroring the signal */
12613 (mirror_freq_spectOOB == false)) |
12615 /* signal is transmitted noninverted */
12616 ((oob_param->spectrum_inverted == false) &
12617 /* and tuner is mirroring the signal */
12618 (mirror_freq_spectOOB == true))
12620 set_param_parameters[0] =
12621 SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_INVSPEC;
12623 set_param_parameters[0] =
12624 SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_REGSPEC;
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));
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 */
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);
12649 WR16(dev_addr, ORX_DDC_OFO_SET_W__A, ORX_DDC_OFO_SET_W__PRE);
12652 WR16(dev_addr, ORX_NSU_AOX_LOPOW_W__A, ext_attr->oob_lo_pow);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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]);
12719 WR16(dev_addr, ORX_FWP_NYQ_ADR_W__A, 31);
12720 WR16(dev_addr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_ACTIVE);
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));
12731 CHK_ERROR(set_orx_nsu_aox(demod, true));
12732 WR16(dev_addr, ORX_NSU_AOX_STHR_W__A, ext_attr->oob_pre_saw);
12734 ext_attr->oob_power_on = true;
12736 return (DRX_STS_OK);
12739 return (DRX_STS_ERROR);
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.
12750 ctrl_get_oob(pdrx_demod_instance_t demod, pdrxoob_status_t oob_status)
12752 #ifndef DRXJ_DIGITAL_ONLY
12753 struct i2c_device_addr *dev_addr = NULL;
12754 pdrxj_data_t ext_attr = NULL;
12757 dev_addr = demod->my_i2c_dev_addr;
12758 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
12760 /* check arguments */
12761 if (oob_status == NULL) {
12762 return (DRX_STS_INVALID_ARG);
12765 if (ext_attr->oob_power_on == false)
12766 return (DRX_STS_ERROR);
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);
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));
12780 return (DRX_STS_OK);
12783 return (DRX_STS_ERROR);
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
12792 #ifndef DRXJ_DIGITAL_ONLY
12794 ctrl_set_cfg_oob_pre_saw(pdrx_demod_instance_t demod, u16 *cfg_data)
12796 struct i2c_device_addr *dev_addr = NULL;
12797 pdrxj_data_t ext_attr = NULL;
12799 if (cfg_data == NULL) {
12800 return (DRX_STS_INVALID_ARG);
12802 dev_addr = demod->my_i2c_dev_addr;
12803 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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);
12809 return (DRX_STS_ERROR);
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
12819 #ifndef DRXJ_DIGITAL_ONLY
12821 ctrl_get_cfg_oob_pre_saw(pdrx_demod_instance_t demod, u16 *cfg_data)
12823 pdrxj_data_t ext_attr = NULL;
12825 if (cfg_data == NULL) {
12826 return (DRX_STS_INVALID_ARG);
12828 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
12830 *cfg_data = ext_attr->oob_pre_saw;
12832 return (DRX_STS_OK);
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
12842 #ifndef DRXJ_DIGITAL_ONLY
12844 ctrl_set_cfg_oob_lo_power(pdrx_demod_instance_t demod, p_drxj_cfg_oob_lo_power_t cfg_data)
12846 struct i2c_device_addr *dev_addr = NULL;
12847 pdrxj_data_t ext_attr = NULL;
12849 if (cfg_data == NULL) {
12850 return (DRX_STS_INVALID_ARG);
12852 dev_addr = demod->my_i2c_dev_addr;
12853 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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);
12859 return (DRX_STS_ERROR);
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
12869 #ifndef DRXJ_DIGITAL_ONLY
12871 ctrl_get_cfg_oob_lo_power(pdrx_demod_instance_t demod, p_drxj_cfg_oob_lo_power_t cfg_data)
12873 pdrxj_data_t ext_attr = NULL;
12875 if (cfg_data == NULL) {
12876 return (DRX_STS_INVALID_ARG);
12878 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
12880 *cfg_data = ext_attr->oob_lo_pow;
12882 return (DRX_STS_OK);
12885 /*============================================================================*/
12886 /*== END OOB DATAPATH FUNCTIONS ==*/
12887 /*============================================================================*/
12889 /*=============================================================================
12890 ===== MC command related functions ==========================================
12891 ===========================================================================*/
12893 /*=============================================================================
12894 ===== ctrl_set_channel() ==========================================================
12895 ===========================================================================*/
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.
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.
12908 ctrl_set_channel(pdrx_demod_instance_t demod, pdrx_channel_t channel)
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;
12927 /*== check arguments ======================================================*/
12928 if ((demod == NULL) || (channel == NULL)) {
12929 return DRX_STS_INVALID_ARG;
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;
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 */
12955 case DRX_STANDARD_UNKNOWN:
12957 return (DRX_STS_INVALID_ARG);
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;
12969 case DRX_BANDWIDTH_8MHZ: /* fall through */
12970 case DRX_BANDWIDTH_7MHZ: /* fall through */
12972 return (DRX_STS_INVALID_ARG);
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:
12982 case DRX_BANDWIDTH_6MHZ: /* fall through */
12983 case DRX_BANDWIDTH_UNKNOWN: /* fall through */
12985 return (DRX_STS_INVALID_ARG);
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;
12999 case DRX_BANDWIDTH_6MHZ: /* fall through */
13000 case DRX_BANDWIDTH_7MHZ: /* fall through */
13002 return (DRX_STS_INVALID_ARG);
13007 /* For QAM annex A and annex C:
13008 -check symbolrate and constellation
13009 -derive bandwidth from symbolrate (input bandwidth is ignored)
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;
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));
13023 if (channel->symbolrate < min_symbol_rate ||
13024 channel->symbolrate > max_symbol_rate) {
13025 return (DRX_STS_INVALID_ARG);
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;
13037 if ((bandwidth_temp % 100) >= 50) {
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;
13051 return (DRX_STS_INVALID_ARG);
13055 /* For QAM annex B:
13056 -check constellation
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:
13065 return (DRX_STS_INVALID_ARG);
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:
13090 return (DRX_STS_INVALID_ARG);
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 };
13098 switch (channel->bandwidth) {
13099 case DRX_BANDWIDTH_8MHZ:
13102 case DRX_BANDWIDTH_7MHZ:
13103 uio1.value = false;
13105 case DRX_BANDWIDTH_6MHZ:
13106 uio1.value = false;
13108 case DRX_BANDWIDTH_UNKNOWN:
13110 return (DRX_STS_INVALID_ARG);
13113 CHK_ERROR(ctrl_uio_write(demod, &uio1));
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
13130 tuner_mode |= TUNER_MODE_ANALOG;
13131 tuner_set_freq = channel->frequency;
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;
13138 channel->frequency + DRXJ_FM_CARRIER_FREQ_OFFSET;
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:
13147 tuner_mode |= TUNER_MODE_DIGITAL;
13148 tuner_set_freq = channel->frequency;
13150 case DRX_STANDARD_UNKNOWN:
13152 return (DRX_STS_ERROR);
13153 } /* switch(standard) */
13155 tuner_mode |= TUNER_MODE_SWITCH;
13156 switch (channel->bandwidth) {
13157 case DRX_BANDWIDTH_8MHZ:
13158 tuner_mode |= TUNER_MODE_8MHZ;
13160 case DRX_BANDWIDTH_7MHZ:
13161 tuner_mode |= TUNER_MODE_7MHZ;
13163 case DRX_BANDWIDTH_6MHZ:
13164 tuner_mode |= TUNER_MODE_6MHZ;
13167 /* TODO: for FM which bandwidth to use ?
13168 also check offset from centre frequency ?
13169 For now using 6MHz.
13171 tuner_mode |= TUNER_MODE_6MHZ;
13173 /* return (DRX_STS_INVALID_ARG); */
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 */
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));
13195 /* Get actual frequency set by tuner and compute offset */
13196 CHK_ERROR(drxbsp_tuner_get_frequency(demod->my_tuner,
13199 &intermediate_freq));
13200 tuner_freq_offset = tuner_get_freq - tuner_set_freq;
13201 common_attr->intermediate_freq = intermediate_freq;
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 ) */
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;
13214 ext_attr->mirror = channel->mirror;
13216 CHK_ERROR(set_vsb(demod));
13217 CHK_ERROR(set_frequency(demod, channel, tuner_freq_offset));
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;
13230 ext_attr->mirror = channel->mirror;
13232 CHK_ERROR(set_atv_channel(demod,
13233 tuner_freq_offset, channel, standard));
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));
13243 case DRX_STANDARD_UNKNOWN:
13245 return (DRX_STS_ERROR);
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;
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));
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));
13270 /* if ( demod->my_tuner !=NULL ) */
13271 /* flag the packet error counter reset */
13272 ext_attr->reset_pkt_err_acc = true;
13274 return (DRX_STS_OK);
13276 return (DRX_STS_ERROR);
13279 /*=============================================================================
13280 ===== ctrl_get_channel() ==========================================================
13281 ===========================================================================*/
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.
13290 ctrl_get_channel(pdrx_demod_instance_t demod, pdrx_channel_t channel)
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;
13306 /* check arguments */
13307 if ((demod == NULL) || (channel == NULL)) {
13308 return DRX_STS_INVALID_ARG;
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;
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;
13333 if (demod->my_tuner != NULL) {
13334 s32 tuner_freq_offset = 0;
13335 bool tuner_mirror = common_attr->mirror_freq_spect ? false : true;
13337 /* Get frequency from tuner */
13338 CHK_ERROR(drxbsp_tuner_get_frequency(demod->my_tuner,
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;
13347 /* negative image */
13348 channel->frequency -= tuner_freq_offset;
13351 /* Handle sound carrier offset in RF domain */
13352 if (standard == DRX_STANDARD_FM) {
13353 channel->frequency -= DRXJ_FM_CARRIER_FREQ_OFFSET;
13356 intermediate_freq = common_attr->intermediate_freq;
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;
13365 channel->symbolrate =
13366 frac28(adc_frequency, (iqm_rc_rateLo + (1 << 23))) >> 7;
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;
13377 #ifndef DRXJ_VSB_ONLY
13378 case DRX_STANDARD_ITU_A:
13379 case DRX_STANDARD_ITU_B:
13380 case DRX_STANDARD_ITU_C:
13382 /* get the channel frequency */
13383 CHK_ERROR(get_ctl_freq_offset
13384 (demod, &ctl_freq_offset));
13385 channel->frequency -= ctl_freq_offset;
13387 if (standard == DRX_STANDARD_ITU_B) {
13388 channel->bandwidth = DRX_BANDWIDTH_6MHZ;
13392 u32 roll_off = 113; /* default annex C */
13394 if (standard == DRX_STANDARD_ITU_A) {
13399 channel->symbolrate * roll_off;
13400 bandwidth = bandwidth_temp / 100;
13402 if ((bandwidth_temp % 100) >= 50) {
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;
13417 } /* if (standard == DRX_STANDARD_ITU_B) */
13420 drxjscu_cmd_t cmd_scu =
13422 /* parameter_len */ 0,
13423 /* result_len */ 0,
13424 /* parameter */ NULL,
13427 u16 cmd_result[3] = { 0, 0, 0 };
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));
13438 channel->interleavemode =
13439 (enum drx_interleave_mode) (cmd_scu.
13443 switch (ext_attr->constellation) {
13444 case DRX_CONSTELLATION_QAM256:
13445 channel->constellation =
13446 DRX_CONSTELLATION_QAM256;
13448 case DRX_CONSTELLATION_QAM128:
13449 channel->constellation =
13450 DRX_CONSTELLATION_QAM128;
13452 case DRX_CONSTELLATION_QAM64:
13453 channel->constellation =
13454 DRX_CONSTELLATION_QAM64;
13456 case DRX_CONSTELLATION_QAM32:
13457 channel->constellation =
13458 DRX_CONSTELLATION_QAM32;
13460 case DRX_CONSTELLATION_QAM16:
13461 channel->constellation =
13462 DRX_CONSTELLATION_QAM16;
13465 channel->constellation =
13466 DRX_CONSTELLATION_UNKNOWN;
13467 return (DRX_STS_ERROR);
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));
13483 case DRX_STANDARD_UNKNOWN: /* fall trough */
13485 return (DRX_STS_ERROR);
13486 } /* switch ( standard ) */
13488 if (lock_status == DRX_LOCKED) {
13489 channel->mirror = ext_attr->mirror;
13492 /* if ( lock_status == DRX_LOCKED ) */
13493 return (DRX_STS_OK);
13495 return (DRX_STS_ERROR);
13498 /*=============================================================================
13499 ===== SigQuality() ==========================================================
13500 ===========================================================================*/
13503 mer2indicator(u16 mer, u16 min_mer, u16 threshold_mer, u16 max_mer)
13507 if (mer < min_mer) {
13509 } else if (mer < threshold_mer) {
13510 if ((threshold_mer - min_mer) != 0) {
13512 25 * (mer - min_mer) / (threshold_mer - min_mer);
13514 } else if (mer < max_mer) {
13515 if ((max_mer - threshold_mer) != 0) {
13517 25 + 75 * (mer - threshold_mer) / (max_mer -
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.
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.
13541 ctrl_sig_quality(pdrx_demod_instance_t demod, pdrx_sig_quality_t sig_quality)
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;
13549 u16 threshold_mer = 0;
13551 /* Check arguments */
13552 if ((sig_quality == NULL) || (demod == NULL)) {
13553 return (DRX_STS_INVALID_ARG);
13556 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
13557 standard = ext_attr->standard;
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));
13567 CHK_ERROR(get_vsb_post_rs_pck_err
13568 (dev_addr, &sig_quality->packet_error));
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;
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));
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,
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;
13601 case DRX_CONSTELLATION_QAM128:
13602 sig_quality->MER = 180;
13604 case DRX_CONSTELLATION_QAM64:
13605 sig_quality->MER = 150;
13607 case DRX_CONSTELLATION_QAM32:
13608 sig_quality->MER = 120;
13610 case DRX_CONSTELLATION_QAM16:
13611 sig_quality->MER = 90;
13614 sig_quality->MER = 0;
13615 return (DRX_STS_ERROR);
13619 switch (ext_attr->constellation) {
13620 case DRX_CONSTELLATION_QAM256:
13622 threshold_mer = 270;
13625 case DRX_CONSTELLATION_QAM64:
13627 threshold_mer = 210;
13630 case DRX_CONSTELLATION_QAM128:
13631 case DRX_CONSTELLATION_QAM32:
13632 case DRX_CONSTELLATION_QAM16:
13635 return (DRX_STS_ERROR);
13637 sig_quality->indicator =
13638 mer2indicator(sig_quality->MER, min_mer, threshold_mer,
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));
13651 case DRX_STANDARD_FM:
13652 CHK_ERROR(fm_sig_quality(demod, sig_quality));
13656 return (DRX_STS_ERROR);
13659 return (DRX_STS_OK);
13661 return (DRX_STS_ERROR);
13664 /*============================================================================*/
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.
13675 ctrl_lock_status(pdrx_demod_instance_t demod, pdrx_lock_status_t lock_stat)
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,
13686 u16 cmd_result[2] = { 0, 0 };
13687 u16 demod_lock = SCU_RAM_PARAM_1_RES_DEMOD_GET_LOCK_DEMOD_LOCKED;
13689 /* check arguments */
13690 if ((demod == NULL) || (lock_stat == NULL)) {
13691 return (DRX_STS_INVALID_ARG);
13694 dev_addr = demod->my_i2c_dev_addr;
13695 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
13696 standard = ext_attr->standard;
13698 *lock_stat = DRX_NOT_LOCKED;
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;
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;
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;
13725 case DRX_STANDARD_FM:
13726 return fm_lock_status(demod, lock_stat);
13728 case DRX_STANDARD_UNKNOWN: /* fallthrough */
13730 return (DRX_STS_ERROR);
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));
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;
13751 /* 0xC000 NEVER LOCKED */
13752 /* (system will never be able to lock to the signal) */
13753 *lock_stat = DRX_NEVER_LOCK;
13756 return (DRX_STS_OK);
13758 return (DRX_STS_ERROR);
13761 /*============================================================================*/
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.
13772 ctrl_constel(pdrx_demod_instance_t demod, pdrx_complex_t complex_nr)
13774 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
13775 /**< active standard */
13777 /* check arguments */
13778 if ((demod == NULL) || (complex_nr == NULL)) {
13779 return (DRX_STS_INVALID_ARG);
13782 /* read device info */
13783 standard = ((pdrxj_data_t) demod->my_ext_attr)->standard;
13785 /* Read constellation point */
13786 switch (standard) {
13787 case DRX_STANDARD_8VSB:
13788 CHK_ERROR(ctrl_get_vsb_constel(demod, complex_nr));
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));
13797 case DRX_STANDARD_UNKNOWN:
13799 return (DRX_STS_ERROR);
13802 return (DRX_STS_OK);
13804 return (DRX_STS_ERROR);
13807 /*============================================================================*/
13810 * \fn int ctrl_set_standard()
13811 * \brief Set modulation standard to be used.
13812 * \param standard Modulation standard.
13815 * Setup stuff for the desired demodulation standard.
13816 * Disable and power down the previous selected demodulation standard
13820 ctrl_set_standard(pdrx_demod_instance_t demod, enum drx_standard *standard)
13822 pdrxj_data_t ext_attr = NULL;
13823 enum drx_standard prev_standard;
13825 /* check arguments */
13826 if ((standard == NULL) || (demod == NULL)) {
13827 return (DRX_STS_INVALID_ARG);
13830 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
13831 prev_standard = ext_attr->standard;
13834 Stop and power down previous standard
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));
13844 case DRX_STANDARD_8VSB:
13845 CHK_ERROR(power_down_vsb(demod, false));
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));
13858 case DRX_STANDARD_UNKNOWN:
13861 case DRX_STANDARD_AUTO: /* fallthrough */
13863 return (DRX_STS_INVALID_ARG);
13867 Initialize channel independent registers
13868 Power up new standard
13870 ext_attr->standard = *standard;
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:
13880 case DRX_STANDARD_8VSB:
13881 CHK_ERROR(set_vsb_leak_n_gain(demod));
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));
13896 ext_attr->standard = DRX_STANDARD_UNKNOWN;
13897 return (DRX_STS_INVALID_ARG);
13901 return (DRX_STS_OK);
13903 /* Don't know what the standard is now ... try again */
13904 ext_attr->standard = DRX_STANDARD_UNKNOWN;
13905 return (DRX_STS_ERROR);
13908 /*============================================================================*/
13911 * \fn int ctrl_get_standard()
13912 * \brief Get modulation standard currently used to demodulate.
13913 * \param standard Modulation standard.
13916 * Returns 8VSB, NTSC, QAM only.
13920 ctrl_get_standard(pdrx_demod_instance_t demod, enum drx_standard *standard)
13922 pdrxj_data_t ext_attr = NULL;
13923 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
13925 /* check arguments */
13926 if (standard == NULL) {
13927 return (DRX_STS_INVALID_ARG);
13929 (*standard) = ext_attr->standard;
13932 return (DRX_STS_OK);
13934 return (DRX_STS_ERROR);
13937 /*============================================================================*/
13940 * \fn int ctrl_get_cfg_symbol_clock_offset()
13941 * \brief Get frequency offsets of STR.
13942 * \param pointer to s32.
13947 ctrl_get_cfg_symbol_clock_offset(pdrx_demod_instance_t demod, s32 *rate_offset)
13949 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
13950 struct i2c_device_addr *dev_addr = NULL;
13951 pdrxj_data_t ext_attr = NULL;
13953 /* check arguments */
13954 if (rate_offset == NULL) {
13955 return (DRX_STS_INVALID_ARG);
13958 dev_addr = demod->my_i2c_dev_addr;
13959 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
13960 standard = ext_attr->standard;
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:
13969 CHK_ERROR(get_str_freq_offset(demod, rate_offset));
13971 case DRX_STANDARD_NTSC:
13972 case DRX_STANDARD_UNKNOWN:
13974 return (DRX_STS_INVALID_ARG);
13977 return (DRX_STS_OK);
13979 return (DRX_STS_ERROR);
13982 /*============================================================================*/
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.
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.
13997 ctrl_power_mode(pdrx_demod_instance_t demod, pdrx_power_mode_t mode)
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;
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;
14008 /* Check arguments */
14009 if (mode == NULL) {
14010 return (DRX_STS_INVALID_ARG);
14013 /* If already in requested power mode, do nothing */
14014 if (common_attr->current_power_mode == *mode) {
14015 return (DRX_STS_OK);
14020 case DRXJ_POWER_DOWN_MAIN_PATH:
14021 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_NONE;
14023 case DRXJ_POWER_DOWN_CORE:
14024 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_CLOCK;
14026 case DRXJ_POWER_DOWN_PLL:
14027 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_PLL;
14029 case DRX_POWER_DOWN:
14030 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC;
14033 /* Unknow sleep mode */
14034 return (DRX_STS_INVALID_ARG);
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));
14043 if ((*mode == DRX_POWER_UP)) {
14044 /* Restore analog & pin configuartion */
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 */
14054 Stop and power down previous standard
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));
14063 case DRX_STANDARD_8VSB:
14064 CHK_ERROR(power_down_vsb(demod, true));
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));
14075 case DRX_STANDARD_UNKNOWN:
14078 case DRX_STANDARD_AUTO: /* fallthrough */
14080 return (DRX_STS_ERROR);
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);
14087 /* Initialize HI, wakeup key especially before put IC to sleep */
14088 CHK_ERROR(init_hi(demod));
14090 ext_attr->hi_cfg_ctrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
14091 CHK_ERROR(hi_cfg_command(demod));
14095 common_attr->current_power_mode = *mode;
14097 return (DRX_STS_OK);
14099 return (DRX_STS_ERROR);
14102 /*============================================================================*/
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.
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.
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
14120 * DRX3942J A2 => number: 42.1.2 text: "DRX3942J:A2"
14121 * DRX3933J B1 => number: 33.2.1 text: "DRX3933J:B1"
14125 ctrl_version(pdrx_demod_instance_t demod, p_drx_version_list_t *version_list)
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 */
14142 static char ucode_name[] = "Microcode";
14143 static char device_name[] = "Device";
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;
14149 /* Microcode version *************************************** */
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];
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);
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);
14168 patch += (10 * (ucode_patch & 0xF));
14170 patch += (100 * (ucode_patch & 0xF));
14172 /* No microcode uploaded, No Rom existed, set version to 0.0.0 */
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;
14181 if (major / 10 != 0) {
14182 ext_attr->v_version[0].v_string[idx++] =
14183 ((char)(major / 10)) + '0';
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';
14195 if (patch / 10 != 0) {
14196 ext_attr->v_version[0].v_string[idx++] =
14197 ((char)(patch / 10)) + '0';
14200 ext_attr->v_version[0].v_string[idx++] = ((char)patch) + '0';
14201 ext_attr->v_version[0].v_string[idx] = '\0';
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]);
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);
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';
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;
14232 ext_attr->v_version[1].v_patch = mfx + 2;
14234 ext_attr->v_version[1].v_patch = mfx + 1;
14236 ext_attr->v_version[1].v_string[6] = ((char)(subtype & 0xF)) + '0';
14237 ext_attr->v_version[1].v_major = (subtype & 0x0F);
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';
14243 ext_attr->v_version[1].v_string[10] = ((char)(mfx & 0xF)) + '2';
14245 ext_attr->v_version[1].v_string[10] = ((char)(mfx & 0xF)) + '1';
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);
14251 *version_list = &(ext_attr->v_list_elements[0]);
14253 return (DRX_STS_OK);
14256 *version_list = (p_drx_version_list_t) (NULL);
14257 return (DRX_STS_ERROR);
14261 /*============================================================================*/
14264 * \fn int ctrl_probe_device()
14265 * \brief Probe device, check if it is present
14266 * \param demod Pointer to demodulator instance.
14268 * \retval DRX_STS_OK a drx39xxj device has been detected.
14269 * \retval DRX_STS_ERROR no drx39xxj device detected.
14271 * This funtion can be caled before open() and after close().
14275 static int ctrl_probe_device(pdrx_demod_instance_t demod)
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);
14281 common_attr = (pdrx_common_attr_t) demod->my_common_attr;
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;
14289 dev_addr = demod->my_i2c_dev_addr;
14291 /* Remeber original power mode */
14292 org_power_mode = common_attr->current_power_mode;
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;
14298 /* Wake-up device, feedback from device */
14299 CHK_ERROR(ctrl_power_mode(demod, &power_mode));
14301 /* Initialize HI, wakeup key especially */
14302 CHK_ERROR(init_hi(demod));
14304 /* Check device id */
14305 RR32(dev_addr, SIO_TOP_JTAGID_LO__A, &jtag);
14306 jtag = (jtag >> 12) & 0xFFFF;
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 */
14318 /* ok , do nothing */
14321 ret_status = DRX_STS_ERROR;
14325 /* Device was not opened, return to orginal powermode,
14326 feedback from device */
14327 CHK_ERROR(ctrl_power_mode(demod, &org_power_mode));
14329 /* dummy read to make this function fail in case device
14330 suddenly disappears after a succesful drx_open */
14334 return (ret_status);
14337 common_attr->current_power_mode = org_power_mode;
14338 return (DRX_STS_ERROR);
14341 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
14342 /*============================================================================*/
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
14352 bool is_mc_block_audio(u32 addr)
14354 if ((addr == AUD_XFP_PRAM_4K__A) || (addr == AUD_XDFP_PRAM_4K__A)) {
14360 /*============================================================================*/
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.
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)
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);
14384 dev_addr = demod->my_i2c_dev_addr;
14385 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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;
14393 mc_data = mc_info->mc_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);
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;
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;
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);
14421 /* Check block header on:
14423 - data larger then 64Kb
14424 - if CRC enabled check CRC
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)))
14432 return DRX_STS_INVALID_ARG;
14435 mc_block_nr_bytes = block_hdr.size * sizeof(u16);
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) {
14441 /*===================================================================*/
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,
14452 return (DRX_STS_ERROR);
14457 /*===================================================================*/
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;
14468 bytes_left_to_compare = mc_block_nr_bytes;
14469 curr_addr = block_hdr.addr;
14470 curr_ptr = mc_data;
14472 while (bytes_left_to_compare != 0) {
14473 if (bytes_left_to_compare >
14475 DRXJ_UCODE_MAX_BUF_SIZE)) {
14478 DRXJ_UCODE_MAX_BUF_SIZE);
14481 bytes_left_to_compare;
14484 if (demod->my_access_funct->
14485 read_block_func(dev_addr,
14493 return (DRX_STS_ERROR);
14497 drxbsp_hst_memcmp(curr_ptr,
14502 return (DRX_STS_ERROR);
14507 (bytes_to_compare / 2));
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 ) */
14516 /*===================================================================*/
14518 return DRX_STS_INVALID_ARG;
14521 } /* switch ( action ) */
14524 /* if( is_mc_block_audio( block_hdr.addr ) == upload_audio_mc ) */
14526 mc_data += mc_block_nr_bytes;
14527 } /* for( i = 0 ; i<mc_nr_of_blks ; i++ ) */
14529 if (upload_audio_mc == false) {
14530 ext_attr->flag_aud_mc_uploaded = false;
14533 return (DRX_STS_OK);
14535 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
14537 /*============================================================================*/
14538 /*== CTRL Set/Get Config related functions ===================================*/
14539 /*============================================================================*/
14541 /*===== SigStrength() =========================================================*/
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.
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.
14554 ctrl_sig_strength(pdrx_demod_instance_t demod, u16 *sig_strength)
14556 pdrxj_data_t ext_attr = NULL;
14557 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
14559 /* Check arguments */
14560 if ((sig_strength == NULL) || (demod == NULL)) {
14561 return (DRX_STS_INVALID_ARG);
14564 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
14565 standard = ext_attr->standard;
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:
14576 CHK_ERROR(get_sig_strength(demod, sig_strength));
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));
14589 case DRX_STANDARD_UNKNOWN: /* fallthrough */
14591 return (DRX_STS_INVALID_ARG);
14595 /* find out if signal strength is calculated in the same way for all standards */
14596 return (DRX_STS_OK);
14598 return (DRX_STS_ERROR);
14601 /*============================================================================*/
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.
14609 #ifndef DRXJ_DIGITAL_ONLY
14611 ctrl_get_cfg_oob_misc(pdrx_demod_instance_t demod, p_drxj_cfg_oob_misc_t misc)
14613 struct i2c_device_addr *dev_addr = NULL;
14617 u16 digital_agc_mant = 0U;
14618 u16 digital_agc_exp = 0U;
14620 /* check arguments */
14621 if (misc == NULL) {
14622 return (DRX_STS_INVALID_ARG);
14624 dev_addr = demod->my_i2c_dev_addr;
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);
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;
14637 SARR16(dev_addr, SCU_RAM_ORX_SCU_LOCK__A, &lock);
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);
14646 SARR16(dev_addr, SCU_RAM_ORX_SCU_STATE__A, &state);
14647 misc->state = (state >> 8) & 0xff;
14649 return (DRX_STS_OK);
14651 return (DRX_STS_ERROR);
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.
14663 ctrl_get_cfg_vsb_misc(pdrx_demod_instance_t demod, p_drxj_cfg_vsb_misc_t misc)
14665 struct i2c_device_addr *dev_addr = NULL;
14667 /* check arguments */
14668 if (misc == NULL) {
14669 return (DRX_STS_INVALID_ARG);
14671 dev_addr = demod->my_i2c_dev_addr;
14673 CHK_ERROR(get_vsb_symb_err(dev_addr, &misc->symb_error));
14675 return (DRX_STS_OK);
14677 return (DRX_STS_ERROR);
14680 /*============================================================================*/
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
14690 * Dispatch handling to standard specific function.
14694 ctrl_set_cfg_agc_if(pdrx_demod_instance_t demod, p_drxj_cfg_agc_t agc_settings)
14696 /* check arguments */
14697 if (agc_settings == NULL) {
14698 return (DRX_STS_INVALID_ARG);
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 */
14707 return (DRX_STS_INVALID_ARG);
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:
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:
14727 return set_agc_if(demod, agc_settings, true);
14728 case DRX_STANDARD_UNKNOWN:
14730 return (DRX_STS_INVALID_ARG);
14733 return (DRX_STS_OK);
14736 /*============================================================================*/
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
14746 * Dispatch handling to standard specific function.
14750 ctrl_get_cfg_agc_if(pdrx_demod_instance_t demod, p_drxj_cfg_agc_t agc_settings)
14752 /* check arguments */
14753 if (agc_settings == NULL) {
14754 return (DRX_STS_INVALID_ARG);
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:
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:
14774 return get_agc_if(demod, agc_settings);
14775 case DRX_STANDARD_UNKNOWN:
14777 return (DRX_STS_INVALID_ARG);
14780 return (DRX_STS_OK);
14783 /*============================================================================*/
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
14793 * Dispatch handling to standard specific function.
14797 ctrl_set_cfg_agc_rf(pdrx_demod_instance_t demod, p_drxj_cfg_agc_t agc_settings)
14799 /* check arguments */
14800 if (agc_settings == NULL) {
14801 return (DRX_STS_INVALID_ARG);
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:
14810 return (DRX_STS_INVALID_ARG);
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:
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:
14830 return set_agc_rf(demod, agc_settings, true);
14831 case DRX_STANDARD_UNKNOWN:
14833 return (DRX_STS_INVALID_ARG);
14836 return (DRX_STS_OK);
14839 /*============================================================================*/
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
14849 * Dispatch handling to standard specific function.
14853 ctrl_get_cfg_agc_rf(pdrx_demod_instance_t demod, p_drxj_cfg_agc_t agc_settings)
14855 /* check arguments */
14856 if (agc_settings == NULL) {
14857 return (DRX_STS_INVALID_ARG);
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:
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:
14877 return get_agc_rf(demod, agc_settings);
14878 case DRX_STANDARD_UNKNOWN:
14880 return (DRX_STS_INVALID_ARG);
14883 return (DRX_STS_OK);
14886 /*============================================================================*/
14889 * \fn int ctrl_get_cfg_agc_internal()
14890 * \brief Retrieve internal AGC value.
14891 * \param demod demod instance
14896 * Dispatch handling to standard specific function.
14900 ctrl_get_cfg_agc_internal(pdrx_demod_instance_t demod, u16 *agc_internal)
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;
14910 /* check arguments */
14911 if (agc_internal == NULL) {
14912 return (DRX_STS_INVALID_ARG);
14914 dev_addr = demod->my_i2c_dev_addr;
14915 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
14917 CHK_ERROR(ctrl_lock_status(demod, &lock_status));
14918 if (lock_status != DRXJ_DEMOD_LOCK && lock_status != DRX_LOCKED) {
14924 switch (ext_attr->standard) {
14925 case DRX_STANDARD_8VSB:
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:
14939 case DRX_CONSTELLATION_QAM64:
14943 return (DRX_STS_ERROR);
14948 return (DRX_STS_INVALID_ARG);
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);
14964 return (DRX_STS_OK);
14966 return (DRX_STS_ERROR);
14969 /*============================================================================*/
14972 * \fn int ctrl_set_cfg_pre_saw()
14973 * \brief Set Pre-saw reference.
14974 * \param demod demod instance
14979 * Dispatch handling to standard specific function.
14983 ctrl_set_cfg_pre_saw(pdrx_demod_instance_t demod, p_drxj_cfg_pre_saw_t pre_saw)
14985 struct i2c_device_addr *dev_addr = NULL;
14986 pdrxj_data_t ext_attr = NULL;
14988 dev_addr = demod->my_i2c_dev_addr;
14989 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
14991 /* check arguments */
14992 if ((pre_saw == NULL) || (pre_saw->reference > IQM_AF_PDREF__M)
14994 return (DRX_STS_INVALID_ARG);
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);
15006 /* Store pre-saw settings */
15007 switch (pre_saw->standard) {
15008 case DRX_STANDARD_8VSB:
15009 ext_attr->vsb_pre_saw_cfg = *pre_saw;
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;
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;
15030 return (DRX_STS_INVALID_ARG);
15033 return (DRX_STS_OK);
15035 return (DRX_STS_ERROR);
15038 /*============================================================================*/
15041 * \fn int ctrl_set_cfg_afe_gain()
15042 * \brief Set AFE Gain.
15043 * \param demod demod instance
15048 * Dispatch handling to standard specific function.
15052 ctrl_set_cfg_afe_gain(pdrx_demod_instance_t demod, p_drxj_cfg_afe_gain_t afe_gain)
15054 struct i2c_device_addr *dev_addr = NULL;
15055 pdrxj_data_t ext_attr = NULL;
15058 /* check arguments */
15059 if (afe_gain == NULL) {
15060 return (DRX_STS_INVALID_ARG);
15063 dev_addr = demod->my_i2c_dev_addr;
15064 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
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:
15076 return (DRX_STS_INVALID_ARG);
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 */
15082 if (afe_gain->gain >= 329)
15084 else if (afe_gain->gain <= 147)
15087 gain = (afe_gain->gain - 140 + 6) / 13;
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);
15093 /* Store AFE Gain settings */
15094 switch (afe_gain->standard) {
15095 case DRX_STANDARD_8VSB:
15096 ext_attr->vsb_pga_cfg = gain * 13 + 140;
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;
15106 return (DRX_STS_ERROR);
15109 return (DRX_STS_OK);
15111 return (DRX_STS_ERROR);
15114 /*============================================================================*/
15117 * \fn int ctrl_get_cfg_pre_saw()
15118 * \brief Get Pre-saw reference setting.
15119 * \param demod demod instance
15124 * Dispatch handling to standard specific function.
15128 ctrl_get_cfg_pre_saw(pdrx_demod_instance_t demod, p_drxj_cfg_pre_saw_t pre_saw)
15130 struct i2c_device_addr *dev_addr = NULL;
15131 pdrxj_data_t ext_attr = NULL;
15133 /* check arguments */
15134 if (pre_saw == NULL) {
15135 return (DRX_STS_INVALID_ARG);
15138 dev_addr = demod->my_i2c_dev_addr;
15139 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
15141 switch (pre_saw->standard) {
15142 case DRX_STANDARD_8VSB:
15143 *pre_saw = ext_attr->vsb_pre_saw_cfg;
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;
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;
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;
15168 return (DRX_STS_INVALID_ARG);
15171 return (DRX_STS_OK);
15174 /*============================================================================*/
15177 * \fn int ctrl_get_cfg_afe_gain()
15178 * \brief Get AFE Gain.
15179 * \param demod demod instance
15184 * Dispatch handling to standard specific function.
15188 ctrl_get_cfg_afe_gain(pdrx_demod_instance_t demod, p_drxj_cfg_afe_gain_t afe_gain)
15190 struct i2c_device_addr *dev_addr = NULL;
15191 pdrxj_data_t ext_attr = NULL;
15193 /* check arguments */
15194 if (afe_gain == NULL) {
15195 return (DRX_STS_INVALID_ARG);
15198 dev_addr = demod->my_i2c_dev_addr;
15199 ext_attr = (pdrxj_data_t) demod->my_ext_attr;
15201 switch (afe_gain->standard) {
15202 case DRX_STANDARD_8VSB:
15203 afe_gain->gain = ext_attr->vsb_pga_cfg;
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;
15213 return (DRX_STS_INVALID_ARG);
15216 return (DRX_STS_OK);
15219 /*============================================================================*/
15222 * \fn int ctrl_get_fec_meas_seq_count()
15223 * \brief Get FEC measurement sequnce number.
15224 * \param demod demod instance
15229 * Dispatch handling to standard specific function.
15233 ctrl_get_fec_meas_seq_count(pdrx_demod_instance_t demod, u16 *fec_meas_seq_count)
15235 /* check arguments */
15236 if (fec_meas_seq_count == NULL) {
15237 return (DRX_STS_INVALID_ARG);
15240 RR16(demod->my_i2c_dev_addr, SCU_RAM_FEC_MEAS_COUNT__A, fec_meas_seq_count);
15242 return (DRX_STS_OK);
15244 return (DRX_STS_ERROR);
15247 /*============================================================================*/
15250 * \fn int ctrl_get_accum_cr_rs_cw_err()
15251 * \brief Get accumulative corrected RS codeword number.
15252 * \param demod demod instance
15257 * Dispatch handling to standard specific function.
15261 ctrl_get_accum_cr_rs_cw_err(pdrx_demod_instance_t demod, u32 *accum_cr_rs_cw_err)
15263 if (accum_cr_rs_cw_err == NULL) {
15264 return (DRX_STS_INVALID_ARG);
15267 RR32(demod->my_i2c_dev_addr, SCU_RAM_FEC_ACCUM_CW_CORRECTED_LO__A,
15268 accum_cr_rs_cw_err);
15270 return (DRX_STS_OK);
15272 return (DRX_STS_ERROR);
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).
15283 static int ctrl_set_cfg(pdrx_demod_instance_t demod, pdrx_cfg_t config)
15285 if (config == NULL) {
15286 return (DRX_STS_INVALID_ARG);
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->
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->
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->
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->
15327 case DRXJ_CFG_ATV_OUTPUT:
15328 return ctrl_set_cfg_atv_output(demod,
15329 (p_drxj_cfg_atv_output_t) config->
15332 case DRXJ_CFG_MPEG_OUTPUT_MISC:
15333 return ctrl_set_cfg_mpeg_output_misc(demod,
15334 (p_drxj_cfg_mpeg_output_misc_t)
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->
15341 case DRX_CFG_I2S_OUTPUT:
15342 return aud_ctrl_set_cfg_output_i2s(demod,
15343 (pdrx_cfg_i2s_output_t) config->
15345 case DRX_CFG_AUD_AUTOSOUND:
15346 return aud_ctr_setl_cfg_auto_sound(demod, (pdrx_cfg_aud_auto_sound_t)
15348 case DRX_CFG_AUD_ASS_THRES:
15349 return aud_ctrl_set_cfg_ass_thres(demod, (pdrx_cfg_aud_ass_thres_t)
15351 case DRX_CFG_AUD_CARRIER:
15352 return aud_ctrl_set_cfg_carrier(demod,
15353 (pdrx_cfg_aud_carriers_t) config->
15355 case DRX_CFG_AUD_DEVIATION:
15356 return aud_ctrl_set_cfg_dev(demod,
15357 (pdrx_cfg_aud_deviation_t) config->
15359 case DRX_CFG_AUD_PRESCALE:
15360 return aud_ctrl_set_cfg_prescale(demod,
15361 (pdrx_cfg_aud_prescale_t) config->
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->
15373 return (DRX_STS_INVALID_ARG);
15376 return (DRX_STS_OK);
15378 return (DRX_STS_ERROR);
15381 /*============================================================================*/
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).
15391 static int ctrl_get_cfg(pdrx_demod_instance_t demod, pdrx_cfg_t config)
15393 if (config == NULL) {
15394 return (DRX_STS_INVALID_ARG);
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->
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->
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->
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->
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->
15454 case DRXJ_CFG_MPEG_OUTPUT_MISC:
15455 return ctrl_get_cfg_mpeg_output_misc(demod,
15456 (p_drxj_cfg_mpeg_output_misc_t)
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->
15466 case DRX_CFG_I2S_OUTPUT:
15467 return aud_ctrl_get_cfg_output_i2s(demod,
15468 (pdrx_cfg_i2s_output_t) config->
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->
15478 case DRX_CFG_AUD_ASS_THRES:
15479 return aud_ctrl_get_cfg_ass_thres(demod,
15480 (pdrx_cfg_aud_ass_thres_t) config->
15482 case DRX_CFG_AUD_CARRIER:
15483 return aud_ctrl_get_cfg_carrier(demod,
15484 (pdrx_cfg_aud_carriers_t) config->
15486 case DRX_CFG_AUD_DEVIATION:
15487 return aud_ctrl_get_cfg_dev(demod,
15488 (pdrx_cfg_aud_deviation_t) config->
15490 case DRX_CFG_AUD_PRESCALE:
15491 return aud_ctrl_get_cfg_prescale(demod,
15492 (pdrx_cfg_aud_prescale_t) config->
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->
15504 return (DRX_STS_INVALID_ARG);
15507 return (DRX_STS_OK);
15509 return (DRX_STS_ERROR);
15512 /*=============================================================================
15513 ===== EXPORTED FUNCTIONS ====================================================*/
15516 * \brief Open the demod instance, configure device, configure drxdriver
15517 * \return Status_t Return status.
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.
15524 int drxj_open(pdrx_demod_instance_t demod)
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;
15533 /* Check arguments */
15534 if (demod->my_ext_attr == NULL) {
15535 return (DRX_STS_INVALID_ARG);
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;
15542 CHK_ERROR(power_up_device(demod));
15543 common_attr->current_power_mode = DRX_POWER_UP;
15545 /* has to be in front of setIqmAf and setOrxNsuAox */
15546 CHK_ERROR(get_device_capabilities(demod));
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));
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);
15559 CHK_ERROR(set_iqm_af(demod, false));
15560 CHK_ERROR(set_orx_nsu_aox(demod, false));
15562 CHK_ERROR(init_hi(demod));
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));
15570 WR16(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_STOP);
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;
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));
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));
15593 (demod, DRX_CTRL_VERIFY_UCODE, &ucode_info));
15594 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
15596 common_attr->is_opened = false;
15599 /* Run SCU for a little while to initialize microcode version numbers */
15600 WR16(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
15602 /* Open tuner instance */
15603 if (demod->my_tuner != NULL) {
15604 demod->my_tuner->my_common_attr->myUser_data = (void *)demod;
15606 if (common_attr->tuner_port_nr == 1) {
15607 bool bridge_closed = true;
15608 CHK_ERROR(ctrl_i2c_bridge(demod, &bridge_closed));
15611 CHK_ERROR(drxbsp_tuner_open(demod->my_tuner));
15613 if (common_attr->tuner_port_nr == 1) {
15614 bool bridge_closed = false;
15615 CHK_ERROR(ctrl_i2c_bridge(demod, &bridge_closed));
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);
15623 /* Initialize scan timeout */
15624 common_attr->scan_demod_lock_timeout = DRXJ_SCAN_TIMEOUT;
15625 common_attr->scan_desired_lock = DRX_LOCKED;
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);
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);
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;
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;
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;
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;
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;
15698 ext_attr->standard = DRX_STANDARD_UNKNOWN;
15700 CHK_ERROR(smart_ant_init(demod));
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
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));
15725 /* refresh the audio data structure with default */
15726 ext_attr->aud_data = drxj_default_aud_data_g;
15728 return (DRX_STS_OK);
15730 common_attr->is_opened = false;
15731 return (DRX_STS_ERROR);
15734 /*============================================================================*/
15737 * \brief Close the demod instance, power down the device
15738 * \return Status_t Return status.
15741 int drxj_close(pdrx_demod_instance_t demod)
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;
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;
15753 CHK_ERROR(ctrl_power_mode(demod, &power_mode));
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));
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));
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));
15774 return (DRX_STS_ERROR);
15777 /*============================================================================*/
15780 * \brief DRXJ specific control function
15781 * \return Status_t Return status.
15784 drxj_ctrl(pdrx_demod_instance_t demod, u32 ctrl, void *ctrl_data)
15787 /*======================================================================*/
15788 case DRX_CTRL_SET_CHANNEL:
15790 return ctrl_set_channel(demod, (pdrx_channel_t) ctrl_data);
15793 /*======================================================================*/
15794 case DRX_CTRL_GET_CHANNEL:
15796 return ctrl_get_channel(demod, (pdrx_channel_t) ctrl_data);
15799 /*======================================================================*/
15800 case DRX_CTRL_SIG_QUALITY:
15802 return ctrl_sig_quality(demod,
15803 (pdrx_sig_quality_t) ctrl_data);
15806 /*======================================================================*/
15807 case DRX_CTRL_SIG_STRENGTH:
15809 return ctrl_sig_strength(demod, (u16 *) ctrl_data);
15812 /*======================================================================*/
15813 case DRX_CTRL_CONSTEL:
15815 return ctrl_constel(demod, (pdrx_complex_t) ctrl_data);
15818 /*======================================================================*/
15819 case DRX_CTRL_SET_CFG:
15821 return ctrl_set_cfg(demod, (pdrx_cfg_t) ctrl_data);
15824 /*======================================================================*/
15825 case DRX_CTRL_GET_CFG:
15827 return ctrl_get_cfg(demod, (pdrx_cfg_t) ctrl_data);
15830 /*======================================================================*/
15831 case DRX_CTRL_I2C_BRIDGE:
15833 return ctrl_i2c_bridge(demod, (bool *) ctrl_data);
15836 /*======================================================================*/
15837 case DRX_CTRL_LOCK_STATUS:
15839 return ctrl_lock_status(demod,
15840 (pdrx_lock_status_t) ctrl_data);
15843 /*======================================================================*/
15844 case DRX_CTRL_SET_STANDARD:
15846 return ctrl_set_standard(demod,
15847 (enum drx_standard *) ctrl_data);
15850 /*======================================================================*/
15851 case DRX_CTRL_GET_STANDARD:
15853 return ctrl_get_standard(demod,
15854 (enum drx_standard *) ctrl_data);
15857 /*======================================================================*/
15858 case DRX_CTRL_POWER_MODE:
15860 return ctrl_power_mode(demod, (pdrx_power_mode_t) ctrl_data);
15863 /*======================================================================*/
15864 case DRX_CTRL_VERSION:
15866 return ctrl_version(demod,
15867 (p_drx_version_list_t *) ctrl_data);
15870 /*======================================================================*/
15871 case DRX_CTRL_PROBE_DEVICE:
15873 return ctrl_probe_device(demod);
15876 /*======================================================================*/
15877 case DRX_CTRL_SET_OOB:
15879 return ctrl_set_oob(demod, (p_drxoob_t) ctrl_data);
15882 /*======================================================================*/
15883 case DRX_CTRL_GET_OOB:
15885 return ctrl_get_oob(demod, (pdrxoob_status_t) ctrl_data);
15888 /*======================================================================*/
15889 case DRX_CTRL_SET_UIO_CFG:
15891 return ctrl_set_uio_cfg(demod, (pdrxuio_cfg_t) ctrl_data);
15894 /*======================================================================*/
15895 case DRX_CTRL_GET_UIO_CFG:
15897 return CtrlGetuio_cfg(demod, (pdrxuio_cfg_t) ctrl_data);
15900 /*======================================================================*/
15901 case DRX_CTRL_UIO_READ:
15903 return ctrl_uio_read(demod, (pdrxuio_data_t) ctrl_data);
15906 /*======================================================================*/
15907 case DRX_CTRL_UIO_WRITE:
15909 return ctrl_uio_write(demod, (pdrxuio_data_t) ctrl_data);
15912 /*======================================================================*/
15913 case DRX_CTRL_AUD_SET_STANDARD:
15915 return aud_ctrl_set_standard(demod,
15916 (pdrx_aud_standard_t) ctrl_data);
15919 /*======================================================================*/
15920 case DRX_CTRL_AUD_GET_STANDARD:
15922 return aud_ctrl_get_standard(demod,
15923 (pdrx_aud_standard_t) ctrl_data);
15926 /*======================================================================*/
15927 case DRX_CTRL_AUD_GET_STATUS:
15929 return aud_ctrl_get_status(demod,
15930 (pdrx_aud_status_t) ctrl_data);
15933 /*======================================================================*/
15934 case DRX_CTRL_AUD_BEEP:
15936 return aud_ctrl_beep(demod, (pdrx_aud_beep_t) ctrl_data);
15940 /*======================================================================*/
15941 case DRX_CTRL_I2C_READWRITE:
15943 return ctrl_i2c_write_read(demod,
15944 (pdrxi2c_data_t) ctrl_data);
15947 #ifdef DRXJ_SPLIT_UCODE_UPLOAD
15948 case DRX_CTRL_LOAD_UCODE:
15950 return ctrl_u_codeUpload(demod,
15951 (p_drxu_code_info_t) ctrl_data,
15952 UCODE_UPLOAD, false);
15955 case DRX_CTRL_VERIFY_UCODE:
15957 return ctrl_u_codeUpload(demod,
15958 (p_drxu_code_info_t) ctrl_data,
15959 UCODE_VERIFY, false);
15962 #endif /* DRXJ_SPLIT_UCODE_UPLOAD */
15963 case DRX_CTRL_VALIDATE_UCODE:
15965 return ctrl_validate_u_code(demod);
15969 return (DRX_STS_FUNC_NOT_AVAILABLE);
15971 return (DRX_STS_OK);