[media] drx-j: avoid calling power_down_foo twice
[linux-2.6/btrfs-unstable.git] / drivers / media / dvb-frontends / drx39xyj / drxj.c
blob7f17cd14839ba5413abdcee9666ac5a77b0a62c7
1 /*
2 Copyright (c), 2004-2005,2007-2010 Trident Microsystems, Inc.
3 All rights reserved.
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
16 permission.
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.
30 DRXJ specific implementation of DRX driver
31 authors: Dragan Savic, Milos Nikolic, Mihajlo Katona, Tao Ding, Paul Janssen
33 The Linux DVB Driver for Micronas DRX39xx family (drx3933j) was
34 written by Devin Heitmueller <devin.heitmueller@kernellabs.com>
36 This program is free software; you can redistribute it and/or modify
37 it under the terms of the GNU General Public License as published by
38 the Free Software Foundation; either version 2 of the License, or
39 (at your option) any later version.
41 This program is distributed in the hope that it will be useful,
42 but WITHOUT ANY WARRANTY; without even the implied warranty of
43 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45 GNU General Public License for more details.
47 You should have received a copy of the GNU General Public License
48 along with this program; if not, write to the Free Software
49 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
52 /*-----------------------------------------------------------------------------
53 INCLUDE FILES
54 ----------------------------------------------------------------------------*/
56 #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
58 #include <linux/module.h>
59 #include <linux/init.h>
60 #include <linux/string.h>
61 #include <linux/slab.h>
63 #include "dvb_frontend.h"
64 #include "drx39xxj.h"
66 #include "drxj.h"
67 #include "drxj_map.h"
69 /*============================================================================*/
70 /*=== DEFINES ================================================================*/
71 /*============================================================================*/
73 #define DRX39XX_MAIN_FIRMWARE "dvb-fe-drxj-mc-1.0.8.fw"
75 /**
76 * \brief Maximum u32 value.
78 #ifndef MAX_U32
79 #define MAX_U32 ((u32) (0xFFFFFFFFL))
80 #endif
82 /* Customer configurable hardware settings, etc */
83 #ifndef MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH
84 #define MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH 0x02
85 #endif
87 #ifndef MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH
88 #define MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH 0x02
89 #endif
91 #ifndef MPEG_OUTPUT_CLK_DRIVE_STRENGTH
92 #define MPEG_OUTPUT_CLK_DRIVE_STRENGTH 0x06
93 #endif
95 #ifndef OOB_CRX_DRIVE_STRENGTH
96 #define OOB_CRX_DRIVE_STRENGTH 0x02
97 #endif
99 #ifndef OOB_DRX_DRIVE_STRENGTH
100 #define OOB_DRX_DRIVE_STRENGTH 0x02
101 #endif
102 /**** START DJCOMBO patches to DRXJ registermap constants *********************/
103 /**** registermap 200706071303 from drxj **************************************/
104 #define ATV_TOP_CR_AMP_TH_FM 0x0
105 #define ATV_TOP_CR_AMP_TH_L 0xA
106 #define ATV_TOP_CR_AMP_TH_LP 0xA
107 #define ATV_TOP_CR_AMP_TH_BG 0x8
108 #define ATV_TOP_CR_AMP_TH_DK 0x8
109 #define ATV_TOP_CR_AMP_TH_I 0x8
110 #define ATV_TOP_CR_CONT_CR_D_MN 0x18
111 #define ATV_TOP_CR_CONT_CR_D_FM 0x0
112 #define ATV_TOP_CR_CONT_CR_D_L 0x20
113 #define ATV_TOP_CR_CONT_CR_D_LP 0x20
114 #define ATV_TOP_CR_CONT_CR_D_BG 0x18
115 #define ATV_TOP_CR_CONT_CR_D_DK 0x18
116 #define ATV_TOP_CR_CONT_CR_D_I 0x18
117 #define ATV_TOP_CR_CONT_CR_I_MN 0x80
118 #define ATV_TOP_CR_CONT_CR_I_FM 0x0
119 #define ATV_TOP_CR_CONT_CR_I_L 0x80
120 #define ATV_TOP_CR_CONT_CR_I_LP 0x80
121 #define ATV_TOP_CR_CONT_CR_I_BG 0x80
122 #define ATV_TOP_CR_CONT_CR_I_DK 0x80
123 #define ATV_TOP_CR_CONT_CR_I_I 0x80
124 #define ATV_TOP_CR_CONT_CR_P_MN 0x4
125 #define ATV_TOP_CR_CONT_CR_P_FM 0x0
126 #define ATV_TOP_CR_CONT_CR_P_L 0x4
127 #define ATV_TOP_CR_CONT_CR_P_LP 0x4
128 #define ATV_TOP_CR_CONT_CR_P_BG 0x4
129 #define ATV_TOP_CR_CONT_CR_P_DK 0x4
130 #define ATV_TOP_CR_CONT_CR_P_I 0x4
131 #define ATV_TOP_CR_OVM_TH_MN 0xA0
132 #define ATV_TOP_CR_OVM_TH_FM 0x0
133 #define ATV_TOP_CR_OVM_TH_L 0xA0
134 #define ATV_TOP_CR_OVM_TH_LP 0xA0
135 #define ATV_TOP_CR_OVM_TH_BG 0xA0
136 #define ATV_TOP_CR_OVM_TH_DK 0xA0
137 #define ATV_TOP_CR_OVM_TH_I 0xA0
138 #define ATV_TOP_EQU0_EQU_C0_FM 0x0
139 #define ATV_TOP_EQU0_EQU_C0_L 0x3
140 #define ATV_TOP_EQU0_EQU_C0_LP 0x3
141 #define ATV_TOP_EQU0_EQU_C0_BG 0x7
142 #define ATV_TOP_EQU0_EQU_C0_DK 0x0
143 #define ATV_TOP_EQU0_EQU_C0_I 0x3
144 #define ATV_TOP_EQU1_EQU_C1_FM 0x0
145 #define ATV_TOP_EQU1_EQU_C1_L 0x1F6
146 #define ATV_TOP_EQU1_EQU_C1_LP 0x1F6
147 #define ATV_TOP_EQU1_EQU_C1_BG 0x197
148 #define ATV_TOP_EQU1_EQU_C1_DK 0x198
149 #define ATV_TOP_EQU1_EQU_C1_I 0x1F6
150 #define ATV_TOP_EQU2_EQU_C2_FM 0x0
151 #define ATV_TOP_EQU2_EQU_C2_L 0x28
152 #define ATV_TOP_EQU2_EQU_C2_LP 0x28
153 #define ATV_TOP_EQU2_EQU_C2_BG 0xC5
154 #define ATV_TOP_EQU2_EQU_C2_DK 0xB0
155 #define ATV_TOP_EQU2_EQU_C2_I 0x28
156 #define ATV_TOP_EQU3_EQU_C3_FM 0x0
157 #define ATV_TOP_EQU3_EQU_C3_L 0x192
158 #define ATV_TOP_EQU3_EQU_C3_LP 0x192
159 #define ATV_TOP_EQU3_EQU_C3_BG 0x12E
160 #define ATV_TOP_EQU3_EQU_C3_DK 0x18E
161 #define ATV_TOP_EQU3_EQU_C3_I 0x192
162 #define ATV_TOP_STD_MODE_MN 0x0
163 #define ATV_TOP_STD_MODE_FM 0x1
164 #define ATV_TOP_STD_MODE_L 0x0
165 #define ATV_TOP_STD_MODE_LP 0x0
166 #define ATV_TOP_STD_MODE_BG 0x0
167 #define ATV_TOP_STD_MODE_DK 0x0
168 #define ATV_TOP_STD_MODE_I 0x0
169 #define ATV_TOP_STD_VID_POL_MN 0x0
170 #define ATV_TOP_STD_VID_POL_FM 0x0
171 #define ATV_TOP_STD_VID_POL_L 0x2
172 #define ATV_TOP_STD_VID_POL_LP 0x2
173 #define ATV_TOP_STD_VID_POL_BG 0x0
174 #define ATV_TOP_STD_VID_POL_DK 0x0
175 #define ATV_TOP_STD_VID_POL_I 0x0
176 #define ATV_TOP_VID_AMP_MN 0x380
177 #define ATV_TOP_VID_AMP_FM 0x0
178 #define ATV_TOP_VID_AMP_L 0xF50
179 #define ATV_TOP_VID_AMP_LP 0xF50
180 #define ATV_TOP_VID_AMP_BG 0x380
181 #define ATV_TOP_VID_AMP_DK 0x394
182 #define ATV_TOP_VID_AMP_I 0x3D8
183 #define IQM_CF_OUT_ENA_OFDM__M 0x4
184 #define IQM_FS_ADJ_SEL_B_QAM 0x1
185 #define IQM_FS_ADJ_SEL_B_OFF 0x0
186 #define IQM_FS_ADJ_SEL_B_VSB 0x2
187 #define IQM_RC_ADJ_SEL_B_OFF 0x0
188 #define IQM_RC_ADJ_SEL_B_QAM 0x1
189 #define IQM_RC_ADJ_SEL_B_VSB 0x2
190 /**** END DJCOMBO patches to DRXJ registermap *********************************/
192 #include "drx_driver_version.h"
194 /* #define DRX_DEBUG */
195 #ifdef DRX_DEBUG
196 #include <stdio.h>
197 #endif
199 /*-----------------------------------------------------------------------------
200 ENUMS
201 ----------------------------------------------------------------------------*/
203 /*-----------------------------------------------------------------------------
204 DEFINES
205 ----------------------------------------------------------------------------*/
206 #ifndef DRXJ_WAKE_UP_KEY
207 #define DRXJ_WAKE_UP_KEY (demod->my_i2c_dev_addr->i2c_addr)
208 #endif
211 * \def DRXJ_DEF_I2C_ADDR
212 * \brief Default I2C addres of a demodulator instance.
214 #define DRXJ_DEF_I2C_ADDR (0x52)
217 * \def DRXJ_DEF_DEMOD_DEV_ID
218 * \brief Default device identifier of a demodultor instance.
220 #define DRXJ_DEF_DEMOD_DEV_ID (1)
223 * \def DRXJ_SCAN_TIMEOUT
224 * \brief Timeout value for waiting on demod lock during channel scan (millisec).
226 #define DRXJ_SCAN_TIMEOUT 1000
229 * \def DRXJ_DAP
230 * \brief Name of structure containing all data access protocol functions.
232 #define DRXJ_DAP drx_dap_drxj_funct_g
235 * \def HI_I2C_DELAY
236 * \brief HI timing delay for I2C timing (in nano seconds)
238 * Used to compute HI_CFG_DIV
240 #define HI_I2C_DELAY 42
243 * \def HI_I2C_BRIDGE_DELAY
244 * \brief HI timing delay for I2C timing (in nano seconds)
246 * Used to compute HI_CFG_BDL
248 #define HI_I2C_BRIDGE_DELAY 750
251 * \brief Time Window for MER and SER Measurement in Units of Segment duration.
253 #define VSB_TOP_MEASUREMENT_PERIOD 64
254 #define SYMBOLS_PER_SEGMENT 832
257 * \brief bit rate and segment rate constants used for SER and BER.
259 /* values taken from the QAM microcode */
260 #define DRXJ_QAM_SL_SIG_POWER_QAM_UNKNOWN 0
261 #define DRXJ_QAM_SL_SIG_POWER_QPSK 32768
262 #define DRXJ_QAM_SL_SIG_POWER_QAM8 24576
263 #define DRXJ_QAM_SL_SIG_POWER_QAM16 40960
264 #define DRXJ_QAM_SL_SIG_POWER_QAM32 20480
265 #define DRXJ_QAM_SL_SIG_POWER_QAM64 43008
266 #define DRXJ_QAM_SL_SIG_POWER_QAM128 20992
267 #define DRXJ_QAM_SL_SIG_POWER_QAM256 43520
269 * \brief Min supported symbolrates.
271 #ifndef DRXJ_QAM_SYMBOLRATE_MIN
272 #define DRXJ_QAM_SYMBOLRATE_MIN (520000)
273 #endif
276 * \brief Max supported symbolrates.
278 #ifndef DRXJ_QAM_SYMBOLRATE_MAX
279 #define DRXJ_QAM_SYMBOLRATE_MAX (7233000)
280 #endif
283 * \def DRXJ_QAM_MAX_WAITTIME
284 * \brief Maximal wait time for QAM auto constellation in ms
286 #ifndef DRXJ_QAM_MAX_WAITTIME
287 #define DRXJ_QAM_MAX_WAITTIME 900
288 #endif
290 #ifndef DRXJ_QAM_FEC_LOCK_WAITTIME
291 #define DRXJ_QAM_FEC_LOCK_WAITTIME 150
292 #endif
294 #ifndef DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME
295 #define DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME 200
296 #endif
299 * \def SCU status and results
300 * \brief SCU
302 #define DRX_SCU_READY 0
303 #define DRXJ_MAX_WAITTIME 100 /* ms */
304 #define FEC_RS_MEASUREMENT_PERIOD 12894 /* 1 sec */
305 #define FEC_RS_MEASUREMENT_PRESCALE 1 /* n sec */
308 * \def DRX_AUD_MAX_DEVIATION
309 * \brief Needed for calculation of prescale feature in AUD
311 #ifndef DRXJ_AUD_MAX_FM_DEVIATION
312 #define DRXJ_AUD_MAX_FM_DEVIATION 100 /* kHz */
313 #endif
316 * \brief Needed for calculation of NICAM prescale feature in AUD
318 #ifndef DRXJ_AUD_MAX_NICAM_PRESCALE
319 #define DRXJ_AUD_MAX_NICAM_PRESCALE (9) /* dB */
320 #endif
323 * \brief Needed for calculation of NICAM prescale feature in AUD
325 #ifndef DRXJ_AUD_MAX_WAITTIME
326 #define DRXJ_AUD_MAX_WAITTIME 250 /* ms */
327 #endif
329 /* ATV config changed flags */
330 #define DRXJ_ATV_CHANGED_COEF (0x00000001UL)
331 #define DRXJ_ATV_CHANGED_PEAK_FLT (0x00000008UL)
332 #define DRXJ_ATV_CHANGED_NOISE_FLT (0x00000010UL)
333 #define DRXJ_ATV_CHANGED_OUTPUT (0x00000020UL)
334 #define DRXJ_ATV_CHANGED_SIF_ATT (0x00000040UL)
336 /* UIO define */
337 #define DRX_UIO_MODE_FIRMWARE_SMA DRX_UIO_MODE_FIRMWARE0
338 #define DRX_UIO_MODE_FIRMWARE_SAW DRX_UIO_MODE_FIRMWARE1
341 * MICROCODE RELATED DEFINES
344 /* Magic word for checking correct Endianess of microcode data */
345 #define DRX_UCODE_MAGIC_WORD ((((u16)'H')<<8)+((u16)'L'))
347 /* CRC flag in ucode header, flags field. */
348 #define DRX_UCODE_CRC_FLAG (0x0001)
351 * Maximum size of buffer used to verify the microcode.
352 * Must be an even number
354 #define DRX_UCODE_MAX_BUF_SIZE (DRXDAP_MAX_RCHUNKSIZE)
356 #if DRX_UCODE_MAX_BUF_SIZE & 1
357 #error DRX_UCODE_MAX_BUF_SIZE must be an even number
358 #endif
361 * Power mode macros
364 #define DRX_ISPOWERDOWNMODE(mode) ((mode == DRX_POWER_MODE_9) || \
365 (mode == DRX_POWER_MODE_10) || \
366 (mode == DRX_POWER_MODE_11) || \
367 (mode == DRX_POWER_MODE_12) || \
368 (mode == DRX_POWER_MODE_13) || \
369 (mode == DRX_POWER_MODE_14) || \
370 (mode == DRX_POWER_MODE_15) || \
371 (mode == DRX_POWER_MODE_16) || \
372 (mode == DRX_POWER_DOWN))
374 /* Pin safe mode macro */
375 #define DRXJ_PIN_SAFE_MODE 0x0000
376 /*============================================================================*/
377 /*=== GLOBAL VARIABLEs =======================================================*/
378 /*============================================================================*/
383 * \brief Temporary register definitions.
384 * (register definitions that are not yet available in register master)
387 /******************************************************************************/
388 /* Audio block 0x103 is write only. To avoid shadowing in driver accessing */
389 /* RAM adresses directly. This must be READ ONLY to avoid problems. */
390 /* Writing to the interface adresses is more than only writing the RAM */
391 /* locations */
392 /******************************************************************************/
394 * \brief RAM location of MODUS registers
396 #define AUD_DEM_RAM_MODUS_HI__A 0x10204A3
397 #define AUD_DEM_RAM_MODUS_HI__M 0xF000
399 #define AUD_DEM_RAM_MODUS_LO__A 0x10204A4
400 #define AUD_DEM_RAM_MODUS_LO__M 0x0FFF
403 * \brief RAM location of I2S config registers
405 #define AUD_DEM_RAM_I2S_CONFIG1__A 0x10204B1
406 #define AUD_DEM_RAM_I2S_CONFIG2__A 0x10204B2
409 * \brief RAM location of DCO config registers
411 #define AUD_DEM_RAM_DCO_B_HI__A 0x1020461
412 #define AUD_DEM_RAM_DCO_B_LO__A 0x1020462
413 #define AUD_DEM_RAM_DCO_A_HI__A 0x1020463
414 #define AUD_DEM_RAM_DCO_A_LO__A 0x1020464
417 * \brief RAM location of Threshold registers
419 #define AUD_DEM_RAM_NICAM_THRSHLD__A 0x102045A
420 #define AUD_DEM_RAM_A2_THRSHLD__A 0x10204BB
421 #define AUD_DEM_RAM_BTSC_THRSHLD__A 0x10204A6
424 * \brief RAM location of Carrier Threshold registers
426 #define AUD_DEM_RAM_CM_A_THRSHLD__A 0x10204AF
427 #define AUD_DEM_RAM_CM_B_THRSHLD__A 0x10204B0
430 * \brief FM Matrix register fix
432 #ifdef AUD_DEM_WR_FM_MATRIX__A
433 #undef AUD_DEM_WR_FM_MATRIX__A
434 #endif
435 #define AUD_DEM_WR_FM_MATRIX__A 0x105006F
437 /*============================================================================*/
439 * \brief Defines required for audio
441 #define AUD_VOLUME_ZERO_DB 115
442 #define AUD_VOLUME_DB_MIN -60
443 #define AUD_VOLUME_DB_MAX 12
444 #define AUD_CARRIER_STRENGTH_QP_0DB 0x4000
445 #define AUD_CARRIER_STRENGTH_QP_0DB_LOG10T100 421
446 #define AUD_MAX_AVC_REF_LEVEL 15
447 #define AUD_I2S_FREQUENCY_MAX 48000UL
448 #define AUD_I2S_FREQUENCY_MIN 12000UL
449 #define AUD_RDS_ARRAY_SIZE 18
452 * \brief Needed for calculation of prescale feature in AUD
454 #ifndef DRX_AUD_MAX_FM_DEVIATION
455 #define DRX_AUD_MAX_FM_DEVIATION (100) /* kHz */
456 #endif
459 * \brief Needed for calculation of NICAM prescale feature in AUD
461 #ifndef DRX_AUD_MAX_NICAM_PRESCALE
462 #define DRX_AUD_MAX_NICAM_PRESCALE (9) /* dB */
463 #endif
465 /*============================================================================*/
466 /* Values for I2S Master/Slave pin configurations */
467 #define SIO_PDR_I2S_CL_CFG_MODE__MASTER 0x0004
468 #define SIO_PDR_I2S_CL_CFG_DRIVE__MASTER 0x0008
469 #define SIO_PDR_I2S_CL_CFG_MODE__SLAVE 0x0004
470 #define SIO_PDR_I2S_CL_CFG_DRIVE__SLAVE 0x0000
472 #define SIO_PDR_I2S_DA_CFG_MODE__MASTER 0x0003
473 #define SIO_PDR_I2S_DA_CFG_DRIVE__MASTER 0x0008
474 #define SIO_PDR_I2S_DA_CFG_MODE__SLAVE 0x0003
475 #define SIO_PDR_I2S_DA_CFG_DRIVE__SLAVE 0x0008
477 #define SIO_PDR_I2S_WS_CFG_MODE__MASTER 0x0004
478 #define SIO_PDR_I2S_WS_CFG_DRIVE__MASTER 0x0008
479 #define SIO_PDR_I2S_WS_CFG_MODE__SLAVE 0x0004
480 #define SIO_PDR_I2S_WS_CFG_DRIVE__SLAVE 0x0000
482 /*============================================================================*/
483 /*=== REGISTER ACCESS MACROS =================================================*/
484 /*============================================================================*/
487 * This macro is used to create byte arrays for block writes.
488 * Block writes speed up I2C traffic between host and demod.
489 * The macro takes care of the required byte order in a 16 bits word.
490 * x -> lowbyte(x), highbyte(x)
492 #define DRXJ_16TO8(x) ((u8) (((u16)x) & 0xFF)), \
493 ((u8)((((u16)x)>>8)&0xFF))
495 * This macro is used to convert byte array to 16 bit register value for block read.
496 * Block read speed up I2C traffic between host and demod.
497 * The macro takes care of the required byte order in a 16 bits word.
499 #define DRXJ_8TO16(x) ((u16) (x[0] | (x[1] << 8)))
501 /*============================================================================*/
502 /*=== MISC DEFINES ===========================================================*/
503 /*============================================================================*/
505 /*============================================================================*/
506 /*=== HI COMMAND RELATED DEFINES =============================================*/
507 /*============================================================================*/
510 * \brief General maximum number of retries for ucode command interfaces
512 #define DRXJ_MAX_RETRIES (100)
514 /*============================================================================*/
515 /*=== STANDARD RELATED MACROS ================================================*/
516 /*============================================================================*/
518 #define DRXJ_ISATVSTD(std) ((std == DRX_STANDARD_PAL_SECAM_BG) || \
519 (std == DRX_STANDARD_PAL_SECAM_DK) || \
520 (std == DRX_STANDARD_PAL_SECAM_I) || \
521 (std == DRX_STANDARD_PAL_SECAM_L) || \
522 (std == DRX_STANDARD_PAL_SECAM_LP) || \
523 (std == DRX_STANDARD_NTSC) || \
524 (std == DRX_STANDARD_FM))
526 #define DRXJ_ISQAMSTD(std) ((std == DRX_STANDARD_ITU_A) || \
527 (std == DRX_STANDARD_ITU_B) || \
528 (std == DRX_STANDARD_ITU_C) || \
529 (std == DRX_STANDARD_ITU_D))
531 /*-----------------------------------------------------------------------------
532 GLOBAL VARIABLES
533 ----------------------------------------------------------------------------*/
535 * DRXJ DAP structures
538 static int drxj_dap_read_block(struct i2c_device_addr *dev_addr,
539 u32 addr,
540 u16 datasize,
541 u8 *data, u32 flags);
543 static int drxj_dap_read_modify_write_reg8(struct i2c_device_addr *dev_addr,
544 u32 waddr,
545 u32 raddr,
546 u8 wdata, u8 *rdata);
548 static int drxj_dap_read_modify_write_reg16(struct i2c_device_addr *dev_addr,
549 u32 waddr,
550 u32 raddr,
551 u16 wdata, u16 *rdata);
553 static int drxj_dap_read_modify_write_reg32(struct i2c_device_addr *dev_addr,
554 u32 waddr,
555 u32 raddr,
556 u32 wdata, u32 *rdata);
558 static int drxj_dap_read_reg8(struct i2c_device_addr *dev_addr,
559 u32 addr,
560 u8 *data, u32 flags);
562 static int drxj_dap_read_reg16(struct i2c_device_addr *dev_addr,
563 u32 addr,
564 u16 *data, u32 flags);
566 static int drxj_dap_read_reg32(struct i2c_device_addr *dev_addr,
567 u32 addr,
568 u32 *data, u32 flags);
570 static int drxj_dap_write_block(struct i2c_device_addr *dev_addr,
571 u32 addr,
572 u16 datasize,
573 u8 *data, u32 flags);
575 static int drxj_dap_write_reg8(struct i2c_device_addr *dev_addr,
576 u32 addr,
577 u8 data, u32 flags);
579 static int drxj_dap_write_reg16(struct i2c_device_addr *dev_addr,
580 u32 addr,
581 u16 data, u32 flags);
583 static int drxj_dap_write_reg32(struct i2c_device_addr *dev_addr,
584 u32 addr,
585 u32 data, u32 flags);
587 /* The version structure of this protocol implementation */
588 char drx_dap_drxj_module_name[] = "DRXJ Data Access Protocol";
589 char drx_dap_drxj_version_text[] = "0.0.0";
591 struct drx_version drx_dap_drxj_version = {
592 DRX_MODULE_DAP, /**< type identifier of the module */
593 drx_dap_drxj_module_name, /**< name or description of module */
595 0, /**< major version number */
596 0, /**< minor version number */
597 0, /**< patch version number */
598 drx_dap_drxj_version_text /**< version as text string */
601 /* The structure containing the protocol interface */
602 struct drx_access_func drx_dap_drxj_funct_g = {
603 &drx_dap_drxj_version,
604 drxj_dap_write_block, /* Supported */
605 drxj_dap_read_block, /* Supported */
606 drxj_dap_write_reg8, /* Not supported */
607 drxj_dap_read_reg8, /* Not supported */
608 drxj_dap_read_modify_write_reg8, /* Not supported */
609 drxj_dap_write_reg16, /* Supported */
610 drxj_dap_read_reg16, /* Supported */
611 drxj_dap_read_modify_write_reg16, /* Supported */
612 drxj_dap_write_reg32, /* Supported */
613 drxj_dap_read_reg32, /* Supported */
614 drxj_dap_read_modify_write_reg32, /* Not supported */
617 struct drxj_data drxj_data_g = {
618 false, /* has_lna : true if LNA (aka PGA) present */
619 false, /* has_oob : true if OOB supported */
620 false, /* has_ntsc: true if NTSC supported */
621 false, /* has_btsc: true if BTSC supported */
622 false, /* has_smatx: true if SMA_TX pin is available */
623 false, /* has_smarx: true if SMA_RX pin is available */
624 false, /* has_gpio : true if GPIO pin is available */
625 false, /* has_irqn : true if IRQN pin is available */
626 0, /* mfx A1/A2/A... */
628 /* tuner settings */
629 false, /* tuner mirrors RF signal */
630 /* standard/channel settings */
631 DRX_STANDARD_UNKNOWN, /* current standard */
632 DRX_CONSTELLATION_AUTO, /* constellation */
633 0, /* frequency in KHz */
634 DRX_BANDWIDTH_UNKNOWN, /* curr_bandwidth */
635 DRX_MIRROR_NO, /* mirror */
637 /* signal quality information: */
638 /* default values taken from the QAM Programming guide */
639 /* fec_bits_desired should not be less than 4000000 */
640 4000000, /* fec_bits_desired */
641 5, /* fec_vd_plen */
642 4, /* qam_vd_prescale */
643 0xFFFF, /* qamVDPeriod */
644 204 * 8, /* fec_rs_plen annex A */
645 1, /* fec_rs_prescale */
646 FEC_RS_MEASUREMENT_PERIOD, /* fec_rs_period */
647 true, /* reset_pkt_err_acc */
648 0, /* pkt_err_acc_start */
650 /* HI configuration */
651 0, /* hi_cfg_timing_div */
652 0, /* hi_cfg_bridge_delay */
653 0, /* hi_cfg_wake_up_key */
654 0, /* hi_cfg_ctrl */
655 0, /* HICfgTimeout */
656 /* UIO configuartion */
657 DRX_UIO_MODE_DISABLE, /* uio_sma_rx_mode */
658 DRX_UIO_MODE_DISABLE, /* uio_sma_tx_mode */
659 DRX_UIO_MODE_DISABLE, /* uioASELMode */
660 DRX_UIO_MODE_DISABLE, /* uio_irqn_mode */
661 /* FS setting */
662 0UL, /* iqm_fs_rate_ofs */
663 false, /* pos_image */
664 /* RC setting */
665 0UL, /* iqm_rc_rate_ofs */
666 /* AUD information */
667 /* false, * flagSetAUDdone */
668 /* false, * detectedRDS */
669 /* true, * flagASDRequest */
670 /* false, * flagHDevClear */
671 /* false, * flagHDevSet */
672 /* (u16) 0xFFF, * rdsLastCount */
674 /* ATV configuartion */
675 0UL, /* flags cfg changes */
676 /* shadow of ATV_TOP_EQU0__A */
677 {-5,
678 ATV_TOP_EQU0_EQU_C0_FM,
679 ATV_TOP_EQU0_EQU_C0_L,
680 ATV_TOP_EQU0_EQU_C0_LP,
681 ATV_TOP_EQU0_EQU_C0_BG,
682 ATV_TOP_EQU0_EQU_C0_DK,
683 ATV_TOP_EQU0_EQU_C0_I},
684 /* shadow of ATV_TOP_EQU1__A */
685 {-50,
686 ATV_TOP_EQU1_EQU_C1_FM,
687 ATV_TOP_EQU1_EQU_C1_L,
688 ATV_TOP_EQU1_EQU_C1_LP,
689 ATV_TOP_EQU1_EQU_C1_BG,
690 ATV_TOP_EQU1_EQU_C1_DK,
691 ATV_TOP_EQU1_EQU_C1_I},
692 /* shadow of ATV_TOP_EQU2__A */
693 {210,
694 ATV_TOP_EQU2_EQU_C2_FM,
695 ATV_TOP_EQU2_EQU_C2_L,
696 ATV_TOP_EQU2_EQU_C2_LP,
697 ATV_TOP_EQU2_EQU_C2_BG,
698 ATV_TOP_EQU2_EQU_C2_DK,
699 ATV_TOP_EQU2_EQU_C2_I},
700 /* shadow of ATV_TOP_EQU3__A */
701 {-160,
702 ATV_TOP_EQU3_EQU_C3_FM,
703 ATV_TOP_EQU3_EQU_C3_L,
704 ATV_TOP_EQU3_EQU_C3_LP,
705 ATV_TOP_EQU3_EQU_C3_BG,
706 ATV_TOP_EQU3_EQU_C3_DK,
707 ATV_TOP_EQU3_EQU_C3_I},
708 false, /* flag: true=bypass */
709 ATV_TOP_VID_PEAK__PRE, /* shadow of ATV_TOP_VID_PEAK__A */
710 ATV_TOP_NOISE_TH__PRE, /* shadow of ATV_TOP_NOISE_TH__A */
711 true, /* flag CVBS ouput enable */
712 false, /* flag SIF ouput enable */
713 DRXJ_SIF_ATTENUATION_0DB, /* current SIF att setting */
714 { /* qam_rf_agc_cfg */
715 DRX_STANDARD_ITU_B, /* standard */
716 DRX_AGC_CTRL_AUTO, /* ctrl_mode */
717 0, /* output_level */
718 0, /* min_output_level */
719 0xFFFF, /* max_output_level */
720 0x0000, /* speed */
721 0x0000, /* top */
722 0x0000 /* c.o.c. */
724 { /* qam_if_agc_cfg */
725 DRX_STANDARD_ITU_B, /* standard */
726 DRX_AGC_CTRL_AUTO, /* ctrl_mode */
727 0, /* output_level */
728 0, /* min_output_level */
729 0xFFFF, /* max_output_level */
730 0x0000, /* speed */
731 0x0000, /* top (don't care) */
732 0x0000 /* c.o.c. (don't care) */
734 { /* vsb_rf_agc_cfg */
735 DRX_STANDARD_8VSB, /* standard */
736 DRX_AGC_CTRL_AUTO, /* ctrl_mode */
737 0, /* output_level */
738 0, /* min_output_level */
739 0xFFFF, /* max_output_level */
740 0x0000, /* speed */
741 0x0000, /* top (don't care) */
742 0x0000 /* c.o.c. (don't care) */
744 { /* vsb_if_agc_cfg */
745 DRX_STANDARD_8VSB, /* standard */
746 DRX_AGC_CTRL_AUTO, /* ctrl_mode */
747 0, /* output_level */
748 0, /* min_output_level */
749 0xFFFF, /* max_output_level */
750 0x0000, /* speed */
751 0x0000, /* top (don't care) */
752 0x0000 /* c.o.c. (don't care) */
754 0, /* qam_pga_cfg */
755 0, /* vsb_pga_cfg */
756 { /* qam_pre_saw_cfg */
757 DRX_STANDARD_ITU_B, /* standard */
758 0, /* reference */
759 false /* use_pre_saw */
761 { /* vsb_pre_saw_cfg */
762 DRX_STANDARD_8VSB, /* standard */
763 0, /* reference */
764 false /* use_pre_saw */
767 /* Version information */
768 #ifndef _CH_
770 "01234567890", /* human readable version microcode */
771 "01234567890" /* human readable version device specific code */
774 { /* struct drx_version for microcode */
775 DRX_MODULE_UNKNOWN,
776 (char *)(NULL),
780 (char *)(NULL)
782 { /* struct drx_version for device specific code */
783 DRX_MODULE_UNKNOWN,
784 (char *)(NULL),
788 (char *)(NULL)
792 { /* struct drx_version_list for microcode */
793 (struct drx_version *) (NULL),
794 (struct drx_version_list *) (NULL)
796 { /* struct drx_version_list for device specific code */
797 (struct drx_version *) (NULL),
798 (struct drx_version_list *) (NULL)
801 #endif
802 false, /* smart_ant_inverted */
803 /* Tracking filter setting for OOB */
805 12000,
806 9300,
807 6600,
808 5280,
809 3700,
810 3000,
811 2000,
813 false, /* oob_power_on */
814 0, /* mpeg_ts_static_bitrate */
815 false, /* disable_te_ihandling */
816 false, /* bit_reverse_mpeg_outout */
817 DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO, /* mpeg_output_clock_rate */
818 DRXJ_MPEG_START_WIDTH_1CLKCYC, /* mpeg_start_width */
820 /* Pre SAW & Agc configuration for ATV */
822 DRX_STANDARD_NTSC, /* standard */
823 7, /* reference */
824 true /* use_pre_saw */
826 { /* ATV RF-AGC */
827 DRX_STANDARD_NTSC, /* standard */
828 DRX_AGC_CTRL_AUTO, /* ctrl_mode */
829 0, /* output_level */
830 0, /* min_output_level (d.c.) */
831 0, /* max_output_level (d.c.) */
832 3, /* speed */
833 9500, /* top */
834 4000 /* cut-off current */
836 { /* ATV IF-AGC */
837 DRX_STANDARD_NTSC, /* standard */
838 DRX_AGC_CTRL_AUTO, /* ctrl_mode */
839 0, /* output_level */
840 0, /* min_output_level (d.c.) */
841 0, /* max_output_level (d.c.) */
842 3, /* speed */
843 2400, /* top */
844 0 /* c.o.c. (d.c.) */
846 140, /* ATV PGA config */
847 0, /* curr_symbol_rate */
849 false, /* pdr_safe_mode */
850 SIO_PDR_GPIO_CFG__PRE, /* pdr_safe_restore_val_gpio */
851 SIO_PDR_VSYNC_CFG__PRE, /* pdr_safe_restore_val_v_sync */
852 SIO_PDR_SMA_RX_CFG__PRE, /* pdr_safe_restore_val_sma_rx */
853 SIO_PDR_SMA_TX_CFG__PRE, /* pdr_safe_restore_val_sma_tx */
855 4, /* oob_pre_saw */
856 DRXJ_OOB_LO_POW_MINUS10DB, /* oob_lo_pow */
858 false /* aud_data, only first member */
863 * \var drxj_default_addr_g
864 * \brief Default I2C address and device identifier.
866 struct i2c_device_addr drxj_default_addr_g = {
867 DRXJ_DEF_I2C_ADDR, /* i2c address */
868 DRXJ_DEF_DEMOD_DEV_ID /* device id */
872 * \var drxj_default_comm_attr_g
873 * \brief Default common attributes of a drxj demodulator instance.
875 struct drx_common_attr drxj_default_comm_attr_g = {
876 NULL, /* ucode file */
877 true, /* ucode verify switch */
878 {0}, /* version record */
880 44000, /* IF in kHz in case no tuner instance is used */
881 (151875 - 0), /* system clock frequency in kHz */
882 0, /* oscillator frequency kHz */
883 0, /* oscillator deviation in ppm, signed */
884 false, /* If true mirror frequency spectrum */
886 /* MPEG output configuration */
887 true, /* If true, enable MPEG ouput */
888 false, /* If true, insert RS byte */
889 true, /* If true, parallel out otherwise serial */
890 false, /* If true, invert DATA signals */
891 false, /* If true, invert ERR signal */
892 false, /* If true, invert STR signals */
893 false, /* If true, invert VAL signals */
894 false, /* If true, invert CLK signals */
895 true, /* If true, static MPEG clockrate will
896 be used, otherwise clockrate will
897 adapt to the bitrate of the TS */
898 19392658UL, /* Maximum bitrate in b/s in case
899 static clockrate is selected */
900 DRX_MPEG_STR_WIDTH_1 /* MPEG Start width in clock cycles */
902 /* Initilisations below can be ommited, they require no user input and
903 are initialy 0, NULL or false. The compiler will initialize them to these
904 values when ommited. */
905 false, /* is_opened */
907 /* SCAN */
908 NULL, /* no scan params yet */
909 0, /* current scan index */
910 0, /* next scan frequency */
911 false, /* scan ready flag */
912 0, /* max channels to scan */
913 0, /* nr of channels scanned */
914 NULL, /* default scan function */
915 NULL, /* default context pointer */
916 0, /* millisec to wait for demod lock */
917 DRXJ_DEMOD_LOCK, /* desired lock */
918 false,
920 /* Power management */
921 DRX_POWER_UP,
923 /* Tuner */
924 1, /* nr of I2C port to wich tuner is */
925 0L, /* minimum RF input frequency, in kHz */
926 0L, /* maximum RF input frequency, in kHz */
927 false, /* Rf Agc Polarity */
928 false, /* If Agc Polarity */
929 false, /* tuner slow mode */
931 { /* current channel (all 0) */
932 0UL /* channel.frequency */
934 DRX_STANDARD_UNKNOWN, /* current standard */
935 DRX_STANDARD_UNKNOWN, /* previous standard */
936 DRX_STANDARD_UNKNOWN, /* di_cache_standard */
937 false, /* use_bootloader */
938 0UL, /* capabilities */
939 0 /* mfx */
943 * \var drxj_default_demod_g
944 * \brief Default drxj demodulator instance.
946 struct drx_demod_instance drxj_default_demod_g = {
947 &DRXJ_DAP, /* data access protocol functions */
948 &drxj_default_addr_g, /* i2c address & device id */
949 &drxj_default_comm_attr_g, /* demod common attributes */
950 &drxj_data_g /* demod device specific attributes */
954 * \brief Default audio data structure for DRK demodulator instance.
956 * This structure is DRXK specific.
959 struct drx_aud_data drxj_default_aud_data_g = {
960 false, /* audio_is_active */
961 DRX_AUD_STANDARD_AUTO, /* audio_standard */
963 /* i2sdata */
965 false, /* output_enable */
966 48000, /* frequency */
967 DRX_I2S_MODE_MASTER, /* mode */
968 DRX_I2S_WORDLENGTH_32, /* word_length */
969 DRX_I2S_POLARITY_RIGHT, /* polarity */
970 DRX_I2S_FORMAT_WS_WITH_DATA /* format */
972 /* volume */
974 true, /* mute; */
975 0, /* volume */
976 DRX_AUD_AVC_OFF, /* avc_mode */
977 0, /* avc_ref_level */
978 DRX_AUD_AVC_MAX_GAIN_12DB, /* avc_max_gain */
979 DRX_AUD_AVC_MAX_ATTEN_24DB, /* avc_max_atten */
980 0, /* strength_left */
981 0 /* strength_right */
983 DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_ON, /* auto_sound */
984 /* ass_thresholds */
986 440, /* A2 */
987 12, /* BTSC */
988 700, /* NICAM */
990 /* carrier */
992 /* a */
994 42, /* thres */
995 DRX_NO_CARRIER_NOISE, /* opt */
996 0, /* shift */
997 0 /* dco */
999 /* b */
1001 42, /* thres */
1002 DRX_NO_CARRIER_MUTE, /* opt */
1003 0, /* shift */
1004 0 /* dco */
1008 /* mixer */
1010 DRX_AUD_SRC_STEREO_OR_A, /* source_i2s */
1011 DRX_AUD_I2S_MATRIX_STEREO, /* matrix_i2s */
1012 DRX_AUD_FM_MATRIX_SOUND_A /* matrix_fm */
1014 DRX_AUD_DEVIATION_NORMAL, /* deviation */
1015 DRX_AUD_AVSYNC_OFF, /* av_sync */
1017 /* prescale */
1019 DRX_AUD_MAX_FM_DEVIATION, /* fm_deviation */
1020 DRX_AUD_MAX_NICAM_PRESCALE /* nicam_gain */
1022 DRX_AUD_FM_DEEMPH_75US, /* deemph */
1023 DRX_BTSC_STEREO, /* btsc_detect */
1024 0, /* rds_data_counter */
1025 false /* rds_data_present */
1028 /*-----------------------------------------------------------------------------
1029 STRUCTURES
1030 ----------------------------------------------------------------------------*/
1031 struct drxjeq_stat {
1032 u16 eq_mse;
1033 u8 eq_mode;
1034 u8 eq_ctrl;
1035 u8 eq_stat;
1038 /* HI command */
1039 struct drxj_hi_cmd {
1040 u16 cmd;
1041 u16 param1;
1042 u16 param2;
1043 u16 param3;
1044 u16 param4;
1045 u16 param5;
1046 u16 param6;
1049 /*============================================================================*/
1050 /*=== MICROCODE RELATED STRUCTURES ===========================================*/
1051 /*============================================================================*/
1054 * struct drxu_code_block_hdr - Structure of the microcode block headers
1056 * @addr: Destination address of the data in this block
1057 * @size: Size of the block data following this header counted in
1058 * 16 bits words
1059 * @CRC: CRC value of the data block, only valid if CRC flag is
1060 * set.
1062 struct drxu_code_block_hdr {
1063 u32 addr;
1064 u16 size;
1065 u16 flags;
1066 u16 CRC;
1069 /*-----------------------------------------------------------------------------
1070 FUNCTIONS
1071 ----------------------------------------------------------------------------*/
1072 /* Some prototypes */
1073 static int
1074 hi_command(struct i2c_device_addr *dev_addr,
1075 const struct drxj_hi_cmd *cmd, u16 *result);
1077 static int
1078 ctrl_lock_status(struct drx_demod_instance *demod, enum drx_lock_status *lock_stat);
1080 static int
1081 ctrl_power_mode(struct drx_demod_instance *demod, enum drx_power_mode *mode);
1083 static int power_down_aud(struct drx_demod_instance *demod);
1085 #if 0
1086 static int power_up_aud(struct drx_demod_instance *demod, bool set_standard);
1088 static int
1089 aud_ctrl_set_standard(struct drx_demod_instance *demod, enum drx_aud_standard *standard);
1090 #endif
1092 static int
1093 ctrl_set_cfg_pre_saw(struct drx_demod_instance *demod, struct drxj_cfg_pre_saw *pre_saw);
1095 static int
1096 ctrl_set_cfg_afe_gain(struct drx_demod_instance *demod, struct drxj_cfg_afe_gain *afe_gain);
1098 /*============================================================================*/
1099 /*============================================================================*/
1100 /*== HELPER FUNCTIONS ==*/
1101 /*============================================================================*/
1102 /*============================================================================*/
1104 #if 0
1106 * \fn void mult32(u32 a, u32 b, u32 *h, u32 *l)
1107 * \brief 32bitsx32bits signed multiplication
1108 * \param a 32 bits multiplicant, typecast from signed to unisgned
1109 * \param b 32 bits multiplier, typecast from signed to unisgned
1110 * \param h pointer to high part 64 bits result, typecast from signed to unisgned
1111 * \param l pointer to low part 64 bits result
1113 * For the 2n+n addition a + b:
1114 * if a >= 0, then h += 0 (sign extension = 0)
1115 * but if a < 0, then h += 2^n-1 ==> h -= 1.
1117 * Also, if a + b < 2^n, then a + b >= a && a + b >= b
1118 * but if a + b >= 2^n, then R = a + b - 2^n,
1119 * and because a < 2^n && b < 2*n ==> R < a && R < b.
1120 * Therefore, to detect overflow, simply compare the addition result with
1121 * one of the operands; if the result is smaller, overflow has occurred and
1122 * h must be incremented.
1124 * Booth multiplication uses additions and subtractions to reduce the number
1125 * of iterations. This is done by taking three subsequent bits abc and calculating
1126 * the following multiplication factor: -2a + b + c. This factor is multiplied
1127 * by the second operand and added to the result. Next, the first operand is
1128 * shifted two bits (hence one of the three bits is reused) and the process
1129 * repeated. The last iteration has only two bits left, but we simply add
1130 * a zero to the end.
1132 * Hence: (n=4)
1133 * 1 * a = 0 * 4a + 1 * a
1134 * 2 * a = 1 * 4a - 2 * a
1135 * 3 * a = 1 * 4a - 1 * a
1136 * -1 * a = 0 * 4a - 1 * a
1137 * -5 * a = -1 * 4a - 1 * a
1139 * etc.
1141 * Note that the function is type size independent. Any unsigned integer type
1142 * can be substituted for booth_t.
1146 #define DRX_IS_BOOTH_NEGATIVE(__a) (((__a) & (1 << (sizeof(u32) * 8 - 1))) != 0)
1148 static void mult32(u32 a, u32 b, u32 *h, u32 *l)
1150 unsigned int i;
1151 *h = *l = 0;
1153 /* n/2 iterations; shift operand a left two bits after each iteration. */
1154 /* This automatically appends a zero to the operand for the last iteration. */
1155 for (i = 0; i < sizeof(a) * 8; i += 2, a = a << 2) {
1156 /* Shift result left two bits */
1157 *h = (*h << 2) + (*l >> (sizeof(*l) * 8 - 2));
1158 *l = (*l << 2);
1160 /* Take the first three bits of operand a for the Booth conversion: */
1161 /* 0, 7: do nothing */
1162 /* 1, 2: add b */
1163 /* 3 : add 2b */
1164 /* 4 : subtract 2b */
1165 /* 5, 6: subtract b */
1166 switch (a >> (sizeof(a) * 8 - 3)) {
1167 case 3:
1168 *l += b;
1169 *h = *h - DRX_IS_BOOTH_NEGATIVE(b) + (*l < b);
1170 case 1:
1171 case 2:
1172 *l += b;
1173 *h = *h - DRX_IS_BOOTH_NEGATIVE(b) + (*l < b);
1174 break;
1175 case 4:
1176 *l -= b;
1177 *h = *h - !DRX_IS_BOOTH_NEGATIVE(b) + !b + (*l <
1178 ((u32)
1180 ((s32)
1181 b))));
1182 case 5:
1183 case 6:
1184 *l -= b;
1185 *h = *h - !DRX_IS_BOOTH_NEGATIVE(b) + !b + (*l <
1186 ((u32)
1188 ((s32)
1189 b))));
1190 break;
1194 #endif
1196 /*============================================================================*/
1199 * \fn u32 frac28(u32 N, u32 D)
1200 * \brief Compute: (1<<28)*N/D
1201 * \param N 32 bits
1202 * \param D 32 bits
1203 * \return (1<<28)*N/D
1204 * This function is used to avoid floating-point calculations as they may
1205 * not be present on the target platform.
1207 * frac28 performs an unsigned 28/28 bits division to 32-bit fixed point
1208 * fraction used for setting the Frequency Shifter registers.
1209 * N and D can hold numbers up to width: 28-bits.
1210 * The 4 bits integer part and the 28 bits fractional part are calculated.
1212 * Usage condition: ((1<<28)*n)/d < ((1<<32)-1) => (n/d) < 15.999
1214 * N: 0...(1<<28)-1 = 268435454
1215 * D: 0...(1<<28)-1
1216 * Q: 0...(1<<32)-1
1218 static u32 frac28(u32 N, u32 D)
1220 int i = 0;
1221 u32 Q1 = 0;
1222 u32 R0 = 0;
1224 R0 = (N % D) << 4; /* 32-28 == 4 shifts possible at max */
1225 Q1 = N / D; /* integer part, only the 4 least significant bits
1226 will be visible in the result */
1228 /* division using radix 16, 7 nibbles in the result */
1229 for (i = 0; i < 7; i++) {
1230 Q1 = (Q1 << 4) | R0 / D;
1231 R0 = (R0 % D) << 4;
1233 /* rounding */
1234 if ((R0 >> 3) >= D)
1235 Q1++;
1237 return Q1;
1241 * \fn u32 log1_times100( u32 x)
1242 * \brief Compute: 100*log10(x)
1243 * \param x 32 bits
1244 * \return 100*log10(x)
1246 * 100*log10(x)
1247 * = 100*(log2(x)/log2(10)))
1248 * = (100*(2^15)*log2(x))/((2^15)*log2(10))
1249 * = ((200*(2^15)*log2(x))/((2^15)*log2(10)))/2
1250 * = ((200*(2^15)*(log2(x/y)+log2(y)))/((2^15)*log2(10)))/2
1251 * = ((200*(2^15)*log2(x/y))+(200*(2^15)*log2(y)))/((2^15)*log2(10)))/2
1253 * where y = 2^k and 1<= (x/y) < 2
1256 static u32 log1_times100(u32 x)
1258 static const u8 scale = 15;
1259 static const u8 index_width = 5;
1261 log2lut[n] = (1<<scale) * 200 * log2( 1.0 + ( (1.0/(1<<INDEXWIDTH)) * n ))
1262 0 <= n < ((1<<INDEXWIDTH)+1)
1265 static const u32 log2lut[] = {
1266 0, /* 0.000000 */
1267 290941, /* 290941.300628 */
1268 573196, /* 573196.476418 */
1269 847269, /* 847269.179851 */
1270 1113620, /* 1113620.489452 */
1271 1372674, /* 1372673.576986 */
1272 1624818, /* 1624817.752104 */
1273 1870412, /* 1870411.981536 */
1274 2109788, /* 2109787.962654 */
1275 2343253, /* 2343252.817465 */
1276 2571091, /* 2571091.461923 */
1277 2793569, /* 2793568.696416 */
1278 3010931, /* 3010931.055901 */
1279 3223408, /* 3223408.452106 */
1280 3431216, /* 3431215.635215 */
1281 3634553, /* 3634553.498355 */
1282 3833610, /* 3833610.244726 */
1283 4028562, /* 4028562.434393 */
1284 4219576, /* 4219575.925308 */
1285 4406807, /* 4406806.721144 */
1286 4590402, /* 4590401.736809 */
1287 4770499, /* 4770499.491025 */
1288 4947231, /* 4947230.734179 */
1289 5120719, /* 5120719.018555 */
1290 5291081, /* 5291081.217197 */
1291 5458428, /* 5458427.996830 */
1292 5622864, /* 5622864.249668 */
1293 5784489, /* 5784489.488298 */
1294 5943398, /* 5943398.207380 */
1295 6099680, /* 6099680.215452 */
1296 6253421, /* 6253420.939751 */
1297 6404702, /* 6404701.706649 */
1298 6553600, /* 6553600.000000 */
1301 u8 i = 0;
1302 u32 y = 0;
1303 u32 d = 0;
1304 u32 k = 0;
1305 u32 r = 0;
1307 if (x == 0)
1308 return 0;
1310 /* Scale x (normalize) */
1311 /* computing y in log(x/y) = log(x) - log(y) */
1312 if ((x & (((u32) (-1)) << (scale + 1))) == 0) {
1313 for (k = scale; k > 0; k--) {
1314 if (x & (((u32) 1) << scale))
1315 break;
1316 x <<= 1;
1318 } else {
1319 for (k = scale; k < 31; k++) {
1320 if ((x & (((u32) (-1)) << (scale + 1))) == 0)
1321 break;
1322 x >>= 1;
1326 Now x has binary point between bit[scale] and bit[scale-1]
1327 and 1.0 <= x < 2.0 */
1329 /* correction for divison: log(x) = log(x/y)+log(y) */
1330 y = k * ((((u32) 1) << scale) * 200);
1332 /* remove integer part */
1333 x &= ((((u32) 1) << scale) - 1);
1334 /* get index */
1335 i = (u8) (x >> (scale - index_width));
1336 /* compute delta (x-a) */
1337 d = x & ((((u32) 1) << (scale - index_width)) - 1);
1338 /* compute log, multiplication ( d* (.. )) must be within range ! */
1339 y += log2lut[i] +
1340 ((d * (log2lut[i + 1] - log2lut[i])) >> (scale - index_width));
1341 /* Conver to log10() */
1342 y /= 108853; /* (log2(10) << scale) */
1343 r = (y >> 1);
1344 /* rounding */
1345 if (y & ((u32)1))
1346 r++;
1348 return r;
1353 * \fn u32 frac_times1e6( u16 N, u32 D)
1354 * \brief Compute: (N/D) * 1000000.
1355 * \param N nominator 16-bits.
1356 * \param D denominator 32-bits.
1357 * \return u32
1358 * \retval ((N/D) * 1000000), 32 bits
1360 * No check on D=0!
1362 static u32 frac_times1e6(u32 N, u32 D)
1364 u32 remainder = 0;
1365 u32 frac = 0;
1368 frac = (N * 1000000) / D
1369 To let it fit in a 32 bits computation:
1370 frac = (N * (1000000 >> 4)) / (D >> 4)
1371 This would result in a problem in case D < 16 (div by 0).
1372 So we do it more elaborate as shown below.
1374 frac = (((u32) N) * (1000000 >> 4)) / D;
1375 frac <<= 4;
1376 remainder = (((u32) N) * (1000000 >> 4)) % D;
1377 remainder <<= 4;
1378 frac += remainder / D;
1379 remainder = remainder % D;
1380 if ((remainder * 2) > D)
1381 frac++;
1383 return frac;
1386 /*============================================================================*/
1388 #if 0
1390 * \brief Compute: 100 * 10^( gd_b / 200 ).
1391 * \param u32 gd_b Gain in 0.1dB
1392 * \return u32 Gainfactor in 0.01 resolution
1395 static u32 d_b2lin_times100(u32 gd_b)
1397 u32 result = 0;
1398 u32 nr6d_b_steps = 0;
1399 u32 remainder = 0;
1400 u32 remainder_fac = 0;
1402 /* start with factors 2 (6.02dB) */
1403 nr6d_b_steps = gd_b * 1000UL / 60206UL;
1404 if (nr6d_b_steps > 17) {
1405 /* Result max overflow if > log2( maxu32 / 2e4 ) ~= 17.7 */
1406 return MAX_U32;
1408 result = (1 << nr6d_b_steps);
1410 /* calculate remaining factor,
1411 poly approximation of 10^(gd_b/200):
1413 y = 1E-04x2 + 0.0106x + 1.0026
1415 max deviation < 0.005 for range x = [0 ... 60]
1417 remainder = ((gd_b * 1000UL) % 60206UL) / 1000UL;
1418 /* using 1e-4 for poly calculation */
1419 remainder_fac = 1 * remainder * remainder;
1420 remainder_fac += 106 * remainder;
1421 remainder_fac += 10026;
1423 /* multiply by remaining factor */
1424 result *= remainder_fac;
1426 /* conversion from 1e-4 to 1e-2 */
1427 return (result + 50) / 100;
1430 #define FRAC_FLOOR 0
1431 #define FRAC_CEIL 1
1432 #define FRAC_ROUND 2
1434 * \fn u32 frac( u32 N, u32 D, u16 RC )
1435 * \brief Compute: N/D.
1436 * \param N nominator 32-bits.
1437 * \param D denominator 32-bits.
1438 * \param RC-result correction: 0-floor; 1-ceil; 2-round
1439 * \return u32
1440 * \retval N/D, 32 bits
1442 * If D=0 returns 0
1444 static u32 frac(u32 N, u32 D, u16 RC)
1446 u32 remainder = 0;
1447 u32 frac = 0;
1448 u16 bit_cnt = 32;
1450 if (D == 0) {
1451 frac = 0;
1452 remainder = 0;
1454 return frac;
1457 if (D > N) {
1458 frac = 0;
1459 remainder = N;
1460 } else {
1461 remainder = 0;
1462 frac = N;
1463 while (bit_cnt-- > 0) {
1464 remainder <<= 1;
1465 remainder |= ((frac & 0x80000000) >> 31);
1466 frac <<= 1;
1467 if (remainder < D) {
1468 frac &= 0xFFFFFFFE;
1469 } else {
1470 remainder -= D;
1471 frac |= 0x1;
1475 /* result correction if needed */
1476 if ((RC == FRAC_CEIL) && (remainder != 0)) {
1477 /* ceil the result */
1478 /*(remainder is not zero -> value behind decimal point exists) */
1479 frac++;
1481 if ((RC == FRAC_ROUND) && (remainder >= D >> 1)) {
1482 /* remainder is bigger from D/2 -> round the result */
1483 frac++;
1487 return frac;
1489 #endif
1492 * \brief Values for NICAM prescaler gain. Computed from dB to integer
1493 * and rounded. For calc used formula: 16*10^(prescaleGain[dB]/20).
1496 static const u16 nicam_presc_table_val[43] = {
1497 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4,
1498 5, 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16,
1499 18, 20, 23, 25, 28, 32, 36, 40, 45,
1500 51, 57, 64, 71, 80, 90, 101, 113, 127
1503 /*============================================================================*/
1504 /*== END HELPER FUNCTIONS ==*/
1505 /*============================================================================*/
1507 /*============================================================================*/
1508 /*============================================================================*/
1509 /*== DRXJ DAP FUNCTIONS ==*/
1510 /*============================================================================*/
1511 /*============================================================================*/
1514 This layer takes care of some device specific register access protocols:
1515 -conversion to short address format
1516 -access to audio block
1517 This layer is placed between the drx_dap_fasi and the rest of the drxj
1518 specific implementation. This layer can use address map knowledge whereas
1519 dap_fasi may not use memory map knowledge.
1521 * For audio currently only 16 bits read and write register access is
1522 supported. More is not needed. RMW and 32 or 8 bit access on audio
1523 registers will have undefined behaviour. Flags (RMW, CRC reset, broadcast
1524 single/multi master) will be ignored.
1526 TODO: check ignoring single/multimaster is ok for AUD access ?
1529 #define DRXJ_ISAUDWRITE(addr) (((((addr)>>16)&1) == 1) ? true : false)
1530 #define DRXJ_DAP_AUDTRIF_TIMEOUT 80 /* millisec */
1531 /*============================================================================*/
1534 * \fn bool is_handled_by_aud_tr_if( u32 addr )
1535 * \brief Check if this address is handled by the audio token ring interface.
1536 * \param addr
1537 * \return bool
1538 * \retval true Yes, handled by audio token ring interface
1539 * \retval false No, not handled by audio token ring interface
1542 static
1543 bool is_handled_by_aud_tr_if(u32 addr)
1545 bool retval = false;
1547 if ((DRXDAP_FASI_ADDR2BLOCK(addr) == 4) &&
1548 (DRXDAP_FASI_ADDR2BANK(addr) > 1) &&
1549 (DRXDAP_FASI_ADDR2BANK(addr) < 6)) {
1550 retval = true;
1553 return retval;
1556 /*============================================================================*/
1558 static int drxj_dap_read_block(struct i2c_device_addr *dev_addr,
1559 u32 addr,
1560 u16 datasize,
1561 u8 *data, u32 flags)
1563 return drx_dap_fasi_funct_g.read_block_func(dev_addr,
1564 addr, datasize, data, flags);
1567 /*============================================================================*/
1569 static int drxj_dap_read_modify_write_reg8(struct i2c_device_addr *dev_addr,
1570 u32 waddr,
1571 u32 raddr,
1572 u8 wdata, u8 *rdata)
1574 return drx_dap_fasi_funct_g.read_modify_write_reg8func(dev_addr,
1575 waddr,
1576 raddr, wdata, rdata);
1579 /*============================================================================*/
1582 * \fn int drxj_dap_rm_write_reg16short
1583 * \brief Read modify write 16 bits audio register using short format only.
1584 * \param dev_addr
1585 * \param waddr Address to write to
1586 * \param raddr Address to read from (usually SIO_HI_RA_RAM_S0_RMWBUF__A)
1587 * \param wdata Data to write
1588 * \param rdata Buffer for data to read
1589 * \return int
1590 * \retval 0 Succes
1591 * \retval -EIO Timeout, I2C error, illegal bank
1593 * 16 bits register read modify write access using short addressing format only.
1594 * Requires knowledge of the registermap, thus device dependent.
1595 * Using DAP FASI directly to avoid endless recursion of RMWs to audio registers.
1599 /* TODO correct define should be #if ( DRXDAPFASI_SHORT_ADDR_ALLOWED==1 )
1600 See comments drxj_dap_read_modify_write_reg16 */
1601 #if (DRXDAPFASI_LONG_ADDR_ALLOWED == 0)
1602 static int drxj_dap_rm_write_reg16short(struct i2c_device_addr *dev_addr,
1603 u32 waddr,
1604 u32 raddr,
1605 u16 wdata, u16 *rdata)
1607 int rc;
1609 if (rdata == NULL)
1610 return -EINVAL;
1612 /* Set RMW flag */
1613 rc = drx_dap_fasi_funct_g.write_reg16func(dev_addr,
1614 SIO_HI_RA_RAM_S0_FLG_ACC__A,
1615 SIO_HI_RA_RAM_S0_FLG_ACC_S0_RWM__M,
1616 0x0000);
1617 if (rc == 0) {
1618 /* Write new data: triggers RMW */
1619 rc = drx_dap_fasi_funct_g.write_reg16func(dev_addr, waddr, wdata,
1620 0x0000);
1622 if (rc == 0) {
1623 /* Read old data */
1624 rc = drx_dap_fasi_funct_g.read_reg16func(dev_addr, raddr, rdata,
1625 0x0000);
1627 if (rc == 0) {
1628 /* Reset RMW flag */
1629 rc = drx_dap_fasi_funct_g.write_reg16func(dev_addr,
1630 SIO_HI_RA_RAM_S0_FLG_ACC__A,
1631 0, 0x0000);
1634 return rc;
1636 #endif
1638 /*============================================================================*/
1640 static int drxj_dap_read_modify_write_reg16(struct i2c_device_addr *dev_addr,
1641 u32 waddr,
1642 u32 raddr,
1643 u16 wdata, u16 *rdata)
1645 /* TODO: correct short/long addressing format decision,
1646 now long format has higher prio then short because short also
1647 needs virt bnks (not impl yet) for certain audio registers */
1648 #if (DRXDAPFASI_LONG_ADDR_ALLOWED == 1)
1649 return drx_dap_fasi_funct_g.read_modify_write_reg16func(dev_addr,
1650 waddr,
1651 raddr, wdata, rdata);
1652 #else
1653 return drxj_dap_rm_write_reg16short(dev_addr, waddr, raddr, wdata, rdata);
1654 #endif
1657 /*============================================================================*/
1659 static int drxj_dap_read_modify_write_reg32(struct i2c_device_addr *dev_addr,
1660 u32 waddr,
1661 u32 raddr,
1662 u32 wdata, u32 *rdata)
1664 return drx_dap_fasi_funct_g.read_modify_write_reg32func(dev_addr,
1665 waddr,
1666 raddr, wdata, rdata);
1669 /*============================================================================*/
1671 static int drxj_dap_read_reg8(struct i2c_device_addr *dev_addr,
1672 u32 addr,
1673 u8 *data, u32 flags)
1675 return drx_dap_fasi_funct_g.read_reg8func(dev_addr, addr, data, flags);
1678 /*============================================================================*/
1681 * \fn int drxj_dap_read_aud_reg16
1682 * \brief Read 16 bits audio register
1683 * \param dev_addr
1684 * \param addr
1685 * \param data
1686 * \return int
1687 * \retval 0 Succes
1688 * \retval -EIO Timeout, I2C error, illegal bank
1690 * 16 bits register read access via audio token ring interface.
1693 static int drxj_dap_read_aud_reg16(struct i2c_device_addr *dev_addr,
1694 u32 addr, u16 *data)
1696 u32 start_timer = 0;
1697 u32 current_timer = 0;
1698 u32 delta_timer = 0;
1699 u16 tr_status = 0;
1700 int stat = -EIO;
1702 /* No read possible for bank 3, return with error */
1703 if (DRXDAP_FASI_ADDR2BANK(addr) == 3) {
1704 stat = -EINVAL;
1705 } else {
1706 const u32 write_bit = ((dr_xaddr_t) 1) << 16;
1708 /* Force reset write bit */
1709 addr &= (~write_bit);
1711 /* Set up read */
1712 start_timer = jiffies_to_msecs(jiffies);
1713 do {
1714 /* RMW to aud TR IF until request is granted or timeout */
1715 stat = drxj_dap_read_modify_write_reg16(dev_addr,
1716 addr,
1717 SIO_HI_RA_RAM_S0_RMWBUF__A,
1718 0x0000, &tr_status);
1720 if (stat != 0)
1721 break;
1723 current_timer = jiffies_to_msecs(jiffies);
1724 delta_timer = current_timer - start_timer;
1725 if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) {
1726 stat = -EIO;
1727 break;
1730 } while (((tr_status & AUD_TOP_TR_CTR_FIFO_LOCK__M) ==
1731 AUD_TOP_TR_CTR_FIFO_LOCK_LOCKED) ||
1732 ((tr_status & AUD_TOP_TR_CTR_FIFO_FULL__M) ==
1733 AUD_TOP_TR_CTR_FIFO_FULL_FULL));
1734 } /* if ( DRXDAP_FASI_ADDR2BANK(addr)!=3 ) */
1736 /* Wait for read ready status or timeout */
1737 if (stat == 0) {
1738 start_timer = jiffies_to_msecs(jiffies);
1740 while ((tr_status & AUD_TOP_TR_CTR_FIFO_RD_RDY__M) !=
1741 AUD_TOP_TR_CTR_FIFO_RD_RDY_READY) {
1742 stat = drxj_dap_read_reg16(dev_addr,
1743 AUD_TOP_TR_CTR__A,
1744 &tr_status, 0x0000);
1745 if (stat != 0)
1746 break;
1748 current_timer = jiffies_to_msecs(jiffies);
1749 delta_timer = current_timer - start_timer;
1750 if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) {
1751 stat = -EIO;
1752 break;
1754 } /* while ( ... ) */
1757 /* Read value */
1758 if (stat == 0)
1759 stat = drxj_dap_read_modify_write_reg16(dev_addr,
1760 AUD_TOP_TR_RD_REG__A,
1761 SIO_HI_RA_RAM_S0_RMWBUF__A,
1762 0x0000, data);
1763 return stat;
1766 /*============================================================================*/
1768 static int drxj_dap_read_reg16(struct i2c_device_addr *dev_addr,
1769 u32 addr,
1770 u16 *data, u32 flags)
1772 int stat = -EIO;
1774 /* Check param */
1775 if ((dev_addr == NULL) || (data == NULL))
1776 return -EINVAL;
1778 if (is_handled_by_aud_tr_if(addr))
1779 stat = drxj_dap_read_aud_reg16(dev_addr, addr, data);
1780 else
1781 stat = drx_dap_fasi_funct_g.read_reg16func(dev_addr,
1782 addr, data, flags);
1784 return stat;
1787 /*============================================================================*/
1789 static int drxj_dap_read_reg32(struct i2c_device_addr *dev_addr,
1790 u32 addr,
1791 u32 *data, u32 flags)
1793 return drx_dap_fasi_funct_g.read_reg32func(dev_addr, addr, data, flags);
1796 /*============================================================================*/
1798 static int drxj_dap_write_block(struct i2c_device_addr *dev_addr,
1799 u32 addr,
1800 u16 datasize,
1801 u8 *data, u32 flags)
1803 return drx_dap_fasi_funct_g.write_block_func(dev_addr,
1804 addr, datasize, data, flags);
1807 /*============================================================================*/
1809 static int drxj_dap_write_reg8(struct i2c_device_addr *dev_addr,
1810 u32 addr,
1811 u8 data, u32 flags)
1813 return drx_dap_fasi_funct_g.write_reg8func(dev_addr, addr, data, flags);
1816 /*============================================================================*/
1819 * \fn int drxj_dap_write_aud_reg16
1820 * \brief Write 16 bits audio register
1821 * \param dev_addr
1822 * \param addr
1823 * \param data
1824 * \return int
1825 * \retval 0 Succes
1826 * \retval -EIO Timeout, I2C error, illegal bank
1828 * 16 bits register write access via audio token ring interface.
1831 static int drxj_dap_write_aud_reg16(struct i2c_device_addr *dev_addr,
1832 u32 addr, u16 data)
1834 int stat = -EIO;
1836 /* No write possible for bank 2, return with error */
1837 if (DRXDAP_FASI_ADDR2BANK(addr) == 2) {
1838 stat = -EINVAL;
1839 } else {
1840 u32 start_timer = 0;
1841 u32 current_timer = 0;
1842 u32 delta_timer = 0;
1843 u16 tr_status = 0;
1844 const u32 write_bit = ((dr_xaddr_t) 1) << 16;
1846 /* Force write bit */
1847 addr |= write_bit;
1848 start_timer = jiffies_to_msecs(jiffies);
1849 do {
1850 /* RMW to aud TR IF until request is granted or timeout */
1851 stat = drxj_dap_read_modify_write_reg16(dev_addr,
1852 addr,
1853 SIO_HI_RA_RAM_S0_RMWBUF__A,
1854 data, &tr_status);
1855 if (stat != 0)
1856 break;
1858 current_timer = jiffies_to_msecs(jiffies);
1859 delta_timer = current_timer - start_timer;
1860 if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) {
1861 stat = -EIO;
1862 break;
1865 } while (((tr_status & AUD_TOP_TR_CTR_FIFO_LOCK__M) ==
1866 AUD_TOP_TR_CTR_FIFO_LOCK_LOCKED) ||
1867 ((tr_status & AUD_TOP_TR_CTR_FIFO_FULL__M) ==
1868 AUD_TOP_TR_CTR_FIFO_FULL_FULL));
1870 } /* if ( DRXDAP_FASI_ADDR2BANK(addr)!=2 ) */
1872 return stat;
1875 /*============================================================================*/
1877 static int drxj_dap_write_reg16(struct i2c_device_addr *dev_addr,
1878 u32 addr,
1879 u16 data, u32 flags)
1881 int stat = -EIO;
1883 /* Check param */
1884 if (dev_addr == NULL)
1885 return -EINVAL;
1887 if (is_handled_by_aud_tr_if(addr))
1888 stat = drxj_dap_write_aud_reg16(dev_addr, addr, data);
1889 else
1890 stat = drx_dap_fasi_funct_g.write_reg16func(dev_addr,
1891 addr, data, flags);
1893 return stat;
1896 /*============================================================================*/
1898 static int drxj_dap_write_reg32(struct i2c_device_addr *dev_addr,
1899 u32 addr,
1900 u32 data, u32 flags)
1902 return drx_dap_fasi_funct_g.write_reg32func(dev_addr, addr, data, flags);
1905 /*============================================================================*/
1907 /* Free data ram in SIO HI */
1908 #define SIO_HI_RA_RAM_USR_BEGIN__A 0x420040
1909 #define SIO_HI_RA_RAM_USR_END__A 0x420060
1911 #define DRXJ_HI_ATOMIC_BUF_START (SIO_HI_RA_RAM_USR_BEGIN__A)
1912 #define DRXJ_HI_ATOMIC_BUF_END (SIO_HI_RA_RAM_USR_BEGIN__A + 7)
1913 #define DRXJ_HI_ATOMIC_READ SIO_HI_RA_RAM_PAR_3_ACP_RW_READ
1914 #define DRXJ_HI_ATOMIC_WRITE SIO_HI_RA_RAM_PAR_3_ACP_RW_WRITE
1917 * \fn int drxj_dap_atomic_read_write_block()
1918 * \brief Basic access routine for atomic read or write access
1919 * \param dev_addr pointer to i2c dev address
1920 * \param addr destination/source address
1921 * \param datasize size of data buffer in bytes
1922 * \param data pointer to data buffer
1923 * \return int
1924 * \retval 0 Succes
1925 * \retval -EIO Timeout, I2C error, illegal bank
1928 static
1929 int drxj_dap_atomic_read_write_block(struct i2c_device_addr *dev_addr,
1930 u32 addr,
1931 u16 datasize,
1932 u8 *data, bool read_flag)
1934 struct drxj_hi_cmd hi_cmd;
1935 int rc;
1936 u16 word;
1937 u16 dummy = 0;
1938 u16 i = 0;
1940 /* Parameter check */
1941 if (!data || !dev_addr || ((datasize % 2)) || ((datasize / 2) > 8))
1942 return -EINVAL;
1944 /* Set up HI parameters to read or write n bytes */
1945 hi_cmd.cmd = SIO_HI_RA_RAM_CMD_ATOMIC_COPY;
1946 hi_cmd.param1 =
1947 (u16) ((DRXDAP_FASI_ADDR2BLOCK(DRXJ_HI_ATOMIC_BUF_START) << 6) +
1948 DRXDAP_FASI_ADDR2BANK(DRXJ_HI_ATOMIC_BUF_START));
1949 hi_cmd.param2 =
1950 (u16) DRXDAP_FASI_ADDR2OFFSET(DRXJ_HI_ATOMIC_BUF_START);
1951 hi_cmd.param3 = (u16) ((datasize / 2) - 1);
1952 if (!read_flag)
1953 hi_cmd.param3 |= DRXJ_HI_ATOMIC_WRITE;
1954 else
1955 hi_cmd.param3 |= DRXJ_HI_ATOMIC_READ;
1956 hi_cmd.param4 = (u16) ((DRXDAP_FASI_ADDR2BLOCK(addr) << 6) +
1957 DRXDAP_FASI_ADDR2BANK(addr));
1958 hi_cmd.param5 = (u16) DRXDAP_FASI_ADDR2OFFSET(addr);
1960 if (!read_flag) {
1961 /* write data to buffer */
1962 for (i = 0; i < (datasize / 2); i++) {
1964 word = ((u16) data[2 * i]);
1965 word += (((u16) data[(2 * i) + 1]) << 8);
1966 drxj_dap_write_reg16(dev_addr,
1967 (DRXJ_HI_ATOMIC_BUF_START + i),
1968 word, 0);
1972 rc = hi_command(dev_addr, &hi_cmd, &dummy);
1973 if (rc != 0) {
1974 pr_err("error %d\n", rc);
1975 goto rw_error;
1978 if (read_flag) {
1979 /* read data from buffer */
1980 for (i = 0; i < (datasize / 2); i++) {
1981 drxj_dap_read_reg16(dev_addr,
1982 (DRXJ_HI_ATOMIC_BUF_START + i),
1983 &word, 0);
1984 data[2 * i] = (u8) (word & 0xFF);
1985 data[(2 * i) + 1] = (u8) (word >> 8);
1989 return 0;
1991 rw_error:
1992 return -EIO;
1996 /*============================================================================*/
1999 * \fn int drxj_dap_atomic_read_reg32()
2000 * \brief Atomic read of 32 bits words
2002 static
2003 int drxj_dap_atomic_read_reg32(struct i2c_device_addr *dev_addr,
2004 u32 addr,
2005 u32 *data, u32 flags)
2007 u8 buf[sizeof(*data)];
2008 int rc = -EIO;
2009 u32 word = 0;
2011 if (!data)
2012 return -EINVAL;
2014 rc = drxj_dap_atomic_read_write_block(dev_addr, addr,
2015 sizeof(*data), buf, true);
2017 if (rc < 0)
2018 return 0;
2020 word = (u32) buf[3];
2021 word <<= 8;
2022 word |= (u32) buf[2];
2023 word <<= 8;
2024 word |= (u32) buf[1];
2025 word <<= 8;
2026 word |= (u32) buf[0];
2028 *data = word;
2030 return rc;
2033 /*============================================================================*/
2035 /*============================================================================*/
2036 /*== END DRXJ DAP FUNCTIONS ==*/
2037 /*============================================================================*/
2039 /*============================================================================*/
2040 /*============================================================================*/
2041 /*== HOST INTERFACE FUNCTIONS ==*/
2042 /*============================================================================*/
2043 /*============================================================================*/
2046 * \fn int hi_cfg_command()
2047 * \brief Configure HI with settings stored in the demod structure.
2048 * \param demod Demodulator.
2049 * \return int.
2051 * This routine was created because to much orthogonal settings have
2052 * been put into one HI API function (configure). Especially the I2C bridge
2053 * enable/disable should not need re-configuration of the HI.
2056 static int hi_cfg_command(const struct drx_demod_instance *demod)
2058 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
2059 struct drxj_hi_cmd hi_cmd;
2060 u16 result = 0;
2061 int rc;
2063 ext_attr = (struct drxj_data *) demod->my_ext_attr;
2065 hi_cmd.cmd = SIO_HI_RA_RAM_CMD_CONFIG;
2066 hi_cmd.param1 = SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY;
2067 hi_cmd.param2 = ext_attr->hi_cfg_timing_div;
2068 hi_cmd.param3 = ext_attr->hi_cfg_bridge_delay;
2069 hi_cmd.param4 = ext_attr->hi_cfg_wake_up_key;
2070 hi_cmd.param5 = ext_attr->hi_cfg_ctrl;
2071 hi_cmd.param6 = ext_attr->hi_cfg_transmit;
2073 rc = hi_command(demod->my_i2c_dev_addr, &hi_cmd, &result);
2074 if (rc != 0) {
2075 pr_err("error %d\n", rc);
2076 goto rw_error;
2079 /* Reset power down flag (set one call only) */
2080 ext_attr->hi_cfg_ctrl &= (~(SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ));
2082 return 0;
2084 rw_error:
2085 return -EIO;
2089 * \fn int hi_command()
2090 * \brief Configure HI with settings stored in the demod structure.
2091 * \param dev_addr I2C address.
2092 * \param cmd HI command.
2093 * \param result HI command result.
2094 * \return int.
2096 * Sends command to HI
2099 static int
2100 hi_command(struct i2c_device_addr *dev_addr, const struct drxj_hi_cmd *cmd, u16 *result)
2102 u16 wait_cmd = 0;
2103 u16 nr_retries = 0;
2104 bool powerdown_cmd = false;
2105 int rc;
2107 /* Write parameters */
2108 switch (cmd->cmd) {
2110 case SIO_HI_RA_RAM_CMD_CONFIG:
2111 case SIO_HI_RA_RAM_CMD_ATOMIC_COPY:
2112 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_HI_RA_RAM_PAR_6__A, cmd->param6, 0);
2113 if (rc != 0) {
2114 pr_err("error %d\n", rc);
2115 goto rw_error;
2117 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_HI_RA_RAM_PAR_5__A, cmd->param5, 0);
2118 if (rc != 0) {
2119 pr_err("error %d\n", rc);
2120 goto rw_error;
2122 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_HI_RA_RAM_PAR_4__A, cmd->param4, 0);
2123 if (rc != 0) {
2124 pr_err("error %d\n", rc);
2125 goto rw_error;
2127 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_HI_RA_RAM_PAR_3__A, cmd->param3, 0);
2128 if (rc != 0) {
2129 pr_err("error %d\n", rc);
2130 goto rw_error;
2132 /* fallthrough */
2133 case SIO_HI_RA_RAM_CMD_BRDCTRL:
2134 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_HI_RA_RAM_PAR_2__A, cmd->param2, 0);
2135 if (rc != 0) {
2136 pr_err("error %d\n", rc);
2137 goto rw_error;
2139 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_HI_RA_RAM_PAR_1__A, cmd->param1, 0);
2140 if (rc != 0) {
2141 pr_err("error %d\n", rc);
2142 goto rw_error;
2144 /* fallthrough */
2145 case SIO_HI_RA_RAM_CMD_NULL:
2146 /* No parameters */
2147 break;
2149 default:
2150 return -EINVAL;
2151 break;
2154 /* Write command */
2155 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_HI_RA_RAM_CMD__A, cmd->cmd, 0);
2156 if (rc != 0) {
2157 pr_err("error %d\n", rc);
2158 goto rw_error;
2161 if ((cmd->cmd) == SIO_HI_RA_RAM_CMD_RESET)
2162 msleep(1);
2164 /* Detect power down to ommit reading result */
2165 powerdown_cmd = (bool) ((cmd->cmd == SIO_HI_RA_RAM_CMD_CONFIG) &&
2166 (((cmd->
2167 param5) & SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M)
2168 == SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ));
2169 if (!powerdown_cmd) {
2170 /* Wait until command rdy */
2171 do {
2172 nr_retries++;
2173 if (nr_retries > DRXJ_MAX_RETRIES) {
2174 pr_err("timeout\n");
2175 goto rw_error;
2178 rc = DRXJ_DAP.read_reg16func(dev_addr, SIO_HI_RA_RAM_CMD__A, &wait_cmd, 0);
2179 if (rc != 0) {
2180 pr_err("error %d\n", rc);
2181 goto rw_error;
2183 } while (wait_cmd != 0);
2185 /* Read result */
2186 rc = DRXJ_DAP.read_reg16func(dev_addr, SIO_HI_RA_RAM_RES__A, result, 0);
2187 if (rc != 0) {
2188 pr_err("error %d\n", rc);
2189 goto rw_error;
2193 /* if ( powerdown_cmd == true ) */
2194 return 0;
2195 rw_error:
2196 return -EIO;
2200 * \fn int init_hi( const struct drx_demod_instance *demod )
2201 * \brief Initialise and configurate HI.
2202 * \param demod pointer to demod data.
2203 * \return int Return status.
2204 * \retval 0 Success.
2205 * \retval -EIO Failure.
2207 * Needs to know Psys (System Clock period) and Posc (Osc Clock period)
2208 * Need to store configuration in driver because of the way I2C
2209 * bridging is controlled.
2212 static int init_hi(const struct drx_demod_instance *demod)
2214 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
2215 struct drx_common_attr *common_attr = (struct drx_common_attr *) (NULL);
2216 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
2217 int rc;
2219 ext_attr = (struct drxj_data *) demod->my_ext_attr;
2220 common_attr = (struct drx_common_attr *) demod->my_common_attr;
2221 dev_addr = demod->my_i2c_dev_addr;
2223 /* PATCH for bug 5003, HI ucode v3.1.0 */
2224 rc = DRXJ_DAP.write_reg16func(dev_addr, 0x4301D7, 0x801, 0);
2225 if (rc != 0) {
2226 pr_err("error %d\n", rc);
2227 goto rw_error;
2230 /* Timing div, 250ns/Psys */
2231 /* Timing div, = ( delay (nano seconds) * sysclk (kHz) )/ 1000 */
2232 ext_attr->hi_cfg_timing_div =
2233 (u16) ((common_attr->sys_clock_freq / 1000) * HI_I2C_DELAY) / 1000;
2234 /* Clipping */
2235 if ((ext_attr->hi_cfg_timing_div) > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M)
2236 ext_attr->hi_cfg_timing_div = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M;
2237 /* Bridge delay, uses oscilator clock */
2238 /* Delay = ( delay (nano seconds) * oscclk (kHz) )/ 1000 */
2239 /* SDA brdige delay */
2240 ext_attr->hi_cfg_bridge_delay =
2241 (u16) ((common_attr->osc_clock_freq / 1000) * HI_I2C_BRIDGE_DELAY) /
2242 1000;
2243 /* Clipping */
2244 if ((ext_attr->hi_cfg_bridge_delay) > SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M)
2245 ext_attr->hi_cfg_bridge_delay = SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M;
2246 /* SCL bridge delay, same as SDA for now */
2247 ext_attr->hi_cfg_bridge_delay += ((ext_attr->hi_cfg_bridge_delay) <<
2248 SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B);
2249 /* Wakeup key, setting the read flag (as suggest in the documentation) does
2250 not always result into a working solution (barebones worked VI2C failed).
2251 Not setting the bit works in all cases . */
2252 ext_attr->hi_cfg_wake_up_key = DRXJ_WAKE_UP_KEY;
2253 /* port/bridge/power down ctrl */
2254 ext_attr->hi_cfg_ctrl = (SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE);
2255 /* transit mode time out delay and watch dog divider */
2256 ext_attr->hi_cfg_transmit = SIO_HI_RA_RAM_PAR_6__PRE;
2258 rc = hi_cfg_command(demod);
2259 if (rc != 0) {
2260 pr_err("error %d\n", rc);
2261 goto rw_error;
2264 return 0;
2266 rw_error:
2267 return -EIO;
2270 /*============================================================================*/
2271 /*== END HOST INTERFACE FUNCTIONS ==*/
2272 /*============================================================================*/
2274 /*============================================================================*/
2275 /*============================================================================*/
2276 /*== AUXILIARY FUNCTIONS ==*/
2277 /*============================================================================*/
2278 /*============================================================================*/
2281 * \fn int get_device_capabilities()
2282 * \brief Get and store device capabilities.
2283 * \param demod Pointer to demodulator instance.
2284 * \return int.
2285 * \return 0 Success
2286 * \retval -EIO Failure
2288 * Depending on pulldowns on MDx pins the following internals are set:
2289 * * common_attr->osc_clock_freq
2290 * * ext_attr->has_lna
2291 * * ext_attr->has_ntsc
2292 * * ext_attr->has_btsc
2293 * * ext_attr->has_oob
2296 static int get_device_capabilities(struct drx_demod_instance *demod)
2298 struct drx_common_attr *common_attr = (struct drx_common_attr *) (NULL);
2299 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
2300 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
2301 u16 sio_pdr_ohw_cfg = 0;
2302 u32 sio_top_jtagid_lo = 0;
2303 u16 bid = 0;
2304 int rc;
2306 common_attr = (struct drx_common_attr *) demod->my_common_attr;
2307 ext_attr = (struct drxj_data *) demod->my_ext_attr;
2308 dev_addr = demod->my_i2c_dev_addr;
2310 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
2311 if (rc != 0) {
2312 pr_err("error %d\n", rc);
2313 goto rw_error;
2315 rc = DRXJ_DAP.read_reg16func(dev_addr, SIO_PDR_OHW_CFG__A, &sio_pdr_ohw_cfg, 0);
2316 if (rc != 0) {
2317 pr_err("error %d\n", rc);
2318 goto rw_error;
2320 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY__PRE, 0);
2321 if (rc != 0) {
2322 pr_err("error %d\n", rc);
2323 goto rw_error;
2326 switch ((sio_pdr_ohw_cfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) {
2327 case 0:
2328 /* ignore (bypass ?) */
2329 break;
2330 case 1:
2331 /* 27 MHz */
2332 common_attr->osc_clock_freq = 27000;
2333 break;
2334 case 2:
2335 /* 20.25 MHz */
2336 common_attr->osc_clock_freq = 20250;
2337 break;
2338 case 3:
2339 /* 4 MHz */
2340 common_attr->osc_clock_freq = 4000;
2341 break;
2342 default:
2343 return -EIO;
2347 Determine device capabilities
2348 Based on pinning v47
2350 rc = DRXJ_DAP.read_reg32func(dev_addr, SIO_TOP_JTAGID_LO__A, &sio_top_jtagid_lo, 0);
2351 if (rc != 0) {
2352 pr_err("error %d\n", rc);
2353 goto rw_error;
2355 ext_attr->mfx = (u8) ((sio_top_jtagid_lo >> 29) & 0xF);
2357 switch ((sio_top_jtagid_lo >> 12) & 0xFF) {
2358 case 0x31:
2359 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
2360 if (rc != 0) {
2361 pr_err("error %d\n", rc);
2362 goto rw_error;
2364 rc = DRXJ_DAP.read_reg16func(dev_addr, SIO_PDR_UIO_IN_HI__A, &bid, 0);
2365 if (rc != 0) {
2366 pr_err("error %d\n", rc);
2367 goto rw_error;
2369 bid = (bid >> 10) & 0xf;
2370 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY__PRE, 0);
2371 if (rc != 0) {
2372 pr_err("error %d\n", rc);
2373 goto rw_error;
2376 ext_attr->has_lna = true;
2377 ext_attr->has_ntsc = false;
2378 ext_attr->has_btsc = false;
2379 ext_attr->has_oob = false;
2380 ext_attr->has_smatx = true;
2381 ext_attr->has_smarx = false;
2382 ext_attr->has_gpio = false;
2383 ext_attr->has_irqn = false;
2384 break;
2385 case 0x33:
2386 ext_attr->has_lna = false;
2387 ext_attr->has_ntsc = false;
2388 ext_attr->has_btsc = false;
2389 ext_attr->has_oob = false;
2390 ext_attr->has_smatx = true;
2391 ext_attr->has_smarx = false;
2392 ext_attr->has_gpio = false;
2393 ext_attr->has_irqn = false;
2394 break;
2395 case 0x45:
2396 ext_attr->has_lna = true;
2397 ext_attr->has_ntsc = true;
2398 ext_attr->has_btsc = false;
2399 ext_attr->has_oob = false;
2400 ext_attr->has_smatx = true;
2401 ext_attr->has_smarx = true;
2402 ext_attr->has_gpio = true;
2403 ext_attr->has_irqn = false;
2404 break;
2405 case 0x46:
2406 ext_attr->has_lna = false;
2407 ext_attr->has_ntsc = true;
2408 ext_attr->has_btsc = false;
2409 ext_attr->has_oob = false;
2410 ext_attr->has_smatx = true;
2411 ext_attr->has_smarx = true;
2412 ext_attr->has_gpio = true;
2413 ext_attr->has_irqn = false;
2414 break;
2415 case 0x41:
2416 ext_attr->has_lna = true;
2417 ext_attr->has_ntsc = true;
2418 ext_attr->has_btsc = true;
2419 ext_attr->has_oob = false;
2420 ext_attr->has_smatx = true;
2421 ext_attr->has_smarx = true;
2422 ext_attr->has_gpio = true;
2423 ext_attr->has_irqn = false;
2424 break;
2425 case 0x43:
2426 ext_attr->has_lna = false;
2427 ext_attr->has_ntsc = true;
2428 ext_attr->has_btsc = true;
2429 ext_attr->has_oob = false;
2430 ext_attr->has_smatx = true;
2431 ext_attr->has_smarx = true;
2432 ext_attr->has_gpio = true;
2433 ext_attr->has_irqn = false;
2434 break;
2435 case 0x32:
2436 ext_attr->has_lna = true;
2437 ext_attr->has_ntsc = false;
2438 ext_attr->has_btsc = false;
2439 ext_attr->has_oob = true;
2440 ext_attr->has_smatx = true;
2441 ext_attr->has_smarx = true;
2442 ext_attr->has_gpio = true;
2443 ext_attr->has_irqn = true;
2444 break;
2445 case 0x34:
2446 ext_attr->has_lna = false;
2447 ext_attr->has_ntsc = true;
2448 ext_attr->has_btsc = true;
2449 ext_attr->has_oob = true;
2450 ext_attr->has_smatx = true;
2451 ext_attr->has_smarx = true;
2452 ext_attr->has_gpio = true;
2453 ext_attr->has_irqn = true;
2454 break;
2455 case 0x42:
2456 ext_attr->has_lna = true;
2457 ext_attr->has_ntsc = true;
2458 ext_attr->has_btsc = true;
2459 ext_attr->has_oob = true;
2460 ext_attr->has_smatx = true;
2461 ext_attr->has_smarx = true;
2462 ext_attr->has_gpio = true;
2463 ext_attr->has_irqn = true;
2464 break;
2465 case 0x44:
2466 ext_attr->has_lna = false;
2467 ext_attr->has_ntsc = true;
2468 ext_attr->has_btsc = true;
2469 ext_attr->has_oob = true;
2470 ext_attr->has_smatx = true;
2471 ext_attr->has_smarx = true;
2472 ext_attr->has_gpio = true;
2473 ext_attr->has_irqn = true;
2474 break;
2475 default:
2476 /* Unknown device variant */
2477 return -EIO;
2478 break;
2481 return 0;
2482 rw_error:
2483 return -EIO;
2487 * \fn int power_up_device()
2488 * \brief Power up device.
2489 * \param demod Pointer to demodulator instance.
2490 * \return int.
2491 * \return 0 Success
2492 * \retval -EIO Failure, I2C or max retries reached
2496 #ifndef DRXJ_MAX_RETRIES_POWERUP
2497 #define DRXJ_MAX_RETRIES_POWERUP 10
2498 #endif
2500 static int power_up_device(struct drx_demod_instance *demod)
2502 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
2503 u8 data = 0;
2504 u16 retry_count = 0;
2505 struct i2c_device_addr wake_up_addr;
2507 dev_addr = demod->my_i2c_dev_addr;
2508 wake_up_addr.i2c_addr = DRXJ_WAKE_UP_KEY;
2509 wake_up_addr.i2c_dev_id = dev_addr->i2c_dev_id;
2510 wake_up_addr.user_data = dev_addr->user_data;
2512 * I2C access may fail in this case: no ack
2513 * dummy write must be used to wake uop device, dummy read must be used to
2514 * reset HI state machine (avoiding actual writes)
2516 do {
2517 data = 0;
2518 drxbsp_i2c_write_read(&wake_up_addr, 1, &data,
2519 (struct i2c_device_addr *)(NULL), 0,
2520 (u8 *)(NULL));
2521 msleep(10);
2522 retry_count++;
2523 } while ((drxbsp_i2c_write_read
2524 ((struct i2c_device_addr *) (NULL), 0, (u8 *)(NULL), dev_addr, 1,
2525 &data)
2526 != 0) && (retry_count < DRXJ_MAX_RETRIES_POWERUP));
2528 /* Need some recovery time .... */
2529 msleep(10);
2531 if (retry_count == DRXJ_MAX_RETRIES_POWERUP)
2532 return -EIO;
2534 return 0;
2537 /*----------------------------------------------------------------------------*/
2538 /* MPEG Output Configuration Functions - begin */
2539 /*----------------------------------------------------------------------------*/
2541 * \fn int ctrl_set_cfg_mpeg_output()
2542 * \brief Set MPEG output configuration of the device.
2543 * \param devmod Pointer to demodulator instance.
2544 * \param cfg_data Pointer to mpeg output configuaration.
2545 * \return int.
2547 * Configure MPEG output parameters.
2550 static int
2551 ctrl_set_cfg_mpeg_output(struct drx_demod_instance *demod, struct drx_cfg_mpeg_output *cfg_data)
2553 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
2554 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
2555 struct drx_common_attr *common_attr = (struct drx_common_attr *) (NULL);
2556 int rc;
2557 u16 fec_oc_reg_mode = 0;
2558 u16 fec_oc_reg_ipr_mode = 0;
2559 u16 fec_oc_reg_ipr_invert = 0;
2560 u32 max_bit_rate = 0;
2561 u32 rcn_rate = 0;
2562 u32 nr_bits = 0;
2563 u16 sio_pdr_md_cfg = 0;
2564 /* data mask for the output data byte */
2565 u16 invert_data_mask =
2566 FEC_OC_IPR_INVERT_MD7__M | FEC_OC_IPR_INVERT_MD6__M |
2567 FEC_OC_IPR_INVERT_MD5__M | FEC_OC_IPR_INVERT_MD4__M |
2568 FEC_OC_IPR_INVERT_MD3__M | FEC_OC_IPR_INVERT_MD2__M |
2569 FEC_OC_IPR_INVERT_MD1__M | FEC_OC_IPR_INVERT_MD0__M;
2571 /* check arguments */
2572 if ((demod == NULL) || (cfg_data == NULL))
2573 return -EINVAL;
2575 dev_addr = demod->my_i2c_dev_addr;
2576 ext_attr = (struct drxj_data *) demod->my_ext_attr;
2577 common_attr = (struct drx_common_attr *) demod->my_common_attr;
2579 if (cfg_data->enable_mpeg_output == true) {
2580 /* quick and dirty patch to set MPEG incase current std is not
2581 producing MPEG */
2582 switch (ext_attr->standard) {
2583 case DRX_STANDARD_8VSB:
2584 case DRX_STANDARD_ITU_A:
2585 case DRX_STANDARD_ITU_B:
2586 case DRX_STANDARD_ITU_C:
2587 break;
2588 default:
2589 /* not an MPEG producing std, just store MPEG cfg */
2590 common_attr->mpeg_cfg.enable_mpeg_output =
2591 cfg_data->enable_mpeg_output;
2592 common_attr->mpeg_cfg.insert_rs_byte =
2593 cfg_data->insert_rs_byte;
2594 common_attr->mpeg_cfg.enable_parallel =
2595 cfg_data->enable_parallel;
2596 common_attr->mpeg_cfg.invert_data = cfg_data->invert_data;
2597 common_attr->mpeg_cfg.invert_err = cfg_data->invert_err;
2598 common_attr->mpeg_cfg.invert_str = cfg_data->invert_str;
2599 common_attr->mpeg_cfg.invert_val = cfg_data->invert_val;
2600 common_attr->mpeg_cfg.invert_clk = cfg_data->invert_clk;
2601 common_attr->mpeg_cfg.static_clk = cfg_data->static_clk;
2602 common_attr->mpeg_cfg.bitrate = cfg_data->bitrate;
2603 return 0;
2606 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_OCR_INVERT__A, 0, 0);
2607 if (rc != 0) {
2608 pr_err("error %d\n", rc);
2609 goto rw_error;
2611 switch (ext_attr->standard) {
2612 case DRX_STANDARD_8VSB:
2613 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_FCT_USAGE__A, 7, 0);
2614 if (rc != 0) {
2615 pr_err("error %d\n", rc);
2616 goto rw_error;
2617 } /* 2048 bytes fifo ram */
2618 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_TMD_CTL_UPD_RATE__A, 10, 0);
2619 if (rc != 0) {
2620 pr_err("error %d\n", rc);
2621 goto rw_error;
2623 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_TMD_INT_UPD_RATE__A, 10, 0);
2624 if (rc != 0) {
2625 pr_err("error %d\n", rc);
2626 goto rw_error;
2628 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_AVR_PARM_A__A, 5, 0);
2629 if (rc != 0) {
2630 pr_err("error %d\n", rc);
2631 goto rw_error;
2633 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_AVR_PARM_B__A, 7, 0);
2634 if (rc != 0) {
2635 pr_err("error %d\n", rc);
2636 goto rw_error;
2638 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_RCN_GAIN__A, 10, 0);
2639 if (rc != 0) {
2640 pr_err("error %d\n", rc);
2641 goto rw_error;
2643 /* Low Water Mark for synchronization */
2644 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_SNC_LWM__A, 3, 0);
2645 if (rc != 0) {
2646 pr_err("error %d\n", rc);
2647 goto rw_error;
2649 /* High Water Mark for synchronization */
2650 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_SNC_HWM__A, 5, 0);
2651 if (rc != 0) {
2652 pr_err("error %d\n", rc);
2653 goto rw_error;
2655 break;
2656 case DRX_STANDARD_ITU_A:
2657 case DRX_STANDARD_ITU_C:
2658 switch (ext_attr->constellation) {
2659 case DRX_CONSTELLATION_QAM256:
2660 nr_bits = 8;
2661 break;
2662 case DRX_CONSTELLATION_QAM128:
2663 nr_bits = 7;
2664 break;
2665 case DRX_CONSTELLATION_QAM64:
2666 nr_bits = 6;
2667 break;
2668 case DRX_CONSTELLATION_QAM32:
2669 nr_bits = 5;
2670 break;
2671 case DRX_CONSTELLATION_QAM16:
2672 nr_bits = 4;
2673 break;
2674 default:
2675 return -EIO;
2676 } /* ext_attr->constellation */
2677 /* max_bit_rate = symbol_rate * nr_bits * coef */
2678 /* coef = 188/204 */
2679 max_bit_rate =
2680 (ext_attr->curr_symbol_rate / 8) * nr_bits * 188;
2681 /* pass through b/c Annex A/c need following settings */
2682 case DRX_STANDARD_ITU_B:
2683 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_FCT_USAGE__A, FEC_OC_FCT_USAGE__PRE, 0);
2684 if (rc != 0) {
2685 pr_err("error %d\n", rc);
2686 goto rw_error;
2688 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_TMD_CTL_UPD_RATE__A, FEC_OC_TMD_CTL_UPD_RATE__PRE, 0);
2689 if (rc != 0) {
2690 pr_err("error %d\n", rc);
2691 goto rw_error;
2693 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_TMD_INT_UPD_RATE__A, 5, 0);
2694 if (rc != 0) {
2695 pr_err("error %d\n", rc);
2696 goto rw_error;
2698 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_AVR_PARM_A__A, FEC_OC_AVR_PARM_A__PRE, 0);
2699 if (rc != 0) {
2700 pr_err("error %d\n", rc);
2701 goto rw_error;
2703 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_AVR_PARM_B__A, FEC_OC_AVR_PARM_B__PRE, 0);
2704 if (rc != 0) {
2705 pr_err("error %d\n", rc);
2706 goto rw_error;
2708 if (cfg_data->static_clk == true) {
2709 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_RCN_GAIN__A, 0xD, 0);
2710 if (rc != 0) {
2711 pr_err("error %d\n", rc);
2712 goto rw_error;
2714 } else {
2715 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_RCN_GAIN__A, FEC_OC_RCN_GAIN__PRE, 0);
2716 if (rc != 0) {
2717 pr_err("error %d\n", rc);
2718 goto rw_error;
2721 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_SNC_LWM__A, 2, 0);
2722 if (rc != 0) {
2723 pr_err("error %d\n", rc);
2724 goto rw_error;
2726 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_SNC_HWM__A, 12, 0);
2727 if (rc != 0) {
2728 pr_err("error %d\n", rc);
2729 goto rw_error;
2731 break;
2732 default:
2733 break;
2734 } /* swtich (standard) */
2736 /* Check insertion of the Reed-Solomon parity bytes */
2737 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_OC_MODE__A, &fec_oc_reg_mode, 0);
2738 if (rc != 0) {
2739 pr_err("error %d\n", rc);
2740 goto rw_error;
2742 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_OC_IPR_MODE__A, &fec_oc_reg_ipr_mode, 0);
2743 if (rc != 0) {
2744 pr_err("error %d\n", rc);
2745 goto rw_error;
2747 if (cfg_data->insert_rs_byte == true) {
2748 /* enable parity symbol forward */
2749 fec_oc_reg_mode |= FEC_OC_MODE_PARITY__M;
2750 /* MVAL disable during parity bytes */
2751 fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M;
2752 switch (ext_attr->standard) {
2753 case DRX_STANDARD_8VSB:
2754 rcn_rate = 0x004854D3;
2755 break;
2756 case DRX_STANDARD_ITU_B:
2757 fec_oc_reg_mode |= FEC_OC_MODE_TRANSPARENT__M;
2758 switch (ext_attr->constellation) {
2759 case DRX_CONSTELLATION_QAM256:
2760 rcn_rate = 0x008945E7;
2761 break;
2762 case DRX_CONSTELLATION_QAM64:
2763 rcn_rate = 0x005F64D4;
2764 break;
2765 default:
2766 return -EIO;
2768 break;
2769 case DRX_STANDARD_ITU_A:
2770 case DRX_STANDARD_ITU_C:
2771 /* insert_rs_byte = true -> coef = 188/188 -> 1, RS bits are in MPEG output */
2772 rcn_rate =
2773 (frac28
2774 (max_bit_rate,
2775 (u32) (common_attr->sys_clock_freq / 8))) /
2776 188;
2777 break;
2778 default:
2779 return -EIO;
2780 } /* ext_attr->standard */
2781 } else { /* insert_rs_byte == false */
2783 /* disable parity symbol forward */
2784 fec_oc_reg_mode &= (~FEC_OC_MODE_PARITY__M);
2785 /* MVAL enable during parity bytes */
2786 fec_oc_reg_ipr_mode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M);
2787 switch (ext_attr->standard) {
2788 case DRX_STANDARD_8VSB:
2789 rcn_rate = 0x0041605C;
2790 break;
2791 case DRX_STANDARD_ITU_B:
2792 fec_oc_reg_mode &= (~FEC_OC_MODE_TRANSPARENT__M);
2793 switch (ext_attr->constellation) {
2794 case DRX_CONSTELLATION_QAM256:
2795 rcn_rate = 0x0082D6A0;
2796 break;
2797 case DRX_CONSTELLATION_QAM64:
2798 rcn_rate = 0x005AEC1A;
2799 break;
2800 default:
2801 return -EIO;
2803 break;
2804 case DRX_STANDARD_ITU_A:
2805 case DRX_STANDARD_ITU_C:
2806 /* insert_rs_byte = false -> coef = 188/204, RS bits not in MPEG output */
2807 rcn_rate =
2808 (frac28
2809 (max_bit_rate,
2810 (u32) (common_attr->sys_clock_freq / 8))) /
2811 204;
2812 break;
2813 default:
2814 return -EIO;
2815 } /* ext_attr->standard */
2818 if (cfg_data->enable_parallel == true) { /* MPEG data output is paralel -> clear ipr_mode[0] */
2819 fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M));
2820 } else { /* MPEG data output is serial -> set ipr_mode[0] */
2821 fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M;
2824 /* Control slective inversion of output bits */
2825 if (cfg_data->invert_data == true)
2826 fec_oc_reg_ipr_invert |= invert_data_mask;
2827 else
2828 fec_oc_reg_ipr_invert &= (~(invert_data_mask));
2830 if (cfg_data->invert_err == true)
2831 fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MERR__M;
2832 else
2833 fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MERR__M));
2835 if (cfg_data->invert_str == true)
2836 fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MSTRT__M;
2837 else
2838 fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MSTRT__M));
2840 if (cfg_data->invert_val == true)
2841 fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MVAL__M;
2842 else
2843 fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MVAL__M));
2845 if (cfg_data->invert_clk == true)
2846 fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MCLK__M;
2847 else
2848 fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MCLK__M));
2850 if (cfg_data->static_clk == true) { /* Static mode */
2851 u32 dto_rate = 0;
2852 u32 bit_rate = 0;
2853 u16 fec_oc_dto_burst_len = 0;
2854 u16 fec_oc_dto_period = 0;
2856 fec_oc_dto_burst_len = FEC_OC_DTO_BURST_LEN__PRE;
2858 switch (ext_attr->standard) {
2859 case DRX_STANDARD_8VSB:
2860 fec_oc_dto_period = 4;
2861 if (cfg_data->insert_rs_byte == true)
2862 fec_oc_dto_burst_len = 208;
2863 break;
2864 case DRX_STANDARD_ITU_A:
2866 u32 symbol_rate_th = 6400000;
2867 if (cfg_data->insert_rs_byte == true) {
2868 fec_oc_dto_burst_len = 204;
2869 symbol_rate_th = 5900000;
2871 if (ext_attr->curr_symbol_rate >=
2872 symbol_rate_th) {
2873 fec_oc_dto_period = 0;
2874 } else {
2875 fec_oc_dto_period = 1;
2878 break;
2879 case DRX_STANDARD_ITU_B:
2880 fec_oc_dto_period = 1;
2881 if (cfg_data->insert_rs_byte == true)
2882 fec_oc_dto_burst_len = 128;
2883 break;
2884 case DRX_STANDARD_ITU_C:
2885 fec_oc_dto_period = 1;
2886 if (cfg_data->insert_rs_byte == true)
2887 fec_oc_dto_burst_len = 204;
2888 break;
2889 default:
2890 return -EIO;
2892 bit_rate =
2893 common_attr->sys_clock_freq * 1000 / (fec_oc_dto_period +
2895 dto_rate =
2896 frac28(bit_rate, common_attr->sys_clock_freq * 1000);
2897 dto_rate >>= 3;
2898 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_DTO_RATE_HI__A, (u16)((dto_rate >> 16) & FEC_OC_DTO_RATE_HI__M), 0);
2899 if (rc != 0) {
2900 pr_err("error %d\n", rc);
2901 goto rw_error;
2903 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_DTO_RATE_LO__A, (u16)(dto_rate & FEC_OC_DTO_RATE_LO_RATE_LO__M), 0);
2904 if (rc != 0) {
2905 pr_err("error %d\n", rc);
2906 goto rw_error;
2908 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_DTO_MODE__A, FEC_OC_DTO_MODE_DYNAMIC__M | FEC_OC_DTO_MODE_OFFSET_ENABLE__M, 0);
2909 if (rc != 0) {
2910 pr_err("error %d\n", rc);
2911 goto rw_error;
2913 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_FCT_MODE__A, FEC_OC_FCT_MODE_RAT_ENA__M | FEC_OC_FCT_MODE_VIRT_ENA__M, 0);
2914 if (rc != 0) {
2915 pr_err("error %d\n", rc);
2916 goto rw_error;
2918 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_DTO_BURST_LEN__A, fec_oc_dto_burst_len, 0);
2919 if (rc != 0) {
2920 pr_err("error %d\n", rc);
2921 goto rw_error;
2923 if (ext_attr->mpeg_output_clock_rate != DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO)
2924 fec_oc_dto_period = ext_attr->mpeg_output_clock_rate - 1;
2925 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_DTO_PERIOD__A, fec_oc_dto_period, 0);
2926 if (rc != 0) {
2927 pr_err("error %d\n", rc);
2928 goto rw_error;
2930 } else { /* Dynamic mode */
2932 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_DTO_MODE__A, FEC_OC_DTO_MODE_DYNAMIC__M, 0);
2933 if (rc != 0) {
2934 pr_err("error %d\n", rc);
2935 goto rw_error;
2937 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_FCT_MODE__A, 0, 0);
2938 if (rc != 0) {
2939 pr_err("error %d\n", rc);
2940 goto rw_error;
2944 rc = DRXJ_DAP.write_reg32func(dev_addr, FEC_OC_RCN_CTL_RATE_LO__A, rcn_rate, 0);
2945 if (rc != 0) {
2946 pr_err("error %d\n", rc);
2947 goto rw_error;
2950 /* Write appropriate registers with requested configuration */
2951 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_MODE__A, fec_oc_reg_mode, 0);
2952 if (rc != 0) {
2953 pr_err("error %d\n", rc);
2954 goto rw_error;
2956 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_IPR_MODE__A, fec_oc_reg_ipr_mode, 0);
2957 if (rc != 0) {
2958 pr_err("error %d\n", rc);
2959 goto rw_error;
2961 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_IPR_INVERT__A, fec_oc_reg_ipr_invert, 0);
2962 if (rc != 0) {
2963 pr_err("error %d\n", rc);
2964 goto rw_error;
2967 /* enabling for both parallel and serial now */
2968 /* Write magic word to enable pdr reg write */
2969 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA, 0);
2970 if (rc != 0) {
2971 pr_err("error %d\n", rc);
2972 goto rw_error;
2974 /* Set MPEG TS pads to outputmode */
2975 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MSTRT_CFG__A, 0x0013, 0);
2976 if (rc != 0) {
2977 pr_err("error %d\n", rc);
2978 goto rw_error;
2980 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MERR_CFG__A, 0x0013, 0);
2981 if (rc != 0) {
2982 pr_err("error %d\n", rc);
2983 goto rw_error;
2985 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MCLK_CFG__A, MPEG_OUTPUT_CLK_DRIVE_STRENGTH << SIO_PDR_MCLK_CFG_DRIVE__B | 0x03 << SIO_PDR_MCLK_CFG_MODE__B, 0);
2986 if (rc != 0) {
2987 pr_err("error %d\n", rc);
2988 goto rw_error;
2990 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MVAL_CFG__A, 0x0013, 0);
2991 if (rc != 0) {
2992 pr_err("error %d\n", rc);
2993 goto rw_error;
2995 sio_pdr_md_cfg =
2996 MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH <<
2997 SIO_PDR_MD0_CFG_DRIVE__B | 0x03 << SIO_PDR_MD0_CFG_MODE__B;
2998 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD0_CFG__A, sio_pdr_md_cfg, 0);
2999 if (rc != 0) {
3000 pr_err("error %d\n", rc);
3001 goto rw_error;
3003 if (cfg_data->enable_parallel == true) { /* MPEG data output is paralel -> set MD1 to MD7 to output mode */
3004 sio_pdr_md_cfg =
3005 MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH <<
3006 SIO_PDR_MD0_CFG_DRIVE__B | 0x03 <<
3007 SIO_PDR_MD0_CFG_MODE__B;
3008 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD0_CFG__A, sio_pdr_md_cfg, 0);
3009 if (rc != 0) {
3010 pr_err("error %d\n", rc);
3011 goto rw_error;
3013 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD1_CFG__A, sio_pdr_md_cfg, 0);
3014 if (rc != 0) {
3015 pr_err("error %d\n", rc);
3016 goto rw_error;
3018 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD2_CFG__A, sio_pdr_md_cfg, 0);
3019 if (rc != 0) {
3020 pr_err("error %d\n", rc);
3021 goto rw_error;
3023 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD3_CFG__A, sio_pdr_md_cfg, 0);
3024 if (rc != 0) {
3025 pr_err("error %d\n", rc);
3026 goto rw_error;
3028 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD4_CFG__A, sio_pdr_md_cfg, 0);
3029 if (rc != 0) {
3030 pr_err("error %d\n", rc);
3031 goto rw_error;
3033 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD5_CFG__A, sio_pdr_md_cfg, 0);
3034 if (rc != 0) {
3035 pr_err("error %d\n", rc);
3036 goto rw_error;
3038 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD6_CFG__A, sio_pdr_md_cfg, 0);
3039 if (rc != 0) {
3040 pr_err("error %d\n", rc);
3041 goto rw_error;
3043 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD7_CFG__A, sio_pdr_md_cfg, 0);
3044 if (rc != 0) {
3045 pr_err("error %d\n", rc);
3046 goto rw_error;
3048 } else { /* MPEG data output is serial -> set MD1 to MD7 to tri-state */
3049 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD1_CFG__A, 0x0000, 0);
3050 if (rc != 0) {
3051 pr_err("error %d\n", rc);
3052 goto rw_error;
3054 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD2_CFG__A, 0x0000, 0);
3055 if (rc != 0) {
3056 pr_err("error %d\n", rc);
3057 goto rw_error;
3059 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD3_CFG__A, 0x0000, 0);
3060 if (rc != 0) {
3061 pr_err("error %d\n", rc);
3062 goto rw_error;
3064 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD4_CFG__A, 0x0000, 0);
3065 if (rc != 0) {
3066 pr_err("error %d\n", rc);
3067 goto rw_error;
3069 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD5_CFG__A, 0x0000, 0);
3070 if (rc != 0) {
3071 pr_err("error %d\n", rc);
3072 goto rw_error;
3074 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD6_CFG__A, 0x0000, 0);
3075 if (rc != 0) {
3076 pr_err("error %d\n", rc);
3077 goto rw_error;
3079 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD7_CFG__A, 0x0000, 0);
3080 if (rc != 0) {
3081 pr_err("error %d\n", rc);
3082 goto rw_error;
3085 /* Enable Monitor Bus output over MPEG pads and ctl input */
3086 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MON_CFG__A, 0x0000, 0);
3087 if (rc != 0) {
3088 pr_err("error %d\n", rc);
3089 goto rw_error;
3091 /* Write nomagic word to enable pdr reg write */
3092 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
3093 if (rc != 0) {
3094 pr_err("error %d\n", rc);
3095 goto rw_error;
3097 } else {
3098 /* Write magic word to enable pdr reg write */
3099 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA, 0);
3100 if (rc != 0) {
3101 pr_err("error %d\n", rc);
3102 goto rw_error;
3104 /* Set MPEG TS pads to inputmode */
3105 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MSTRT_CFG__A, 0x0000, 0);
3106 if (rc != 0) {
3107 pr_err("error %d\n", rc);
3108 goto rw_error;
3110 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MERR_CFG__A, 0x0000, 0);
3111 if (rc != 0) {
3112 pr_err("error %d\n", rc);
3113 goto rw_error;
3115 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MCLK_CFG__A, 0x0000, 0);
3116 if (rc != 0) {
3117 pr_err("error %d\n", rc);
3118 goto rw_error;
3120 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MVAL_CFG__A, 0x0000, 0);
3121 if (rc != 0) {
3122 pr_err("error %d\n", rc);
3123 goto rw_error;
3125 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD0_CFG__A, 0x0000, 0);
3126 if (rc != 0) {
3127 pr_err("error %d\n", rc);
3128 goto rw_error;
3130 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD1_CFG__A, 0x0000, 0);
3131 if (rc != 0) {
3132 pr_err("error %d\n", rc);
3133 goto rw_error;
3135 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD2_CFG__A, 0x0000, 0);
3136 if (rc != 0) {
3137 pr_err("error %d\n", rc);
3138 goto rw_error;
3140 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD3_CFG__A, 0x0000, 0);
3141 if (rc != 0) {
3142 pr_err("error %d\n", rc);
3143 goto rw_error;
3145 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD4_CFG__A, 0x0000, 0);
3146 if (rc != 0) {
3147 pr_err("error %d\n", rc);
3148 goto rw_error;
3150 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD5_CFG__A, 0x0000, 0);
3151 if (rc != 0) {
3152 pr_err("error %d\n", rc);
3153 goto rw_error;
3155 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD6_CFG__A, 0x0000, 0);
3156 if (rc != 0) {
3157 pr_err("error %d\n", rc);
3158 goto rw_error;
3160 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD7_CFG__A, 0x0000, 0);
3161 if (rc != 0) {
3162 pr_err("error %d\n", rc);
3163 goto rw_error;
3165 /* Enable Monitor Bus output over MPEG pads and ctl input */
3166 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MON_CFG__A, 0x0000, 0);
3167 if (rc != 0) {
3168 pr_err("error %d\n", rc);
3169 goto rw_error;
3171 /* Write nomagic word to enable pdr reg write */
3172 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
3173 if (rc != 0) {
3174 pr_err("error %d\n", rc);
3175 goto rw_error;
3179 /* save values for restore after re-acquire */
3180 common_attr->mpeg_cfg.enable_mpeg_output = cfg_data->enable_mpeg_output;
3181 common_attr->mpeg_cfg.insert_rs_byte = cfg_data->insert_rs_byte;
3182 common_attr->mpeg_cfg.enable_parallel = cfg_data->enable_parallel;
3183 common_attr->mpeg_cfg.invert_data = cfg_data->invert_data;
3184 common_attr->mpeg_cfg.invert_err = cfg_data->invert_err;
3185 common_attr->mpeg_cfg.invert_str = cfg_data->invert_str;
3186 common_attr->mpeg_cfg.invert_val = cfg_data->invert_val;
3187 common_attr->mpeg_cfg.invert_clk = cfg_data->invert_clk;
3188 common_attr->mpeg_cfg.static_clk = cfg_data->static_clk;
3189 common_attr->mpeg_cfg.bitrate = cfg_data->bitrate;
3191 return 0;
3192 rw_error:
3193 return -EIO;
3196 /*----------------------------------------------------------------------------*/
3198 #if 0
3200 * \fn int ctrl_get_cfg_mpeg_output()
3201 * \brief Get MPEG output configuration of the device.
3202 * \param devmod Pointer to demodulator instance.
3203 * \param cfg_data Pointer to MPEG output configuaration struct.
3204 * \return int.
3206 * Retrieve MPEG output configuartion.
3209 static int
3210 ctrl_get_cfg_mpeg_output(struct drx_demod_instance *demod, struct drx_cfg_mpeg_output *cfg_data)
3212 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
3213 struct drx_common_attr *common_attr = (struct drx_common_attr *) (NULL);
3214 enum drx_lock_status lock_status = DRX_NOT_LOCKED;
3215 int rc;
3216 u32 rate_reg = 0;
3217 u32 data64hi = 0;
3218 u32 data64lo = 0;
3220 if (cfg_data == NULL)
3221 return -EINVAL;
3223 dev_addr = demod->my_i2c_dev_addr;
3224 common_attr = demod->my_common_attr;
3226 cfg_data->enable_mpeg_output = common_attr->mpeg_cfg.enable_mpeg_output;
3227 cfg_data->insert_rs_byte = common_attr->mpeg_cfg.insert_rs_byte;
3228 cfg_data->enable_parallel = common_attr->mpeg_cfg.enable_parallel;
3229 cfg_data->invert_data = common_attr->mpeg_cfg.invert_data;
3230 cfg_data->invert_err = common_attr->mpeg_cfg.invert_err;
3231 cfg_data->invert_str = common_attr->mpeg_cfg.invert_str;
3232 cfg_data->invert_val = common_attr->mpeg_cfg.invert_val;
3233 cfg_data->invert_clk = common_attr->mpeg_cfg.invert_clk;
3234 cfg_data->static_clk = common_attr->mpeg_cfg.static_clk;
3235 cfg_data->bitrate = 0;
3237 rc = ctrl_lock_status(demod, &lock_status);
3238 if (rc != 0) {
3239 pr_err("error %d\n", rc);
3240 goto rw_error;
3242 if ((lock_status == DRX_LOCKED)) {
3243 rc = DRXJ_DAP.read_reg32func(dev_addr, FEC_OC_RCN_DYN_RATE_LO__A, &rate_reg, 0);
3244 if (rc != 0) {
3245 pr_err("error %d\n", rc);
3246 goto rw_error;
3248 /* Frcn_rate = rate_reg * Fsys / 2 ^ 25 */
3249 mult32(rate_reg, common_attr->sys_clock_freq * 1000, &data64hi,
3250 &data64lo);
3251 cfg_data->bitrate = (data64hi << 7) | (data64lo >> 25);
3254 return 0;
3255 rw_error:
3256 return -EIO;
3258 #endif
3260 /*----------------------------------------------------------------------------*/
3261 /* MPEG Output Configuration Functions - end */
3262 /*----------------------------------------------------------------------------*/
3264 /*----------------------------------------------------------------------------*/
3265 /* miscellaneous configuartions - begin */
3266 /*----------------------------------------------------------------------------*/
3269 * \fn int set_mpegtei_handling()
3270 * \brief Activate MPEG TEI handling settings.
3271 * \param devmod Pointer to demodulator instance.
3272 * \return int.
3274 * This routine should be called during a set channel of QAM/VSB
3277 static int set_mpegtei_handling(struct drx_demod_instance *demod)
3279 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
3280 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
3281 int rc;
3282 u16 fec_oc_dpr_mode = 0;
3283 u16 fec_oc_snc_mode = 0;
3284 u16 fec_oc_ems_mode = 0;
3286 dev_addr = demod->my_i2c_dev_addr;
3287 ext_attr = (struct drxj_data *) demod->my_ext_attr;
3289 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_OC_DPR_MODE__A, &fec_oc_dpr_mode, 0);
3290 if (rc != 0) {
3291 pr_err("error %d\n", rc);
3292 goto rw_error;
3294 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode, 0);
3295 if (rc != 0) {
3296 pr_err("error %d\n", rc);
3297 goto rw_error;
3299 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_OC_EMS_MODE__A, &fec_oc_ems_mode, 0);
3300 if (rc != 0) {
3301 pr_err("error %d\n", rc);
3302 goto rw_error;
3305 /* reset to default, allow TEI bit to be changed */
3306 fec_oc_dpr_mode &= (~FEC_OC_DPR_MODE_ERR_DISABLE__M);
3307 fec_oc_snc_mode &= (~(FEC_OC_SNC_MODE_ERROR_CTL__M |
3308 FEC_OC_SNC_MODE_CORR_DISABLE__M));
3309 fec_oc_ems_mode &= (~FEC_OC_EMS_MODE_MODE__M);
3311 if (ext_attr->disable_te_ihandling) {
3312 /* do not change TEI bit */
3313 fec_oc_dpr_mode |= FEC_OC_DPR_MODE_ERR_DISABLE__M;
3314 fec_oc_snc_mode |= FEC_OC_SNC_MODE_CORR_DISABLE__M |
3315 ((0x2) << (FEC_OC_SNC_MODE_ERROR_CTL__B));
3316 fec_oc_ems_mode |= ((0x01) << (FEC_OC_EMS_MODE_MODE__B));
3319 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_DPR_MODE__A, fec_oc_dpr_mode, 0);
3320 if (rc != 0) {
3321 pr_err("error %d\n", rc);
3322 goto rw_error;
3324 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_SNC_MODE__A, fec_oc_snc_mode, 0);
3325 if (rc != 0) {
3326 pr_err("error %d\n", rc);
3327 goto rw_error;
3329 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_EMS_MODE__A, fec_oc_ems_mode, 0);
3330 if (rc != 0) {
3331 pr_err("error %d\n", rc);
3332 goto rw_error;
3335 return 0;
3336 rw_error:
3337 return -EIO;
3340 /*----------------------------------------------------------------------------*/
3342 * \fn int bit_reverse_mpeg_output()
3343 * \brief Set MPEG output bit-endian settings.
3344 * \param devmod Pointer to demodulator instance.
3345 * \return int.
3347 * This routine should be called during a set channel of QAM/VSB
3350 static int bit_reverse_mpeg_output(struct drx_demod_instance *demod)
3352 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
3353 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
3354 int rc;
3355 u16 fec_oc_ipr_mode = 0;
3357 dev_addr = demod->my_i2c_dev_addr;
3358 ext_attr = (struct drxj_data *) demod->my_ext_attr;
3360 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_OC_IPR_MODE__A, &fec_oc_ipr_mode, 0);
3361 if (rc != 0) {
3362 pr_err("error %d\n", rc);
3363 goto rw_error;
3366 /* reset to default (normal bit order) */
3367 fec_oc_ipr_mode &= (~FEC_OC_IPR_MODE_REVERSE_ORDER__M);
3369 if (ext_attr->bit_reverse_mpeg_outout)
3370 fec_oc_ipr_mode |= FEC_OC_IPR_MODE_REVERSE_ORDER__M;
3372 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_IPR_MODE__A, fec_oc_ipr_mode, 0);
3373 if (rc != 0) {
3374 pr_err("error %d\n", rc);
3375 goto rw_error;
3378 return 0;
3379 rw_error:
3380 return -EIO;
3383 /*----------------------------------------------------------------------------*/
3385 * \fn int set_mpeg_output_clock_rate()
3386 * \brief Set MPEG output clock rate.
3387 * \param devmod Pointer to demodulator instance.
3388 * \return int.
3390 * This routine should be called during a set channel of QAM/VSB
3393 #if 0
3394 static int set_mpeg_output_clock_rate(struct drx_demod_instance *demod)
3396 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
3397 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
3398 int rc;
3400 dev_addr = demod->my_i2c_dev_addr;
3401 ext_attr = (struct drxj_data *) demod->my_ext_attr;
3403 if (ext_attr->mpeg_output_clock_rate != DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO) {
3404 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_DTO_PERIOD__A, ext_attr->mpeg_output_clock_rate - 1, 0);
3405 if (rc != 0) {
3406 pr_err("error %d\n", rc);
3407 goto rw_error;
3411 return 0;
3412 rw_error:
3413 return -EIO;
3415 #endif
3417 /*----------------------------------------------------------------------------*/
3419 * \fn int set_mpeg_start_width()
3420 * \brief Set MPEG start width.
3421 * \param devmod Pointer to demodulator instance.
3422 * \return int.
3424 * This routine should be called during a set channel of QAM/VSB
3427 static int set_mpeg_start_width(struct drx_demod_instance *demod)
3429 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
3430 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
3431 struct drx_common_attr *common_attr = (struct drx_common_attr *) NULL;
3432 int rc;
3433 u16 fec_oc_comm_mb = 0;
3435 dev_addr = demod->my_i2c_dev_addr;
3436 ext_attr = (struct drxj_data *) demod->my_ext_attr;
3437 common_attr = demod->my_common_attr;
3439 if ((common_attr->mpeg_cfg.static_clk == true)
3440 && (common_attr->mpeg_cfg.enable_parallel == false)) {
3441 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_OC_COMM_MB__A, &fec_oc_comm_mb, 0);
3442 if (rc != 0) {
3443 pr_err("error %d\n", rc);
3444 goto rw_error;
3446 fec_oc_comm_mb &= ~FEC_OC_COMM_MB_CTL_ON;
3447 if (ext_attr->mpeg_start_width == DRXJ_MPEG_START_WIDTH_8CLKCYC)
3448 fec_oc_comm_mb |= FEC_OC_COMM_MB_CTL_ON;
3449 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_COMM_MB__A, fec_oc_comm_mb, 0);
3450 if (rc != 0) {
3451 pr_err("error %d\n", rc);
3452 goto rw_error;
3456 return 0;
3457 rw_error:
3458 return -EIO;
3461 #if 0
3462 /*----------------------------------------------------------------------------*/
3464 * \fn int ctrl_set_cfg_mpeg_output_misc()
3465 * \brief Set miscellaneous configuartions
3466 * \param devmod Pointer to demodulator instance.
3467 * \param cfg_data pDRXJCfgMisc_t
3468 * \return int.
3470 * This routine can be used to set configuartion options that are DRXJ
3471 * specific and/or added to the requirements at a late stage.
3474 static int
3475 ctrl_set_cfg_mpeg_output_misc(struct drx_demod_instance *demod,
3476 struct drxj_cfg_mpeg_output_misc *cfg_data)
3478 struct drxj_data *ext_attr = NULL;
3479 int rc;
3481 if (cfg_data == NULL)
3482 return -EINVAL;
3484 ext_attr = demod->my_ext_attr;
3487 Set disable TEI bit handling flag.
3488 TEI must be left untouched by device in case of BER measurements using
3489 external equipment that is unable to ignore the TEI bit in the TS.
3490 Default will false (enable TEI bit handling).
3491 Reverse output bit order. Default is false (msb on MD7 (parallel) or out first (serial)).
3492 Set clock rate. Default is auto that is derived from symbol rate.
3493 The flags and values will also be used to set registers during a set channel.
3495 ext_attr->disable_te_ihandling = cfg_data->disable_tei_handling;
3496 ext_attr->bit_reverse_mpeg_outout = cfg_data->bit_reverse_mpeg_outout;
3497 ext_attr->mpeg_output_clock_rate = cfg_data->mpeg_output_clock_rate;
3498 ext_attr->mpeg_start_width = cfg_data->mpeg_start_width;
3499 /* Don't care what the active standard is, activate setting immediatly */
3500 rc = set_mpegtei_handling(demod);
3501 if (rc != 0) {
3502 pr_err("error %d\n", rc);
3503 goto rw_error;
3505 rc = bit_reverse_mpeg_output(demod);
3506 if (rc != 0) {
3507 pr_err("error %d\n", rc);
3508 goto rw_error;
3510 rc = set_mpeg_output_clock_rate(demod);
3511 if (rc != 0) {
3512 pr_err("error %d\n", rc);
3513 goto rw_error;
3515 rc = set_mpeg_start_width(demod);
3516 if (rc != 0) {
3517 pr_err("error %d\n", rc);
3518 goto rw_error;
3521 return 0;
3522 rw_error:
3523 return -EIO;
3526 /*----------------------------------------------------------------------------*/
3529 * \fn int ctrl_get_cfg_mpeg_output_misc()
3530 * \brief Get miscellaneous configuartions.
3531 * \param devmod Pointer to demodulator instance.
3532 * \param cfg_data Pointer to DRXJCfgMisc_t.
3533 * \return int.
3535 * This routine can be used to retreive the current setting of the configuartion
3536 * options that are DRXJ specific and/or added to the requirements at a
3537 * late stage.
3540 static int
3541 ctrl_get_cfg_mpeg_output_misc(struct drx_demod_instance *demod,
3542 struct drxj_cfg_mpeg_output_misc *cfg_data)
3544 struct drxj_data *ext_attr = NULL;
3545 int rc;
3546 u16 data = 0;
3548 if (cfg_data == NULL)
3549 return -EINVAL;
3551 ext_attr = (struct drxj_data *) demod->my_ext_attr;
3552 cfg_data->disable_tei_handling = ext_attr->disable_te_ihandling;
3553 cfg_data->bit_reverse_mpeg_outout = ext_attr->bit_reverse_mpeg_outout;
3554 cfg_data->mpeg_start_width = ext_attr->mpeg_start_width;
3555 if (ext_attr->mpeg_output_clock_rate != DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO) {
3556 cfg_data->mpeg_output_clock_rate = ext_attr->mpeg_output_clock_rate;
3557 } else {
3558 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, FEC_OC_DTO_PERIOD__A, &data, 0);
3559 if (rc != 0) {
3560 pr_err("error %d\n", rc);
3561 goto rw_error;
3563 cfg_data->mpeg_output_clock_rate =
3564 (enum drxj_mpeg_output_clock_rate) (data + 1);
3567 return 0;
3568 rw_error:
3569 return -EIO;
3572 /*----------------------------------------------------------------------------*/
3575 * \fn int ctrl_get_cfg_hw_cfg()
3576 * \brief Get HW configuartions.
3577 * \param devmod Pointer to demodulator instance.
3578 * \param cfg_data Pointer to Bool.
3579 * \return int.
3581 * This routine can be used to retreive the current setting of the configuartion
3582 * options that are DRXJ specific and/or added to the requirements at a
3583 * late stage.
3586 static int
3587 ctrl_get_cfg_hw_cfg(struct drx_demod_instance *demod, struct drxj_cfg_hw_cfg *cfg_data)
3589 int rc;
3590 u16 data = 0;
3592 if (cfg_data == NULL)
3593 return -EINVAL;
3595 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA, 0);
3596 if (rc != 0) {
3597 pr_err("error %d\n", rc);
3598 goto rw_error;
3600 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SIO_PDR_OHW_CFG__A, &data, 0);
3601 if (rc != 0) {
3602 pr_err("error %d\n", rc);
3603 goto rw_error;
3605 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
3606 if (rc != 0) {
3607 pr_err("error %d\n", rc);
3608 goto rw_error;
3611 cfg_data->i2c_speed = (enum drxji2c_speed) ((data >> 6) & 0x1);
3612 cfg_data->xtal_freq = (enum drxj_xtal_freq) (data & 0x3);
3614 return 0;
3615 rw_error:
3616 return -EIO;
3618 #endif
3620 /*----------------------------------------------------------------------------*/
3621 /* miscellaneous configuartions - end */
3622 /*----------------------------------------------------------------------------*/
3624 /*----------------------------------------------------------------------------*/
3625 /* UIO Configuration Functions - begin */
3626 /*----------------------------------------------------------------------------*/
3628 * \fn int ctrl_set_uio_cfg()
3629 * \brief Configure modus oprandi UIO.
3630 * \param demod Pointer to demodulator instance.
3631 * \param uio_cfg Pointer to a configuration setting for a certain UIO.
3632 * \return int.
3634 static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg *uio_cfg)
3636 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
3637 int rc;
3639 if ((uio_cfg == NULL) || (demod == NULL))
3640 return -EINVAL;
3642 ext_attr = (struct drxj_data *) demod->my_ext_attr;
3644 /* Write magic word to enable pdr reg write */
3645 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
3646 if (rc != 0) {
3647 pr_err("error %d\n", rc);
3648 goto rw_error;
3650 switch (uio_cfg->uio) {
3651 /*====================================================================*/
3652 case DRX_UIO1:
3653 /* DRX_UIO1: SMA_TX UIO-1 */
3654 if (!ext_attr->has_smatx)
3655 return -EIO;
3656 switch (uio_cfg->mode) {
3657 case DRX_UIO_MODE_FIRMWARE_SMA: /* falltrough */
3658 case DRX_UIO_MODE_FIRMWARE_SAW: /* falltrough */
3659 case DRX_UIO_MODE_READWRITE:
3660 ext_attr->uio_sma_tx_mode = uio_cfg->mode;
3661 break;
3662 case DRX_UIO_MODE_DISABLE:
3663 ext_attr->uio_sma_tx_mode = uio_cfg->mode;
3664 /* pad configuration register is set 0 - input mode */
3665 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, 0, 0);
3666 if (rc != 0) {
3667 pr_err("error %d\n", rc);
3668 goto rw_error;
3670 break;
3671 default:
3672 return -EINVAL;
3673 } /* switch ( uio_cfg->mode ) */
3674 break;
3675 /*====================================================================*/
3676 case DRX_UIO2:
3677 /* DRX_UIO2: SMA_RX UIO-2 */
3678 if (!ext_attr->has_smarx)
3679 return -EIO;
3680 switch (uio_cfg->mode) {
3681 case DRX_UIO_MODE_FIRMWARE0: /* falltrough */
3682 case DRX_UIO_MODE_READWRITE:
3683 ext_attr->uio_sma_rx_mode = uio_cfg->mode;
3684 break;
3685 case DRX_UIO_MODE_DISABLE:
3686 ext_attr->uio_sma_rx_mode = uio_cfg->mode;
3687 /* pad configuration register is set 0 - input mode */
3688 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_SMA_RX_CFG__A, 0, 0);
3689 if (rc != 0) {
3690 pr_err("error %d\n", rc);
3691 goto rw_error;
3693 break;
3694 default:
3695 return -EINVAL;
3696 break;
3697 } /* switch ( uio_cfg->mode ) */
3698 break;
3699 /*====================================================================*/
3700 case DRX_UIO3:
3701 /* DRX_UIO3: GPIO UIO-3 */
3702 if (!ext_attr->has_gpio)
3703 return -EIO;
3704 switch (uio_cfg->mode) {
3705 case DRX_UIO_MODE_FIRMWARE0: /* falltrough */
3706 case DRX_UIO_MODE_READWRITE:
3707 ext_attr->uio_gpio_mode = uio_cfg->mode;
3708 break;
3709 case DRX_UIO_MODE_DISABLE:
3710 ext_attr->uio_gpio_mode = uio_cfg->mode;
3711 /* pad configuration register is set 0 - input mode */
3712 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_GPIO_CFG__A, 0, 0);
3713 if (rc != 0) {
3714 pr_err("error %d\n", rc);
3715 goto rw_error;
3717 break;
3718 default:
3719 return -EINVAL;
3720 break;
3721 } /* switch ( uio_cfg->mode ) */
3722 break;
3723 /*====================================================================*/
3724 case DRX_UIO4:
3725 /* DRX_UIO4: IRQN UIO-4 */
3726 if (!ext_attr->has_irqn)
3727 return -EIO;
3728 switch (uio_cfg->mode) {
3729 case DRX_UIO_MODE_READWRITE:
3730 ext_attr->uio_irqn_mode = uio_cfg->mode;
3731 break;
3732 case DRX_UIO_MODE_DISABLE:
3733 /* pad configuration register is set 0 - input mode */
3734 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_IRQN_CFG__A, 0, 0);
3735 if (rc != 0) {
3736 pr_err("error %d\n", rc);
3737 goto rw_error;
3739 ext_attr->uio_irqn_mode = uio_cfg->mode;
3740 break;
3741 case DRX_UIO_MODE_FIRMWARE0: /* falltrough */
3742 default:
3743 return -EINVAL;
3744 break;
3745 } /* switch ( uio_cfg->mode ) */
3746 break;
3747 /*====================================================================*/
3748 default:
3749 return -EINVAL;
3750 } /* switch ( uio_cfg->uio ) */
3752 /* Write magic word to disable pdr reg write */
3753 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
3754 if (rc != 0) {
3755 pr_err("error %d\n", rc);
3756 goto rw_error;
3759 return 0;
3760 rw_error:
3761 return -EIO;
3764 #if 0
3765 /*============================================================================*/
3767 * \fn int ctrl_getuio_cfg()
3768 * \brief Get modus oprandi UIO.
3769 * \param demod Pointer to demodulator instance.
3770 * \param uio_cfg Pointer to a configuration setting for a certain UIO.
3771 * \return int.
3773 static int ctrl_getuio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg *uio_cfg)
3776 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
3777 enum drxuio_mode *uio_mode[4] = { NULL };
3778 bool *uio_available[4] = { NULL };
3780 ext_attr = demod->my_ext_attr;
3782 uio_mode[DRX_UIO1] = &ext_attr->uio_sma_tx_mode;
3783 uio_mode[DRX_UIO2] = &ext_attr->uio_sma_rx_mode;
3784 uio_mode[DRX_UIO3] = &ext_attr->uio_gpio_mode;
3785 uio_mode[DRX_UIO4] = &ext_attr->uio_irqn_mode;
3787 uio_available[DRX_UIO1] = &ext_attr->has_smatx;
3788 uio_available[DRX_UIO2] = &ext_attr->has_smarx;
3789 uio_available[DRX_UIO3] = &ext_attr->has_gpio;
3790 uio_available[DRX_UIO4] = &ext_attr->has_irqn;
3792 if (uio_cfg == NULL)
3793 return -EINVAL;
3795 if ((uio_cfg->uio > DRX_UIO4) || (uio_cfg->uio < DRX_UIO1))
3796 return -EINVAL;
3798 if (!*uio_available[uio_cfg->uio])
3799 return -EIO;
3801 uio_cfg->mode = *uio_mode[uio_cfg->uio];
3803 return 0;
3805 #endif
3808 * \fn int ctrl_uio_write()
3809 * \brief Write to a UIO.
3810 * \param demod Pointer to demodulator instance.
3811 * \param uio_data Pointer to data container for a certain UIO.
3812 * \return int.
3814 static int
3815 ctrl_uio_write(struct drx_demod_instance *demod, struct drxuio_data *uio_data)
3817 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
3818 int rc;
3819 u16 pin_cfg_value = 0;
3820 u16 value = 0;
3822 if ((uio_data == NULL) || (demod == NULL))
3823 return -EINVAL;
3825 ext_attr = (struct drxj_data *) demod->my_ext_attr;
3827 /* Write magic word to enable pdr reg write */
3828 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
3829 if (rc != 0) {
3830 pr_err("error %d\n", rc);
3831 goto rw_error;
3833 switch (uio_data->uio) {
3834 /*====================================================================*/
3835 case DRX_UIO1:
3836 /* DRX_UIO1: SMA_TX UIO-1 */
3837 if (!ext_attr->has_smatx)
3838 return -EIO;
3839 if ((ext_attr->uio_sma_tx_mode != DRX_UIO_MODE_READWRITE)
3840 && (ext_attr->uio_sma_tx_mode != DRX_UIO_MODE_FIRMWARE_SAW)) {
3841 return -EIO;
3843 pin_cfg_value = 0;
3844 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
3845 pin_cfg_value |= 0x0113;
3846 /* io_pad_cfg_mode output mode is drive always */
3847 /* io_pad_cfg_drive is set to power 2 (23 mA) */
3849 /* write to io pad configuration register - output mode */
3850 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, pin_cfg_value, 0);
3851 if (rc != 0) {
3852 pr_err("error %d\n", rc);
3853 goto rw_error;
3856 /* use corresponding bit in io data output registar */
3857 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, &value, 0);
3858 if (rc != 0) {
3859 pr_err("error %d\n", rc);
3860 goto rw_error;
3862 if (!uio_data->value)
3863 value &= 0x7FFF; /* write zero to 15th bit - 1st UIO */
3864 else
3865 value |= 0x8000; /* write one to 15th bit - 1st UIO */
3867 /* write back to io data output register */
3868 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value, 0);
3869 if (rc != 0) {
3870 pr_err("error %d\n", rc);
3871 goto rw_error;
3873 break;
3874 /*======================================================================*/
3875 case DRX_UIO2:
3876 /* DRX_UIO2: SMA_RX UIO-2 */
3877 if (!ext_attr->has_smarx)
3878 return -EIO;
3879 if (ext_attr->uio_sma_rx_mode != DRX_UIO_MODE_READWRITE)
3880 return -EIO;
3882 pin_cfg_value = 0;
3883 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
3884 pin_cfg_value |= 0x0113;
3885 /* io_pad_cfg_mode output mode is drive always */
3886 /* io_pad_cfg_drive is set to power 2 (23 mA) */
3888 /* write to io pad configuration register - output mode */
3889 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_SMA_RX_CFG__A, pin_cfg_value, 0);
3890 if (rc != 0) {
3891 pr_err("error %d\n", rc);
3892 goto rw_error;
3895 /* use corresponding bit in io data output registar */
3896 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, &value, 0);
3897 if (rc != 0) {
3898 pr_err("error %d\n", rc);
3899 goto rw_error;
3901 if (!uio_data->value)
3902 value &= 0xBFFF; /* write zero to 14th bit - 2nd UIO */
3903 else
3904 value |= 0x4000; /* write one to 14th bit - 2nd UIO */
3906 /* write back to io data output register */
3907 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value, 0);
3908 if (rc != 0) {
3909 pr_err("error %d\n", rc);
3910 goto rw_error;
3912 break;
3913 /*====================================================================*/
3914 case DRX_UIO3:
3915 /* DRX_UIO3: ASEL UIO-3 */
3916 if (!ext_attr->has_gpio)
3917 return -EIO;
3918 if (ext_attr->uio_gpio_mode != DRX_UIO_MODE_READWRITE)
3919 return -EIO;
3921 pin_cfg_value = 0;
3922 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
3923 pin_cfg_value |= 0x0113;
3924 /* io_pad_cfg_mode output mode is drive always */
3925 /* io_pad_cfg_drive is set to power 2 (23 mA) */
3927 /* write to io pad configuration register - output mode */
3928 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_GPIO_CFG__A, pin_cfg_value, 0);
3929 if (rc != 0) {
3930 pr_err("error %d\n", rc);
3931 goto rw_error;
3934 /* use corresponding bit in io data output registar */
3935 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_HI__A, &value, 0);
3936 if (rc != 0) {
3937 pr_err("error %d\n", rc);
3938 goto rw_error;
3940 if (!uio_data->value)
3941 value &= 0xFFFB; /* write zero to 2nd bit - 3rd UIO */
3942 else
3943 value |= 0x0004; /* write one to 2nd bit - 3rd UIO */
3945 /* write back to io data output register */
3946 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_HI__A, value, 0);
3947 if (rc != 0) {
3948 pr_err("error %d\n", rc);
3949 goto rw_error;
3951 break;
3952 /*=====================================================================*/
3953 case DRX_UIO4:
3954 /* DRX_UIO4: IRQN UIO-4 */
3955 if (!ext_attr->has_irqn)
3956 return -EIO;
3958 if (ext_attr->uio_irqn_mode != DRX_UIO_MODE_READWRITE)
3959 return -EIO;
3961 pin_cfg_value = 0;
3962 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
3963 pin_cfg_value |= 0x0113;
3964 /* io_pad_cfg_mode output mode is drive always */
3965 /* io_pad_cfg_drive is set to power 2 (23 mA) */
3967 /* write to io pad configuration register - output mode */
3968 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_IRQN_CFG__A, pin_cfg_value, 0);
3969 if (rc != 0) {
3970 pr_err("error %d\n", rc);
3971 goto rw_error;
3974 /* use corresponding bit in io data output registar */
3975 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, &value, 0);
3976 if (rc != 0) {
3977 pr_err("error %d\n", rc);
3978 goto rw_error;
3980 if (uio_data->value == false)
3981 value &= 0xEFFF; /* write zero to 12th bit - 4th UIO */
3982 else
3983 value |= 0x1000; /* write one to 12th bit - 4th UIO */
3985 /* write back to io data output register */
3986 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value, 0);
3987 if (rc != 0) {
3988 pr_err("error %d\n", rc);
3989 goto rw_error;
3991 break;
3992 /*=====================================================================*/
3993 default:
3994 return -EINVAL;
3995 } /* switch ( uio_data->uio ) */
3997 /* Write magic word to disable pdr reg write */
3998 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
3999 if (rc != 0) {
4000 pr_err("error %d\n", rc);
4001 goto rw_error;
4004 return 0;
4005 rw_error:
4006 return -EIO;
4009 #if 0
4011 *\fn int ctrl_uio_read
4012 *\brief Read from a UIO.
4013 * \param demod Pointer to demodulator instance.
4014 * \param uio_data Pointer to data container for a certain UIO.
4015 * \return int.
4017 static int ctrl_uio_read(struct drx_demod_instance *demod, struct drxuio_data *uio_data)
4019 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
4020 int rc;
4021 u16 pin_cfg_value = 0;
4022 u16 value = 0;
4024 if ((uio_data == NULL) || (demod == NULL))
4025 return -EINVAL;
4027 ext_attr = (struct drxj_data *) demod->my_ext_attr;
4029 /* Write magic word to enable pdr reg write */
4030 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
4031 if (rc != 0) {
4032 pr_err("error %d\n", rc);
4033 goto rw_error;
4035 switch (uio_data->uio) {
4036 /*====================================================================*/
4037 case DRX_UIO1:
4038 /* DRX_UIO1: SMA_TX UIO-1 */
4039 if (!ext_attr->has_smatx)
4040 return -EIO;
4042 if (ext_attr->uio_sma_tx_mode != DRX_UIO_MODE_READWRITE)
4043 return -EIO;
4045 pin_cfg_value = 0;
4046 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
4047 pin_cfg_value |= 0x0110;
4048 /* io_pad_cfg_mode output mode is drive always */
4049 /* io_pad_cfg_drive is set to power 2 (23 mA) */
4051 /* write to io pad configuration register - input mode */
4052 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, pin_cfg_value, 0);
4053 if (rc != 0) {
4054 pr_err("error %d\n", rc);
4055 goto rw_error;
4058 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SIO_PDR_UIO_IN_LO__A, &value, 0);
4059 if (rc != 0) {
4060 pr_err("error %d\n", rc);
4061 goto rw_error;
4063 if ((value & 0x8000) != 0) { /* check 15th bit - 1st UIO */
4064 uio_data->value = true;
4065 } else {
4066 uio_data->value = false;
4068 break;
4069 /*======================================================================*/
4070 case DRX_UIO2:
4071 /* DRX_UIO2: SMA_RX UIO-2 */
4072 if (!ext_attr->has_smarx)
4073 return -EIO;
4075 if (ext_attr->uio_sma_rx_mode != DRX_UIO_MODE_READWRITE)
4076 return -EIO;
4078 pin_cfg_value = 0;
4079 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
4080 pin_cfg_value |= 0x0110;
4081 /* io_pad_cfg_mode output mode is drive always */
4082 /* io_pad_cfg_drive is set to power 2 (23 mA) */
4084 /* write to io pad configuration register - input mode */
4085 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_SMA_RX_CFG__A, pin_cfg_value, 0);
4086 if (rc != 0) {
4087 pr_err("error %d\n", rc);
4088 goto rw_error;
4091 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SIO_PDR_UIO_IN_LO__A, &value, 0);
4092 if (rc != 0) {
4093 pr_err("error %d\n", rc);
4094 goto rw_error;
4097 if ((value & 0x4000) != 0) /* check 14th bit - 2nd UIO */
4098 uio_data->value = true;
4099 else
4100 uio_data->value = false;
4102 break;
4103 /*=====================================================================*/
4104 case DRX_UIO3:
4105 /* DRX_UIO3: GPIO UIO-3 */
4106 if (!ext_attr->has_gpio)
4107 return -EIO;
4109 if (ext_attr->uio_gpio_mode != DRX_UIO_MODE_READWRITE)
4110 return -EIO;
4112 pin_cfg_value = 0;
4113 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
4114 pin_cfg_value |= 0x0110;
4115 /* io_pad_cfg_mode output mode is drive always */
4116 /* io_pad_cfg_drive is set to power 2 (23 mA) */
4118 /* write to io pad configuration register - input mode */
4119 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_GPIO_CFG__A, pin_cfg_value, 0);
4120 if (rc != 0) {
4121 pr_err("error %d\n", rc);
4122 goto rw_error;
4125 /* read io input data registar */
4126 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SIO_PDR_UIO_IN_HI__A, &value, 0);
4127 if (rc != 0) {
4128 pr_err("error %d\n", rc);
4129 goto rw_error;
4131 if ((value & 0x0004) != 0) { /* check 2nd bit - 3rd UIO */
4132 uio_data->value = true;
4133 } else {
4134 uio_data->value = false;
4136 break;
4137 /*=====================================================================*/
4138 case DRX_UIO4:
4139 /* DRX_UIO4: IRQN UIO-4 */
4140 if (!ext_attr->has_irqn)
4141 return -EIO;
4143 if (ext_attr->uio_irqn_mode != DRX_UIO_MODE_READWRITE)
4144 return -EIO;
4146 pin_cfg_value = 0;
4147 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
4148 pin_cfg_value |= 0x0110;
4149 /* io_pad_cfg_mode output mode is drive always */
4150 /* io_pad_cfg_drive is set to power 2 (23 mA) */
4152 /* write to io pad configuration register - input mode */
4153 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_IRQN_CFG__A, pin_cfg_value, 0);
4154 if (rc != 0) {
4155 pr_err("error %d\n", rc);
4156 goto rw_error;
4159 /* read io input data registar */
4160 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SIO_PDR_UIO_IN_LO__A, &value, 0);
4161 if (rc != 0) {
4162 pr_err("error %d\n", rc);
4163 goto rw_error;
4165 if ((value & 0x1000) != 0) /* check 12th bit - 4th UIO */
4166 uio_data->value = true;
4167 else
4168 uio_data->value = false;
4170 break;
4171 /*====================================================================*/
4172 default:
4173 return -EINVAL;
4174 } /* switch ( uio_data->uio ) */
4176 /* Write magic word to disable pdr reg write */
4177 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
4178 if (rc != 0) {
4179 pr_err("error %d\n", rc);
4180 goto rw_error;
4183 return 0;
4184 rw_error:
4185 return -EIO;
4187 #endif
4189 /*---------------------------------------------------------------------------*/
4190 /* UIO Configuration Functions - end */
4191 /*---------------------------------------------------------------------------*/
4193 /*----------------------------------------------------------------------------*/
4194 /* I2C Bridge Functions - begin */
4195 /*----------------------------------------------------------------------------*/
4197 * \fn int ctrl_i2c_bridge()
4198 * \brief Open or close the I2C switch to tuner.
4199 * \param demod Pointer to demodulator instance.
4200 * \param bridge_closed Pointer to bool indication if bridge is closed not.
4201 * \return int.
4204 static int
4205 ctrl_i2c_bridge(struct drx_demod_instance *demod, bool *bridge_closed)
4207 struct drxj_hi_cmd hi_cmd;
4208 u16 result = 0;
4210 /* check arguments */
4211 if (bridge_closed == NULL)
4212 return -EINVAL;
4214 hi_cmd.cmd = SIO_HI_RA_RAM_CMD_BRDCTRL;
4215 hi_cmd.param1 = SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY;
4216 if (*bridge_closed)
4217 hi_cmd.param2 = SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED;
4218 else
4219 hi_cmd.param2 = SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN;
4221 return hi_command(demod->my_i2c_dev_addr, &hi_cmd, &result);
4224 /*----------------------------------------------------------------------------*/
4225 /* I2C Bridge Functions - end */
4226 /*----------------------------------------------------------------------------*/
4228 /*----------------------------------------------------------------------------*/
4229 /* Smart antenna Functions - begin */
4230 /*----------------------------------------------------------------------------*/
4232 * \fn int smart_ant_init()
4233 * \brief Initialize Smart Antenna.
4234 * \param pointer to struct drx_demod_instance.
4235 * \return int.
4238 static int smart_ant_init(struct drx_demod_instance *demod)
4240 struct drxj_data *ext_attr = NULL;
4241 struct i2c_device_addr *dev_addr = NULL;
4242 struct drxuio_cfg uio_cfg = { DRX_UIO1, DRX_UIO_MODE_FIRMWARE_SMA };
4243 int rc;
4244 u16 data = 0;
4246 dev_addr = demod->my_i2c_dev_addr;
4247 ext_attr = (struct drxj_data *) demod->my_ext_attr;
4249 /* Write magic word to enable pdr reg write */
4250 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
4251 if (rc != 0) {
4252 pr_err("error %d\n", rc);
4253 goto rw_error;
4255 /* init smart antenna */
4256 rc = DRXJ_DAP.read_reg16func(dev_addr, SIO_SA_TX_COMMAND__A, &data, 0);
4257 if (rc != 0) {
4258 pr_err("error %d\n", rc);
4259 goto rw_error;
4261 if (ext_attr->smart_ant_inverted) {
4262 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_SA_TX_COMMAND__A, (data | SIO_SA_TX_COMMAND_TX_INVERT__M) | SIO_SA_TX_COMMAND_TX_ENABLE__M, 0);
4263 if (rc != 0) {
4264 pr_err("error %d\n", rc);
4265 goto rw_error;
4267 } else {
4268 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_SA_TX_COMMAND__A, (data & (~SIO_SA_TX_COMMAND_TX_INVERT__M)) | SIO_SA_TX_COMMAND_TX_ENABLE__M, 0);
4269 if (rc != 0) {
4270 pr_err("error %d\n", rc);
4271 goto rw_error;
4275 /* config SMA_TX pin to smart antenna mode */
4276 rc = ctrl_set_uio_cfg(demod, &uio_cfg);
4277 if (rc != 0) {
4278 pr_err("error %d\n", rc);
4279 goto rw_error;
4281 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, 0x13, 0);
4282 if (rc != 0) {
4283 pr_err("error %d\n", rc);
4284 goto rw_error;
4286 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_GPIO_FNC__A, 0x03, 0);
4287 if (rc != 0) {
4288 pr_err("error %d\n", rc);
4289 goto rw_error;
4292 /* Write magic word to disable pdr reg write */
4293 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
4294 if (rc != 0) {
4295 pr_err("error %d\n", rc);
4296 goto rw_error;
4299 return 0;
4300 rw_error:
4301 return -EIO;
4304 #if 0
4306 * \fn int ctrl_set_cfg_smart_ant()
4307 * \brief Set Smart Antenna.
4308 * \param pointer to struct drxj_cfg_smart_ant.
4309 * \return int.
4312 static int
4313 ctrl_set_cfg_smart_ant(struct drx_demod_instance *demod, struct drxj_cfg_smart_ant *smart_ant)
4315 struct drxj_data *ext_attr = NULL;
4316 struct i2c_device_addr *dev_addr = NULL;
4317 int rc;
4318 u32 start_time = 0;
4319 u16 data = 0;
4320 static bool bit_inverted;
4322 dev_addr = demod->my_i2c_dev_addr;
4323 ext_attr = (struct drxj_data *) demod->my_ext_attr;
4325 /* check arguments */
4326 if (smart_ant == NULL)
4327 return -EINVAL;
4329 if (bit_inverted != ext_attr->smart_ant_inverted
4330 || ext_attr->uio_sma_tx_mode != DRX_UIO_MODE_FIRMWARE_SMA) {
4331 rc = smart_ant_init(demod);
4332 if (rc != 0) {
4333 pr_err("error %d\n", rc);
4334 goto rw_error;
4336 bit_inverted = ext_attr->smart_ant_inverted;
4339 /* Write magic word to enable pdr reg write */
4340 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
4341 if (rc != 0) {
4342 pr_err("error %d\n", rc);
4343 goto rw_error;
4346 switch (smart_ant->io) {
4347 case DRXJ_SMT_ANT_OUTPUT:
4348 /* enable Tx if Mode B (input) is supported */
4350 RR16( dev_addr, SIO_SA_TX_COMMAND__A, &data );
4351 WR16( dev_addr, SIO_SA_TX_COMMAND__A, data | SIO_SA_TX_COMMAND_TX_ENABLE__M );
4353 start_time = jiffies_to_msecs(jiffies);
4354 do {
4355 rc = DRXJ_DAP.read_reg16func(dev_addr, SIO_SA_TX_STATUS__A, &data, 0);
4356 if (rc != 0) {
4357 pr_err("error %d\n", rc);
4358 goto rw_error;
4360 } while ((data & SIO_SA_TX_STATUS_BUSY__M) && ((jiffies_to_msecs(jiffies) - start_time) < DRXJ_MAX_WAITTIME));
4362 if (data & SIO_SA_TX_STATUS_BUSY__M)
4363 return -EIO;
4365 /* write to smart antenna configuration register */
4366 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_SA_TX_DATA0__A, 0x9200 | ((smart_ant->ctrl_data & 0x0001) << 8) | ((smart_ant->ctrl_data & 0x0002) << 10) | ((smart_ant->ctrl_data & 0x0004) << 12), 0);
4367 if (rc != 0) {
4368 pr_err("error %d\n", rc);
4369 goto rw_error;
4371 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_SA_TX_DATA1__A, 0x4924 | ((smart_ant->ctrl_data & 0x0008) >> 2) | ((smart_ant->ctrl_data & 0x0010)) | ((smart_ant->ctrl_data & 0x0020) << 2) | ((smart_ant->ctrl_data & 0x0040) << 4) | ((smart_ant->ctrl_data & 0x0080) << 6), 0);
4372 if (rc != 0) {
4373 pr_err("error %d\n", rc);
4374 goto rw_error;
4376 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_SA_TX_DATA2__A, 0x2492 | ((smart_ant->ctrl_data & 0x0100) >> 8) | ((smart_ant->ctrl_data & 0x0200) >> 6) | ((smart_ant->ctrl_data & 0x0400) >> 4) | ((smart_ant->ctrl_data & 0x0800) >> 2) | ((smart_ant->ctrl_data & 0x1000)) | ((smart_ant->ctrl_data & 0x2000) << 2), 0);
4377 if (rc != 0) {
4378 pr_err("error %d\n", rc);
4379 goto rw_error;
4381 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_SA_TX_DATA3__A, 0xff8d, 0);
4382 if (rc != 0) {
4383 pr_err("error %d\n", rc);
4384 goto rw_error;
4387 /* trigger the sending */
4388 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_SA_TX_LENGTH__A, 56, 0);
4389 if (rc != 0) {
4390 pr_err("error %d\n", rc);
4391 goto rw_error;
4394 break;
4395 case DRXJ_SMT_ANT_INPUT:
4396 /* disable Tx if Mode B (input) is supported */
4398 RR16( dev_addr, SIO_SA_TX_COMMAND__A, &data );
4399 WR16( dev_addr, SIO_SA_TX_COMMAND__A, data & (~SIO_SA_TX_COMMAND_TX_ENABLE__M) );
4401 default:
4402 return -EINVAL;
4404 /* Write magic word to enable pdr reg write */
4405 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
4406 if (rc != 0) {
4407 pr_err("error %d\n", rc);
4408 goto rw_error;
4411 return 0;
4412 rw_error:
4413 return -EIO;
4415 #endif
4417 static int scu_command(struct i2c_device_addr *dev_addr, struct drxjscu_cmd *cmd)
4419 int rc;
4420 u32 start_time = 0;
4421 u16 cur_cmd = 0;
4423 /* Check param */
4424 if (cmd == NULL)
4425 return -EINVAL;
4427 /* Wait until SCU command interface is ready to receive command */
4428 rc = DRXJ_DAP.read_reg16func(dev_addr, SCU_RAM_COMMAND__A, &cur_cmd, 0);
4429 if (rc != 0) {
4430 pr_err("error %d\n", rc);
4431 goto rw_error;
4433 if (cur_cmd != DRX_SCU_READY)
4434 return -EIO;
4436 switch (cmd->parameter_len) {
4437 case 5:
4438 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_PARAM_4__A, *(cmd->parameter + 4), 0);
4439 if (rc != 0) {
4440 pr_err("error %d\n", rc);
4441 goto rw_error;
4442 } /* fallthrough */
4443 case 4:
4444 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_PARAM_3__A, *(cmd->parameter + 3), 0);
4445 if (rc != 0) {
4446 pr_err("error %d\n", rc);
4447 goto rw_error;
4448 } /* fallthrough */
4449 case 3:
4450 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_PARAM_2__A, *(cmd->parameter + 2), 0);
4451 if (rc != 0) {
4452 pr_err("error %d\n", rc);
4453 goto rw_error;
4454 } /* fallthrough */
4455 case 2:
4456 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_PARAM_1__A, *(cmd->parameter + 1), 0);
4457 if (rc != 0) {
4458 pr_err("error %d\n", rc);
4459 goto rw_error;
4460 } /* fallthrough */
4461 case 1:
4462 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_PARAM_0__A, *(cmd->parameter + 0), 0);
4463 if (rc != 0) {
4464 pr_err("error %d\n", rc);
4465 goto rw_error;
4466 } /* fallthrough */
4467 case 0:
4468 /* do nothing */
4469 break;
4470 default:
4471 /* this number of parameters is not supported */
4472 return -EIO;
4474 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_COMMAND__A, cmd->command, 0);
4475 if (rc != 0) {
4476 pr_err("error %d\n", rc);
4477 goto rw_error;
4480 /* Wait until SCU has processed command */
4481 start_time = jiffies_to_msecs(jiffies);
4482 do {
4483 rc = DRXJ_DAP.read_reg16func(dev_addr, SCU_RAM_COMMAND__A, &cur_cmd, 0);
4484 if (rc != 0) {
4485 pr_err("error %d\n", rc);
4486 goto rw_error;
4488 } while (!(cur_cmd == DRX_SCU_READY)
4489 && ((jiffies_to_msecs(jiffies) - start_time) < DRXJ_MAX_WAITTIME));
4491 if (cur_cmd != DRX_SCU_READY)
4492 return -EIO;
4494 /* read results */
4495 if ((cmd->result_len > 0) && (cmd->result != NULL)) {
4496 s16 err;
4498 switch (cmd->result_len) {
4499 case 4:
4500 rc = DRXJ_DAP.read_reg16func(dev_addr, SCU_RAM_PARAM_3__A, cmd->result + 3, 0);
4501 if (rc != 0) {
4502 pr_err("error %d\n", rc);
4503 goto rw_error;
4504 } /* fallthrough */
4505 case 3:
4506 rc = DRXJ_DAP.read_reg16func(dev_addr, SCU_RAM_PARAM_2__A, cmd->result + 2, 0);
4507 if (rc != 0) {
4508 pr_err("error %d\n", rc);
4509 goto rw_error;
4510 } /* fallthrough */
4511 case 2:
4512 rc = DRXJ_DAP.read_reg16func(dev_addr, SCU_RAM_PARAM_1__A, cmd->result + 1, 0);
4513 if (rc != 0) {
4514 pr_err("error %d\n", rc);
4515 goto rw_error;
4516 } /* fallthrough */
4517 case 1:
4518 rc = DRXJ_DAP.read_reg16func(dev_addr, SCU_RAM_PARAM_0__A, cmd->result + 0, 0);
4519 if (rc != 0) {
4520 pr_err("error %d\n", rc);
4521 goto rw_error;
4522 } /* fallthrough */
4523 case 0:
4524 /* do nothing */
4525 break;
4526 default:
4527 /* this number of parameters is not supported */
4528 return -EIO;
4531 /* Check if an error was reported by SCU */
4532 err = cmd->result[0];
4534 /* check a few fixed error codes */
4535 if ((err == (s16) SCU_RAM_PARAM_0_RESULT_UNKSTD)
4536 || (err == (s16) SCU_RAM_PARAM_0_RESULT_UNKCMD)
4537 || (err == (s16) SCU_RAM_PARAM_0_RESULT_INVPAR)
4538 || (err == (s16) SCU_RAM_PARAM_0_RESULT_SIZE)
4540 return -EINVAL;
4542 /* here it is assumed that negative means error, and positive no error */
4543 else if (err < 0)
4544 return -EIO;
4545 else
4546 return 0;
4549 return 0;
4551 rw_error:
4552 return -EIO;
4556 * \fn int DRXJ_DAP_SCUAtomicReadWriteBlock()
4557 * \brief Basic access routine for SCU atomic read or write access
4558 * \param dev_addr pointer to i2c dev address
4559 * \param addr destination/source address
4560 * \param datasize size of data buffer in bytes
4561 * \param data pointer to data buffer
4562 * \return int
4563 * \retval 0 Succes
4564 * \retval -EIO Timeout, I2C error, illegal bank
4567 #define ADDR_AT_SCU_SPACE(x) ((x - 0x82E000) * 2)
4568 static
4569 int drxj_dap_scu_atomic_read_write_block(struct i2c_device_addr *dev_addr, u32 addr, u16 datasize, /* max 30 bytes because the limit of SCU parameter */
4570 u8 *data, bool read_flag)
4572 struct drxjscu_cmd scu_cmd;
4573 int rc;
4574 u16 set_param_parameters[15];
4575 u16 cmd_result[15];
4577 /* Parameter check */
4578 if (!data || !dev_addr || (datasize % 2) || ((datasize / 2) > 16))
4579 return -EINVAL;
4581 set_param_parameters[1] = (u16) ADDR_AT_SCU_SPACE(addr);
4582 if (read_flag) { /* read */
4583 set_param_parameters[0] = ((~(0x0080)) & datasize);
4584 scu_cmd.parameter_len = 2;
4585 scu_cmd.result_len = datasize / 2 + 2;
4586 } else {
4587 int i = 0;
4589 set_param_parameters[0] = 0x0080 | datasize;
4590 for (i = 0; i < (datasize / 2); i++) {
4591 set_param_parameters[i + 2] =
4592 (data[2 * i] | (data[(2 * i) + 1] << 8));
4594 scu_cmd.parameter_len = datasize / 2 + 2;
4595 scu_cmd.result_len = 1;
4598 scu_cmd.command =
4599 SCU_RAM_COMMAND_STANDARD_TOP |
4600 SCU_RAM_COMMAND_CMD_AUX_SCU_ATOMIC_ACCESS;
4601 scu_cmd.result = cmd_result;
4602 scu_cmd.parameter = set_param_parameters;
4603 rc = scu_command(dev_addr, &scu_cmd);
4604 if (rc != 0) {
4605 pr_err("error %d\n", rc);
4606 goto rw_error;
4609 if (read_flag) {
4610 int i = 0;
4611 /* read data from buffer */
4612 for (i = 0; i < (datasize / 2); i++) {
4613 data[2 * i] = (u8) (scu_cmd.result[i + 2] & 0xFF);
4614 data[(2 * i) + 1] = (u8) (scu_cmd.result[i + 2] >> 8);
4618 return 0;
4620 rw_error:
4621 return -EIO;
4625 /*============================================================================*/
4628 * \fn int DRXJ_DAP_AtomicReadReg16()
4629 * \brief Atomic read of 16 bits words
4631 static
4632 int drxj_dap_scu_atomic_read_reg16(struct i2c_device_addr *dev_addr,
4633 u32 addr,
4634 u16 *data, u32 flags)
4636 u8 buf[2];
4637 int rc = -EIO;
4638 u16 word = 0;
4640 if (!data)
4641 return -EINVAL;
4643 rc = drxj_dap_scu_atomic_read_write_block(dev_addr, addr, 2, buf, true);
4644 if (rc < 0)
4645 return rc;
4647 word = (u16) (buf[0] + (buf[1] << 8));
4649 *data = word;
4651 return rc;
4654 /*============================================================================*/
4656 * \fn int drxj_dap_scu_atomic_write_reg16()
4657 * \brief Atomic read of 16 bits words
4659 static
4660 int drxj_dap_scu_atomic_write_reg16(struct i2c_device_addr *dev_addr,
4661 u32 addr,
4662 u16 data, u32 flags)
4664 u8 buf[2];
4665 int rc = -EIO;
4667 buf[0] = (u8) (data & 0xff);
4668 buf[1] = (u8) ((data >> 8) & 0xff);
4670 rc = drxj_dap_scu_atomic_read_write_block(dev_addr, addr, 2, buf, false);
4672 return rc;
4675 /* -------------------------------------------------------------------------- */
4677 * \brief Measure result of ADC synchronisation
4678 * \param demod demod instance
4679 * \param count (returned) count
4680 * \return int.
4681 * \retval 0 Success
4682 * \retval -EIO Failure: I2C error
4685 static int adc_sync_measurement(struct drx_demod_instance *demod, u16 *count)
4687 struct i2c_device_addr *dev_addr = NULL;
4688 int rc;
4689 u16 data = 0;
4691 dev_addr = demod->my_i2c_dev_addr;
4693 /* Start measurement */
4694 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_COMM_EXEC__A, IQM_AF_COMM_EXEC_ACTIVE, 0);
4695 if (rc != 0) {
4696 pr_err("error %d\n", rc);
4697 goto rw_error;
4699 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_START_LOCK__A, 1, 0);
4700 if (rc != 0) {
4701 pr_err("error %d\n", rc);
4702 goto rw_error;
4705 /* Wait at least 3*128*(1/sysclk) <<< 1 millisec */
4706 msleep(1);
4708 *count = 0;
4709 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_PHASE0__A, &data, 0);
4710 if (rc != 0) {
4711 pr_err("error %d\n", rc);
4712 goto rw_error;
4714 if (data == 127)
4715 *count = *count + 1;
4716 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_PHASE1__A, &data, 0);
4717 if (rc != 0) {
4718 pr_err("error %d\n", rc);
4719 goto rw_error;
4721 if (data == 127)
4722 *count = *count + 1;
4723 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_PHASE2__A, &data, 0);
4724 if (rc != 0) {
4725 pr_err("error %d\n", rc);
4726 goto rw_error;
4728 if (data == 127)
4729 *count = *count + 1;
4731 return 0;
4732 rw_error:
4733 return -EIO;
4737 * \brief Synchronize analog and digital clock domains
4738 * \param demod demod instance
4739 * \return int.
4740 * \retval 0 Success
4741 * \retval -EIO Failure: I2C error or failure to synchronize
4743 * An IQM reset will also reset the results of this synchronization.
4744 * After an IQM reset this routine needs to be called again.
4748 static int adc_synchronization(struct drx_demod_instance *demod)
4750 struct i2c_device_addr *dev_addr = NULL;
4751 int rc;
4752 u16 count = 0;
4754 dev_addr = demod->my_i2c_dev_addr;
4756 rc = adc_sync_measurement(demod, &count);
4757 if (rc != 0) {
4758 pr_err("error %d\n", rc);
4759 goto rw_error;
4762 if (count == 1) {
4763 /* Try sampling on a diffrent edge */
4764 u16 clk_neg = 0;
4766 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_CLKNEG__A, &clk_neg, 0);
4767 if (rc != 0) {
4768 pr_err("error %d\n", rc);
4769 goto rw_error;
4772 clk_neg ^= IQM_AF_CLKNEG_CLKNEGDATA__M;
4773 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_CLKNEG__A, clk_neg, 0);
4774 if (rc != 0) {
4775 pr_err("error %d\n", rc);
4776 goto rw_error;
4779 rc = adc_sync_measurement(demod, &count);
4780 if (rc != 0) {
4781 pr_err("error %d\n", rc);
4782 goto rw_error;
4786 /* TODO: implement fallback scenarios */
4787 if (count < 2)
4788 return -EIO;
4790 return 0;
4791 rw_error:
4792 return -EIO;
4795 #if 0
4797 * \brief Configure IQM AF registers
4798 * \param demod instance of demodulator.
4799 * \param active
4800 * \return int.
4802 static int iqm_set_af(struct drx_demod_instance *demod, bool active)
4804 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
4805 int rc;
4806 u16 data = 0;
4808 /* Configure IQM */
4809 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_STDBY__A, &data, 0);
4810 if (rc != 0) {
4811 pr_err("error %d\n", rc);
4812 goto rw_error;
4814 if (!active)
4815 data &= ((~IQM_AF_STDBY_STDBY_ADC_A2_ACTIVE) & (~IQM_AF_STDBY_STDBY_AMP_A2_ACTIVE) & (~IQM_AF_STDBY_STDBY_PD_A2_ACTIVE) & (~IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE) & (~IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE));
4816 else
4817 data |= (IQM_AF_STDBY_STDBY_ADC_A2_ACTIVE | IQM_AF_STDBY_STDBY_AMP_A2_ACTIVE | IQM_AF_STDBY_STDBY_PD_A2_ACTIVE | IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE | IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE);
4818 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_STDBY__A, data, 0);
4819 if (rc != 0) {
4820 pr_err("error %d\n", rc);
4821 goto rw_error;
4824 return 0;
4825 rw_error:
4826 return -EIO;
4829 /* -------------------------------------------------------------------------- */
4830 static int
4831 ctrl_set_cfg_atv_output(struct drx_demod_instance *demod, struct drxj_cfg_atv_output *output_cfg);
4834 * \brief set configuration of pin-safe mode
4835 * \param demod instance of demodulator.
4836 * \param enable boolean; true: activate pin-safe mode, false: de-activate p.s.m.
4837 * \return int.
4839 static int
4840 ctrl_set_cfg_pdr_safe_mode(struct drx_demod_instance *demod, bool *enable)
4842 struct drxj_data *ext_attr = NULL;
4843 struct i2c_device_addr *dev_addr = NULL;
4844 int rc;
4846 if (enable == NULL)
4847 return -EINVAL;
4849 dev_addr = demod->my_i2c_dev_addr;
4850 ext_attr = (struct drxj_data *) demod->my_ext_attr;
4852 /* Write magic word to enable pdr reg write */
4853 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
4854 if (rc != 0) {
4855 pr_err("error %d\n", rc);
4856 goto rw_error;
4859 if (*enable) {
4860 bool bridge_enabled = false;
4862 /* MPEG pins to input */
4863 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MSTRT_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4864 if (rc != 0) {
4865 pr_err("error %d\n", rc);
4866 goto rw_error;
4868 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MERR_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4869 if (rc != 0) {
4870 pr_err("error %d\n", rc);
4871 goto rw_error;
4873 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MCLK_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4874 if (rc != 0) {
4875 pr_err("error %d\n", rc);
4876 goto rw_error;
4878 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MVAL_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4879 if (rc != 0) {
4880 pr_err("error %d\n", rc);
4881 goto rw_error;
4883 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD0_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4884 if (rc != 0) {
4885 pr_err("error %d\n", rc);
4886 goto rw_error;
4888 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD1_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4889 if (rc != 0) {
4890 pr_err("error %d\n", rc);
4891 goto rw_error;
4893 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD2_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4894 if (rc != 0) {
4895 pr_err("error %d\n", rc);
4896 goto rw_error;
4898 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD3_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4899 if (rc != 0) {
4900 pr_err("error %d\n", rc);
4901 goto rw_error;
4903 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD4_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4904 if (rc != 0) {
4905 pr_err("error %d\n", rc);
4906 goto rw_error;
4908 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD5_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4909 if (rc != 0) {
4910 pr_err("error %d\n", rc);
4911 goto rw_error;
4913 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD6_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4914 if (rc != 0) {
4915 pr_err("error %d\n", rc);
4916 goto rw_error;
4918 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_MD7_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4919 if (rc != 0) {
4920 pr_err("error %d\n", rc);
4921 goto rw_error;
4924 /* PD_I2C_SDA2 Bridge off, Port2 Inactive
4925 PD_I2C_SCL2 Bridge off, Port2 Inactive */
4926 rc = ctrl_i2c_bridge(demod, &bridge_enabled);
4927 if (rc != 0) {
4928 pr_err("error %d\n", rc);
4929 goto rw_error;
4931 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_I2C_SDA2_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4932 if (rc != 0) {
4933 pr_err("error %d\n", rc);
4934 goto rw_error;
4936 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_I2C_SCL2_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4937 if (rc != 0) {
4938 pr_err("error %d\n", rc);
4939 goto rw_error;
4942 /* PD_GPIO Store and set to input
4943 PD_VSYNC Store and set to input
4944 PD_SMA_RX Store and set to input
4945 PD_SMA_TX Store and set to input */
4946 rc = DRXJ_DAP.read_reg16func(dev_addr, SIO_PDR_GPIO_CFG__A, &ext_attr->pdr_safe_restore_val_gpio, 0);
4947 if (rc != 0) {
4948 pr_err("error %d\n", rc);
4949 goto rw_error;
4951 rc = DRXJ_DAP.read_reg16func(dev_addr, SIO_PDR_VSYNC_CFG__A, &ext_attr->pdr_safe_restore_val_v_sync, 0);
4952 if (rc != 0) {
4953 pr_err("error %d\n", rc);
4954 goto rw_error;
4956 rc = DRXJ_DAP.read_reg16func(dev_addr, SIO_PDR_SMA_RX_CFG__A, &ext_attr->pdr_safe_restore_val_sma_rx, 0);
4957 if (rc != 0) {
4958 pr_err("error %d\n", rc);
4959 goto rw_error;
4961 rc = DRXJ_DAP.read_reg16func(dev_addr, SIO_PDR_SMA_TX_CFG__A, &ext_attr->pdr_safe_restore_val_sma_tx, 0);
4962 if (rc != 0) {
4963 pr_err("error %d\n", rc);
4964 goto rw_error;
4966 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_GPIO_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4967 if (rc != 0) {
4968 pr_err("error %d\n", rc);
4969 goto rw_error;
4971 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_VSYNC_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4972 if (rc != 0) {
4973 pr_err("error %d\n", rc);
4974 goto rw_error;
4976 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_SMA_RX_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4977 if (rc != 0) {
4978 pr_err("error %d\n", rc);
4979 goto rw_error;
4981 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_SMA_TX_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
4982 if (rc != 0) {
4983 pr_err("error %d\n", rc);
4984 goto rw_error;
4987 /* PD_RF_AGC Analog DAC outputs, cannot be set to input or tristate!
4988 PD_IF_AGC Analog DAC outputs, cannot be set to input or tristate! */
4989 rc = iqm_set_af(demod, false);
4990 if (rc != 0) {
4991 pr_err("error %d\n", rc);
4992 goto rw_error;
4995 /* PD_CVBS Analog DAC output, standby mode
4996 PD_SIF Analog DAC output, standby mode */
4997 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_STDBY__A, (ATV_TOP_STDBY_SIF_STDBY_STANDBY & (~ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE)), 0);
4998 if (rc != 0) {
4999 pr_err("error %d\n", rc);
5000 goto rw_error;
5003 /* PD_I2S_CL Input
5004 PD_I2S_DA Input
5005 PD_I2S_WS Input */
5006 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_I2S_CL_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
5007 if (rc != 0) {
5008 pr_err("error %d\n", rc);
5009 goto rw_error;
5011 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_I2S_DA_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
5012 if (rc != 0) {
5013 pr_err("error %d\n", rc);
5014 goto rw_error;
5016 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_I2S_WS_CFG__A, DRXJ_PIN_SAFE_MODE, 0);
5017 if (rc != 0) {
5018 pr_err("error %d\n", rc);
5019 goto rw_error;
5021 } else {
5022 /* No need to restore MPEG pins;
5023 is done in SetStandard/SetChannel */
5025 /* PD_I2C_SDA2 Port2 active
5026 PD_I2C_SCL2 Port2 active */
5027 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_I2C_SDA2_CFG__A, SIO_PDR_I2C_SDA2_CFG__PRE, 0);
5028 if (rc != 0) {
5029 pr_err("error %d\n", rc);
5030 goto rw_error;
5032 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_I2C_SCL2_CFG__A, SIO_PDR_I2C_SCL2_CFG__PRE, 0);
5033 if (rc != 0) {
5034 pr_err("error %d\n", rc);
5035 goto rw_error;
5038 /* PD_GPIO Restore
5039 PD_VSYNC Restore
5040 PD_SMA_RX Restore
5041 PD_SMA_TX Restore */
5042 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_GPIO_CFG__A, ext_attr->pdr_safe_restore_val_gpio, 0);
5043 if (rc != 0) {
5044 pr_err("error %d\n", rc);
5045 goto rw_error;
5047 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_VSYNC_CFG__A, ext_attr->pdr_safe_restore_val_v_sync, 0);
5048 if (rc != 0) {
5049 pr_err("error %d\n", rc);
5050 goto rw_error;
5052 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_SMA_RX_CFG__A, ext_attr->pdr_safe_restore_val_sma_rx, 0);
5053 if (rc != 0) {
5054 pr_err("error %d\n", rc);
5055 goto rw_error;
5057 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_SMA_TX_CFG__A, ext_attr->pdr_safe_restore_val_sma_tx, 0);
5058 if (rc != 0) {
5059 pr_err("error %d\n", rc);
5060 goto rw_error;
5063 /* PD_RF_AGC, PD_IF_AGC
5064 No need to restore; will be restored in SetStandard/SetChannel */
5066 /* PD_CVBS, PD_SIF
5067 No need to restore; will be restored in SetStandard/SetChannel */
5069 /* PD_I2S_CL, PD_I2S_DA, PD_I2S_WS
5070 Should be restored via DRX_CTRL_SET_AUD */
5073 /* Write magic word to disable pdr reg write */
5074 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
5075 if (rc != 0) {
5076 pr_err("error %d\n", rc);
5077 goto rw_error;
5079 ext_attr->pdr_safe_mode = *enable;
5081 return 0;
5083 rw_error:
5084 return -EIO;
5087 /* -------------------------------------------------------------------------- */
5090 * \brief get configuration of pin-safe mode
5091 * \param demod instance of demodulator.
5092 * \param enable boolean indicating whether pin-safe mode is active
5093 * \return int.
5095 static int
5096 ctrl_get_cfg_pdr_safe_mode(struct drx_demod_instance *demod, bool *enabled)
5098 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
5100 if (enabled == NULL)
5101 return -EINVAL;
5103 ext_attr = (struct drxj_data *) demod->my_ext_attr;
5104 *enabled = ext_attr->pdr_safe_mode;
5106 return 0;
5108 #endif
5110 /*============================================================================*/
5111 /*== END AUXILIARY FUNCTIONS ==*/
5112 /*============================================================================*/
5114 /*============================================================================*/
5115 /*============================================================================*/
5116 /*== 8VSB & QAM COMMON DATAPATH FUNCTIONS ==*/
5117 /*============================================================================*/
5118 /*============================================================================*/
5120 * \fn int init_agc ()
5121 * \brief Initialize AGC for all standards.
5122 * \param demod instance of demodulator.
5123 * \param channel pointer to channel data.
5124 * \return int.
5126 static int init_agc(struct drx_demod_instance *demod)
5128 struct i2c_device_addr *dev_addr = NULL;
5129 struct drx_common_attr *common_attr = NULL;
5130 struct drxj_data *ext_attr = NULL;
5131 struct drxj_cfg_agc *p_agc_rf_settings = NULL;
5132 struct drxj_cfg_agc *p_agc_if_settings = NULL;
5133 int rc;
5134 u16 ingain_tgt_max = 0;
5135 u16 clp_dir_to = 0;
5136 u16 sns_sum_max = 0;
5137 u16 clp_sum_max = 0;
5138 u16 sns_dir_to = 0;
5139 u16 ki_innergain_min = 0;
5140 u16 agc_ki = 0;
5141 u16 ki_max = 0;
5142 u16 if_iaccu_hi_tgt_min = 0;
5143 u16 data = 0;
5144 u16 agc_ki_dgain = 0;
5145 u16 ki_min = 0;
5146 u16 clp_ctrl_mode = 0;
5147 u16 agc_rf = 0;
5148 u16 agc_if = 0;
5150 dev_addr = demod->my_i2c_dev_addr;
5151 common_attr = (struct drx_common_attr *) demod->my_common_attr;
5152 ext_attr = (struct drxj_data *) demod->my_ext_attr;
5154 switch (ext_attr->standard) {
5155 case DRX_STANDARD_8VSB:
5156 clp_sum_max = 1023;
5157 clp_dir_to = (u16) (-9);
5158 sns_sum_max = 1023;
5159 sns_dir_to = (u16) (-9);
5160 ki_innergain_min = (u16) (-32768);
5161 ki_max = 0x032C;
5162 agc_ki_dgain = 0xC;
5163 if_iaccu_hi_tgt_min = 2047;
5164 ki_min = 0x0117;
5165 ingain_tgt_max = 16383;
5166 clp_ctrl_mode = 0;
5167 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff, 0);
5168 if (rc != 0) {
5169 pr_err("error %d\n", rc);
5170 goto rw_error;
5172 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0, 0);
5173 if (rc != 0) {
5174 pr_err("error %d\n", rc);
5175 goto rw_error;
5177 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_CLP_SUM__A, 0, 0);
5178 if (rc != 0) {
5179 pr_err("error %d\n", rc);
5180 goto rw_error;
5182 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_CLP_CYCCNT__A, 0, 0);
5183 if (rc != 0) {
5184 pr_err("error %d\n", rc);
5185 goto rw_error;
5187 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_CLP_DIR_WD__A, 0, 0);
5188 if (rc != 0) {
5189 pr_err("error %d\n", rc);
5190 goto rw_error;
5192 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_CLP_DIR_STP__A, 1, 0);
5193 if (rc != 0) {
5194 pr_err("error %d\n", rc);
5195 goto rw_error;
5197 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_SNS_SUM__A, 0, 0);
5198 if (rc != 0) {
5199 pr_err("error %d\n", rc);
5200 goto rw_error;
5202 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_SNS_CYCCNT__A, 0, 0);
5203 if (rc != 0) {
5204 pr_err("error %d\n", rc);
5205 goto rw_error;
5207 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_SNS_DIR_WD__A, 0, 0);
5208 if (rc != 0) {
5209 pr_err("error %d\n", rc);
5210 goto rw_error;
5212 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_SNS_DIR_STP__A, 1, 0);
5213 if (rc != 0) {
5214 pr_err("error %d\n", rc);
5215 goto rw_error;
5217 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_INGAIN__A, 1024, 0);
5218 if (rc != 0) {
5219 pr_err("error %d\n", rc);
5220 goto rw_error;
5222 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_VSB_AGC_POW_TGT__A, 22600, 0);
5223 if (rc != 0) {
5224 pr_err("error %d\n", rc);
5225 goto rw_error;
5227 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, 13200, 0);
5228 if (rc != 0) {
5229 pr_err("error %d\n", rc);
5230 goto rw_error;
5232 p_agc_if_settings = &(ext_attr->vsb_if_agc_cfg);
5233 p_agc_rf_settings = &(ext_attr->vsb_rf_agc_cfg);
5234 break;
5235 #ifndef DRXJ_VSB_ONLY
5236 case DRX_STANDARD_ITU_A:
5237 case DRX_STANDARD_ITU_C:
5238 case DRX_STANDARD_ITU_B:
5239 ingain_tgt_max = 5119;
5240 clp_sum_max = 1023;
5241 clp_dir_to = (u16) (-5);
5242 sns_sum_max = 127;
5243 sns_dir_to = (u16) (-3);
5244 ki_innergain_min = 0;
5245 ki_max = 0x0657;
5246 if_iaccu_hi_tgt_min = 2047;
5247 agc_ki_dgain = 0x7;
5248 ki_min = 0x0117;
5249 clp_ctrl_mode = 0;
5250 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff, 0);
5251 if (rc != 0) {
5252 pr_err("error %d\n", rc);
5253 goto rw_error;
5255 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0, 0);
5256 if (rc != 0) {
5257 pr_err("error %d\n", rc);
5258 goto rw_error;
5260 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_CLP_SUM__A, 0, 0);
5261 if (rc != 0) {
5262 pr_err("error %d\n", rc);
5263 goto rw_error;
5265 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_CLP_CYCCNT__A, 0, 0);
5266 if (rc != 0) {
5267 pr_err("error %d\n", rc);
5268 goto rw_error;
5270 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_CLP_DIR_WD__A, 0, 0);
5271 if (rc != 0) {
5272 pr_err("error %d\n", rc);
5273 goto rw_error;
5275 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_CLP_DIR_STP__A, 1, 0);
5276 if (rc != 0) {
5277 pr_err("error %d\n", rc);
5278 goto rw_error;
5280 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_SNS_SUM__A, 0, 0);
5281 if (rc != 0) {
5282 pr_err("error %d\n", rc);
5283 goto rw_error;
5285 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_SNS_CYCCNT__A, 0, 0);
5286 if (rc != 0) {
5287 pr_err("error %d\n", rc);
5288 goto rw_error;
5290 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_SNS_DIR_WD__A, 0, 0);
5291 if (rc != 0) {
5292 pr_err("error %d\n", rc);
5293 goto rw_error;
5295 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_SNS_DIR_STP__A, 1, 0);
5296 if (rc != 0) {
5297 pr_err("error %d\n", rc);
5298 goto rw_error;
5300 p_agc_if_settings = &(ext_attr->qam_if_agc_cfg);
5301 p_agc_rf_settings = &(ext_attr->qam_rf_agc_cfg);
5302 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, p_agc_if_settings->top, 0);
5303 if (rc != 0) {
5304 pr_err("error %d\n", rc);
5305 goto rw_error;
5308 rc = DRXJ_DAP.read_reg16func(dev_addr, SCU_RAM_AGC_KI__A, &agc_ki, 0);
5309 if (rc != 0) {
5310 pr_err("error %d\n", rc);
5311 goto rw_error;
5313 agc_ki &= 0xf000;
5314 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_KI__A, agc_ki, 0);
5315 if (rc != 0) {
5316 pr_err("error %d\n", rc);
5317 goto rw_error;
5319 break;
5320 #endif
5321 #if 0
5322 case DRX_STANDARD_FM:
5323 clp_sum_max = 1023;
5324 sns_sum_max = 1023;
5325 ki_innergain_min = (u16) (-32768);
5326 if_iaccu_hi_tgt_min = 2047;
5327 agc_ki_dgain = 0x7;
5328 ki_min = 0x0225;
5329 ki_max = 0x0547;
5330 clp_dir_to = (u16) (-9);
5331 sns_dir_to = (u16) (-9);
5332 ingain_tgt_max = 9000;
5333 clp_ctrl_mode = 1;
5334 p_agc_if_settings = &(ext_attr->atv_if_agc_cfg);
5335 p_agc_rf_settings = &(ext_attr->atv_rf_agc_cfg);
5336 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, p_agc_if_settings->top, 0);
5337 if (rc != 0) {
5338 pr_err("error %d\n", rc);
5339 goto rw_error;
5341 break;
5342 case DRX_STANDARD_NTSC:
5343 case DRX_STANDARD_PAL_SECAM_BG:
5344 case DRX_STANDARD_PAL_SECAM_DK:
5345 case DRX_STANDARD_PAL_SECAM_I:
5346 clp_sum_max = 1023;
5347 sns_sum_max = 1023;
5348 ki_innergain_min = (u16) (-32768);
5349 if_iaccu_hi_tgt_min = 2047;
5350 agc_ki_dgain = 0x7;
5351 ki_min = 0x0225;
5352 ki_max = 0x0547;
5353 clp_dir_to = (u16) (-9);
5354 ingain_tgt_max = 9000;
5355 p_agc_if_settings = &(ext_attr->atv_if_agc_cfg);
5356 p_agc_rf_settings = &(ext_attr->atv_rf_agc_cfg);
5357 sns_dir_to = (u16) (-9);
5358 clp_ctrl_mode = 1;
5359 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, p_agc_if_settings->top, 0);
5360 if (rc != 0) {
5361 pr_err("error %d\n", rc);
5362 goto rw_error;
5364 break;
5365 case DRX_STANDARD_PAL_SECAM_L:
5366 case DRX_STANDARD_PAL_SECAM_LP:
5367 clp_sum_max = 1023;
5368 sns_sum_max = 1023;
5369 ki_innergain_min = (u16) (-32768);
5370 if_iaccu_hi_tgt_min = 2047;
5371 agc_ki_dgain = 0x7;
5372 ki_min = 0x0225;
5373 ki_max = 0x0547;
5374 clp_dir_to = (u16) (-9);
5375 sns_dir_to = (u16) (-9);
5376 ingain_tgt_max = 9000;
5377 clp_ctrl_mode = 1;
5378 p_agc_if_settings = &(ext_attr->atv_if_agc_cfg);
5379 p_agc_rf_settings = &(ext_attr->atv_rf_agc_cfg);
5380 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, p_agc_if_settings->top, 0);
5381 if (rc != 0) {
5382 pr_err("error %d\n", rc);
5383 goto rw_error;
5385 break;
5386 #endif
5387 default:
5388 return -EINVAL;
5391 /* for new AGC interface */
5392 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_INGAIN_TGT_MIN__A, p_agc_if_settings->top, 0);
5393 if (rc != 0) {
5394 pr_err("error %d\n", rc);
5395 goto rw_error;
5397 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_INGAIN__A, p_agc_if_settings->top, 0);
5398 if (rc != 0) {
5399 pr_err("error %d\n", rc);
5400 goto rw_error;
5401 } /* Gain fed from inner to outer AGC */
5402 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingain_tgt_max, 0);
5403 if (rc != 0) {
5404 pr_err("error %d\n", rc);
5405 goto rw_error;
5407 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, if_iaccu_hi_tgt_min, 0);
5408 if (rc != 0) {
5409 pr_err("error %d\n", rc);
5410 goto rw_error;
5412 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_IF_IACCU_HI__A, 0, 0);
5413 if (rc != 0) {
5414 pr_err("error %d\n", rc);
5415 goto rw_error;
5416 } /* set to p_agc_settings->top before */
5417 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_IF_IACCU_LO__A, 0, 0);
5418 if (rc != 0) {
5419 pr_err("error %d\n", rc);
5420 goto rw_error;
5422 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_RF_IACCU_HI__A, 0, 0);
5423 if (rc != 0) {
5424 pr_err("error %d\n", rc);
5425 goto rw_error;
5427 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_RF_IACCU_LO__A, 0, 0);
5428 if (rc != 0) {
5429 pr_err("error %d\n", rc);
5430 goto rw_error;
5432 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_RF_MAX__A, 32767, 0);
5433 if (rc != 0) {
5434 pr_err("error %d\n", rc);
5435 goto rw_error;
5437 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_CLP_SUM_MAX__A, clp_sum_max, 0);
5438 if (rc != 0) {
5439 pr_err("error %d\n", rc);
5440 goto rw_error;
5442 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_SNS_SUM_MAX__A, sns_sum_max, 0);
5443 if (rc != 0) {
5444 pr_err("error %d\n", rc);
5445 goto rw_error;
5447 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, ki_innergain_min, 0);
5448 if (rc != 0) {
5449 pr_err("error %d\n", rc);
5450 goto rw_error;
5452 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_FAST_SNS_CTRL_DELAY__A, 50, 0);
5453 if (rc != 0) {
5454 pr_err("error %d\n", rc);
5455 goto rw_error;
5457 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_KI_CYCLEN__A, 500, 0);
5458 if (rc != 0) {
5459 pr_err("error %d\n", rc);
5460 goto rw_error;
5462 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_SNS_CYCLEN__A, 500, 0);
5463 if (rc != 0) {
5464 pr_err("error %d\n", rc);
5465 goto rw_error;
5467 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_KI_MAXMINGAIN_TH__A, 20, 0);
5468 if (rc != 0) {
5469 pr_err("error %d\n", rc);
5470 goto rw_error;
5472 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_KI_MIN__A, ki_min, 0);
5473 if (rc != 0) {
5474 pr_err("error %d\n", rc);
5475 goto rw_error;
5477 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_KI_MAX__A, ki_max, 0);
5478 if (rc != 0) {
5479 pr_err("error %d\n", rc);
5480 goto rw_error;
5482 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_KI_RED__A, 0, 0);
5483 if (rc != 0) {
5484 pr_err("error %d\n", rc);
5485 goto rw_error;
5487 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_CLP_SUM_MIN__A, 8, 0);
5488 if (rc != 0) {
5489 pr_err("error %d\n", rc);
5490 goto rw_error;
5492 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_CLP_CYCLEN__A, 500, 0);
5493 if (rc != 0) {
5494 pr_err("error %d\n", rc);
5495 goto rw_error;
5497 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_CLP_DIR_TO__A, clp_dir_to, 0);
5498 if (rc != 0) {
5499 pr_err("error %d\n", rc);
5500 goto rw_error;
5502 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_SNS_SUM_MIN__A, 8, 0);
5503 if (rc != 0) {
5504 pr_err("error %d\n", rc);
5505 goto rw_error;
5507 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_SNS_DIR_TO__A, sns_dir_to, 0);
5508 if (rc != 0) {
5509 pr_err("error %d\n", rc);
5510 goto rw_error;
5512 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, 50, 0);
5513 if (rc != 0) {
5514 pr_err("error %d\n", rc);
5515 goto rw_error;
5517 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_CLP_CTRL_MODE__A, clp_ctrl_mode, 0);
5518 if (rc != 0) {
5519 pr_err("error %d\n", rc);
5520 goto rw_error;
5523 agc_rf = 0x800 + p_agc_rf_settings->cut_off_current;
5524 if (common_attr->tuner_rf_agc_pol == true)
5525 agc_rf = 0x87ff - agc_rf;
5527 agc_if = 0x800;
5528 if (common_attr->tuner_if_agc_pol == true)
5529 agc_rf = 0x87ff - agc_rf;
5531 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_AGC_RF__A, agc_rf, 0);
5532 if (rc != 0) {
5533 pr_err("error %d\n", rc);
5534 goto rw_error;
5536 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_AGC_IF__A, agc_if, 0);
5537 if (rc != 0) {
5538 pr_err("error %d\n", rc);
5539 goto rw_error;
5542 /* Set/restore Ki DGAIN factor */
5543 rc = DRXJ_DAP.read_reg16func(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
5544 if (rc != 0) {
5545 pr_err("error %d\n", rc);
5546 goto rw_error;
5548 data &= ~SCU_RAM_AGC_KI_DGAIN__M;
5549 data |= (agc_ki_dgain << SCU_RAM_AGC_KI_DGAIN__B);
5550 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
5551 if (rc != 0) {
5552 pr_err("error %d\n", rc);
5553 goto rw_error;
5556 return 0;
5557 rw_error:
5558 return -EIO;
5562 * \fn int set_frequency ()
5563 * \brief Set frequency shift.
5564 * \param demod instance of demodulator.
5565 * \param channel pointer to channel data.
5566 * \param tuner_freq_offset residual frequency from tuner.
5567 * \return int.
5569 static int
5570 set_frequency(struct drx_demod_instance *demod,
5571 struct drx_channel *channel, s32 tuner_freq_offset)
5573 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
5574 struct drxj_data *ext_attr = demod->my_ext_attr;
5575 int rc;
5576 s32 sampling_frequency = 0;
5577 s32 frequency_shift = 0;
5578 s32 if_freq_actual = 0;
5579 s32 rf_freq_residual = -1 * tuner_freq_offset;
5580 s32 adc_freq = 0;
5581 s32 intermediate_freq = 0;
5582 u32 iqm_fs_rate_ofs = 0;
5583 bool adc_flip = true;
5584 bool select_pos_image = false;
5585 bool rf_mirror;
5586 bool tuner_mirror;
5587 bool image_to_select = true;
5588 s32 fm_frequency_shift = 0;
5590 rf_mirror = (ext_attr->mirror == DRX_MIRROR_YES) ? true : false;
5591 tuner_mirror = demod->my_common_attr->mirror_freq_spect ? false : true;
5593 Program frequency shifter
5594 No need to account for mirroring on RF
5596 switch (ext_attr->standard) {
5597 case DRX_STANDARD_ITU_A: /* fallthrough */
5598 case DRX_STANDARD_ITU_C: /* fallthrough */
5599 case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
5600 case DRX_STANDARD_8VSB:
5601 select_pos_image = true;
5602 break;
5603 case DRX_STANDARD_FM:
5604 /* After IQM FS sound carrier must appear at 4 Mhz in spect.
5605 Sound carrier is already 3Mhz above centre frequency due
5606 to tuner setting so now add an extra shift of 1MHz... */
5607 fm_frequency_shift = 1000;
5608 case DRX_STANDARD_ITU_B: /* fallthrough */
5609 case DRX_STANDARD_NTSC: /* fallthrough */
5610 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
5611 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
5612 case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
5613 case DRX_STANDARD_PAL_SECAM_L:
5614 select_pos_image = false;
5615 break;
5616 default:
5617 return -EINVAL;
5619 intermediate_freq = demod->my_common_attr->intermediate_freq;
5620 sampling_frequency = demod->my_common_attr->sys_clock_freq / 3;
5621 if (tuner_mirror)
5622 if_freq_actual = intermediate_freq + rf_freq_residual + fm_frequency_shift;
5623 else
5624 if_freq_actual = intermediate_freq - rf_freq_residual - fm_frequency_shift;
5625 if (if_freq_actual > sampling_frequency / 2) {
5626 /* adc mirrors */
5627 adc_freq = sampling_frequency - if_freq_actual;
5628 adc_flip = true;
5629 } else {
5630 /* adc doesn't mirror */
5631 adc_freq = if_freq_actual;
5632 adc_flip = false;
5635 frequency_shift = adc_freq;
5636 image_to_select =
5637 (bool) (rf_mirror ^ tuner_mirror ^ adc_flip ^ select_pos_image);
5638 iqm_fs_rate_ofs = frac28(frequency_shift, sampling_frequency);
5640 if (image_to_select)
5641 iqm_fs_rate_ofs = ~iqm_fs_rate_ofs + 1;
5643 /* Program frequency shifter with tuner offset compensation */
5644 /* frequency_shift += tuner_freq_offset; TODO */
5645 rc = DRXJ_DAP.write_reg32func(dev_addr, IQM_FS_RATE_OFS_LO__A, iqm_fs_rate_ofs, 0);
5646 if (rc != 0) {
5647 pr_err("error %d\n", rc);
5648 goto rw_error;
5650 ext_attr->iqm_fs_rate_ofs = iqm_fs_rate_ofs;
5651 ext_attr->pos_image = (bool) (rf_mirror ^ tuner_mirror ^ select_pos_image);
5653 return 0;
5654 rw_error:
5655 return -EIO;
5658 #if 0
5660 * \fn int get_sig_strength()
5661 * \brief Retrieve signal strength for VSB and QAM.
5662 * \param demod Pointer to demod instance
5663 * \param u16-t Pointer to signal strength data; range 0, .. , 100.
5664 * \return int.
5665 * \retval 0 sig_strength contains valid data.
5666 * \retval -EINVAL sig_strength is NULL.
5667 * \retval -EIO Erroneous data, sig_strength contains invalid data.
5669 #define DRXJ_AGC_TOP 0x2800
5670 #define DRXJ_AGC_SNS 0x1600
5671 #define DRXJ_RFAGC_MAX 0x3fff
5672 #define DRXJ_RFAGC_MIN 0x800
5674 static int get_sig_strength(struct drx_demod_instance *demod, u16 *sig_strength)
5676 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
5677 int rc;
5678 u16 rf_gain = 0;
5679 u16 if_gain = 0;
5680 u16 if_agc_sns = 0;
5681 u16 if_agc_top = 0;
5682 u16 rf_agc_max = 0;
5683 u16 rf_agc_min = 0;
5685 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_AGC_IF__A, &if_gain, 0);
5686 if (rc != 0) {
5687 pr_err("error %d\n", rc);
5688 goto rw_error;
5690 if_gain &= IQM_AF_AGC_IF__M;
5691 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_AGC_RF__A, &rf_gain, 0);
5692 if (rc != 0) {
5693 pr_err("error %d\n", rc);
5694 goto rw_error;
5696 rf_gain &= IQM_AF_AGC_RF__M;
5698 if_agc_sns = DRXJ_AGC_SNS;
5699 if_agc_top = DRXJ_AGC_TOP;
5700 rf_agc_max = DRXJ_RFAGC_MAX;
5701 rf_agc_min = DRXJ_RFAGC_MIN;
5703 if (if_gain > if_agc_top) {
5704 if (rf_gain > rf_agc_max)
5705 *sig_strength = 100;
5706 else if (rf_gain > rf_agc_min) {
5707 if (rf_agc_max == rf_agc_min) {
5708 pr_err("error: rf_agc_max == rf_agc_min\n");
5709 return -EIO;
5711 *sig_strength =
5712 75 + 25 * (rf_gain - rf_agc_min) / (rf_agc_max -
5713 rf_agc_min);
5714 } else
5715 *sig_strength = 75;
5716 } else if (if_gain > if_agc_sns) {
5717 if (if_agc_top == if_agc_sns) {
5718 pr_err("error: if_agc_top == if_agc_sns\n");
5719 return -EIO;
5721 *sig_strength =
5722 20 + 55 * (if_gain - if_agc_sns) / (if_agc_top - if_agc_sns);
5723 } else {
5724 if (!if_agc_sns) {
5725 pr_err("error: if_agc_sns is zero!\n");
5726 return -EIO;
5728 *sig_strength = (20 * if_gain / if_agc_sns);
5731 return 0;
5732 rw_error:
5733 return -EIO;
5735 #endif
5738 * \fn int get_acc_pkt_err()
5739 * \brief Retrieve signal strength for VSB and QAM.
5740 * \param demod Pointer to demod instance
5741 * \param packet_err Pointer to packet error
5742 * \return int.
5743 * \retval 0 sig_strength contains valid data.
5744 * \retval -EINVAL sig_strength is NULL.
5745 * \retval -EIO Erroneous data, sig_strength contains invalid data.
5747 #ifdef DRXJ_SIGNAL_ACCUM_ERR
5748 static int get_acc_pkt_err(struct drx_demod_instance *demod, u16 *packet_err)
5750 int rc;
5751 static u16 pkt_err;
5752 static u16 last_pkt_err;
5753 u16 data = 0;
5754 struct drxj_data *ext_attr = NULL;
5755 struct i2c_device_addr *dev_addr = NULL;
5757 ext_attr = (struct drxj_data *) demod->my_ext_attr;
5758 dev_addr = demod->my_i2c_dev_addr;
5760 rc = DRXJ_DAP.read_reg16func(dev_addr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, &data, 0);
5761 if (rc != 0) {
5762 pr_err("error %d\n", rc);
5763 goto rw_error;
5765 if (ext_attr->reset_pkt_err_acc) {
5766 last_pkt_err = data;
5767 pkt_err = 0;
5768 ext_attr->reset_pkt_err_acc = false;
5771 if (data < last_pkt_err) {
5772 pkt_err += 0xffff - last_pkt_err;
5773 pkt_err += data;
5774 } else {
5775 pkt_err += (data - last_pkt_err);
5777 *packet_err = pkt_err;
5778 last_pkt_err = data;
5780 return 0;
5781 rw_error:
5782 return -EIO;
5784 #endif
5786 #if 0
5788 * \fn int ResetAccPktErr()
5789 * \brief Reset Accumulating packet error count.
5790 * \param demod Pointer to demod instance
5791 * \return int.
5792 * \retval 0.
5793 * \retval -EIO Erroneous data.
5795 static int ctrl_set_cfg_reset_pkt_err(struct drx_demod_instance *demod)
5797 struct drxj_data *ext_attr = NULL;
5798 int rc;
5799 u16 packet_error = 0;
5801 ext_attr = (struct drxj_data *) demod->my_ext_attr;
5802 ext_attr->reset_pkt_err_acc = true;
5803 /* call to reset counter */
5804 rc = get_acc_pkt_err(demod, &packet_error);
5805 if (rc != 0) {
5806 pr_err("error %d\n", rc);
5807 goto rw_error;
5810 return 0;
5811 rw_error:
5812 return -EIO;
5816 * \fn static short get_str_freq_offset()
5817 * \brief Get symbol rate offset in QAM & 8VSB mode
5818 * \return Error code
5820 static int get_str_freq_offset(struct drx_demod_instance *demod, s32 *str_freq)
5822 int rc;
5823 u32 symbol_frequency_ratio = 0;
5824 u32 symbol_nom_frequency_ratio = 0;
5826 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
5827 struct drxj_data *ext_attr = demod->my_ext_attr;
5829 rc = drxj_dap_atomic_read_reg32(dev_addr, IQM_RC_RATE_LO__A, &symbol_frequency_ratio, 0);
5830 if (rc != 0) {
5831 pr_err("error %d\n", rc);
5832 goto rw_error;
5834 symbol_nom_frequency_ratio = ext_attr->iqm_rc_rate_ofs;
5836 if (symbol_frequency_ratio > symbol_nom_frequency_ratio)
5837 *str_freq =
5838 -1 *
5839 frac_times1e6((symbol_frequency_ratio -
5840 symbol_nom_frequency_ratio),
5841 (symbol_frequency_ratio + (1 << 23)));
5842 else
5843 *str_freq =
5844 frac_times1e6((symbol_nom_frequency_ratio -
5845 symbol_frequency_ratio),
5846 (symbol_frequency_ratio + (1 << 23)));
5848 return 0;
5849 rw_error:
5850 return -EIO;
5854 * \fn static short get_ctl_freq_offset
5855 * \brief Get the value of ctl_freq in QAM & ATSC mode
5856 * \return Error code
5858 static int get_ctl_freq_offset(struct drx_demod_instance *demod, s32 *ctl_freq)
5860 s32 sampling_frequency = 0;
5861 s32 current_frequency = 0;
5862 s32 nominal_frequency = 0;
5863 s32 carrier_frequency_shift = 0;
5864 s32 sign = 1;
5865 u32 data64hi = 0;
5866 u32 data64lo = 0;
5867 struct drxj_data *ext_attr = NULL;
5868 struct drx_common_attr *common_attr = NULL;
5869 struct i2c_device_addr *dev_addr = NULL;
5870 int rc;
5872 dev_addr = demod->my_i2c_dev_addr;
5873 ext_attr = (struct drxj_data *) demod->my_ext_attr;
5874 common_attr = (struct drx_common_attr *) demod->my_common_attr;
5876 sampling_frequency = common_attr->sys_clock_freq / 3;
5878 /* both registers are sign extended */
5879 nominal_frequency = ext_attr->iqm_fs_rate_ofs;
5880 rc = drxj_dap_atomic_read_reg32(dev_addr, IQM_FS_RATE_LO__A, (u32 *)&current_frequency, 0);
5881 if (rc != 0) {
5882 pr_err("error %d\n", rc);
5883 goto rw_error;
5886 if (ext_attr->pos_image) {
5887 /* negative image */
5888 carrier_frequency_shift = nominal_frequency - current_frequency;
5889 } else {
5890 /* positive image */
5891 carrier_frequency_shift = current_frequency - nominal_frequency;
5894 /* carrier Frequency Shift In Hz */
5895 if (carrier_frequency_shift < 0) {
5896 sign = -1;
5897 carrier_frequency_shift *= sign;
5900 /* *ctl_freq = carrier_frequency_shift * 50.625e6 / (1 << 28); */
5901 mult32(carrier_frequency_shift, sampling_frequency, &data64hi, &data64lo);
5902 *ctl_freq =
5903 (s32) ((((data64lo >> 28) & 0xf) | (data64hi << 4)) * sign);
5905 return 0;
5906 rw_error:
5907 return -EIO;
5909 #endif
5911 /*============================================================================*/
5914 * \fn int set_agc_rf ()
5915 * \brief Configure RF AGC
5916 * \param demod instance of demodulator.
5917 * \param agc_settings AGC configuration structure
5918 * \return int.
5920 static int
5921 set_agc_rf(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings, bool atomic)
5923 struct i2c_device_addr *dev_addr = NULL;
5924 struct drxj_data *ext_attr = NULL;
5925 struct drxj_cfg_agc *p_agc_settings = NULL;
5926 struct drx_common_attr *common_attr = NULL;
5927 int rc;
5928 drx_write_reg16func_t scu_wr16 = NULL;
5929 drx_read_reg16func_t scu_rr16 = NULL;
5931 common_attr = (struct drx_common_attr *) demod->my_common_attr;
5932 dev_addr = demod->my_i2c_dev_addr;
5933 ext_attr = (struct drxj_data *) demod->my_ext_attr;
5935 if (atomic) {
5936 scu_rr16 = drxj_dap_scu_atomic_read_reg16;
5937 scu_wr16 = drxj_dap_scu_atomic_write_reg16;
5938 } else {
5939 scu_rr16 = DRXJ_DAP.read_reg16func;
5940 scu_wr16 = DRXJ_DAP.write_reg16func;
5943 /* Configure AGC only if standard is currently active */
5944 if ((ext_attr->standard == agc_settings->standard) ||
5945 (DRXJ_ISQAMSTD(ext_attr->standard) &&
5946 DRXJ_ISQAMSTD(agc_settings->standard)) ||
5947 (DRXJ_ISATVSTD(ext_attr->standard) &&
5948 DRXJ_ISATVSTD(agc_settings->standard))) {
5949 u16 data = 0;
5951 switch (agc_settings->ctrl_mode) {
5952 case DRX_AGC_CTRL_AUTO:
5954 /* Enable RF AGC DAC */
5955 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_STDBY__A, &data, 0);
5956 if (rc != 0) {
5957 pr_err("error %d\n", rc);
5958 goto rw_error;
5960 data |= IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE;
5961 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_STDBY__A, data, 0);
5962 if (rc != 0) {
5963 pr_err("error %d\n", rc);
5964 goto rw_error;
5967 /* Enable SCU RF AGC loop */
5968 rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
5969 if (rc != 0) {
5970 pr_err("error %d\n", rc);
5971 goto rw_error;
5973 data &= ~SCU_RAM_AGC_KI_RF__M;
5974 if (ext_attr->standard == DRX_STANDARD_8VSB)
5975 data |= (2 << SCU_RAM_AGC_KI_RF__B);
5976 else if (DRXJ_ISQAMSTD(ext_attr->standard))
5977 data |= (5 << SCU_RAM_AGC_KI_RF__B);
5978 else
5979 data |= (4 << SCU_RAM_AGC_KI_RF__B);
5981 if (common_attr->tuner_rf_agc_pol)
5982 data |= SCU_RAM_AGC_KI_INV_RF_POL__M;
5983 else
5984 data &= ~SCU_RAM_AGC_KI_INV_RF_POL__M;
5985 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
5986 if (rc != 0) {
5987 pr_err("error %d\n", rc);
5988 goto rw_error;
5991 /* Set speed ( using complementary reduction value ) */
5992 rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI_RED__A, &data, 0);
5993 if (rc != 0) {
5994 pr_err("error %d\n", rc);
5995 goto rw_error;
5997 data &= ~SCU_RAM_AGC_KI_RED_RAGC_RED__M;
5998 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI_RED__A, (~(agc_settings->speed << SCU_RAM_AGC_KI_RED_RAGC_RED__B) & SCU_RAM_AGC_KI_RED_RAGC_RED__M) | data, 0);
5999 if (rc != 0) {
6000 pr_err("error %d\n", rc);
6001 goto rw_error;
6004 if (agc_settings->standard == DRX_STANDARD_8VSB)
6005 p_agc_settings = &(ext_attr->vsb_if_agc_cfg);
6006 else if (DRXJ_ISQAMSTD(agc_settings->standard))
6007 p_agc_settings = &(ext_attr->qam_if_agc_cfg);
6008 else if (DRXJ_ISATVSTD(agc_settings->standard))
6009 p_agc_settings = &(ext_attr->atv_if_agc_cfg);
6010 else
6011 return -EINVAL;
6013 /* Set TOP, only if IF-AGC is in AUTO mode */
6014 if (p_agc_settings->ctrl_mode == DRX_AGC_CTRL_AUTO) {
6015 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, agc_settings->top, 0);
6016 if (rc != 0) {
6017 pr_err("error %d\n", rc);
6018 goto rw_error;
6020 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, agc_settings->top, 0);
6021 if (rc != 0) {
6022 pr_err("error %d\n", rc);
6023 goto rw_error;
6027 /* Cut-Off current */
6028 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_RF_IACCU_HI_CO__A, agc_settings->cut_off_current, 0);
6029 if (rc != 0) {
6030 pr_err("error %d\n", rc);
6031 goto rw_error;
6033 break;
6034 case DRX_AGC_CTRL_USER:
6036 /* Enable RF AGC DAC */
6037 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_STDBY__A, &data, 0);
6038 if (rc != 0) {
6039 pr_err("error %d\n", rc);
6040 goto rw_error;
6042 data |= IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE;
6043 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_STDBY__A, data, 0);
6044 if (rc != 0) {
6045 pr_err("error %d\n", rc);
6046 goto rw_error;
6049 /* Disable SCU RF AGC loop */
6050 rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
6051 if (rc != 0) {
6052 pr_err("error %d\n", rc);
6053 goto rw_error;
6055 data &= ~SCU_RAM_AGC_KI_RF__M;
6056 if (common_attr->tuner_rf_agc_pol)
6057 data |= SCU_RAM_AGC_KI_INV_RF_POL__M;
6058 else
6059 data &= ~SCU_RAM_AGC_KI_INV_RF_POL__M;
6060 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
6061 if (rc != 0) {
6062 pr_err("error %d\n", rc);
6063 goto rw_error;
6066 /* Write value to output pin */
6067 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_RF_IACCU_HI__A, agc_settings->output_level, 0);
6068 if (rc != 0) {
6069 pr_err("error %d\n", rc);
6070 goto rw_error;
6072 break;
6073 case DRX_AGC_CTRL_OFF:
6075 /* Disable RF AGC DAC */
6076 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_STDBY__A, &data, 0);
6077 if (rc != 0) {
6078 pr_err("error %d\n", rc);
6079 goto rw_error;
6081 data &= (~IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE);
6082 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_STDBY__A, data, 0);
6083 if (rc != 0) {
6084 pr_err("error %d\n", rc);
6085 goto rw_error;
6088 /* Disable SCU RF AGC loop */
6089 rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
6090 if (rc != 0) {
6091 pr_err("error %d\n", rc);
6092 goto rw_error;
6094 data &= ~SCU_RAM_AGC_KI_RF__M;
6095 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
6096 if (rc != 0) {
6097 pr_err("error %d\n", rc);
6098 goto rw_error;
6100 break;
6101 default:
6102 return -EINVAL;
6103 } /* switch ( agcsettings->ctrl_mode ) */
6106 /* Store rf agc settings */
6107 switch (agc_settings->standard) {
6108 case DRX_STANDARD_8VSB:
6109 ext_attr->vsb_rf_agc_cfg = *agc_settings;
6110 break;
6111 #ifndef DRXJ_VSB_ONLY
6112 case DRX_STANDARD_ITU_A:
6113 case DRX_STANDARD_ITU_B:
6114 case DRX_STANDARD_ITU_C:
6115 ext_attr->qam_rf_agc_cfg = *agc_settings;
6116 break;
6117 #endif
6118 #if 0
6119 case DRX_STANDARD_PAL_SECAM_BG:
6120 case DRX_STANDARD_PAL_SECAM_DK:
6121 case DRX_STANDARD_PAL_SECAM_I:
6122 case DRX_STANDARD_PAL_SECAM_L:
6123 case DRX_STANDARD_PAL_SECAM_LP:
6124 case DRX_STANDARD_NTSC:
6125 case DRX_STANDARD_FM:
6126 ext_attr->atv_rf_agc_cfg = *agc_settings;
6127 break;
6128 #endif
6129 default:
6130 return -EIO;
6133 return 0;
6134 rw_error:
6135 return -EIO;
6138 #if 0
6140 * \fn int get_agc_rf ()
6141 * \brief get configuration of RF AGC
6142 * \param demod instance of demodulator.
6143 * \param agc_settings AGC configuration structure
6144 * \return int.
6146 static int
6147 get_agc_rf(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings)
6149 struct i2c_device_addr *dev_addr = NULL;
6150 struct drxj_data *ext_attr = NULL;
6151 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
6152 int rc;
6154 dev_addr = demod->my_i2c_dev_addr;
6155 ext_attr = (struct drxj_data *) demod->my_ext_attr;
6157 /* Return stored AGC settings */
6158 standard = agc_settings->standard;
6159 switch (agc_settings->standard) {
6160 case DRX_STANDARD_8VSB:
6161 *agc_settings = ext_attr->vsb_rf_agc_cfg;
6162 break;
6163 #ifndef DRXJ_VSB_ONLY
6164 case DRX_STANDARD_ITU_A:
6165 case DRX_STANDARD_ITU_B:
6166 case DRX_STANDARD_ITU_C:
6167 *agc_settings = ext_attr->qam_rf_agc_cfg;
6168 break;
6169 #endif
6170 #if 0
6171 case DRX_STANDARD_PAL_SECAM_BG:
6172 case DRX_STANDARD_PAL_SECAM_DK:
6173 case DRX_STANDARD_PAL_SECAM_I:
6174 case DRX_STANDARD_PAL_SECAM_L:
6175 case DRX_STANDARD_PAL_SECAM_LP:
6176 case DRX_STANDARD_NTSC:
6177 case DRX_STANDARD_FM:
6178 *agc_settings = ext_attr->atv_rf_agc_cfg;
6179 break;
6180 #endif
6181 default:
6182 return -EIO;
6184 agc_settings->standard = standard;
6186 /* Get AGC output only if standard is currently active. */
6187 if ((ext_attr->standard == agc_settings->standard) ||
6188 (DRXJ_ISQAMSTD(ext_attr->standard) &&
6189 DRXJ_ISQAMSTD(agc_settings->standard)) ||
6190 (DRXJ_ISATVSTD(ext_attr->standard) &&
6191 DRXJ_ISATVSTD(agc_settings->standard))) {
6192 rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_AGC_RF_IACCU_HI__A, &(agc_settings->output_level), 0);
6193 if (rc != 0) {
6194 pr_err("error %d\n", rc);
6195 goto rw_error;
6199 return 0;
6200 rw_error:
6201 return -EIO;
6203 #endif
6206 * \fn int set_agc_if ()
6207 * \brief Configure If AGC
6208 * \param demod instance of demodulator.
6209 * \param agc_settings AGC configuration structure
6210 * \return int.
6212 static int
6213 set_agc_if(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings, bool atomic)
6215 struct i2c_device_addr *dev_addr = NULL;
6216 struct drxj_data *ext_attr = NULL;
6217 struct drxj_cfg_agc *p_agc_settings = NULL;
6218 struct drx_common_attr *common_attr = NULL;
6219 drx_write_reg16func_t scu_wr16 = NULL;
6220 drx_read_reg16func_t scu_rr16 = NULL;
6221 int rc;
6223 common_attr = (struct drx_common_attr *) demod->my_common_attr;
6224 dev_addr = demod->my_i2c_dev_addr;
6225 ext_attr = (struct drxj_data *) demod->my_ext_attr;
6227 if (atomic) {
6228 scu_rr16 = drxj_dap_scu_atomic_read_reg16;
6229 scu_wr16 = drxj_dap_scu_atomic_write_reg16;
6230 } else {
6231 scu_rr16 = DRXJ_DAP.read_reg16func;
6232 scu_wr16 = DRXJ_DAP.write_reg16func;
6235 /* Configure AGC only if standard is currently active */
6236 if ((ext_attr->standard == agc_settings->standard) ||
6237 (DRXJ_ISQAMSTD(ext_attr->standard) &&
6238 DRXJ_ISQAMSTD(agc_settings->standard)) ||
6239 (DRXJ_ISATVSTD(ext_attr->standard) &&
6240 DRXJ_ISATVSTD(agc_settings->standard))) {
6241 u16 data = 0;
6243 switch (agc_settings->ctrl_mode) {
6244 case DRX_AGC_CTRL_AUTO:
6245 /* Enable IF AGC DAC */
6246 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_STDBY__A, &data, 0);
6247 if (rc != 0) {
6248 pr_err("error %d\n", rc);
6249 goto rw_error;
6251 data |= IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE;
6252 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_STDBY__A, data, 0);
6253 if (rc != 0) {
6254 pr_err("error %d\n", rc);
6255 goto rw_error;
6258 /* Enable SCU IF AGC loop */
6259 rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
6260 if (rc != 0) {
6261 pr_err("error %d\n", rc);
6262 goto rw_error;
6264 data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
6265 data &= ~SCU_RAM_AGC_KI_IF__M;
6266 if (ext_attr->standard == DRX_STANDARD_8VSB)
6267 data |= (3 << SCU_RAM_AGC_KI_IF__B);
6268 else if (DRXJ_ISQAMSTD(ext_attr->standard))
6269 data |= (6 << SCU_RAM_AGC_KI_IF__B);
6270 else
6271 data |= (5 << SCU_RAM_AGC_KI_IF__B);
6273 if (common_attr->tuner_if_agc_pol)
6274 data |= SCU_RAM_AGC_KI_INV_IF_POL__M;
6275 else
6276 data &= ~SCU_RAM_AGC_KI_INV_IF_POL__M;
6277 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
6278 if (rc != 0) {
6279 pr_err("error %d\n", rc);
6280 goto rw_error;
6283 /* Set speed (using complementary reduction value) */
6284 rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI_RED__A, &data, 0);
6285 if (rc != 0) {
6286 pr_err("error %d\n", rc);
6287 goto rw_error;
6289 data &= ~SCU_RAM_AGC_KI_RED_IAGC_RED__M;
6290 rc = (*scu_wr16) (dev_addr, SCU_RAM_AGC_KI_RED__A, (~(agc_settings->speed << SCU_RAM_AGC_KI_RED_IAGC_RED__B) & SCU_RAM_AGC_KI_RED_IAGC_RED__M) | data, 0);
6291 if (rc != 0) {
6292 pr_err("error %d\n", rc);
6293 goto rw_error;
6296 if (agc_settings->standard == DRX_STANDARD_8VSB)
6297 p_agc_settings = &(ext_attr->vsb_rf_agc_cfg);
6298 else if (DRXJ_ISQAMSTD(agc_settings->standard))
6299 p_agc_settings = &(ext_attr->qam_rf_agc_cfg);
6300 else if (DRXJ_ISATVSTD(agc_settings->standard))
6301 p_agc_settings = &(ext_attr->atv_rf_agc_cfg);
6302 else
6303 return -EINVAL;
6305 /* Restore TOP */
6306 if (p_agc_settings->ctrl_mode == DRX_AGC_CTRL_AUTO) {
6307 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, p_agc_settings->top, 0);
6308 if (rc != 0) {
6309 pr_err("error %d\n", rc);
6310 goto rw_error;
6312 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, p_agc_settings->top, 0);
6313 if (rc != 0) {
6314 pr_err("error %d\n", rc);
6315 goto rw_error;
6317 } else {
6318 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, 0, 0);
6319 if (rc != 0) {
6320 pr_err("error %d\n", rc);
6321 goto rw_error;
6323 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, 0, 0);
6324 if (rc != 0) {
6325 pr_err("error %d\n", rc);
6326 goto rw_error;
6329 break;
6331 case DRX_AGC_CTRL_USER:
6333 /* Enable IF AGC DAC */
6334 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_STDBY__A, &data, 0);
6335 if (rc != 0) {
6336 pr_err("error %d\n", rc);
6337 goto rw_error;
6339 data |= IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE;
6340 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_STDBY__A, data, 0);
6341 if (rc != 0) {
6342 pr_err("error %d\n", rc);
6343 goto rw_error;
6346 /* Disable SCU IF AGC loop */
6347 rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
6348 if (rc != 0) {
6349 pr_err("error %d\n", rc);
6350 goto rw_error;
6352 data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
6353 data |= SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
6354 if (common_attr->tuner_if_agc_pol)
6355 data |= SCU_RAM_AGC_KI_INV_IF_POL__M;
6356 else
6357 data &= ~SCU_RAM_AGC_KI_INV_IF_POL__M;
6358 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
6359 if (rc != 0) {
6360 pr_err("error %d\n", rc);
6361 goto rw_error;
6364 /* Write value to output pin */
6365 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, agc_settings->output_level, 0);
6366 if (rc != 0) {
6367 pr_err("error %d\n", rc);
6368 goto rw_error;
6370 break;
6372 case DRX_AGC_CTRL_OFF:
6374 /* Disable If AGC DAC */
6375 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_STDBY__A, &data, 0);
6376 if (rc != 0) {
6377 pr_err("error %d\n", rc);
6378 goto rw_error;
6380 data &= (~IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE);
6381 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_STDBY__A, data, 0);
6382 if (rc != 0) {
6383 pr_err("error %d\n", rc);
6384 goto rw_error;
6387 /* Disable SCU IF AGC loop */
6388 rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
6389 if (rc != 0) {
6390 pr_err("error %d\n", rc);
6391 goto rw_error;
6393 data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
6394 data |= SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
6395 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
6396 if (rc != 0) {
6397 pr_err("error %d\n", rc);
6398 goto rw_error;
6400 break;
6401 default:
6402 return -EINVAL;
6403 } /* switch ( agcsettings->ctrl_mode ) */
6405 /* always set the top to support configurations without if-loop */
6406 rc = (*scu_wr16) (dev_addr, SCU_RAM_AGC_INGAIN_TGT_MIN__A, agc_settings->top, 0);
6407 if (rc != 0) {
6408 pr_err("error %d\n", rc);
6409 goto rw_error;
6413 /* Store if agc settings */
6414 switch (agc_settings->standard) {
6415 case DRX_STANDARD_8VSB:
6416 ext_attr->vsb_if_agc_cfg = *agc_settings;
6417 break;
6418 #ifndef DRXJ_VSB_ONLY
6419 case DRX_STANDARD_ITU_A:
6420 case DRX_STANDARD_ITU_B:
6421 case DRX_STANDARD_ITU_C:
6422 ext_attr->qam_if_agc_cfg = *agc_settings;
6423 break;
6424 #endif
6425 #if 0
6426 case DRX_STANDARD_PAL_SECAM_BG:
6427 case DRX_STANDARD_PAL_SECAM_DK:
6428 case DRX_STANDARD_PAL_SECAM_I:
6429 case DRX_STANDARD_PAL_SECAM_L:
6430 case DRX_STANDARD_PAL_SECAM_LP:
6431 case DRX_STANDARD_NTSC:
6432 case DRX_STANDARD_FM:
6433 ext_attr->atv_if_agc_cfg = *agc_settings;
6434 break;
6435 #endif
6436 default:
6437 return -EIO;
6440 return 0;
6441 rw_error:
6442 return -EIO;
6445 #if 0
6447 * \fn int get_agc_if ()
6448 * \brief get configuration of If AGC
6449 * \param demod instance of demodulator.
6450 * \param agc_settings AGC configuration structure
6451 * \return int.
6453 static int
6454 get_agc_if(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings)
6456 struct i2c_device_addr *dev_addr = NULL;
6457 struct drxj_data *ext_attr = NULL;
6458 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
6459 int rc;
6461 dev_addr = demod->my_i2c_dev_addr;
6462 ext_attr = (struct drxj_data *) demod->my_ext_attr;
6464 /* Return stored ATV AGC settings */
6465 standard = agc_settings->standard;
6466 switch (agc_settings->standard) {
6467 case DRX_STANDARD_8VSB:
6468 *agc_settings = ext_attr->vsb_if_agc_cfg;
6469 break;
6470 #ifndef DRXJ_VSB_ONLY
6471 case DRX_STANDARD_ITU_A:
6472 case DRX_STANDARD_ITU_B:
6473 case DRX_STANDARD_ITU_C:
6474 *agc_settings = ext_attr->qam_if_agc_cfg;
6475 break;
6476 #endif
6477 case DRX_STANDARD_PAL_SECAM_BG:
6478 case DRX_STANDARD_PAL_SECAM_DK:
6479 case DRX_STANDARD_PAL_SECAM_I:
6480 case DRX_STANDARD_PAL_SECAM_L:
6481 case DRX_STANDARD_PAL_SECAM_LP:
6482 case DRX_STANDARD_NTSC:
6483 case DRX_STANDARD_FM:
6484 *agc_settings = ext_attr->atv_if_agc_cfg;
6485 break;
6486 default:
6487 return -EIO;
6489 agc_settings->standard = standard;
6491 /* Get AGC output only if standard is currently active */
6492 if ((ext_attr->standard == agc_settings->standard) ||
6493 (DRXJ_ISQAMSTD(ext_attr->standard) &&
6494 DRXJ_ISQAMSTD(agc_settings->standard)) ||
6495 (DRXJ_ISATVSTD(ext_attr->standard) &&
6496 DRXJ_ISATVSTD(agc_settings->standard))) {
6497 /* read output level */
6498 rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_AGC_IF_IACCU_HI__A, &(agc_settings->output_level), 0);
6499 if (rc != 0) {
6500 pr_err("error %d\n", rc);
6501 goto rw_error;
6505 return 0;
6506 rw_error:
6507 return -EIO;
6509 #endif
6512 * \fn int set_iqm_af ()
6513 * \brief Configure IQM AF registers
6514 * \param demod instance of demodulator.
6515 * \param active
6516 * \return int.
6518 static int set_iqm_af(struct drx_demod_instance *demod, bool active)
6520 u16 data = 0;
6521 struct i2c_device_addr *dev_addr = NULL;
6522 int rc;
6524 dev_addr = demod->my_i2c_dev_addr;
6526 /* Configure IQM */
6527 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_STDBY__A, &data, 0);
6528 if (rc != 0) {
6529 pr_err("error %d\n", rc);
6530 goto rw_error;
6532 if (!active)
6533 data &= ((~IQM_AF_STDBY_STDBY_ADC_A2_ACTIVE) & (~IQM_AF_STDBY_STDBY_AMP_A2_ACTIVE) & (~IQM_AF_STDBY_STDBY_PD_A2_ACTIVE) & (~IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE) & (~IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE));
6534 else
6535 data |= (IQM_AF_STDBY_STDBY_ADC_A2_ACTIVE | IQM_AF_STDBY_STDBY_AMP_A2_ACTIVE | IQM_AF_STDBY_STDBY_PD_A2_ACTIVE | IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE | IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE);
6536 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_STDBY__A, data, 0);
6537 if (rc != 0) {
6538 pr_err("error %d\n", rc);
6539 goto rw_error;
6542 return 0;
6543 rw_error:
6544 return -EIO;
6547 /*============================================================================*/
6548 /*== END 8VSB & QAM COMMON DATAPATH FUNCTIONS ==*/
6549 /*============================================================================*/
6551 /*============================================================================*/
6552 /*============================================================================*/
6553 /*== 8VSB DATAPATH FUNCTIONS ==*/
6554 /*============================================================================*/
6555 /*============================================================================*/
6558 * \fn int power_down_vsb ()
6559 * \brief Powr down QAM related blocks.
6560 * \param demod instance of demodulator.
6561 * \param channel pointer to channel data.
6562 * \return int.
6564 static int power_down_vsb(struct drx_demod_instance *demod, bool primary)
6566 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
6567 struct drxjscu_cmd cmd_scu = { /* command */ 0,
6568 /* parameter_len */ 0,
6569 /* result_len */ 0,
6570 /* *parameter */ NULL,
6571 /* *result */ NULL
6573 struct drx_cfg_mpeg_output cfg_mpeg_output;
6574 int rc;
6575 u16 cmd_result = 0;
6578 STOP demodulator
6579 reset of FEC and VSB HW
6581 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB |
6582 SCU_RAM_COMMAND_CMD_DEMOD_STOP;
6583 cmd_scu.parameter_len = 0;
6584 cmd_scu.result_len = 1;
6585 cmd_scu.parameter = NULL;
6586 cmd_scu.result = &cmd_result;
6587 rc = scu_command(dev_addr, &cmd_scu);
6588 if (rc != 0) {
6589 pr_err("error %d\n", rc);
6590 goto rw_error;
6593 /* stop all comm_exec */
6594 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP, 0);
6595 if (rc != 0) {
6596 pr_err("error %d\n", rc);
6597 goto rw_error;
6599 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_STOP, 0);
6600 if (rc != 0) {
6601 pr_err("error %d\n", rc);
6602 goto rw_error;
6604 if (primary) {
6605 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP, 0);
6606 if (rc != 0) {
6607 pr_err("error %d\n", rc);
6608 goto rw_error;
6610 rc = set_iqm_af(demod, false);
6611 if (rc != 0) {
6612 pr_err("error %d\n", rc);
6613 goto rw_error;
6615 } else {
6616 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0);
6617 if (rc != 0) {
6618 pr_err("error %d\n", rc);
6619 goto rw_error;
6621 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0);
6622 if (rc != 0) {
6623 pr_err("error %d\n", rc);
6624 goto rw_error;
6626 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0);
6627 if (rc != 0) {
6628 pr_err("error %d\n", rc);
6629 goto rw_error;
6631 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0);
6632 if (rc != 0) {
6633 pr_err("error %d\n", rc);
6634 goto rw_error;
6636 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0);
6637 if (rc != 0) {
6638 pr_err("error %d\n", rc);
6639 goto rw_error;
6643 cfg_mpeg_output.enable_mpeg_output = false;
6644 rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output);
6645 if (rc != 0) {
6646 pr_err("error %d\n", rc);
6647 goto rw_error;
6650 return 0;
6651 rw_error:
6652 return -EIO;
6656 * \fn int set_vsb_leak_n_gain ()
6657 * \brief Set ATSC demod.
6658 * \param demod instance of demodulator.
6659 * \return int.
6661 static int set_vsb_leak_n_gain(struct drx_demod_instance *demod)
6663 struct i2c_device_addr *dev_addr = NULL;
6664 int rc;
6666 const u8 vsb_ffe_leak_gain_ram0[] = {
6667 DRXJ_16TO8(0x8), /* FFETRAINLKRATIO1 */
6668 DRXJ_16TO8(0x8), /* FFETRAINLKRATIO2 */
6669 DRXJ_16TO8(0x8), /* FFETRAINLKRATIO3 */
6670 DRXJ_16TO8(0xf), /* FFETRAINLKRATIO4 */
6671 DRXJ_16TO8(0xf), /* FFETRAINLKRATIO5 */
6672 DRXJ_16TO8(0xf), /* FFETRAINLKRATIO6 */
6673 DRXJ_16TO8(0xf), /* FFETRAINLKRATIO7 */
6674 DRXJ_16TO8(0xf), /* FFETRAINLKRATIO8 */
6675 DRXJ_16TO8(0xf), /* FFETRAINLKRATIO9 */
6676 DRXJ_16TO8(0x8), /* FFETRAINLKRATIO10 */
6677 DRXJ_16TO8(0x8), /* FFETRAINLKRATIO11 */
6678 DRXJ_16TO8(0x8), /* FFETRAINLKRATIO12 */
6679 DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO1 */
6680 DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO2 */
6681 DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO3 */
6682 DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO4 */
6683 DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO5 */
6684 DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO6 */
6685 DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO7 */
6686 DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO8 */
6687 DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO9 */
6688 DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO10 */
6689 DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO11 */
6690 DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO12 */
6691 DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO1 */
6692 DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO2 */
6693 DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO3 */
6694 DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO4 */
6695 DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO5 */
6696 DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO6 */
6697 DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO7 */
6698 DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO8 */
6699 DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO9 */
6700 DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO10 */
6701 DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO11 */
6702 DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO12 */
6703 DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO1 */
6704 DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO2 */
6705 DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO3 */
6706 DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO4 */
6707 DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO5 */
6708 DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO6 */
6709 DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO7 */
6710 DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO8 */
6711 DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO9 */
6712 DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO10 */
6713 DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO11 */
6714 DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO12 */
6715 DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO1 */
6716 DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO2 */
6717 DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO3 */
6718 DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO4 */
6719 DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO5 */
6720 DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO6 */
6721 DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO7 */
6722 DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO8 */
6723 DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO9 */
6724 DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO10 */
6725 DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO11 */
6726 DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO12 */
6727 DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO1 */
6728 DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO2 */
6729 DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO3 */
6730 DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO4 */
6731 DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO5 */
6732 DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO6 */
6733 DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO7 */
6734 DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO8 */
6735 DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO9 */
6736 DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO10 */
6737 DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO11 */
6738 DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO12 */
6739 DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO1 */
6740 DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO2 */
6741 DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO3 */
6742 DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO4 */
6743 DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO5 */
6744 DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO6 */
6745 DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO7 */
6746 DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO8 */
6747 DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO9 */
6748 DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO10 */
6749 DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO11 */
6750 DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO12 */
6751 DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO1 */
6752 DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO2 */
6753 DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO3 */
6754 DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO4 */
6755 DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO5 */
6756 DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO6 */
6757 DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO7 */
6758 DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO8 */
6759 DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO9 */
6760 DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO10 */
6761 DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO11 */
6762 DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO12 */
6763 DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO1 */
6764 DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO2 */
6765 DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO3 */
6766 DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO4 */
6767 DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO5 */
6768 DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO6 */
6769 DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO7 */
6770 DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO8 */
6771 DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO9 */
6772 DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO10 */
6773 DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO11 */
6774 DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO12 */
6775 DRXJ_16TO8(0x2020), /* FIRTRAINGAIN1 */
6776 DRXJ_16TO8(0x2020), /* FIRTRAINGAIN2 */
6777 DRXJ_16TO8(0x2020), /* FIRTRAINGAIN3 */
6778 DRXJ_16TO8(0x4040), /* FIRTRAINGAIN4 */
6779 DRXJ_16TO8(0x4040), /* FIRTRAINGAIN5 */
6780 DRXJ_16TO8(0x4040), /* FIRTRAINGAIN6 */
6781 DRXJ_16TO8(0x4040), /* FIRTRAINGAIN7 */
6782 DRXJ_16TO8(0x4040), /* FIRTRAINGAIN8 */
6783 DRXJ_16TO8(0x4040), /* FIRTRAINGAIN9 */
6784 DRXJ_16TO8(0x2020), /* FIRTRAINGAIN10 */
6785 DRXJ_16TO8(0x2020), /* FIRTRAINGAIN11 */
6786 DRXJ_16TO8(0x2020), /* FIRTRAINGAIN12 */
6787 DRXJ_16TO8(0x0808), /* FIRRCA1GAIN1 */
6788 DRXJ_16TO8(0x0808), /* FIRRCA1GAIN2 */
6789 DRXJ_16TO8(0x0808), /* FIRRCA1GAIN3 */
6790 DRXJ_16TO8(0x1010), /* FIRRCA1GAIN4 */
6791 DRXJ_16TO8(0x1010), /* FIRRCA1GAIN5 */
6792 DRXJ_16TO8(0x1010), /* FIRRCA1GAIN6 */
6793 DRXJ_16TO8(0x1010), /* FIRRCA1GAIN7 */
6794 DRXJ_16TO8(0x1010) /* FIRRCA1GAIN8 */
6797 const u8 vsb_ffe_leak_gain_ram1[] = {
6798 DRXJ_16TO8(0x1010), /* FIRRCA1GAIN9 */
6799 DRXJ_16TO8(0x0808), /* FIRRCA1GAIN10 */
6800 DRXJ_16TO8(0x0808), /* FIRRCA1GAIN11 */
6801 DRXJ_16TO8(0x0808), /* FIRRCA1GAIN12 */
6802 DRXJ_16TO8(0x0808), /* FIRRCA2GAIN1 */
6803 DRXJ_16TO8(0x0808), /* FIRRCA2GAIN2 */
6804 DRXJ_16TO8(0x0808), /* FIRRCA2GAIN3 */
6805 DRXJ_16TO8(0x1010), /* FIRRCA2GAIN4 */
6806 DRXJ_16TO8(0x1010), /* FIRRCA2GAIN5 */
6807 DRXJ_16TO8(0x1010), /* FIRRCA2GAIN6 */
6808 DRXJ_16TO8(0x1010), /* FIRRCA2GAIN7 */
6809 DRXJ_16TO8(0x1010), /* FIRRCA2GAIN8 */
6810 DRXJ_16TO8(0x1010), /* FIRRCA2GAIN9 */
6811 DRXJ_16TO8(0x0808), /* FIRRCA2GAIN10 */
6812 DRXJ_16TO8(0x0808), /* FIRRCA2GAIN11 */
6813 DRXJ_16TO8(0x0808), /* FIRRCA2GAIN12 */
6814 DRXJ_16TO8(0x0303), /* FIRDDM1GAIN1 */
6815 DRXJ_16TO8(0x0303), /* FIRDDM1GAIN2 */
6816 DRXJ_16TO8(0x0303), /* FIRDDM1GAIN3 */
6817 DRXJ_16TO8(0x0606), /* FIRDDM1GAIN4 */
6818 DRXJ_16TO8(0x0606), /* FIRDDM1GAIN5 */
6819 DRXJ_16TO8(0x0606), /* FIRDDM1GAIN6 */
6820 DRXJ_16TO8(0x0606), /* FIRDDM1GAIN7 */
6821 DRXJ_16TO8(0x0606), /* FIRDDM1GAIN8 */
6822 DRXJ_16TO8(0x0606), /* FIRDDM1GAIN9 */
6823 DRXJ_16TO8(0x0303), /* FIRDDM1GAIN10 */
6824 DRXJ_16TO8(0x0303), /* FIRDDM1GAIN11 */
6825 DRXJ_16TO8(0x0303), /* FIRDDM1GAIN12 */
6826 DRXJ_16TO8(0x0303), /* FIRDDM2GAIN1 */
6827 DRXJ_16TO8(0x0303), /* FIRDDM2GAIN2 */
6828 DRXJ_16TO8(0x0303), /* FIRDDM2GAIN3 */
6829 DRXJ_16TO8(0x0505), /* FIRDDM2GAIN4 */
6830 DRXJ_16TO8(0x0505), /* FIRDDM2GAIN5 */
6831 DRXJ_16TO8(0x0505), /* FIRDDM2GAIN6 */
6832 DRXJ_16TO8(0x0505), /* FIRDDM2GAIN7 */
6833 DRXJ_16TO8(0x0505), /* FIRDDM2GAIN8 */
6834 DRXJ_16TO8(0x0505), /* FIRDDM2GAIN9 */
6835 DRXJ_16TO8(0x0303), /* FIRDDM2GAIN10 */
6836 DRXJ_16TO8(0x0303), /* FIRDDM2GAIN11 */
6837 DRXJ_16TO8(0x0303), /* FIRDDM2GAIN12 */
6838 DRXJ_16TO8(0x001f), /* DFETRAINLKRATIO */
6839 DRXJ_16TO8(0x01ff), /* DFERCA1TRAINLKRATIO */
6840 DRXJ_16TO8(0x01ff), /* DFERCA1DATALKRATIO */
6841 DRXJ_16TO8(0x004f), /* DFERCA2TRAINLKRATIO */
6842 DRXJ_16TO8(0x004f), /* DFERCA2DATALKRATIO */
6843 DRXJ_16TO8(0x01ff), /* DFEDDM1TRAINLKRATIO */
6844 DRXJ_16TO8(0x01ff), /* DFEDDM1DATALKRATIO */
6845 DRXJ_16TO8(0x0352), /* DFEDDM2TRAINLKRATIO */
6846 DRXJ_16TO8(0x0352), /* DFEDDM2DATALKRATIO */
6847 DRXJ_16TO8(0x0000), /* DFETRAINGAIN */
6848 DRXJ_16TO8(0x2020), /* DFERCA1GAIN */
6849 DRXJ_16TO8(0x1010), /* DFERCA2GAIN */
6850 DRXJ_16TO8(0x1818), /* DFEDDM1GAIN */
6851 DRXJ_16TO8(0x1212) /* DFEDDM2GAIN */
6854 dev_addr = demod->my_i2c_dev_addr;
6855 rc = DRXJ_DAP.write_block_func(dev_addr, VSB_SYSCTRL_RAM0_FFETRAINLKRATIO1__A, sizeof(vsb_ffe_leak_gain_ram0), ((u8 *)vsb_ffe_leak_gain_ram0), 0);
6856 if (rc != 0) {
6857 pr_err("error %d\n", rc);
6858 goto rw_error;
6860 rc = DRXJ_DAP.write_block_func(dev_addr, VSB_SYSCTRL_RAM1_FIRRCA1GAIN9__A, sizeof(vsb_ffe_leak_gain_ram1), ((u8 *)vsb_ffe_leak_gain_ram1), 0);
6861 if (rc != 0) {
6862 pr_err("error %d\n", rc);
6863 goto rw_error;
6866 return 0;
6867 rw_error:
6868 return -EIO;
6872 * \fn int set_vsb()
6873 * \brief Set 8VSB demod.
6874 * \param demod instance of demodulator.
6875 * \return int.
6878 static int set_vsb(struct drx_demod_instance *demod)
6880 struct i2c_device_addr *dev_addr = NULL;
6881 int rc;
6882 struct drx_common_attr *common_attr = NULL;
6883 struct drxjscu_cmd cmd_scu;
6884 struct drxj_data *ext_attr = NULL;
6885 u16 cmd_result = 0;
6886 u16 cmd_param = 0;
6887 const u8 vsb_taps_re[] = {
6888 DRXJ_16TO8(-2), /* re0 */
6889 DRXJ_16TO8(4), /* re1 */
6890 DRXJ_16TO8(1), /* re2 */
6891 DRXJ_16TO8(-4), /* re3 */
6892 DRXJ_16TO8(1), /* re4 */
6893 DRXJ_16TO8(4), /* re5 */
6894 DRXJ_16TO8(-3), /* re6 */
6895 DRXJ_16TO8(-3), /* re7 */
6896 DRXJ_16TO8(6), /* re8 */
6897 DRXJ_16TO8(1), /* re9 */
6898 DRXJ_16TO8(-9), /* re10 */
6899 DRXJ_16TO8(3), /* re11 */
6900 DRXJ_16TO8(12), /* re12 */
6901 DRXJ_16TO8(-9), /* re13 */
6902 DRXJ_16TO8(-15), /* re14 */
6903 DRXJ_16TO8(17), /* re15 */
6904 DRXJ_16TO8(19), /* re16 */
6905 DRXJ_16TO8(-29), /* re17 */
6906 DRXJ_16TO8(-22), /* re18 */
6907 DRXJ_16TO8(45), /* re19 */
6908 DRXJ_16TO8(25), /* re20 */
6909 DRXJ_16TO8(-70), /* re21 */
6910 DRXJ_16TO8(-28), /* re22 */
6911 DRXJ_16TO8(111), /* re23 */
6912 DRXJ_16TO8(30), /* re24 */
6913 DRXJ_16TO8(-201), /* re25 */
6914 DRXJ_16TO8(-31), /* re26 */
6915 DRXJ_16TO8(629) /* re27 */
6918 dev_addr = demod->my_i2c_dev_addr;
6919 common_attr = (struct drx_common_attr *) demod->my_common_attr;
6920 ext_attr = (struct drxj_data *) demod->my_ext_attr;
6922 /* stop all comm_exec */
6923 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP, 0);
6924 if (rc != 0) {
6925 pr_err("error %d\n", rc);
6926 goto rw_error;
6928 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_STOP, 0);
6929 if (rc != 0) {
6930 pr_err("error %d\n", rc);
6931 goto rw_error;
6933 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0);
6934 if (rc != 0) {
6935 pr_err("error %d\n", rc);
6936 goto rw_error;
6938 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0);
6939 if (rc != 0) {
6940 pr_err("error %d\n", rc);
6941 goto rw_error;
6943 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0);
6944 if (rc != 0) {
6945 pr_err("error %d\n", rc);
6946 goto rw_error;
6948 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0);
6949 if (rc != 0) {
6950 pr_err("error %d\n", rc);
6951 goto rw_error;
6953 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0);
6954 if (rc != 0) {
6955 pr_err("error %d\n", rc);
6956 goto rw_error;
6959 /* reset demodulator */
6960 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB
6961 | SCU_RAM_COMMAND_CMD_DEMOD_RESET;
6962 cmd_scu.parameter_len = 0;
6963 cmd_scu.result_len = 1;
6964 cmd_scu.parameter = NULL;
6965 cmd_scu.result = &cmd_result;
6966 rc = scu_command(dev_addr, &cmd_scu);
6967 if (rc != 0) {
6968 pr_err("error %d\n", rc);
6969 goto rw_error;
6972 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_DCF_BYPASS__A, 1, 0);
6973 if (rc != 0) {
6974 pr_err("error %d\n", rc);
6975 goto rw_error;
6977 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_FS_ADJ_SEL__A, IQM_FS_ADJ_SEL_B_VSB, 0);
6978 if (rc != 0) {
6979 pr_err("error %d\n", rc);
6980 goto rw_error;
6982 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RC_ADJ_SEL__A, IQM_RC_ADJ_SEL_B_VSB, 0);
6983 if (rc != 0) {
6984 pr_err("error %d\n", rc);
6985 goto rw_error;
6987 ext_attr->iqm_rc_rate_ofs = 0x00AD0D79;
6988 rc = DRXJ_DAP.write_reg32func(dev_addr, IQM_RC_RATE_OFS_LO__A, ext_attr->iqm_rc_rate_ofs, 0);
6989 if (rc != 0) {
6990 pr_err("error %d\n", rc);
6991 goto rw_error;
6993 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_CFAGC_GAINSHIFT__A, 4, 0);
6994 if (rc != 0) {
6995 pr_err("error %d\n", rc);
6996 goto rw_error;
6998 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_CYGN1TRK__A, 1, 0);
6999 if (rc != 0) {
7000 pr_err("error %d\n", rc);
7001 goto rw_error;
7004 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RC_CROUT_ENA__A, 1, 0);
7005 if (rc != 0) {
7006 pr_err("error %d\n", rc);
7007 goto rw_error;
7009 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RC_STRETCH__A, 28, 0);
7010 if (rc != 0) {
7011 pr_err("error %d\n", rc);
7012 goto rw_error;
7014 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_ACTIVE__A, 0, 0);
7015 if (rc != 0) {
7016 pr_err("error %d\n", rc);
7017 goto rw_error;
7019 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_SYMMETRIC__A, 0, 0);
7020 if (rc != 0) {
7021 pr_err("error %d\n", rc);
7022 goto rw_error;
7024 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_MIDTAP__A, 3, 0);
7025 if (rc != 0) {
7026 pr_err("error %d\n", rc);
7027 goto rw_error;
7029 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_OUT_ENA__A, IQM_CF_OUT_ENA_VSB__M, 0);
7030 if (rc != 0) {
7031 pr_err("error %d\n", rc);
7032 goto rw_error;
7034 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_SCALE__A, 1393, 0);
7035 if (rc != 0) {
7036 pr_err("error %d\n", rc);
7037 goto rw_error;
7039 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_SCALE_SH__A, 0, 0);
7040 if (rc != 0) {
7041 pr_err("error %d\n", rc);
7042 goto rw_error;
7044 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_POW_MEAS_LEN__A, 1, 0);
7045 if (rc != 0) {
7046 pr_err("error %d\n", rc);
7047 goto rw_error;
7050 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_RE0__A, sizeof(vsb_taps_re), ((u8 *)vsb_taps_re), 0);
7051 if (rc != 0) {
7052 pr_err("error %d\n", rc);
7053 goto rw_error;
7055 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_IM0__A, sizeof(vsb_taps_re), ((u8 *)vsb_taps_re), 0);
7056 if (rc != 0) {
7057 pr_err("error %d\n", rc);
7058 goto rw_error;
7061 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_BNTHRESH__A, 330, 0);
7062 if (rc != 0) {
7063 pr_err("error %d\n", rc);
7064 goto rw_error;
7065 } /* set higher threshold */
7066 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_CLPLASTNUM__A, 90, 0);
7067 if (rc != 0) {
7068 pr_err("error %d\n", rc);
7069 goto rw_error;
7070 } /* burst detection on */
7071 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_SNRTH_RCA1__A, 0x0042, 0);
7072 if (rc != 0) {
7073 pr_err("error %d\n", rc);
7074 goto rw_error;
7075 } /* drop thresholds by 1 dB */
7076 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_SNRTH_RCA2__A, 0x0053, 0);
7077 if (rc != 0) {
7078 pr_err("error %d\n", rc);
7079 goto rw_error;
7080 } /* drop thresholds by 2 dB */
7081 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_EQCTRL__A, 0x1, 0);
7082 if (rc != 0) {
7083 pr_err("error %d\n", rc);
7084 goto rw_error;
7085 } /* cma on */
7086 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_GPIO__A, 0, 0);
7087 if (rc != 0) {
7088 pr_err("error %d\n", rc);
7089 goto rw_error;
7090 } /* GPIO */
7092 /* Initialize the FEC Subsystem */
7093 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_TOP_ANNEX__A, FEC_TOP_ANNEX_D, 0);
7094 if (rc != 0) {
7095 pr_err("error %d\n", rc);
7096 goto rw_error;
7099 u16 fec_oc_snc_mode = 0;
7100 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode, 0);
7101 if (rc != 0) {
7102 pr_err("error %d\n", rc);
7103 goto rw_error;
7105 /* output data even when not locked */
7106 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_SNC_MODE__A, fec_oc_snc_mode | FEC_OC_SNC_MODE_UNLOCK_ENABLE__M, 0);
7107 if (rc != 0) {
7108 pr_err("error %d\n", rc);
7109 goto rw_error;
7113 /* set clip */
7114 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_CLP_LEN__A, 0, 0);
7115 if (rc != 0) {
7116 pr_err("error %d\n", rc);
7117 goto rw_error;
7119 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_CLP_TH__A, 470, 0);
7120 if (rc != 0) {
7121 pr_err("error %d\n", rc);
7122 goto rw_error;
7124 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_SNS_LEN__A, 0, 0);
7125 if (rc != 0) {
7126 pr_err("error %d\n", rc);
7127 goto rw_error;
7129 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_SNRTH_PT__A, 0xD4, 0);
7130 if (rc != 0) {
7131 pr_err("error %d\n", rc);
7132 goto rw_error;
7134 /* no transparent, no A&C framing; parity is set in mpegoutput */
7136 u16 fec_oc_reg_mode = 0;
7137 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_OC_MODE__A, &fec_oc_reg_mode, 0);
7138 if (rc != 0) {
7139 pr_err("error %d\n", rc);
7140 goto rw_error;
7142 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_MODE__A, fec_oc_reg_mode & (~(FEC_OC_MODE_TRANSPARENT__M | FEC_OC_MODE_CLEAR__M | FEC_OC_MODE_RETAIN_FRAMING__M)), 0);
7143 if (rc != 0) {
7144 pr_err("error %d\n", rc);
7145 goto rw_error;
7149 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_DI_TIMEOUT_LO__A, 0, 0);
7150 if (rc != 0) {
7151 pr_err("error %d\n", rc);
7152 goto rw_error;
7153 } /* timeout counter for restarting */
7154 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_DI_TIMEOUT_HI__A, 3, 0);
7155 if (rc != 0) {
7156 pr_err("error %d\n", rc);
7157 goto rw_error;
7159 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_RS_MODE__A, 0, 0);
7160 if (rc != 0) {
7161 pr_err("error %d\n", rc);
7162 goto rw_error;
7163 } /* bypass disabled */
7164 /* initialize RS packet error measurement parameters */
7165 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_RS_MEASUREMENT_PERIOD__A, FEC_RS_MEASUREMENT_PERIOD, 0);
7166 if (rc != 0) {
7167 pr_err("error %d\n", rc);
7168 goto rw_error;
7170 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_RS_MEASUREMENT_PRESCALE__A, FEC_RS_MEASUREMENT_PRESCALE, 0);
7171 if (rc != 0) {
7172 pr_err("error %d\n", rc);
7173 goto rw_error;
7176 /* init measurement period of MER/SER */
7177 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_MEASUREMENT_PERIOD__A, VSB_TOP_MEASUREMENT_PERIOD, 0);
7178 if (rc != 0) {
7179 pr_err("error %d\n", rc);
7180 goto rw_error;
7182 rc = DRXJ_DAP.write_reg32func(dev_addr, SCU_RAM_FEC_ACCUM_CW_CORRECTED_LO__A, 0, 0);
7183 if (rc != 0) {
7184 pr_err("error %d\n", rc);
7185 goto rw_error;
7187 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_FEC_MEAS_COUNT__A, 0, 0);
7188 if (rc != 0) {
7189 pr_err("error %d\n", rc);
7190 goto rw_error;
7192 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0, 0);
7193 if (rc != 0) {
7194 pr_err("error %d\n", rc);
7195 goto rw_error;
7198 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_CKGN1TRK__A, 128, 0);
7199 if (rc != 0) {
7200 pr_err("error %d\n", rc);
7201 goto rw_error;
7203 /* B-Input to ADC, PGA+filter in standby */
7204 if (!ext_attr->has_lna) {
7205 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_AMUX__A, 0x02, 0);
7206 if (rc != 0) {
7207 pr_err("error %d\n", rc);
7208 goto rw_error;
7212 /* turn on IQMAF. It has to be in front of setAgc**() */
7213 rc = set_iqm_af(demod, true);
7214 if (rc != 0) {
7215 pr_err("error %d\n", rc);
7216 goto rw_error;
7218 rc = adc_synchronization(demod);
7219 if (rc != 0) {
7220 pr_err("error %d\n", rc);
7221 goto rw_error;
7224 rc = init_agc(demod);
7225 if (rc != 0) {
7226 pr_err("error %d\n", rc);
7227 goto rw_error;
7229 rc = set_agc_if(demod, &(ext_attr->vsb_if_agc_cfg), false);
7230 if (rc != 0) {
7231 pr_err("error %d\n", rc);
7232 goto rw_error;
7234 rc = set_agc_rf(demod, &(ext_attr->vsb_rf_agc_cfg), false);
7235 if (rc != 0) {
7236 pr_err("error %d\n", rc);
7237 goto rw_error;
7240 /* TODO fix this, store a struct drxj_cfg_afe_gain structure in struct drxj_data instead
7241 of only the gain */
7242 struct drxj_cfg_afe_gain vsb_pga_cfg = { DRX_STANDARD_8VSB, 0 };
7244 vsb_pga_cfg.gain = ext_attr->vsb_pga_cfg;
7245 rc = ctrl_set_cfg_afe_gain(demod, &vsb_pga_cfg);
7246 if (rc != 0) {
7247 pr_err("error %d\n", rc);
7248 goto rw_error;
7251 rc = ctrl_set_cfg_pre_saw(demod, &(ext_attr->vsb_pre_saw_cfg));
7252 if (rc != 0) {
7253 pr_err("error %d\n", rc);
7254 goto rw_error;
7257 /* Mpeg output has to be in front of FEC active */
7258 rc = set_mpegtei_handling(demod);
7259 if (rc != 0) {
7260 pr_err("error %d\n", rc);
7261 goto rw_error;
7263 rc = bit_reverse_mpeg_output(demod);
7264 if (rc != 0) {
7265 pr_err("error %d\n", rc);
7266 goto rw_error;
7268 rc = set_mpeg_start_width(demod);
7269 if (rc != 0) {
7270 pr_err("error %d\n", rc);
7271 goto rw_error;
7274 /* TODO: move to set_standard after hardware reset value problem is solved */
7275 /* Configure initial MPEG output */
7276 struct drx_cfg_mpeg_output cfg_mpeg_output;
7277 cfg_mpeg_output.enable_mpeg_output = true;
7278 cfg_mpeg_output.insert_rs_byte = common_attr->mpeg_cfg.insert_rs_byte;
7279 cfg_mpeg_output.enable_parallel =
7280 common_attr->mpeg_cfg.enable_parallel;
7281 cfg_mpeg_output.invert_data = common_attr->mpeg_cfg.invert_data;
7282 cfg_mpeg_output.invert_err = common_attr->mpeg_cfg.invert_err;
7283 cfg_mpeg_output.invert_str = common_attr->mpeg_cfg.invert_str;
7284 cfg_mpeg_output.invert_val = common_attr->mpeg_cfg.invert_val;
7285 cfg_mpeg_output.invert_clk = common_attr->mpeg_cfg.invert_clk;
7286 cfg_mpeg_output.static_clk = common_attr->mpeg_cfg.static_clk;
7287 cfg_mpeg_output.bitrate = common_attr->mpeg_cfg.bitrate;
7288 rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output);
7289 if (rc != 0) {
7290 pr_err("error %d\n", rc);
7291 goto rw_error;
7295 /* TBD: what parameters should be set */
7296 cmd_param = 0x00; /* Default mode AGC on, etc */
7297 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB
7298 | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM;
7299 cmd_scu.parameter_len = 1;
7300 cmd_scu.result_len = 1;
7301 cmd_scu.parameter = &cmd_param;
7302 cmd_scu.result = &cmd_result;
7303 rc = scu_command(dev_addr, &cmd_scu);
7304 if (rc != 0) {
7305 pr_err("error %d\n", rc);
7306 goto rw_error;
7309 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_BEAGC_GAINSHIFT__A, 0x0004, 0);
7310 if (rc != 0) {
7311 pr_err("error %d\n", rc);
7312 goto rw_error;
7314 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_SNRTH_PT__A, 0x00D2, 0);
7315 if (rc != 0) {
7316 pr_err("error %d\n", rc);
7317 goto rw_error;
7319 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_SYSSMTRNCTRL__A, VSB_TOP_SYSSMTRNCTRL__PRE | VSB_TOP_SYSSMTRNCTRL_NCOTIMEOUTCNTEN__M, 0);
7320 if (rc != 0) {
7321 pr_err("error %d\n", rc);
7322 goto rw_error;
7324 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_BEDETCTRL__A, 0x142, 0);
7325 if (rc != 0) {
7326 pr_err("error %d\n", rc);
7327 goto rw_error;
7329 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_LBAGCREFLVL__A, 640, 0);
7330 if (rc != 0) {
7331 pr_err("error %d\n", rc);
7332 goto rw_error;
7334 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_CYGN1ACQ__A, 4, 0);
7335 if (rc != 0) {
7336 pr_err("error %d\n", rc);
7337 goto rw_error;
7339 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_CYGN1TRK__A, 2, 0);
7340 if (rc != 0) {
7341 pr_err("error %d\n", rc);
7342 goto rw_error;
7344 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_CYGN2TRK__A, 3, 0);
7345 if (rc != 0) {
7346 pr_err("error %d\n", rc);
7347 goto rw_error;
7350 /* start demodulator */
7351 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB
7352 | SCU_RAM_COMMAND_CMD_DEMOD_START;
7353 cmd_scu.parameter_len = 0;
7354 cmd_scu.result_len = 1;
7355 cmd_scu.parameter = NULL;
7356 cmd_scu.result = &cmd_result;
7357 rc = scu_command(dev_addr, &cmd_scu);
7358 if (rc != 0) {
7359 pr_err("error %d\n", rc);
7360 goto rw_error;
7363 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_ACTIVE, 0);
7364 if (rc != 0) {
7365 pr_err("error %d\n", rc);
7366 goto rw_error;
7368 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_ACTIVE, 0);
7369 if (rc != 0) {
7370 pr_err("error %d\n", rc);
7371 goto rw_error;
7373 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE, 0);
7374 if (rc != 0) {
7375 pr_err("error %d\n", rc);
7376 goto rw_error;
7379 return 0;
7380 rw_error:
7381 return -EIO;
7385 * \fn static short get_vsb_post_rs_pck_err(struct i2c_device_addr *dev_addr, u16 *PckErrs)
7386 * \brief Get the values of packet error in 8VSB mode
7387 * \return Error code
7389 static int get_vsb_post_rs_pck_err(struct i2c_device_addr *dev_addr, u16 *pck_errs)
7391 int rc;
7392 u16 data = 0;
7393 u16 period = 0;
7394 u16 prescale = 0;
7395 u16 packet_errors_mant = 0;
7396 u16 packet_errors_exp = 0;
7398 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_RS_NR_FAILURES__A, &data, 0);
7399 if (rc != 0) {
7400 pr_err("error %d\n", rc);
7401 goto rw_error;
7403 packet_errors_mant = data & FEC_RS_NR_FAILURES_FIXED_MANT__M;
7404 packet_errors_exp = (data & FEC_RS_NR_FAILURES_EXP__M)
7405 >> FEC_RS_NR_FAILURES_EXP__B;
7406 period = FEC_RS_MEASUREMENT_PERIOD;
7407 prescale = FEC_RS_MEASUREMENT_PRESCALE;
7408 /* packet error rate = (error packet number) per second */
7409 /* 77.3 us is time for per packet */
7410 if (period * prescale == 0) {
7411 pr_err("error: period and/or prescale is zero!\n");
7412 return -EIO;
7414 *pck_errs =
7415 (u16) frac_times1e6(packet_errors_mant * (1 << packet_errors_exp),
7416 (period * prescale * 77));
7418 return 0;
7419 rw_error:
7420 return -EIO;
7424 * \fn static short GetVSBBer(struct i2c_device_addr *dev_addr, u32 *ber)
7425 * \brief Get the values of ber in VSB mode
7426 * \return Error code
7428 static int get_vs_bpost_viterbi_ber(struct i2c_device_addr *dev_addr, u32 *ber)
7430 int rc;
7431 u16 data = 0;
7432 u16 period = 0;
7433 u16 prescale = 0;
7434 u16 bit_errors_mant = 0;
7435 u16 bit_errors_exp = 0;
7437 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_RS_NR_BIT_ERRORS__A, &data, 0);
7438 if (rc != 0) {
7439 pr_err("error %d\n", rc);
7440 goto rw_error;
7442 period = FEC_RS_MEASUREMENT_PERIOD;
7443 prescale = FEC_RS_MEASUREMENT_PRESCALE;
7445 bit_errors_mant = data & FEC_RS_NR_BIT_ERRORS_FIXED_MANT__M;
7446 bit_errors_exp = (data & FEC_RS_NR_BIT_ERRORS_EXP__M)
7447 >> FEC_RS_NR_BIT_ERRORS_EXP__B;
7449 if (((bit_errors_mant << bit_errors_exp) >> 3) > 68700)
7450 *ber = 26570;
7451 else {
7452 if (period * prescale == 0) {
7453 pr_err("error: period and/or prescale is zero!\n");
7454 return -EIO;
7456 *ber =
7457 frac_times1e6(bit_errors_mant <<
7458 ((bit_errors_exp >
7459 2) ? (bit_errors_exp - 3) : bit_errors_exp),
7460 period * prescale * 207 *
7461 ((bit_errors_exp > 2) ? 1 : 8));
7464 return 0;
7465 rw_error:
7466 return -EIO;
7470 * \fn static short get_vs_bpre_viterbi_ber(struct i2c_device_addr *dev_addr, u32 *ber)
7471 * \brief Get the values of ber in VSB mode
7472 * \return Error code
7474 static int get_vs_bpre_viterbi_ber(struct i2c_device_addr *dev_addr, u32 *ber)
7476 u16 data = 0;
7477 int rc;
7479 rc = DRXJ_DAP.read_reg16func(dev_addr, VSB_TOP_NR_SYM_ERRS__A, &data, 0);
7480 if (rc != 0) {
7481 pr_err("error %d\n", rc);
7482 goto rw_error;
7484 *ber =
7485 frac_times1e6(data,
7486 VSB_TOP_MEASUREMENT_PERIOD * SYMBOLS_PER_SEGMENT);
7488 return 0;
7489 rw_error:
7490 return -EIO;
7493 #if 0
7495 * \fn static short get_vsb_symb_err(struct i2c_device_addr *dev_addr, u32 *ber)
7496 * \brief Get the values of ber in VSB mode
7497 * \return Error code
7499 static int get_vsb_symb_err(struct i2c_device_addr *dev_addr, u32 *ser)
7501 int rc;
7502 u16 data = 0;
7503 u16 period = 0;
7504 u16 prescale = 0;
7505 u16 symb_errors_mant = 0;
7506 u16 symb_errors_exp = 0;
7508 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_RS_NR_SYMBOL_ERRORS__A, &data, 0);
7509 if (rc != 0) {
7510 pr_err("error %d\n", rc);
7511 goto rw_error;
7513 period = FEC_RS_MEASUREMENT_PERIOD;
7514 prescale = FEC_RS_MEASUREMENT_PRESCALE;
7516 symb_errors_mant = data & FEC_RS_NR_SYMBOL_ERRORS_FIXED_MANT__M;
7517 symb_errors_exp = (data & FEC_RS_NR_SYMBOL_ERRORS_EXP__M)
7518 >> FEC_RS_NR_SYMBOL_ERRORS_EXP__B;
7520 if (period * prescale == 0) {
7521 pr_err("error: period and/or prescale is zero!\n");
7522 return -EIO;
7524 *ser = (u32) frac_times1e6((symb_errors_mant << symb_errors_exp) * 1000,
7525 (period * prescale * 77318));
7527 return 0;
7528 rw_error:
7529 return -EIO;
7531 #endif
7534 * \fn static int get_vsbmer(struct i2c_device_addr *dev_addr, u16 *mer)
7535 * \brief Get the values of MER
7536 * \return Error code
7538 static int get_vsbmer(struct i2c_device_addr *dev_addr, u16 *mer)
7540 int rc;
7541 u16 data_hi = 0;
7543 rc = DRXJ_DAP.read_reg16func(dev_addr, VSB_TOP_ERR_ENERGY_H__A, &data_hi, 0);
7544 if (rc != 0) {
7545 pr_err("error %d\n", rc);
7546 goto rw_error;
7548 *mer =
7549 (u16) (log1_times100(21504) - log1_times100((data_hi << 6) / 52));
7551 return 0;
7552 rw_error:
7553 return -EIO;
7556 #if 0
7557 /*============================================================================*/
7559 * \fn int ctrl_get_vsb_constel()
7560 * \brief Retreive a VSB constellation point via I2C.
7561 * \param demod Pointer to demodulator instance.
7562 * \param complex_nr Pointer to the structure in which to store the
7563 constellation point.
7564 * \return int.
7566 static int
7567 ctrl_get_vsb_constel(struct drx_demod_instance *demod, struct drx_complex *complex_nr)
7569 struct i2c_device_addr *dev_addr = NULL;
7570 int rc;
7571 /**< device address */
7572 u16 vsb_top_comm_mb = 0; /**< VSB SL MB configuration */
7573 u16 vsb_top_comm_mb_init = 0; /**< VSB SL MB intial configuration */
7574 u16 re = 0; /**< constellation Re part */
7575 u32 data = 0;
7577 /* read device info */
7578 dev_addr = demod->my_i2c_dev_addr;
7580 /* TODO: */
7581 /* Monitor bus grabbing is an open external interface issue */
7582 /* Needs to be checked when external interface PG is updated */
7584 /* Configure MB (Monitor bus) */
7585 rc = DRXJ_DAP.read_reg16func(dev_addr, VSB_TOP_COMM_MB__A, &vsb_top_comm_mb_init, 0);
7586 if (rc != 0) {
7587 pr_err("error %d\n", rc);
7588 goto rw_error;
7590 /* set observe flag & MB mux */
7591 vsb_top_comm_mb = (vsb_top_comm_mb_init |
7592 VSB_TOP_COMM_MB_OBS_OBS_ON |
7593 VSB_TOP_COMM_MB_MUX_OBS_VSB_TCMEQ_2);
7594 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_COMM_MB__A, vsb_top_comm_mb, 0);
7595 if (rc != 0) {
7596 pr_err("error %d\n", rc);
7597 goto rw_error;
7600 /* Enable MB grabber in the FEC OC */
7601 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_OCR_MODE__A, FEC_OC_OCR_MODE_GRAB_ENABLE__M, 0);
7602 if (rc != 0) {
7603 pr_err("error %d\n", rc);
7604 goto rw_error;
7607 /* Disable MB grabber in the FEC OC */
7608 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_OCR_MODE__A, 0x0, 0);
7609 if (rc != 0) {
7610 pr_err("error %d\n", rc);
7611 goto rw_error;
7614 /* read data */
7615 rc = DRXJ_DAP.read_reg32func(dev_addr, FEC_OC_OCR_GRAB_RD1__A, &data, 0);
7616 if (rc != 0) {
7617 pr_err("error %d\n", rc);
7618 goto rw_error;
7620 re = (u16) (((data >> 10) & 0x300) | ((data >> 2) & 0xff));
7621 if (re & 0x0200)
7622 re |= 0xfc00;
7623 complex_nr->re = re;
7624 complex_nr->im = 0;
7626 /* Restore MB (Monitor bus) */
7627 rc = DRXJ_DAP.write_reg16func(dev_addr, VSB_TOP_COMM_MB__A, vsb_top_comm_mb_init, 0);
7628 if (rc != 0) {
7629 pr_err("error %d\n", rc);
7630 goto rw_error;
7633 return 0;
7634 rw_error:
7635 return -EIO;
7637 #endif
7639 /*============================================================================*/
7640 /*== END 8VSB DATAPATH FUNCTIONS ==*/
7641 /*============================================================================*/
7643 /*============================================================================*/
7644 /*============================================================================*/
7645 /*== QAM DATAPATH FUNCTIONS ==*/
7646 /*============================================================================*/
7647 /*============================================================================*/
7650 * \fn int power_down_qam ()
7651 * \brief Powr down QAM related blocks.
7652 * \param demod instance of demodulator.
7653 * \param channel pointer to channel data.
7654 * \return int.
7656 static int power_down_qam(struct drx_demod_instance *demod, bool primary)
7658 struct drxjscu_cmd cmd_scu = { /* command */ 0,
7659 /* parameter_len */ 0,
7660 /* result_len */ 0,
7661 /* *parameter */ NULL,
7662 /* *result */ NULL
7664 int rc;
7665 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
7666 struct drx_cfg_mpeg_output cfg_mpeg_output;
7667 u16 cmd_result = 0;
7670 STOP demodulator
7671 resets IQM, QAM and FEC HW blocks
7673 /* stop all comm_exec */
7674 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP, 0);
7675 if (rc != 0) {
7676 pr_err("error %d\n", rc);
7677 goto rw_error;
7679 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP, 0);
7680 if (rc != 0) {
7681 pr_err("error %d\n", rc);
7682 goto rw_error;
7685 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
7686 SCU_RAM_COMMAND_CMD_DEMOD_STOP;
7687 cmd_scu.parameter_len = 0;
7688 cmd_scu.result_len = 1;
7689 cmd_scu.parameter = NULL;
7690 cmd_scu.result = &cmd_result;
7691 rc = scu_command(dev_addr, &cmd_scu);
7692 if (rc != 0) {
7693 pr_err("error %d\n", rc);
7694 goto rw_error;
7697 if (primary) {
7698 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP, 0);
7699 if (rc != 0) {
7700 pr_err("error %d\n", rc);
7701 goto rw_error;
7703 rc = set_iqm_af(demod, false);
7704 if (rc != 0) {
7705 pr_err("error %d\n", rc);
7706 goto rw_error;
7708 } else {
7709 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0);
7710 if (rc != 0) {
7711 pr_err("error %d\n", rc);
7712 goto rw_error;
7714 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0);
7715 if (rc != 0) {
7716 pr_err("error %d\n", rc);
7717 goto rw_error;
7719 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0);
7720 if (rc != 0) {
7721 pr_err("error %d\n", rc);
7722 goto rw_error;
7724 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0);
7725 if (rc != 0) {
7726 pr_err("error %d\n", rc);
7727 goto rw_error;
7729 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0);
7730 if (rc != 0) {
7731 pr_err("error %d\n", rc);
7732 goto rw_error;
7736 cfg_mpeg_output.enable_mpeg_output = false;
7737 rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output);
7738 if (rc != 0) {
7739 pr_err("error %d\n", rc);
7740 goto rw_error;
7743 return 0;
7744 rw_error:
7745 return -EIO;
7748 /*============================================================================*/
7751 * \fn int set_qam_measurement ()
7752 * \brief Setup of the QAM Measuremnt intervals for signal quality
7753 * \param demod instance of demod.
7754 * \param constellation current constellation.
7755 * \return int.
7757 * NOTE:
7758 * Take into account that for certain settings the errorcounters can overflow.
7759 * The implementation does not check this.
7761 * TODO: overriding the ext_attr->fec_bits_desired by constellation dependent
7762 * constants to get a measurement period of approx. 1 sec. Remove fec_bits_desired
7763 * field ?
7766 #ifndef DRXJ_VSB_ONLY
7767 static int
7768 set_qam_measurement(struct drx_demod_instance *demod,
7769 enum drx_modulation constellation, u32 symbol_rate)
7771 struct i2c_device_addr *dev_addr = NULL; /* device address for I2C writes */
7772 struct drxj_data *ext_attr = NULL; /* Global data container for DRXJ specif data */
7773 int rc;
7774 u32 fec_bits_desired = 0; /* BER accounting period */
7775 u16 fec_rs_plen = 0; /* defines RS BER measurement period */
7776 u16 fec_rs_prescale = 0; /* ReedSolomon Measurement Prescale */
7777 u32 fec_rs_period = 0; /* Value for corresponding I2C register */
7778 u32 fec_rs_bit_cnt = 0; /* Actual precise amount of bits */
7779 u32 fec_oc_snc_fail_period = 0; /* Value for corresponding I2C register */
7780 u32 qam_vd_period = 0; /* Value for corresponding I2C register */
7781 u32 qam_vd_bit_cnt = 0; /* Actual precise amount of bits */
7782 u16 fec_vd_plen = 0; /* no of trellis symbols: VD SER measur period */
7783 u16 qam_vd_prescale = 0; /* Viterbi Measurement Prescale */
7785 dev_addr = demod->my_i2c_dev_addr;
7786 ext_attr = (struct drxj_data *) demod->my_ext_attr;
7788 fec_bits_desired = ext_attr->fec_bits_desired;
7789 fec_rs_prescale = ext_attr->fec_rs_prescale;
7791 switch (constellation) {
7792 case DRX_CONSTELLATION_QAM16:
7793 fec_bits_desired = 4 * symbol_rate;
7794 break;
7795 case DRX_CONSTELLATION_QAM32:
7796 fec_bits_desired = 5 * symbol_rate;
7797 break;
7798 case DRX_CONSTELLATION_QAM64:
7799 fec_bits_desired = 6 * symbol_rate;
7800 break;
7801 case DRX_CONSTELLATION_QAM128:
7802 fec_bits_desired = 7 * symbol_rate;
7803 break;
7804 case DRX_CONSTELLATION_QAM256:
7805 fec_bits_desired = 8 * symbol_rate;
7806 break;
7807 default:
7808 return -EINVAL;
7811 /* Parameters for Reed-Solomon Decoder */
7812 /* fecrs_period = (int)ceil(FEC_BITS_DESIRED/(fecrs_prescale*plen)) */
7813 /* rs_bit_cnt = fecrs_period*fecrs_prescale*plen */
7814 /* result is within 32 bit arithmetic -> */
7815 /* no need for mult or frac functions */
7817 /* TODO: use constant instead of calculation and remove the fec_rs_plen in ext_attr */
7818 switch (ext_attr->standard) {
7819 case DRX_STANDARD_ITU_A:
7820 case DRX_STANDARD_ITU_C:
7821 fec_rs_plen = 204 * 8;
7822 break;
7823 case DRX_STANDARD_ITU_B:
7824 fec_rs_plen = 128 * 7;
7825 break;
7826 default:
7827 return -EINVAL;
7830 ext_attr->fec_rs_plen = fec_rs_plen; /* for getSigQual */
7831 fec_rs_bit_cnt = fec_rs_prescale * fec_rs_plen; /* temp storage */
7832 if (fec_rs_bit_cnt == 0) {
7833 pr_err("error: fec_rs_bit_cnt is zero!\n");
7834 return -EIO;
7836 fec_rs_period = fec_bits_desired / fec_rs_bit_cnt + 1; /* ceil */
7837 if (ext_attr->standard != DRX_STANDARD_ITU_B)
7838 fec_oc_snc_fail_period = fec_rs_period;
7840 /* limit to max 16 bit value (I2C register width) if needed */
7841 if (fec_rs_period > 0xFFFF)
7842 fec_rs_period = 0xFFFF;
7844 /* write corresponding registers */
7845 switch (ext_attr->standard) {
7846 case DRX_STANDARD_ITU_A:
7847 case DRX_STANDARD_ITU_C:
7848 break;
7849 case DRX_STANDARD_ITU_B:
7850 switch (constellation) {
7851 case DRX_CONSTELLATION_QAM64:
7852 fec_rs_period = 31581;
7853 fec_oc_snc_fail_period = 17932;
7854 break;
7855 case DRX_CONSTELLATION_QAM256:
7856 fec_rs_period = 45446;
7857 fec_oc_snc_fail_period = 25805;
7858 break;
7859 default:
7860 return -EINVAL;
7862 break;
7863 default:
7864 return -EINVAL;
7867 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_SNC_FAIL_PERIOD__A, (u16)fec_oc_snc_fail_period, 0);
7868 if (rc != 0) {
7869 pr_err("error %d\n", rc);
7870 goto rw_error;
7872 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_RS_MEASUREMENT_PERIOD__A, (u16)fec_rs_period, 0);
7873 if (rc != 0) {
7874 pr_err("error %d\n", rc);
7875 goto rw_error;
7877 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_RS_MEASUREMENT_PRESCALE__A, fec_rs_prescale, 0);
7878 if (rc != 0) {
7879 pr_err("error %d\n", rc);
7880 goto rw_error;
7882 ext_attr->fec_rs_period = (u16) fec_rs_period;
7883 ext_attr->fec_rs_prescale = fec_rs_prescale;
7884 rc = DRXJ_DAP.write_reg32func(dev_addr, SCU_RAM_FEC_ACCUM_CW_CORRECTED_LO__A, 0, 0);
7885 if (rc != 0) {
7886 pr_err("error %d\n", rc);
7887 goto rw_error;
7889 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_FEC_MEAS_COUNT__A, 0, 0);
7890 if (rc != 0) {
7891 pr_err("error %d\n", rc);
7892 goto rw_error;
7894 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0, 0);
7895 if (rc != 0) {
7896 pr_err("error %d\n", rc);
7897 goto rw_error;
7900 if (ext_attr->standard == DRX_STANDARD_ITU_B) {
7901 /* Parameters for Viterbi Decoder */
7902 /* qamvd_period = (int)ceil(FEC_BITS_DESIRED/ */
7903 /* (qamvd_prescale*plen*(qam_constellation+1))) */
7904 /* vd_bit_cnt = qamvd_period*qamvd_prescale*plen */
7905 /* result is within 32 bit arithmetic -> */
7906 /* no need for mult or frac functions */
7908 /* a(8 bit) * b(8 bit) = 16 bit result => mult32 not needed */
7909 fec_vd_plen = ext_attr->fec_vd_plen;
7910 qam_vd_prescale = ext_attr->qam_vd_prescale;
7911 qam_vd_bit_cnt = qam_vd_prescale * fec_vd_plen; /* temp storage */
7913 switch (constellation) {
7914 case DRX_CONSTELLATION_QAM64:
7915 /* a(16 bit) * b(4 bit) = 20 bit result => mult32 not needed */
7916 qam_vd_period =
7917 qam_vd_bit_cnt * (QAM_TOP_CONSTELLATION_QAM64 + 1)
7918 * (QAM_TOP_CONSTELLATION_QAM64 + 1);
7919 break;
7920 case DRX_CONSTELLATION_QAM256:
7921 /* a(16 bit) * b(5 bit) = 21 bit result => mult32 not needed */
7922 qam_vd_period =
7923 qam_vd_bit_cnt * (QAM_TOP_CONSTELLATION_QAM256 + 1)
7924 * (QAM_TOP_CONSTELLATION_QAM256 + 1);
7925 break;
7926 default:
7927 return -EINVAL;
7929 if (qam_vd_period == 0) {
7930 pr_err("error: qam_vd_period is zero!\n");
7931 return -EIO;
7933 qam_vd_period = fec_bits_desired / qam_vd_period;
7934 /* limit to max 16 bit value (I2C register width) if needed */
7935 if (qam_vd_period > 0xFFFF)
7936 qam_vd_period = 0xFFFF;
7938 /* a(16 bit) * b(16 bit) = 32 bit result => mult32 not needed */
7939 qam_vd_bit_cnt *= qam_vd_period;
7941 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_VD_MEASUREMENT_PERIOD__A, (u16)qam_vd_period, 0);
7942 if (rc != 0) {
7943 pr_err("error %d\n", rc);
7944 goto rw_error;
7946 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_VD_MEASUREMENT_PRESCALE__A, qam_vd_prescale, 0);
7947 if (rc != 0) {
7948 pr_err("error %d\n", rc);
7949 goto rw_error;
7951 ext_attr->qam_vd_period = (u16) qam_vd_period;
7952 ext_attr->qam_vd_prescale = qam_vd_prescale;
7955 return 0;
7956 rw_error:
7957 return -EIO;
7960 /*============================================================================*/
7963 * \fn int set_qam16 ()
7964 * \brief QAM16 specific setup
7965 * \param demod instance of demod.
7966 * \return int.
7968 static int set_qam16(struct drx_demod_instance *demod)
7970 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
7971 int rc;
7972 const u8 qam_dq_qual_fun[] = {
7973 DRXJ_16TO8(2), /* fun0 */
7974 DRXJ_16TO8(2), /* fun1 */
7975 DRXJ_16TO8(2), /* fun2 */
7976 DRXJ_16TO8(2), /* fun3 */
7977 DRXJ_16TO8(3), /* fun4 */
7978 DRXJ_16TO8(3), /* fun5 */
7980 const u8 qam_eq_cma_rad[] = {
7981 DRXJ_16TO8(13517), /* RAD0 */
7982 DRXJ_16TO8(13517), /* RAD1 */
7983 DRXJ_16TO8(13517), /* RAD2 */
7984 DRXJ_16TO8(13517), /* RAD3 */
7985 DRXJ_16TO8(13517), /* RAD4 */
7986 DRXJ_16TO8(13517), /* RAD5 */
7989 rc = DRXJ_DAP.write_block_func(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun), ((u8 *)qam_dq_qual_fun), 0);
7990 if (rc != 0) {
7991 pr_err("error %d\n", rc);
7992 goto rw_error;
7994 rc = DRXJ_DAP.write_block_func(dev_addr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qam_eq_cma_rad), ((u8 *)qam_eq_cma_rad), 0);
7995 if (rc != 0) {
7996 pr_err("error %d\n", rc);
7997 goto rw_error;
8000 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 140, 0);
8001 if (rc != 0) {
8002 pr_err("error %d\n", rc);
8003 goto rw_error;
8005 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 50, 0);
8006 if (rc != 0) {
8007 pr_err("error %d\n", rc);
8008 goto rw_error;
8010 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 120, 0);
8011 if (rc != 0) {
8012 pr_err("error %d\n", rc);
8013 goto rw_error;
8015 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 230, 0);
8016 if (rc != 0) {
8017 pr_err("error %d\n", rc);
8018 goto rw_error;
8020 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 95, 0);
8021 if (rc != 0) {
8022 pr_err("error %d\n", rc);
8023 goto rw_error;
8025 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 105, 0);
8026 if (rc != 0) {
8027 pr_err("error %d\n", rc);
8028 goto rw_error;
8031 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40, 0);
8032 if (rc != 0) {
8033 pr_err("error %d\n", rc);
8034 goto rw_error;
8036 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 56, 0);
8037 if (rc != 0) {
8038 pr_err("error %d\n", rc);
8039 goto rw_error;
8041 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3, 0);
8042 if (rc != 0) {
8043 pr_err("error %d\n", rc);
8044 goto rw_error;
8047 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 16, 0);
8048 if (rc != 0) {
8049 pr_err("error %d\n", rc);
8050 goto rw_error;
8052 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 220, 0);
8053 if (rc != 0) {
8054 pr_err("error %d\n", rc);
8055 goto rw_error;
8057 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 25, 0);
8058 if (rc != 0) {
8059 pr_err("error %d\n", rc);
8060 goto rw_error;
8062 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 6, 0);
8063 if (rc != 0) {
8064 pr_err("error %d\n", rc);
8065 goto rw_error;
8067 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16)(-24), 0);
8068 if (rc != 0) {
8069 pr_err("error %d\n", rc);
8070 goto rw_error;
8072 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16)(-65), 0);
8073 if (rc != 0) {
8074 pr_err("error %d\n", rc);
8075 goto rw_error;
8077 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16)(-127), 0);
8078 if (rc != 0) {
8079 pr_err("error %d\n", rc);
8080 goto rw_error;
8083 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15, 0);
8084 if (rc != 0) {
8085 pr_err("error %d\n", rc);
8086 goto rw_error;
8088 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40, 0);
8089 if (rc != 0) {
8090 pr_err("error %d\n", rc);
8091 goto rw_error;
8093 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2, 0);
8094 if (rc != 0) {
8095 pr_err("error %d\n", rc);
8096 goto rw_error;
8098 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20, 0);
8099 if (rc != 0) {
8100 pr_err("error %d\n", rc);
8101 goto rw_error;
8103 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255, 0);
8104 if (rc != 0) {
8105 pr_err("error %d\n", rc);
8106 goto rw_error;
8108 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2, 0);
8109 if (rc != 0) {
8110 pr_err("error %d\n", rc);
8111 goto rw_error;
8113 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 10, 0);
8114 if (rc != 0) {
8115 pr_err("error %d\n", rc);
8116 goto rw_error;
8118 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 50, 0);
8119 if (rc != 0) {
8120 pr_err("error %d\n", rc);
8121 goto rw_error;
8123 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12, 0);
8124 if (rc != 0) {
8125 pr_err("error %d\n", rc);
8126 goto rw_error;
8128 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24, 0);
8129 if (rc != 0) {
8130 pr_err("error %d\n", rc);
8131 goto rw_error;
8133 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24, 0);
8134 if (rc != 0) {
8135 pr_err("error %d\n", rc);
8136 goto rw_error;
8138 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12, 0);
8139 if (rc != 0) {
8140 pr_err("error %d\n", rc);
8141 goto rw_error;
8143 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16, 0);
8144 if (rc != 0) {
8145 pr_err("error %d\n", rc);
8146 goto rw_error;
8148 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16, 0);
8149 if (rc != 0) {
8150 pr_err("error %d\n", rc);
8151 goto rw_error;
8153 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16, 0);
8154 if (rc != 0) {
8155 pr_err("error %d\n", rc);
8156 goto rw_error;
8158 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 32, 0);
8159 if (rc != 0) {
8160 pr_err("error %d\n", rc);
8161 goto rw_error;
8163 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 240, 0);
8164 if (rc != 0) {
8165 pr_err("error %d\n", rc);
8166 goto rw_error;
8168 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5, 0);
8169 if (rc != 0) {
8170 pr_err("error %d\n", rc);
8171 goto rw_error;
8173 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15, 0);
8174 if (rc != 0) {
8175 pr_err("error %d\n", rc);
8176 goto rw_error;
8178 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 32, 0);
8179 if (rc != 0) {
8180 pr_err("error %d\n", rc);
8181 goto rw_error;
8184 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 40960, 0);
8185 if (rc != 0) {
8186 pr_err("error %d\n", rc);
8187 goto rw_error;
8190 return 0;
8191 rw_error:
8192 return -EIO;
8195 /*============================================================================*/
8198 * \fn int set_qam32 ()
8199 * \brief QAM32 specific setup
8200 * \param demod instance of demod.
8201 * \return int.
8203 static int set_qam32(struct drx_demod_instance *demod)
8205 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
8206 int rc;
8207 const u8 qam_dq_qual_fun[] = {
8208 DRXJ_16TO8(3), /* fun0 */
8209 DRXJ_16TO8(3), /* fun1 */
8210 DRXJ_16TO8(3), /* fun2 */
8211 DRXJ_16TO8(3), /* fun3 */
8212 DRXJ_16TO8(4), /* fun4 */
8213 DRXJ_16TO8(4), /* fun5 */
8215 const u8 qam_eq_cma_rad[] = {
8216 DRXJ_16TO8(6707), /* RAD0 */
8217 DRXJ_16TO8(6707), /* RAD1 */
8218 DRXJ_16TO8(6707), /* RAD2 */
8219 DRXJ_16TO8(6707), /* RAD3 */
8220 DRXJ_16TO8(6707), /* RAD4 */
8221 DRXJ_16TO8(6707), /* RAD5 */
8224 rc = DRXJ_DAP.write_block_func(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun), ((u8 *)qam_dq_qual_fun), 0);
8225 if (rc != 0) {
8226 pr_err("error %d\n", rc);
8227 goto rw_error;
8229 rc = DRXJ_DAP.write_block_func(dev_addr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qam_eq_cma_rad), ((u8 *)qam_eq_cma_rad), 0);
8230 if (rc != 0) {
8231 pr_err("error %d\n", rc);
8232 goto rw_error;
8235 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 90, 0);
8236 if (rc != 0) {
8237 pr_err("error %d\n", rc);
8238 goto rw_error;
8240 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 50, 0);
8241 if (rc != 0) {
8242 pr_err("error %d\n", rc);
8243 goto rw_error;
8245 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 100, 0);
8246 if (rc != 0) {
8247 pr_err("error %d\n", rc);
8248 goto rw_error;
8250 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 170, 0);
8251 if (rc != 0) {
8252 pr_err("error %d\n", rc);
8253 goto rw_error;
8255 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 80, 0);
8256 if (rc != 0) {
8257 pr_err("error %d\n", rc);
8258 goto rw_error;
8260 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 100, 0);
8261 if (rc != 0) {
8262 pr_err("error %d\n", rc);
8263 goto rw_error;
8266 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40, 0);
8267 if (rc != 0) {
8268 pr_err("error %d\n", rc);
8269 goto rw_error;
8271 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 56, 0);
8272 if (rc != 0) {
8273 pr_err("error %d\n", rc);
8274 goto rw_error;
8276 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3, 0);
8277 if (rc != 0) {
8278 pr_err("error %d\n", rc);
8279 goto rw_error;
8282 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 12, 0);
8283 if (rc != 0) {
8284 pr_err("error %d\n", rc);
8285 goto rw_error;
8287 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 140, 0);
8288 if (rc != 0) {
8289 pr_err("error %d\n", rc);
8290 goto rw_error;
8292 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16)(-8), 0);
8293 if (rc != 0) {
8294 pr_err("error %d\n", rc);
8295 goto rw_error;
8297 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16)(-16), 0);
8298 if (rc != 0) {
8299 pr_err("error %d\n", rc);
8300 goto rw_error;
8302 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16)(-26), 0);
8303 if (rc != 0) {
8304 pr_err("error %d\n", rc);
8305 goto rw_error;
8307 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16)(-56), 0);
8308 if (rc != 0) {
8309 pr_err("error %d\n", rc);
8310 goto rw_error;
8312 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16)(-86), 0);
8313 if (rc != 0) {
8314 pr_err("error %d\n", rc);
8315 goto rw_error;
8318 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15, 0);
8319 if (rc != 0) {
8320 pr_err("error %d\n", rc);
8321 goto rw_error;
8323 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40, 0);
8324 if (rc != 0) {
8325 pr_err("error %d\n", rc);
8326 goto rw_error;
8328 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2, 0);
8329 if (rc != 0) {
8330 pr_err("error %d\n", rc);
8331 goto rw_error;
8333 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20, 0);
8334 if (rc != 0) {
8335 pr_err("error %d\n", rc);
8336 goto rw_error;
8338 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255, 0);
8339 if (rc != 0) {
8340 pr_err("error %d\n", rc);
8341 goto rw_error;
8343 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2, 0);
8344 if (rc != 0) {
8345 pr_err("error %d\n", rc);
8346 goto rw_error;
8348 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 10, 0);
8349 if (rc != 0) {
8350 pr_err("error %d\n", rc);
8351 goto rw_error;
8353 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 50, 0);
8354 if (rc != 0) {
8355 pr_err("error %d\n", rc);
8356 goto rw_error;
8358 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12, 0);
8359 if (rc != 0) {
8360 pr_err("error %d\n", rc);
8361 goto rw_error;
8363 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24, 0);
8364 if (rc != 0) {
8365 pr_err("error %d\n", rc);
8366 goto rw_error;
8368 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24, 0);
8369 if (rc != 0) {
8370 pr_err("error %d\n", rc);
8371 goto rw_error;
8373 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12, 0);
8374 if (rc != 0) {
8375 pr_err("error %d\n", rc);
8376 goto rw_error;
8378 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16, 0);
8379 if (rc != 0) {
8380 pr_err("error %d\n", rc);
8381 goto rw_error;
8383 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16, 0);
8384 if (rc != 0) {
8385 pr_err("error %d\n", rc);
8386 goto rw_error;
8388 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16, 0);
8389 if (rc != 0) {
8390 pr_err("error %d\n", rc);
8391 goto rw_error;
8393 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 32, 0);
8394 if (rc != 0) {
8395 pr_err("error %d\n", rc);
8396 goto rw_error;
8398 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 176, 0);
8399 if (rc != 0) {
8400 pr_err("error %d\n", rc);
8401 goto rw_error;
8403 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5, 0);
8404 if (rc != 0) {
8405 pr_err("error %d\n", rc);
8406 goto rw_error;
8408 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15, 0);
8409 if (rc != 0) {
8410 pr_err("error %d\n", rc);
8411 goto rw_error;
8413 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 8, 0);
8414 if (rc != 0) {
8415 pr_err("error %d\n", rc);
8416 goto rw_error;
8419 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 20480, 0);
8420 if (rc != 0) {
8421 pr_err("error %d\n", rc);
8422 goto rw_error;
8425 return 0;
8426 rw_error:
8427 return -EIO;
8430 /*============================================================================*/
8433 * \fn int set_qam64 ()
8434 * \brief QAM64 specific setup
8435 * \param demod instance of demod.
8436 * \return int.
8438 static int set_qam64(struct drx_demod_instance *demod)
8440 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
8441 int rc;
8442 const u8 qam_dq_qual_fun[] = { /* this is hw reset value. no necessary to re-write */
8443 DRXJ_16TO8(4), /* fun0 */
8444 DRXJ_16TO8(4), /* fun1 */
8445 DRXJ_16TO8(4), /* fun2 */
8446 DRXJ_16TO8(4), /* fun3 */
8447 DRXJ_16TO8(6), /* fun4 */
8448 DRXJ_16TO8(6), /* fun5 */
8450 const u8 qam_eq_cma_rad[] = {
8451 DRXJ_16TO8(13336), /* RAD0 */
8452 DRXJ_16TO8(12618), /* RAD1 */
8453 DRXJ_16TO8(11988), /* RAD2 */
8454 DRXJ_16TO8(13809), /* RAD3 */
8455 DRXJ_16TO8(13809), /* RAD4 */
8456 DRXJ_16TO8(15609), /* RAD5 */
8459 rc = DRXJ_DAP.write_block_func(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun), ((u8 *)qam_dq_qual_fun), 0);
8460 if (rc != 0) {
8461 pr_err("error %d\n", rc);
8462 goto rw_error;
8464 rc = DRXJ_DAP.write_block_func(dev_addr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qam_eq_cma_rad), ((u8 *)qam_eq_cma_rad), 0);
8465 if (rc != 0) {
8466 pr_err("error %d\n", rc);
8467 goto rw_error;
8470 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 105, 0);
8471 if (rc != 0) {
8472 pr_err("error %d\n", rc);
8473 goto rw_error;
8475 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 60, 0);
8476 if (rc != 0) {
8477 pr_err("error %d\n", rc);
8478 goto rw_error;
8480 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 100, 0);
8481 if (rc != 0) {
8482 pr_err("error %d\n", rc);
8483 goto rw_error;
8485 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 195, 0);
8486 if (rc != 0) {
8487 pr_err("error %d\n", rc);
8488 goto rw_error;
8490 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 80, 0);
8491 if (rc != 0) {
8492 pr_err("error %d\n", rc);
8493 goto rw_error;
8495 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 84, 0);
8496 if (rc != 0) {
8497 pr_err("error %d\n", rc);
8498 goto rw_error;
8501 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40, 0);
8502 if (rc != 0) {
8503 pr_err("error %d\n", rc);
8504 goto rw_error;
8506 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 32, 0);
8507 if (rc != 0) {
8508 pr_err("error %d\n", rc);
8509 goto rw_error;
8511 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3, 0);
8512 if (rc != 0) {
8513 pr_err("error %d\n", rc);
8514 goto rw_error;
8517 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 12, 0);
8518 if (rc != 0) {
8519 pr_err("error %d\n", rc);
8520 goto rw_error;
8522 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 141, 0);
8523 if (rc != 0) {
8524 pr_err("error %d\n", rc);
8525 goto rw_error;
8527 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 7, 0);
8528 if (rc != 0) {
8529 pr_err("error %d\n", rc);
8530 goto rw_error;
8532 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 0, 0);
8533 if (rc != 0) {
8534 pr_err("error %d\n", rc);
8535 goto rw_error;
8537 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16)(-15), 0);
8538 if (rc != 0) {
8539 pr_err("error %d\n", rc);
8540 goto rw_error;
8542 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16)(-45), 0);
8543 if (rc != 0) {
8544 pr_err("error %d\n", rc);
8545 goto rw_error;
8547 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16)(-80), 0);
8548 if (rc != 0) {
8549 pr_err("error %d\n", rc);
8550 goto rw_error;
8553 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15, 0);
8554 if (rc != 0) {
8555 pr_err("error %d\n", rc);
8556 goto rw_error;
8558 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40, 0);
8559 if (rc != 0) {
8560 pr_err("error %d\n", rc);
8561 goto rw_error;
8563 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2, 0);
8564 if (rc != 0) {
8565 pr_err("error %d\n", rc);
8566 goto rw_error;
8568 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 30, 0);
8569 if (rc != 0) {
8570 pr_err("error %d\n", rc);
8571 goto rw_error;
8573 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255, 0);
8574 if (rc != 0) {
8575 pr_err("error %d\n", rc);
8576 goto rw_error;
8578 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2, 0);
8579 if (rc != 0) {
8580 pr_err("error %d\n", rc);
8581 goto rw_error;
8583 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 15, 0);
8584 if (rc != 0) {
8585 pr_err("error %d\n", rc);
8586 goto rw_error;
8588 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 80, 0);
8589 if (rc != 0) {
8590 pr_err("error %d\n", rc);
8591 goto rw_error;
8593 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12, 0);
8594 if (rc != 0) {
8595 pr_err("error %d\n", rc);
8596 goto rw_error;
8598 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24, 0);
8599 if (rc != 0) {
8600 pr_err("error %d\n", rc);
8601 goto rw_error;
8603 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24, 0);
8604 if (rc != 0) {
8605 pr_err("error %d\n", rc);
8606 goto rw_error;
8608 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12, 0);
8609 if (rc != 0) {
8610 pr_err("error %d\n", rc);
8611 goto rw_error;
8613 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16, 0);
8614 if (rc != 0) {
8615 pr_err("error %d\n", rc);
8616 goto rw_error;
8618 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16, 0);
8619 if (rc != 0) {
8620 pr_err("error %d\n", rc);
8621 goto rw_error;
8623 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16, 0);
8624 if (rc != 0) {
8625 pr_err("error %d\n", rc);
8626 goto rw_error;
8628 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 48, 0);
8629 if (rc != 0) {
8630 pr_err("error %d\n", rc);
8631 goto rw_error;
8633 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 160, 0);
8634 if (rc != 0) {
8635 pr_err("error %d\n", rc);
8636 goto rw_error;
8638 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5, 0);
8639 if (rc != 0) {
8640 pr_err("error %d\n", rc);
8641 goto rw_error;
8643 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15, 0);
8644 if (rc != 0) {
8645 pr_err("error %d\n", rc);
8646 goto rw_error;
8648 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 32, 0);
8649 if (rc != 0) {
8650 pr_err("error %d\n", rc);
8651 goto rw_error;
8654 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 43008, 0);
8655 if (rc != 0) {
8656 pr_err("error %d\n", rc);
8657 goto rw_error;
8660 return 0;
8661 rw_error:
8662 return -EIO;
8665 /*============================================================================*/
8668 * \fn int set_qam128 ()
8669 * \brief QAM128 specific setup
8670 * \param demod: instance of demod.
8671 * \return int.
8673 static int set_qam128(struct drx_demod_instance *demod)
8675 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
8676 int rc;
8677 const u8 qam_dq_qual_fun[] = {
8678 DRXJ_16TO8(6), /* fun0 */
8679 DRXJ_16TO8(6), /* fun1 */
8680 DRXJ_16TO8(6), /* fun2 */
8681 DRXJ_16TO8(6), /* fun3 */
8682 DRXJ_16TO8(9), /* fun4 */
8683 DRXJ_16TO8(9), /* fun5 */
8685 const u8 qam_eq_cma_rad[] = {
8686 DRXJ_16TO8(6164), /* RAD0 */
8687 DRXJ_16TO8(6598), /* RAD1 */
8688 DRXJ_16TO8(6394), /* RAD2 */
8689 DRXJ_16TO8(6409), /* RAD3 */
8690 DRXJ_16TO8(6656), /* RAD4 */
8691 DRXJ_16TO8(7238), /* RAD5 */
8694 rc = DRXJ_DAP.write_block_func(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun), ((u8 *)qam_dq_qual_fun), 0);
8695 if (rc != 0) {
8696 pr_err("error %d\n", rc);
8697 goto rw_error;
8699 rc = DRXJ_DAP.write_block_func(dev_addr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qam_eq_cma_rad), ((u8 *)qam_eq_cma_rad), 0);
8700 if (rc != 0) {
8701 pr_err("error %d\n", rc);
8702 goto rw_error;
8705 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 50, 0);
8706 if (rc != 0) {
8707 pr_err("error %d\n", rc);
8708 goto rw_error;
8710 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 60, 0);
8711 if (rc != 0) {
8712 pr_err("error %d\n", rc);
8713 goto rw_error;
8715 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 100, 0);
8716 if (rc != 0) {
8717 pr_err("error %d\n", rc);
8718 goto rw_error;
8720 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 140, 0);
8721 if (rc != 0) {
8722 pr_err("error %d\n", rc);
8723 goto rw_error;
8725 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 80, 0);
8726 if (rc != 0) {
8727 pr_err("error %d\n", rc);
8728 goto rw_error;
8730 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 100, 0);
8731 if (rc != 0) {
8732 pr_err("error %d\n", rc);
8733 goto rw_error;
8736 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40, 0);
8737 if (rc != 0) {
8738 pr_err("error %d\n", rc);
8739 goto rw_error;
8741 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 32, 0);
8742 if (rc != 0) {
8743 pr_err("error %d\n", rc);
8744 goto rw_error;
8746 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3, 0);
8747 if (rc != 0) {
8748 pr_err("error %d\n", rc);
8749 goto rw_error;
8752 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 8, 0);
8753 if (rc != 0) {
8754 pr_err("error %d\n", rc);
8755 goto rw_error;
8757 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 65, 0);
8758 if (rc != 0) {
8759 pr_err("error %d\n", rc);
8760 goto rw_error;
8762 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 5, 0);
8763 if (rc != 0) {
8764 pr_err("error %d\n", rc);
8765 goto rw_error;
8767 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 3, 0);
8768 if (rc != 0) {
8769 pr_err("error %d\n", rc);
8770 goto rw_error;
8772 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16)(-1), 0);
8773 if (rc != 0) {
8774 pr_err("error %d\n", rc);
8775 goto rw_error;
8777 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, 12, 0);
8778 if (rc != 0) {
8779 pr_err("error %d\n", rc);
8780 goto rw_error;
8782 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16)(-23), 0);
8783 if (rc != 0) {
8784 pr_err("error %d\n", rc);
8785 goto rw_error;
8788 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15, 0);
8789 if (rc != 0) {
8790 pr_err("error %d\n", rc);
8791 goto rw_error;
8793 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40, 0);
8794 if (rc != 0) {
8795 pr_err("error %d\n", rc);
8796 goto rw_error;
8798 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2, 0);
8799 if (rc != 0) {
8800 pr_err("error %d\n", rc);
8801 goto rw_error;
8803 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 40, 0);
8804 if (rc != 0) {
8805 pr_err("error %d\n", rc);
8806 goto rw_error;
8808 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255, 0);
8809 if (rc != 0) {
8810 pr_err("error %d\n", rc);
8811 goto rw_error;
8813 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2, 0);
8814 if (rc != 0) {
8815 pr_err("error %d\n", rc);
8816 goto rw_error;
8818 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 20, 0);
8819 if (rc != 0) {
8820 pr_err("error %d\n", rc);
8821 goto rw_error;
8823 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 80, 0);
8824 if (rc != 0) {
8825 pr_err("error %d\n", rc);
8826 goto rw_error;
8828 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12, 0);
8829 if (rc != 0) {
8830 pr_err("error %d\n", rc);
8831 goto rw_error;
8833 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24, 0);
8834 if (rc != 0) {
8835 pr_err("error %d\n", rc);
8836 goto rw_error;
8838 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24, 0);
8839 if (rc != 0) {
8840 pr_err("error %d\n", rc);
8841 goto rw_error;
8843 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12, 0);
8844 if (rc != 0) {
8845 pr_err("error %d\n", rc);
8846 goto rw_error;
8848 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16, 0);
8849 if (rc != 0) {
8850 pr_err("error %d\n", rc);
8851 goto rw_error;
8853 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16, 0);
8854 if (rc != 0) {
8855 pr_err("error %d\n", rc);
8856 goto rw_error;
8858 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16, 0);
8859 if (rc != 0) {
8860 pr_err("error %d\n", rc);
8861 goto rw_error;
8863 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 32, 0);
8864 if (rc != 0) {
8865 pr_err("error %d\n", rc);
8866 goto rw_error;
8868 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 144, 0);
8869 if (rc != 0) {
8870 pr_err("error %d\n", rc);
8871 goto rw_error;
8873 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5, 0);
8874 if (rc != 0) {
8875 pr_err("error %d\n", rc);
8876 goto rw_error;
8878 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15, 0);
8879 if (rc != 0) {
8880 pr_err("error %d\n", rc);
8881 goto rw_error;
8883 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 16, 0);
8884 if (rc != 0) {
8885 pr_err("error %d\n", rc);
8886 goto rw_error;
8889 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 20992, 0);
8890 if (rc != 0) {
8891 pr_err("error %d\n", rc);
8892 goto rw_error;
8895 return 0;
8896 rw_error:
8897 return -EIO;
8900 /*============================================================================*/
8903 * \fn int set_qam256 ()
8904 * \brief QAM256 specific setup
8905 * \param demod: instance of demod.
8906 * \return int.
8908 static int set_qam256(struct drx_demod_instance *demod)
8910 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
8911 int rc;
8912 const u8 qam_dq_qual_fun[] = {
8913 DRXJ_16TO8(8), /* fun0 */
8914 DRXJ_16TO8(8), /* fun1 */
8915 DRXJ_16TO8(8), /* fun2 */
8916 DRXJ_16TO8(8), /* fun3 */
8917 DRXJ_16TO8(12), /* fun4 */
8918 DRXJ_16TO8(12), /* fun5 */
8920 const u8 qam_eq_cma_rad[] = {
8921 DRXJ_16TO8(12345), /* RAD0 */
8922 DRXJ_16TO8(12345), /* RAD1 */
8923 DRXJ_16TO8(13626), /* RAD2 */
8924 DRXJ_16TO8(12931), /* RAD3 */
8925 DRXJ_16TO8(14719), /* RAD4 */
8926 DRXJ_16TO8(15356), /* RAD5 */
8929 rc = DRXJ_DAP.write_block_func(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun), ((u8 *)qam_dq_qual_fun), 0);
8930 if (rc != 0) {
8931 pr_err("error %d\n", rc);
8932 goto rw_error;
8934 rc = DRXJ_DAP.write_block_func(dev_addr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qam_eq_cma_rad), ((u8 *)qam_eq_cma_rad), 0);
8935 if (rc != 0) {
8936 pr_err("error %d\n", rc);
8937 goto rw_error;
8940 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 50, 0);
8941 if (rc != 0) {
8942 pr_err("error %d\n", rc);
8943 goto rw_error;
8945 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 60, 0);
8946 if (rc != 0) {
8947 pr_err("error %d\n", rc);
8948 goto rw_error;
8950 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 100, 0);
8951 if (rc != 0) {
8952 pr_err("error %d\n", rc);
8953 goto rw_error;
8955 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 150, 0);
8956 if (rc != 0) {
8957 pr_err("error %d\n", rc);
8958 goto rw_error;
8960 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 80, 0);
8961 if (rc != 0) {
8962 pr_err("error %d\n", rc);
8963 goto rw_error;
8965 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 110, 0);
8966 if (rc != 0) {
8967 pr_err("error %d\n", rc);
8968 goto rw_error;
8971 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40, 0);
8972 if (rc != 0) {
8973 pr_err("error %d\n", rc);
8974 goto rw_error;
8976 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 16, 0);
8977 if (rc != 0) {
8978 pr_err("error %d\n", rc);
8979 goto rw_error;
8981 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3, 0);
8982 if (rc != 0) {
8983 pr_err("error %d\n", rc);
8984 goto rw_error;
8987 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 8, 0);
8988 if (rc != 0) {
8989 pr_err("error %d\n", rc);
8990 goto rw_error;
8992 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 74, 0);
8993 if (rc != 0) {
8994 pr_err("error %d\n", rc);
8995 goto rw_error;
8997 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 18, 0);
8998 if (rc != 0) {
8999 pr_err("error %d\n", rc);
9000 goto rw_error;
9002 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 13, 0);
9003 if (rc != 0) {
9004 pr_err("error %d\n", rc);
9005 goto rw_error;
9007 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, 7, 0);
9008 if (rc != 0) {
9009 pr_err("error %d\n", rc);
9010 goto rw_error;
9012 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, 0, 0);
9013 if (rc != 0) {
9014 pr_err("error %d\n", rc);
9015 goto rw_error;
9017 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16)(-8), 0);
9018 if (rc != 0) {
9019 pr_err("error %d\n", rc);
9020 goto rw_error;
9023 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15, 0);
9024 if (rc != 0) {
9025 pr_err("error %d\n", rc);
9026 goto rw_error;
9028 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40, 0);
9029 if (rc != 0) {
9030 pr_err("error %d\n", rc);
9031 goto rw_error;
9033 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2, 0);
9034 if (rc != 0) {
9035 pr_err("error %d\n", rc);
9036 goto rw_error;
9038 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 50, 0);
9039 if (rc != 0) {
9040 pr_err("error %d\n", rc);
9041 goto rw_error;
9043 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255, 0);
9044 if (rc != 0) {
9045 pr_err("error %d\n", rc);
9046 goto rw_error;
9048 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2, 0);
9049 if (rc != 0) {
9050 pr_err("error %d\n", rc);
9051 goto rw_error;
9053 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 25, 0);
9054 if (rc != 0) {
9055 pr_err("error %d\n", rc);
9056 goto rw_error;
9058 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 80, 0);
9059 if (rc != 0) {
9060 pr_err("error %d\n", rc);
9061 goto rw_error;
9063 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12, 0);
9064 if (rc != 0) {
9065 pr_err("error %d\n", rc);
9066 goto rw_error;
9068 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24, 0);
9069 if (rc != 0) {
9070 pr_err("error %d\n", rc);
9071 goto rw_error;
9073 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24, 0);
9074 if (rc != 0) {
9075 pr_err("error %d\n", rc);
9076 goto rw_error;
9078 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12, 0);
9079 if (rc != 0) {
9080 pr_err("error %d\n", rc);
9081 goto rw_error;
9083 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16, 0);
9084 if (rc != 0) {
9085 pr_err("error %d\n", rc);
9086 goto rw_error;
9088 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16, 0);
9089 if (rc != 0) {
9090 pr_err("error %d\n", rc);
9091 goto rw_error;
9093 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16, 0);
9094 if (rc != 0) {
9095 pr_err("error %d\n", rc);
9096 goto rw_error;
9098 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 48, 0);
9099 if (rc != 0) {
9100 pr_err("error %d\n", rc);
9101 goto rw_error;
9103 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 80, 0);
9104 if (rc != 0) {
9105 pr_err("error %d\n", rc);
9106 goto rw_error;
9108 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5, 0);
9109 if (rc != 0) {
9110 pr_err("error %d\n", rc);
9111 goto rw_error;
9113 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15, 0);
9114 if (rc != 0) {
9115 pr_err("error %d\n", rc);
9116 goto rw_error;
9118 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 16, 0);
9119 if (rc != 0) {
9120 pr_err("error %d\n", rc);
9121 goto rw_error;
9124 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 43520, 0);
9125 if (rc != 0) {
9126 pr_err("error %d\n", rc);
9127 goto rw_error;
9130 return 0;
9131 rw_error:
9132 return -EIO;
9135 /*============================================================================*/
9136 #define QAM_SET_OP_ALL 0x1
9137 #define QAM_SET_OP_CONSTELLATION 0x2
9138 #define QAM_SET_OP_SPECTRUM 0X4
9141 * \fn int set_qam ()
9142 * \brief Set QAM demod.
9143 * \param demod: instance of demod.
9144 * \param channel: pointer to channel data.
9145 * \return int.
9147 static int
9148 set_qam(struct drx_demod_instance *demod,
9149 struct drx_channel *channel, s32 tuner_freq_offset, u32 op)
9151 struct i2c_device_addr *dev_addr = NULL;
9152 struct drxj_data *ext_attr = NULL;
9153 struct drx_common_attr *common_attr = NULL;
9154 int rc;
9155 u32 adc_frequency = 0;
9156 u32 iqm_rc_rate = 0;
9157 u16 cmd_result = 0;
9158 u16 lc_symbol_freq = 0;
9159 u16 iqm_rc_stretch = 0;
9160 u16 set_env_parameters = 0;
9161 u16 set_param_parameters[2] = { 0 };
9162 struct drxjscu_cmd cmd_scu = { /* command */ 0,
9163 /* parameter_len */ 0,
9164 /* result_len */ 0,
9165 /* parameter */ NULL,
9166 /* result */ NULL
9168 const u8 qam_a_taps[] = {
9169 DRXJ_16TO8(-1), /* re0 */
9170 DRXJ_16TO8(1), /* re1 */
9171 DRXJ_16TO8(1), /* re2 */
9172 DRXJ_16TO8(-1), /* re3 */
9173 DRXJ_16TO8(-1), /* re4 */
9174 DRXJ_16TO8(2), /* re5 */
9175 DRXJ_16TO8(1), /* re6 */
9176 DRXJ_16TO8(-2), /* re7 */
9177 DRXJ_16TO8(0), /* re8 */
9178 DRXJ_16TO8(3), /* re9 */
9179 DRXJ_16TO8(-1), /* re10 */
9180 DRXJ_16TO8(-3), /* re11 */
9181 DRXJ_16TO8(4), /* re12 */
9182 DRXJ_16TO8(1), /* re13 */
9183 DRXJ_16TO8(-8), /* re14 */
9184 DRXJ_16TO8(4), /* re15 */
9185 DRXJ_16TO8(13), /* re16 */
9186 DRXJ_16TO8(-13), /* re17 */
9187 DRXJ_16TO8(-19), /* re18 */
9188 DRXJ_16TO8(28), /* re19 */
9189 DRXJ_16TO8(25), /* re20 */
9190 DRXJ_16TO8(-53), /* re21 */
9191 DRXJ_16TO8(-31), /* re22 */
9192 DRXJ_16TO8(96), /* re23 */
9193 DRXJ_16TO8(37), /* re24 */
9194 DRXJ_16TO8(-190), /* re25 */
9195 DRXJ_16TO8(-40), /* re26 */
9196 DRXJ_16TO8(619) /* re27 */
9198 const u8 qam_b64_taps[] = {
9199 DRXJ_16TO8(0), /* re0 */
9200 DRXJ_16TO8(-2), /* re1 */
9201 DRXJ_16TO8(1), /* re2 */
9202 DRXJ_16TO8(2), /* re3 */
9203 DRXJ_16TO8(-2), /* re4 */
9204 DRXJ_16TO8(0), /* re5 */
9205 DRXJ_16TO8(4), /* re6 */
9206 DRXJ_16TO8(-2), /* re7 */
9207 DRXJ_16TO8(-4), /* re8 */
9208 DRXJ_16TO8(4), /* re9 */
9209 DRXJ_16TO8(3), /* re10 */
9210 DRXJ_16TO8(-6), /* re11 */
9211 DRXJ_16TO8(0), /* re12 */
9212 DRXJ_16TO8(6), /* re13 */
9213 DRXJ_16TO8(-5), /* re14 */
9214 DRXJ_16TO8(-3), /* re15 */
9215 DRXJ_16TO8(11), /* re16 */
9216 DRXJ_16TO8(-4), /* re17 */
9217 DRXJ_16TO8(-19), /* re18 */
9218 DRXJ_16TO8(19), /* re19 */
9219 DRXJ_16TO8(28), /* re20 */
9220 DRXJ_16TO8(-45), /* re21 */
9221 DRXJ_16TO8(-36), /* re22 */
9222 DRXJ_16TO8(90), /* re23 */
9223 DRXJ_16TO8(42), /* re24 */
9224 DRXJ_16TO8(-185), /* re25 */
9225 DRXJ_16TO8(-46), /* re26 */
9226 DRXJ_16TO8(614) /* re27 */
9228 const u8 qam_b256_taps[] = {
9229 DRXJ_16TO8(-2), /* re0 */
9230 DRXJ_16TO8(4), /* re1 */
9231 DRXJ_16TO8(1), /* re2 */
9232 DRXJ_16TO8(-4), /* re3 */
9233 DRXJ_16TO8(0), /* re4 */
9234 DRXJ_16TO8(4), /* re5 */
9235 DRXJ_16TO8(-2), /* re6 */
9236 DRXJ_16TO8(-4), /* re7 */
9237 DRXJ_16TO8(5), /* re8 */
9238 DRXJ_16TO8(2), /* re9 */
9239 DRXJ_16TO8(-8), /* re10 */
9240 DRXJ_16TO8(2), /* re11 */
9241 DRXJ_16TO8(11), /* re12 */
9242 DRXJ_16TO8(-8), /* re13 */
9243 DRXJ_16TO8(-15), /* re14 */
9244 DRXJ_16TO8(16), /* re15 */
9245 DRXJ_16TO8(19), /* re16 */
9246 DRXJ_16TO8(-27), /* re17 */
9247 DRXJ_16TO8(-22), /* re18 */
9248 DRXJ_16TO8(44), /* re19 */
9249 DRXJ_16TO8(26), /* re20 */
9250 DRXJ_16TO8(-69), /* re21 */
9251 DRXJ_16TO8(-28), /* re22 */
9252 DRXJ_16TO8(110), /* re23 */
9253 DRXJ_16TO8(31), /* re24 */
9254 DRXJ_16TO8(-201), /* re25 */
9255 DRXJ_16TO8(-32), /* re26 */
9256 DRXJ_16TO8(628) /* re27 */
9258 const u8 qam_c_taps[] = {
9259 DRXJ_16TO8(-3), /* re0 */
9260 DRXJ_16TO8(3), /* re1 */
9261 DRXJ_16TO8(2), /* re2 */
9262 DRXJ_16TO8(-4), /* re3 */
9263 DRXJ_16TO8(0), /* re4 */
9264 DRXJ_16TO8(4), /* re5 */
9265 DRXJ_16TO8(-1), /* re6 */
9266 DRXJ_16TO8(-4), /* re7 */
9267 DRXJ_16TO8(3), /* re8 */
9268 DRXJ_16TO8(3), /* re9 */
9269 DRXJ_16TO8(-5), /* re10 */
9270 DRXJ_16TO8(0), /* re11 */
9271 DRXJ_16TO8(9), /* re12 */
9272 DRXJ_16TO8(-4), /* re13 */
9273 DRXJ_16TO8(-12), /* re14 */
9274 DRXJ_16TO8(10), /* re15 */
9275 DRXJ_16TO8(16), /* re16 */
9276 DRXJ_16TO8(-21), /* re17 */
9277 DRXJ_16TO8(-20), /* re18 */
9278 DRXJ_16TO8(37), /* re19 */
9279 DRXJ_16TO8(25), /* re20 */
9280 DRXJ_16TO8(-62), /* re21 */
9281 DRXJ_16TO8(-28), /* re22 */
9282 DRXJ_16TO8(105), /* re23 */
9283 DRXJ_16TO8(31), /* re24 */
9284 DRXJ_16TO8(-197), /* re25 */
9285 DRXJ_16TO8(-33), /* re26 */
9286 DRXJ_16TO8(626) /* re27 */
9289 dev_addr = demod->my_i2c_dev_addr;
9290 ext_attr = (struct drxj_data *) demod->my_ext_attr;
9291 common_attr = (struct drx_common_attr *) demod->my_common_attr;
9293 if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
9294 if (ext_attr->standard == DRX_STANDARD_ITU_B) {
9295 switch (channel->constellation) {
9296 case DRX_CONSTELLATION_QAM256:
9297 iqm_rc_rate = 0x00AE3562;
9298 lc_symbol_freq =
9299 QAM_LC_SYMBOL_FREQ_FREQ_QAM_B_256;
9300 channel->symbolrate = 5360537;
9301 iqm_rc_stretch = IQM_RC_STRETCH_QAM_B_256;
9302 break;
9303 case DRX_CONSTELLATION_QAM64:
9304 iqm_rc_rate = 0x00C05A0E;
9305 lc_symbol_freq = 409;
9306 channel->symbolrate = 5056941;
9307 iqm_rc_stretch = IQM_RC_STRETCH_QAM_B_64;
9308 break;
9309 default:
9310 return -EINVAL;
9312 } else {
9313 adc_frequency = (common_attr->sys_clock_freq * 1000) / 3;
9314 if (channel->symbolrate == 0) {
9315 pr_err("error: channel symbolrate is zero!\n");
9316 return -EIO;
9318 iqm_rc_rate =
9319 (adc_frequency / channel->symbolrate) * (1 << 21) +
9320 (frac28
9321 ((adc_frequency % channel->symbolrate),
9322 channel->symbolrate) >> 7) - (1 << 23);
9323 lc_symbol_freq =
9324 (u16) (frac28
9325 (channel->symbolrate +
9326 (adc_frequency >> 13),
9327 adc_frequency) >> 16);
9328 if (lc_symbol_freq > 511)
9329 lc_symbol_freq = 511;
9331 iqm_rc_stretch = 21;
9334 if (ext_attr->standard == DRX_STANDARD_ITU_A) {
9335 set_env_parameters = QAM_TOP_ANNEX_A; /* annex */
9336 set_param_parameters[0] = channel->constellation; /* constellation */
9337 set_param_parameters[1] = DRX_INTERLEAVEMODE_I12_J17; /* interleave mode */
9338 } else if (ext_attr->standard == DRX_STANDARD_ITU_B) {
9339 set_env_parameters = QAM_TOP_ANNEX_B; /* annex */
9340 set_param_parameters[0] = channel->constellation; /* constellation */
9341 set_param_parameters[1] = channel->interleavemode; /* interleave mode */
9342 } else if (ext_attr->standard == DRX_STANDARD_ITU_C) {
9343 set_env_parameters = QAM_TOP_ANNEX_C; /* annex */
9344 set_param_parameters[0] = channel->constellation; /* constellation */
9345 set_param_parameters[1] = DRX_INTERLEAVEMODE_I12_J17; /* interleave mode */
9346 } else {
9347 return -EINVAL;
9351 if (op & QAM_SET_OP_ALL) {
9353 STEP 1: reset demodulator
9354 resets IQM, QAM and FEC HW blocks
9355 resets SCU variables
9357 /* stop all comm_exec */
9358 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP, 0);
9359 if (rc != 0) {
9360 pr_err("error %d\n", rc);
9361 goto rw_error;
9363 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP, 0);
9364 if (rc != 0) {
9365 pr_err("error %d\n", rc);
9366 goto rw_error;
9368 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0);
9369 if (rc != 0) {
9370 pr_err("error %d\n", rc);
9371 goto rw_error;
9373 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0);
9374 if (rc != 0) {
9375 pr_err("error %d\n", rc);
9376 goto rw_error;
9378 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0);
9379 if (rc != 0) {
9380 pr_err("error %d\n", rc);
9381 goto rw_error;
9383 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0);
9384 if (rc != 0) {
9385 pr_err("error %d\n", rc);
9386 goto rw_error;
9388 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0);
9389 if (rc != 0) {
9390 pr_err("error %d\n", rc);
9391 goto rw_error;
9394 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
9395 SCU_RAM_COMMAND_CMD_DEMOD_RESET;
9396 cmd_scu.parameter_len = 0;
9397 cmd_scu.result_len = 1;
9398 cmd_scu.parameter = NULL;
9399 cmd_scu.result = &cmd_result;
9400 rc = scu_command(dev_addr, &cmd_scu);
9401 if (rc != 0) {
9402 pr_err("error %d\n", rc);
9403 goto rw_error;
9407 if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
9409 STEP 2: configure demodulator
9410 -set env
9411 -set params (resets IQM,QAM,FEC HW; initializes some SCU variables )
9413 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
9414 SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV;
9415 cmd_scu.parameter_len = 1;
9416 cmd_scu.result_len = 1;
9417 cmd_scu.parameter = &set_env_parameters;
9418 cmd_scu.result = &cmd_result;
9419 rc = scu_command(dev_addr, &cmd_scu);
9420 if (rc != 0) {
9421 pr_err("error %d\n", rc);
9422 goto rw_error;
9425 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
9426 SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM;
9427 cmd_scu.parameter_len = 2;
9428 cmd_scu.result_len = 1;
9429 cmd_scu.parameter = set_param_parameters;
9430 cmd_scu.result = &cmd_result;
9431 rc = scu_command(dev_addr, &cmd_scu);
9432 if (rc != 0) {
9433 pr_err("error %d\n", rc);
9434 goto rw_error;
9436 /* set symbol rate */
9437 rc = DRXJ_DAP.write_reg32func(dev_addr, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate, 0);
9438 if (rc != 0) {
9439 pr_err("error %d\n", rc);
9440 goto rw_error;
9442 ext_attr->iqm_rc_rate_ofs = iqm_rc_rate;
9443 rc = set_qam_measurement(demod, channel->constellation, channel->symbolrate);
9444 if (rc != 0) {
9445 pr_err("error %d\n", rc);
9446 goto rw_error;
9449 /* STEP 3: enable the system in a mode where the ADC provides valid signal
9450 setup constellation independent registers */
9451 /* from qam_cmd.py script (qam_driver_b) */
9452 /* TODO: remove re-writes of HW reset values */
9453 if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_SPECTRUM)) {
9454 rc = set_frequency(demod, channel, tuner_freq_offset);
9455 if (rc != 0) {
9456 pr_err("error %d\n", rc);
9457 goto rw_error;
9461 if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
9463 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_SYMBOL_FREQ__A, lc_symbol_freq, 0);
9464 if (rc != 0) {
9465 pr_err("error %d\n", rc);
9466 goto rw_error;
9468 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RC_STRETCH__A, iqm_rc_stretch, 0);
9469 if (rc != 0) {
9470 pr_err("error %d\n", rc);
9471 goto rw_error;
9475 if (op & QAM_SET_OP_ALL) {
9476 if (!ext_attr->has_lna) {
9477 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_AMUX__A, 0x02, 0);
9478 if (rc != 0) {
9479 pr_err("error %d\n", rc);
9480 goto rw_error;
9483 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_SYMMETRIC__A, 0, 0);
9484 if (rc != 0) {
9485 pr_err("error %d\n", rc);
9486 goto rw_error;
9488 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_MIDTAP__A, 3, 0);
9489 if (rc != 0) {
9490 pr_err("error %d\n", rc);
9491 goto rw_error;
9493 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_OUT_ENA__A, IQM_CF_OUT_ENA_QAM__M, 0);
9494 if (rc != 0) {
9495 pr_err("error %d\n", rc);
9496 goto rw_error;
9499 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_WR_RSV_0__A, 0x5f, 0);
9500 if (rc != 0) {
9501 pr_err("error %d\n", rc);
9502 goto rw_error;
9503 } /* scu temporary shut down agc */
9505 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_SYNC_SEL__A, 3, 0);
9506 if (rc != 0) {
9507 pr_err("error %d\n", rc);
9508 goto rw_error;
9510 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_CLP_LEN__A, 0, 0);
9511 if (rc != 0) {
9512 pr_err("error %d\n", rc);
9513 goto rw_error;
9515 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_CLP_TH__A, 448, 0);
9516 if (rc != 0) {
9517 pr_err("error %d\n", rc);
9518 goto rw_error;
9520 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_SNS_LEN__A, 0, 0);
9521 if (rc != 0) {
9522 pr_err("error %d\n", rc);
9523 goto rw_error;
9525 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_PDREF__A, 4, 0);
9526 if (rc != 0) {
9527 pr_err("error %d\n", rc);
9528 goto rw_error;
9530 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_STDBY__A, 0x10, 0);
9531 if (rc != 0) {
9532 pr_err("error %d\n", rc);
9533 goto rw_error;
9535 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_PGA_GAIN__A, 11, 0);
9536 if (rc != 0) {
9537 pr_err("error %d\n", rc);
9538 goto rw_error;
9541 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_POW_MEAS_LEN__A, 1, 0);
9542 if (rc != 0) {
9543 pr_err("error %d\n", rc);
9544 goto rw_error;
9546 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_SCALE_SH__A, IQM_CF_SCALE_SH__PRE, 0);
9547 if (rc != 0) {
9548 pr_err("error %d\n", rc);
9549 goto rw_error;
9550 } /*! reset default val ! */
9552 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_SY_TIMEOUT__A, QAM_SY_TIMEOUT__PRE, 0);
9553 if (rc != 0) {
9554 pr_err("error %d\n", rc);
9555 goto rw_error;
9556 } /*! reset default val ! */
9557 if (ext_attr->standard == DRX_STANDARD_ITU_B) {
9558 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_SY_SYNC_LWM__A, QAM_SY_SYNC_LWM__PRE, 0);
9559 if (rc != 0) {
9560 pr_err("error %d\n", rc);
9561 goto rw_error;
9562 } /*! reset default val ! */
9563 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_SY_SYNC_AWM__A, QAM_SY_SYNC_AWM__PRE, 0);
9564 if (rc != 0) {
9565 pr_err("error %d\n", rc);
9566 goto rw_error;
9567 } /*! reset default val ! */
9568 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_SY_SYNC_HWM__A, QAM_SY_SYNC_HWM__PRE, 0);
9569 if (rc != 0) {
9570 pr_err("error %d\n", rc);
9571 goto rw_error;
9572 } /*! reset default val ! */
9573 } else {
9574 switch (channel->constellation) {
9575 case DRX_CONSTELLATION_QAM16:
9576 case DRX_CONSTELLATION_QAM64:
9577 case DRX_CONSTELLATION_QAM256:
9578 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_SY_SYNC_LWM__A, 0x03, 0);
9579 if (rc != 0) {
9580 pr_err("error %d\n", rc);
9581 goto rw_error;
9583 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_SY_SYNC_AWM__A, 0x04, 0);
9584 if (rc != 0) {
9585 pr_err("error %d\n", rc);
9586 goto rw_error;
9588 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_SY_SYNC_HWM__A, QAM_SY_SYNC_HWM__PRE, 0);
9589 if (rc != 0) {
9590 pr_err("error %d\n", rc);
9591 goto rw_error;
9592 } /*! reset default val ! */
9593 break;
9594 case DRX_CONSTELLATION_QAM32:
9595 case DRX_CONSTELLATION_QAM128:
9596 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_SY_SYNC_LWM__A, 0x03, 0);
9597 if (rc != 0) {
9598 pr_err("error %d\n", rc);
9599 goto rw_error;
9601 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_SY_SYNC_AWM__A, 0x05, 0);
9602 if (rc != 0) {
9603 pr_err("error %d\n", rc);
9604 goto rw_error;
9606 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_SY_SYNC_HWM__A, 0x06, 0);
9607 if (rc != 0) {
9608 pr_err("error %d\n", rc);
9609 goto rw_error;
9611 break;
9612 default:
9613 return -EIO;
9614 } /* switch */
9617 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_MODE__A, QAM_LC_MODE__PRE, 0);
9618 if (rc != 0) {
9619 pr_err("error %d\n", rc);
9620 goto rw_error;
9621 } /*! reset default val ! */
9622 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_RATE_LIMIT__A, 3, 0);
9623 if (rc != 0) {
9624 pr_err("error %d\n", rc);
9625 goto rw_error;
9627 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_LPF_FACTORP__A, 4, 0);
9628 if (rc != 0) {
9629 pr_err("error %d\n", rc);
9630 goto rw_error;
9632 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_LPF_FACTORI__A, 4, 0);
9633 if (rc != 0) {
9634 pr_err("error %d\n", rc);
9635 goto rw_error;
9637 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_MODE__A, 7, 0);
9638 if (rc != 0) {
9639 pr_err("error %d\n", rc);
9640 goto rw_error;
9642 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_QUAL_TAB0__A, 1, 0);
9643 if (rc != 0) {
9644 pr_err("error %d\n", rc);
9645 goto rw_error;
9647 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_QUAL_TAB1__A, 1, 0);
9648 if (rc != 0) {
9649 pr_err("error %d\n", rc);
9650 goto rw_error;
9652 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_QUAL_TAB2__A, 1, 0);
9653 if (rc != 0) {
9654 pr_err("error %d\n", rc);
9655 goto rw_error;
9657 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_QUAL_TAB3__A, 1, 0);
9658 if (rc != 0) {
9659 pr_err("error %d\n", rc);
9660 goto rw_error;
9662 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_QUAL_TAB4__A, 2, 0);
9663 if (rc != 0) {
9664 pr_err("error %d\n", rc);
9665 goto rw_error;
9667 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_QUAL_TAB5__A, 2, 0);
9668 if (rc != 0) {
9669 pr_err("error %d\n", rc);
9670 goto rw_error;
9672 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_QUAL_TAB6__A, 2, 0);
9673 if (rc != 0) {
9674 pr_err("error %d\n", rc);
9675 goto rw_error;
9677 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_QUAL_TAB8__A, 2, 0);
9678 if (rc != 0) {
9679 pr_err("error %d\n", rc);
9680 goto rw_error;
9682 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_QUAL_TAB9__A, 2, 0);
9683 if (rc != 0) {
9684 pr_err("error %d\n", rc);
9685 goto rw_error;
9687 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_QUAL_TAB10__A, 2, 0);
9688 if (rc != 0) {
9689 pr_err("error %d\n", rc);
9690 goto rw_error;
9692 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_QUAL_TAB12__A, 2, 0);
9693 if (rc != 0) {
9694 pr_err("error %d\n", rc);
9695 goto rw_error;
9697 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_QUAL_TAB15__A, 3, 0);
9698 if (rc != 0) {
9699 pr_err("error %d\n", rc);
9700 goto rw_error;
9702 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_QUAL_TAB16__A, 3, 0);
9703 if (rc != 0) {
9704 pr_err("error %d\n", rc);
9705 goto rw_error;
9707 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_QUAL_TAB20__A, 4, 0);
9708 if (rc != 0) {
9709 pr_err("error %d\n", rc);
9710 goto rw_error;
9712 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_QUAL_TAB25__A, 4, 0);
9713 if (rc != 0) {
9714 pr_err("error %d\n", rc);
9715 goto rw_error;
9718 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_FS_ADJ_SEL__A, 1, 0);
9719 if (rc != 0) {
9720 pr_err("error %d\n", rc);
9721 goto rw_error;
9723 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RC_ADJ_SEL__A, 1, 0);
9724 if (rc != 0) {
9725 pr_err("error %d\n", rc);
9726 goto rw_error;
9728 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_ADJ_SEL__A, 1, 0);
9729 if (rc != 0) {
9730 pr_err("error %d\n", rc);
9731 goto rw_error;
9733 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_POW_MEAS_LEN__A, 0, 0);
9734 if (rc != 0) {
9735 pr_err("error %d\n", rc);
9736 goto rw_error;
9738 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_GPIO__A, 0, 0);
9739 if (rc != 0) {
9740 pr_err("error %d\n", rc);
9741 goto rw_error;
9744 /* No more resets of the IQM, current standard correctly set =>
9745 now AGCs can be configured. */
9746 /* turn on IQMAF. It has to be in front of setAgc**() */
9747 rc = set_iqm_af(demod, true);
9748 if (rc != 0) {
9749 pr_err("error %d\n", rc);
9750 goto rw_error;
9752 rc = adc_synchronization(demod);
9753 if (rc != 0) {
9754 pr_err("error %d\n", rc);
9755 goto rw_error;
9758 rc = init_agc(demod);
9759 if (rc != 0) {
9760 pr_err("error %d\n", rc);
9761 goto rw_error;
9763 rc = set_agc_if(demod, &(ext_attr->qam_if_agc_cfg), false);
9764 if (rc != 0) {
9765 pr_err("error %d\n", rc);
9766 goto rw_error;
9768 rc = set_agc_rf(demod, &(ext_attr->qam_rf_agc_cfg), false);
9769 if (rc != 0) {
9770 pr_err("error %d\n", rc);
9771 goto rw_error;
9774 /* TODO fix this, store a struct drxj_cfg_afe_gain structure in struct drxj_data instead
9775 of only the gain */
9776 struct drxj_cfg_afe_gain qam_pga_cfg = { DRX_STANDARD_ITU_B, 0 };
9778 qam_pga_cfg.gain = ext_attr->qam_pga_cfg;
9779 rc = ctrl_set_cfg_afe_gain(demod, &qam_pga_cfg);
9780 if (rc != 0) {
9781 pr_err("error %d\n", rc);
9782 goto rw_error;
9785 rc = ctrl_set_cfg_pre_saw(demod, &(ext_attr->qam_pre_saw_cfg));
9786 if (rc != 0) {
9787 pr_err("error %d\n", rc);
9788 goto rw_error;
9792 if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
9793 if (ext_attr->standard == DRX_STANDARD_ITU_A) {
9794 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_RE0__A, sizeof(qam_a_taps), ((u8 *)qam_a_taps), 0);
9795 if (rc != 0) {
9796 pr_err("error %d\n", rc);
9797 goto rw_error;
9799 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_IM0__A, sizeof(qam_a_taps), ((u8 *)qam_a_taps), 0);
9800 if (rc != 0) {
9801 pr_err("error %d\n", rc);
9802 goto rw_error;
9804 } else if (ext_attr->standard == DRX_STANDARD_ITU_B) {
9805 switch (channel->constellation) {
9806 case DRX_CONSTELLATION_QAM64:
9807 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_RE0__A, sizeof(qam_b64_taps), ((u8 *)qam_b64_taps), 0);
9808 if (rc != 0) {
9809 pr_err("error %d\n", rc);
9810 goto rw_error;
9812 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_IM0__A, sizeof(qam_b64_taps), ((u8 *)qam_b64_taps), 0);
9813 if (rc != 0) {
9814 pr_err("error %d\n", rc);
9815 goto rw_error;
9817 break;
9818 case DRX_CONSTELLATION_QAM256:
9819 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_RE0__A, sizeof(qam_b256_taps), ((u8 *)qam_b256_taps), 0);
9820 if (rc != 0) {
9821 pr_err("error %d\n", rc);
9822 goto rw_error;
9824 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_IM0__A, sizeof(qam_b256_taps), ((u8 *)qam_b256_taps), 0);
9825 if (rc != 0) {
9826 pr_err("error %d\n", rc);
9827 goto rw_error;
9829 break;
9830 default:
9831 return -EIO;
9833 } else if (ext_attr->standard == DRX_STANDARD_ITU_C) {
9834 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_RE0__A, sizeof(qam_c_taps), ((u8 *)qam_c_taps), 0);
9835 if (rc != 0) {
9836 pr_err("error %d\n", rc);
9837 goto rw_error;
9839 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_IM0__A, sizeof(qam_c_taps), ((u8 *)qam_c_taps), 0);
9840 if (rc != 0) {
9841 pr_err("error %d\n", rc);
9842 goto rw_error;
9846 /* SETP 4: constellation specific setup */
9847 switch (channel->constellation) {
9848 case DRX_CONSTELLATION_QAM16:
9849 rc = set_qam16(demod);
9850 if (rc != 0) {
9851 pr_err("error %d\n", rc);
9852 goto rw_error;
9854 break;
9855 case DRX_CONSTELLATION_QAM32:
9856 rc = set_qam32(demod);
9857 if (rc != 0) {
9858 pr_err("error %d\n", rc);
9859 goto rw_error;
9861 break;
9862 case DRX_CONSTELLATION_QAM64:
9863 rc = set_qam64(demod);
9864 if (rc != 0) {
9865 pr_err("error %d\n", rc);
9866 goto rw_error;
9868 break;
9869 case DRX_CONSTELLATION_QAM128:
9870 rc = set_qam128(demod);
9871 if (rc != 0) {
9872 pr_err("error %d\n", rc);
9873 goto rw_error;
9875 break;
9876 case DRX_CONSTELLATION_QAM256:
9877 rc = set_qam256(demod);
9878 if (rc != 0) {
9879 pr_err("error %d\n", rc);
9880 goto rw_error;
9882 break;
9883 default:
9884 return -EIO;
9885 } /* switch */
9888 if ((op & QAM_SET_OP_ALL)) {
9889 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_SCALE_SH__A, 0, 0);
9890 if (rc != 0) {
9891 pr_err("error %d\n", rc);
9892 goto rw_error;
9895 /* Mpeg output has to be in front of FEC active */
9896 rc = set_mpegtei_handling(demod);
9897 if (rc != 0) {
9898 pr_err("error %d\n", rc);
9899 goto rw_error;
9901 rc = bit_reverse_mpeg_output(demod);
9902 if (rc != 0) {
9903 pr_err("error %d\n", rc);
9904 goto rw_error;
9906 rc = set_mpeg_start_width(demod);
9907 if (rc != 0) {
9908 pr_err("error %d\n", rc);
9909 goto rw_error;
9912 /* TODO: move to set_standard after hardware reset value problem is solved */
9913 /* Configure initial MPEG output */
9914 struct drx_cfg_mpeg_output cfg_mpeg_output;
9916 cfg_mpeg_output.enable_mpeg_output = true;
9917 cfg_mpeg_output.insert_rs_byte =
9918 common_attr->mpeg_cfg.insert_rs_byte;
9919 cfg_mpeg_output.enable_parallel =
9920 common_attr->mpeg_cfg.enable_parallel;
9921 cfg_mpeg_output.invert_data =
9922 common_attr->mpeg_cfg.invert_data;
9923 cfg_mpeg_output.invert_err = common_attr->mpeg_cfg.invert_err;
9924 cfg_mpeg_output.invert_str = common_attr->mpeg_cfg.invert_str;
9925 cfg_mpeg_output.invert_val = common_attr->mpeg_cfg.invert_val;
9926 cfg_mpeg_output.invert_clk = common_attr->mpeg_cfg.invert_clk;
9927 cfg_mpeg_output.static_clk = common_attr->mpeg_cfg.static_clk;
9928 cfg_mpeg_output.bitrate = common_attr->mpeg_cfg.bitrate;
9929 rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output);
9930 if (rc != 0) {
9931 pr_err("error %d\n", rc);
9932 goto rw_error;
9937 if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
9939 /* STEP 5: start QAM demodulator (starts FEC, QAM and IQM HW) */
9940 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
9941 SCU_RAM_COMMAND_CMD_DEMOD_START;
9942 cmd_scu.parameter_len = 0;
9943 cmd_scu.result_len = 1;
9944 cmd_scu.parameter = NULL;
9945 cmd_scu.result = &cmd_result;
9946 rc = scu_command(dev_addr, &cmd_scu);
9947 if (rc != 0) {
9948 pr_err("error %d\n", rc);
9949 goto rw_error;
9953 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_ACTIVE, 0);
9954 if (rc != 0) {
9955 pr_err("error %d\n", rc);
9956 goto rw_error;
9958 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_COMM_EXEC__A, QAM_COMM_EXEC_ACTIVE, 0);
9959 if (rc != 0) {
9960 pr_err("error %d\n", rc);
9961 goto rw_error;
9963 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE, 0);
9964 if (rc != 0) {
9965 pr_err("error %d\n", rc);
9966 goto rw_error;
9969 return 0;
9970 rw_error:
9971 return -EIO;
9974 /*============================================================================*/
9975 static int
9976 ctrl_get_qam_sig_quality(struct drx_demod_instance *demod, struct drx_sig_quality *sig_quality);
9977 static int qam_flip_spec(struct drx_demod_instance *demod, struct drx_channel *channel)
9979 int rc;
9980 u32 iqm_fs_rate_ofs = 0;
9981 u32 iqm_fs_rate_lo = 0;
9982 u16 qam_ctl_ena = 0;
9983 u16 data = 0;
9984 u16 equ_mode = 0;
9985 u16 fsm_state = 0;
9986 int i = 0;
9987 int ofsofs = 0;
9988 struct i2c_device_addr *dev_addr = NULL;
9989 struct drxj_data *ext_attr = NULL;
9991 dev_addr = demod->my_i2c_dev_addr;
9992 ext_attr = (struct drxj_data *) demod->my_ext_attr;
9994 /* Silence the controlling of lc, equ, and the acquisition state machine */
9995 rc = DRXJ_DAP.read_reg16func(dev_addr, SCU_RAM_QAM_CTL_ENA__A, &qam_ctl_ena, 0);
9996 if (rc != 0) {
9997 pr_err("error %d\n", rc);
9998 goto rw_error;
10000 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_CTL_ENA__A, qam_ctl_ena & ~(SCU_RAM_QAM_CTL_ENA_ACQ__M | SCU_RAM_QAM_CTL_ENA_EQU__M | SCU_RAM_QAM_CTL_ENA_LC__M), 0);
10001 if (rc != 0) {
10002 pr_err("error %d\n", rc);
10003 goto rw_error;
10006 /* freeze the frequency control loop */
10007 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_CF__A, 0, 0);
10008 if (rc != 0) {
10009 pr_err("error %d\n", rc);
10010 goto rw_error;
10012 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_CF1__A, 0, 0);
10013 if (rc != 0) {
10014 pr_err("error %d\n", rc);
10015 goto rw_error;
10018 rc = drxj_dap_atomic_read_reg32(dev_addr, IQM_FS_RATE_OFS_LO__A, &iqm_fs_rate_ofs, 0);
10019 if (rc != 0) {
10020 pr_err("error %d\n", rc);
10021 goto rw_error;
10023 rc = drxj_dap_atomic_read_reg32(dev_addr, IQM_FS_RATE_LO__A, &iqm_fs_rate_lo, 0);
10024 if (rc != 0) {
10025 pr_err("error %d\n", rc);
10026 goto rw_error;
10028 ofsofs = iqm_fs_rate_lo - iqm_fs_rate_ofs;
10029 iqm_fs_rate_ofs = ~iqm_fs_rate_ofs + 1;
10030 iqm_fs_rate_ofs -= 2 * ofsofs;
10032 /* freeze dq/fq updating */
10033 rc = DRXJ_DAP.read_reg16func(dev_addr, QAM_DQ_MODE__A, &data, 0);
10034 if (rc != 0) {
10035 pr_err("error %d\n", rc);
10036 goto rw_error;
10038 data = (data & 0xfff9);
10039 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_DQ_MODE__A, data, 0);
10040 if (rc != 0) {
10041 pr_err("error %d\n", rc);
10042 goto rw_error;
10044 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_FQ_MODE__A, data, 0);
10045 if (rc != 0) {
10046 pr_err("error %d\n", rc);
10047 goto rw_error;
10050 /* lc_cp / _ci / _ca */
10051 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_CI__A, 0, 0);
10052 if (rc != 0) {
10053 pr_err("error %d\n", rc);
10054 goto rw_error;
10056 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_LC_EP__A, 0, 0);
10057 if (rc != 0) {
10058 pr_err("error %d\n", rc);
10059 goto rw_error;
10061 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_FQ_LA_FACTOR__A, 0, 0);
10062 if (rc != 0) {
10063 pr_err("error %d\n", rc);
10064 goto rw_error;
10067 /* flip the spec */
10068 rc = DRXJ_DAP.write_reg32func(dev_addr, IQM_FS_RATE_OFS_LO__A, iqm_fs_rate_ofs, 0);
10069 if (rc != 0) {
10070 pr_err("error %d\n", rc);
10071 goto rw_error;
10073 ext_attr->iqm_fs_rate_ofs = iqm_fs_rate_ofs;
10074 ext_attr->pos_image = (ext_attr->pos_image) ? false : true;
10076 /* freeze dq/fq updating */
10077 rc = DRXJ_DAP.read_reg16func(dev_addr, QAM_DQ_MODE__A, &data, 0);
10078 if (rc != 0) {
10079 pr_err("error %d\n", rc);
10080 goto rw_error;
10082 equ_mode = data;
10083 data = (data & 0xfff9);
10084 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_DQ_MODE__A, data, 0);
10085 if (rc != 0) {
10086 pr_err("error %d\n", rc);
10087 goto rw_error;
10089 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_FQ_MODE__A, data, 0);
10090 if (rc != 0) {
10091 pr_err("error %d\n", rc);
10092 goto rw_error;
10095 for (i = 0; i < 28; i++) {
10096 rc = DRXJ_DAP.read_reg16func(dev_addr, QAM_DQ_TAP_IM_EL0__A + (2 * i), &data, 0);
10097 if (rc != 0) {
10098 pr_err("error %d\n", rc);
10099 goto rw_error;
10101 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_DQ_TAP_IM_EL0__A + (2 * i), -data, 0);
10102 if (rc != 0) {
10103 pr_err("error %d\n", rc);
10104 goto rw_error;
10108 for (i = 0; i < 24; i++) {
10109 rc = DRXJ_DAP.read_reg16func(dev_addr, QAM_FQ_TAP_IM_EL0__A + (2 * i), &data, 0);
10110 if (rc != 0) {
10111 pr_err("error %d\n", rc);
10112 goto rw_error;
10114 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_FQ_TAP_IM_EL0__A + (2 * i), -data, 0);
10115 if (rc != 0) {
10116 pr_err("error %d\n", rc);
10117 goto rw_error;
10121 data = equ_mode;
10122 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_DQ_MODE__A, data, 0);
10123 if (rc != 0) {
10124 pr_err("error %d\n", rc);
10125 goto rw_error;
10127 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_FQ_MODE__A, data, 0);
10128 if (rc != 0) {
10129 pr_err("error %d\n", rc);
10130 goto rw_error;
10133 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_FSM_STATE_TGT__A, 4, 0);
10134 if (rc != 0) {
10135 pr_err("error %d\n", rc);
10136 goto rw_error;
10139 i = 0;
10140 while ((fsm_state != 4) && (i++ < 100)) {
10141 rc = DRXJ_DAP.read_reg16func(dev_addr, SCU_RAM_QAM_FSM_STATE__A, &fsm_state, 0);
10142 if (rc != 0) {
10143 pr_err("error %d\n", rc);
10144 goto rw_error;
10147 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_QAM_CTL_ENA__A, (qam_ctl_ena | 0x0016), 0);
10148 if (rc != 0) {
10149 pr_err("error %d\n", rc);
10150 goto rw_error;
10153 return 0;
10154 rw_error:
10155 return -EIO;
10159 #define NO_LOCK 0x0
10160 #define DEMOD_LOCKED 0x1
10161 #define SYNC_FLIPPED 0x2
10162 #define SPEC_MIRRORED 0x4
10164 * \fn int qam64auto ()
10165 * \brief auto do sync pattern switching and mirroring.
10166 * \param demod: instance of demod.
10167 * \param channel: pointer to channel data.
10168 * \param tuner_freq_offset: tuner frequency offset.
10169 * \param lock_status: pointer to lock status.
10170 * \return int.
10172 static int
10173 qam64auto(struct drx_demod_instance *demod,
10174 struct drx_channel *channel,
10175 s32 tuner_freq_offset, enum drx_lock_status *lock_status)
10177 struct drx_sig_quality sig_quality;
10178 struct drxj_data *ext_attr = NULL;
10179 int rc;
10180 u32 state = NO_LOCK;
10181 u32 start_time = 0;
10182 u32 d_locked_time = 0;
10183 u32 timeout_ofs = 0;
10184 u16 data = 0;
10186 /* external attributes for storing aquired channel constellation */
10187 ext_attr = (struct drxj_data *) demod->my_ext_attr;
10188 *lock_status = DRX_NOT_LOCKED;
10189 start_time = jiffies_to_msecs(jiffies);
10190 state = NO_LOCK;
10191 do {
10192 rc = ctrl_lock_status(demod, lock_status);
10193 if (rc != 0) {
10194 pr_err("error %d\n", rc);
10195 goto rw_error;
10198 switch (state) {
10199 case NO_LOCK:
10200 if (*lock_status == DRXJ_DEMOD_LOCK) {
10201 rc = ctrl_get_qam_sig_quality(demod, &sig_quality);
10202 if (rc != 0) {
10203 pr_err("error %d\n", rc);
10204 goto rw_error;
10206 if (sig_quality.MER > 208) {
10207 state = DEMOD_LOCKED;
10208 /* some delay to see if fec_lock possible TODO find the right value */
10209 timeout_ofs += DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME; /* see something, waiting longer */
10210 d_locked_time = jiffies_to_msecs(jiffies);
10213 break;
10214 case DEMOD_LOCKED:
10215 if ((*lock_status == DRXJ_DEMOD_LOCK) && /* still demod_lock in 150ms */
10216 ((jiffies_to_msecs(jiffies) - d_locked_time) >
10217 DRXJ_QAM_FEC_LOCK_WAITTIME)) {
10218 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, &data, 0);
10219 if (rc != 0) {
10220 pr_err("error %d\n", rc);
10221 goto rw_error;
10223 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, data | 0x1, 0);
10224 if (rc != 0) {
10225 pr_err("error %d\n", rc);
10226 goto rw_error;
10228 state = SYNC_FLIPPED;
10229 msleep(10);
10231 break;
10232 case SYNC_FLIPPED:
10233 if (*lock_status == DRXJ_DEMOD_LOCK) {
10234 if (channel->mirror == DRX_MIRROR_AUTO) {
10235 /* flip sync pattern back */
10236 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, &data, 0);
10237 if (rc != 0) {
10238 pr_err("error %d\n", rc);
10239 goto rw_error;
10241 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, data & 0xFFFE, 0);
10242 if (rc != 0) {
10243 pr_err("error %d\n", rc);
10244 goto rw_error;
10246 /* flip spectrum */
10247 ext_attr->mirror = DRX_MIRROR_YES;
10248 rc = qam_flip_spec(demod, channel);
10249 if (rc != 0) {
10250 pr_err("error %d\n", rc);
10251 goto rw_error;
10253 state = SPEC_MIRRORED;
10254 /* reset timer TODO: still need 500ms? */
10255 start_time = d_locked_time =
10256 jiffies_to_msecs(jiffies);
10257 timeout_ofs = 0;
10258 } else { /* no need to wait lock */
10260 start_time =
10261 jiffies_to_msecs(jiffies) -
10262 DRXJ_QAM_MAX_WAITTIME - timeout_ofs;
10265 break;
10266 case SPEC_MIRRORED:
10267 if ((*lock_status == DRXJ_DEMOD_LOCK) && /* still demod_lock in 150ms */
10268 ((jiffies_to_msecs(jiffies) - d_locked_time) >
10269 DRXJ_QAM_FEC_LOCK_WAITTIME)) {
10270 rc = ctrl_get_qam_sig_quality(demod, &sig_quality);
10271 if (rc != 0) {
10272 pr_err("error %d\n", rc);
10273 goto rw_error;
10275 if (sig_quality.MER > 208) {
10276 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, &data, 0);
10277 if (rc != 0) {
10278 pr_err("error %d\n", rc);
10279 goto rw_error;
10281 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, data | 0x1, 0);
10282 if (rc != 0) {
10283 pr_err("error %d\n", rc);
10284 goto rw_error;
10286 /* no need to wait lock */
10287 start_time =
10288 jiffies_to_msecs(jiffies) -
10289 DRXJ_QAM_MAX_WAITTIME - timeout_ofs;
10292 break;
10293 default:
10294 break;
10296 msleep(10);
10297 } while
10298 ((*lock_status != DRX_LOCKED) &&
10299 (*lock_status != DRX_NEVER_LOCK) &&
10300 ((jiffies_to_msecs(jiffies) - start_time) <
10301 (DRXJ_QAM_MAX_WAITTIME + timeout_ofs))
10303 /* Returning control to apllication ... */
10305 return 0;
10306 rw_error:
10307 return -EIO;
10311 * \fn int qam256auto ()
10312 * \brief auto do sync pattern switching and mirroring.
10313 * \param demod: instance of demod.
10314 * \param channel: pointer to channel data.
10315 * \param tuner_freq_offset: tuner frequency offset.
10316 * \param lock_status: pointer to lock status.
10317 * \return int.
10319 static int
10320 qam256auto(struct drx_demod_instance *demod,
10321 struct drx_channel *channel,
10322 s32 tuner_freq_offset, enum drx_lock_status *lock_status)
10324 struct drx_sig_quality sig_quality;
10325 struct drxj_data *ext_attr = NULL;
10326 int rc;
10327 u32 state = NO_LOCK;
10328 u32 start_time = 0;
10329 u32 d_locked_time = 0;
10330 u32 timeout_ofs = DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME;
10332 /* external attributes for storing aquired channel constellation */
10333 ext_attr = (struct drxj_data *) demod->my_ext_attr;
10334 *lock_status = DRX_NOT_LOCKED;
10335 start_time = jiffies_to_msecs(jiffies);
10336 state = NO_LOCK;
10337 do {
10338 rc = ctrl_lock_status(demod, lock_status);
10339 if (rc != 0) {
10340 pr_err("error %d\n", rc);
10341 goto rw_error;
10343 switch (state) {
10344 case NO_LOCK:
10345 if (*lock_status == DRXJ_DEMOD_LOCK) {
10346 rc = ctrl_get_qam_sig_quality(demod, &sig_quality);
10347 if (rc != 0) {
10348 pr_err("error %d\n", rc);
10349 goto rw_error;
10351 if (sig_quality.MER > 268) {
10352 state = DEMOD_LOCKED;
10353 timeout_ofs += DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME; /* see something, wait longer */
10354 d_locked_time = jiffies_to_msecs(jiffies);
10357 break;
10358 case DEMOD_LOCKED:
10359 if (*lock_status == DRXJ_DEMOD_LOCK) {
10360 if ((channel->mirror == DRX_MIRROR_AUTO) &&
10361 ((jiffies_to_msecs(jiffies) - d_locked_time) >
10362 DRXJ_QAM_FEC_LOCK_WAITTIME)) {
10363 ext_attr->mirror = DRX_MIRROR_YES;
10364 rc = qam_flip_spec(demod, channel);
10365 if (rc != 0) {
10366 pr_err("error %d\n", rc);
10367 goto rw_error;
10369 state = SPEC_MIRRORED;
10370 /* reset timer TODO: still need 300ms? */
10371 start_time = jiffies_to_msecs(jiffies);
10372 timeout_ofs = -DRXJ_QAM_MAX_WAITTIME / 2;
10375 break;
10376 case SPEC_MIRRORED:
10377 break;
10378 default:
10379 break;
10381 msleep(10);
10382 } while
10383 ((*lock_status < DRX_LOCKED) &&
10384 (*lock_status != DRX_NEVER_LOCK) &&
10385 ((jiffies_to_msecs(jiffies) - start_time) <
10386 (DRXJ_QAM_MAX_WAITTIME + timeout_ofs)));
10388 return 0;
10389 rw_error:
10390 return -EIO;
10394 * \fn int set_qam_channel ()
10395 * \brief Set QAM channel according to the requested constellation.
10396 * \param demod: instance of demod.
10397 * \param channel: pointer to channel data.
10398 * \return int.
10400 static int
10401 set_qam_channel(struct drx_demod_instance *demod,
10402 struct drx_channel *channel, s32 tuner_freq_offset)
10404 struct drxj_data *ext_attr = NULL;
10405 int rc;
10406 enum drx_lock_status lock_status = DRX_NOT_LOCKED;
10407 bool auto_flag = false;
10409 /* external attributes for storing aquired channel constellation */
10410 ext_attr = (struct drxj_data *) demod->my_ext_attr;
10412 /* set QAM channel constellation */
10413 switch (channel->constellation) {
10414 case DRX_CONSTELLATION_QAM16:
10415 case DRX_CONSTELLATION_QAM32:
10416 case DRX_CONSTELLATION_QAM64:
10417 case DRX_CONSTELLATION_QAM128:
10418 case DRX_CONSTELLATION_QAM256:
10419 ext_attr->constellation = channel->constellation;
10420 if (channel->mirror == DRX_MIRROR_AUTO)
10421 ext_attr->mirror = DRX_MIRROR_NO;
10422 else
10423 ext_attr->mirror = channel->mirror;
10424 rc = set_qam(demod, channel, tuner_freq_offset, QAM_SET_OP_ALL);
10425 if (rc != 0) {
10426 pr_err("error %d\n", rc);
10427 goto rw_error;
10430 if ((ext_attr->standard == DRX_STANDARD_ITU_B) &&
10431 (channel->constellation == DRX_CONSTELLATION_QAM64)) {
10432 rc = qam64auto(demod, channel, tuner_freq_offset, &lock_status);
10433 if (rc != 0) {
10434 pr_err("error %d\n", rc);
10435 goto rw_error;
10439 if ((ext_attr->standard == DRX_STANDARD_ITU_B) &&
10440 (channel->mirror == DRX_MIRROR_AUTO) &&
10441 (channel->constellation == DRX_CONSTELLATION_QAM256)) {
10442 rc = qam256auto(demod, channel, tuner_freq_offset, &lock_status);
10443 if (rc != 0) {
10444 pr_err("error %d\n", rc);
10445 goto rw_error;
10448 break;
10449 case DRX_CONSTELLATION_AUTO: /* for channel scan */
10450 if (ext_attr->standard == DRX_STANDARD_ITU_B) {
10451 auto_flag = true;
10452 /* try to lock default QAM constellation: QAM64 */
10453 channel->constellation = DRX_CONSTELLATION_QAM256;
10454 ext_attr->constellation = DRX_CONSTELLATION_QAM256;
10455 if (channel->mirror == DRX_MIRROR_AUTO)
10456 ext_attr->mirror = DRX_MIRROR_NO;
10457 else
10458 ext_attr->mirror = channel->mirror;
10459 rc = set_qam(demod, channel, tuner_freq_offset, QAM_SET_OP_ALL);
10460 if (rc != 0) {
10461 pr_err("error %d\n", rc);
10462 goto rw_error;
10464 rc = qam256auto(demod, channel, tuner_freq_offset, &lock_status);
10465 if (rc != 0) {
10466 pr_err("error %d\n", rc);
10467 goto rw_error;
10470 if (lock_status < DRX_LOCKED) {
10471 /* QAM254 not locked -> try to lock QAM64 constellation */
10472 channel->constellation =
10473 DRX_CONSTELLATION_QAM64;
10474 ext_attr->constellation =
10475 DRX_CONSTELLATION_QAM64;
10476 if (channel->mirror == DRX_MIRROR_AUTO)
10477 ext_attr->mirror = DRX_MIRROR_NO;
10478 else
10479 ext_attr->mirror = channel->mirror;
10481 u16 qam_ctl_ena = 0;
10482 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SCU_RAM_QAM_CTL_ENA__A, &qam_ctl_ena, 0);
10483 if (rc != 0) {
10484 pr_err("error %d\n", rc);
10485 goto rw_error;
10487 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SCU_RAM_QAM_CTL_ENA__A, qam_ctl_ena & ~SCU_RAM_QAM_CTL_ENA_ACQ__M, 0);
10488 if (rc != 0) {
10489 pr_err("error %d\n", rc);
10490 goto rw_error;
10492 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SCU_RAM_QAM_FSM_STATE_TGT__A, 0x2, 0);
10493 if (rc != 0) {
10494 pr_err("error %d\n", rc);
10495 goto rw_error;
10496 } /* force to rate hunting */
10498 rc = set_qam(demod, channel, tuner_freq_offset, QAM_SET_OP_CONSTELLATION);
10499 if (rc != 0) {
10500 pr_err("error %d\n", rc);
10501 goto rw_error;
10503 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SCU_RAM_QAM_CTL_ENA__A, qam_ctl_ena, 0);
10504 if (rc != 0) {
10505 pr_err("error %d\n", rc);
10506 goto rw_error;
10509 rc = qam64auto(demod, channel, tuner_freq_offset, &lock_status);
10510 if (rc != 0) {
10511 pr_err("error %d\n", rc);
10512 goto rw_error;
10515 channel->constellation = DRX_CONSTELLATION_AUTO;
10516 } else if (ext_attr->standard == DRX_STANDARD_ITU_C) {
10517 channel->constellation = DRX_CONSTELLATION_QAM64;
10518 ext_attr->constellation = DRX_CONSTELLATION_QAM64;
10519 auto_flag = true;
10521 if (channel->mirror == DRX_MIRROR_AUTO)
10522 ext_attr->mirror = DRX_MIRROR_NO;
10523 else
10524 ext_attr->mirror = channel->mirror;
10526 u16 qam_ctl_ena = 0;
10527 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SCU_RAM_QAM_CTL_ENA__A, &qam_ctl_ena, 0);
10528 if (rc != 0) {
10529 pr_err("error %d\n", rc);
10530 goto rw_error;
10532 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SCU_RAM_QAM_CTL_ENA__A, qam_ctl_ena & ~SCU_RAM_QAM_CTL_ENA_ACQ__M, 0);
10533 if (rc != 0) {
10534 pr_err("error %d\n", rc);
10535 goto rw_error;
10537 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SCU_RAM_QAM_FSM_STATE_TGT__A, 0x2, 0);
10538 if (rc != 0) {
10539 pr_err("error %d\n", rc);
10540 goto rw_error;
10541 } /* force to rate hunting */
10543 rc = set_qam(demod, channel, tuner_freq_offset, QAM_SET_OP_CONSTELLATION);
10544 if (rc != 0) {
10545 pr_err("error %d\n", rc);
10546 goto rw_error;
10548 rc = DRXJ_DAP.write_reg16func(demod->my_i2c_dev_addr, SCU_RAM_QAM_CTL_ENA__A, qam_ctl_ena, 0);
10549 if (rc != 0) {
10550 pr_err("error %d\n", rc);
10551 goto rw_error;
10554 rc = qam64auto(demod, channel, tuner_freq_offset, &lock_status);
10555 if (rc != 0) {
10556 pr_err("error %d\n", rc);
10557 goto rw_error;
10559 channel->constellation = DRX_CONSTELLATION_AUTO;
10560 } else {
10561 channel->constellation = DRX_CONSTELLATION_AUTO;
10562 return -EINVAL;
10564 break;
10565 default:
10566 return -EINVAL;
10569 return 0;
10570 rw_error:
10571 /* restore starting value */
10572 if (auto_flag)
10573 channel->constellation = DRX_CONSTELLATION_AUTO;
10574 return -EIO;
10577 /*============================================================================*/
10580 * \fn static short get_qamrs_err_count(struct i2c_device_addr *dev_addr)
10581 * \brief Get RS error count in QAM mode (used for post RS BER calculation)
10582 * \return Error code
10584 * precondition: measurement period & measurement prescale must be set
10587 static int
10588 get_qamrs_err_count(struct i2c_device_addr *dev_addr, struct drxjrs_errors *rs_errors)
10590 int rc;
10591 u16 nr_bit_errors = 0,
10592 nr_symbol_errors = 0,
10593 nr_packet_errors = 0, nr_failures = 0, nr_snc_par_fail_count = 0;
10595 /* check arguments */
10596 if (dev_addr == NULL)
10597 return -EINVAL;
10599 /* all reported errors are received in the */
10600 /* most recently finished measurment period */
10601 /* no of pre RS bit errors */
10602 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_RS_NR_BIT_ERRORS__A, &nr_bit_errors, 0);
10603 if (rc != 0) {
10604 pr_err("error %d\n", rc);
10605 goto rw_error;
10607 /* no of symbol errors */
10608 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_RS_NR_SYMBOL_ERRORS__A, &nr_symbol_errors, 0);
10609 if (rc != 0) {
10610 pr_err("error %d\n", rc);
10611 goto rw_error;
10613 /* no of packet errors */
10614 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_RS_NR_PACKET_ERRORS__A, &nr_packet_errors, 0);
10615 if (rc != 0) {
10616 pr_err("error %d\n", rc);
10617 goto rw_error;
10619 /* no of failures to decode */
10620 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_RS_NR_FAILURES__A, &nr_failures, 0);
10621 if (rc != 0) {
10622 pr_err("error %d\n", rc);
10623 goto rw_error;
10625 /* no of post RS bit erros */
10626 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_OC_SNC_FAIL_COUNT__A, &nr_snc_par_fail_count, 0);
10627 if (rc != 0) {
10628 pr_err("error %d\n", rc);
10629 goto rw_error;
10631 /* TODO: NOTE */
10632 /* These register values are fetched in non-atomic fashion */
10633 /* It is possible that the read values contain unrelated information */
10635 rs_errors->nr_bit_errors = nr_bit_errors & FEC_RS_NR_BIT_ERRORS__M;
10636 rs_errors->nr_symbol_errors = nr_symbol_errors & FEC_RS_NR_SYMBOL_ERRORS__M;
10637 rs_errors->nr_packet_errors = nr_packet_errors & FEC_RS_NR_PACKET_ERRORS__M;
10638 rs_errors->nr_failures = nr_failures & FEC_RS_NR_FAILURES__M;
10639 rs_errors->nr_snc_par_fail_count =
10640 nr_snc_par_fail_count & FEC_OC_SNC_FAIL_COUNT__M;
10642 return 0;
10643 rw_error:
10644 return -EIO;
10647 /*============================================================================*/
10650 * \fn int ctrl_get_qam_sig_quality()
10651 * \brief Retreive QAM signal quality from device.
10652 * \param devmod Pointer to demodulator instance.
10653 * \param sig_quality Pointer to signal quality data.
10654 * \return int.
10655 * \retval 0 sig_quality contains valid data.
10656 * \retval -EINVAL sig_quality is NULL.
10657 * \retval -EIO Erroneous data, sig_quality contains invalid data.
10659 * Pre-condition: Device must be started and in lock.
10661 static int
10662 ctrl_get_qam_sig_quality(struct drx_demod_instance *demod, struct drx_sig_quality *sig_quality)
10664 struct i2c_device_addr *dev_addr = NULL;
10665 struct drxj_data *ext_attr = NULL;
10666 int rc;
10667 enum drx_modulation constellation = DRX_CONSTELLATION_UNKNOWN;
10668 struct drxjrs_errors measuredrs_errors = { 0, 0, 0, 0, 0 };
10670 u32 pre_bit_err_rs = 0; /* pre RedSolomon Bit Error Rate */
10671 u32 post_bit_err_rs = 0; /* post RedSolomon Bit Error Rate */
10672 u32 pkt_errs = 0; /* no of packet errors in RS */
10673 u16 qam_sl_err_power = 0; /* accumulated error between raw and sliced symbols */
10674 u16 qsym_err_vd = 0; /* quadrature symbol errors in QAM_VD */
10675 u16 fec_oc_period = 0; /* SNC sync failure measurement period */
10676 u16 fec_rs_prescale = 0; /* ReedSolomon Measurement Prescale */
10677 u16 fec_rs_period = 0; /* Value for corresponding I2C register */
10678 /* calculation constants */
10679 u32 rs_bit_cnt = 0; /* RedSolomon Bit Count */
10680 u32 qam_sl_sig_power = 0; /* used for MER, depends of QAM constellation */
10681 /* intermediate results */
10682 u32 e = 0; /* exponent value used for QAM BER/SER */
10683 u32 m = 0; /* mantisa value used for QAM BER/SER */
10684 u32 ber_cnt = 0; /* BER count */
10685 /* signal quality info */
10686 u32 qam_sl_mer = 0; /* QAM MER */
10687 u32 qam_pre_rs_ber = 0; /* Pre RedSolomon BER */
10688 u32 qam_post_rs_ber = 0; /* Post RedSolomon BER */
10689 u32 qam_vd_ser = 0; /* ViterbiDecoder SER */
10690 u16 qam_vd_prescale = 0; /* Viterbi Measurement Prescale */
10691 u16 qam_vd_period = 0; /* Viterbi Measurement period */
10692 u32 vd_bit_cnt = 0; /* ViterbiDecoder Bit Count */
10694 /* get device basic information */
10695 dev_addr = demod->my_i2c_dev_addr;
10696 ext_attr = (struct drxj_data *) demod->my_ext_attr;
10697 constellation = ext_attr->constellation;
10699 /* read the physical registers */
10700 /* Get the RS error data */
10701 rc = get_qamrs_err_count(dev_addr, &measuredrs_errors);
10702 if (rc != 0) {
10703 pr_err("error %d\n", rc);
10704 goto rw_error;
10706 /* get the register value needed for MER */
10707 rc = DRXJ_DAP.read_reg16func(dev_addr, QAM_SL_ERR_POWER__A, &qam_sl_err_power, 0);
10708 if (rc != 0) {
10709 pr_err("error %d\n", rc);
10710 goto rw_error;
10712 /* get the register value needed for post RS BER */
10713 rc = DRXJ_DAP.read_reg16func(dev_addr, FEC_OC_SNC_FAIL_PERIOD__A, &fec_oc_period, 0);
10714 if (rc != 0) {
10715 pr_err("error %d\n", rc);
10716 goto rw_error;
10719 /* get constants needed for signal quality calculation */
10720 fec_rs_period = ext_attr->fec_rs_period;
10721 fec_rs_prescale = ext_attr->fec_rs_prescale;
10722 rs_bit_cnt = fec_rs_period * fec_rs_prescale * ext_attr->fec_rs_plen;
10723 qam_vd_period = ext_attr->qam_vd_period;
10724 qam_vd_prescale = ext_attr->qam_vd_prescale;
10725 vd_bit_cnt = qam_vd_period * qam_vd_prescale * ext_attr->fec_vd_plen;
10727 /* DRXJ_QAM_SL_SIG_POWER_QAMxxx * 4 */
10728 switch (constellation) {
10729 case DRX_CONSTELLATION_QAM16:
10730 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM16 << 2;
10731 break;
10732 case DRX_CONSTELLATION_QAM32:
10733 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM32 << 2;
10734 break;
10735 case DRX_CONSTELLATION_QAM64:
10736 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM64 << 2;
10737 break;
10738 case DRX_CONSTELLATION_QAM128:
10739 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM128 << 2;
10740 break;
10741 case DRX_CONSTELLATION_QAM256:
10742 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM256 << 2;
10743 break;
10744 default:
10745 return -EIO;
10748 /* ------------------------------ */
10749 /* MER Calculation */
10750 /* ------------------------------ */
10751 /* MER is good if it is above 27.5 for QAM256 or 21.5 for QAM64 */
10753 /* 10.0*log10(qam_sl_sig_power * 4.0 / qam_sl_err_power); */
10754 if (qam_sl_err_power == 0)
10755 qam_sl_mer = 0;
10756 else
10757 qam_sl_mer = log1_times100(qam_sl_sig_power) - log1_times100((u32)qam_sl_err_power);
10759 /* ----------------------------------------- */
10760 /* Pre Viterbi Symbol Error Rate Calculation */
10761 /* ----------------------------------------- */
10762 /* pre viterbi SER is good if it is bellow 0.025 */
10764 /* get the register value */
10765 /* no of quadrature symbol errors */
10766 rc = DRXJ_DAP.read_reg16func(dev_addr, QAM_VD_NR_QSYM_ERRORS__A, &qsym_err_vd, 0);
10767 if (rc != 0) {
10768 pr_err("error %d\n", rc);
10769 goto rw_error;
10771 /* Extract the Exponent and the Mantisa */
10772 /* of number of quadrature symbol errors */
10773 e = (qsym_err_vd & QAM_VD_NR_QSYM_ERRORS_EXP__M) >>
10774 QAM_VD_NR_QSYM_ERRORS_EXP__B;
10775 m = (qsym_err_vd & QAM_VD_NR_SYMBOL_ERRORS_FIXED_MANT__M) >>
10776 QAM_VD_NR_SYMBOL_ERRORS_FIXED_MANT__B;
10778 if ((m << e) >> 3 > 549752)
10779 qam_vd_ser = 500000;
10780 else
10781 qam_vd_ser = frac_times1e6(m << ((e > 2) ? (e - 3) : e), vd_bit_cnt * ((e > 2) ? 1 : 8) / 8);
10783 /* --------------------------------------- */
10784 /* pre and post RedSolomon BER Calculation */
10785 /* --------------------------------------- */
10786 /* pre RS BER is good if it is below 3.5e-4 */
10788 /* get the register values */
10789 pre_bit_err_rs = (u32) measuredrs_errors.nr_bit_errors;
10790 pkt_errs = post_bit_err_rs = (u32) measuredrs_errors.nr_snc_par_fail_count;
10792 /* Extract the Exponent and the Mantisa of the */
10793 /* pre Reed-Solomon bit error count */
10794 e = (pre_bit_err_rs & FEC_RS_NR_BIT_ERRORS_EXP__M) >>
10795 FEC_RS_NR_BIT_ERRORS_EXP__B;
10796 m = (pre_bit_err_rs & FEC_RS_NR_BIT_ERRORS_FIXED_MANT__M) >>
10797 FEC_RS_NR_BIT_ERRORS_FIXED_MANT__B;
10799 ber_cnt = m << e;
10801 /*qam_pre_rs_ber = frac_times1e6( ber_cnt, rs_bit_cnt ); */
10802 if (m > (rs_bit_cnt >> (e + 1)) || (rs_bit_cnt >> e) == 0)
10803 qam_pre_rs_ber = 500000;
10804 else
10805 qam_pre_rs_ber = frac_times1e6(m, rs_bit_cnt >> e);
10807 /* post RS BER = 1000000* (11.17 * FEC_OC_SNC_FAIL_COUNT__A) / */
10808 /* (1504.0 * FEC_OC_SNC_FAIL_PERIOD__A) */
10810 => c = (1000000*100*11.17)/1504 =
10811 post RS BER = (( c* FEC_OC_SNC_FAIL_COUNT__A) /
10812 (100 * FEC_OC_SNC_FAIL_PERIOD__A)
10813 *100 and /100 is for more precision.
10814 => (20 bits * 12 bits) /(16 bits * 7 bits) => safe in 32 bits computation
10816 Precision errors still possible.
10818 e = post_bit_err_rs * 742686;
10819 m = fec_oc_period * 100;
10820 if (fec_oc_period == 0)
10821 qam_post_rs_ber = 0xFFFFFFFF;
10822 else
10823 qam_post_rs_ber = e / m;
10825 /* fill signal quality data structure */
10826 sig_quality->MER = ((u16) qam_sl_mer);
10827 if (ext_attr->standard == DRX_STANDARD_ITU_B)
10828 sig_quality->pre_viterbi_ber = qam_vd_ser;
10829 else
10830 sig_quality->pre_viterbi_ber = qam_pre_rs_ber;
10831 sig_quality->post_viterbi_ber = qam_pre_rs_ber;
10832 sig_quality->post_reed_solomon_ber = qam_post_rs_ber;
10833 sig_quality->scale_factor_ber = ((u32) 1000000);
10834 #ifdef DRXJ_SIGNAL_ACCUM_ERR
10835 rc = get_acc_pkt_err(demod, &sig_quality->packet_error);
10836 if (rc != 0) {
10837 pr_err("error %d\n", rc);
10838 goto rw_error;
10840 #else
10841 sig_quality->packet_error = ((u16) pkt_errs);
10842 #endif
10844 return 0;
10845 rw_error:
10846 return -EIO;
10849 #if 0
10851 * \fn int ctrl_get_qam_constel()
10852 * \brief Retreive a QAM constellation point via I2C.
10853 * \param demod Pointer to demodulator instance.
10854 * \param complex_nr Pointer to the structure in which to store the
10855 constellation point.
10856 * \return int.
10858 static int
10859 ctrl_get_qam_constel(struct drx_demod_instance *demod, struct drx_complex *complex_nr)
10861 struct i2c_device_addr *dev_addr = NULL;
10862 int rc;
10863 u32 data = 0;
10864 u16 fec_oc_ocr_mode = 0;
10865 /**< FEC OCR grabber configuration */
10866 u16 qam_sl_comm_mb = 0;/**< QAM SL MB configuration */
10867 u16 qam_sl_comm_mb_init = 0;
10868 /**< QAM SL MB intial configuration */
10869 u16 im = 0; /**< constellation Im part */
10870 u16 re = 0; /**< constellation Re part */
10871 /**< device address */
10873 /* read device info */
10874 dev_addr = demod->my_i2c_dev_addr;
10876 /* TODO: */
10877 /* Monitor bus grabbing is an open external interface issue */
10878 /* Needs to be checked when external interface PG is updated */
10880 /* Configure MB (Monitor bus) */
10881 rc = DRXJ_DAP.read_reg16func(dev_addr, QAM_SL_COMM_MB__A, &qam_sl_comm_mb_init, 0);
10882 if (rc != 0) {
10883 pr_err("error %d\n", rc);
10884 goto rw_error;
10886 /* set observe flag & MB mux */
10887 qam_sl_comm_mb = qam_sl_comm_mb_init & (~(QAM_SL_COMM_MB_OBS__M +
10888 QAM_SL_COMM_MB_MUX_OBS__M));
10889 qam_sl_comm_mb |= (QAM_SL_COMM_MB_OBS_ON +
10890 QAM_SL_COMM_MB_MUX_OBS_CONST_CORR);
10891 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_SL_COMM_MB__A, qam_sl_comm_mb, 0);
10892 if (rc != 0) {
10893 pr_err("error %d\n", rc);
10894 goto rw_error;
10897 /* Enable MB grabber in the FEC OC */
10898 fec_oc_ocr_mode = (/* output select: observe bus */
10899 (FEC_OC_OCR_MODE_MB_SELECT__M &
10900 (0x0 << FEC_OC_OCR_MODE_MB_SELECT__B)) |
10901 /* grabber enable: on */
10902 (FEC_OC_OCR_MODE_GRAB_ENABLE__M &
10903 (0x1 << FEC_OC_OCR_MODE_GRAB_ENABLE__B)) |
10904 /* grabber select: observe bus */
10905 (FEC_OC_OCR_MODE_GRAB_SELECT__M &
10906 (0x0 << FEC_OC_OCR_MODE_GRAB_SELECT__B)) |
10907 /* grabber mode: continuous */
10908 (FEC_OC_OCR_MODE_GRAB_COUNTED__M &
10909 (0x0 << FEC_OC_OCR_MODE_GRAB_COUNTED__B)));
10910 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_OCR_MODE__A, fec_oc_ocr_mode, 0);
10911 if (rc != 0) {
10912 pr_err("error %d\n", rc);
10913 goto rw_error;
10916 /* Disable MB grabber in the FEC OC */
10917 rc = DRXJ_DAP.write_reg16func(dev_addr, FEC_OC_OCR_MODE__A, 0x00, 0);
10918 if (rc != 0) {
10919 pr_err("error %d\n", rc);
10920 goto rw_error;
10923 /* read data */
10924 rc = DRXJ_DAP.read_reg32func(dev_addr, FEC_OC_OCR_GRAB_RD0__A, &data, 0);
10925 if (rc != 0) {
10926 pr_err("error %d\n", rc);
10927 goto rw_error;
10929 re = (u16) (data & FEC_OC_OCR_GRAB_RD0__M);
10930 im = (u16) ((data >> 16) & FEC_OC_OCR_GRAB_RD1__M);
10932 /* TODO: */
10933 /* interpret data (re & im) according to the Monitor bus mapping ?? */
10935 /* sign extension, 10th bit is sign bit */
10936 if ((re & 0x0200) == 0x0200)
10937 re |= 0xFC00;
10938 if ((im & 0x0200) == 0x0200)
10939 im |= 0xFC00;
10940 complex_nr->re = ((s16) re);
10941 complex_nr->im = ((s16) im);
10943 /* Restore MB (Monitor bus) */
10944 rc = DRXJ_DAP.write_reg16func(dev_addr, QAM_SL_COMM_MB__A, qam_sl_comm_mb_init, 0);
10945 if (rc != 0) {
10946 pr_err("error %d\n", rc);
10947 goto rw_error;
10950 return 0;
10951 rw_error:
10952 return -EIO;
10954 #endif /* #if 0 */
10955 #endif /* #ifndef DRXJ_VSB_ONLY */
10957 /*============================================================================*/
10958 /*== END QAM DATAPATH FUNCTIONS ==*/
10959 /*============================================================================*/
10961 /*============================================================================*/
10962 /*============================================================================*/
10963 /*== ATV DATAPATH FUNCTIONS ==*/
10964 /*============================================================================*/
10965 /*============================================================================*/
10968 Implementation notes.
10970 NTSC/FM AGCs
10972 Four AGCs are used for NTSC:
10973 (1) RF (used to attenuate the input signal in case of to much power)
10974 (2) IF (used to attenuate the input signal in case of to much power)
10975 (3) Video AGC (used to amplify the output signal in case input to low)
10976 (4) SIF AGC (used to amplify the output signal in case input to low)
10978 Video AGC is coupled to RF and IF. SIF AGC is not coupled. It is assumed
10979 that the coupling between Video AGC and the RF and IF AGCs also works in
10980 favor of the SIF AGC.
10982 Three AGCs are used for FM:
10983 (1) RF (used to attenuate the input signal in case of to much power)
10984 (2) IF (used to attenuate the input signal in case of to much power)
10985 (3) SIF AGC (used to amplify the output signal in case input to low)
10987 The SIF AGC is now coupled to the RF/IF AGCs.
10988 The SIF AGC is needed for both SIF ouput and the internal SIF signal to
10989 the AUD block.
10991 RF and IF AGCs DACs are part of AFE, Video and SIF AGC DACs are part of
10992 the ATV block. The AGC control algorithms are all implemented in
10993 microcode.
10995 ATV SETTINGS
10997 (Shadow settings will not be used for now, they will be implemented
10998 later on because of the schedule)
11000 Several HW/SCU "settings" can be used for ATV. The standard selection
11001 will reset most of these settings. To avoid that the end user apllication
11002 has to perform these settings each time the ATV or FM standards is
11003 selected the driver will shadow these settings. This enables the end user
11004 to perform the settings only once after a drx_open(). The driver must
11005 write the shadow settings to HW/SCU incase:
11006 ( setstandard FM/ATV) ||
11007 ( settings have changed && FM/ATV standard is active)
11008 The shadow settings will be stored in the device specific data container.
11009 A set of flags will be defined to flag changes in shadow settings.
11010 A routine will be implemented to write all changed shadow settings to
11011 HW/SCU.
11013 The "settings" will consist of: AGC settings, filter settings etc.
11015 Disadvantage of use of shadow settings:
11016 Direct changes in HW/SCU registers will not be reflected in the
11017 shadow settings and these changes will be overwritten during a next
11018 update. This can happen during evaluation. This will not be a problem
11019 for normal customer usage.
11021 /* -------------------------------------------------------------------------- */
11023 #if 0
11025 * \brief Get array index for atv coef (ext_attr->atvTopCoefX[index])
11026 * \param standard
11027 * \param pointer to index
11028 * \return int.
11031 static int atv_equ_coef_index(enum drx_standard standard, int *index)
11033 switch (standard) {
11034 case DRX_STANDARD_PAL_SECAM_BG:
11035 *index = (int)DRXJ_COEF_IDX_BG;
11036 break;
11037 case DRX_STANDARD_PAL_SECAM_DK:
11038 *index = (int)DRXJ_COEF_IDX_DK;
11039 break;
11040 case DRX_STANDARD_PAL_SECAM_I:
11041 *index = (int)DRXJ_COEF_IDX_I;
11042 break;
11043 case DRX_STANDARD_PAL_SECAM_L:
11044 *index = (int)DRXJ_COEF_IDX_L;
11045 break;
11046 case DRX_STANDARD_PAL_SECAM_LP:
11047 *index = (int)DRXJ_COEF_IDX_LP;
11048 break;
11049 case DRX_STANDARD_NTSC:
11050 *index = (int)DRXJ_COEF_IDX_MN;
11051 break;
11052 case DRX_STANDARD_FM:
11053 *index = (int)DRXJ_COEF_IDX_FM;
11054 break;
11055 default:
11056 *index = (int)DRXJ_COEF_IDX_MN; /* still return a valid index */
11057 return -EIO;
11058 break;
11061 return 0;
11064 /* -------------------------------------------------------------------------- */
11066 * \fn int atv_update_config ()
11067 * \brief Flush changes in ATV shadow registers to physical registers.
11068 * \param demod instance of demodulator
11069 * \param force_update don't look at standard or change flags, flush all.
11070 * \return int.
11073 static int
11074 atv_update_config(struct drx_demod_instance *demod, bool force_update)
11076 struct i2c_device_addr *dev_addr = NULL;
11077 struct drxj_data *ext_attr = NULL;
11078 int rc;
11080 dev_addr = demod->my_i2c_dev_addr;
11081 ext_attr = (struct drxj_data *) demod->my_ext_attr;
11083 /* equalizer coefficients */
11084 if (force_update ||
11085 ((ext_attr->atv_cfg_changed_flags & DRXJ_ATV_CHANGED_COEF) != 0)) {
11086 int index = 0;
11088 rc = atv_equ_coef_index(ext_attr->standard, &index);
11089 if (rc != 0) {
11090 pr_err("error %d\n", rc);
11091 goto rw_error;
11093 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_EQU0__A, ext_attr->atv_top_equ0[index], 0);
11094 if (rc != 0) {
11095 pr_err("error %d\n", rc);
11096 goto rw_error;
11098 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_EQU1__A, ext_attr->atv_top_equ1[index], 0);
11099 if (rc != 0) {
11100 pr_err("error %d\n", rc);
11101 goto rw_error;
11103 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_EQU2__A, ext_attr->atv_top_equ2[index], 0);
11104 if (rc != 0) {
11105 pr_err("error %d\n", rc);
11106 goto rw_error;
11108 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_EQU3__A, ext_attr->atv_top_equ3[index], 0);
11109 if (rc != 0) {
11110 pr_err("error %d\n", rc);
11111 goto rw_error;
11115 /* bypass fast carrier recovery */
11116 if (force_update) {
11117 u16 data = 0;
11119 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_RT_ROT_BP__A, &data, 0);
11120 if (rc != 0) {
11121 pr_err("error %d\n", rc);
11122 goto rw_error;
11124 data &= (~((u16) IQM_RT_ROT_BP_ROT_OFF__M));
11125 if (ext_attr->phase_correction_bypass)
11126 data |= IQM_RT_ROT_BP_ROT_OFF_OFF;
11127 else
11128 data |= IQM_RT_ROT_BP_ROT_OFF_ACTIVE;
11129 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_ROT_BP__A, data, 0);
11130 if (rc != 0) {
11131 pr_err("error %d\n", rc);
11132 goto rw_error;
11136 /* peak filter setting */
11137 if (force_update ||
11138 ((ext_attr->atv_cfg_changed_flags & DRXJ_ATV_CHANGED_PEAK_FLT) != 0)) {
11139 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_VID_PEAK__A, ext_attr->atv_top_vid_peak, 0);
11140 if (rc != 0) {
11141 pr_err("error %d\n", rc);
11142 goto rw_error;
11146 /* noise filter setting */
11147 if (force_update ||
11148 ((ext_attr->atv_cfg_changed_flags & DRXJ_ATV_CHANGED_NOISE_FLT) != 0)) {
11149 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_NOISE_TH__A, ext_attr->atv_top_noise_th, 0);
11150 if (rc != 0) {
11151 pr_err("error %d\n", rc);
11152 goto rw_error;
11156 /* SIF attenuation */
11157 if (force_update ||
11158 ((ext_attr->atv_cfg_changed_flags & DRXJ_ATV_CHANGED_SIF_ATT) != 0)) {
11159 u16 attenuation = 0;
11161 switch (ext_attr->sif_attenuation) {
11162 case DRXJ_SIF_ATTENUATION_0DB:
11163 attenuation = ATV_TOP_AF_SIF_ATT_0DB;
11164 break;
11165 case DRXJ_SIF_ATTENUATION_3DB:
11166 attenuation = ATV_TOP_AF_SIF_ATT_M3DB;
11167 break;
11168 case DRXJ_SIF_ATTENUATION_6DB:
11169 attenuation = ATV_TOP_AF_SIF_ATT_M6DB;
11170 break;
11171 case DRXJ_SIF_ATTENUATION_9DB:
11172 attenuation = ATV_TOP_AF_SIF_ATT_M9DB;
11173 break;
11174 default:
11175 return -EIO;
11176 break;
11178 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_AF_SIF_ATT__A, attenuation, 0);
11179 if (rc != 0) {
11180 pr_err("error %d\n", rc);
11181 goto rw_error;
11185 /* SIF & CVBS enable */
11186 if (force_update ||
11187 ((ext_attr->atv_cfg_changed_flags & DRXJ_ATV_CHANGED_OUTPUT) != 0)) {
11188 u16 data = 0;
11190 rc = DRXJ_DAP.read_reg16func(dev_addr, ATV_TOP_STDBY__A, &data, 0);
11191 if (rc != 0) {
11192 pr_err("error %d\n", rc);
11193 goto rw_error;
11195 if (ext_attr->enable_cvbs_output)
11196 data |= ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE;
11197 else
11198 data &= (~ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE);
11200 if (ext_attr->enable_sif_output)
11201 data &= (~ATV_TOP_STDBY_SIF_STDBY_STANDBY);
11202 else
11203 data |= ATV_TOP_STDBY_SIF_STDBY_STANDBY;
11204 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_STDBY__A, data, 0);
11205 if (rc != 0) {
11206 pr_err("error %d\n", rc);
11207 goto rw_error;
11211 ext_attr->atv_cfg_changed_flags = 0;
11213 return 0;
11214 rw_error:
11215 return -EIO;
11218 /* -------------------------------------------------------------------------- */
11220 * \fn int ctrl_set_cfg_atv_output()
11221 * \brief Configure ATV ouputs
11222 * \param demod instance of demodulator
11223 * \param output_cfg output configuaration
11224 * \return int.
11227 static int
11228 ctrl_set_cfg_atv_output(struct drx_demod_instance *demod, struct drxj_cfg_atv_output *output_cfg)
11230 struct drxj_data *ext_attr = NULL;
11231 int rc;
11233 /* Check arguments */
11234 if (output_cfg == NULL)
11235 return -EINVAL;
11237 ext_attr = (struct drxj_data *) demod->my_ext_attr;
11238 if (output_cfg->enable_sif_output) {
11239 switch (output_cfg->sif_attenuation) {
11240 case DRXJ_SIF_ATTENUATION_0DB: /* fallthrough */
11241 case DRXJ_SIF_ATTENUATION_3DB: /* fallthrough */
11242 case DRXJ_SIF_ATTENUATION_6DB: /* fallthrough */
11243 case DRXJ_SIF_ATTENUATION_9DB:
11244 /* Do nothing */
11245 break;
11246 default:
11247 return -EINVAL;
11248 break;
11251 if (ext_attr->sif_attenuation != output_cfg->sif_attenuation) {
11252 ext_attr->sif_attenuation = output_cfg->sif_attenuation;
11253 ext_attr->atv_cfg_changed_flags |= DRXJ_ATV_CHANGED_SIF_ATT;
11257 if (ext_attr->enable_cvbs_output != output_cfg->enable_cvbs_output) {
11258 ext_attr->enable_cvbs_output = output_cfg->enable_cvbs_output;
11259 ext_attr->atv_cfg_changed_flags |= DRXJ_ATV_CHANGED_OUTPUT;
11262 if (ext_attr->enable_sif_output != output_cfg->enable_sif_output) {
11263 ext_attr->enable_sif_output = output_cfg->enable_sif_output;
11264 ext_attr->atv_cfg_changed_flags |= DRXJ_ATV_CHANGED_OUTPUT;
11267 rc = atv_update_config(demod, false);
11268 if (rc != 0) {
11269 pr_err("error %d\n", rc);
11270 goto rw_error;
11273 return 0;
11274 rw_error:
11275 return -EIO;
11278 /* -------------------------------------------------------------------------- */
11280 * \fn int ctrl_set_cfg_atv_equ_coef()
11281 * \brief Set ATV equalizer coefficients
11282 * \param demod instance of demodulator
11283 * \param coef the equalizer coefficients
11284 * \return int.
11287 static int
11288 ctrl_set_cfg_atv_equ_coef(struct drx_demod_instance *demod, struct drxj_cfg_atv_equ_coef *coef)
11290 struct drxj_data *ext_attr = NULL;
11291 int rc;
11292 int index;
11294 ext_attr = (struct drxj_data *) demod->my_ext_attr;
11296 /* current standard needs to be an ATV standard */
11297 if (!DRXJ_ISATVSTD(ext_attr->standard))
11298 return -EIO;
11300 /* Check arguments */
11301 if ((coef == NULL) ||
11302 (coef->coef0 > (ATV_TOP_EQU0_EQU_C0__M / 2)) ||
11303 (coef->coef1 > (ATV_TOP_EQU1_EQU_C1__M / 2)) ||
11304 (coef->coef2 > (ATV_TOP_EQU2_EQU_C2__M / 2)) ||
11305 (coef->coef3 > (ATV_TOP_EQU3_EQU_C3__M / 2)) ||
11306 (coef->coef0 < ((s16) ~(ATV_TOP_EQU0_EQU_C0__M >> 1))) ||
11307 (coef->coef1 < ((s16) ~(ATV_TOP_EQU1_EQU_C1__M >> 1))) ||
11308 (coef->coef2 < ((s16) ~(ATV_TOP_EQU2_EQU_C2__M >> 1))) ||
11309 (coef->coef3 < ((s16) ~(ATV_TOP_EQU3_EQU_C3__M >> 1)))) {
11310 return -EINVAL;
11313 rc = atv_equ_coef_index(ext_attr->standard, &index);
11314 if (rc != 0) {
11315 pr_err("error %d\n", rc);
11316 goto rw_error;
11318 ext_attr->atv_top_equ0[index] = coef->coef0;
11319 ext_attr->atv_top_equ1[index] = coef->coef1;
11320 ext_attr->atv_top_equ2[index] = coef->coef2;
11321 ext_attr->atv_top_equ3[index] = coef->coef3;
11322 ext_attr->atv_cfg_changed_flags |= DRXJ_ATV_CHANGED_COEF;
11324 rc = atv_update_config(demod, false);
11325 if (rc != 0) {
11326 pr_err("error %d\n", rc);
11327 goto rw_error;
11330 return 0;
11331 rw_error:
11332 return -EIO;
11335 /* -------------------------------------------------------------------------- */
11337 * \fn int ctrl_get_cfg_atv_equ_coef()
11338 * \brief Get ATV equ coef settings
11339 * \param demod instance of demodulator
11340 * \param coef The ATV equ coefficients
11341 * \return int.
11343 * The values are read from the shadow registers maintained by the drxdriver
11344 * If registers are manipulated outside of the drxdriver scope the reported
11345 * settings will not reflect these changes because of the use of shadow
11346 * regitsers.
11349 static int
11350 ctrl_get_cfg_atv_equ_coef(struct drx_demod_instance *demod, struct drxj_cfg_atv_equ_coef *coef)
11352 struct drxj_data *ext_attr = NULL;
11353 int rc;
11354 int index = 0;
11356 ext_attr = (struct drxj_data *) demod->my_ext_attr;
11358 /* current standard needs to be an ATV standard */
11359 if (!DRXJ_ISATVSTD(ext_attr->standard))
11360 return -EIO;
11362 /* Check arguments */
11363 if (coef == NULL)
11364 return -EINVAL;
11366 rc = atv_equ_coef_index(ext_attr->standard, &index);
11367 if (rc != 0) {
11368 pr_err("error %d\n", rc);
11369 goto rw_error;
11371 coef->coef0 = ext_attr->atv_top_equ0[index];
11372 coef->coef1 = ext_attr->atv_top_equ1[index];
11373 coef->coef2 = ext_attr->atv_top_equ2[index];
11374 coef->coef3 = ext_attr->atv_top_equ3[index];
11376 return 0;
11377 rw_error:
11378 return -EIO;
11381 /* -------------------------------------------------------------------------- */
11383 * \fn int ctrl_set_cfg_atv_misc()
11384 * \brief Set misc. settings for ATV.
11385 * \param demod instance of demodulator
11386 * \param
11387 * \return int.
11390 static int
11391 ctrl_set_cfg_atv_misc(struct drx_demod_instance *demod, struct drxj_cfg_atv_misc *settings)
11393 struct drxj_data *ext_attr = NULL;
11394 int rc;
11396 /* Check arguments */
11397 if ((settings == NULL) ||
11398 ((settings->peak_filter) < (s16) (-8)) ||
11399 ((settings->peak_filter) > (s16) (15)) ||
11400 ((settings->noise_filter) > 15)) {
11401 return -EINVAL;
11403 /* if */
11404 ext_attr = (struct drxj_data *) demod->my_ext_attr;
11406 if (settings->peak_filter != ext_attr->atv_top_vid_peak) {
11407 ext_attr->atv_top_vid_peak = settings->peak_filter;
11408 ext_attr->atv_cfg_changed_flags |= DRXJ_ATV_CHANGED_PEAK_FLT;
11411 if (settings->noise_filter != ext_attr->atv_top_noise_th) {
11412 ext_attr->atv_top_noise_th = settings->noise_filter;
11413 ext_attr->atv_cfg_changed_flags |= DRXJ_ATV_CHANGED_NOISE_FLT;
11416 rc = atv_update_config(demod, false);
11417 if (rc != 0) {
11418 pr_err("error %d\n", rc);
11419 goto rw_error;
11422 return 0;
11423 rw_error:
11424 return -EIO;
11427 /* -------------------------------------------------------------------------- */
11429 * \fn int ctrl_get_cfg_atv_misc()
11430 * \brief Get misc settings of ATV.
11431 * \param demod instance of demodulator
11432 * \param settings misc. ATV settings
11433 * \return int.
11435 * The values are read from the shadow registers maintained by the drxdriver
11436 * If registers are manipulated outside of the drxdriver scope the reported
11437 * settings will not reflect these changes because of the use of shadow
11438 * regitsers.
11440 static int
11441 ctrl_get_cfg_atv_misc(struct drx_demod_instance *demod, struct drxj_cfg_atv_misc *settings)
11443 struct drxj_data *ext_attr = NULL;
11445 /* Check arguments */
11446 if (settings == NULL)
11447 return -EINVAL;
11449 ext_attr = (struct drxj_data *) demod->my_ext_attr;
11451 settings->peak_filter = ext_attr->atv_top_vid_peak;
11452 settings->noise_filter = ext_attr->atv_top_noise_th;
11454 return 0;
11457 /* -------------------------------------------------------------------------- */
11459 /* -------------------------------------------------------------------------- */
11461 * \fn int ctrl_get_cfg_atv_output()
11462 * \brief
11463 * \param demod instance of demodulator
11464 * \param output_cfg output configuaration
11465 * \return int.
11468 static int
11469 ctrl_get_cfg_atv_output(struct drx_demod_instance *demod, struct drxj_cfg_atv_output *output_cfg)
11471 int rc;
11472 u16 data = 0;
11474 /* Check arguments */
11475 if (output_cfg == NULL)
11476 return -EINVAL;
11478 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, ATV_TOP_STDBY__A, &data, 0);
11479 if (rc != 0) {
11480 pr_err("error %d\n", rc);
11481 goto rw_error;
11483 if (data & ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE)
11484 output_cfg->enable_cvbs_output = true;
11485 else
11486 output_cfg->enable_cvbs_output = false;
11488 if (data & ATV_TOP_STDBY_SIF_STDBY_STANDBY) {
11489 output_cfg->enable_sif_output = false;
11490 } else {
11491 output_cfg->enable_sif_output = true;
11492 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, ATV_TOP_AF_SIF_ATT__A, &data, 0);
11493 if (rc != 0) {
11494 pr_err("error %d\n", rc);
11495 goto rw_error;
11497 output_cfg->sif_attenuation = (enum drxjsif_attenuation) data;
11500 return 0;
11501 rw_error:
11502 return -EIO;
11505 /* -------------------------------------------------------------------------- */
11507 * \fn int ctrl_get_cfg_atv_agc_status()
11508 * \brief
11509 * \param demod instance of demodulator
11510 * \param agc_status agc status
11511 * \return int.
11514 static int
11515 ctrl_get_cfg_atv_agc_status(struct drx_demod_instance *demod,
11516 struct drxj_cfg_atv_agc_status *agc_status)
11518 struct i2c_device_addr *dev_addr = NULL;
11519 int rc;
11520 u16 data = 0;
11521 u32 tmp = 0;
11523 /* Check arguments */
11524 if (agc_status == NULL)
11525 return -EINVAL;
11527 dev_addr = demod->my_i2c_dev_addr;
11530 RFgain = (IQM_AF_AGC_RF__A * 26.75)/1000 (uA)
11531 = ((IQM_AF_AGC_RF__A * 27) - (0.25*IQM_AF_AGC_RF__A))/1000
11533 IQM_AF_AGC_RF__A * 27 is 20 bits worst case.
11535 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_AGC_RF__A, &data, 0);
11536 if (rc != 0) {
11537 pr_err("error %d\n", rc);
11538 goto rw_error;
11540 tmp = ((u32) data) * 27 - ((u32) (data >> 2)); /* nA */
11541 agc_status->rf_agc_gain = (u16) (tmp / 1000); /* uA */
11542 /* rounding */
11543 if (tmp % 1000 >= 500)
11544 (agc_status->rf_agc_gain)++;
11547 IFgain = (IQM_AF_AGC_IF__A * 26.75)/1000 (uA)
11548 = ((IQM_AF_AGC_IF__A * 27) - (0.25*IQM_AF_AGC_IF__A))/1000
11550 IQM_AF_AGC_IF__A * 27 is 20 bits worst case.
11552 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_AGC_IF__A, &data, 0);
11553 if (rc != 0) {
11554 pr_err("error %d\n", rc);
11555 goto rw_error;
11557 tmp = ((u32) data) * 27 - ((u32) (data >> 2)); /* nA */
11558 agc_status->if_agc_gain = (u16) (tmp / 1000); /* uA */
11559 /* rounding */
11560 if (tmp % 1000 >= 500)
11561 (agc_status->if_agc_gain)++;
11564 videoGain = (ATV_TOP_SFR_VID_GAIN__A/16 -150)* 0.05 (dB)
11565 = (ATV_TOP_SFR_VID_GAIN__A/16 -150)/20 (dB)
11566 = 10*(ATV_TOP_SFR_VID_GAIN__A/16 -150)/20 (in 0.1 dB)
11567 = (ATV_TOP_SFR_VID_GAIN__A/16 -150)/2 (in 0.1 dB)
11568 = (ATV_TOP_SFR_VID_GAIN__A/32) - 75 (in 0.1 dB)
11571 rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, &data, 0);
11572 if (rc != 0) {
11573 pr_err("error %d\n", rc);
11574 goto rw_error;
11576 /* dividing by 32 inclusive rounding */
11577 data >>= 4;
11578 if ((data & 1) != 0)
11579 data++;
11580 data >>= 1;
11581 agc_status->video_agc_gain = ((s16) data) - 75; /* 0.1 dB */
11584 audioGain = (SCU_RAM_ATV_SIF_GAIN__A -8)* 0.05 (dB)
11585 = (SCU_RAM_ATV_SIF_GAIN__A -8)/20 (dB)
11586 = 10*(SCU_RAM_ATV_SIF_GAIN__A -8)/20 (in 0.1 dB)
11587 = (SCU_RAM_ATV_SIF_GAIN__A -8)/2 (in 0.1 dB)
11588 = (SCU_RAM_ATV_SIF_GAIN__A/2) - 4 (in 0.1 dB)
11591 rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_ATV_SIF_GAIN__A, &data, 0);
11592 if (rc != 0) {
11593 pr_err("error %d\n", rc);
11594 goto rw_error;
11596 data &= SCU_RAM_ATV_SIF_GAIN__M;
11597 /* dividing by 2 inclusive rounding */
11598 if ((data & 1) != 0)
11599 data++;
11600 data >>= 1;
11601 agc_status->audio_agc_gain = ((s16) data) - 4; /* 0.1 dB */
11603 /* Loop gain's */
11604 rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
11605 if (rc != 0) {
11606 pr_err("error %d\n", rc);
11607 goto rw_error;
11609 agc_status->video_agc_loop_gain =
11610 ((data & SCU_RAM_AGC_KI_DGAIN__M) >> SCU_RAM_AGC_KI_DGAIN__B);
11611 agc_status->rf_agc_loop_gain =
11612 ((data & SCU_RAM_AGC_KI_RF__M) >> SCU_RAM_AGC_KI_RF__B);
11613 agc_status->if_agc_loop_gain =
11614 ((data & SCU_RAM_AGC_KI_IF__M) >> SCU_RAM_AGC_KI_IF__B);
11616 return 0;
11617 rw_error:
11618 return -EIO;
11621 /* -------------------------------------------------------------------------- */
11624 * \fn int power_up_atv ()
11625 * \brief Power up ATV.
11626 * \param demod instance of demodulator
11627 * \param standard either NTSC or FM (sub strandard for ATV )
11628 * \return int.
11630 * * Starts ATV and IQM
11631 * * AUdio already started during standard init for ATV.
11633 static int power_up_atv(struct drx_demod_instance *demod, enum drx_standard standard)
11635 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
11636 int rc;
11638 /* ATV NTSC */
11639 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_COMM_EXEC__A, ATV_COMM_EXEC_ACTIVE, 0);
11640 if (rc != 0) {
11641 pr_err("error %d\n", rc);
11642 goto rw_error;
11644 /* turn on IQM_AF */
11645 rc = set_iqm_af(demod, true);
11646 if (rc != 0) {
11647 pr_err("error %d\n", rc);
11648 goto rw_error;
11650 rc = adc_synchronization(demod);
11651 if (rc != 0) {
11652 pr_err("error %d\n", rc);
11653 goto rw_error;
11656 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_ACTIVE, 0);
11657 if (rc != 0) {
11658 pr_err("error %d\n", rc);
11659 goto rw_error;
11662 /* Audio, already done during set standard */
11664 return 0;
11665 rw_error:
11666 return -EIO;
11668 #endif
11670 /* -------------------------------------------------------------------------- */
11673 * \fn int power_down_atv ()
11674 * \brief Power down ATV.
11675 * \param demod instance of demodulator
11676 * \param standard either NTSC or FM (sub strandard for ATV )
11677 * \return int.
11679 * Stops and thus resets ATV and IQM block
11680 * SIF and CVBS ADC are powered down
11681 * Calls audio power down
11683 static int
11684 power_down_atv(struct drx_demod_instance *demod, enum drx_standard standard, bool primary)
11686 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
11687 struct drxjscu_cmd cmd_scu = { /* command */ 0,
11688 /* parameter_len */ 0,
11689 /* result_len */ 0,
11690 /* *parameter */ NULL,
11691 /* *result */ NULL
11693 int rc;
11694 u16 cmd_result = 0;
11696 /* ATV NTSC */
11698 /* Stop ATV SCU (will reset ATV and IQM hardware */
11699 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_ATV |
11700 SCU_RAM_COMMAND_CMD_DEMOD_STOP;
11701 cmd_scu.parameter_len = 0;
11702 cmd_scu.result_len = 1;
11703 cmd_scu.parameter = NULL;
11704 cmd_scu.result = &cmd_result;
11705 rc = scu_command(dev_addr, &cmd_scu);
11706 if (rc != 0) {
11707 pr_err("error %d\n", rc);
11708 goto rw_error;
11710 /* Disable ATV outputs (ATV reset enables CVBS, undo this) */
11711 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_STDBY__A, (ATV_TOP_STDBY_SIF_STDBY_STANDBY & (~ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE)), 0);
11712 if (rc != 0) {
11713 pr_err("error %d\n", rc);
11714 goto rw_error;
11717 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_COMM_EXEC__A, ATV_COMM_EXEC_STOP, 0);
11718 if (rc != 0) {
11719 pr_err("error %d\n", rc);
11720 goto rw_error;
11722 if (primary) {
11723 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP, 0);
11724 if (rc != 0) {
11725 pr_err("error %d\n", rc);
11726 goto rw_error;
11728 rc = set_iqm_af(demod, false);
11729 if (rc != 0) {
11730 pr_err("error %d\n", rc);
11731 goto rw_error;
11733 } else {
11734 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0);
11735 if (rc != 0) {
11736 pr_err("error %d\n", rc);
11737 goto rw_error;
11739 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0);
11740 if (rc != 0) {
11741 pr_err("error %d\n", rc);
11742 goto rw_error;
11744 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0);
11745 if (rc != 0) {
11746 pr_err("error %d\n", rc);
11747 goto rw_error;
11749 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0);
11750 if (rc != 0) {
11751 pr_err("error %d\n", rc);
11752 goto rw_error;
11754 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0);
11755 if (rc != 0) {
11756 pr_err("error %d\n", rc);
11757 goto rw_error;
11760 rc = power_down_aud(demod);
11761 if (rc != 0) {
11762 pr_err("error %d\n", rc);
11763 goto rw_error;
11766 return 0;
11767 rw_error:
11768 return -EIO;
11771 /* -------------------------------------------------------------------------- */
11773 * \fn int set_atv_standard ()
11774 * \brief Set up ATV demodulator.
11775 * \param demod instance of demodulator
11776 * \param standard either NTSC or FM (sub strandard for ATV )
11777 * \return int.
11779 * Init all channel independent registers.
11780 * Assuming that IQM, ATV and AUD blocks have been reset and are in STOP mode
11783 #if 0
11784 #define SCU_RAM_ATV_ENABLE_IIR_WA__A 0x831F6D /* TODO remove after done with reg import */
11785 static int
11786 set_atv_standard(struct drx_demod_instance *demod, enum drx_standard *standard)
11788 /* TODO: enable alternative for tap settings via external file
11790 something like:
11791 #ifdef DRXJ_ATV_COEF_FILE
11792 #include DRXJ_ATV_COEF_FILE
11793 #else
11794 ... code defining fixed coef's ...
11795 #endif
11797 Cutsomer must create file "customer_coefs.c.inc" containing
11798 modified copy off the constants below, and define the compiler
11799 switch DRXJ_ATV_COEF_FILE="customer_coefs.c.inc".
11801 Still to check if this will work; DRXJ_16TO8 macro may cause
11802 trouble ?
11804 const u8 ntsc_taps_re[] = {
11805 DRXJ_16TO8(-12), /* re0 */
11806 DRXJ_16TO8(-9), /* re1 */
11807 DRXJ_16TO8(9), /* re2 */
11808 DRXJ_16TO8(19), /* re3 */
11809 DRXJ_16TO8(-4), /* re4 */
11810 DRXJ_16TO8(-24), /* re5 */
11811 DRXJ_16TO8(-6), /* re6 */
11812 DRXJ_16TO8(16), /* re7 */
11813 DRXJ_16TO8(6), /* re8 */
11814 DRXJ_16TO8(-16), /* re9 */
11815 DRXJ_16TO8(-5), /* re10 */
11816 DRXJ_16TO8(13), /* re11 */
11817 DRXJ_16TO8(-2), /* re12 */
11818 DRXJ_16TO8(-20), /* re13 */
11819 DRXJ_16TO8(4), /* re14 */
11820 DRXJ_16TO8(25), /* re15 */
11821 DRXJ_16TO8(-6), /* re16 */
11822 DRXJ_16TO8(-36), /* re17 */
11823 DRXJ_16TO8(2), /* re18 */
11824 DRXJ_16TO8(38), /* re19 */
11825 DRXJ_16TO8(-10), /* re20 */
11826 DRXJ_16TO8(-48), /* re21 */
11827 DRXJ_16TO8(35), /* re22 */
11828 DRXJ_16TO8(94), /* re23 */
11829 DRXJ_16TO8(-59), /* re24 */
11830 DRXJ_16TO8(-217), /* re25 */
11831 DRXJ_16TO8(50), /* re26 */
11832 DRXJ_16TO8(679) /* re27 */
11834 const u8 ntsc_taps_im[] = {
11835 DRXJ_16TO8(11), /* im0 */
11836 DRXJ_16TO8(1), /* im1 */
11837 DRXJ_16TO8(-10), /* im2 */
11838 DRXJ_16TO8(2), /* im3 */
11839 DRXJ_16TO8(24), /* im4 */
11840 DRXJ_16TO8(21), /* im5 */
11841 DRXJ_16TO8(1), /* im6 */
11842 DRXJ_16TO8(-4), /* im7 */
11843 DRXJ_16TO8(7), /* im8 */
11844 DRXJ_16TO8(14), /* im9 */
11845 DRXJ_16TO8(27), /* im10 */
11846 DRXJ_16TO8(42), /* im11 */
11847 DRXJ_16TO8(22), /* im12 */
11848 DRXJ_16TO8(-20), /* im13 */
11849 DRXJ_16TO8(2), /* im14 */
11850 DRXJ_16TO8(98), /* im15 */
11851 DRXJ_16TO8(122), /* im16 */
11852 DRXJ_16TO8(0), /* im17 */
11853 DRXJ_16TO8(-85), /* im18 */
11854 DRXJ_16TO8(51), /* im19 */
11855 DRXJ_16TO8(247), /* im20 */
11856 DRXJ_16TO8(192), /* im21 */
11857 DRXJ_16TO8(-55), /* im22 */
11858 DRXJ_16TO8(-95), /* im23 */
11859 DRXJ_16TO8(217), /* im24 */
11860 DRXJ_16TO8(544), /* im25 */
11861 DRXJ_16TO8(553), /* im26 */
11862 DRXJ_16TO8(302) /* im27 */
11864 const u8 bg_taps_re[] = {
11865 DRXJ_16TO8(-18), /* re0 */
11866 DRXJ_16TO8(18), /* re1 */
11867 DRXJ_16TO8(19), /* re2 */
11868 DRXJ_16TO8(-26), /* re3 */
11869 DRXJ_16TO8(-20), /* re4 */
11870 DRXJ_16TO8(36), /* re5 */
11871 DRXJ_16TO8(5), /* re6 */
11872 DRXJ_16TO8(-51), /* re7 */
11873 DRXJ_16TO8(15), /* re8 */
11874 DRXJ_16TO8(45), /* re9 */
11875 DRXJ_16TO8(-46), /* re10 */
11876 DRXJ_16TO8(-24), /* re11 */
11877 DRXJ_16TO8(71), /* re12 */
11878 DRXJ_16TO8(-17), /* re13 */
11879 DRXJ_16TO8(-83), /* re14 */
11880 DRXJ_16TO8(74), /* re15 */
11881 DRXJ_16TO8(75), /* re16 */
11882 DRXJ_16TO8(-134), /* re17 */
11883 DRXJ_16TO8(-40), /* re18 */
11884 DRXJ_16TO8(191), /* re19 */
11885 DRXJ_16TO8(-11), /* re20 */
11886 DRXJ_16TO8(-233), /* re21 */
11887 DRXJ_16TO8(74), /* re22 */
11888 DRXJ_16TO8(271), /* re23 */
11889 DRXJ_16TO8(-132), /* re24 */
11890 DRXJ_16TO8(-341), /* re25 */
11891 DRXJ_16TO8(172), /* re26 */
11892 DRXJ_16TO8(801) /* re27 */
11894 const u8 bg_taps_im[] = {
11895 DRXJ_16TO8(-24), /* im0 */
11896 DRXJ_16TO8(-10), /* im1 */
11897 DRXJ_16TO8(9), /* im2 */
11898 DRXJ_16TO8(-5), /* im3 */
11899 DRXJ_16TO8(-51), /* im4 */
11900 DRXJ_16TO8(-17), /* im5 */
11901 DRXJ_16TO8(31), /* im6 */
11902 DRXJ_16TO8(-48), /* im7 */
11903 DRXJ_16TO8(-95), /* im8 */
11904 DRXJ_16TO8(25), /* im9 */
11905 DRXJ_16TO8(37), /* im10 */
11906 DRXJ_16TO8(-123), /* im11 */
11907 DRXJ_16TO8(-77), /* im12 */
11908 DRXJ_16TO8(94), /* im13 */
11909 DRXJ_16TO8(-10), /* im14 */
11910 DRXJ_16TO8(-149), /* im15 */
11911 DRXJ_16TO8(10), /* im16 */
11912 DRXJ_16TO8(108), /* im17 */
11913 DRXJ_16TO8(-49), /* im18 */
11914 DRXJ_16TO8(-59), /* im19 */
11915 DRXJ_16TO8(90), /* im20 */
11916 DRXJ_16TO8(73), /* im21 */
11917 DRXJ_16TO8(55), /* im22 */
11918 DRXJ_16TO8(148), /* im23 */
11919 DRXJ_16TO8(86), /* im24 */
11920 DRXJ_16TO8(146), /* im25 */
11921 DRXJ_16TO8(687), /* im26 */
11922 DRXJ_16TO8(877) /* im27 */
11924 const u8 dk_i_l_lp_taps_re[] = {
11925 DRXJ_16TO8(-23), /* re0 */
11926 DRXJ_16TO8(9), /* re1 */
11927 DRXJ_16TO8(16), /* re2 */
11928 DRXJ_16TO8(-26), /* re3 */
11929 DRXJ_16TO8(-3), /* re4 */
11930 DRXJ_16TO8(13), /* re5 */
11931 DRXJ_16TO8(-19), /* re6 */
11932 DRXJ_16TO8(-3), /* re7 */
11933 DRXJ_16TO8(13), /* re8 */
11934 DRXJ_16TO8(-26), /* re9 */
11935 DRXJ_16TO8(-4), /* re10 */
11936 DRXJ_16TO8(28), /* re11 */
11937 DRXJ_16TO8(-15), /* re12 */
11938 DRXJ_16TO8(-14), /* re13 */
11939 DRXJ_16TO8(10), /* re14 */
11940 DRXJ_16TO8(1), /* re15 */
11941 DRXJ_16TO8(39), /* re16 */
11942 DRXJ_16TO8(-18), /* re17 */
11943 DRXJ_16TO8(-90), /* re18 */
11944 DRXJ_16TO8(109), /* re19 */
11945 DRXJ_16TO8(113), /* re20 */
11946 DRXJ_16TO8(-235), /* re21 */
11947 DRXJ_16TO8(-49), /* re22 */
11948 DRXJ_16TO8(359), /* re23 */
11949 DRXJ_16TO8(-79), /* re24 */
11950 DRXJ_16TO8(-459), /* re25 */
11951 DRXJ_16TO8(206), /* re26 */
11952 DRXJ_16TO8(894) /* re27 */
11954 const u8 dk_i_l_lp_taps_im[] = {
11955 DRXJ_16TO8(-8), /* im0 */
11956 DRXJ_16TO8(-20), /* im1 */
11957 DRXJ_16TO8(17), /* im2 */
11958 DRXJ_16TO8(-14), /* im3 */
11959 DRXJ_16TO8(-52), /* im4 */
11960 DRXJ_16TO8(4), /* im5 */
11961 DRXJ_16TO8(9), /* im6 */
11962 DRXJ_16TO8(-62), /* im7 */
11963 DRXJ_16TO8(-47), /* im8 */
11964 DRXJ_16TO8(0), /* im9 */
11965 DRXJ_16TO8(-20), /* im10 */
11966 DRXJ_16TO8(-48), /* im11 */
11967 DRXJ_16TO8(-65), /* im12 */
11968 DRXJ_16TO8(-23), /* im13 */
11969 DRXJ_16TO8(44), /* im14 */
11970 DRXJ_16TO8(-60), /* im15 */
11971 DRXJ_16TO8(-113), /* im16 */
11972 DRXJ_16TO8(92), /* im17 */
11973 DRXJ_16TO8(81), /* im18 */
11974 DRXJ_16TO8(-125), /* im19 */
11975 DRXJ_16TO8(28), /* im20 */
11976 DRXJ_16TO8(182), /* im21 */
11977 DRXJ_16TO8(35), /* im22 */
11978 DRXJ_16TO8(94), /* im23 */
11979 DRXJ_16TO8(180), /* im24 */
11980 DRXJ_16TO8(134), /* im25 */
11981 DRXJ_16TO8(657), /* im26 */
11982 DRXJ_16TO8(1023) /* im27 */
11984 const u8 fm_taps_re[] = {
11985 DRXJ_16TO8(0), /* re0 */
11986 DRXJ_16TO8(0), /* re1 */
11987 DRXJ_16TO8(0), /* re2 */
11988 DRXJ_16TO8(0), /* re3 */
11989 DRXJ_16TO8(0), /* re4 */
11990 DRXJ_16TO8(0), /* re5 */
11991 DRXJ_16TO8(0), /* re6 */
11992 DRXJ_16TO8(0), /* re7 */
11993 DRXJ_16TO8(0), /* re8 */
11994 DRXJ_16TO8(0), /* re9 */
11995 DRXJ_16TO8(0), /* re10 */
11996 DRXJ_16TO8(0), /* re11 */
11997 DRXJ_16TO8(0), /* re12 */
11998 DRXJ_16TO8(0), /* re13 */
11999 DRXJ_16TO8(0), /* re14 */
12000 DRXJ_16TO8(0), /* re15 */
12001 DRXJ_16TO8(0), /* re16 */
12002 DRXJ_16TO8(0), /* re17 */
12003 DRXJ_16TO8(0), /* re18 */
12004 DRXJ_16TO8(0), /* re19 */
12005 DRXJ_16TO8(0), /* re20 */
12006 DRXJ_16TO8(0), /* re21 */
12007 DRXJ_16TO8(0), /* re22 */
12008 DRXJ_16TO8(0), /* re23 */
12009 DRXJ_16TO8(0), /* re24 */
12010 DRXJ_16TO8(0), /* re25 */
12011 DRXJ_16TO8(0), /* re26 */
12012 DRXJ_16TO8(0) /* re27 */
12014 const u8 fm_taps_im[] = {
12015 DRXJ_16TO8(-6), /* im0 */
12016 DRXJ_16TO8(2), /* im1 */
12017 DRXJ_16TO8(14), /* im2 */
12018 DRXJ_16TO8(-38), /* im3 */
12019 DRXJ_16TO8(58), /* im4 */
12020 DRXJ_16TO8(-62), /* im5 */
12021 DRXJ_16TO8(42), /* im6 */
12022 DRXJ_16TO8(0), /* im7 */
12023 DRXJ_16TO8(-45), /* im8 */
12024 DRXJ_16TO8(73), /* im9 */
12025 DRXJ_16TO8(-65), /* im10 */
12026 DRXJ_16TO8(23), /* im11 */
12027 DRXJ_16TO8(34), /* im12 */
12028 DRXJ_16TO8(-77), /* im13 */
12029 DRXJ_16TO8(80), /* im14 */
12030 DRXJ_16TO8(-39), /* im15 */
12031 DRXJ_16TO8(-25), /* im16 */
12032 DRXJ_16TO8(78), /* im17 */
12033 DRXJ_16TO8(-90), /* im18 */
12034 DRXJ_16TO8(52), /* im19 */
12035 DRXJ_16TO8(16), /* im20 */
12036 DRXJ_16TO8(-77), /* im21 */
12037 DRXJ_16TO8(97), /* im22 */
12038 DRXJ_16TO8(-62), /* im23 */
12039 DRXJ_16TO8(-8), /* im24 */
12040 DRXJ_16TO8(75), /* im25 */
12041 DRXJ_16TO8(-100), /* im26 */
12042 DRXJ_16TO8(70) /* im27 */
12045 struct i2c_device_addr *dev_addr = NULL;
12046 struct drxjscu_cmd cmd_scu = { /* command */ 0,
12047 /* parameter_len */ 0,
12048 /* result_len */ 0,
12049 /* *parameter */ NULL,
12050 /* *result */ NULL
12052 u16 cmd_result = 0;
12053 u16 cmd_param = 0;
12054 struct drxj_data *ext_attr = NULL;
12055 int rc;
12057 ext_attr = (struct drxj_data *) demod->my_ext_attr;
12058 dev_addr = demod->my_i2c_dev_addr;
12060 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_COMM_EXEC__A, ATV_COMM_EXEC_STOP, 0);
12061 if (rc != 0) {
12062 pr_err("error %d\n", rc);
12063 goto rw_error;
12065 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0);
12066 if (rc != 0) {
12067 pr_err("error %d\n", rc);
12068 goto rw_error;
12070 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0);
12071 if (rc != 0) {
12072 pr_err("error %d\n", rc);
12073 goto rw_error;
12075 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0);
12076 if (rc != 0) {
12077 pr_err("error %d\n", rc);
12078 goto rw_error;
12080 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0);
12081 if (rc != 0) {
12082 pr_err("error %d\n", rc);
12083 goto rw_error;
12085 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0);
12086 if (rc != 0) {
12087 pr_err("error %d\n", rc);
12088 goto rw_error;
12090 /* Reset ATV SCU */
12091 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_ATV |
12092 SCU_RAM_COMMAND_CMD_DEMOD_RESET;
12093 cmd_scu.parameter_len = 0;
12094 cmd_scu.result_len = 1;
12095 cmd_scu.parameter = NULL;
12096 cmd_scu.result = &cmd_result;
12097 rc = scu_command(dev_addr, &cmd_scu);
12098 if (rc != 0) {
12099 pr_err("error %d\n", rc);
12100 goto rw_error;
12103 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_MOD_CONTROL__A, ATV_TOP_MOD_CONTROL__PRE, 0);
12104 if (rc != 0) {
12105 pr_err("error %d\n", rc);
12106 goto rw_error;
12109 /* TODO remove AUTO/OFF patches after ucode fix. */
12110 switch (*standard) {
12111 case DRX_STANDARD_NTSC:
12112 /* NTSC */
12113 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_MN;
12115 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_LO_INCR__A, IQM_RT_LO_INCR_MN, 0);
12116 if (rc != 0) {
12117 pr_err("error %d\n", rc);
12118 goto rw_error;
12120 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_MIDTAP__A, IQM_CF_MIDTAP_RE__M, 0);
12121 if (rc != 0) {
12122 pr_err("error %d\n", rc);
12123 goto rw_error;
12125 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_RE0__A, sizeof(ntsc_taps_re), ((u8 *)ntsc_taps_re), 0);
12126 if (rc != 0) {
12127 pr_err("error %d\n", rc);
12128 goto rw_error;
12130 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_IM0__A, sizeof(ntsc_taps_im), ((u8 *)ntsc_taps_im), 0);
12131 if (rc != 0) {
12132 pr_err("error %d\n", rc);
12133 goto rw_error;
12136 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_AMP_TH__A, ATV_TOP_CR_AMP_TH_MN, 0);
12137 if (rc != 0) {
12138 pr_err("error %d\n", rc);
12139 goto rw_error;
12141 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_CONT__A, (ATV_TOP_CR_CONT_CR_P_MN | ATV_TOP_CR_CONT_CR_D_MN | ATV_TOP_CR_CONT_CR_I_MN), 0);
12142 if (rc != 0) {
12143 pr_err("error %d\n", rc);
12144 goto rw_error;
12146 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_OVM_TH__A, ATV_TOP_CR_OVM_TH_MN, 0);
12147 if (rc != 0) {
12148 pr_err("error %d\n", rc);
12149 goto rw_error;
12151 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_STD__A, (ATV_TOP_STD_MODE_MN | ATV_TOP_STD_VID_POL_MN), 0);
12152 if (rc != 0) {
12153 pr_err("error %d\n", rc);
12154 goto rw_error;
12156 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_VID_AMP__A, ATV_TOP_VID_AMP_MN, 0);
12157 if (rc != 0) {
12158 pr_err("error %d\n", rc);
12159 goto rw_error;
12162 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_AGC_MODE__A, (SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_FM | SCU_RAM_ATV_AGC_MODE_FAST_VAGC_EN_FAGC_ENABLE), 0);
12163 if (rc != 0) {
12164 pr_err("error %d\n", rc);
12165 goto rw_error;
12167 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000, 0);
12168 if (rc != 0) {
12169 pr_err("error %d\n", rc);
12170 goto rw_error;
12172 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000, 0);
12173 if (rc != 0) {
12174 pr_err("error %d\n", rc);
12175 goto rw_error;
12177 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_AMS_MAX_REF__A, SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_BG_MN, 0);
12178 if (rc != 0) {
12179 pr_err("error %d\n", rc);
12180 goto rw_error;
12182 ext_attr->phase_correction_bypass = false;
12183 ext_attr->enable_cvbs_output = true;
12184 break;
12185 case DRX_STANDARD_FM:
12186 /* FM */
12187 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_FM;
12189 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_LO_INCR__A, 2994, 0);
12190 if (rc != 0) {
12191 pr_err("error %d\n", rc);
12192 goto rw_error;
12194 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_MIDTAP__A, 0, 0);
12195 if (rc != 0) {
12196 pr_err("error %d\n", rc);
12197 goto rw_error;
12199 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_RE0__A, sizeof(fm_taps_re), ((u8 *)fm_taps_re), 0);
12200 if (rc != 0) {
12201 pr_err("error %d\n", rc);
12202 goto rw_error;
12204 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_IM0__A, sizeof(fm_taps_im), ((u8 *)fm_taps_im), 0);
12205 if (rc != 0) {
12206 pr_err("error %d\n", rc);
12207 goto rw_error;
12209 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_STD__A, (ATV_TOP_STD_MODE_FM | ATV_TOP_STD_VID_POL_FM), 0);
12210 if (rc != 0) {
12211 pr_err("error %d\n", rc);
12212 goto rw_error;
12214 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_MOD_CONTROL__A, 0, 0);
12215 if (rc != 0) {
12216 pr_err("error %d\n", rc);
12217 goto rw_error;
12219 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_CONT__A, 0, 0);
12220 if (rc != 0) {
12221 pr_err("error %d\n", rc);
12222 goto rw_error;
12225 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_AGC_MODE__A, (SCU_RAM_ATV_AGC_MODE_VAGC_VEL_AGC_SLOW | SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_FM), 0);
12226 if (rc != 0) {
12227 pr_err("error %d\n", rc);
12228 goto rw_error;
12230 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_ROT_BP__A, IQM_RT_ROT_BP_ROT_OFF_OFF, 0);
12231 if (rc != 0) {
12232 pr_err("error %d\n", rc);
12233 goto rw_error;
12235 ext_attr->phase_correction_bypass = true;
12236 ext_attr->enable_cvbs_output = false;
12237 break;
12238 case DRX_STANDARD_PAL_SECAM_BG:
12239 /* PAL/SECAM B/G */
12240 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_B;
12242 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_LO_INCR__A, 1820, 0);
12243 if (rc != 0) {
12244 pr_err("error %d\n", rc);
12245 goto rw_error;
12246 } /* TODO check with IS */
12247 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_MIDTAP__A, IQM_CF_MIDTAP_RE__M, 0);
12248 if (rc != 0) {
12249 pr_err("error %d\n", rc);
12250 goto rw_error;
12252 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_RE0__A, sizeof(bg_taps_re), ((u8 *)bg_taps_re), 0);
12253 if (rc != 0) {
12254 pr_err("error %d\n", rc);
12255 goto rw_error;
12257 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_IM0__A, sizeof(bg_taps_im), ((u8 *)bg_taps_im), 0);
12258 if (rc != 0) {
12259 pr_err("error %d\n", rc);
12260 goto rw_error;
12262 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_VID_AMP__A, ATV_TOP_VID_AMP_BG, 0);
12263 if (rc != 0) {
12264 pr_err("error %d\n", rc);
12265 goto rw_error;
12267 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_AMP_TH__A, ATV_TOP_CR_AMP_TH_BG, 0);
12268 if (rc != 0) {
12269 pr_err("error %d\n", rc);
12270 goto rw_error;
12272 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_CONT__A, (ATV_TOP_CR_CONT_CR_P_BG | ATV_TOP_CR_CONT_CR_D_BG | ATV_TOP_CR_CONT_CR_I_BG), 0);
12273 if (rc != 0) {
12274 pr_err("error %d\n", rc);
12275 goto rw_error;
12277 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_OVM_TH__A, ATV_TOP_CR_OVM_TH_BG, 0);
12278 if (rc != 0) {
12279 pr_err("error %d\n", rc);
12280 goto rw_error;
12282 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_STD__A, (ATV_TOP_STD_MODE_BG | ATV_TOP_STD_VID_POL_BG), 0);
12283 if (rc != 0) {
12284 pr_err("error %d\n", rc);
12285 goto rw_error;
12287 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_AGC_MODE__A, (SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_FM | SCU_RAM_ATV_AGC_MODE_FAST_VAGC_EN_FAGC_ENABLE), 0);
12288 if (rc != 0) {
12289 pr_err("error %d\n", rc);
12290 goto rw_error;
12292 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000, 0);
12293 if (rc != 0) {
12294 pr_err("error %d\n", rc);
12295 goto rw_error;
12297 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000, 0);
12298 if (rc != 0) {
12299 pr_err("error %d\n", rc);
12300 goto rw_error;
12302 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_AMS_MAX_REF__A, SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_BG_MN, 0);
12303 if (rc != 0) {
12304 pr_err("error %d\n", rc);
12305 goto rw_error;
12307 ext_attr->phase_correction_bypass = false;
12308 ext_attr->atv_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
12309 ext_attr->enable_cvbs_output = true;
12310 break;
12311 case DRX_STANDARD_PAL_SECAM_DK:
12312 /* PAL/SECAM D/K */
12313 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_DK;
12315 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_LO_INCR__A, 2225, 0);
12316 if (rc != 0) {
12317 pr_err("error %d\n", rc);
12318 goto rw_error;
12319 } /* TODO check with IS */
12320 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_MIDTAP__A, IQM_CF_MIDTAP_RE__M, 0);
12321 if (rc != 0) {
12322 pr_err("error %d\n", rc);
12323 goto rw_error;
12325 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_RE0__A, sizeof(dk_i_l_lp_taps_re), ((u8 *)dk_i_l_lp_taps_re), 0);
12326 if (rc != 0) {
12327 pr_err("error %d\n", rc);
12328 goto rw_error;
12330 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_IM0__A, sizeof(dk_i_l_lp_taps_im), ((u8 *)dk_i_l_lp_taps_im), 0);
12331 if (rc != 0) {
12332 pr_err("error %d\n", rc);
12333 goto rw_error;
12335 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_AMP_TH__A, ATV_TOP_CR_AMP_TH_DK, 0);
12336 if (rc != 0) {
12337 pr_err("error %d\n", rc);
12338 goto rw_error;
12340 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_VID_AMP__A, ATV_TOP_VID_AMP_DK, 0);
12341 if (rc != 0) {
12342 pr_err("error %d\n", rc);
12343 goto rw_error;
12345 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_CONT__A, (ATV_TOP_CR_CONT_CR_P_DK | ATV_TOP_CR_CONT_CR_D_DK | ATV_TOP_CR_CONT_CR_I_DK), 0);
12346 if (rc != 0) {
12347 pr_err("error %d\n", rc);
12348 goto rw_error;
12350 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_OVM_TH__A, ATV_TOP_CR_OVM_TH_DK, 0);
12351 if (rc != 0) {
12352 pr_err("error %d\n", rc);
12353 goto rw_error;
12355 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_STD__A, (ATV_TOP_STD_MODE_DK | ATV_TOP_STD_VID_POL_DK), 0);
12356 if (rc != 0) {
12357 pr_err("error %d\n", rc);
12358 goto rw_error;
12360 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_AGC_MODE__A, (SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_FM | SCU_RAM_ATV_AGC_MODE_FAST_VAGC_EN_FAGC_ENABLE), 0);
12361 if (rc != 0) {
12362 pr_err("error %d\n", rc);
12363 goto rw_error;
12365 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000, 0);
12366 if (rc != 0) {
12367 pr_err("error %d\n", rc);
12368 goto rw_error;
12370 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000, 0);
12371 if (rc != 0) {
12372 pr_err("error %d\n", rc);
12373 goto rw_error;
12375 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_AMS_MAX_REF__A, SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_DK, 0);
12376 if (rc != 0) {
12377 pr_err("error %d\n", rc);
12378 goto rw_error;
12380 ext_attr->phase_correction_bypass = false;
12381 ext_attr->atv_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
12382 ext_attr->enable_cvbs_output = true;
12383 break;
12384 case DRX_STANDARD_PAL_SECAM_I:
12385 /* PAL/SECAM I */
12386 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_I;
12388 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_LO_INCR__A, 2225, 0);
12389 if (rc != 0) {
12390 pr_err("error %d\n", rc);
12391 goto rw_error;
12392 } /* TODO check with IS */
12393 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_MIDTAP__A, IQM_CF_MIDTAP_RE__M, 0);
12394 if (rc != 0) {
12395 pr_err("error %d\n", rc);
12396 goto rw_error;
12398 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_RE0__A, sizeof(dk_i_l_lp_taps_re), ((u8 *)dk_i_l_lp_taps_re), 0);
12399 if (rc != 0) {
12400 pr_err("error %d\n", rc);
12401 goto rw_error;
12403 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_IM0__A, sizeof(dk_i_l_lp_taps_im), ((u8 *)dk_i_l_lp_taps_im), 0);
12404 if (rc != 0) {
12405 pr_err("error %d\n", rc);
12406 goto rw_error;
12408 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_AMP_TH__A, ATV_TOP_CR_AMP_TH_I, 0);
12409 if (rc != 0) {
12410 pr_err("error %d\n", rc);
12411 goto rw_error;
12413 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_VID_AMP__A, ATV_TOP_VID_AMP_I, 0);
12414 if (rc != 0) {
12415 pr_err("error %d\n", rc);
12416 goto rw_error;
12418 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_CONT__A, (ATV_TOP_CR_CONT_CR_P_I | ATV_TOP_CR_CONT_CR_D_I | ATV_TOP_CR_CONT_CR_I_I), 0);
12419 if (rc != 0) {
12420 pr_err("error %d\n", rc);
12421 goto rw_error;
12423 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_OVM_TH__A, ATV_TOP_CR_OVM_TH_I, 0);
12424 if (rc != 0) {
12425 pr_err("error %d\n", rc);
12426 goto rw_error;
12428 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_STD__A, (ATV_TOP_STD_MODE_I | ATV_TOP_STD_VID_POL_I), 0);
12429 if (rc != 0) {
12430 pr_err("error %d\n", rc);
12431 goto rw_error;
12433 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_AGC_MODE__A, (SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_FM | SCU_RAM_ATV_AGC_MODE_FAST_VAGC_EN_FAGC_ENABLE), 0);
12434 if (rc != 0) {
12435 pr_err("error %d\n", rc);
12436 goto rw_error;
12438 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000, 0);
12439 if (rc != 0) {
12440 pr_err("error %d\n", rc);
12441 goto rw_error;
12443 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000, 0);
12444 if (rc != 0) {
12445 pr_err("error %d\n", rc);
12446 goto rw_error;
12448 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_AMS_MAX_REF__A, SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_I, 0);
12449 if (rc != 0) {
12450 pr_err("error %d\n", rc);
12451 goto rw_error;
12453 ext_attr->phase_correction_bypass = false;
12454 ext_attr->atv_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
12455 ext_attr->enable_cvbs_output = true;
12456 break;
12457 case DRX_STANDARD_PAL_SECAM_L:
12458 /* PAL/SECAM L with negative modulation */
12459 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_L;
12461 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_LO_INCR__A, 2225, 0);
12462 if (rc != 0) {
12463 pr_err("error %d\n", rc);
12464 goto rw_error;
12465 } /* TODO check with IS */
12466 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_VID_AMP__A, ATV_TOP_VID_AMP_L, 0);
12467 if (rc != 0) {
12468 pr_err("error %d\n", rc);
12469 goto rw_error;
12471 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_MIDTAP__A, IQM_CF_MIDTAP_RE__M, 0);
12472 if (rc != 0) {
12473 pr_err("error %d\n", rc);
12474 goto rw_error;
12476 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_RE0__A, sizeof(dk_i_l_lp_taps_re), ((u8 *)dk_i_l_lp_taps_re), 0);
12477 if (rc != 0) {
12478 pr_err("error %d\n", rc);
12479 goto rw_error;
12481 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_IM0__A, sizeof(dk_i_l_lp_taps_im), ((u8 *)dk_i_l_lp_taps_im), 0);
12482 if (rc != 0) {
12483 pr_err("error %d\n", rc);
12484 goto rw_error;
12486 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_AMP_TH__A, 0x2, 0);
12487 if (rc != 0) {
12488 pr_err("error %d\n", rc);
12489 goto rw_error;
12490 } /* TODO check with IS */
12491 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_CONT__A, (ATV_TOP_CR_CONT_CR_P_L | ATV_TOP_CR_CONT_CR_D_L | ATV_TOP_CR_CONT_CR_I_L), 0);
12492 if (rc != 0) {
12493 pr_err("error %d\n", rc);
12494 goto rw_error;
12496 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_OVM_TH__A, ATV_TOP_CR_OVM_TH_L, 0);
12497 if (rc != 0) {
12498 pr_err("error %d\n", rc);
12499 goto rw_error;
12501 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_STD__A, (ATV_TOP_STD_MODE_L | ATV_TOP_STD_VID_POL_L), 0);
12502 if (rc != 0) {
12503 pr_err("error %d\n", rc);
12504 goto rw_error;
12506 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_AGC_MODE__A, (SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_AM | SCU_RAM_ATV_AGC_MODE_BP_EN_BPC_ENABLE | SCU_RAM_ATV_AGC_MODE_VAGC_VEL_AGC_SLOW), 0);
12507 if (rc != 0) {
12508 pr_err("error %d\n", rc);
12509 goto rw_error;
12511 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000, 0);
12512 if (rc != 0) {
12513 pr_err("error %d\n", rc);
12514 goto rw_error;
12516 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000, 0);
12517 if (rc != 0) {
12518 pr_err("error %d\n", rc);
12519 goto rw_error;
12521 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_AMS_MAX_REF__A, SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_LLP, 0);
12522 if (rc != 0) {
12523 pr_err("error %d\n", rc);
12524 goto rw_error;
12526 ext_attr->phase_correction_bypass = false;
12527 ext_attr->atv_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_USER;
12528 ext_attr->atv_if_agc_cfg.output_level = ext_attr->atv_rf_agc_cfg.top;
12529 ext_attr->enable_cvbs_output = true;
12530 break;
12531 case DRX_STANDARD_PAL_SECAM_LP:
12532 /* PAL/SECAM L with positive modulation */
12533 cmd_param = SCU_RAM_ATV_STANDARD_STANDARD_LP;
12535 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_VID_AMP__A, ATV_TOP_VID_AMP_LP, 0);
12536 if (rc != 0) {
12537 pr_err("error %d\n", rc);
12538 goto rw_error;
12540 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_LO_INCR__A, 2225, 0);
12541 if (rc != 0) {
12542 pr_err("error %d\n", rc);
12543 goto rw_error;
12544 } /* TODO check with IS */
12545 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_MIDTAP__A, IQM_CF_MIDTAP_RE__M, 0);
12546 if (rc != 0) {
12547 pr_err("error %d\n", rc);
12548 goto rw_error;
12550 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_RE0__A, sizeof(dk_i_l_lp_taps_re), ((u8 *)dk_i_l_lp_taps_re), 0);
12551 if (rc != 0) {
12552 pr_err("error %d\n", rc);
12553 goto rw_error;
12555 rc = DRXJ_DAP.write_block_func(dev_addr, IQM_CF_TAP_IM0__A, sizeof(dk_i_l_lp_taps_im), ((u8 *)dk_i_l_lp_taps_im), 0);
12556 if (rc != 0) {
12557 pr_err("error %d\n", rc);
12558 goto rw_error;
12560 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_AMP_TH__A, 0x2, 0);
12561 if (rc != 0) {
12562 pr_err("error %d\n", rc);
12563 goto rw_error;
12564 } /* TODO check with IS */
12565 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_CONT__A, (ATV_TOP_CR_CONT_CR_P_LP | ATV_TOP_CR_CONT_CR_D_LP | ATV_TOP_CR_CONT_CR_I_LP), 0);
12566 if (rc != 0) {
12567 pr_err("error %d\n", rc);
12568 goto rw_error;
12570 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_OVM_TH__A, ATV_TOP_CR_OVM_TH_LP, 0);
12571 if (rc != 0) {
12572 pr_err("error %d\n", rc);
12573 goto rw_error;
12575 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_STD__A, (ATV_TOP_STD_MODE_LP | ATV_TOP_STD_VID_POL_LP), 0);
12576 if (rc != 0) {
12577 pr_err("error %d\n", rc);
12578 goto rw_error;
12580 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_AGC_MODE__A, (SCU_RAM_ATV_AGC_MODE_SIF_STD_SIF_AGC_AM | SCU_RAM_ATV_AGC_MODE_BP_EN_BPC_ENABLE | SCU_RAM_ATV_AGC_MODE_VAGC_VEL_AGC_SLOW), 0);
12581 if (rc != 0) {
12582 pr_err("error %d\n", rc);
12583 goto rw_error;
12585 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, 0x1000, 0);
12586 if (rc != 0) {
12587 pr_err("error %d\n", rc);
12588 goto rw_error;
12590 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_VID_GAIN_LO__A, 0x0000, 0);
12591 if (rc != 0) {
12592 pr_err("error %d\n", rc);
12593 goto rw_error;
12595 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_AMS_MAX_REF__A, SCU_RAM_ATV_AMS_MAX_REF_AMS_MAX_REF_LLP, 0);
12596 if (rc != 0) {
12597 pr_err("error %d\n", rc);
12598 goto rw_error;
12600 ext_attr->phase_correction_bypass = false;
12601 ext_attr->atv_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_USER;
12602 ext_attr->atv_if_agc_cfg.output_level = ext_attr->atv_rf_agc_cfg.top;
12603 ext_attr->enable_cvbs_output = true;
12604 break;
12605 default:
12606 return -EIO;
12609 /* Common initializations FM & NTSC & B/G & D/K & I & L & LP */
12610 if (!ext_attr->has_lna) {
12611 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_AMUX__A, 0x01, 0);
12612 if (rc != 0) {
12613 pr_err("error %d\n", rc);
12614 goto rw_error;
12618 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_STANDARD__A, 0x002, 0);
12619 if (rc != 0) {
12620 pr_err("error %d\n", rc);
12621 goto rw_error;
12623 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_CLP_LEN__A, IQM_AF_CLP_LEN_ATV, 0);
12624 if (rc != 0) {
12625 pr_err("error %d\n", rc);
12626 goto rw_error;
12628 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_CLP_TH__A, IQM_AF_CLP_TH_ATV, 0);
12629 if (rc != 0) {
12630 pr_err("error %d\n", rc);
12631 goto rw_error;
12633 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_SNS_LEN__A, IQM_AF_SNS_LEN_ATV, 0);
12634 if (rc != 0) {
12635 pr_err("error %d\n", rc);
12636 goto rw_error;
12638 rc = ctrl_set_cfg_pre_saw(demod, &(ext_attr->atv_pre_saw_cfg));
12639 if (rc != 0) {
12640 pr_err("error %d\n", rc);
12641 goto rw_error;
12643 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_AGC_IF__A, 10248, 0);
12644 if (rc != 0) {
12645 pr_err("error %d\n", rc);
12646 goto rw_error;
12649 ext_attr->iqm_rc_rate_ofs = 0x00200000L;
12650 rc = DRXJ_DAP.write_reg32func(dev_addr, IQM_RC_RATE_OFS_LO__A, ext_attr->iqm_rc_rate_ofs, 0);
12651 if (rc != 0) {
12652 pr_err("error %d\n", rc);
12653 goto rw_error;
12655 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RC_ADJ_SEL__A, IQM_RC_ADJ_SEL_B_OFF, 0);
12656 if (rc != 0) {
12657 pr_err("error %d\n", rc);
12658 goto rw_error;
12660 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RC_STRETCH__A, IQM_RC_STRETCH_ATV, 0);
12661 if (rc != 0) {
12662 pr_err("error %d\n", rc);
12663 goto rw_error;
12666 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_ACTIVE__A, IQM_RT_ACTIVE_ACTIVE_RT_ATV_FCR_ON | IQM_RT_ACTIVE_ACTIVE_CR_ATV_CR_ON, 0);
12667 if (rc != 0) {
12668 pr_err("error %d\n", rc);
12669 goto rw_error;
12672 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_OUT_ENA__A, IQM_CF_OUT_ENA_ATV__M, 0);
12673 if (rc != 0) {
12674 pr_err("error %d\n", rc);
12675 goto rw_error;
12677 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_CF_SYMMETRIC__A, IQM_CF_SYMMETRIC_IM__M, 0);
12678 if (rc != 0) {
12679 pr_err("error %d\n", rc);
12680 goto rw_error;
12682 /* default: SIF in standby */
12683 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_SYNC_SLICE__A, ATV_TOP_SYNC_SLICE_MN, 0);
12684 if (rc != 0) {
12685 pr_err("error %d\n", rc);
12686 goto rw_error;
12688 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_MOD_ACCU__A, ATV_TOP_MOD_ACCU__PRE, 0);
12689 if (rc != 0) {
12690 pr_err("error %d\n", rc);
12691 goto rw_error;
12694 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_SIF_GAIN__A, 0x080, 0);
12695 if (rc != 0) {
12696 pr_err("error %d\n", rc);
12697 goto rw_error;
12699 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_FAGC_TH_RED__A, 10, 0);
12700 if (rc != 0) {
12701 pr_err("error %d\n", rc);
12702 goto rw_error;
12704 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_AAGC_CNT__A, 7, 0);
12705 if (rc != 0) {
12706 pr_err("error %d\n", rc);
12707 goto rw_error;
12709 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_NAGC_KI_MIN__A, 0x0225, 0);
12710 if (rc != 0) {
12711 pr_err("error %d\n", rc);
12712 goto rw_error;
12714 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_NAGC_KI_MAX__A, 0x0547, 0);
12715 if (rc != 0) {
12716 pr_err("error %d\n", rc);
12717 goto rw_error;
12719 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_KI_CHANGE_TH__A, 20, 0);
12720 if (rc != 0) {
12721 pr_err("error %d\n", rc);
12722 goto rw_error;
12724 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_LOCK__A, 0, 0);
12725 if (rc != 0) {
12726 pr_err("error %d\n", rc);
12727 goto rw_error;
12730 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_RT_DELAY__A, IQM_RT_DELAY__PRE, 0);
12731 if (rc != 0) {
12732 pr_err("error %d\n", rc);
12733 goto rw_error;
12735 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_BPC_KI_MIN__A, 531, 0);
12736 if (rc != 0) {
12737 pr_err("error %d\n", rc);
12738 goto rw_error;
12740 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_PAGC_KI_MIN__A, 1061, 0);
12741 if (rc != 0) {
12742 pr_err("error %d\n", rc);
12743 goto rw_error;
12745 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_BP_REF_MIN__A, 100, 0);
12746 if (rc != 0) {
12747 pr_err("error %d\n", rc);
12748 goto rw_error;
12750 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_BP_REF_MAX__A, 260, 0);
12751 if (rc != 0) {
12752 pr_err("error %d\n", rc);
12753 goto rw_error;
12755 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_BP_LVL__A, 0, 0);
12756 if (rc != 0) {
12757 pr_err("error %d\n", rc);
12758 goto rw_error;
12760 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_AMS_MAX__A, 0, 0);
12761 if (rc != 0) {
12762 pr_err("error %d\n", rc);
12763 goto rw_error;
12765 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_AMS_MIN__A, 2047, 0);
12766 if (rc != 0) {
12767 pr_err("error %d\n", rc);
12768 goto rw_error;
12770 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_GPIO__A, 0, 0);
12771 if (rc != 0) {
12772 pr_err("error %d\n", rc);
12773 goto rw_error;
12776 /* Override reset values with current shadow settings */
12777 rc = atv_update_config(demod, true);
12778 if (rc != 0) {
12779 pr_err("error %d\n", rc);
12780 goto rw_error;
12783 /* Configure/restore AGC settings */
12784 rc = init_agc(demod);
12785 if (rc != 0) {
12786 pr_err("error %d\n", rc);
12787 goto rw_error;
12789 rc = set_agc_if(demod, &(ext_attr->atv_if_agc_cfg), false);
12790 if (rc != 0) {
12791 pr_err("error %d\n", rc);
12792 goto rw_error;
12794 rc = set_agc_rf(demod, &(ext_attr->atv_rf_agc_cfg), false);
12795 if (rc != 0) {
12796 pr_err("error %d\n", rc);
12797 goto rw_error;
12799 rc = ctrl_set_cfg_pre_saw(demod, &(ext_attr->atv_pre_saw_cfg));
12800 if (rc != 0) {
12801 pr_err("error %d\n", rc);
12802 goto rw_error;
12805 /* Set SCU ATV substandard,assuming this doesn't require running ATV block */
12806 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_ATV |
12807 SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV;
12808 cmd_scu.parameter_len = 1;
12809 cmd_scu.result_len = 1;
12810 cmd_scu.parameter = &cmd_param;
12811 cmd_scu.result = &cmd_result;
12812 rc = scu_command(dev_addr, &cmd_scu);
12813 if (rc != 0) {
12814 pr_err("error %d\n", rc);
12815 goto rw_error;
12818 /* turn the analog work around on/off (must after set_env b/c it is set in mc) */
12819 if (ext_attr->mfx == 0x03) {
12820 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_ENABLE_IIR_WA__A, 0, 0);
12821 if (rc != 0) {
12822 pr_err("error %d\n", rc);
12823 goto rw_error;
12825 } else {
12826 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_ENABLE_IIR_WA__A, 1, 0);
12827 if (rc != 0) {
12828 pr_err("error %d\n", rc);
12829 goto rw_error;
12831 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ATV_IIR_CRIT__A, 225, 0);
12832 if (rc != 0) {
12833 pr_err("error %d\n", rc);
12834 goto rw_error;
12838 return 0;
12839 rw_error:
12840 return -EIO;
12843 /* -------------------------------------------------------------------------- */
12846 * \fn int set_atv_channel ()
12847 * \brief Set ATV channel.
12848 * \param demod: instance of demod.
12849 * \return int.
12851 * Not much needs to be done here, only start the SCU for NTSC/FM.
12852 * Mirrored channels are not expected in the RF domain, so IQM FS setting
12853 * doesn't need to be remembered.
12854 * The channel->mirror parameter is therefor ignored.
12857 static int
12858 set_atv_channel(struct drx_demod_instance *demod,
12859 s32 tuner_freq_offset,
12860 struct drx_channel *channel, enum drx_standard standard)
12862 struct drxjscu_cmd cmd_scu = { /* command */ 0,
12863 /* parameter_len */ 0,
12864 /* result_len */ 0,
12865 /* parameter */ NULL,
12866 /* result */ NULL
12868 u16 cmd_result = 0;
12869 struct drxj_data *ext_attr = NULL;
12870 struct i2c_device_addr *dev_addr = NULL;
12871 int rc;
12873 dev_addr = demod->my_i2c_dev_addr;
12874 ext_attr = (struct drxj_data *) demod->my_ext_attr;
12877 Program frequency shifter
12878 No need to account for mirroring on RF
12880 if (channel->mirror == DRX_MIRROR_AUTO)
12881 ext_attr->mirror = DRX_MIRROR_NO;
12882 else
12883 ext_attr->mirror = channel->mirror;
12885 rc = set_frequency(demod, channel, tuner_freq_offset);
12886 if (rc != 0) {
12887 pr_err("error %d\n", rc);
12888 goto rw_error;
12890 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_CR_FREQ__A, ATV_TOP_CR_FREQ__PRE, 0);
12891 if (rc != 0) {
12892 pr_err("error %d\n", rc);
12893 goto rw_error;
12896 /* Start ATV SCU */
12897 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_ATV |
12898 SCU_RAM_COMMAND_CMD_DEMOD_START;
12899 cmd_scu.parameter_len = 0;
12900 cmd_scu.result_len = 1;
12901 cmd_scu.parameter = NULL;
12902 cmd_scu.result = &cmd_result;
12903 rc = scu_command(dev_addr, &cmd_scu);
12904 if (rc != 0) {
12905 pr_err("error %d\n", rc);
12906 goto rw_error;
12909 /* if ( (ext_attr->standard == DRX_STANDARD_FM) && (ext_attr->flagSetAUDdone == true) )
12911 ext_attr->detectedRDS = (bool)false;
12914 return 0;
12915 rw_error:
12916 return -EIO;
12919 /* -------------------------------------------------------------------------- */
12922 * \fn int get_atv_channel ()
12923 * \brief Set ATV channel.
12924 * \param demod: instance of demod.
12925 * \param channel: pointer to channel data.
12926 * \param standard: NTSC or FM.
12927 * \return int.
12929 * Covers NTSC, PAL/SECAM - B/G, D/K, I, L, LP and FM.
12930 * Computes the frequency offset in te RF domain and adds it to
12931 * channel->frequency. Determines the value for channel->bandwidth.
12934 static int
12935 get_atv_channel(struct drx_demod_instance *demod,
12936 struct drx_channel *channel, enum drx_standard standard)
12938 s32 offset = 0;
12939 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
12940 int rc;
12942 /* Bandwidth */
12943 channel->bandwidth = ((struct drxj_data *) demod->my_ext_attr)->curr_bandwidth;
12945 switch (standard) {
12946 case DRX_STANDARD_NTSC:
12947 case DRX_STANDARD_PAL_SECAM_BG:
12948 case DRX_STANDARD_PAL_SECAM_DK:
12949 case DRX_STANDARD_PAL_SECAM_I:
12950 case DRX_STANDARD_PAL_SECAM_L:
12952 u16 measured_offset = 0;
12954 /* get measured frequency offset */
12955 rc = DRXJ_DAP.read_reg16func(dev_addr, ATV_TOP_CR_FREQ__A, &measured_offset, 0);
12956 if (rc != 0) {
12957 pr_err("error %d\n", rc);
12958 goto rw_error;
12960 /* Signed 8 bit register => sign extension needed */
12961 if ((measured_offset & 0x0080) != 0)
12962 measured_offset |= 0xFF80;
12963 offset +=
12964 (s32) (((s16) measured_offset) * 10);
12965 break;
12967 case DRX_STANDARD_PAL_SECAM_LP:
12969 u16 measured_offset = 0;
12971 /* get measured frequency offset */
12972 rc = DRXJ_DAP.read_reg16func(dev_addr, ATV_TOP_CR_FREQ__A, &measured_offset, 0);
12973 if (rc != 0) {
12974 pr_err("error %d\n", rc);
12975 goto rw_error;
12977 /* Signed 8 bit register => sign extension needed */
12978 if ((measured_offset & 0x0080) != 0)
12979 measured_offset |= 0xFF80;
12980 offset -=
12981 (s32) (((s16) measured_offset) * 10);
12983 break;
12984 case DRX_STANDARD_FM:
12985 /* TODO: compute offset using AUD_DSP_RD_FM_DC_LEVEL_A__A and
12986 AUD_DSP_RD_FM_DC_LEVEL_B__A. For now leave frequency as is.
12988 /* No bandwidth know for FM */
12989 channel->bandwidth = DRX_BANDWIDTH_UNKNOWN;
12990 break;
12991 default:
12992 return -EIO;
12995 channel->frequency -= offset;
12997 return 0;
12998 rw_error:
12999 return -EIO;
13002 /* -------------------------------------------------------------------------- */
13004 * \fn int get_atv_sig_strength()
13005 * \brief Retrieve signal strength for ATV & FM.
13006 * \param devmod Pointer to demodulator instance.
13007 * \param sig_quality Pointer to signal strength data; range 0, .. , 100.
13008 * \return int.
13009 * \retval 0 sig_strength contains valid data.
13010 * \retval -EIO Erroneous data, sig_strength equals 0.
13012 * Taking into account:
13013 * * digital gain
13014 * * IF gain (not implemented yet, waiting for IF gain control by ucode)
13015 * * RF gain
13017 * All weights (digital, if, rf) must add up to 100.
13019 * TODO: ? dynamically adapt weights in case RF and/or IF agc of drxj
13020 * is not used ?
13022 static int
13023 get_atv_sig_strength(struct drx_demod_instance *demod, u16 *sig_strength)
13025 struct i2c_device_addr *dev_addr = NULL;
13026 struct drxj_data *ext_attr = NULL;
13027 int rc;
13029 /* All weights must add up to 100 (%)
13030 TODO: change weights when IF ctrl is available */
13031 u32 digital_weight = 50; /* 0 .. 100 */
13032 u32 rf_weight = 50; /* 0 .. 100 */
13033 u32 if_weight = 0; /* 0 .. 100 */
13035 u16 digital_curr_gain = 0;
13036 u32 digital_max_gain = 0;
13037 u32 digital_min_gain = 0;
13038 u16 rf_curr_gain = 0;
13039 u32 rf_max_gain = 0x800; /* taken from ucode */
13040 u32 rf_min_gain = 0x7fff;
13041 u16 if_curr_gain = 0;
13042 u32 if_max_gain = 0x800; /* taken from ucode */
13043 u32 if_min_gain = 0x7fff;
13045 u32 digital_strength = 0; /* 0.. 100 */
13046 u32 rf_strength = 0; /* 0.. 100 */
13047 u32 if_strength = 0; /* 0.. 100 */
13049 dev_addr = demod->my_i2c_dev_addr;
13050 ext_attr = (struct drxj_data *) demod->my_ext_attr;
13052 *sig_strength = 0;
13054 switch (ext_attr->standard) {
13055 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
13056 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
13057 case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
13058 case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */
13059 case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
13060 case DRX_STANDARD_NTSC:
13061 rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_ATV_VID_GAIN_HI__A, &digital_curr_gain, 0);
13062 if (rc != 0) {
13063 pr_err("error %d\n", rc);
13064 goto rw_error;
13066 digital_max_gain = 22512; /* taken from ucode */
13067 digital_min_gain = 2400; /* taken from ucode */
13068 break;
13069 case DRX_STANDARD_FM:
13070 rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_ATV_SIF_GAIN__A, &digital_curr_gain, 0);
13071 if (rc != 0) {
13072 pr_err("error %d\n", rc);
13073 goto rw_error;
13075 digital_max_gain = 0x4ff; /* taken from ucode */
13076 digital_min_gain = 0; /* taken from ucode */
13077 break;
13078 default:
13079 return -EIO;
13080 break;
13082 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_AGC_RF__A, &rf_curr_gain, 0);
13083 if (rc != 0) {
13084 pr_err("error %d\n", rc);
13085 goto rw_error;
13087 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_AGC_IF__A, &if_curr_gain, 0);
13088 if (rc != 0) {
13089 pr_err("error %d\n", rc);
13090 goto rw_error;
13093 /* clipping */
13094 if (digital_curr_gain >= digital_max_gain)
13095 digital_curr_gain = (u16)digital_max_gain;
13096 if (digital_curr_gain <= digital_min_gain)
13097 digital_curr_gain = (u16)digital_min_gain;
13098 if (if_curr_gain <= if_max_gain)
13099 if_curr_gain = (u16)if_max_gain;
13100 if (if_curr_gain >= if_min_gain)
13101 if_curr_gain = (u16)if_min_gain;
13102 if (rf_curr_gain <= rf_max_gain)
13103 rf_curr_gain = (u16)rf_max_gain;
13104 if (rf_curr_gain >= rf_min_gain)
13105 rf_curr_gain = (u16)rf_min_gain;
13107 /* TODO: use SCU_RAM_ATV_RAGC_HR__A to shift max and min in case
13108 of clipping at ADC */
13110 /* Compute signal strength (in %) per "gain domain" */
13112 /* Digital gain */
13113 /* TODO: ADC clipping not handled */
13114 digital_strength = (100 * (digital_max_gain - (u32) digital_curr_gain)) /
13115 (digital_max_gain - digital_min_gain);
13117 /* TODO: IF gain not implemented yet in microcode, check after impl. */
13118 if_strength = (100 * ((u32) if_curr_gain - if_max_gain)) /
13119 (if_min_gain - if_max_gain);
13121 /* Rf gain */
13122 /* TODO: ADC clipping not handled */
13123 rf_strength = (100 * ((u32) rf_curr_gain - rf_max_gain)) /
13124 (rf_min_gain - rf_max_gain);
13126 /* Compute a weighted signal strength (in %) */
13127 *sig_strength = (u16) (digital_weight * digital_strength +
13128 rf_weight * rf_strength + if_weight * if_strength);
13129 *sig_strength /= 100;
13131 return 0;
13132 rw_error:
13133 return -EIO;
13136 /* -------------------------------------------------------------------------- */
13138 * \fn int atv_sig_quality()
13139 * \brief Retrieve signal quality indication for ATV.
13140 * \param devmod Pointer to demodulator instance.
13141 * \param sig_quality Pointer to signal quality structure.
13142 * \return int.
13143 * \retval 0 sig_quality contains valid data.
13144 * \retval -EIO Erroneous data, sig_quality indicator equals 0.
13148 static int
13149 atv_sig_quality(struct drx_demod_instance *demod, struct drx_sig_quality *sig_quality)
13151 struct i2c_device_addr *dev_addr = NULL;
13152 u16 quality_indicator = 0;
13153 int rc;
13155 dev_addr = demod->my_i2c_dev_addr;
13157 /* defined values for fields not used */
13158 sig_quality->MER = 0;
13159 sig_quality->pre_viterbi_ber = 0;
13160 sig_quality->post_viterbi_ber = 0;
13161 sig_quality->scale_factor_ber = 1;
13162 sig_quality->packet_error = 0;
13163 sig_quality->post_reed_solomon_ber = 0;
13166 Mapping:
13167 0x000..0x080: strong signal => 80% .. 100%
13168 0x080..0x700: weak signal => 30% .. 80%
13169 0x700..0x7ff: no signal => 0% .. 30%
13172 rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_ATV_CR_LOCK__A, &quality_indicator, 0);
13173 if (rc != 0) {
13174 pr_err("error %d\n", rc);
13175 goto rw_error;
13177 quality_indicator &= SCU_RAM_ATV_CR_LOCK_CR_LOCK__M;
13178 if (quality_indicator <= 0x80) {
13179 sig_quality->indicator =
13180 80 + ((20 * (0x80 - quality_indicator)) / 0x80);
13181 } else if (quality_indicator <= 0x700)
13182 sig_quality->indicator = 30 + ((50 * (0x700 - quality_indicator)) / (0x700 - 0x81));
13183 else
13184 sig_quality->indicator = (30 * (0x7FF - quality_indicator)) / (0x7FF - 0x701);
13186 return 0;
13187 rw_error:
13188 return -EIO;
13191 /*============================================================================*/
13192 /*== END ATV DATAPATH FUNCTIONS ==*/
13193 /*============================================================================*/
13195 /*===========================================================================*/
13196 /*===========================================================================*/
13197 /*== AUDIO DATAPATH FUNCTIONS ==*/
13198 /*===========================================================================*/
13199 /*===========================================================================*/
13202 * \brief Power up AUD.
13203 * \param demod instance of demodulator
13204 * \return int.
13207 static int power_up_aud(struct drx_demod_instance *demod, bool set_standard)
13209 enum drx_aud_standard aud_standard = DRX_AUD_STANDARD_AUTO;
13210 struct i2c_device_addr *dev_addr = NULL;
13211 int rc;
13213 dev_addr = demod->my_i2c_dev_addr;
13215 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_TOP_COMM_EXEC__A, AUD_TOP_COMM_EXEC_ACTIVE, 0);
13216 if (rc != 0) {
13217 pr_err("error %d\n", rc);
13218 goto rw_error;
13220 /* setup TR interface: R/W mode, fifosize=8 */
13221 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_TOP_TR_MDE__A, 8, 0);
13222 if (rc != 0) {
13223 pr_err("error %d\n", rc);
13224 goto rw_error;
13226 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_COMM_EXEC__A, AUD_COMM_EXEC_ACTIVE, 0);
13227 if (rc != 0) {
13228 pr_err("error %d\n", rc);
13229 goto rw_error;
13232 if (set_standard) {
13233 rc = aud_ctrl_set_standard(demod, &aud_standard);
13234 if (rc != 0) {
13235 pr_err("error %d\n", rc);
13236 goto rw_error;
13240 return 0;
13241 rw_error:
13242 return -EIO;
13244 #endif
13246 /*============================================================================*/
13249 * \brief Power up AUD.
13250 * \param demod instance of demodulator
13251 * \return int.
13254 static int power_down_aud(struct drx_demod_instance *demod)
13256 struct i2c_device_addr *dev_addr = NULL;
13257 struct drxj_data *ext_attr = NULL;
13258 int rc;
13260 dev_addr = (struct i2c_device_addr *)demod->my_i2c_dev_addr;
13261 ext_attr = (struct drxj_data *) demod->my_ext_attr;
13263 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_COMM_EXEC__A, AUD_COMM_EXEC_STOP, 0);
13264 if (rc != 0) {
13265 pr_err("error %d\n", rc);
13266 goto rw_error;
13269 ext_attr->aud_data.audio_is_active = false;
13271 return 0;
13272 rw_error:
13273 return -EIO;
13276 #if 0
13277 /*============================================================================*/
13279 * \brief Get Modus data from audio RAM
13280 * \param demod instance of demodulator
13281 * \param pointer to modus
13282 * \return int.
13285 static int aud_get_modus(struct drx_demod_instance *demod, u16 *modus)
13287 struct i2c_device_addr *dev_addr = NULL;
13288 struct drxj_data *ext_attr = NULL;
13289 int rc;
13291 u16 r_modus = 0;
13292 u16 r_modus_hi = 0;
13293 u16 r_modus_lo = 0;
13295 if (modus == NULL)
13296 return -EINVAL;
13298 dev_addr = (struct i2c_device_addr *)demod->my_i2c_dev_addr;
13299 ext_attr = (struct drxj_data *) demod->my_ext_attr;
13301 /* power up */
13302 if (ext_attr->aud_data.audio_is_active == false) {
13303 rc = power_up_aud(demod, true);
13304 if (rc != 0) {
13305 pr_err("error %d\n", rc);
13306 goto rw_error;
13308 ext_attr->aud_data.audio_is_active = true;
13311 /* Modus register is combined in to RAM location */
13312 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_RAM_MODUS_HI__A, &r_modus_hi, 0);
13313 if (rc != 0) {
13314 pr_err("error %d\n", rc);
13315 goto rw_error;
13317 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_RAM_MODUS_LO__A, &r_modus_lo, 0);
13318 if (rc != 0) {
13319 pr_err("error %d\n", rc);
13320 goto rw_error;
13323 r_modus = ((r_modus_hi << 12) & AUD_DEM_RAM_MODUS_HI__M)
13324 | (((r_modus_lo & AUD_DEM_RAM_MODUS_LO__M)));
13326 *modus = r_modus;
13328 return 0;
13329 rw_error:
13330 return -EIO;
13334 /*============================================================================*/
13336 * \brief Get audio RDS dat
13337 * \param demod instance of demodulator
13338 * \param pointer to struct drx_cfg_aud_rds * \return int.
13341 static int
13342 aud_ctrl_get_cfg_rds(struct drx_demod_instance *demod, struct drx_cfg_aud_rds *status)
13344 struct i2c_device_addr *addr = NULL;
13345 struct drxj_data *ext_attr = NULL;
13346 int rc;
13348 u16 r_rds_array_cnt_init = 0;
13349 u16 r_rds_array_cnt_check = 0;
13350 u16 r_rds_data = 0;
13351 u16 rds_data_cnt = 0;
13353 addr = (struct i2c_device_addr *)demod->my_i2c_dev_addr;
13354 ext_attr = (struct drxj_data *) demod->my_ext_attr;
13356 if (status == NULL)
13357 return -EINVAL;
13359 /* power up */
13360 if (ext_attr->aud_data.audio_is_active == false) {
13361 rc = power_up_aud(demod, true);
13362 if (rc != 0) {
13363 pr_err("error %d\n", rc);
13364 goto rw_error;
13366 ext_attr->aud_data.audio_is_active = true;
13369 status->valid = false;
13371 rc = DRXJ_DAP.read_reg16func(addr, AUD_DEM_RD_RDS_ARRAY_CNT__A, &r_rds_array_cnt_init, 0);
13372 if (rc != 0) {
13373 pr_err("error %d\n", rc);
13374 goto rw_error;
13377 if (r_rds_array_cnt_init ==
13378 AUD_DEM_RD_RDS_ARRAY_CNT_RDS_ARRAY_CT_RDS_DATA_NOT_VALID) {
13379 /* invalid data */
13380 return 0;
13383 if (ext_attr->aud_data.rds_data_counter == r_rds_array_cnt_init) {
13384 /* no new data */
13385 return 0;
13388 /* RDS is detected, as long as FM radio is selected assume
13389 RDS will be available */
13390 ext_attr->aud_data.rds_data_present = true;
13392 /* new data */
13393 /* read the data */
13394 for (rds_data_cnt = 0; rds_data_cnt < AUD_RDS_ARRAY_SIZE; rds_data_cnt++) {
13395 rc = DRXJ_DAP.read_reg16func(addr, AUD_DEM_RD_RDS_DATA__A, &r_rds_data, 0);
13396 if (rc != 0) {
13397 pr_err("error %d\n", rc);
13398 goto rw_error;
13400 status->data[rds_data_cnt] = r_rds_data;
13403 rc = DRXJ_DAP.read_reg16func(addr, AUD_DEM_RD_RDS_ARRAY_CNT__A, &r_rds_array_cnt_check, 0);
13404 if (rc != 0) {
13405 pr_err("error %d\n", rc);
13406 goto rw_error;
13409 if (r_rds_array_cnt_check == r_rds_array_cnt_init) {
13410 status->valid = true;
13411 ext_attr->aud_data.rds_data_counter = r_rds_array_cnt_check;
13414 return 0;
13415 rw_error:
13416 return -EIO;
13419 /*============================================================================*/
13421 * \brief Get the current audio carrier detection status
13422 * \param demod instance of demodulator
13423 * \param pointer to aud_ctrl_get_status
13424 * \return int.
13427 static int
13428 aud_ctrl_get_carrier_detect_status(struct drx_demod_instance *demod, struct drx_aud_status *status)
13430 struct drxj_data *ext_attr = NULL;
13431 struct i2c_device_addr *dev_addr = NULL;
13432 int rc;
13433 u16 r_data = 0;
13435 if (status == NULL)
13436 return -EINVAL;
13438 dev_addr = (struct i2c_device_addr *)demod->my_i2c_dev_addr;
13439 ext_attr = (struct drxj_data *) demod->my_ext_attr;
13441 /* power up */
13442 if (ext_attr->aud_data.audio_is_active == false) {
13443 rc = power_up_aud(demod, true);
13444 if (rc != 0) {
13445 pr_err("error %d\n", rc);
13446 goto rw_error;
13448 ext_attr->aud_data.audio_is_active = true;
13451 /* initialize the variables */
13452 status->carrier_a = false;
13453 status->carrier_b = false;
13454 status->nicam_status = DRX_AUD_NICAM_NOT_DETECTED;
13455 status->sap = false;
13456 status->stereo = false;
13458 /* read stereo sound mode indication */
13459 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_RD_STATUS__A, &r_data, 0);
13460 if (rc != 0) {
13461 pr_err("error %d\n", rc);
13462 goto rw_error;
13465 /* carrier a detected */
13466 if ((r_data & AUD_DEM_RD_STATUS_STAT_CARR_A__M) == AUD_DEM_RD_STATUS_STAT_CARR_A_DETECTED)
13467 status->carrier_a = true;
13469 /* carrier b detected */
13470 if ((r_data & AUD_DEM_RD_STATUS_STAT_CARR_B__M) == AUD_DEM_RD_STATUS_STAT_CARR_B_DETECTED)
13471 status->carrier_b = true;
13472 /* nicam detected */
13473 if ((r_data & AUD_DEM_RD_STATUS_STAT_NICAM__M) ==
13474 AUD_DEM_RD_STATUS_STAT_NICAM_NICAM_DETECTED) {
13475 if ((r_data & AUD_DEM_RD_STATUS_BAD_NICAM__M) == AUD_DEM_RD_STATUS_BAD_NICAM_OK)
13476 status->nicam_status = DRX_AUD_NICAM_DETECTED;
13477 else
13478 status->nicam_status = DRX_AUD_NICAM_BAD;
13481 /* audio mode bilingual or SAP detected */
13482 if ((r_data & AUD_DEM_RD_STATUS_STAT_BIL_OR_SAP__M) == AUD_DEM_RD_STATUS_STAT_BIL_OR_SAP_SAP)
13483 status->sap = true;
13485 /* stereo detected */
13486 if ((r_data & AUD_DEM_RD_STATUS_STAT_STEREO__M) == AUD_DEM_RD_STATUS_STAT_STEREO_STEREO)
13487 status->stereo = true;
13489 return 0;
13490 rw_error:
13491 return -EIO;
13494 /*============================================================================*/
13496 * \brief Get the current audio status parameters
13497 * \param demod instance of demodulator
13498 * \param pointer to aud_ctrl_get_status
13499 * \return int.
13502 static int
13503 aud_ctrl_get_status(struct drx_demod_instance *demod, struct drx_aud_status *status)
13505 struct drxj_data *ext_attr = NULL;
13506 struct i2c_device_addr *dev_addr = NULL;
13507 struct drx_cfg_aud_rds rds = { false, {0} };
13508 int rc;
13509 u16 r_data = 0;
13511 if (status == NULL)
13512 return -EINVAL;
13514 dev_addr = (struct i2c_device_addr *)demod->my_i2c_dev_addr;
13515 ext_attr = (struct drxj_data *) demod->my_ext_attr;
13517 /* carrier detection */
13518 rc = aud_ctrl_get_carrier_detect_status(demod, status);
13519 if (rc != 0) {
13520 pr_err("error %d\n", rc);
13521 goto rw_error;
13524 /* rds data */
13525 status->rds = false;
13526 rc = aud_ctrl_get_cfg_rds(demod, &rds);
13527 if (rc != 0) {
13528 pr_err("error %d\n", rc);
13529 goto rw_error;
13531 status->rds = ext_attr->aud_data.rds_data_present;
13533 /* fm_ident */
13534 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DSP_RD_FM_IDENT_VALUE__A, &r_data, 0);
13535 if (rc != 0) {
13536 pr_err("error %d\n", rc);
13537 goto rw_error;
13539 r_data >>= AUD_DSP_RD_FM_IDENT_VALUE_FM_IDENT__B;
13540 status->fm_ident = (s8) r_data;
13542 return 0;
13543 rw_error:
13544 return -EIO;
13547 /*============================================================================*/
13549 * \brief Get the current volume settings
13550 * \param demod instance of demodulator
13551 * \param pointer to struct drx_cfg_aud_volume * \return int.
13554 static int
13555 aud_ctrl_get_cfg_volume(struct drx_demod_instance *demod, struct drx_cfg_aud_volume *volume)
13557 struct i2c_device_addr *dev_addr = NULL;
13558 struct drxj_data *ext_attr = NULL;
13559 int rc;
13561 u16 r_volume = 0;
13562 u16 r_avc = 0;
13563 u16 r_strength_left = 0;
13564 u16 r_strength_right = 0;
13566 if (volume == NULL)
13567 return -EINVAL;
13569 dev_addr = (struct i2c_device_addr *)demod->my_i2c_dev_addr;
13570 ext_attr = (struct drxj_data *) demod->my_ext_attr;
13572 /* power up */
13573 if (ext_attr->aud_data.audio_is_active == false) {
13574 rc = power_up_aud(demod, true);
13575 if (rc != 0) {
13576 pr_err("error %d\n", rc);
13577 goto rw_error;
13579 ext_attr->aud_data.audio_is_active = true;
13582 /* volume */
13583 volume->mute = ext_attr->aud_data.volume.mute;
13584 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DSP_WR_VOLUME__A, &r_volume, 0);
13585 if (rc != 0) {
13586 pr_err("error %d\n", rc);
13587 goto rw_error;
13589 if (r_volume == 0) {
13590 volume->mute = true;
13591 volume->volume = ext_attr->aud_data.volume.volume;
13592 } else {
13593 volume->mute = false;
13594 volume->volume = ((r_volume & AUD_DSP_WR_VOLUME_VOL_MAIN__M) >>
13595 AUD_DSP_WR_VOLUME_VOL_MAIN__B) -
13596 AUD_VOLUME_ZERO_DB;
13597 if (volume->volume < AUD_VOLUME_DB_MIN)
13598 volume->volume = AUD_VOLUME_DB_MIN;
13599 if (volume->volume > AUD_VOLUME_DB_MAX)
13600 volume->volume = AUD_VOLUME_DB_MAX;
13603 /* automatic volume control */
13604 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DSP_WR_AVC__A, &r_avc, 0);
13605 if (rc != 0) {
13606 pr_err("error %d\n", rc);
13607 goto rw_error;
13610 if ((r_avc & AUD_DSP_WR_AVC_AVC_ON__M) == AUD_DSP_WR_AVC_AVC_ON_OFF) {
13611 volume->avc_mode = DRX_AUD_AVC_OFF;
13612 } else {
13613 switch (r_avc & AUD_DSP_WR_AVC_AVC_DECAY__M) {
13614 case AUD_DSP_WR_AVC_AVC_DECAY_20_MSEC:
13615 volume->avc_mode = DRX_AUD_AVC_DECAYTIME_20MS;
13616 break;
13617 case AUD_DSP_WR_AVC_AVC_DECAY_8_SEC:
13618 volume->avc_mode = DRX_AUD_AVC_DECAYTIME_8S;
13619 break;
13620 case AUD_DSP_WR_AVC_AVC_DECAY_4_SEC:
13621 volume->avc_mode = DRX_AUD_AVC_DECAYTIME_4S;
13622 break;
13623 case AUD_DSP_WR_AVC_AVC_DECAY_2_SEC:
13624 volume->avc_mode = DRX_AUD_AVC_DECAYTIME_2S;
13625 break;
13626 default:
13627 return -EIO;
13628 break;
13632 /* max attenuation */
13633 switch (r_avc & AUD_DSP_WR_AVC_AVC_MAX_ATT__M) {
13634 case AUD_DSP_WR_AVC_AVC_MAX_ATT_12DB:
13635 volume->avc_max_atten = DRX_AUD_AVC_MAX_ATTEN_12DB;
13636 break;
13637 case AUD_DSP_WR_AVC_AVC_MAX_ATT_18DB:
13638 volume->avc_max_atten = DRX_AUD_AVC_MAX_ATTEN_18DB;
13639 break;
13640 case AUD_DSP_WR_AVC_AVC_MAX_ATT_24DB:
13641 volume->avc_max_atten = DRX_AUD_AVC_MAX_ATTEN_24DB;
13642 break;
13643 default:
13644 return -EIO;
13645 break;
13648 /* max gain */
13649 switch (r_avc & AUD_DSP_WR_AVC_AVC_MAX_GAIN__M) {
13650 case AUD_DSP_WR_AVC_AVC_MAX_GAIN_0DB:
13651 volume->avc_max_gain = DRX_AUD_AVC_MAX_GAIN_0DB;
13652 break;
13653 case AUD_DSP_WR_AVC_AVC_MAX_GAIN_6DB:
13654 volume->avc_max_gain = DRX_AUD_AVC_MAX_GAIN_6DB;
13655 break;
13656 case AUD_DSP_WR_AVC_AVC_MAX_GAIN_12DB:
13657 volume->avc_max_gain = DRX_AUD_AVC_MAX_GAIN_12DB;
13658 break;
13659 default:
13660 return -EIO;
13661 break;
13664 /* reference level */
13665 volume->avc_ref_level = (u16) ((r_avc & AUD_DSP_WR_AVC_AVC_REF_LEV__M) >>
13666 AUD_DSP_WR_AVC_AVC_REF_LEV__B);
13668 /* read qpeak registers and calculate strength of left and right carrier */
13669 /* quasi peaks formula: QP(dB) = 20 * log( AUD_DSP_RD_QPEAKx / Q(0dB) */
13670 /* Q(0dB) represents QP value of 0dB (hex value 0x4000) */
13671 /* left carrier */
13673 /* QP vaues */
13674 /* left carrier */
13675 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DSP_RD_QPEAK_L__A, &r_strength_left, 0);
13676 if (rc != 0) {
13677 pr_err("error %d\n", rc);
13678 goto rw_error;
13680 volume->strength_left = (((s16) log1_times100(r_strength_left)) -
13681 AUD_CARRIER_STRENGTH_QP_0DB_LOG10T100) / 5;
13683 /* right carrier */
13684 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DSP_RD_QPEAK_R__A, &r_strength_right, 0);
13685 if (rc != 0) {
13686 pr_err("error %d\n", rc);
13687 goto rw_error;
13689 volume->strength_right = (((s16) log1_times100(r_strength_right)) -
13690 AUD_CARRIER_STRENGTH_QP_0DB_LOG10T100) / 5;
13692 return 0;
13693 rw_error:
13694 return -EIO;
13697 /*============================================================================*/
13699 * \brief Set the current volume settings
13700 * \param demod instance of demodulator
13701 * \param pointer to struct drx_cfg_aud_volume * \return int.
13704 static int
13705 aud_ctrl_set_cfg_volume(struct drx_demod_instance *demod, struct drx_cfg_aud_volume *volume)
13707 struct i2c_device_addr *dev_addr = NULL;
13708 struct drxj_data *ext_attr = NULL;
13709 int rc;
13711 u16 w_volume = 0;
13712 u16 w_avc = 0;
13714 if (volume == NULL)
13715 return -EINVAL;
13717 dev_addr = (struct i2c_device_addr *)demod->my_i2c_dev_addr;
13718 ext_attr = (struct drxj_data *) demod->my_ext_attr;
13720 /* power up */
13721 if (ext_attr->aud_data.audio_is_active == false) {
13722 rc = power_up_aud(demod, true);
13723 if (rc != 0) {
13724 pr_err("error %d\n", rc);
13725 goto rw_error;
13727 ext_attr->aud_data.audio_is_active = true;
13730 /* volume */
13731 /* volume range from -60 to 12 (expressed in dB) */
13732 if ((volume->volume < AUD_VOLUME_DB_MIN) ||
13733 (volume->volume > AUD_VOLUME_DB_MAX))
13734 return -EINVAL;
13736 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DSP_WR_VOLUME__A, &w_volume, 0);
13737 if (rc != 0) {
13738 pr_err("error %d\n", rc);
13739 goto rw_error;
13742 /* clear the volume mask */
13743 w_volume &= (u16) ~AUD_DSP_WR_VOLUME_VOL_MAIN__M;
13744 if (volume->mute == true)
13745 w_volume |= (u16)(0);
13746 else
13747 w_volume |= (u16)((volume->volume + AUD_VOLUME_ZERO_DB) << AUD_DSP_WR_VOLUME_VOL_MAIN__B);
13749 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DSP_WR_VOLUME__A, w_volume, 0);
13750 if (rc != 0) {
13751 pr_err("error %d\n", rc);
13752 goto rw_error;
13755 /* automatic volume control */
13756 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DSP_WR_AVC__A, &w_avc, 0);
13757 if (rc != 0) {
13758 pr_err("error %d\n", rc);
13759 goto rw_error;
13762 /* clear masks that require writing */
13763 w_avc &= (u16) ~AUD_DSP_WR_AVC_AVC_ON__M;
13764 w_avc &= (u16) ~AUD_DSP_WR_AVC_AVC_DECAY__M;
13766 if (volume->avc_mode == DRX_AUD_AVC_OFF) {
13767 w_avc |= (AUD_DSP_WR_AVC_AVC_ON_OFF);
13768 } else {
13770 w_avc |= (AUD_DSP_WR_AVC_AVC_ON_ON);
13772 /* avc decay */
13773 switch (volume->avc_mode) {
13774 case DRX_AUD_AVC_DECAYTIME_20MS:
13775 w_avc |= AUD_DSP_WR_AVC_AVC_DECAY_20_MSEC;
13776 break;
13777 case DRX_AUD_AVC_DECAYTIME_8S:
13778 w_avc |= AUD_DSP_WR_AVC_AVC_DECAY_8_SEC;
13779 break;
13780 case DRX_AUD_AVC_DECAYTIME_4S:
13781 w_avc |= AUD_DSP_WR_AVC_AVC_DECAY_4_SEC;
13782 break;
13783 case DRX_AUD_AVC_DECAYTIME_2S:
13784 w_avc |= AUD_DSP_WR_AVC_AVC_DECAY_2_SEC;
13785 break;
13786 default:
13787 return -EINVAL;
13791 /* max attenuation */
13792 w_avc &= (u16) ~AUD_DSP_WR_AVC_AVC_MAX_ATT__M;
13793 switch (volume->avc_max_atten) {
13794 case DRX_AUD_AVC_MAX_ATTEN_12DB:
13795 w_avc |= AUD_DSP_WR_AVC_AVC_MAX_ATT_12DB;
13796 break;
13797 case DRX_AUD_AVC_MAX_ATTEN_18DB:
13798 w_avc |= AUD_DSP_WR_AVC_AVC_MAX_ATT_18DB;
13799 break;
13800 case DRX_AUD_AVC_MAX_ATTEN_24DB:
13801 w_avc |= AUD_DSP_WR_AVC_AVC_MAX_ATT_24DB;
13802 break;
13803 default:
13804 return -EINVAL;
13807 /* max gain */
13808 w_avc &= (u16) ~AUD_DSP_WR_AVC_AVC_MAX_GAIN__M;
13809 switch (volume->avc_max_gain) {
13810 case DRX_AUD_AVC_MAX_GAIN_0DB:
13811 w_avc |= AUD_DSP_WR_AVC_AVC_MAX_GAIN_0DB;
13812 break;
13813 case DRX_AUD_AVC_MAX_GAIN_6DB:
13814 w_avc |= AUD_DSP_WR_AVC_AVC_MAX_GAIN_6DB;
13815 break;
13816 case DRX_AUD_AVC_MAX_GAIN_12DB:
13817 w_avc |= AUD_DSP_WR_AVC_AVC_MAX_GAIN_12DB;
13818 break;
13819 default:
13820 return -EINVAL;
13823 /* avc reference level */
13824 if (volume->avc_ref_level > AUD_MAX_AVC_REF_LEVEL)
13825 return -EINVAL;
13827 w_avc &= (u16) ~AUD_DSP_WR_AVC_AVC_REF_LEV__M;
13828 w_avc |= (u16) (volume->avc_ref_level << AUD_DSP_WR_AVC_AVC_REF_LEV__B);
13830 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DSP_WR_AVC__A, w_avc, 0);
13831 if (rc != 0) {
13832 pr_err("error %d\n", rc);
13833 goto rw_error;
13836 /* all done, store config in data structure */
13837 ext_attr->aud_data.volume = *volume;
13839 return 0;
13840 rw_error:
13841 return -EIO;
13844 /*============================================================================*/
13846 * \brief Get the I2S settings
13847 * \param demod instance of demodulator
13848 * \param pointer to struct drx_cfg_i2s_output * \return int.
13851 static int
13852 aud_ctrl_get_cfg_output_i2s(struct drx_demod_instance *demod, struct drx_cfg_i2s_output *output)
13854 struct i2c_device_addr *dev_addr = NULL;
13855 struct drxj_data *ext_attr = NULL;
13856 int rc;
13857 u16 w_i2s_config = 0;
13858 u16 r_i2s_freq = 0;
13860 if (output == NULL)
13861 return -EINVAL;
13863 dev_addr = (struct i2c_device_addr *)demod->my_i2c_dev_addr;
13864 ext_attr = (struct drxj_data *) demod->my_ext_attr;
13866 /* power up */
13867 if (ext_attr->aud_data.audio_is_active == false) {
13868 rc = power_up_aud(demod, true);
13869 if (rc != 0) {
13870 pr_err("error %d\n", rc);
13871 goto rw_error;
13873 ext_attr->aud_data.audio_is_active = true;
13876 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_RAM_I2S_CONFIG2__A, &w_i2s_config, 0);
13877 if (rc != 0) {
13878 pr_err("error %d\n", rc);
13879 goto rw_error;
13881 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DSP_WR_I2S_OUT_FS__A, &r_i2s_freq, 0);
13882 if (rc != 0) {
13883 pr_err("error %d\n", rc);
13884 goto rw_error;
13887 /* I2S mode */
13888 switch (w_i2s_config & AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST__M) {
13889 case AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST_MASTER:
13890 output->mode = DRX_I2S_MODE_MASTER;
13891 break;
13892 case AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST_SLAVE:
13893 output->mode = DRX_I2S_MODE_SLAVE;
13894 break;
13895 default:
13896 return -EIO;
13899 /* I2S format */
13900 switch (w_i2s_config & AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE__M) {
13901 case AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE_DELAY:
13902 output->format = DRX_I2S_FORMAT_WS_ADVANCED;
13903 break;
13904 case AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE_NO_DELAY:
13905 output->format = DRX_I2S_FORMAT_WS_WITH_DATA;
13906 break;
13907 default:
13908 return -EIO;
13911 /* I2S word length */
13912 switch (w_i2s_config & AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN__M) {
13913 case AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN_BIT_16:
13914 output->word_length = DRX_I2S_WORDLENGTH_16;
13915 break;
13916 case AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN_BIT_32:
13917 output->word_length = DRX_I2S_WORDLENGTH_32;
13918 break;
13919 default:
13920 return -EIO;
13923 /* I2S polarity */
13924 switch (w_i2s_config & AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL__M) {
13925 case AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL_LEFT_HIGH:
13926 output->polarity = DRX_I2S_POLARITY_LEFT;
13927 break;
13928 case AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL_LEFT_LOW:
13929 output->polarity = DRX_I2S_POLARITY_RIGHT;
13930 break;
13931 default:
13932 return -EIO;
13935 /* I2S output enabled */
13936 if ((w_i2s_config & AUD_DEM_WR_I2S_CONFIG2_I2S_ENABLE__M) == AUD_DEM_WR_I2S_CONFIG2_I2S_ENABLE_ENABLE)
13937 output->output_enable = true;
13938 else
13939 output->output_enable = false;
13941 if (r_i2s_freq > 0) {
13942 output->frequency = 6144UL * 48000 / r_i2s_freq;
13943 if (output->word_length == DRX_I2S_WORDLENGTH_16)
13944 output->frequency *= 2;
13945 } else {
13946 output->frequency = AUD_I2S_FREQUENCY_MAX;
13949 return 0;
13950 rw_error:
13951 return -EIO;
13954 /*============================================================================*/
13956 * \brief Set the I2S settings
13957 * \param demod instance of demodulator
13958 * \param pointer to struct drx_cfg_i2s_output * \return int.
13961 static int
13962 aud_ctrl_set_cfg_output_i2s(struct drx_demod_instance *demod, struct drx_cfg_i2s_output *output)
13964 struct i2c_device_addr *dev_addr = NULL;
13965 struct drxj_data *ext_attr = NULL;
13966 int rc;
13967 u16 w_i2s_config = 0;
13968 u16 w_i2s_pads_data_da = 0;
13969 u16 w_i2s_pads_data_cl = 0;
13970 u16 w_i2s_pads_data_ws = 0;
13971 u32 w_i2s_freq = 0;
13973 if (output == NULL)
13974 return -EINVAL;
13976 dev_addr = (struct i2c_device_addr *)demod->my_i2c_dev_addr;
13977 ext_attr = (struct drxj_data *) demod->my_ext_attr;
13979 /* power up */
13980 if (ext_attr->aud_data.audio_is_active == false) {
13981 rc = power_up_aud(demod, true);
13982 if (rc != 0) {
13983 pr_err("error %d\n", rc);
13984 goto rw_error;
13986 ext_attr->aud_data.audio_is_active = true;
13989 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_RAM_I2S_CONFIG2__A, &w_i2s_config, 0);
13990 if (rc != 0) {
13991 pr_err("error %d\n", rc);
13992 goto rw_error;
13995 /* I2S mode */
13996 w_i2s_config &= (u16) ~AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST__M;
13998 switch (output->mode) {
13999 case DRX_I2S_MODE_MASTER:
14000 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST_MASTER;
14001 break;
14002 case DRX_I2S_MODE_SLAVE:
14003 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_SLV_MST_SLAVE;
14004 break;
14005 default:
14006 return -EINVAL;
14009 /* I2S format */
14010 w_i2s_config &= (u16) ~AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE__M;
14012 switch (output->format) {
14013 case DRX_I2S_FORMAT_WS_ADVANCED:
14014 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE_DELAY;
14015 break;
14016 case DRX_I2S_FORMAT_WS_WITH_DATA:
14017 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_WS_MODE_NO_DELAY;
14018 break;
14019 default:
14020 return -EINVAL;
14023 /* I2S word length */
14024 w_i2s_config &= (u16) ~AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN__M;
14026 switch (output->word_length) {
14027 case DRX_I2S_WORDLENGTH_16:
14028 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN_BIT_16;
14029 break;
14030 case DRX_I2S_WORDLENGTH_32:
14031 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_WORD_LEN_BIT_32;
14032 break;
14033 default:
14034 return -EINVAL;
14037 /* I2S polarity */
14038 w_i2s_config &= (u16) ~AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL__M;
14039 switch (output->polarity) {
14040 case DRX_I2S_POLARITY_LEFT:
14041 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL_LEFT_HIGH;
14042 break;
14043 case DRX_I2S_POLARITY_RIGHT:
14044 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_WS_POL_LEFT_LOW;
14045 break;
14046 default:
14047 return -EINVAL;
14050 /* I2S output enabled */
14051 w_i2s_config &= (u16) ~AUD_DEM_WR_I2S_CONFIG2_I2S_ENABLE__M;
14052 if (output->output_enable == true)
14053 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_ENABLE_ENABLE;
14054 else
14055 w_i2s_config |= AUD_DEM_WR_I2S_CONFIG2_I2S_ENABLE_DISABLE;
14058 I2S frequency
14060 w_i2s_freq = 6144 * 48000 * nrbits / ( 32 * frequency )
14062 16bit: 6144 * 48000 / ( 2 * freq ) = ( 6144 * 48000 / freq ) / 2
14063 32bit: 6144 * 48000 / freq = ( 6144 * 48000 / freq )
14065 if ((output->frequency > AUD_I2S_FREQUENCY_MAX) ||
14066 output->frequency < AUD_I2S_FREQUENCY_MIN) {
14067 return -EINVAL;
14070 w_i2s_freq = (6144UL * 48000UL) + (output->frequency >> 1);
14071 w_i2s_freq /= output->frequency;
14073 if (output->word_length == DRX_I2S_WORDLENGTH_16)
14074 w_i2s_freq *= 2;
14076 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DEM_WR_I2S_CONFIG2__A, w_i2s_config, 0);
14077 if (rc != 0) {
14078 pr_err("error %d\n", rc);
14079 goto rw_error;
14081 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DSP_WR_I2S_OUT_FS__A, (u16)w_i2s_freq, 0);
14082 if (rc != 0) {
14083 pr_err("error %d\n", rc);
14084 goto rw_error;
14087 /* configure I2S output pads for master or slave mode */
14088 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
14089 if (rc != 0) {
14090 pr_err("error %d\n", rc);
14091 goto rw_error;
14094 if (output->mode == DRX_I2S_MODE_MASTER) {
14095 w_i2s_pads_data_da = SIO_PDR_I2S_DA_CFG_MODE__MASTER |
14096 SIO_PDR_I2S_DA_CFG_DRIVE__MASTER;
14097 w_i2s_pads_data_cl = SIO_PDR_I2S_CL_CFG_MODE__MASTER |
14098 SIO_PDR_I2S_CL_CFG_DRIVE__MASTER;
14099 w_i2s_pads_data_ws = SIO_PDR_I2S_WS_CFG_MODE__MASTER |
14100 SIO_PDR_I2S_WS_CFG_DRIVE__MASTER;
14101 } else {
14102 w_i2s_pads_data_da = SIO_PDR_I2S_DA_CFG_MODE__SLAVE |
14103 SIO_PDR_I2S_DA_CFG_DRIVE__SLAVE;
14104 w_i2s_pads_data_cl = SIO_PDR_I2S_CL_CFG_MODE__SLAVE |
14105 SIO_PDR_I2S_CL_CFG_DRIVE__SLAVE;
14106 w_i2s_pads_data_ws = SIO_PDR_I2S_WS_CFG_MODE__SLAVE |
14107 SIO_PDR_I2S_WS_CFG_DRIVE__SLAVE;
14110 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_I2S_DA_CFG__A, w_i2s_pads_data_da, 0);
14111 if (rc != 0) {
14112 pr_err("error %d\n", rc);
14113 goto rw_error;
14115 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_I2S_CL_CFG__A, w_i2s_pads_data_cl, 0);
14116 if (rc != 0) {
14117 pr_err("error %d\n", rc);
14118 goto rw_error;
14120 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_I2S_WS_CFG__A, w_i2s_pads_data_ws, 0);
14121 if (rc != 0) {
14122 pr_err("error %d\n", rc);
14123 goto rw_error;
14126 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY__PRE, 0);
14127 if (rc != 0) {
14128 pr_err("error %d\n", rc);
14129 goto rw_error;
14132 /* all done, store config in data structure */
14133 ext_attr->aud_data.i2sdata = *output;
14135 return 0;
14136 rw_error:
14137 return -EIO;
14140 /*============================================================================*/
14142 * \brief Get the Automatic Standard Select (ASS)
14143 * and Automatic Sound Change (ASC)
14144 * \param demod instance of demodulator
14145 * \param pointer to pDRXAudAutoSound_t
14146 * \return int.
14149 static int
14150 aud_ctrl_get_cfg_auto_sound(struct drx_demod_instance *demod,
14151 enum drx_cfg_aud_auto_sound *auto_sound)
14153 struct drxj_data *ext_attr = NULL;
14154 int rc;
14155 u16 r_modus = 0;
14157 if (auto_sound == NULL)
14158 return -EINVAL;
14160 ext_attr = (struct drxj_data *) demod->my_ext_attr;
14162 /* power up */
14163 if (ext_attr->aud_data.audio_is_active == false) {
14164 rc = power_up_aud(demod, true);
14165 if (rc != 0) {
14166 pr_err("error %d\n", rc);
14167 goto rw_error;
14169 ext_attr->aud_data.audio_is_active = true;
14172 rc = aud_get_modus(demod, &r_modus);
14173 if (rc != 0) {
14174 pr_err("error %d\n", rc);
14175 goto rw_error;
14178 switch (r_modus & (AUD_DEM_WR_MODUS_MOD_ASS__M |
14179 AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG__M)) {
14180 case AUD_DEM_WR_MODUS_MOD_ASS_OFF | AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_DISABLED:
14181 case AUD_DEM_WR_MODUS_MOD_ASS_OFF | AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_ENABLED:
14182 *auto_sound =
14183 DRX_AUD_AUTO_SOUND_OFF;
14184 break;
14185 case AUD_DEM_WR_MODUS_MOD_ASS_ON | AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_ENABLED:
14186 *auto_sound =
14187 DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_ON;
14188 break;
14189 case AUD_DEM_WR_MODUS_MOD_ASS_ON | AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_DISABLED:
14190 *auto_sound =
14191 DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_OFF;
14192 break;
14193 default:
14194 return -EIO;
14197 return 0;
14198 rw_error:
14199 return -EIO;
14202 /*============================================================================*/
14204 * \brief Set the Automatic Standard Select (ASS)
14205 * and Automatic Sound Change (ASC)
14206 * \param demod instance of demodulator
14207 * \param pointer to pDRXAudAutoSound_t
14208 * \return int.
14211 static int
14212 aud_ctr_setl_cfg_auto_sound(struct drx_demod_instance *demod,
14213 enum drx_cfg_aud_auto_sound *auto_sound)
14215 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)NULL;
14216 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
14217 int rc;
14218 u16 r_modus = 0;
14219 u16 w_modus = 0;
14221 if (auto_sound == NULL)
14222 return -EINVAL;
14224 dev_addr = demod->my_i2c_dev_addr;
14225 ext_attr = (struct drxj_data *) demod->my_ext_attr;
14227 /* power up */
14228 if (ext_attr->aud_data.audio_is_active == false) {
14229 rc = power_up_aud(demod, true);
14230 if (rc != 0) {
14231 pr_err("error %d\n", rc);
14232 goto rw_error;
14234 ext_attr->aud_data.audio_is_active = true;
14237 rc = aud_get_modus(demod, &r_modus);
14238 if (rc != 0) {
14239 pr_err("error %d\n", rc);
14240 goto rw_error;
14243 w_modus = r_modus;
14244 /* clear ASS & ASC bits */
14245 w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_ASS__M;
14246 w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG__M;
14248 switch (*auto_sound) {
14249 case DRX_AUD_AUTO_SOUND_OFF:
14250 w_modus |= AUD_DEM_WR_MODUS_MOD_ASS_OFF;
14251 w_modus |= AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_DISABLED;
14252 break;
14253 case DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_ON:
14254 w_modus |= AUD_DEM_WR_MODUS_MOD_ASS_ON;
14255 w_modus |= AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_ENABLED;
14256 break;
14257 case DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_OFF:
14258 w_modus |= AUD_DEM_WR_MODUS_MOD_ASS_ON;
14259 w_modus |= AUD_DEM_WR_MODUS_MOD_DIS_STD_CHG_DISABLED;
14260 break;
14261 default:
14262 return -EINVAL;
14265 if (w_modus != r_modus) {
14266 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DEM_WR_MODUS__A, w_modus, 0);
14267 if (rc != 0) {
14268 pr_err("error %d\n", rc);
14269 goto rw_error;
14272 /* copy to data structure */
14273 ext_attr->aud_data.auto_sound = *auto_sound;
14275 return 0;
14276 rw_error:
14277 return -EIO;
14280 /*============================================================================*/
14282 * \brief Get the Automatic Standard Select thresholds
14283 * \param demod instance of demodulator
14284 * \param pointer to pDRXAudASSThres_t
14285 * \return int.
14288 static int
14289 aud_ctrl_get_cfg_ass_thres(struct drx_demod_instance *demod, struct drx_cfg_aud_ass_thres *thres)
14291 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)NULL;
14292 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
14293 int rc;
14294 u16 thres_a2 = 0;
14295 u16 thres_btsc = 0;
14296 u16 thres_nicam = 0;
14298 if (thres == NULL)
14299 return -EINVAL;
14301 dev_addr = demod->my_i2c_dev_addr;
14302 ext_attr = (struct drxj_data *) demod->my_ext_attr;
14304 /* power up */
14305 if (ext_attr->aud_data.audio_is_active == false) {
14306 rc = power_up_aud(demod, true);
14307 if (rc != 0) {
14308 pr_err("error %d\n", rc);
14309 goto rw_error;
14311 ext_attr->aud_data.audio_is_active = true;
14314 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_RAM_A2_THRSHLD__A, &thres_a2, 0);
14315 if (rc != 0) {
14316 pr_err("error %d\n", rc);
14317 goto rw_error;
14319 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_RAM_BTSC_THRSHLD__A, &thres_btsc, 0);
14320 if (rc != 0) {
14321 pr_err("error %d\n", rc);
14322 goto rw_error;
14324 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_RAM_NICAM_THRSHLD__A, &thres_nicam, 0);
14325 if (rc != 0) {
14326 pr_err("error %d\n", rc);
14327 goto rw_error;
14330 thres->a2 = thres_a2;
14331 thres->btsc = thres_btsc;
14332 thres->nicam = thres_nicam;
14334 return 0;
14335 rw_error:
14336 return -EIO;
14339 /*============================================================================*/
14341 * \brief Get the Automatic Standard Select thresholds
14342 * \param demod instance of demodulator
14343 * \param pointer to pDRXAudASSThres_t
14344 * \return int.
14347 static int
14348 aud_ctrl_set_cfg_ass_thres(struct drx_demod_instance *demod, struct drx_cfg_aud_ass_thres *thres)
14350 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)NULL;
14351 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
14352 int rc;
14353 if (thres == NULL)
14354 return -EINVAL;
14356 dev_addr = demod->my_i2c_dev_addr;
14357 ext_attr = (struct drxj_data *) demod->my_ext_attr;
14359 /* power up */
14360 if (ext_attr->aud_data.audio_is_active == false) {
14361 rc = power_up_aud(demod, true);
14362 if (rc != 0) {
14363 pr_err("error %d\n", rc);
14364 goto rw_error;
14366 ext_attr->aud_data.audio_is_active = true;
14369 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DEM_WR_A2_THRSHLD__A, thres->a2, 0);
14370 if (rc != 0) {
14371 pr_err("error %d\n", rc);
14372 goto rw_error;
14374 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DEM_WR_BTSC_THRSHLD__A, thres->btsc, 0);
14375 if (rc != 0) {
14376 pr_err("error %d\n", rc);
14377 goto rw_error;
14379 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DEM_WR_NICAM_THRSHLD__A, thres->nicam, 0);
14380 if (rc != 0) {
14381 pr_err("error %d\n", rc);
14382 goto rw_error;
14385 /* update DRXK data structure with hardware values */
14386 ext_attr->aud_data.ass_thresholds = *thres;
14388 return 0;
14389 rw_error:
14390 return -EIO;
14393 /*============================================================================*/
14395 * \brief Get Audio Carrier settings
14396 * \param demod instance of demodulator
14397 * \param pointer to struct drx_aud_carrier ** \return int.
14400 static int
14401 aud_ctrl_get_cfg_carrier(struct drx_demod_instance *demod, struct drx_cfg_aud_carriers *carriers)
14403 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)NULL;
14404 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
14405 int rc;
14406 u16 w_modus = 0;
14408 u16 dco_a_hi = 0;
14409 u16 dco_a_lo = 0;
14410 u16 dco_b_hi = 0;
14411 u16 dco_b_lo = 0;
14413 u32 valA = 0;
14414 u32 valB = 0;
14416 u16 dc_lvl_a = 0;
14417 u16 dc_lvl_b = 0;
14419 u16 cm_thes_a = 0;
14420 u16 cm_thes_b = 0;
14422 if (carriers == NULL)
14423 return -EINVAL;
14425 dev_addr = demod->my_i2c_dev_addr;
14426 ext_attr = (struct drxj_data *) demod->my_ext_attr;
14428 /* power up */
14429 if (ext_attr->aud_data.audio_is_active == false) {
14430 rc = power_up_aud(demod, true);
14431 if (rc != 0) {
14432 pr_err("error %d\n", rc);
14433 goto rw_error;
14435 ext_attr->aud_data.audio_is_active = true;
14438 rc = aud_get_modus(demod, &w_modus);
14439 if (rc != 0) {
14440 pr_err("error %d\n", rc);
14441 goto rw_error;
14444 /* Behaviour of primary audio channel */
14445 switch (w_modus & (AUD_DEM_WR_MODUS_MOD_CM_A__M)) {
14446 case AUD_DEM_WR_MODUS_MOD_CM_A_MUTE:
14447 carriers->a.opt = DRX_NO_CARRIER_MUTE;
14448 break;
14449 case AUD_DEM_WR_MODUS_MOD_CM_A_NOISE:
14450 carriers->a.opt = DRX_NO_CARRIER_NOISE;
14451 break;
14452 default:
14453 return -EIO;
14454 break;
14457 /* Behaviour of secondary audio channel */
14458 switch (w_modus & (AUD_DEM_WR_MODUS_MOD_CM_B__M)) {
14459 case AUD_DEM_WR_MODUS_MOD_CM_B_MUTE:
14460 carriers->b.opt = DRX_NO_CARRIER_MUTE;
14461 break;
14462 case AUD_DEM_WR_MODUS_MOD_CM_B_NOISE:
14463 carriers->b.opt = DRX_NO_CARRIER_NOISE;
14464 break;
14465 default:
14466 return -EIO;
14467 break;
14470 /* frequency adjustment for primary & secondary audio channel */
14471 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_RAM_DCO_A_HI__A, &dco_a_hi, 0);
14472 if (rc != 0) {
14473 pr_err("error %d\n", rc);
14474 goto rw_error;
14476 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_RAM_DCO_A_LO__A, &dco_a_lo, 0);
14477 if (rc != 0) {
14478 pr_err("error %d\n", rc);
14479 goto rw_error;
14481 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_RAM_DCO_B_HI__A, &dco_b_hi, 0);
14482 if (rc != 0) {
14483 pr_err("error %d\n", rc);
14484 goto rw_error;
14486 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_RAM_DCO_B_LO__A, &dco_b_lo, 0);
14487 if (rc != 0) {
14488 pr_err("error %d\n", rc);
14489 goto rw_error;
14492 valA = (((u32) dco_a_hi) << 12) | ((u32) dco_a_lo & 0xFFF);
14493 valB = (((u32) dco_b_hi) << 12) | ((u32) dco_b_lo & 0xFFF);
14495 /* Multiply by 20250 * 1>>24 ~= 2 / 1657 */
14496 carriers->a.dco = DRX_S24TODRXFREQ(valA) * 2L / 1657L;
14497 carriers->b.dco = DRX_S24TODRXFREQ(valB) * 2L / 1657L;
14499 /* DC level of the incoming FM signal on the primary
14500 & seconday sound channel */
14501 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DSP_RD_FM_DC_LEVEL_A__A, &dc_lvl_a, 0);
14502 if (rc != 0) {
14503 pr_err("error %d\n", rc);
14504 goto rw_error;
14506 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DSP_RD_FM_DC_LEVEL_B__A, &dc_lvl_b, 0);
14507 if (rc != 0) {
14508 pr_err("error %d\n", rc);
14509 goto rw_error;
14512 /* offset (kHz) = (dcLvl / 322) */
14513 carriers->a.shift = (DRX_U16TODRXFREQ(dc_lvl_a) / 322L);
14514 carriers->b.shift = (DRX_U16TODRXFREQ(dc_lvl_b) / 322L);
14516 /* Carrier detetcion threshold for primary & secondary channel */
14517 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_RAM_CM_A_THRSHLD__A, &cm_thes_a, 0);
14518 if (rc != 0) {
14519 pr_err("error %d\n", rc);
14520 goto rw_error;
14522 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_RAM_CM_B_THRSHLD__A, &cm_thes_b, 0);
14523 if (rc != 0) {
14524 pr_err("error %d\n", rc);
14525 goto rw_error;
14528 carriers->a.thres = cm_thes_a;
14529 carriers->b.thres = cm_thes_b;
14531 return 0;
14532 rw_error:
14533 return -EIO;
14536 /*============================================================================*/
14538 * \brief Set Audio Carrier settings
14539 * \param demod instance of demodulator
14540 * \param pointer to struct drx_aud_carrier ** \return int.
14543 static int
14544 aud_ctrl_set_cfg_carrier(struct drx_demod_instance *demod, struct drx_cfg_aud_carriers *carriers)
14546 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)NULL;
14547 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
14548 int rc;
14549 u16 w_modus = 0;
14550 u16 r_modus = 0;
14551 u16 dco_a_hi = 0;
14552 u16 dco_a_lo = 0;
14553 u16 dco_b_hi = 0;
14554 u16 dco_b_lo = 0;
14555 s32 valA = 0;
14556 s32 valB = 0;
14558 if (carriers == NULL)
14559 return -EINVAL;
14561 dev_addr = demod->my_i2c_dev_addr;
14562 ext_attr = (struct drxj_data *) demod->my_ext_attr;
14564 /* power up */
14565 if (ext_attr->aud_data.audio_is_active == false) {
14566 rc = power_up_aud(demod, true);
14567 if (rc != 0) {
14568 pr_err("error %d\n", rc);
14569 goto rw_error;
14571 ext_attr->aud_data.audio_is_active = true;
14574 rc = aud_get_modus(demod, &r_modus);
14575 if (rc != 0) {
14576 pr_err("error %d\n", rc);
14577 goto rw_error;
14580 w_modus = r_modus;
14581 w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_CM_A__M;
14582 /* Behaviour of primary audio channel */
14583 switch (carriers->a.opt) {
14584 case DRX_NO_CARRIER_MUTE:
14585 w_modus |= AUD_DEM_WR_MODUS_MOD_CM_A_MUTE;
14586 break;
14587 case DRX_NO_CARRIER_NOISE:
14588 w_modus |= AUD_DEM_WR_MODUS_MOD_CM_A_NOISE;
14589 break;
14590 default:
14591 return -EINVAL;
14592 break;
14595 /* Behaviour of secondary audio channel */
14596 w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_CM_B__M;
14597 switch (carriers->b.opt) {
14598 case DRX_NO_CARRIER_MUTE:
14599 w_modus |= AUD_DEM_WR_MODUS_MOD_CM_B_MUTE;
14600 break;
14601 case DRX_NO_CARRIER_NOISE:
14602 w_modus |= AUD_DEM_WR_MODUS_MOD_CM_B_NOISE;
14603 break;
14604 default:
14605 return -EINVAL;
14606 break;
14609 /* now update the modus register */
14610 if (w_modus != r_modus) {
14611 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DEM_WR_MODUS__A, w_modus, 0);
14612 if (rc != 0) {
14613 pr_err("error %d\n", rc);
14614 goto rw_error;
14618 /* frequency adjustment for primary & secondary audio channel */
14619 valA = (s32) ((carriers->a.dco) * 1657L / 2);
14620 valB = (s32) ((carriers->b.dco) * 1657L / 2);
14622 dco_a_hi = (u16) ((valA >> 12) & 0xFFF);
14623 dco_a_lo = (u16) (valA & 0xFFF);
14624 dco_b_hi = (u16) ((valB >> 12) & 0xFFF);
14625 dco_b_lo = (u16) (valB & 0xFFF);
14627 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DEM_WR_DCO_A_HI__A, dco_a_hi, 0);
14628 if (rc != 0) {
14629 pr_err("error %d\n", rc);
14630 goto rw_error;
14632 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DEM_WR_DCO_A_LO__A, dco_a_lo, 0);
14633 if (rc != 0) {
14634 pr_err("error %d\n", rc);
14635 goto rw_error;
14637 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DEM_WR_DCO_B_HI__A, dco_b_hi, 0);
14638 if (rc != 0) {
14639 pr_err("error %d\n", rc);
14640 goto rw_error;
14642 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DEM_WR_DCO_B_LO__A, dco_b_lo, 0);
14643 if (rc != 0) {
14644 pr_err("error %d\n", rc);
14645 goto rw_error;
14648 /* Carrier detetcion threshold for primary & secondary channel */
14649 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DEM_WR_CM_A_THRSHLD__A, carriers->a.thres, 0);
14650 if (rc != 0) {
14651 pr_err("error %d\n", rc);
14652 goto rw_error;
14654 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DEM_WR_CM_B_THRSHLD__A, carriers->b.thres, 0);
14655 if (rc != 0) {
14656 pr_err("error %d\n", rc);
14657 goto rw_error;
14660 /* update DRXK data structure */
14661 ext_attr->aud_data.carriers = *carriers;
14663 return 0;
14664 rw_error:
14665 return -EIO;
14668 /*============================================================================*/
14670 * \brief Get I2S Source, I2S matrix and FM matrix
14671 * \param demod instance of demodulator
14672 * \param pointer to pDRXAudmixer_t
14673 * \return int.
14676 static int
14677 aud_ctrl_get_cfg_mixer(struct drx_demod_instance *demod, struct drx_cfg_aud_mixer *mixer)
14679 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)NULL;
14680 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
14681 int rc;
14682 u16 src_i2s_matr = 0;
14683 u16 fm_matr = 0;
14685 if (mixer == NULL)
14686 return -EINVAL;
14688 dev_addr = demod->my_i2c_dev_addr;
14689 ext_attr = (struct drxj_data *) demod->my_ext_attr;
14691 /* power up */
14692 if (ext_attr->aud_data.audio_is_active == false) {
14693 rc = power_up_aud(demod, true);
14694 if (rc != 0) {
14695 pr_err("error %d\n", rc);
14696 goto rw_error;
14698 ext_attr->aud_data.audio_is_active = true;
14701 /* Source Selctor */
14702 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DSP_WR_SRC_I2S_MATR__A, &src_i2s_matr, 0);
14703 if (rc != 0) {
14704 pr_err("error %d\n", rc);
14705 goto rw_error;
14708 switch (src_i2s_matr & AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S__M) {
14709 case AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_MONO:
14710 mixer->source_i2s = DRX_AUD_SRC_MONO;
14711 break;
14712 case AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_AB:
14713 mixer->source_i2s = DRX_AUD_SRC_STEREO_OR_AB;
14714 break;
14715 case AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_A:
14716 mixer->source_i2s = DRX_AUD_SRC_STEREO_OR_A;
14717 break;
14718 case AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_B:
14719 mixer->source_i2s = DRX_AUD_SRC_STEREO_OR_B;
14720 break;
14721 default:
14722 return -EIO;
14725 /* Matrix */
14726 switch (src_i2s_matr & AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S__M) {
14727 case AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_MONO:
14728 mixer->matrix_i2s = DRX_AUD_I2S_MATRIX_MONO;
14729 break;
14730 case AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_STEREO:
14731 mixer->matrix_i2s = DRX_AUD_I2S_MATRIX_STEREO;
14732 break;
14733 case AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_SOUND_A:
14734 mixer->matrix_i2s = DRX_AUD_I2S_MATRIX_A_MONO;
14735 break;
14736 case AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_SOUND_B:
14737 mixer->matrix_i2s = DRX_AUD_I2S_MATRIX_B_MONO;
14738 break;
14739 default:
14740 return -EIO;
14743 /* FM Matrix */
14744 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_WR_FM_MATRIX__A, &fm_matr, 0);
14745 if (rc != 0) {
14746 pr_err("error %d\n", rc);
14747 goto rw_error;
14749 switch (fm_matr & AUD_DEM_WR_FM_MATRIX__M) {
14750 case AUD_DEM_WR_FM_MATRIX_NO_MATRIX:
14751 mixer->matrix_fm = DRX_AUD_FM_MATRIX_NO_MATRIX;
14752 break;
14753 case AUD_DEM_WR_FM_MATRIX_GERMAN_MATRIX:
14754 mixer->matrix_fm = DRX_AUD_FM_MATRIX_GERMAN;
14755 break;
14756 case AUD_DEM_WR_FM_MATRIX_KOREAN_MATRIX:
14757 mixer->matrix_fm = DRX_AUD_FM_MATRIX_KOREAN;
14758 break;
14759 case AUD_DEM_WR_FM_MATRIX_SOUND_A:
14760 mixer->matrix_fm = DRX_AUD_FM_MATRIX_SOUND_A;
14761 break;
14762 case AUD_DEM_WR_FM_MATRIX_SOUND_B:
14763 mixer->matrix_fm = DRX_AUD_FM_MATRIX_SOUND_B;
14764 break;
14765 default:
14766 return -EIO;
14769 return 0;
14770 rw_error:
14771 return -EIO;
14774 /*============================================================================*/
14776 * \brief Set I2S Source, I2S matrix and FM matrix
14777 * \param demod instance of demodulator
14778 * \param pointer to DRXAudmixer_t
14779 * \return int.
14782 static int
14783 aud_ctrl_set_cfg_mixer(struct drx_demod_instance *demod, struct drx_cfg_aud_mixer *mixer)
14785 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)NULL;
14786 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
14787 int rc;
14788 u16 src_i2s_matr = 0;
14789 u16 fm_matr = 0;
14791 if (mixer == NULL)
14792 return -EINVAL;
14794 dev_addr = demod->my_i2c_dev_addr;
14795 ext_attr = (struct drxj_data *) demod->my_ext_attr;
14797 /* power up */
14798 if (ext_attr->aud_data.audio_is_active == false) {
14799 rc = power_up_aud(demod, true);
14800 if (rc != 0) {
14801 pr_err("error %d\n", rc);
14802 goto rw_error;
14804 ext_attr->aud_data.audio_is_active = true;
14807 /* Source Selctor */
14808 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DSP_WR_SRC_I2S_MATR__A, &src_i2s_matr, 0);
14809 if (rc != 0) {
14810 pr_err("error %d\n", rc);
14811 goto rw_error;
14813 src_i2s_matr &= (u16) ~AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S__M;
14815 switch (mixer->source_i2s) {
14816 case DRX_AUD_SRC_MONO:
14817 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_MONO;
14818 break;
14819 case DRX_AUD_SRC_STEREO_OR_AB:
14820 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_AB;
14821 break;
14822 case DRX_AUD_SRC_STEREO_OR_A:
14823 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_A;
14824 break;
14825 case DRX_AUD_SRC_STEREO_OR_B:
14826 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_SRC_I2S_STEREO_B;
14827 break;
14828 default:
14829 return -EINVAL;
14832 /* Matrix */
14833 src_i2s_matr &= (u16) ~AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S__M;
14834 switch (mixer->matrix_i2s) {
14835 case DRX_AUD_I2S_MATRIX_MONO:
14836 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_MONO;
14837 break;
14838 case DRX_AUD_I2S_MATRIX_STEREO:
14839 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_STEREO;
14840 break;
14841 case DRX_AUD_I2S_MATRIX_A_MONO:
14842 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_SOUND_A;
14843 break;
14844 case DRX_AUD_I2S_MATRIX_B_MONO:
14845 src_i2s_matr |= AUD_DSP_WR_SRC_I2S_MATR_MAT_I2S_SOUND_B;
14846 break;
14847 default:
14848 return -EINVAL;
14850 /* write the result */
14851 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DSP_WR_SRC_I2S_MATR__A, src_i2s_matr, 0);
14852 if (rc != 0) {
14853 pr_err("error %d\n", rc);
14854 goto rw_error;
14857 /* FM Matrix */
14858 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_WR_FM_MATRIX__A, &fm_matr, 0);
14859 if (rc != 0) {
14860 pr_err("error %d\n", rc);
14861 goto rw_error;
14863 fm_matr &= (u16) ~AUD_DEM_WR_FM_MATRIX__M;
14864 switch (mixer->matrix_fm) {
14865 case DRX_AUD_FM_MATRIX_NO_MATRIX:
14866 fm_matr |= AUD_DEM_WR_FM_MATRIX_NO_MATRIX;
14867 break;
14868 case DRX_AUD_FM_MATRIX_GERMAN:
14869 fm_matr |= AUD_DEM_WR_FM_MATRIX_GERMAN_MATRIX;
14870 break;
14871 case DRX_AUD_FM_MATRIX_KOREAN:
14872 fm_matr |= AUD_DEM_WR_FM_MATRIX_KOREAN_MATRIX;
14873 break;
14874 case DRX_AUD_FM_MATRIX_SOUND_A:
14875 fm_matr |= AUD_DEM_WR_FM_MATRIX_SOUND_A;
14876 break;
14877 case DRX_AUD_FM_MATRIX_SOUND_B:
14878 fm_matr |= AUD_DEM_WR_FM_MATRIX_SOUND_B;
14879 break;
14880 default:
14881 return -EINVAL;
14884 /* Only write if ASS is off */
14885 if (ext_attr->aud_data.auto_sound == DRX_AUD_AUTO_SOUND_OFF) {
14886 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DEM_WR_FM_MATRIX__A, fm_matr, 0);
14887 if (rc != 0) {
14888 pr_err("error %d\n", rc);
14889 goto rw_error;
14893 /* update the data structure with hardware state */
14894 ext_attr->aud_data.mixer = *mixer;
14896 return 0;
14897 rw_error:
14898 return -EIO;
14901 /*============================================================================*/
14903 * \brief Set AV Sync settings
14904 * \param demod instance of demodulator
14905 * \param pointer to DRXICfgAVSync_t
14906 * \return int.
14909 static int
14910 aud_ctrl_set_cfg_av_sync(struct drx_demod_instance *demod, enum drx_cfg_aud_av_sync *av_sync)
14912 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)NULL;
14913 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
14914 int rc;
14915 u16 w_aud_vid_sync = 0;
14917 if (av_sync == NULL)
14918 return -EINVAL;
14920 dev_addr = demod->my_i2c_dev_addr;
14921 ext_attr = (struct drxj_data *) demod->my_ext_attr;
14923 /* power up */
14924 if (ext_attr->aud_data.audio_is_active == false) {
14925 rc = power_up_aud(demod, true);
14926 if (rc != 0) {
14927 pr_err("error %d\n", rc);
14928 goto rw_error;
14930 ext_attr->aud_data.audio_is_active = true;
14933 /* audio/video synchronisation */
14934 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DSP_WR_AV_SYNC__A, &w_aud_vid_sync, 0);
14935 if (rc != 0) {
14936 pr_err("error %d\n", rc);
14937 goto rw_error;
14940 w_aud_vid_sync &= (u16) ~AUD_DSP_WR_AV_SYNC_AV_ON__M;
14942 if (*av_sync == DRX_AUD_AVSYNC_OFF)
14943 w_aud_vid_sync |= AUD_DSP_WR_AV_SYNC_AV_ON_DISABLE;
14944 else
14945 w_aud_vid_sync |= AUD_DSP_WR_AV_SYNC_AV_ON_ENABLE;
14947 w_aud_vid_sync &= (u16) ~AUD_DSP_WR_AV_SYNC_AV_STD_SEL__M;
14949 switch (*av_sync) {
14950 case DRX_AUD_AVSYNC_NTSC:
14951 w_aud_vid_sync |= AUD_DSP_WR_AV_SYNC_AV_STD_SEL_NTSC;
14952 break;
14953 case DRX_AUD_AVSYNC_MONOCHROME:
14954 w_aud_vid_sync |= AUD_DSP_WR_AV_SYNC_AV_STD_SEL_MONOCHROME;
14955 break;
14956 case DRX_AUD_AVSYNC_PAL_SECAM:
14957 w_aud_vid_sync |= AUD_DSP_WR_AV_SYNC_AV_STD_SEL_PAL_SECAM;
14958 break;
14959 case DRX_AUD_AVSYNC_OFF:
14960 /* OK */
14961 break;
14962 default:
14963 return -EINVAL;
14966 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DSP_WR_AV_SYNC__A, w_aud_vid_sync, 0);
14967 if (rc != 0) {
14968 pr_err("error %d\n", rc);
14969 goto rw_error;
14971 return 0;
14972 rw_error:
14973 return -EIO;
14976 /*============================================================================*/
14978 * \brief Get AV Sync settings
14979 * \param demod instance of demodulator
14980 * \param pointer to DRXICfgAVSync_t
14981 * \return int.
14984 static int
14985 aud_ctrl_get_cfg_av_sync(struct drx_demod_instance *demod, enum drx_cfg_aud_av_sync *av_sync)
14987 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)NULL;
14988 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
14989 int rc;
14990 u16 w_aud_vid_sync = 0;
14992 if (av_sync == NULL)
14993 return -EINVAL;
14995 dev_addr = demod->my_i2c_dev_addr;
14996 ext_attr = (struct drxj_data *) demod->my_ext_attr;
14998 /* power up */
14999 if (ext_attr->aud_data.audio_is_active == false) {
15000 rc = power_up_aud(demod, true);
15001 if (rc != 0) {
15002 pr_err("error %d\n", rc);
15003 goto rw_error;
15005 ext_attr->aud_data.audio_is_active = true;
15008 /* audio/video synchronisation */
15009 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DSP_WR_AV_SYNC__A, &w_aud_vid_sync, 0);
15010 if (rc != 0) {
15011 pr_err("error %d\n", rc);
15012 goto rw_error;
15015 if ((w_aud_vid_sync & AUD_DSP_WR_AV_SYNC_AV_ON__M) ==
15016 AUD_DSP_WR_AV_SYNC_AV_ON_DISABLE) {
15017 *av_sync = DRX_AUD_AVSYNC_OFF;
15018 return 0;
15021 switch (w_aud_vid_sync & AUD_DSP_WR_AV_SYNC_AV_STD_SEL__M) {
15022 case AUD_DSP_WR_AV_SYNC_AV_STD_SEL_NTSC:
15023 *av_sync = DRX_AUD_AVSYNC_NTSC;
15024 break;
15025 case AUD_DSP_WR_AV_SYNC_AV_STD_SEL_MONOCHROME:
15026 *av_sync = DRX_AUD_AVSYNC_MONOCHROME;
15027 break;
15028 case AUD_DSP_WR_AV_SYNC_AV_STD_SEL_PAL_SECAM:
15029 *av_sync = DRX_AUD_AVSYNC_PAL_SECAM;
15030 break;
15031 default:
15032 return -EIO;
15035 return 0;
15036 rw_error:
15037 return -EIO;
15040 /*============================================================================*/
15042 * \brief Get deviation mode
15043 * \param demod instance of demodulator
15044 * \param pointer to enum drx_cfg_aud_deviation * \return int.
15047 static int
15048 aud_ctrl_get_cfg_dev(struct drx_demod_instance *demod, enum drx_cfg_aud_deviation *dev)
15050 u16 r_modus = 0;
15051 int rc;
15053 if (dev == NULL)
15054 return -EINVAL;
15056 rc = aud_get_modus(demod, &r_modus);
15057 if (rc != 0) {
15058 pr_err("error %d\n", rc);
15059 goto rw_error;
15062 switch (r_modus & AUD_DEM_WR_MODUS_MOD_HDEV_A__M) {
15063 case AUD_DEM_WR_MODUS_MOD_HDEV_A_NORMAL:
15064 *dev = DRX_AUD_DEVIATION_NORMAL;
15065 break;
15066 case AUD_DEM_WR_MODUS_MOD_HDEV_A_HIGH_DEVIATION:
15067 *dev = DRX_AUD_DEVIATION_HIGH;
15068 break;
15069 default:
15070 return -EIO;
15073 return 0;
15074 rw_error:
15075 return -EIO;
15078 /*============================================================================*/
15080 * \brief Get deviation mode
15081 * \param demod instance of demodulator
15082 * \param pointer to enum drx_cfg_aud_deviation * \return int.
15085 static int
15086 aud_ctrl_set_cfg_dev(struct drx_demod_instance *demod, enum drx_cfg_aud_deviation *dev)
15088 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)NULL;
15089 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
15090 int rc;
15091 u16 w_modus = 0;
15092 u16 r_modus = 0;
15094 if (dev == NULL)
15095 return -EINVAL;
15097 ext_attr = (struct drxj_data *) demod->my_ext_attr;
15098 dev_addr = demod->my_i2c_dev_addr;
15100 rc = aud_get_modus(demod, &r_modus);
15101 if (rc != 0) {
15102 pr_err("error %d\n", rc);
15103 goto rw_error;
15106 w_modus = r_modus;
15108 w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_HDEV_A__M;
15110 switch (*dev) {
15111 case DRX_AUD_DEVIATION_NORMAL:
15112 w_modus |= AUD_DEM_WR_MODUS_MOD_HDEV_A_NORMAL;
15113 break;
15114 case DRX_AUD_DEVIATION_HIGH:
15115 w_modus |= AUD_DEM_WR_MODUS_MOD_HDEV_A_HIGH_DEVIATION;
15116 break;
15117 default:
15118 return -EINVAL;
15121 /* now update the modus register */
15122 if (w_modus != r_modus) {
15123 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DEM_WR_MODUS__A, w_modus, 0);
15124 if (rc != 0) {
15125 pr_err("error %d\n", rc);
15126 goto rw_error;
15129 /* store in drxk data struct */
15130 ext_attr->aud_data.deviation = *dev;
15132 return 0;
15133 rw_error:
15134 return -EIO;
15137 /*============================================================================*/
15139 * \brief Get Prescaler settings
15140 * \param demod instance of demodulator
15141 * \param pointer to struct drx_cfg_aud_prescale * \return int.
15144 static int
15145 aud_ctrl_get_cfg_prescale(struct drx_demod_instance *demod, struct drx_cfg_aud_prescale *presc)
15147 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)NULL;
15148 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
15149 int rc;
15150 u16 r_max_fm_deviation = 0;
15151 u16 r_nicam_prescaler = 0;
15153 if (presc == NULL)
15154 return -EINVAL;
15156 dev_addr = demod->my_i2c_dev_addr;
15157 ext_attr = (struct drxj_data *) demod->my_ext_attr;
15159 /* power up */
15160 if (ext_attr->aud_data.audio_is_active == false) {
15161 rc = power_up_aud(demod, true);
15162 if (rc != 0) {
15163 pr_err("error %d\n", rc);
15164 goto rw_error;
15166 ext_attr->aud_data.audio_is_active = true;
15169 /* read register data */
15170 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DSP_WR_NICAM_PRESC__A, &r_nicam_prescaler, 0);
15171 if (rc != 0) {
15172 pr_err("error %d\n", rc);
15173 goto rw_error;
15175 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DSP_WR_FM_PRESC__A, &r_max_fm_deviation, 0);
15176 if (rc != 0) {
15177 pr_err("error %d\n", rc);
15178 goto rw_error;
15181 /* calculate max FM deviation */
15182 r_max_fm_deviation >>= AUD_DSP_WR_FM_PRESC_FM_AM_PRESC__B;
15183 if (r_max_fm_deviation > 0) {
15184 presc->fm_deviation = 3600UL + (r_max_fm_deviation >> 1);
15185 presc->fm_deviation /= r_max_fm_deviation;
15186 } else {
15187 presc->fm_deviation = 380; /* kHz */
15190 /* calculate NICAM gain from pre-scaler */
15192 nicam_gain = 20 * ( log10( preScaler / 16) )
15193 = ( 100log10( preScaler ) - 100log10( 16 ) ) / 5
15195 because log1_times100() cannot return negative numbers
15196 = ( 100log10( 10 * preScaler ) - 100log10( 10 * 16) ) / 5
15198 for 0.1dB resolution:
15200 nicam_gain = 200 * ( log10( preScaler / 16) )
15201 = 2 * ( 100log10( 10 * preScaler ) - 100log10( 10 * 16) )
15202 = ( 100log10( 10 * preScaler^2 ) - 100log10( 10 * 16^2 ) )
15205 r_nicam_prescaler >>= 8;
15206 if (r_nicam_prescaler <= 1)
15207 presc->nicam_gain = -241;
15208 else
15209 presc->nicam_gain = (s16)(((s32)(log1_times100(10 * r_nicam_prescaler * r_nicam_prescaler)) - (s32)(log1_times100(10 * 16 * 16))));
15211 return 0;
15212 rw_error:
15213 return -EIO;
15216 /*============================================================================*/
15218 * \brief Set Prescaler settings
15219 * \param demod instance of demodulator
15220 * \param pointer to struct drx_cfg_aud_prescale * \return int.
15223 static int
15224 aud_ctrl_set_cfg_prescale(struct drx_demod_instance *demod, struct drx_cfg_aud_prescale *presc)
15226 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)NULL;
15227 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
15228 int rc;
15229 u16 w_max_fm_deviation = 0;
15230 u16 nicam_prescaler;
15232 if (presc == NULL)
15233 return -EINVAL;
15235 dev_addr = demod->my_i2c_dev_addr;
15236 ext_attr = (struct drxj_data *) demod->my_ext_attr;
15238 /* power up */
15239 if (ext_attr->aud_data.audio_is_active == false) {
15240 rc = power_up_aud(demod, true);
15241 if (rc != 0) {
15242 pr_err("error %d\n", rc);
15243 goto rw_error;
15245 ext_attr->aud_data.audio_is_active = true;
15248 /* setting of max FM deviation */
15249 w_max_fm_deviation = (u16) (frac(3600UL, presc->fm_deviation, 0));
15250 w_max_fm_deviation <<= AUD_DSP_WR_FM_PRESC_FM_AM_PRESC__B;
15251 if (w_max_fm_deviation >= AUD_DSP_WR_FM_PRESC_FM_AM_PRESC_28_KHZ_FM_DEVIATION)
15252 w_max_fm_deviation = AUD_DSP_WR_FM_PRESC_FM_AM_PRESC_28_KHZ_FM_DEVIATION;
15254 /* NICAM Prescaler */
15255 if ((presc->nicam_gain >= -241) && (presc->nicam_gain <= 180)) {
15256 /* calculation
15258 prescaler = 16 * 10^( gd_b / 20 )
15260 minval of gd_b = -20*log( 16 ) = -24.1dB
15262 negative numbers not allowed for d_b2lin_times100, so
15264 prescaler = 16 * 10^( gd_b / 20 )
15265 = 10^( (gd_b / 20) + log10(16) )
15266 = 10^( (gd_b + 20log10(16)) / 20 )
15268 in 0.1dB
15270 = 10^( G0.1dB + 200log10(16)) / 200 )
15273 nicam_prescaler = (u16)
15274 ((d_b2lin_times100(presc->nicam_gain + 241UL) + 50UL) / 100UL);
15276 /* clip result */
15277 if (nicam_prescaler > 127)
15278 nicam_prescaler = 127;
15280 /* shift before writing to register */
15281 nicam_prescaler <<= 8;
15282 } else {
15283 return -EINVAL;
15285 /* end of setting NICAM Prescaler */
15287 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DSP_WR_NICAM_PRESC__A, nicam_prescaler, 0);
15288 if (rc != 0) {
15289 pr_err("error %d\n", rc);
15290 goto rw_error;
15292 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DSP_WR_FM_PRESC__A, w_max_fm_deviation, 0);
15293 if (rc != 0) {
15294 pr_err("error %d\n", rc);
15295 goto rw_error;
15298 ext_attr->aud_data.prescale = *presc;
15300 return 0;
15301 rw_error:
15302 return -EIO;
15305 /*============================================================================*/
15307 * \brief Beep
15308 * \param demod instance of demodulator
15309 * \param pointer to struct drx_aud_beep * \return int.
15312 static int aud_ctrl_beep(struct drx_demod_instance *demod, struct drx_aud_beep *beep)
15314 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)NULL;
15315 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
15316 int rc;
15317 u16 the_beep = 0;
15318 u16 volume = 0;
15319 u32 frequency = 0;
15321 if (beep == NULL)
15322 return -EINVAL;
15324 dev_addr = demod->my_i2c_dev_addr;
15325 ext_attr = (struct drxj_data *) demod->my_ext_attr;
15327 /* power up */
15328 if (ext_attr->aud_data.audio_is_active == false) {
15329 rc = power_up_aud(demod, true);
15330 if (rc != 0) {
15331 pr_err("error %d\n", rc);
15332 goto rw_error;
15334 ext_attr->aud_data.audio_is_active = true;
15337 if ((beep->volume > 0) || (beep->volume < -127))
15338 return -EINVAL;
15340 if (beep->frequency > 3000)
15341 return -EINVAL;
15343 volume = (u16) beep->volume + 127;
15344 the_beep |= volume << AUD_DSP_WR_BEEPER_BEEP_VOLUME__B;
15346 frequency = ((u32) beep->frequency) * 23 / 500;
15347 if (frequency > AUD_DSP_WR_BEEPER_BEEP_FREQUENCY__M)
15348 frequency = AUD_DSP_WR_BEEPER_BEEP_FREQUENCY__M;
15349 the_beep |= (u16) frequency;
15351 if (beep->mute == true)
15352 the_beep = 0;
15354 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DSP_WR_BEEPER__A, the_beep, 0);
15355 if (rc != 0) {
15356 pr_err("error %d\n", rc);
15357 goto rw_error;
15360 return 0;
15361 rw_error:
15362 return -EIO;
15365 /*============================================================================*/
15367 * \brief Set an audio standard
15368 * \param demod instance of demodulator
15369 * \param pointer to enum drx_aud_standard * \return int.
15372 static int
15373 aud_ctrl_set_standard(struct drx_demod_instance *demod, enum drx_aud_standard *standard)
15375 struct i2c_device_addr *dev_addr = NULL;
15376 struct drxj_data *ext_attr = NULL;
15377 enum drx_standard current_standard = DRX_STANDARD_UNKNOWN;
15378 int rc;
15379 u16 w_standard = 0;
15380 u16 w_modus = 0;
15381 u16 r_modus = 0;
15383 bool mute_buffer = false;
15384 s16 volume_buffer = 0;
15385 u16 w_volume = 0;
15387 if (standard == NULL)
15388 return -EINVAL;
15390 dev_addr = (struct i2c_device_addr *)demod->my_i2c_dev_addr;
15391 ext_attr = (struct drxj_data *) demod->my_ext_attr;
15393 /* power up */
15394 if (ext_attr->aud_data.audio_is_active == false) {
15395 rc = power_up_aud(demod, false);
15396 if (rc != 0) {
15397 pr_err("error %d\n", rc);
15398 goto rw_error;
15400 ext_attr->aud_data.audio_is_active = true;
15403 /* reset RDS data availability flag */
15404 ext_attr->aud_data.rds_data_present = false;
15406 /* we need to mute from here to avoid noise during standard switching */
15407 mute_buffer = ext_attr->aud_data.volume.mute;
15408 volume_buffer = ext_attr->aud_data.volume.volume;
15410 ext_attr->aud_data.volume.mute = true;
15411 /* restore data structure from DRX ExtAttr, call volume first to mute */
15412 rc = aud_ctrl_set_cfg_volume(demod, &ext_attr->aud_data.volume);
15413 if (rc != 0) {
15414 pr_err("error %d\n", rc);
15415 goto rw_error;
15417 rc = aud_ctrl_set_cfg_carrier(demod, &ext_attr->aud_data.carriers);
15418 if (rc != 0) {
15419 pr_err("error %d\n", rc);
15420 goto rw_error;
15422 rc = aud_ctrl_set_cfg_ass_thres(demod, &ext_attr->aud_data.ass_thresholds);
15423 if (rc != 0) {
15424 pr_err("error %d\n", rc);
15425 goto rw_error;
15427 rc = aud_ctr_setl_cfg_auto_sound(demod, &ext_attr->aud_data.auto_sound);
15428 if (rc != 0) {
15429 pr_err("error %d\n", rc);
15430 goto rw_error;
15432 rc = aud_ctrl_set_cfg_mixer(demod, &ext_attr->aud_data.mixer);
15433 if (rc != 0) {
15434 pr_err("error %d\n", rc);
15435 goto rw_error;
15437 rc = aud_ctrl_set_cfg_av_sync(demod, &ext_attr->aud_data.av_sync);
15438 if (rc != 0) {
15439 pr_err("error %d\n", rc);
15440 goto rw_error;
15442 rc = aud_ctrl_set_cfg_output_i2s(demod, &ext_attr->aud_data.i2sdata);
15443 if (rc != 0) {
15444 pr_err("error %d\n", rc);
15445 goto rw_error;
15448 /* get prescaler from presets */
15449 rc = aud_ctrl_set_cfg_prescale(demod, &ext_attr->aud_data.prescale);
15450 if (rc != 0) {
15451 pr_err("error %d\n", rc);
15452 goto rw_error;
15455 rc = aud_get_modus(demod, &r_modus);
15456 if (rc != 0) {
15457 pr_err("error %d\n", rc);
15458 goto rw_error;
15461 w_modus = r_modus;
15463 switch (*standard) {
15464 case DRX_AUD_STANDARD_AUTO:
15465 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_AUTO;
15466 break;
15467 case DRX_AUD_STANDARD_BTSC:
15468 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_BTSC_STEREO;
15469 if (ext_attr->aud_data.btsc_detect == DRX_BTSC_MONO_AND_SAP)
15470 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_BTSC_SAP;
15471 break;
15472 case DRX_AUD_STANDARD_A2:
15473 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_M_KOREA;
15474 break;
15475 case DRX_AUD_STANDARD_EIAJ:
15476 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_EIA_J;
15477 break;
15478 case DRX_AUD_STANDARD_FM_STEREO:
15479 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_FM_RADIO;
15480 break;
15481 case DRX_AUD_STANDARD_BG_FM:
15482 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_BG_FM;
15483 break;
15484 case DRX_AUD_STANDARD_D_K1:
15485 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_D_K1;
15486 break;
15487 case DRX_AUD_STANDARD_D_K2:
15488 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_D_K2;
15489 break;
15490 case DRX_AUD_STANDARD_D_K3:
15491 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_D_K3;
15492 break;
15493 case DRX_AUD_STANDARD_BG_NICAM_FM:
15494 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_BG_NICAM_FM;
15495 break;
15496 case DRX_AUD_STANDARD_L_NICAM_AM:
15497 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_L_NICAM_AM;
15498 break;
15499 case DRX_AUD_STANDARD_I_NICAM_FM:
15500 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_I_NICAM_FM;
15501 break;
15502 case DRX_AUD_STANDARD_D_K_NICAM_FM:
15503 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_D_K_NICAM_FM;
15504 break;
15505 case DRX_AUD_STANDARD_UNKNOWN:
15506 w_standard = AUD_DEM_WR_STANDARD_SEL_STD_SEL_AUTO;
15507 break;
15508 default:
15509 return -EIO;
15512 if (*standard == DRX_AUD_STANDARD_AUTO) {
15513 /* we need the current standard here */
15514 current_standard = ext_attr->standard;
15516 w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_6_5MHZ__M;
15518 if ((current_standard == DRX_STANDARD_PAL_SECAM_L) || (current_standard == DRX_STANDARD_PAL_SECAM_LP))
15519 w_modus |= (AUD_DEM_WR_MODUS_MOD_6_5MHZ_SECAM);
15520 else
15521 w_modus |= (AUD_DEM_WR_MODUS_MOD_6_5MHZ_D_K);
15523 w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_4_5MHZ__M;
15524 if (current_standard == DRX_STANDARD_NTSC)
15525 w_modus |= (AUD_DEM_WR_MODUS_MOD_4_5MHZ_M_BTSC);
15526 else
15527 w_modus |= (AUD_DEM_WR_MODUS_MOD_4_5MHZ_CHROMA);
15531 w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_FMRADIO__M;
15533 /* just get hardcoded deemphasis and activate here */
15534 if (ext_attr->aud_data.deemph == DRX_AUD_FM_DEEMPH_50US)
15535 w_modus |= (AUD_DEM_WR_MODUS_MOD_FMRADIO_EU_50U);
15536 else
15537 w_modus |= (AUD_DEM_WR_MODUS_MOD_FMRADIO_US_75U);
15539 w_modus &= (u16) ~AUD_DEM_WR_MODUS_MOD_BTSC__M;
15540 if (ext_attr->aud_data.btsc_detect == DRX_BTSC_STEREO)
15541 w_modus |= (AUD_DEM_WR_MODUS_MOD_BTSC_BTSC_STEREO);
15542 else
15543 w_modus |= (AUD_DEM_WR_MODUS_MOD_BTSC_BTSC_SAP);
15545 if (w_modus != r_modus) {
15546 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DEM_WR_MODUS__A, w_modus, 0);
15547 if (rc != 0) {
15548 pr_err("error %d\n", rc);
15549 goto rw_error;
15553 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DEM_WR_STANDARD_SEL__A, w_standard, 0);
15554 if (rc != 0) {
15555 pr_err("error %d\n", rc);
15556 goto rw_error;
15559 /**************************************************************************/
15560 /* NOT calling aud_ctrl_set_cfg_volume to avoid interfering standard */
15561 /* detection, need to keep things very minimal here, but keep audio */
15562 /* buffers intact */
15563 /**************************************************************************/
15564 ext_attr->aud_data.volume.mute = mute_buffer;
15565 if (ext_attr->aud_data.volume.mute == false) {
15566 w_volume |= (u16) ((volume_buffer + AUD_VOLUME_ZERO_DB) <<
15567 AUD_DSP_WR_VOLUME_VOL_MAIN__B);
15568 rc = DRXJ_DAP.write_reg16func(dev_addr, AUD_DSP_WR_VOLUME__A, w_volume, 0);
15569 if (rc != 0) {
15570 pr_err("error %d\n", rc);
15571 goto rw_error;
15575 /* write standard selected */
15576 ext_attr->aud_data.audio_standard = *standard;
15578 return 0;
15579 rw_error:
15580 return -EIO;
15583 /*============================================================================*/
15585 * \brief Get the current audio standard
15586 * \param demod instance of demodulator
15587 * \param pointer to enum drx_aud_standard * \return int.
15590 static int
15591 aud_ctrl_get_standard(struct drx_demod_instance *demod, enum drx_aud_standard *standard)
15593 struct i2c_device_addr *dev_addr = NULL;
15594 struct drxj_data *ext_attr = NULL;
15595 int rc;
15596 u16 r_data = 0;
15598 if (standard == NULL)
15599 return -EINVAL;
15601 ext_attr = (struct drxj_data *) demod->my_ext_attr;
15602 dev_addr = (struct i2c_device_addr *)demod->my_i2c_dev_addr;
15604 /* power up */
15605 if (ext_attr->aud_data.audio_is_active == false) {
15606 rc = power_up_aud(demod, true);
15607 if (rc != 0) {
15608 pr_err("error %d\n", rc);
15609 goto rw_error;
15611 ext_attr->aud_data.audio_is_active = true;
15614 *standard = DRX_AUD_STANDARD_UNKNOWN;
15616 rc = DRXJ_DAP.read_reg16func(dev_addr, AUD_DEM_RD_STANDARD_RES__A, &r_data, 0);
15617 if (rc != 0) {
15618 pr_err("error %d\n", rc);
15619 goto rw_error;
15622 /* return OK if the detection is not ready yet */
15623 if (r_data >= AUD_DEM_RD_STANDARD_RES_STD_RESULT_DETECTION_STILL_ACTIVE) {
15624 *standard = DRX_AUD_STANDARD_NOT_READY;
15625 return 0;
15628 /* detection done, return correct standard */
15629 switch (r_data) {
15630 /* no standard detected */
15631 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_NO_SOUND_STANDARD:
15632 *standard = DRX_AUD_STANDARD_UNKNOWN;
15633 break;
15634 /* standard is KOREA(A2) */
15635 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_NTSC_M_DUAL_CARRIER_FM:
15636 *standard = DRX_AUD_STANDARD_A2;
15637 break;
15638 /* standard is EIA-J (Japan) */
15639 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_NTSC_EIA_J:
15640 *standard = DRX_AUD_STANDARD_EIAJ;
15641 break;
15642 /* standard is BTSC-stereo */
15643 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_BTSC_STEREO:
15644 *standard = DRX_AUD_STANDARD_BTSC;
15645 break;
15646 /* standard is BTSC-mono (SAP) */
15647 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_BTSC_MONO_SAP:
15648 *standard = DRX_AUD_STANDARD_BTSC;
15649 break;
15650 /* standard is FM radio */
15651 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_FM_RADIO:
15652 *standard = DRX_AUD_STANDARD_FM_STEREO;
15653 break;
15654 /* standard is BG FM */
15655 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_B_G_DUAL_CARRIER_FM:
15656 *standard = DRX_AUD_STANDARD_BG_FM;
15657 break;
15658 /* standard is DK-1 FM */
15659 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_D_K1_DUAL_CARRIER_FM:
15660 *standard = DRX_AUD_STANDARD_D_K1;
15661 break;
15662 /* standard is DK-2 FM */
15663 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_D_K2_DUAL_CARRIER_FM:
15664 *standard = DRX_AUD_STANDARD_D_K2;
15665 break;
15666 /* standard is DK-3 FM */
15667 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_D_K3_DUAL_CARRIER_FM:
15668 *standard = DRX_AUD_STANDARD_D_K3;
15669 break;
15670 /* standard is BG-NICAM FM */
15671 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_B_G_NICAM_FM:
15672 *standard = DRX_AUD_STANDARD_BG_NICAM_FM;
15673 break;
15674 /* standard is L-NICAM AM */
15675 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_L_NICAM_AM:
15676 *standard = DRX_AUD_STANDARD_L_NICAM_AM;
15677 break;
15678 /* standard is I-NICAM FM */
15679 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_I_NICAM_FM:
15680 *standard = DRX_AUD_STANDARD_I_NICAM_FM;
15681 break;
15682 /* standard is DK-NICAM FM */
15683 case AUD_DEM_RD_STANDARD_RES_STD_RESULT_D_K_NICAM_FM:
15684 *standard = DRX_AUD_STANDARD_D_K_NICAM_FM;
15685 break;
15686 default:
15687 *standard = DRX_AUD_STANDARD_UNKNOWN;
15690 return 0;
15691 rw_error:
15692 return -EIO;
15696 /*============================================================================*/
15698 * \brief Retreive lock status in case of FM standard
15699 * \param demod instance of demodulator
15700 * \param pointer to lock status
15701 * \return int.
15704 static int
15705 fm_lock_status(struct drx_demod_instance *demod, enum drx_lock_status *lock_stat)
15707 struct drx_aud_status status;
15708 int rc;
15710 /* Check detection of audio carriers */
15711 rc = aud_ctrl_get_carrier_detect_status(demod, &status);
15712 if (rc != 0) {
15713 pr_err("error %d\n", rc);
15714 goto rw_error;
15717 /* locked if either primary or secondary carrier is detected */
15718 if ((status.carrier_a == true) || (status.carrier_b == true))
15719 *lock_stat = DRX_LOCKED;
15720 else
15721 *lock_stat = DRX_NOT_LOCKED;
15723 return 0;
15725 rw_error:
15726 return -EIO;
15729 /*============================================================================*/
15731 * \brief retreive signal quality in case of FM standard
15732 * \param demod instance of demodulator
15733 * \param pointer to signal quality
15734 * \return int.
15736 * Only the quality indicator field is will be supplied.
15737 * This will either be 0% or 100%, nothing in between.
15740 static int
15741 fm_sig_quality(struct drx_demod_instance *demod, struct drx_sig_quality *sig_quality)
15743 enum drx_lock_status lock_status = DRX_NOT_LOCKED;
15744 int rc;
15746 rc = fm_lock_status(demod, &lock_status);
15747 if (rc != 0) {
15748 pr_err("error %d\n", rc);
15749 goto rw_error;
15751 if (lock_status == DRX_LOCKED)
15752 sig_quality->indicator = 100;
15753 else
15754 sig_quality->indicator = 0;
15756 return 0;
15758 rw_error:
15759 return -EIO;
15762 /*===========================================================================*/
15763 /*== END AUDIO DATAPATH FUNCTIONS ==*/
15764 /*===========================================================================*/
15766 /*============================================================================*/
15767 /*============================================================================*/
15768 /*== OOB DATAPATH FUNCTIONS ==*/
15769 /*============================================================================*/
15770 /*============================================================================*/
15772 * \fn int get_oob_lock_status ()
15773 * \brief Get OOB lock status.
15774 * \param dev_addr I2C address
15775 \ oob_lock OOB lock status.
15776 * \return int.
15778 * Gets OOB lock status
15781 static int
15782 get_oob_lock_status(struct drx_demod_instance *demod,
15783 struct i2c_device_addr *dev_addr, enum drx_lock_status *oob_lock)
15785 struct drxjscu_cmd scu_cmd;
15786 int rc;
15787 u16 cmd_result[2];
15788 u16 oob_lock_state;
15790 *oob_lock = DRX_NOT_LOCKED;
15792 scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB |
15793 SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK;
15794 scu_cmd.result_len = 2;
15795 scu_cmd.result = cmd_result;
15796 scu_cmd.parameter_len = 0;
15798 rc = scu_command(dev_addr, &scu_cmd);
15799 if (rc != 0) {
15800 pr_err("error %d\n", rc);
15801 goto rw_error;
15804 if (scu_cmd.result[1] < 0x4000) {
15805 /* 0x00 NOT LOCKED */
15806 *oob_lock = DRX_NOT_LOCKED;
15807 } else if (scu_cmd.result[1] < 0x8000) {
15808 /* 0x40 DEMOD LOCKED */
15809 *oob_lock = DRXJ_OOB_SYNC_LOCK;
15810 } else if (scu_cmd.result[1] < 0xC000) {
15811 /* 0x80 DEMOD + OOB LOCKED (system lock) */
15812 oob_lock_state = scu_cmd.result[1] & 0x00FF;
15814 if (oob_lock_state & 0x0008)
15815 *oob_lock = DRXJ_OOB_SYNC_LOCK;
15816 else if ((oob_lock_state & 0x0002) && (oob_lock_state & 0x0001))
15817 *oob_lock = DRXJ_OOB_AGC_LOCK;
15818 } else {
15819 /* 0xC0 NEVER LOCKED (system will never be able to lock to the signal) */
15820 *oob_lock = DRX_NEVER_LOCK;
15823 /* *oob_lock = scu_cmd.result[1]; */
15825 return 0;
15826 rw_error:
15827 return -EIO;
15831 * \fn int get_oob_symbol_rate_offset ()
15832 * \brief Get OOB Symbol rate offset. Unit is [ppm]
15833 * \param dev_addr I2C address
15834 * \ Symbol Rate Offset OOB parameter.
15835 * \return int.
15837 * Gets OOB frequency offset
15840 static int
15841 get_oob_symbol_rate_offset(struct i2c_device_addr *dev_addr, s32 *symbol_rate_offset)
15843 /* offset = -{(timing_offset/2^19)*(symbol_rate/12,656250MHz)}*10^6 [ppm] */
15844 /* offset = -{(timing_offset/2^19)*(symbol_rate/12656250)}*10^6 [ppm] */
15845 /* after reconfiguration: */
15846 /* offset = -{(timing_offset*symbol_rate)/(2^19*12656250)}*10^6 [ppm] */
15847 /* shift symbol rate left by 5 without lossing information */
15848 /* offset = -{(timing_offset*(symbol_rate * 2^-5))/(2^14*12656250)}*10^6 [ppm]*/
15849 /* shift 10^6 left by 6 without loosing information */
15850 /* offset = -{(timing_offset*(symbol_rate * 2^-5))/(2^8*12656250)}*15625 [ppm]*/
15851 /* trim 12656250/15625 = 810 */
15852 /* offset = -{(timing_offset*(symbol_rate * 2^-5))/(2^8*810)} [ppm] */
15853 /* offset = -[(symbol_rate * 2^-5)*(timing_offset)/(2^8)]/810 [ppm] */
15854 int rc;
15855 s32 timing_offset = 0;
15856 u32 unsigned_timing_offset = 0;
15857 s32 division_factor = 810;
15858 u16 data = 0;
15859 u32 symbol_rate = 0;
15860 bool negative = false;
15862 *symbol_rate_offset = 0;
15863 /* read data rate */
15864 rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_ORX_RF_RX_DATA_RATE__A, &data, 0);
15865 if (rc != 0) {
15866 pr_err("error %d\n", rc);
15867 goto rw_error;
15869 switch (data & SCU_RAM_ORX_RF_RX_DATA_RATE__M) {
15870 case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC:
15871 case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC:
15872 case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC_ALT:
15873 case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC_ALT:
15874 symbol_rate = 1024000; /* bps */
15875 break;
15876 case SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_REGSPEC:
15877 case SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_INVSPEC:
15878 symbol_rate = 772000; /* bps */
15879 break;
15880 case SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_REGSPEC:
15881 case SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_INVSPEC:
15882 symbol_rate = 1544000; /* bps */
15883 break;
15884 default:
15885 return -EIO;
15888 rc = DRXJ_DAP.read_reg16func(dev_addr, ORX_CON_CTI_DTI_R__A, &data, 0);
15889 if (rc != 0) {
15890 pr_err("error %d\n", rc);
15891 goto rw_error;
15893 /* convert data to positive and keep information about sign */
15894 if ((data & 0x8000) == 0x8000) {
15895 if (data == 0x8000)
15896 unsigned_timing_offset = 32768;
15897 else
15898 unsigned_timing_offset = 0x00007FFF & (u32) (-data);
15899 negative = true;
15900 } else
15901 unsigned_timing_offset = (u32) data;
15903 symbol_rate = symbol_rate >> 5;
15904 unsigned_timing_offset = (unsigned_timing_offset * symbol_rate);
15905 unsigned_timing_offset = frac(unsigned_timing_offset, 256, FRAC_ROUND);
15906 unsigned_timing_offset = frac(unsigned_timing_offset,
15907 division_factor, FRAC_ROUND);
15908 if (negative)
15909 timing_offset = (s32) unsigned_timing_offset;
15910 else
15911 timing_offset = -(s32) unsigned_timing_offset;
15913 *symbol_rate_offset = timing_offset;
15915 return 0;
15916 rw_error:
15917 return -EIO;
15921 * \fn int get_oob_freq_offset ()
15922 * \brief Get OOB lock status.
15923 * \param dev_addr I2C address
15924 * \ freq_offset OOB frequency offset.
15925 * \return int.
15927 * Gets OOB frequency offset
15930 static int
15931 get_oob_freq_offset(struct drx_demod_instance *demod, s32 *freq_offset)
15933 struct drx_common_attr *common_attr = (struct drx_common_attr *) (NULL);
15934 struct i2c_device_addr *dev_addr = NULL;
15935 int rc;
15936 u16 data = 0;
15937 u16 rot = 0;
15938 u16 symbol_rate_reg = 0;
15939 u32 symbol_rate = 0;
15940 s32 coarse_freq_offset = 0;
15941 s32 fine_freq_offset = 0;
15942 s32 fine_sign = 1;
15943 s32 coarse_sign = 1;
15944 u32 data64hi = 0;
15945 u32 data64lo = 0;
15946 u32 temp_freq_offset = 0;
15948 /* check arguments */
15949 if ((demod == NULL) || (freq_offset == NULL))
15950 return -EINVAL;
15952 dev_addr = demod->my_i2c_dev_addr;
15953 common_attr = (struct drx_common_attr *) demod->my_common_attr;
15955 *freq_offset = 0;
15957 /* read sign (spectrum inversion) */
15958 rc = DRXJ_DAP.read_reg16func(dev_addr, ORX_FWP_IQM_FRQ_W__A, &rot, 0);
15959 if (rc != 0) {
15960 pr_err("error %d\n", rc);
15961 goto rw_error;
15964 /* read frequency offset */
15965 rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_ORX_FRQ_OFFSET__A, &data, 0);
15966 if (rc != 0) {
15967 pr_err("error %d\n", rc);
15968 goto rw_error;
15970 /* find COARSE frequency offset */
15971 /* coarse_freq_offset = ( 25312500Hz*FRQ_OFFSET >> 21 ); */
15972 if (data & 0x8000) {
15973 data = (0xffff - data + 1);
15974 coarse_sign = -1;
15976 mult32(data, (common_attr->sys_clock_freq * 1000) / 6, &data64hi,
15977 &data64lo);
15978 temp_freq_offset = (((data64lo >> 21) & 0x7ff) | (data64hi << 11));
15980 /* get value in KHz */
15981 coarse_freq_offset = coarse_sign * frac(temp_freq_offset, 1000, FRAC_ROUND); /* KHz */
15982 /* read data rate */
15983 rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_ORX_RF_RX_DATA_RATE__A, &symbol_rate_reg, 0);
15984 if (rc != 0) {
15985 pr_err("error %d\n", rc);
15986 goto rw_error;
15988 switch (symbol_rate_reg & SCU_RAM_ORX_RF_RX_DATA_RATE__M) {
15989 case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC:
15990 case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC:
15991 case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC_ALT:
15992 case SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC_ALT:
15993 symbol_rate = 1024000;
15994 break;
15995 case SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_REGSPEC:
15996 case SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_INVSPEC:
15997 symbol_rate = 772000;
15998 break;
15999 case SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_REGSPEC:
16000 case SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_INVSPEC:
16001 symbol_rate = 1544000;
16002 break;
16003 default:
16004 return -EIO;
16007 /* find FINE frequency offset */
16008 /* fine_freq_offset = ( (CORRECTION_VALUE*symbol_rate) >> 18 ); */
16009 rc = DRXJ_DAP.read_reg16func(dev_addr, ORX_CON_CPH_FRQ_R__A, &data, 0);
16010 if (rc != 0) {
16011 pr_err("error %d\n", rc);
16012 goto rw_error;
16014 /* at least 5 MSB are 0 so first divide with 2^5 without information loss */
16015 fine_freq_offset = (symbol_rate >> 5);
16016 if (data & 0x8000) {
16017 fine_freq_offset *= 0xffff - data + 1; /* Hz */
16018 fine_sign = -1;
16019 } else {
16020 fine_freq_offset *= data; /* Hz */
16022 /* Left to divide with 8192 (2^13) */
16023 fine_freq_offset = frac(fine_freq_offset, 8192, FRAC_ROUND);
16024 /* and to divide with 1000 to get KHz */
16025 fine_freq_offset = fine_sign * frac(fine_freq_offset, 1000, FRAC_ROUND); /* KHz */
16027 if ((rot & 0x8000) == 0x8000)
16028 *freq_offset = -(coarse_freq_offset + fine_freq_offset);
16029 else
16030 *freq_offset = (coarse_freq_offset + fine_freq_offset);
16032 return 0;
16033 rw_error:
16034 return -EIO;
16038 * \fn int get_oob_frequency ()
16039 * \brief Get OOB frequency (Unit:KHz).
16040 * \param dev_addr I2C address
16041 * \ frequency OOB frequency parameters.
16042 * \return int.
16044 * Gets OOB frequency
16047 static int
16048 get_oob_frequency(struct drx_demod_instance *demod, s32 *frequency)
16050 struct i2c_device_addr *dev_addr = NULL;
16051 int rc;
16052 u16 data = 0;
16053 s32 freq_offset = 0;
16054 s32 freq = 0;
16056 dev_addr = demod->my_i2c_dev_addr;
16058 *frequency = 0; /* KHz */
16060 rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_ORX_RF_RX_FREQUENCY_VALUE__A, &data, 0);
16061 if (rc != 0) {
16062 pr_err("error %d\n", rc);
16063 goto rw_error;
16066 freq = (s32) ((s32) data * 50 + 50000L);
16068 rc = get_oob_freq_offset(demod, &freq_offset);
16069 if (rc != 0) {
16070 pr_err("error %d\n", rc);
16071 goto rw_error;
16074 *frequency = freq + freq_offset;
16076 return 0;
16077 rw_error:
16078 return -EIO;
16082 * \fn int get_oobmer ()
16083 * \brief Get OOB MER.
16084 * \param dev_addr I2C address
16085 \ MER OOB parameter in dB.
16086 * \return int.
16088 * Gets OOB MER. Table for MER is in Programming guide.
16091 static int get_oobmer(struct i2c_device_addr *dev_addr, u32 *mer)
16093 int rc;
16094 u16 data = 0;
16096 *mer = 0;
16097 /* READ MER */
16098 rc = DRXJ_DAP.read_reg16func(dev_addr, ORX_EQU_MER_MER_R__A, &data, 0);
16099 if (rc != 0) {
16100 pr_err("error %d\n", rc);
16101 goto rw_error;
16103 switch (data) {
16104 case 0: /* fall through */
16105 case 1:
16106 *mer = 39;
16107 break;
16108 case 2:
16109 *mer = 33;
16110 break;
16111 case 3:
16112 *mer = 29;
16113 break;
16114 case 4:
16115 *mer = 27;
16116 break;
16117 case 5:
16118 *mer = 25;
16119 break;
16120 case 6:
16121 *mer = 23;
16122 break;
16123 case 7:
16124 *mer = 22;
16125 break;
16126 case 8:
16127 *mer = 21;
16128 break;
16129 case 9:
16130 *mer = 20;
16131 break;
16132 case 10:
16133 *mer = 19;
16134 break;
16135 case 11:
16136 *mer = 18;
16137 break;
16138 case 12:
16139 *mer = 17;
16140 break;
16141 case 13: /* fall through */
16142 case 14:
16143 *mer = 16;
16144 break;
16145 case 15: /* fall through */
16146 case 16:
16147 *mer = 15;
16148 break;
16149 case 17: /* fall through */
16150 case 18:
16151 *mer = 14;
16152 break;
16153 case 19: /* fall through */
16154 case 20:
16155 *mer = 13;
16156 break;
16157 case 21: /* fall through */
16158 case 22:
16159 *mer = 12;
16160 break;
16161 case 23: /* fall through */
16162 case 24: /* fall through */
16163 case 25:
16164 *mer = 11;
16165 break;
16166 case 26: /* fall through */
16167 case 27: /* fall through */
16168 case 28:
16169 *mer = 10;
16170 break;
16171 case 29: /* fall through */
16172 case 30: /* fall through */
16173 case 31: /* fall through */
16174 case 32:
16175 *mer = 9;
16176 break;
16177 case 33: /* fall through */
16178 case 34: /* fall through */
16179 case 35: /* fall through */
16180 case 36:
16181 *mer = 8;
16182 break;
16183 case 37: /* fall through */
16184 case 38: /* fall through */
16185 case 39: /* fall through */
16186 case 40:
16187 *mer = 7;
16188 break;
16189 case 41: /* fall through */
16190 case 42: /* fall through */
16191 case 43: /* fall through */
16192 case 44: /* fall through */
16193 case 45:
16194 *mer = 6;
16195 break;
16196 case 46: /* fall through */
16197 case 47: /* fall through */
16198 case 48: /* fall through */
16199 case 49: /* fall through */
16200 case 50: /* fall through */
16201 *mer = 5;
16202 break;
16203 case 51: /* fall through */
16204 case 52: /* fall through */
16205 case 53: /* fall through */
16206 case 54: /* fall through */
16207 case 55: /* fall through */
16208 case 56: /* fall through */
16209 case 57:
16210 *mer = 4;
16211 break;
16212 case 58: /* fall through */
16213 case 59: /* fall through */
16214 case 60: /* fall through */
16215 case 61: /* fall through */
16216 case 62: /* fall through */
16217 case 63:
16218 *mer = 0;
16219 break;
16220 default:
16221 *mer = 0;
16222 break;
16224 return 0;
16225 rw_error:
16226 return -EIO;
16228 #endif
16231 * \fn int set_orx_nsu_aox()
16232 * \brief Configure OrxNsuAox for OOB
16233 * \param demod instance of demodulator.
16234 * \param active
16235 * \return int.
16237 static int set_orx_nsu_aox(struct drx_demod_instance *demod, bool active)
16239 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
16240 int rc;
16241 u16 data = 0;
16243 /* Configure NSU_AOX */
16244 rc = DRXJ_DAP.read_reg16func(dev_addr, ORX_NSU_AOX_STDBY_W__A, &data, 0);
16245 if (rc != 0) {
16246 pr_err("error %d\n", rc);
16247 goto rw_error;
16249 if (!active)
16250 data &= ((~ORX_NSU_AOX_STDBY_W_STDBYADC_A2_ON) & (~ORX_NSU_AOX_STDBY_W_STDBYAMP_A2_ON) & (~ORX_NSU_AOX_STDBY_W_STDBYBIAS_A2_ON) & (~ORX_NSU_AOX_STDBY_W_STDBYPLL_A2_ON) & (~ORX_NSU_AOX_STDBY_W_STDBYPD_A2_ON) & (~ORX_NSU_AOX_STDBY_W_STDBYTAGC_IF_A2_ON) & (~ORX_NSU_AOX_STDBY_W_STDBYTAGC_RF_A2_ON) & (~ORX_NSU_AOX_STDBY_W_STDBYFLT_A2_ON));
16251 else
16252 data |= (ORX_NSU_AOX_STDBY_W_STDBYADC_A2_ON | ORX_NSU_AOX_STDBY_W_STDBYAMP_A2_ON | ORX_NSU_AOX_STDBY_W_STDBYBIAS_A2_ON | ORX_NSU_AOX_STDBY_W_STDBYPLL_A2_ON | ORX_NSU_AOX_STDBY_W_STDBYPD_A2_ON | ORX_NSU_AOX_STDBY_W_STDBYTAGC_IF_A2_ON | ORX_NSU_AOX_STDBY_W_STDBYTAGC_RF_A2_ON | ORX_NSU_AOX_STDBY_W_STDBYFLT_A2_ON);
16253 rc = DRXJ_DAP.write_reg16func(dev_addr, ORX_NSU_AOX_STDBY_W__A, data, 0);
16254 if (rc != 0) {
16255 pr_err("error %d\n", rc);
16256 goto rw_error;
16259 return 0;
16260 rw_error:
16261 return -EIO;
16265 * \fn int ctrl_set_oob()
16266 * \brief Set OOB channel to be used.
16267 * \param demod instance of demodulator
16268 * \param oob_param OOB parameters for channel setting.
16269 * \frequency should be in KHz
16270 * \return int.
16272 * Accepts only. Returns error otherwise.
16273 * Demapper value is written after scu_command START
16274 * because START command causes COMM_EXEC transition
16275 * from 0 to 1 which causes all registers to be
16276 * overwritten with initial value
16280 /* Nyquist filter impulse response */
16281 #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 */
16282 #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 */
16283 #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) */
16285 /* Coefficients for the nyquist fitler (total: 27 taps) */
16286 #define NYQFILTERLEN 27
16288 #if 0
16289 static int ctrl_set_oob(struct drx_demod_instance *demod, struct drxoob *oob_param)
16291 int rc;
16292 s32 freq = 0; /* KHz */
16293 struct i2c_device_addr *dev_addr = NULL;
16294 struct drxj_data *ext_attr = NULL;
16295 u16 i = 0;
16296 bool mirror_freq_spect_oob = false;
16297 u16 trk_filter_value = 0;
16298 struct drxjscu_cmd scu_cmd;
16299 u16 set_param_parameters[3];
16300 u16 cmd_result[2] = { 0, 0 };
16301 s16 nyquist_coeffs[4][(NYQFILTERLEN + 1) / 2] = {
16302 IMPULSE_COSINE_ALPHA_0_3, /* Target Mode 0 */
16303 IMPULSE_COSINE_ALPHA_0_3, /* Target Mode 1 */
16304 IMPULSE_COSINE_ALPHA_0_5, /* Target Mode 2 */
16305 IMPULSE_COSINE_ALPHA_RO_0_5 /* Target Mode 3 */
16307 u8 mode_val[4] = { 2, 2, 0, 1 };
16308 u8 pfi_coeffs[4][6] = {
16309 {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) */
16310 {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) */
16311 {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) */
16312 {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) */
16314 u16 mode_index;
16316 dev_addr = demod->my_i2c_dev_addr;
16317 ext_attr = (struct drxj_data *) demod->my_ext_attr;
16318 mirror_freq_spect_oob = ext_attr->mirror_freq_spect_oob;
16320 /* Check parameters */
16321 if (oob_param == NULL) {
16322 /* power off oob module */
16323 scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB
16324 | SCU_RAM_COMMAND_CMD_DEMOD_STOP;
16325 scu_cmd.parameter_len = 0;
16326 scu_cmd.result_len = 1;
16327 scu_cmd.result = cmd_result;
16328 rc = scu_command(dev_addr, &scu_cmd);
16329 if (rc != 0) {
16330 pr_err("error %d\n", rc);
16331 goto rw_error;
16333 rc = set_orx_nsu_aox(demod, false);
16334 if (rc != 0) {
16335 pr_err("error %d\n", rc);
16336 goto rw_error;
16338 rc = DRXJ_DAP.write_reg16func(dev_addr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_STOP, 0);
16339 if (rc != 0) {
16340 pr_err("error %d\n", rc);
16341 goto rw_error;
16344 ext_attr->oob_power_on = false;
16345 return 0;
16348 freq = oob_param->frequency;
16349 if ((freq < 70000) || (freq > 130000))
16350 return -EIO;
16351 freq = (freq - 50000) / 50;
16354 u16 index = 0;
16355 u16 remainder = 0;
16356 u16 *trk_filtercfg = ext_attr->oob_trk_filter_cfg;
16358 index = (u16) ((freq - 400) / 200);
16359 remainder = (u16) ((freq - 400) % 200);
16360 trk_filter_value =
16361 trk_filtercfg[index] - (trk_filtercfg[index] -
16362 trk_filtercfg[index +
16363 1]) / 10 * remainder /
16367 /*********/
16368 /* Stop */
16369 /*********/
16370 rc = DRXJ_DAP.write_reg16func(dev_addr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_STOP, 0);
16371 if (rc != 0) {
16372 pr_err("error %d\n", rc);
16373 goto rw_error;
16375 scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB
16376 | SCU_RAM_COMMAND_CMD_DEMOD_STOP;
16377 scu_cmd.parameter_len = 0;
16378 scu_cmd.result_len = 1;
16379 scu_cmd.result = cmd_result;
16380 rc = scu_command(dev_addr, &scu_cmd);
16381 if (rc != 0) {
16382 pr_err("error %d\n", rc);
16383 goto rw_error;
16385 /*********/
16386 /* Reset */
16387 /*********/
16388 scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB
16389 | SCU_RAM_COMMAND_CMD_DEMOD_RESET;
16390 scu_cmd.parameter_len = 0;
16391 scu_cmd.result_len = 1;
16392 scu_cmd.result = cmd_result;
16393 rc = scu_command(dev_addr, &scu_cmd);
16394 if (rc != 0) {
16395 pr_err("error %d\n", rc);
16396 goto rw_error;
16398 /***********/
16399 /* SET_ENV */
16400 /***********/
16401 /* set frequency, spectrum inversion and data rate */
16402 scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB
16403 | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV;
16404 scu_cmd.parameter_len = 3;
16405 /* 1-data rate;2-frequency */
16406 switch (oob_param->standard) {
16407 case DRX_OOB_MODE_A:
16408 if (
16409 /* signal is transmitted inverted */
16410 ((oob_param->spectrum_inverted == true) &
16411 /* and tuner is not mirroring the signal */
16412 (!mirror_freq_spect_oob)) |
16413 /* or */
16414 /* signal is transmitted noninverted */
16415 ((oob_param->spectrum_inverted == false) &
16416 /* and tuner is mirroring the signal */
16417 (mirror_freq_spect_oob))
16419 set_param_parameters[0] =
16420 SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC;
16421 else
16422 set_param_parameters[0] =
16423 SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC;
16424 break;
16425 case DRX_OOB_MODE_B_GRADE_A:
16426 if (
16427 /* signal is transmitted inverted */
16428 ((oob_param->spectrum_inverted == true) &
16429 /* and tuner is not mirroring the signal */
16430 (!mirror_freq_spect_oob)) |
16431 /* or */
16432 /* signal is transmitted noninverted */
16433 ((oob_param->spectrum_inverted == false) &
16434 /* and tuner is mirroring the signal */
16435 (mirror_freq_spect_oob))
16437 set_param_parameters[0] =
16438 SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_INVSPEC;
16439 else
16440 set_param_parameters[0] =
16441 SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_REGSPEC;
16442 break;
16443 case DRX_OOB_MODE_B_GRADE_B:
16444 default:
16445 if (
16446 /* signal is transmitted inverted */
16447 ((oob_param->spectrum_inverted == true) &
16448 /* and tuner is not mirroring the signal */
16449 (!mirror_freq_spect_oob)) |
16450 /* or */
16451 /* signal is transmitted noninverted */
16452 ((oob_param->spectrum_inverted == false) &
16453 /* and tuner is mirroring the signal */
16454 (mirror_freq_spect_oob))
16456 set_param_parameters[0] =
16457 SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_INVSPEC;
16458 else
16459 set_param_parameters[0] =
16460 SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_REGSPEC;
16461 break;
16463 set_param_parameters[1] = (u16) (freq & 0xFFFF);
16464 set_param_parameters[2] = trk_filter_value;
16465 scu_cmd.parameter = set_param_parameters;
16466 scu_cmd.result_len = 1;
16467 scu_cmd.result = cmd_result;
16468 mode_index = mode_val[(set_param_parameters[0] & 0xC0) >> 6];
16469 rc = scu_command(dev_addr, &scu_cmd);
16470 if (rc != 0) {
16471 pr_err("error %d\n", rc);
16472 goto rw_error;
16475 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA, 0);
16476 if (rc != 0) {
16477 pr_err("error %d\n", rc);
16478 goto rw_error;
16479 } /* Write magic word to enable pdr reg write */
16480 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_OOB_CRX_CFG__A, OOB_CRX_DRIVE_STRENGTH << SIO_PDR_OOB_CRX_CFG_DRIVE__B | 0x03 << SIO_PDR_OOB_CRX_CFG_MODE__B, 0);
16481 if (rc != 0) {
16482 pr_err("error %d\n", rc);
16483 goto rw_error;
16485 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_PDR_OOB_DRX_CFG__A, OOB_DRX_DRIVE_STRENGTH << SIO_PDR_OOB_DRX_CFG_DRIVE__B | 0x03 << SIO_PDR_OOB_DRX_CFG_MODE__B, 0);
16486 if (rc != 0) {
16487 pr_err("error %d\n", rc);
16488 goto rw_error;
16490 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
16491 if (rc != 0) {
16492 pr_err("error %d\n", rc);
16493 goto rw_error;
16494 } /* Write magic word to disable pdr reg write */
16496 rc = DRXJ_DAP.write_reg16func(dev_addr, ORX_TOP_COMM_KEY__A, 0, 0);
16497 if (rc != 0) {
16498 pr_err("error %d\n", rc);
16499 goto rw_error;
16501 rc = DRXJ_DAP.write_reg16func(dev_addr, ORX_FWP_AAG_LEN_W__A, 16000, 0);
16502 if (rc != 0) {
16503 pr_err("error %d\n", rc);
16504 goto rw_error;
16506 rc = DRXJ_DAP.write_reg16func(dev_addr, ORX_FWP_AAG_THR_W__A, 40, 0);
16507 if (rc != 0) {
16508 pr_err("error %d\n", rc);
16509 goto rw_error;
16512 /* ddc */
16513 rc = DRXJ_DAP.write_reg16func(dev_addr, ORX_DDC_OFO_SET_W__A, ORX_DDC_OFO_SET_W__PRE, 0);
16514 if (rc != 0) {
16515 pr_err("error %d\n", rc);
16516 goto rw_error;
16519 /* nsu */
16520 rc = DRXJ_DAP.write_reg16func(dev_addr, ORX_NSU_AOX_LOPOW_W__A, ext_attr->oob_lo_pow, 0);
16521 if (rc != 0) {
16522 pr_err("error %d\n", rc);
16523 goto rw_error;
16526 /* initialization for target mode */
16527 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_TARGET_MODE__A, SCU_RAM_ORX_TARGET_MODE_2048KBPS_SQRT, 0);
16528 if (rc != 0) {
16529 pr_err("error %d\n", rc);
16530 goto rw_error;
16532 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_FREQ_GAIN_CORR__A, SCU_RAM_ORX_FREQ_GAIN_CORR_2048KBPS, 0);
16533 if (rc != 0) {
16534 pr_err("error %d\n", rc);
16535 goto rw_error;
16538 /* Reset bits for timing and freq. recovery */
16539 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_RST_CPH__A, 0x0001, 0);
16540 if (rc != 0) {
16541 pr_err("error %d\n", rc);
16542 goto rw_error;
16544 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_RST_CTI__A, 0x0002, 0);
16545 if (rc != 0) {
16546 pr_err("error %d\n", rc);
16547 goto rw_error;
16549 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_RST_KRN__A, 0x0004, 0);
16550 if (rc != 0) {
16551 pr_err("error %d\n", rc);
16552 goto rw_error;
16554 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_RST_KRP__A, 0x0008, 0);
16555 if (rc != 0) {
16556 pr_err("error %d\n", rc);
16557 goto rw_error;
16560 /* AGN_LOCK = {2048>>3, -2048, 8, -8, 0, 1}; */
16561 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_AGN_LOCK_TH__A, 2048 >> 3, 0);
16562 if (rc != 0) {
16563 pr_err("error %d\n", rc);
16564 goto rw_error;
16566 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_AGN_LOCK_TOTH__A, (u16)(-2048), 0);
16567 if (rc != 0) {
16568 pr_err("error %d\n", rc);
16569 goto rw_error;
16571 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_AGN_ONLOCK_TTH__A, 8, 0);
16572 if (rc != 0) {
16573 pr_err("error %d\n", rc);
16574 goto rw_error;
16576 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_AGN_UNLOCK_TTH__A, (u16)(-8), 0);
16577 if (rc != 0) {
16578 pr_err("error %d\n", rc);
16579 goto rw_error;
16581 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_AGN_LOCK_MASK__A, 1, 0);
16582 if (rc != 0) {
16583 pr_err("error %d\n", rc);
16584 goto rw_error;
16587 /* DGN_LOCK = {10, -2048, 8, -8, 0, 1<<1}; */
16588 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_DGN_LOCK_TH__A, 10, 0);
16589 if (rc != 0) {
16590 pr_err("error %d\n", rc);
16591 goto rw_error;
16593 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_DGN_LOCK_TOTH__A, (u16)(-2048), 0);
16594 if (rc != 0) {
16595 pr_err("error %d\n", rc);
16596 goto rw_error;
16598 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_DGN_ONLOCK_TTH__A, 8, 0);
16599 if (rc != 0) {
16600 pr_err("error %d\n", rc);
16601 goto rw_error;
16603 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_DGN_UNLOCK_TTH__A, (u16)(-8), 0);
16604 if (rc != 0) {
16605 pr_err("error %d\n", rc);
16606 goto rw_error;
16608 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_DGN_LOCK_MASK__A, 1 << 1, 0);
16609 if (rc != 0) {
16610 pr_err("error %d\n", rc);
16611 goto rw_error;
16614 /* FRQ_LOCK = {15,-2048, 8, -8, 0, 1<<2}; */
16615 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_FRQ_LOCK_TH__A, 17, 0);
16616 if (rc != 0) {
16617 pr_err("error %d\n", rc);
16618 goto rw_error;
16620 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_FRQ_LOCK_TOTH__A, (u16)(-2048), 0);
16621 if (rc != 0) {
16622 pr_err("error %d\n", rc);
16623 goto rw_error;
16625 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_FRQ_ONLOCK_TTH__A, 8, 0);
16626 if (rc != 0) {
16627 pr_err("error %d\n", rc);
16628 goto rw_error;
16630 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_FRQ_UNLOCK_TTH__A, (u16)(-8), 0);
16631 if (rc != 0) {
16632 pr_err("error %d\n", rc);
16633 goto rw_error;
16635 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_FRQ_LOCK_MASK__A, 1 << 2, 0);
16636 if (rc != 0) {
16637 pr_err("error %d\n", rc);
16638 goto rw_error;
16641 /* PHA_LOCK = {5000, -2048, 8, -8, 0, 1<<3}; */
16642 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_PHA_LOCK_TH__A, 3000, 0);
16643 if (rc != 0) {
16644 pr_err("error %d\n", rc);
16645 goto rw_error;
16647 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_PHA_LOCK_TOTH__A, (u16)(-2048), 0);
16648 if (rc != 0) {
16649 pr_err("error %d\n", rc);
16650 goto rw_error;
16652 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_PHA_ONLOCK_TTH__A, 8, 0);
16653 if (rc != 0) {
16654 pr_err("error %d\n", rc);
16655 goto rw_error;
16657 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_PHA_UNLOCK_TTH__A, (u16)(-8), 0);
16658 if (rc != 0) {
16659 pr_err("error %d\n", rc);
16660 goto rw_error;
16662 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_PHA_LOCK_MASK__A, 1 << 3, 0);
16663 if (rc != 0) {
16664 pr_err("error %d\n", rc);
16665 goto rw_error;
16668 /* TIM_LOCK = {300, -2048, 8, -8, 0, 1<<4}; */
16669 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_TIM_LOCK_TH__A, 400, 0);
16670 if (rc != 0) {
16671 pr_err("error %d\n", rc);
16672 goto rw_error;
16674 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_TIM_LOCK_TOTH__A, (u16)(-2048), 0);
16675 if (rc != 0) {
16676 pr_err("error %d\n", rc);
16677 goto rw_error;
16679 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_TIM_ONLOCK_TTH__A, 8, 0);
16680 if (rc != 0) {
16681 pr_err("error %d\n", rc);
16682 goto rw_error;
16684 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_TIM_UNLOCK_TTH__A, (u16)(-8), 0);
16685 if (rc != 0) {
16686 pr_err("error %d\n", rc);
16687 goto rw_error;
16689 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_TIM_LOCK_MASK__A, 1 << 4, 0);
16690 if (rc != 0) {
16691 pr_err("error %d\n", rc);
16692 goto rw_error;
16695 /* EQU_LOCK = {20, -2048, 8, -8, 0, 1<<5}; */
16696 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_EQU_LOCK_TH__A, 20, 0);
16697 if (rc != 0) {
16698 pr_err("error %d\n", rc);
16699 goto rw_error;
16701 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_EQU_LOCK_TOTH__A, (u16)(-2048), 0);
16702 if (rc != 0) {
16703 pr_err("error %d\n", rc);
16704 goto rw_error;
16706 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_EQU_ONLOCK_TTH__A, 4, 0);
16707 if (rc != 0) {
16708 pr_err("error %d\n", rc);
16709 goto rw_error;
16711 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_EQU_UNLOCK_TTH__A, (u16)(-4), 0);
16712 if (rc != 0) {
16713 pr_err("error %d\n", rc);
16714 goto rw_error;
16716 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_ORX_EQU_LOCK_MASK__A, 1 << 5, 0);
16717 if (rc != 0) {
16718 pr_err("error %d\n", rc);
16719 goto rw_error;
16722 /* PRE-Filter coefficients (PFI) */
16723 rc = DRXJ_DAP.write_block_func(dev_addr, ORX_FWP_PFI_A_W__A, sizeof(pfi_coeffs[mode_index]), ((u8 *)pfi_coeffs[mode_index]), 0);
16724 if (rc != 0) {
16725 pr_err("error %d\n", rc);
16726 goto rw_error;
16728 rc = DRXJ_DAP.write_reg16func(dev_addr, ORX_TOP_MDE_W__A, mode_index, 0);
16729 if (rc != 0) {
16730 pr_err("error %d\n", rc);
16731 goto rw_error;
16734 /* NYQUIST-Filter coefficients (NYQ) */
16735 for (i = 0; i < (NYQFILTERLEN + 1) / 2; i++) {
16736 rc = DRXJ_DAP.write_reg16func(dev_addr, ORX_FWP_NYQ_ADR_W__A, i, 0);
16737 if (rc != 0) {
16738 pr_err("error %d\n", rc);
16739 goto rw_error;
16741 rc = DRXJ_DAP.write_reg16func(dev_addr, ORX_FWP_NYQ_COF_RW__A, nyquist_coeffs[mode_index][i], 0);
16742 if (rc != 0) {
16743 pr_err("error %d\n", rc);
16744 goto rw_error;
16747 rc = DRXJ_DAP.write_reg16func(dev_addr, ORX_FWP_NYQ_ADR_W__A, 31, 0);
16748 if (rc != 0) {
16749 pr_err("error %d\n", rc);
16750 goto rw_error;
16752 rc = DRXJ_DAP.write_reg16func(dev_addr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_ACTIVE, 0);
16753 if (rc != 0) {
16754 pr_err("error %d\n", rc);
16755 goto rw_error;
16757 /*********/
16758 /* Start */
16759 /*********/
16760 scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB
16761 | SCU_RAM_COMMAND_CMD_DEMOD_START;
16762 scu_cmd.parameter_len = 0;
16763 scu_cmd.result_len = 1;
16764 scu_cmd.result = cmd_result;
16765 rc = scu_command(dev_addr, &scu_cmd);
16766 if (rc != 0) {
16767 pr_err("error %d\n", rc);
16768 goto rw_error;
16771 rc = set_orx_nsu_aox(demod, true);
16772 if (rc != 0) {
16773 pr_err("error %d\n", rc);
16774 goto rw_error;
16776 rc = DRXJ_DAP.write_reg16func(dev_addr, ORX_NSU_AOX_STHR_W__A, ext_attr->oob_pre_saw, 0);
16777 if (rc != 0) {
16778 pr_err("error %d\n", rc);
16779 goto rw_error;
16782 ext_attr->oob_power_on = true;
16784 return 0;
16785 rw_error:
16786 return -EIO;
16790 * \fn int ctrl_get_oob()
16791 * \brief Set modulation standard to be used.
16792 * \param demod instance of demodulator
16793 * \param oob_status OOB status parameters.
16794 * \return int.
16796 static int
16797 ctrl_get_oob(struct drx_demod_instance *demod, struct drxoob_status *oob_status)
16799 int rc;
16800 struct i2c_device_addr *dev_addr = NULL;
16801 struct drxj_data *ext_attr = NULL;
16802 u16 data = 0;
16804 dev_addr = demod->my_i2c_dev_addr;
16805 ext_attr = (struct drxj_data *) demod->my_ext_attr;
16807 /* check arguments */
16808 if (oob_status == NULL)
16809 return -EINVAL;
16811 if (!ext_attr->oob_power_on)
16812 return -EIO;
16814 rc = DRXJ_DAP.read_reg16func(dev_addr, ORX_DDC_OFO_SET_W__A, &data, 0);
16815 if (rc != 0) {
16816 pr_err("error %d\n", rc);
16817 goto rw_error;
16819 rc = DRXJ_DAP.read_reg16func(dev_addr, ORX_NSU_TUN_RFGAIN_W__A, &data, 0);
16820 if (rc != 0) {
16821 pr_err("error %d\n", rc);
16822 goto rw_error;
16824 rc = DRXJ_DAP.read_reg16func(dev_addr, ORX_FWP_AAG_THR_W__A, &data, 0);
16825 if (rc != 0) {
16826 pr_err("error %d\n", rc);
16827 goto rw_error;
16829 rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_ORX_DGN_KI__A, &data, 0);
16830 if (rc != 0) {
16831 pr_err("error %d\n", rc);
16832 goto rw_error;
16834 rc = DRXJ_DAP.read_reg16func(dev_addr, ORX_FWP_SRC_DGN_W__A, &data, 0);
16835 if (rc != 0) {
16836 pr_err("error %d\n", rc);
16837 goto rw_error;
16840 rc = get_oob_lock_status(demod, dev_addr, &oob_status->lock);
16841 if (rc != 0) {
16842 pr_err("error %d\n", rc);
16843 goto rw_error;
16845 rc = get_oob_frequency(demod, &oob_status->frequency);
16846 if (rc != 0) {
16847 pr_err("error %d\n", rc);
16848 goto rw_error;
16850 rc = get_oobmer(dev_addr, &oob_status->mer);
16851 if (rc != 0) {
16852 pr_err("error %d\n", rc);
16853 goto rw_error;
16855 rc = get_oob_symbol_rate_offset(dev_addr, &oob_status->symbol_rate_offset);
16856 if (rc != 0) {
16857 pr_err("error %d\n", rc);
16858 goto rw_error;
16861 return 0;
16862 rw_error:
16863 return -EIO;
16867 * \fn int ctrl_set_cfg_oob_pre_saw()
16868 * \brief Configure PreSAW treshold value
16869 * \param cfg_data Pointer to configuration parameter
16870 * \return Error code
16872 static int
16873 ctrl_set_cfg_oob_pre_saw(struct drx_demod_instance *demod, u16 *cfg_data)
16875 struct i2c_device_addr *dev_addr = NULL;
16876 struct drxj_data *ext_attr = NULL;
16877 int rc;
16879 if (cfg_data == NULL)
16880 return -EINVAL;
16882 dev_addr = demod->my_i2c_dev_addr;
16883 ext_attr = (struct drxj_data *) demod->my_ext_attr;
16885 rc = DRXJ_DAP.write_reg16func(dev_addr, ORX_NSU_AOX_STHR_W__A, *cfg_data, 0);
16886 if (rc != 0) {
16887 pr_err("error %d\n", rc);
16888 goto rw_error;
16890 ext_attr->oob_pre_saw = *cfg_data;
16891 return 0;
16892 rw_error:
16893 return -EIO;
16897 * \fn int ctrl_get_cfg_oob_pre_saw()
16898 * \brief Configure PreSAW treshold value
16899 * \param cfg_data Pointer to configuration parameter
16900 * \return Error code
16902 static int
16903 ctrl_get_cfg_oob_pre_saw(struct drx_demod_instance *demod, u16 *cfg_data)
16905 struct drxj_data *ext_attr = NULL;
16907 if (cfg_data == NULL)
16908 return -EINVAL;
16910 ext_attr = (struct drxj_data *) demod->my_ext_attr;
16912 *cfg_data = ext_attr->oob_pre_saw;
16914 return 0;
16918 * \fn int ctrl_set_cfg_oob_lo_power()
16919 * \brief Configure LO Power value
16920 * \param cfg_data Pointer to enum drxj_cfg_oob_lo_power ** \return Error code
16922 static int
16923 ctrl_set_cfg_oob_lo_power(struct drx_demod_instance *demod, enum drxj_cfg_oob_lo_power *cfg_data)
16925 struct i2c_device_addr *dev_addr = NULL;
16926 struct drxj_data *ext_attr = NULL;
16927 int rc;
16929 if (cfg_data == NULL)
16930 return -EINVAL;
16932 dev_addr = demod->my_i2c_dev_addr;
16933 ext_attr = (struct drxj_data *) demod->my_ext_attr;
16935 rc = DRXJ_DAP.write_reg16func(dev_addr, ORX_NSU_AOX_LOPOW_W__A, *cfg_data, 0);
16936 if (rc != 0) {
16937 pr_err("error %d\n", rc);
16938 goto rw_error;
16940 ext_attr->oob_lo_pow = *cfg_data;
16941 return 0;
16942 rw_error:
16943 return -EIO;
16947 * \fn int ctrl_get_cfg_oob_lo_power()
16948 * \brief Configure LO Power value
16949 * \param cfg_data Pointer to enum drxj_cfg_oob_lo_power ** \return Error code
16951 static int
16952 ctrl_get_cfg_oob_lo_power(struct drx_demod_instance *demod, enum drxj_cfg_oob_lo_power *cfg_data)
16954 struct drxj_data *ext_attr = NULL;
16956 if (cfg_data == NULL)
16957 return -EINVAL;
16959 ext_attr = (struct drxj_data *) demod->my_ext_attr;
16961 *cfg_data = ext_attr->oob_lo_pow;
16963 return 0;
16965 #endif
16966 /*============================================================================*/
16967 /*== END OOB DATAPATH FUNCTIONS ==*/
16968 /*============================================================================*/
16970 /*=============================================================================
16971 ===== MC command related functions ==========================================
16972 ===========================================================================*/
16974 /*=============================================================================
16975 ===== ctrl_set_channel() ==========================================================
16976 ===========================================================================*/
16978 * \fn int ctrl_set_channel()
16979 * \brief Select a new transmission channel.
16980 * \param demod instance of demod.
16981 * \param channel Pointer to channel data.
16982 * \return int.
16984 * In case the tuner module is not used and in case of NTSC/FM the pogrammer
16985 * must tune the tuner to the centre frequency of the NTSC/FM channel.
16988 static int
16989 ctrl_set_channel(struct drx_demod_instance *demod, struct drx_channel *channel)
16991 int rc;
16992 s32 tuner_freq_offset = 0;
16993 s32 intermediate_freq = 0;
16994 struct drxj_data *ext_attr = NULL;
16995 struct i2c_device_addr *dev_addr = NULL;
16996 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
16997 struct drx_common_attr *common_attr = NULL;
16998 #ifndef DRXJ_VSB_ONLY
16999 u32 min_symbol_rate = 0;
17000 u32 max_symbol_rate = 0;
17001 int bandwidth_temp = 0;
17002 int bandwidth = 0;
17003 #endif
17004 /*== check arguments ======================================================*/
17005 if ((demod == NULL) || (channel == NULL))
17006 return -EINVAL;
17008 common_attr = (struct drx_common_attr *) demod->my_common_attr;
17009 dev_addr = demod->my_i2c_dev_addr;
17010 ext_attr = (struct drxj_data *) demod->my_ext_attr;
17011 standard = ext_attr->standard;
17013 /* check valid standards */
17014 switch (standard) {
17015 case DRX_STANDARD_8VSB:
17016 #ifndef DRXJ_VSB_ONLY
17017 case DRX_STANDARD_ITU_A:
17018 case DRX_STANDARD_ITU_B:
17019 case DRX_STANDARD_ITU_C:
17020 #endif /* DRXJ_VSB_ONLY */
17021 #if 0
17022 case DRX_STANDARD_NTSC:
17023 case DRX_STANDARD_FM:
17024 case DRX_STANDARD_PAL_SECAM_BG:
17025 case DRX_STANDARD_PAL_SECAM_DK:
17026 case DRX_STANDARD_PAL_SECAM_I:
17027 case DRX_STANDARD_PAL_SECAM_L:
17028 case DRX_STANDARD_PAL_SECAM_LP:
17029 #endif
17030 break;
17031 case DRX_STANDARD_UNKNOWN:
17032 default:
17033 return -EINVAL;
17036 /* check bandwidth QAM annex B, NTSC and 8VSB */
17037 if ((standard == DRX_STANDARD_ITU_B) ||
17038 (standard == DRX_STANDARD_8VSB) ||
17039 (standard == DRX_STANDARD_NTSC)) {
17040 switch (channel->bandwidth) {
17041 case DRX_BANDWIDTH_6MHZ:
17042 case DRX_BANDWIDTH_UNKNOWN: /* fall through */
17043 channel->bandwidth = DRX_BANDWIDTH_6MHZ;
17044 break;
17045 case DRX_BANDWIDTH_8MHZ: /* fall through */
17046 case DRX_BANDWIDTH_7MHZ: /* fall through */
17047 default:
17048 return -EINVAL;
17051 #if 0
17052 if (standard == DRX_STANDARD_PAL_SECAM_BG) {
17053 switch (channel->bandwidth) {
17054 case DRX_BANDWIDTH_7MHZ: /* fall through */
17055 case DRX_BANDWIDTH_8MHZ:
17056 /* ok */
17057 break;
17058 case DRX_BANDWIDTH_6MHZ: /* fall through */
17059 case DRX_BANDWIDTH_UNKNOWN: /* fall through */
17060 default:
17061 return -EINVAL;
17064 /* check bandwidth PAL/SECAM */
17065 if ((standard == DRX_STANDARD_PAL_SECAM_BG) ||
17066 (standard == DRX_STANDARD_PAL_SECAM_DK) ||
17067 (standard == DRX_STANDARD_PAL_SECAM_I) ||
17068 (standard == DRX_STANDARD_PAL_SECAM_L) ||
17069 (standard == DRX_STANDARD_PAL_SECAM_LP)) {
17070 switch (channel->bandwidth) {
17071 case DRX_BANDWIDTH_8MHZ:
17072 case DRX_BANDWIDTH_UNKNOWN: /* fall through */
17073 channel->bandwidth = DRX_BANDWIDTH_8MHZ;
17074 break;
17075 case DRX_BANDWIDTH_6MHZ: /* fall through */
17076 case DRX_BANDWIDTH_7MHZ: /* fall through */
17077 default:
17078 return -EINVAL;
17081 #endif
17083 /* For QAM annex A and annex C:
17084 -check symbolrate and constellation
17085 -derive bandwidth from symbolrate (input bandwidth is ignored)
17087 #ifndef DRXJ_VSB_ONLY
17088 if ((standard == DRX_STANDARD_ITU_A) ||
17089 (standard == DRX_STANDARD_ITU_C)) {
17090 struct drxuio_cfg uio_cfg = { DRX_UIO1, DRX_UIO_MODE_FIRMWARE_SAW };
17091 int bw_rolloff_factor = 0;
17093 bw_rolloff_factor = (standard == DRX_STANDARD_ITU_A) ? 115 : 113;
17094 min_symbol_rate = DRXJ_QAM_SYMBOLRATE_MIN;
17095 max_symbol_rate = DRXJ_QAM_SYMBOLRATE_MAX;
17096 /* config SMA_TX pin to SAW switch mode */
17097 rc = ctrl_set_uio_cfg(demod, &uio_cfg);
17098 if (rc != 0) {
17099 pr_err("error %d\n", rc);
17100 goto rw_error;
17103 if (channel->symbolrate < min_symbol_rate ||
17104 channel->symbolrate > max_symbol_rate) {
17105 return -EINVAL;
17108 switch (channel->constellation) {
17109 case DRX_CONSTELLATION_QAM16: /* fall through */
17110 case DRX_CONSTELLATION_QAM32: /* fall through */
17111 case DRX_CONSTELLATION_QAM64: /* fall through */
17112 case DRX_CONSTELLATION_QAM128: /* fall through */
17113 case DRX_CONSTELLATION_QAM256:
17114 bandwidth_temp = channel->symbolrate * bw_rolloff_factor;
17115 bandwidth = bandwidth_temp / 100;
17117 if ((bandwidth_temp % 100) >= 50)
17118 bandwidth++;
17120 if (bandwidth <= 6100000) {
17121 channel->bandwidth = DRX_BANDWIDTH_6MHZ;
17122 } else if ((bandwidth > 6100000)
17123 && (bandwidth <= 7100000)) {
17124 channel->bandwidth = DRX_BANDWIDTH_7MHZ;
17125 } else if (bandwidth > 7100000) {
17126 channel->bandwidth = DRX_BANDWIDTH_8MHZ;
17128 break;
17129 default:
17130 return -EINVAL;
17134 /* For QAM annex B:
17135 -check constellation
17137 if (standard == DRX_STANDARD_ITU_B) {
17138 switch (channel->constellation) {
17139 case DRX_CONSTELLATION_AUTO:
17140 case DRX_CONSTELLATION_QAM256:
17141 case DRX_CONSTELLATION_QAM64:
17142 break;
17143 default:
17144 return -EINVAL;
17147 switch (channel->interleavemode) {
17148 case DRX_INTERLEAVEMODE_I128_J1:
17149 case DRX_INTERLEAVEMODE_I128_J1_V2:
17150 case DRX_INTERLEAVEMODE_I128_J2:
17151 case DRX_INTERLEAVEMODE_I64_J2:
17152 case DRX_INTERLEAVEMODE_I128_J3:
17153 case DRX_INTERLEAVEMODE_I32_J4:
17154 case DRX_INTERLEAVEMODE_I128_J4:
17155 case DRX_INTERLEAVEMODE_I16_J8:
17156 case DRX_INTERLEAVEMODE_I128_J5:
17157 case DRX_INTERLEAVEMODE_I8_J16:
17158 case DRX_INTERLEAVEMODE_I128_J6:
17159 case DRX_INTERLEAVEMODE_I128_J7:
17160 case DRX_INTERLEAVEMODE_I128_J8:
17161 case DRX_INTERLEAVEMODE_I12_J17:
17162 case DRX_INTERLEAVEMODE_I5_J4:
17163 case DRX_INTERLEAVEMODE_B52_M240:
17164 case DRX_INTERLEAVEMODE_B52_M720:
17165 case DRX_INTERLEAVEMODE_UNKNOWN:
17166 case DRX_INTERLEAVEMODE_AUTO:
17167 break;
17168 default:
17169 return -EINVAL;
17173 if ((ext_attr->uio_sma_tx_mode) == DRX_UIO_MODE_FIRMWARE_SAW) {
17174 /* SAW SW, user UIO is used for switchable SAW */
17175 struct drxuio_data uio1 = { DRX_UIO1, false };
17177 switch (channel->bandwidth) {
17178 case DRX_BANDWIDTH_8MHZ:
17179 uio1.value = true;
17180 break;
17181 case DRX_BANDWIDTH_7MHZ:
17182 uio1.value = false;
17183 break;
17184 case DRX_BANDWIDTH_6MHZ:
17185 uio1.value = false;
17186 break;
17187 case DRX_BANDWIDTH_UNKNOWN:
17188 default:
17189 return -EINVAL;
17192 rc = ctrl_uio_write(demod, &uio1);
17193 if (rc != 0) {
17194 pr_err("error %d\n", rc);
17195 goto rw_error;
17198 #endif /* DRXJ_VSB_ONLY */
17199 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE, 0);
17200 if (rc != 0) {
17201 pr_err("error %d\n", rc);
17202 goto rw_error;
17205 tuner_freq_offset = 0;
17206 intermediate_freq = demod->my_common_attr->intermediate_freq;
17208 /*== Setup demod for specific standard ====================================*/
17209 switch (standard) {
17210 case DRX_STANDARD_8VSB:
17211 if (channel->mirror == DRX_MIRROR_AUTO)
17212 ext_attr->mirror = DRX_MIRROR_NO;
17213 else
17214 ext_attr->mirror = channel->mirror;
17215 rc = set_vsb(demod);
17216 if (rc != 0) {
17217 pr_err("error %d\n", rc);
17218 goto rw_error;
17220 rc = set_frequency(demod, channel, tuner_freq_offset);
17221 if (rc != 0) {
17222 pr_err("error %d\n", rc);
17223 goto rw_error;
17225 break;
17226 #if 0
17227 case DRX_STANDARD_NTSC: /* fallthrough */
17228 case DRX_STANDARD_FM: /* fallthrough */
17229 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
17230 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
17231 case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
17232 case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */
17233 case DRX_STANDARD_PAL_SECAM_LP:
17234 if (channel->mirror == DRX_MIRROR_AUTO)
17235 ext_attr->mirror = DRX_MIRROR_NO;
17236 else
17237 ext_attr->mirror = channel->mirror;
17238 rc = set_atv_channel(demod, tuner_freq_offset, channel, standard);
17239 if (rc != 0) {
17240 pr_err("error %d\n", rc);
17241 goto rw_error;
17243 break;
17244 #endif
17245 #ifndef DRXJ_VSB_ONLY
17246 case DRX_STANDARD_ITU_A: /* fallthrough */
17247 case DRX_STANDARD_ITU_B: /* fallthrough */
17248 case DRX_STANDARD_ITU_C:
17249 rc = set_qam_channel(demod, channel, tuner_freq_offset);
17250 if (rc != 0) {
17251 pr_err("error %d\n", rc);
17252 goto rw_error;
17254 break;
17255 #endif
17256 case DRX_STANDARD_UNKNOWN:
17257 default:
17258 return -EIO;
17261 /* flag the packet error counter reset */
17262 ext_attr->reset_pkt_err_acc = true;
17264 return 0;
17265 rw_error:
17266 return -EIO;
17269 #if 0
17270 /*=============================================================================
17271 ===== ctrl_get_channel() ==========================================================
17272 ===========================================================================*/
17274 * \fn int ctrl_get_channel()
17275 * \brief Retreive parameters of current transmission channel.
17276 * \param demod Pointer to demod instance.
17277 * \param channel Pointer to channel data.
17278 * \return int.
17280 static int
17281 ctrl_get_channel(struct drx_demod_instance *demod, struct drx_channel *channel)
17283 struct i2c_device_addr *dev_addr = NULL;
17284 struct drxj_data *ext_attr = NULL;
17285 int rc;
17286 enum drx_lock_status lock_status = DRX_NOT_LOCKED;
17287 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
17288 struct drx_common_attr *common_attr = NULL;
17289 s32 intermediate_freq = 0;
17290 s32 ctl_freq_offset = 0;
17291 u32 iqm_rc_rate_lo = 0;
17292 u32 adc_frequency = 0;
17293 #ifndef DRXJ_VSB_ONLY
17294 int bandwidth_temp = 0;
17295 int bandwidth = 0;
17296 #endif
17298 /* check arguments */
17299 if ((demod == NULL) || (channel == NULL))
17300 return -EINVAL;
17302 dev_addr = demod->my_i2c_dev_addr;
17303 ext_attr = (struct drxj_data *) demod->my_ext_attr;
17304 standard = ext_attr->standard;
17305 common_attr = (struct drx_common_attr *) demod->my_common_attr;
17307 /* initialize channel fields */
17308 channel->mirror = DRX_MIRROR_UNKNOWN;
17309 channel->hierarchy = DRX_HIERARCHY_UNKNOWN;
17310 channel->priority = DRX_PRIORITY_UNKNOWN;
17311 channel->coderate = DRX_CODERATE_UNKNOWN;
17312 channel->guard = DRX_GUARD_UNKNOWN;
17313 channel->fftmode = DRX_FFTMODE_UNKNOWN;
17314 channel->classification = DRX_CLASSIFICATION_UNKNOWN;
17315 channel->bandwidth = DRX_BANDWIDTH_UNKNOWN;
17316 channel->constellation = DRX_CONSTELLATION_UNKNOWN;
17317 channel->symbolrate = 0;
17318 channel->interleavemode = DRX_INTERLEAVEMODE_UNKNOWN;
17319 channel->carrier = DRX_CARRIER_UNKNOWN;
17320 channel->framemode = DRX_FRAMEMODE_UNKNOWN;
17321 /* channel->interleaver = DRX_INTERLEAVER_UNKNOWN;*/
17322 channel->ldpc = DRX_LDPC_UNKNOWN;
17324 intermediate_freq = common_attr->intermediate_freq;
17326 /* check lock status */
17327 rc = ctrl_lock_status(demod, &lock_status);
17328 if (rc != 0) {
17329 pr_err("error %d\n", rc);
17330 goto rw_error;
17332 if ((lock_status == DRX_LOCKED) || (lock_status == DRXJ_DEMOD_LOCK)) {
17333 rc = drxj_dap_atomic_read_reg32(dev_addr, IQM_RC_RATE_LO__A, &iqm_rc_rate_lo, 0);
17334 if (rc != 0) {
17335 pr_err("error %d\n", rc);
17336 goto rw_error;
17338 adc_frequency = (common_attr->sys_clock_freq * 1000) / 3;
17340 channel->symbolrate =
17341 frac28(adc_frequency, (iqm_rc_rate_lo + (1 << 23))) >> 7;
17343 switch (standard) {
17344 case DRX_STANDARD_8VSB:
17345 channel->bandwidth = DRX_BANDWIDTH_6MHZ;
17346 /* get the channel frequency */
17347 rc = get_ctl_freq_offset(demod, &ctl_freq_offset);
17348 if (rc != 0) {
17349 pr_err("error %d\n", rc);
17350 goto rw_error;
17352 channel->frequency -= ctl_freq_offset;
17353 /* get the channel constellation */
17354 channel->constellation = DRX_CONSTELLATION_AUTO;
17355 break;
17356 #ifndef DRXJ_VSB_ONLY
17357 case DRX_STANDARD_ITU_A:
17358 case DRX_STANDARD_ITU_B:
17359 case DRX_STANDARD_ITU_C:
17361 /* get the channel frequency */
17362 rc = get_ctl_freq_offset(demod, &ctl_freq_offset);
17363 if (rc != 0) {
17364 pr_err("error %d\n", rc);
17365 goto rw_error;
17367 channel->frequency -= ctl_freq_offset;
17369 if (standard == DRX_STANDARD_ITU_B) {
17370 channel->bandwidth = DRX_BANDWIDTH_6MHZ;
17371 } else {
17372 /* annex A & C */
17374 u32 roll_off = 113; /* default annex C */
17376 if (standard == DRX_STANDARD_ITU_A)
17377 roll_off = 115;
17379 bandwidth_temp =
17380 channel->symbolrate * roll_off;
17381 bandwidth = bandwidth_temp / 100;
17383 if ((bandwidth_temp % 100) >= 50)
17384 bandwidth++;
17386 if (bandwidth <= 6000000) {
17387 channel->bandwidth =
17388 DRX_BANDWIDTH_6MHZ;
17389 } else if ((bandwidth > 6000000)
17390 && (bandwidth <= 7000000)) {
17391 channel->bandwidth =
17392 DRX_BANDWIDTH_7MHZ;
17393 } else if (bandwidth > 7000000) {
17394 channel->bandwidth =
17395 DRX_BANDWIDTH_8MHZ;
17397 } /* if (standard == DRX_STANDARD_ITU_B) */
17400 struct drxjscu_cmd cmd_scu = { 0, 0, 0, NULL, NULL };
17401 u16 cmd_result[3] = { 0, 0, 0 };
17403 cmd_scu.command =
17404 SCU_RAM_COMMAND_STANDARD_QAM |
17405 SCU_RAM_COMMAND_CMD_DEMOD_GET_PARAM;
17406 cmd_scu.parameter_len = 0;
17407 cmd_scu.result_len = 3;
17408 cmd_scu.parameter = NULL;
17409 cmd_scu.result = cmd_result;
17410 rc = scu_command(dev_addr, &cmd_scu);
17411 if (rc != 0) {
17412 pr_err("error %d\n", rc);
17413 goto rw_error;
17416 channel->interleavemode =
17417 (enum drx_interleave_mode) (cmd_scu.
17418 result[2]);
17421 switch (ext_attr->constellation) {
17422 case DRX_CONSTELLATION_QAM256:
17423 channel->constellation =
17424 DRX_CONSTELLATION_QAM256;
17425 break;
17426 case DRX_CONSTELLATION_QAM128:
17427 channel->constellation =
17428 DRX_CONSTELLATION_QAM128;
17429 break;
17430 case DRX_CONSTELLATION_QAM64:
17431 channel->constellation =
17432 DRX_CONSTELLATION_QAM64;
17433 break;
17434 case DRX_CONSTELLATION_QAM32:
17435 channel->constellation =
17436 DRX_CONSTELLATION_QAM32;
17437 break;
17438 case DRX_CONSTELLATION_QAM16:
17439 channel->constellation =
17440 DRX_CONSTELLATION_QAM16;
17441 break;
17442 default:
17443 channel->constellation =
17444 DRX_CONSTELLATION_UNKNOWN;
17445 return -EIO;
17448 break;
17449 #endif
17450 case DRX_STANDARD_NTSC: /* fall trough */
17451 case DRX_STANDARD_PAL_SECAM_BG:
17452 case DRX_STANDARD_PAL_SECAM_DK:
17453 case DRX_STANDARD_PAL_SECAM_I:
17454 case DRX_STANDARD_PAL_SECAM_L:
17455 case DRX_STANDARD_PAL_SECAM_LP:
17456 case DRX_STANDARD_FM:
17457 rc = get_atv_channel(demod, channel, standard);
17458 if (rc != 0) {
17459 pr_err("error %d\n", rc);
17460 goto rw_error;
17462 break;
17463 case DRX_STANDARD_UNKNOWN: /* fall trough */
17464 default:
17465 return -EIO;
17466 } /* switch ( standard ) */
17468 if (lock_status == DRX_LOCKED)
17469 channel->mirror = ext_attr->mirror;
17471 /* if ( lock_status == DRX_LOCKED ) */
17472 return 0;
17473 rw_error:
17474 return -EIO;
17476 #endif
17478 /*=============================================================================
17479 ===== SigQuality() ==========================================================
17480 ===========================================================================*/
17482 static u16
17483 mer2indicator(u16 mer, u16 min_mer, u16 threshold_mer, u16 max_mer)
17485 u16 indicator = 0;
17487 if (mer < min_mer) {
17488 indicator = 0;
17489 } else if (mer < threshold_mer) {
17490 if ((threshold_mer - min_mer) != 0)
17491 indicator = 25 * (mer - min_mer) / (threshold_mer - min_mer);
17492 } else if (mer < max_mer) {
17493 if ((max_mer - threshold_mer) != 0)
17494 indicator = 25 + 75 * (mer - threshold_mer) / (max_mer - threshold_mer);
17495 else
17496 indicator = 25;
17497 } else {
17498 indicator = 100;
17501 return indicator;
17505 * \fn int ctrl_sig_quality()
17506 * \brief Retreive signal quality form device.
17507 * \param devmod Pointer to demodulator instance.
17508 * \param sig_quality Pointer to signal quality data.
17509 * \return int.
17510 * \retval 0 sig_quality contains valid data.
17511 * \retval -EINVAL sig_quality is NULL.
17512 * \retval -EIO Erroneous data, sig_quality contains invalid data.
17515 static int
17516 ctrl_sig_quality(struct drx_demod_instance *demod, struct drx_sig_quality *sig_quality)
17518 struct i2c_device_addr *dev_addr = NULL;
17519 struct drxj_data *ext_attr = NULL;
17520 int rc;
17521 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
17522 enum drx_lock_status lock_status = DRX_NOT_LOCKED;
17523 u16 min_mer = 0;
17524 u16 max_mer = 0;
17525 u16 threshold_mer = 0;
17527 /* Check arguments */
17528 if ((sig_quality == NULL) || (demod == NULL))
17529 return -EINVAL;
17531 ext_attr = (struct drxj_data *) demod->my_ext_attr;
17532 standard = ext_attr->standard;
17534 /* get basic information */
17535 dev_addr = demod->my_i2c_dev_addr;
17536 rc = ctrl_lock_status(demod, &lock_status);
17537 if (rc != 0) {
17538 pr_err("error %d\n", rc);
17539 goto rw_error;
17541 switch (standard) {
17542 case DRX_STANDARD_8VSB:
17543 #ifdef DRXJ_SIGNAL_ACCUM_ERR
17544 rc = get_acc_pkt_err(demod, &sig_quality->packet_error);
17545 if (rc != 0) {
17546 pr_err("error %d\n", rc);
17547 goto rw_error;
17549 #else
17550 rc = get_vsb_post_rs_pck_err(dev_addr, &sig_quality->packet_error);
17551 if (rc != 0) {
17552 pr_err("error %d\n", rc);
17553 goto rw_error;
17555 #endif
17556 if (lock_status != DRXJ_DEMOD_LOCK && lock_status != DRX_LOCKED) {
17557 sig_quality->post_viterbi_ber = 500000;
17558 sig_quality->MER = 20;
17559 sig_quality->pre_viterbi_ber = 0;
17560 } else {
17561 /* PostViterbi is compute in steps of 10^(-6) */
17562 rc = get_vs_bpre_viterbi_ber(dev_addr, &sig_quality->pre_viterbi_ber);
17563 if (rc != 0) {
17564 pr_err("error %d\n", rc);
17565 goto rw_error;
17567 rc = get_vs_bpost_viterbi_ber(dev_addr, &sig_quality->post_viterbi_ber);
17568 if (rc != 0) {
17569 pr_err("error %d\n", rc);
17570 goto rw_error;
17572 rc = get_vsbmer(dev_addr, &sig_quality->MER);
17573 if (rc != 0) {
17574 pr_err("error %d\n", rc);
17575 goto rw_error;
17578 min_mer = 20;
17579 max_mer = 360;
17580 threshold_mer = 145;
17581 sig_quality->post_reed_solomon_ber = 0;
17582 sig_quality->scale_factor_ber = 1000000;
17583 sig_quality->indicator =
17584 mer2indicator(sig_quality->MER, min_mer, threshold_mer,
17585 max_mer);
17586 break;
17587 #ifndef DRXJ_VSB_ONLY
17588 case DRX_STANDARD_ITU_A:
17589 case DRX_STANDARD_ITU_B:
17590 case DRX_STANDARD_ITU_C:
17591 rc = ctrl_get_qam_sig_quality(demod, sig_quality);
17592 if (rc != 0) {
17593 pr_err("error %d\n", rc);
17594 goto rw_error;
17596 if (lock_status != DRXJ_DEMOD_LOCK && lock_status != DRX_LOCKED) {
17597 switch (ext_attr->constellation) {
17598 case DRX_CONSTELLATION_QAM256:
17599 sig_quality->MER = 210;
17600 break;
17601 case DRX_CONSTELLATION_QAM128:
17602 sig_quality->MER = 180;
17603 break;
17604 case DRX_CONSTELLATION_QAM64:
17605 sig_quality->MER = 150;
17606 break;
17607 case DRX_CONSTELLATION_QAM32:
17608 sig_quality->MER = 120;
17609 break;
17610 case DRX_CONSTELLATION_QAM16:
17611 sig_quality->MER = 90;
17612 break;
17613 default:
17614 sig_quality->MER = 0;
17615 return -EIO;
17619 switch (ext_attr->constellation) {
17620 case DRX_CONSTELLATION_QAM256:
17621 min_mer = 210;
17622 threshold_mer = 270;
17623 max_mer = 380;
17624 break;
17625 case DRX_CONSTELLATION_QAM64:
17626 min_mer = 150;
17627 threshold_mer = 210;
17628 max_mer = 380;
17629 break;
17630 case DRX_CONSTELLATION_QAM128:
17631 case DRX_CONSTELLATION_QAM32:
17632 case DRX_CONSTELLATION_QAM16:
17633 break;
17634 default:
17635 return -EIO;
17637 sig_quality->indicator =
17638 mer2indicator(sig_quality->MER, min_mer, threshold_mer,
17639 max_mer);
17640 break;
17641 #endif
17642 #if 0
17643 case DRX_STANDARD_PAL_SECAM_BG:
17644 case DRX_STANDARD_PAL_SECAM_DK:
17645 case DRX_STANDARD_PAL_SECAM_I:
17646 case DRX_STANDARD_PAL_SECAM_L:
17647 case DRX_STANDARD_PAL_SECAM_LP:
17648 case DRX_STANDARD_NTSC:
17649 rc = atv_sig_quality(demod, sig_quality);
17650 if (rc != 0) {
17651 pr_err("error %d\n", rc);
17652 goto rw_error;
17654 break;
17655 case DRX_STANDARD_FM:
17656 rc = fm_sig_quality(demod, sig_quality);
17657 if (rc != 0) {
17658 pr_err("error %d\n", rc);
17659 goto rw_error;
17661 break;
17662 #endif
17663 default:
17664 return -EIO;
17667 return 0;
17668 rw_error:
17669 return -EIO;
17672 /*============================================================================*/
17675 * \fn int ctrl_lock_status()
17676 * \brief Retreive lock status .
17677 * \param dev_addr Pointer to demodulator device address.
17678 * \param lock_stat Pointer to lock status structure.
17679 * \return int.
17682 static int
17683 ctrl_lock_status(struct drx_demod_instance *demod, enum drx_lock_status *lock_stat)
17685 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
17686 struct drxj_data *ext_attr = NULL;
17687 struct i2c_device_addr *dev_addr = NULL;
17688 struct drxjscu_cmd cmd_scu = { /* command */ 0,
17689 /* parameter_len */ 0,
17690 /* result_len */ 0,
17691 /* *parameter */ NULL,
17692 /* *result */ NULL
17694 int rc;
17695 u16 cmd_result[2] = { 0, 0 };
17696 u16 demod_lock = SCU_RAM_PARAM_1_RES_DEMOD_GET_LOCK_DEMOD_LOCKED;
17698 /* check arguments */
17699 if ((demod == NULL) || (lock_stat == NULL))
17700 return -EINVAL;
17702 dev_addr = demod->my_i2c_dev_addr;
17703 ext_attr = (struct drxj_data *) demod->my_ext_attr;
17704 standard = ext_attr->standard;
17706 *lock_stat = DRX_NOT_LOCKED;
17708 /* define the SCU command code */
17709 switch (standard) {
17710 case DRX_STANDARD_8VSB:
17711 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB |
17712 SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK;
17713 demod_lock |= 0x6;
17714 break;
17715 #ifndef DRXJ_VSB_ONLY
17716 case DRX_STANDARD_ITU_A:
17717 case DRX_STANDARD_ITU_B:
17718 case DRX_STANDARD_ITU_C:
17719 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
17720 SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK;
17721 break;
17722 #endif
17723 #if 0
17724 case DRX_STANDARD_NTSC:
17725 case DRX_STANDARD_PAL_SECAM_BG:
17726 case DRX_STANDARD_PAL_SECAM_DK:
17727 case DRX_STANDARD_PAL_SECAM_I:
17728 case DRX_STANDARD_PAL_SECAM_L:
17729 case DRX_STANDARD_PAL_SECAM_LP:
17730 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_ATV |
17731 SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK;
17732 break;
17733 case DRX_STANDARD_FM:
17734 return fm_lock_status(demod, lock_stat);
17735 #endif
17736 case DRX_STANDARD_UNKNOWN: /* fallthrough */
17737 default:
17738 return -EIO;
17741 /* define the SCU command paramters and execute the command */
17742 cmd_scu.parameter_len = 0;
17743 cmd_scu.result_len = 2;
17744 cmd_scu.parameter = NULL;
17745 cmd_scu.result = cmd_result;
17746 rc = scu_command(dev_addr, &cmd_scu);
17747 if (rc != 0) {
17748 pr_err("error %d\n", rc);
17749 goto rw_error;
17752 /* set the lock status */
17753 if (cmd_scu.result[1] < demod_lock) {
17754 /* 0x0000 NOT LOCKED */
17755 *lock_stat = DRX_NOT_LOCKED;
17756 } else if (cmd_scu.result[1] < SCU_RAM_PARAM_1_RES_DEMOD_GET_LOCK_LOCKED) {
17757 *lock_stat = DRXJ_DEMOD_LOCK;
17758 } else if (cmd_scu.result[1] <
17759 SCU_RAM_PARAM_1_RES_DEMOD_GET_LOCK_NEVER_LOCK) {
17760 /* 0x8000 DEMOD + FEC LOCKED (system lock) */
17761 *lock_stat = DRX_LOCKED;
17762 } else {
17763 /* 0xC000 NEVER LOCKED */
17764 /* (system will never be able to lock to the signal) */
17765 *lock_stat = DRX_NEVER_LOCK;
17768 return 0;
17769 rw_error:
17770 return -EIO;
17773 /*============================================================================*/
17775 #if 0
17777 * \fn int ctrl_constel()
17778 * \brief Retreive a constellation point via I2C.
17779 * \param demod Pointer to demodulator instance.
17780 * \param complex_nr Pointer to the structure in which to store the
17781 constellation point.
17782 * \return int.
17784 static int
17785 ctrl_constel(struct drx_demod_instance *demod, struct drx_complex *complex_nr)
17787 int rc;
17788 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
17789 /**< active standard */
17791 /* check arguments */
17792 if ((demod == NULL) || (complex_nr == NULL))
17793 return -EINVAL;
17795 /* read device info */
17796 standard = ((struct drxj_data *) demod->my_ext_attr)->standard;
17798 /* Read constellation point */
17799 switch (standard) {
17800 case DRX_STANDARD_8VSB:
17801 rc = ctrl_get_vsb_constel(demod, complex_nr);
17802 if (rc != 0) {
17803 pr_err("error %d\n", rc);
17804 goto rw_error;
17806 break;
17807 #ifndef DRXJ_VSB_ONLY
17808 case DRX_STANDARD_ITU_A: /* fallthrough */
17809 case DRX_STANDARD_ITU_B: /* fallthrough */
17810 case DRX_STANDARD_ITU_C:
17811 rc = ctrl_get_qam_constel(demod, complex_nr);
17812 if (rc != 0) {
17813 pr_err("error %d\n", rc);
17814 goto rw_error;
17816 break;
17817 #endif
17818 case DRX_STANDARD_UNKNOWN:
17819 default:
17820 return -EIO;
17823 return 0;
17824 rw_error:
17825 return -EIO;
17827 #endif
17829 /*============================================================================*/
17832 * \fn int ctrl_set_standard()
17833 * \brief Set modulation standard to be used.
17834 * \param standard Modulation standard.
17835 * \return int.
17837 * Setup stuff for the desired demodulation standard.
17838 * Disable and power down the previous selected demodulation standard
17841 static int
17842 ctrl_set_standard(struct drx_demod_instance *demod, enum drx_standard *standard)
17844 struct drxj_data *ext_attr = NULL;
17845 int rc;
17846 enum drx_standard prev_standard;
17848 /* check arguments */
17849 if ((standard == NULL) || (demod == NULL))
17850 return -EINVAL;
17852 ext_attr = (struct drxj_data *) demod->my_ext_attr;
17853 prev_standard = ext_attr->standard;
17856 Stop and power down previous standard
17858 switch (prev_standard) {
17859 #ifndef DRXJ_VSB_ONLY
17860 case DRX_STANDARD_ITU_A: /* fallthrough */
17861 case DRX_STANDARD_ITU_B: /* fallthrough */
17862 case DRX_STANDARD_ITU_C:
17863 rc = power_down_qam(demod, false);
17864 if (rc != 0) {
17865 pr_err("error %d\n", rc);
17866 goto rw_error;
17868 break;
17869 #endif
17870 case DRX_STANDARD_8VSB:
17871 rc = power_down_vsb(demod, false);
17872 if (rc != 0) {
17873 pr_err("error %d\n", rc);
17874 goto rw_error;
17876 break;
17877 #if 0
17878 case DRX_STANDARD_NTSC: /* fallthrough */
17879 case DRX_STANDARD_FM: /* fallthrough */
17880 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
17881 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
17882 case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
17883 case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */
17884 case DRX_STANDARD_PAL_SECAM_LP:
17885 rc = power_down_atv(demod, prev_standard, false);
17886 if (rc != 0) {
17887 pr_err("error %d\n", rc);
17888 goto rw_error;
17890 break;
17891 #endif
17892 case DRX_STANDARD_UNKNOWN:
17893 /* Do nothing */
17894 break;
17895 case DRX_STANDARD_AUTO: /* fallthrough */
17896 default:
17897 return -EINVAL;
17901 Initialize channel independent registers
17902 Power up new standard
17904 ext_attr->standard = *standard;
17906 switch (*standard) {
17907 #ifndef DRXJ_VSB_ONLY
17908 case DRX_STANDARD_ITU_A: /* fallthrough */
17909 case DRX_STANDARD_ITU_B: /* fallthrough */
17910 case DRX_STANDARD_ITU_C:
17911 do {
17912 u16 dummy;
17913 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SCU_RAM_VERSION_HI__A, &dummy, 0);
17914 if (rc != 0) {
17915 pr_err("error %d\n", rc);
17916 goto rw_error;
17918 } while (0);
17919 break;
17920 #endif
17921 case DRX_STANDARD_8VSB:
17922 rc = set_vsb_leak_n_gain(demod);
17923 if (rc != 0) {
17924 pr_err("error %d\n", rc);
17925 goto rw_error;
17927 break;
17928 #if 0
17929 case DRX_STANDARD_NTSC: /* fallthrough */
17930 case DRX_STANDARD_FM: /* fallthrough */
17931 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
17932 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
17933 case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
17934 case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */
17935 case DRX_STANDARD_PAL_SECAM_LP:
17936 rc = set_atv_standard(demod, standard);
17937 if (rc != 0) {
17938 pr_err("error %d\n", rc);
17939 goto rw_error;
17941 rc = power_up_atv(demod, *standard);
17942 if (rc != 0) {
17943 pr_err("error %d\n", rc);
17944 goto rw_error;
17946 break;
17947 #endif
17948 default:
17949 ext_attr->standard = DRX_STANDARD_UNKNOWN;
17950 return -EINVAL;
17951 break;
17954 return 0;
17955 rw_error:
17956 /* Don't know what the standard is now ... try again */
17957 ext_attr->standard = DRX_STANDARD_UNKNOWN;
17958 return -EIO;
17961 #if 0
17962 /*============================================================================*/
17965 * \fn int ctrl_get_standard()
17966 * \brief Get modulation standard currently used to demodulate.
17967 * \param standard Modulation standard.
17968 * \return int.
17970 * Returns 8VSB, NTSC, QAM only.
17973 static int
17974 ctrl_get_standard(struct drx_demod_instance *demod, enum drx_standard *standard)
17976 struct drxj_data *ext_attr = NULL;
17977 int rc;
17978 ext_attr = (struct drxj_data *) demod->my_ext_attr;
17980 /* check arguments */
17981 if (standard == NULL)
17982 return -EINVAL;
17984 *standard = ext_attr->standard;
17985 do {
17986 u16 dummy;
17987 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SCU_RAM_VERSION_HI__A, &dummy, 0);
17988 if (rc != 0) {
17989 pr_err("error %d\n", rc);
17990 goto rw_error;
17992 } while (0);
17994 return 0;
17995 rw_error:
17996 return -EIO;
17999 /*============================================================================*/
18002 * \fn int ctrl_get_cfg_symbol_clock_offset()
18003 * \brief Get frequency offsets of STR.
18004 * \param pointer to s32.
18005 * \return int.
18008 static int
18009 ctrl_get_cfg_symbol_clock_offset(struct drx_demod_instance *demod, s32 *rate_offset)
18011 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
18012 int rc;
18013 struct drxj_data *ext_attr = NULL;
18015 /* check arguments */
18016 if (rate_offset == NULL)
18017 return -EINVAL;
18019 ext_attr = (struct drxj_data *) demod->my_ext_attr;
18020 standard = ext_attr->standard;
18022 switch (standard) {
18023 case DRX_STANDARD_8VSB: /* fallthrough */
18024 #ifndef DRXJ_VSB_ONLY
18025 case DRX_STANDARD_ITU_A: /* fallthrough */
18026 case DRX_STANDARD_ITU_B: /* fallthrough */
18027 case DRX_STANDARD_ITU_C:
18028 #endif
18029 rc = get_str_freq_offset(demod, rate_offset);
18030 if (rc != 0) {
18031 pr_err("error %d\n", rc);
18032 goto rw_error;
18034 break;
18035 case DRX_STANDARD_NTSC:
18036 case DRX_STANDARD_UNKNOWN:
18037 default:
18038 return -EINVAL;
18041 return 0;
18042 rw_error:
18043 return -EIO;
18045 #endif
18047 /*============================================================================*/
18049 static void drxj_reset_mode(struct drxj_data *ext_attr)
18051 /* Initialize default AFE configuartion for QAM */
18052 if (ext_attr->has_lna) {
18053 /* IF AGC off, PGA active */
18054 #ifndef DRXJ_VSB_ONLY
18055 ext_attr->qam_if_agc_cfg.standard = DRX_STANDARD_ITU_B;
18056 ext_attr->qam_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_OFF;
18057 ext_attr->qam_pga_cfg = 140 + (11 * 13);
18058 #endif
18059 ext_attr->vsb_if_agc_cfg.standard = DRX_STANDARD_8VSB;
18060 ext_attr->vsb_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_OFF;
18061 ext_attr->vsb_pga_cfg = 140 + (11 * 13);
18062 } else {
18063 /* IF AGC on, PGA not active */
18064 #ifndef DRXJ_VSB_ONLY
18065 ext_attr->qam_if_agc_cfg.standard = DRX_STANDARD_ITU_B;
18066 ext_attr->qam_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
18067 ext_attr->qam_if_agc_cfg.min_output_level = 0;
18068 ext_attr->qam_if_agc_cfg.max_output_level = 0x7FFF;
18069 ext_attr->qam_if_agc_cfg.speed = 3;
18070 ext_attr->qam_if_agc_cfg.top = 1297;
18071 ext_attr->qam_pga_cfg = 140;
18072 #endif
18073 ext_attr->vsb_if_agc_cfg.standard = DRX_STANDARD_8VSB;
18074 ext_attr->vsb_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
18075 ext_attr->vsb_if_agc_cfg.min_output_level = 0;
18076 ext_attr->vsb_if_agc_cfg.max_output_level = 0x7FFF;
18077 ext_attr->vsb_if_agc_cfg.speed = 3;
18078 ext_attr->vsb_if_agc_cfg.top = 1024;
18079 ext_attr->vsb_pga_cfg = 140;
18081 /* TODO: remove min_output_level and max_output_level for both QAM and VSB after */
18082 /* mc has not used them */
18083 #ifndef DRXJ_VSB_ONLY
18084 ext_attr->qam_rf_agc_cfg.standard = DRX_STANDARD_ITU_B;
18085 ext_attr->qam_rf_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
18086 ext_attr->qam_rf_agc_cfg.min_output_level = 0;
18087 ext_attr->qam_rf_agc_cfg.max_output_level = 0x7FFF;
18088 ext_attr->qam_rf_agc_cfg.speed = 3;
18089 ext_attr->qam_rf_agc_cfg.top = 9500;
18090 ext_attr->qam_rf_agc_cfg.cut_off_current = 4000;
18091 ext_attr->qam_pre_saw_cfg.standard = DRX_STANDARD_ITU_B;
18092 ext_attr->qam_pre_saw_cfg.reference = 0x07;
18093 ext_attr->qam_pre_saw_cfg.use_pre_saw = true;
18094 #endif
18095 /* Initialize default AFE configuartion for VSB */
18096 ext_attr->vsb_rf_agc_cfg.standard = DRX_STANDARD_8VSB;
18097 ext_attr->vsb_rf_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
18098 ext_attr->vsb_rf_agc_cfg.min_output_level = 0;
18099 ext_attr->vsb_rf_agc_cfg.max_output_level = 0x7FFF;
18100 ext_attr->vsb_rf_agc_cfg.speed = 3;
18101 ext_attr->vsb_rf_agc_cfg.top = 9500;
18102 ext_attr->vsb_rf_agc_cfg.cut_off_current = 4000;
18103 ext_attr->vsb_pre_saw_cfg.standard = DRX_STANDARD_8VSB;
18104 ext_attr->vsb_pre_saw_cfg.reference = 0x07;
18105 ext_attr->vsb_pre_saw_cfg.use_pre_saw = true;
18107 #if 0
18108 /* Initialize default AFE configuartion for ATV */
18109 ext_attr->atv_rf_agc_cfg.standard = DRX_STANDARD_NTSC;
18110 ext_attr->atv_rf_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
18111 ext_attr->atv_rf_agc_cfg.top = 9500;
18112 ext_attr->atv_rf_agc_cfg.cut_off_current = 4000;
18113 ext_attr->atv_rf_agc_cfg.speed = 3;
18114 ext_attr->atv_if_agc_cfg.standard = DRX_STANDARD_NTSC;
18115 ext_attr->atv_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
18116 ext_attr->atv_if_agc_cfg.speed = 3;
18117 ext_attr->atv_if_agc_cfg.top = 2400;
18118 ext_attr->atv_pre_saw_cfg.reference = 0x0007;
18119 ext_attr->atv_pre_saw_cfg.use_pre_saw = true;
18120 ext_attr->atv_pre_saw_cfg.standard = DRX_STANDARD_NTSC;
18121 #endif
18125 * \fn int ctrl_power_mode()
18126 * \brief Set the power mode of the device to the specified power mode
18127 * \param demod Pointer to demodulator instance.
18128 * \param mode Pointer to new power mode.
18129 * \return int.
18130 * \retval 0 Success
18131 * \retval -EIO I2C error or other failure
18132 * \retval -EINVAL Invalid mode argument.
18136 static int
18137 ctrl_power_mode(struct drx_demod_instance *demod, enum drx_power_mode *mode)
18139 struct drx_common_attr *common_attr = (struct drx_common_attr *) NULL;
18140 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
18141 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)NULL;
18142 int rc;
18143 u16 sio_cc_pwd_mode = 0;
18145 common_attr = (struct drx_common_attr *) demod->my_common_attr;
18146 ext_attr = (struct drxj_data *) demod->my_ext_attr;
18147 dev_addr = demod->my_i2c_dev_addr;
18149 /* Check arguments */
18150 if (mode == NULL)
18151 return -EINVAL;
18153 /* If already in requested power mode, do nothing */
18154 if (common_attr->current_power_mode == *mode)
18155 return 0;
18157 switch (*mode) {
18158 case DRX_POWER_UP:
18159 case DRXJ_POWER_DOWN_MAIN_PATH:
18160 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_NONE;
18161 break;
18162 case DRXJ_POWER_DOWN_CORE:
18163 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_CLOCK;
18164 break;
18165 case DRXJ_POWER_DOWN_PLL:
18166 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_PLL;
18167 break;
18168 case DRX_POWER_DOWN:
18169 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC;
18170 break;
18171 default:
18172 /* Unknow sleep mode */
18173 return -EINVAL;
18174 break;
18177 /* Check if device needs to be powered up */
18178 if ((common_attr->current_power_mode != DRX_POWER_UP)) {
18179 rc = power_up_device(demod);
18180 if (rc != 0) {
18181 pr_err("error %d\n", rc);
18182 goto rw_error;
18186 if ((*mode == DRX_POWER_UP)) {
18187 /* Restore analog & pin configuartion */
18189 /* Initialize default AFE configuartion for VSB */
18190 drxj_reset_mode(ext_attr);
18191 } else {
18192 /* Power down to requested mode */
18193 /* Backup some register settings */
18194 /* Set pins with possible pull-ups connected to them in input mode */
18195 /* Analog power down */
18196 /* ADC power down */
18197 /* Power down device */
18198 /* stop all comm_exec */
18200 Stop and power down previous standard
18203 switch (ext_attr->standard) {
18204 case DRX_STANDARD_ITU_A:
18205 case DRX_STANDARD_ITU_B:
18206 case DRX_STANDARD_ITU_C:
18207 rc = power_down_qam(demod, true);
18208 if (rc != 0) {
18209 pr_err("error %d\n", rc);
18210 goto rw_error;
18212 break;
18213 case DRX_STANDARD_8VSB:
18214 rc = power_down_vsb(demod, true);
18215 if (rc != 0) {
18216 pr_err("error %d\n", rc);
18217 goto rw_error;
18219 break;
18220 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
18221 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
18222 case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
18223 case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */
18224 case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
18225 case DRX_STANDARD_NTSC: /* fallthrough */
18226 case DRX_STANDARD_FM:
18227 rc = power_down_atv(demod, ext_attr->standard, true);
18228 if (rc != 0) {
18229 pr_err("error %d\n", rc);
18230 goto rw_error;
18232 break;
18233 case DRX_STANDARD_UNKNOWN:
18234 /* Do nothing */
18235 break;
18236 case DRX_STANDARD_AUTO: /* fallthrough */
18237 default:
18238 return -EIO;
18241 if (*mode != DRXJ_POWER_DOWN_MAIN_PATH) {
18242 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_CC_PWD_MODE__A, sio_cc_pwd_mode, 0);
18243 if (rc != 0) {
18244 pr_err("error %d\n", rc);
18245 goto rw_error;
18247 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY, 0);
18248 if (rc != 0) {
18249 pr_err("error %d\n", rc);
18250 goto rw_error;
18253 /* Initialize HI, wakeup key especially before put IC to sleep */
18254 rc = init_hi(demod);
18255 if (rc != 0) {
18256 pr_err("error %d\n", rc);
18257 goto rw_error;
18260 ext_attr->hi_cfg_ctrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
18261 rc = hi_cfg_command(demod);
18262 if (rc != 0) {
18263 pr_err("error %d\n", rc);
18264 goto rw_error;
18267 ext_attr->standard = DRX_STANDARD_UNKNOWN;
18270 common_attr->current_power_mode = *mode;
18272 return 0;
18273 rw_error:
18274 return -EIO;
18277 #if 0
18278 /*============================================================================*/
18281 * \fn int ctrl_probe_device()
18282 * \brief Probe device, check if it is present
18283 * \param demod Pointer to demodulator instance.
18284 * \return int.
18285 * \retval 0 a drx39xxj device has been detected.
18286 * \retval -EIO no drx39xxj device detected.
18288 * This funtion can be caled before open() and after close().
18292 static int ctrl_probe_device(struct drx_demod_instance *demod)
18294 enum drx_power_mode org_power_mode = DRX_POWER_UP;
18295 int ret_status = 0;
18296 struct drx_common_attr *common_attr = (struct drx_common_attr *) (NULL);
18297 int rc;
18299 common_attr = (struct drx_common_attr *) demod->my_common_attr;
18301 if (common_attr->is_opened == false
18302 || common_attr->current_power_mode != DRX_POWER_UP) {
18303 struct i2c_device_addr *dev_addr = NULL;
18304 enum drx_power_mode power_mode = DRX_POWER_UP;
18305 u32 jtag = 0;
18307 dev_addr = demod->my_i2c_dev_addr;
18309 /* Remeber original power mode */
18310 org_power_mode = common_attr->current_power_mode;
18312 if (demod->my_common_attr->is_opened == false) {
18313 rc = power_up_device(demod);
18314 if (rc != 0) {
18315 pr_err("error %d\n", rc);
18316 goto rw_error;
18318 common_attr->current_power_mode = DRX_POWER_UP;
18319 } else {
18320 /* Wake-up device, feedback from device */
18321 rc = ctrl_power_mode(demod, &power_mode);
18322 if (rc != 0) {
18323 pr_err("error %d\n", rc);
18324 goto rw_error;
18327 /* Initialize HI, wakeup key especially */
18328 rc = init_hi(demod);
18329 if (rc != 0) {
18330 pr_err("error %d\n", rc);
18331 goto rw_error;
18334 /* Check device id */
18335 rc = DRXJ_DAP.read_reg32func(dev_addr, SIO_TOP_JTAGID_LO__A, &jtag, 0);
18336 if (rc != 0) {
18337 pr_err("error %d\n", rc);
18338 goto rw_error;
18340 jtag = (jtag >> 12) & 0xFFFF;
18341 switch (jtag) {
18342 case 0x3931: /* fallthrough */
18343 case 0x3932: /* fallthrough */
18344 case 0x3933: /* fallthrough */
18345 case 0x3934: /* fallthrough */
18346 case 0x3941: /* fallthrough */
18347 case 0x3942: /* fallthrough */
18348 case 0x3943: /* fallthrough */
18349 case 0x3944: /* fallthrough */
18350 case 0x3945: /* fallthrough */
18351 case 0x3946:
18352 /* ok , do nothing */
18353 break;
18354 default:
18355 ret_status = -EIO;
18356 break;
18359 /* Device was not opened, return to orginal powermode,
18360 feedback from device */
18361 rc = ctrl_power_mode(demod, &org_power_mode);
18362 if (rc != 0) {
18363 pr_err("error %d\n", rc);
18364 goto rw_error;
18366 } else {
18367 /* dummy read to make this function fail in case device
18368 suddenly disappears after a succesful drx_open */
18369 do {
18370 u16 dummy;
18371 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SCU_RAM_VERSION_HI__A, &dummy, 0);
18372 if (rc != 0) {
18373 pr_err("error %d\n", rc);
18374 goto rw_error;
18376 } while (0);
18379 return ret_status;
18381 rw_error:
18382 common_attr->current_power_mode = org_power_mode;
18383 return -EIO;
18385 #endif
18387 /*============================================================================*/
18388 /*== CTRL Set/Get Config related functions ===================================*/
18389 /*============================================================================*/
18391 #if 0
18392 /*===== SigStrength() =========================================================*/
18394 * \fn int ctrl_sig_strength()
18395 * \brief Retrieve signal strength.
18396 * \param devmod Pointer to demodulator instance.
18397 * \param sig_quality Pointer to signal strength data; range 0, .. , 100.
18398 * \return int.
18399 * \retval 0 sig_strength contains valid data.
18400 * \retval -EINVAL sig_strength is NULL.
18401 * \retval -EIO Erroneous data, sig_strength contains invalid data.
18404 static int
18405 ctrl_sig_strength(struct drx_demod_instance *demod, u16 *sig_strength)
18407 struct drxj_data *ext_attr = NULL;
18408 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
18409 int rc;
18411 /* Check arguments */
18412 if ((sig_strength == NULL) || (demod == NULL))
18413 return -EINVAL;
18415 ext_attr = (struct drxj_data *) demod->my_ext_attr;
18416 standard = ext_attr->standard;
18417 *sig_strength = 0;
18419 /* Signal strength indication for each standard */
18420 switch (standard) {
18421 case DRX_STANDARD_8VSB: /* fallthrough */
18422 #ifndef DRXJ_VSB_ONLY
18423 case DRX_STANDARD_ITU_A: /* fallthrough */
18424 case DRX_STANDARD_ITU_B: /* fallthrough */
18425 case DRX_STANDARD_ITU_C:
18426 #endif
18427 rc = get_sig_strength(demod, sig_strength);
18428 if (rc != 0) {
18429 pr_err("error %d\n", rc);
18430 goto rw_error;
18432 break;
18433 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
18434 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
18435 case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
18436 case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */
18437 case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
18438 case DRX_STANDARD_NTSC: /* fallthrough */
18439 case DRX_STANDARD_FM:
18440 rc = get_atv_sig_strength(demod, sig_strength);
18441 if (rc != 0) {
18442 pr_err("error %d\n", rc);
18443 goto rw_error;
18445 break;
18446 case DRX_STANDARD_UNKNOWN: /* fallthrough */
18447 default:
18448 return -EINVAL;
18451 /* TODO */
18452 /* find out if signal strength is calculated in the same way for all standards */
18453 return 0;
18454 rw_error:
18455 return -EIO;
18458 /*============================================================================*/
18460 * \fn int ctrl_get_cfg_oob_misc()
18461 * \brief Get current state information of OOB.
18462 * \param pointer to struct drxj_cfg_oob_misc.
18463 * \return int.
18466 static int
18467 ctrl_get_cfg_oob_misc(struct drx_demod_instance *demod, struct drxj_cfg_oob_misc *misc)
18469 struct i2c_device_addr *dev_addr = NULL;
18470 int rc;
18471 u16 lock = 0U;
18472 u16 state = 0U;
18473 u16 data = 0U;
18474 u16 digital_agc_mant = 0U;
18475 u16 digital_agc_exp = 0U;
18477 /* check arguments */
18478 if (misc == NULL)
18479 return -EINVAL;
18481 dev_addr = demod->my_i2c_dev_addr;
18483 /* TODO */
18484 /* check if the same registers are used for all standards (QAM/VSB/ATV) */
18485 rc = DRXJ_DAP.read_reg16func(dev_addr, ORX_NSU_TUN_IFGAIN_W__A, &misc->agc.IFAGC, 0);
18486 if (rc != 0) {
18487 pr_err("error %d\n", rc);
18488 goto rw_error;
18490 rc = DRXJ_DAP.read_reg16func(dev_addr, ORX_NSU_TUN_RFGAIN_W__A, &misc->agc.RFAGC, 0);
18491 if (rc != 0) {
18492 pr_err("error %d\n", rc);
18493 goto rw_error;
18495 rc = DRXJ_DAP.read_reg16func(dev_addr, ORX_FWP_SRC_DGN_W__A, &data, 0);
18496 if (rc != 0) {
18497 pr_err("error %d\n", rc);
18498 goto rw_error;
18501 digital_agc_mant = data & ORX_FWP_SRC_DGN_W_MANT__M;
18502 digital_agc_exp = (data & ORX_FWP_SRC_DGN_W_EXP__M)
18503 >> ORX_FWP_SRC_DGN_W_EXP__B;
18504 misc->agc.digital_agc = digital_agc_mant << digital_agc_exp;
18506 rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_ORX_SCU_LOCK__A, &lock, 0);
18507 if (rc != 0) {
18508 pr_err("error %d\n", rc);
18509 goto rw_error;
18512 misc->ana_gain_lock = ((lock & 0x0001) ? true : false);
18513 misc->dig_gain_lock = ((lock & 0x0002) ? true : false);
18514 misc->freq_lock = ((lock & 0x0004) ? true : false);
18515 misc->phase_lock = ((lock & 0x0008) ? true : false);
18516 misc->sym_timing_lock = ((lock & 0x0010) ? true : false);
18517 misc->eq_lock = ((lock & 0x0020) ? true : false);
18519 rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_ORX_SCU_STATE__A, &state, 0);
18520 if (rc != 0) {
18521 pr_err("error %d\n", rc);
18522 goto rw_error;
18524 misc->state = (state >> 8) & 0xff;
18526 return 0;
18527 rw_error:
18528 return -EIO;
18532 * \fn int ctrl_get_cfg_vsb_misc()
18533 * \brief Get current state information of OOB.
18534 * \param pointer to struct drxj_cfg_oob_misc.
18535 * \return int.
18538 static int
18539 ctrl_get_cfg_vsb_misc(struct drx_demod_instance *demod, struct drxj_cfg_vsb_misc *misc)
18541 struct i2c_device_addr *dev_addr = NULL;
18542 int rc;
18544 /* check arguments */
18545 if (misc == NULL)
18546 return -EINVAL;
18548 dev_addr = demod->my_i2c_dev_addr;
18550 rc = get_vsb_symb_err(dev_addr, &misc->symb_error);
18551 if (rc != 0) {
18552 pr_err("error %d\n", rc);
18553 goto rw_error;
18556 return 0;
18557 rw_error:
18558 return -EIO;
18561 /*============================================================================*/
18564 * \fn int ctrl_set_cfg_agc_if()
18565 * \brief Set IF AGC.
18566 * \param demod demod instance
18567 * \param agc_settings If agc configuration
18568 * \return int.
18570 * Check arguments
18571 * Dispatch handling to standard specific function.
18574 static int
18575 ctrl_set_cfg_agc_if(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings)
18577 /* check arguments */
18578 if (agc_settings == NULL)
18579 return -EINVAL;
18581 switch (agc_settings->ctrl_mode) {
18582 case DRX_AGC_CTRL_AUTO: /* fallthrough */
18583 case DRX_AGC_CTRL_USER: /* fallthrough */
18584 case DRX_AGC_CTRL_OFF: /* fallthrough */
18585 break;
18586 default:
18587 return -EINVAL;
18590 /* Distpatch */
18591 switch (agc_settings->standard) {
18592 case DRX_STANDARD_8VSB: /* fallthrough */
18593 #ifndef DRXJ_VSB_ONLY
18594 case DRX_STANDARD_ITU_A: /* fallthrough */
18595 case DRX_STANDARD_ITU_B: /* fallthrough */
18596 case DRX_STANDARD_ITU_C:
18597 #endif
18598 #if 0
18599 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
18600 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
18601 case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
18602 case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */
18603 case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
18604 case DRX_STANDARD_NTSC: /* fallthrough */
18605 case DRX_STANDARD_FM:
18606 #endif
18607 return set_agc_if(demod, agc_settings, true);
18608 case DRX_STANDARD_UNKNOWN:
18609 default:
18610 return -EINVAL;
18613 return 0;
18616 /*============================================================================*/
18619 * \fn int ctrl_get_cfg_agc_if()
18620 * \brief Retrieve IF AGC settings.
18621 * \param demod demod instance
18622 * \param agc_settings If agc configuration
18623 * \return int.
18625 * Check arguments
18626 * Dispatch handling to standard specific function.
18629 static int
18630 ctrl_get_cfg_agc_if(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings)
18632 /* check arguments */
18633 if (agc_settings == NULL)
18634 return -EINVAL;
18636 /* Distpatch */
18637 switch (agc_settings->standard) {
18638 case DRX_STANDARD_8VSB: /* fallthrough */
18639 #ifndef DRXJ_VSB_ONLY
18640 case DRX_STANDARD_ITU_A: /* fallthrough */
18641 case DRX_STANDARD_ITU_B: /* fallthrough */
18642 case DRX_STANDARD_ITU_C:
18643 #endif
18644 #if 0
18645 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
18646 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
18647 case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
18648 case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */
18649 case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
18650 case DRX_STANDARD_NTSC: /* fallthrough */
18651 case DRX_STANDARD_FM:
18652 #endif
18653 return get_agc_if(demod, agc_settings);
18654 case DRX_STANDARD_UNKNOWN:
18655 default:
18656 return -EINVAL;
18659 return 0;
18662 /*============================================================================*/
18665 * \fn int ctrl_set_cfg_agc_rf()
18666 * \brief Set RF AGC.
18667 * \param demod demod instance
18668 * \param agc_settings rf agc configuration
18669 * \return int.
18671 * Check arguments
18672 * Dispatch handling to standard specific function.
18675 static int
18676 ctrl_set_cfg_agc_rf(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings)
18678 /* check arguments */
18679 if (agc_settings == NULL)
18680 return -EINVAL;
18682 switch (agc_settings->ctrl_mode) {
18683 case DRX_AGC_CTRL_AUTO: /* fallthrough */
18684 case DRX_AGC_CTRL_USER: /* fallthrough */
18685 case DRX_AGC_CTRL_OFF:
18686 break;
18687 default:
18688 return -EINVAL;
18691 /* Distpatch */
18692 switch (agc_settings->standard) {
18693 case DRX_STANDARD_8VSB: /* fallthrough */
18694 #ifndef DRXJ_VSB_ONLY
18695 case DRX_STANDARD_ITU_A: /* fallthrough */
18696 case DRX_STANDARD_ITU_B: /* fallthrough */
18697 case DRX_STANDARD_ITU_C:
18698 #endif
18699 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
18700 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
18701 case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
18702 case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */
18703 case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
18704 case DRX_STANDARD_NTSC: /* fallthrough */
18705 case DRX_STANDARD_FM:
18706 return set_agc_rf(demod, agc_settings, true);
18707 case DRX_STANDARD_UNKNOWN:
18708 default:
18709 return -EINVAL;
18712 return 0;
18715 /*============================================================================*/
18718 * \fn int ctrl_get_cfg_agc_rf()
18719 * \brief Retrieve RF AGC settings.
18720 * \param demod demod instance
18721 * \param agc_settings Rf agc configuration
18722 * \return int.
18724 * Check arguments
18725 * Dispatch handling to standard specific function.
18728 static int
18729 ctrl_get_cfg_agc_rf(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings)
18731 /* check arguments */
18732 if (agc_settings == NULL)
18733 return -EINVAL;
18735 /* Distpatch */
18736 switch (agc_settings->standard) {
18737 case DRX_STANDARD_8VSB: /* fallthrough */
18738 #ifndef DRXJ_VSB_ONLY
18739 case DRX_STANDARD_ITU_A: /* fallthrough */
18740 case DRX_STANDARD_ITU_B: /* fallthrough */
18741 case DRX_STANDARD_ITU_C:
18742 #endif
18743 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
18744 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
18745 case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
18746 case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */
18747 case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
18748 case DRX_STANDARD_NTSC: /* fallthrough */
18749 case DRX_STANDARD_FM:
18750 return get_agc_rf(demod, agc_settings);
18751 case DRX_STANDARD_UNKNOWN:
18752 default:
18753 return -EINVAL;
18756 return 0;
18759 /*============================================================================*/
18762 * \fn int ctrl_get_cfg_agc_internal()
18763 * \brief Retrieve internal AGC value.
18764 * \param demod demod instance
18765 * \param u16
18766 * \return int.
18768 * Check arguments
18769 * Dispatch handling to standard specific function.
18772 static int
18773 ctrl_get_cfg_agc_internal(struct drx_demod_instance *demod, u16 *agc_internal)
18775 struct i2c_device_addr *dev_addr = NULL;
18776 int rc;
18777 enum drx_lock_status lock_status = DRX_NOT_LOCKED;
18778 struct drxj_data *ext_attr = NULL;
18779 u16 iqm_cf_scale_sh = 0;
18780 u16 iqm_cf_power = 0;
18781 u16 iqm_cf_amp = 0;
18782 u16 iqm_cf_gain = 0;
18784 /* check arguments */
18785 if (agc_internal == NULL)
18786 return -EINVAL;
18787 dev_addr = demod->my_i2c_dev_addr;
18788 ext_attr = (struct drxj_data *) demod->my_ext_attr;
18790 rc = ctrl_lock_status(demod, &lock_status);
18791 if (rc != 0) {
18792 pr_err("error %d\n", rc);
18793 goto rw_error;
18795 if (lock_status != DRXJ_DEMOD_LOCK && lock_status != DRX_LOCKED) {
18796 *agc_internal = 0;
18797 return 0;
18800 /* Distpatch */
18801 switch (ext_attr->standard) {
18802 case DRX_STANDARD_8VSB:
18803 iqm_cf_gain = 57;
18804 break;
18805 #ifndef DRXJ_VSB_ONLY
18806 case DRX_STANDARD_ITU_A:
18807 case DRX_STANDARD_ITU_B:
18808 case DRX_STANDARD_ITU_C:
18809 switch (ext_attr->constellation) {
18810 case DRX_CONSTELLATION_QAM256:
18811 case DRX_CONSTELLATION_QAM128:
18812 case DRX_CONSTELLATION_QAM32:
18813 case DRX_CONSTELLATION_QAM16:
18814 iqm_cf_gain = 57;
18815 break;
18816 case DRX_CONSTELLATION_QAM64:
18817 iqm_cf_gain = 56;
18818 break;
18819 default:
18820 return -EIO;
18822 break;
18823 #endif
18824 default:
18825 return -EINVAL;
18828 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_CF_POW__A, &iqm_cf_power, 0);
18829 if (rc != 0) {
18830 pr_err("error %d\n", rc);
18831 goto rw_error;
18833 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_CF_SCALE_SH__A, &iqm_cf_scale_sh, 0);
18834 if (rc != 0) {
18835 pr_err("error %d\n", rc);
18836 goto rw_error;
18838 rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_CF_AMP__A, &iqm_cf_amp, 0);
18839 if (rc != 0) {
18840 pr_err("error %d\n", rc);
18841 goto rw_error;
18843 /* IQM_CF_PWR_CORRECTION_dB = 3;
18844 P5dB =10*log10(IQM_CF_POW)+12-6*9-IQM_CF_PWR_CORRECTION_dB; */
18845 /* P4dB = P5dB -20*log10(IQM_CF_AMP)-6*10
18846 -IQM_CF_Gain_dB-18+6*(27-IQM_CF_SCALE_SH*2-10)
18847 +6*7+10*log10(1+0.115/4); */
18848 /* PadcdB = P4dB +3 -6 +60; dBmV */
18849 *agc_internal = (u16) (log1_times100(iqm_cf_power)
18850 - 2 * log1_times100(iqm_cf_amp)
18851 - iqm_cf_gain - 120 * iqm_cf_scale_sh + 781);
18853 return 0;
18854 rw_error:
18855 return -EIO;
18858 /*============================================================================*/
18859 #endif
18862 * \fn int ctrl_set_cfg_pre_saw()
18863 * \brief Set Pre-saw reference.
18864 * \param demod demod instance
18865 * \param u16 *
18866 * \return int.
18868 * Check arguments
18869 * Dispatch handling to standard specific function.
18872 static int
18873 ctrl_set_cfg_pre_saw(struct drx_demod_instance *demod, struct drxj_cfg_pre_saw *pre_saw)
18875 struct i2c_device_addr *dev_addr = NULL;
18876 struct drxj_data *ext_attr = NULL;
18877 int rc;
18879 dev_addr = demod->my_i2c_dev_addr;
18880 ext_attr = (struct drxj_data *) demod->my_ext_attr;
18882 /* check arguments */
18883 if ((pre_saw == NULL) || (pre_saw->reference > IQM_AF_PDREF__M)
18885 return -EINVAL;
18888 /* Only if standard is currently active */
18889 if ((ext_attr->standard == pre_saw->standard) ||
18890 (DRXJ_ISQAMSTD(ext_attr->standard) &&
18891 DRXJ_ISQAMSTD(pre_saw->standard)) ||
18892 (DRXJ_ISATVSTD(ext_attr->standard) &&
18893 DRXJ_ISATVSTD(pre_saw->standard))) {
18894 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_PDREF__A, pre_saw->reference, 0);
18895 if (rc != 0) {
18896 pr_err("error %d\n", rc);
18897 goto rw_error;
18901 /* Store pre-saw settings */
18902 switch (pre_saw->standard) {
18903 case DRX_STANDARD_8VSB:
18904 ext_attr->vsb_pre_saw_cfg = *pre_saw;
18905 break;
18906 #ifndef DRXJ_VSB_ONLY
18907 case DRX_STANDARD_ITU_A: /* fallthrough */
18908 case DRX_STANDARD_ITU_B: /* fallthrough */
18909 case DRX_STANDARD_ITU_C:
18910 ext_attr->qam_pre_saw_cfg = *pre_saw;
18911 break;
18912 #endif
18913 #if 0
18914 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
18915 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
18916 case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
18917 case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */
18918 case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
18919 case DRX_STANDARD_NTSC: /* fallthrough */
18920 case DRX_STANDARD_FM:
18921 ext_attr->atv_pre_saw_cfg = *pre_saw;
18922 break;
18923 #endif
18924 default:
18925 return -EINVAL;
18928 return 0;
18929 rw_error:
18930 return -EIO;
18933 /*============================================================================*/
18936 * \fn int ctrl_set_cfg_afe_gain()
18937 * \brief Set AFE Gain.
18938 * \param demod demod instance
18939 * \param u16 *
18940 * \return int.
18942 * Check arguments
18943 * Dispatch handling to standard specific function.
18946 static int
18947 ctrl_set_cfg_afe_gain(struct drx_demod_instance *demod, struct drxj_cfg_afe_gain *afe_gain)
18949 struct i2c_device_addr *dev_addr = NULL;
18950 struct drxj_data *ext_attr = NULL;
18951 int rc;
18952 u8 gain = 0;
18954 /* check arguments */
18955 if (afe_gain == NULL)
18956 return -EINVAL;
18958 dev_addr = demod->my_i2c_dev_addr;
18959 ext_attr = (struct drxj_data *) demod->my_ext_attr;
18961 switch (afe_gain->standard) {
18962 case DRX_STANDARD_8VSB: /* fallthrough */
18963 #ifndef DRXJ_VSB_ONLY
18964 case DRX_STANDARD_ITU_A: /* fallthrough */
18965 case DRX_STANDARD_ITU_B: /* fallthrough */
18966 case DRX_STANDARD_ITU_C:
18967 #endif
18968 /* Do nothing */
18969 break;
18970 default:
18971 return -EINVAL;
18974 /* TODO PGA gain is also written by microcode (at least by QAM and VSB)
18975 So I (PJ) think interface requires choice between auto, user mode */
18977 if (afe_gain->gain >= 329)
18978 gain = 15;
18979 else if (afe_gain->gain <= 147)
18980 gain = 0;
18981 else
18982 gain = (afe_gain->gain - 140 + 6) / 13;
18984 /* Only if standard is currently active */
18985 if (ext_attr->standard == afe_gain->standard) {
18986 rc = DRXJ_DAP.write_reg16func(dev_addr, IQM_AF_PGA_GAIN__A, gain, 0);
18987 if (rc != 0) {
18988 pr_err("error %d\n", rc);
18989 goto rw_error;
18993 /* Store AFE Gain settings */
18994 switch (afe_gain->standard) {
18995 case DRX_STANDARD_8VSB:
18996 ext_attr->vsb_pga_cfg = gain * 13 + 140;
18997 break;
18998 #ifndef DRXJ_VSB_ONLY
18999 case DRX_STANDARD_ITU_A: /* fallthrough */
19000 case DRX_STANDARD_ITU_B: /* fallthrough */
19001 case DRX_STANDARD_ITU_C:
19002 ext_attr->qam_pga_cfg = gain * 13 + 140;
19003 break;
19004 #endif
19005 default:
19006 return -EIO;
19009 return 0;
19010 rw_error:
19011 return -EIO;
19014 /*============================================================================*/
19016 #if 0
19018 * \fn int ctrl_get_cfg_pre_saw()
19019 * \brief Get Pre-saw reference setting.
19020 * \param demod demod instance
19021 * \param u16 *
19022 * \return int.
19024 * Check arguments
19025 * Dispatch handling to standard specific function.
19028 static int
19029 ctrl_get_cfg_pre_saw(struct drx_demod_instance *demod, struct drxj_cfg_pre_saw *pre_saw)
19031 struct drxj_data *ext_attr = NULL;
19033 /* check arguments */
19034 if (pre_saw == NULL)
19035 return -EINVAL;
19037 ext_attr = (struct drxj_data *) demod->my_ext_attr;
19039 switch (pre_saw->standard) {
19040 case DRX_STANDARD_8VSB:
19041 *pre_saw = ext_attr->vsb_pre_saw_cfg;
19042 break;
19043 #ifndef DRXJ_VSB_ONLY
19044 case DRX_STANDARD_ITU_A: /* fallthrough */
19045 case DRX_STANDARD_ITU_B: /* fallthrough */
19046 case DRX_STANDARD_ITU_C:
19047 *pre_saw = ext_attr->qam_pre_saw_cfg;
19048 break;
19049 #endif
19050 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
19051 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
19052 case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
19053 case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */
19054 case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
19055 case DRX_STANDARD_NTSC:
19056 ext_attr->atv_pre_saw_cfg.standard = DRX_STANDARD_NTSC;
19057 *pre_saw = ext_attr->atv_pre_saw_cfg;
19058 break;
19059 case DRX_STANDARD_FM:
19060 ext_attr->atv_pre_saw_cfg.standard = DRX_STANDARD_FM;
19061 *pre_saw = ext_attr->atv_pre_saw_cfg;
19062 break;
19064 default:
19065 return -EINVAL;
19068 return 0;
19071 /*============================================================================*/
19074 * \fn int ctrl_get_cfg_afe_gain()
19075 * \brief Get AFE Gain.
19076 * \param demod demod instance
19077 * \param u16 *
19078 * \return int.
19080 * Check arguments
19081 * Dispatch handling to standard specific function.
19084 static int
19085 ctrl_get_cfg_afe_gain(struct drx_demod_instance *demod, struct drxj_cfg_afe_gain *afe_gain)
19087 struct drxj_data *ext_attr = NULL;
19089 /* check arguments */
19090 if (afe_gain == NULL)
19091 return -EINVAL;
19093 ext_attr = demod->my_ext_attr;
19095 switch (afe_gain->standard) {
19096 case DRX_STANDARD_8VSB:
19097 afe_gain->gain = ext_attr->vsb_pga_cfg;
19098 break;
19099 #ifndef DRXJ_VSB_ONLY
19100 case DRX_STANDARD_ITU_A: /* fallthrough */
19101 case DRX_STANDARD_ITU_B: /* fallthrough */
19102 case DRX_STANDARD_ITU_C:
19103 afe_gain->gain = ext_attr->qam_pga_cfg;
19104 break;
19105 #endif
19106 default:
19107 return -EINVAL;
19110 return 0;
19113 /*============================================================================*/
19116 * \fn int ctrl_get_fec_meas_seq_count()
19117 * \brief Get FEC measurement sequnce number.
19118 * \param demod demod instance
19119 * \param u16 *
19120 * \return int.
19122 * Check arguments
19123 * Dispatch handling to standard specific function.
19126 static int
19127 ctrl_get_fec_meas_seq_count(struct drx_demod_instance *demod, u16 *fec_meas_seq_count)
19129 int rc;
19130 /* check arguments */
19131 if (fec_meas_seq_count == NULL)
19132 return -EINVAL;
19134 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SCU_RAM_FEC_MEAS_COUNT__A, fec_meas_seq_count, 0);
19135 if (rc != 0) {
19136 pr_err("error %d\n", rc);
19137 goto rw_error;
19140 return 0;
19141 rw_error:
19142 return -EIO;
19145 /*============================================================================*/
19148 * \fn int ctrl_get_accum_cr_rs_cw_err()
19149 * \brief Get accumulative corrected RS codeword number.
19150 * \param demod demod instance
19151 * \param u32 *
19152 * \return int.
19154 * Check arguments
19155 * Dispatch handling to standard specific function.
19158 static int
19159 ctrl_get_accum_cr_rs_cw_err(struct drx_demod_instance *demod, u32 *accum_cr_rs_cw_err)
19161 int rc;
19162 if (accum_cr_rs_cw_err == NULL)
19163 return -EINVAL;
19165 rc = DRXJ_DAP.read_reg32func(demod->my_i2c_dev_addr, SCU_RAM_FEC_ACCUM_CW_CORRECTED_LO__A, accum_cr_rs_cw_err, 0);
19166 if (rc != 0) {
19167 pr_err("error %d\n", rc);
19168 goto rw_error;
19171 return 0;
19172 rw_error:
19173 return -EIO;
19177 * \fn int ctrl_set_cfg()
19178 * \brief Set 'some' configuration of the device.
19179 * \param devmod Pointer to demodulator instance.
19180 * \param config Pointer to configuration parameters (type and data).
19181 * \return int.
19184 static int ctrl_set_cfg(struct drx_demod_instance *demod, struct drx_cfg *config)
19186 int rc;
19188 if (config == NULL)
19189 return -EINVAL;
19191 do {
19192 u16 dummy;
19193 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SCU_RAM_VERSION_HI__A, &dummy, 0);
19194 if (rc != 0) {
19195 pr_err("error %d\n", rc);
19196 goto rw_error;
19198 } while (0);
19199 switch (config->cfg_type) {
19200 case DRX_CFG_MPEG_OUTPUT:
19201 return ctrl_set_cfg_mpeg_output(demod,
19202 (struct drx_cfg_mpeg_output *) config->
19203 cfg_data);
19204 case DRX_CFG_PINS_SAFE_MODE:
19205 return ctrl_set_cfg_pdr_safe_mode(demod, (bool *)config->cfg_data);
19206 case DRXJ_CFG_AGC_RF:
19207 return ctrl_set_cfg_agc_rf(demod, (struct drxj_cfg_agc *) config->cfg_data);
19208 case DRXJ_CFG_AGC_IF:
19209 return ctrl_set_cfg_agc_if(demod, (struct drxj_cfg_agc *) config->cfg_data);
19210 case DRXJ_CFG_PRE_SAW:
19211 return ctrl_set_cfg_pre_saw(demod,
19212 (struct drxj_cfg_pre_saw *) config->cfg_data);
19213 case DRXJ_CFG_AFE_GAIN:
19214 return ctrl_set_cfg_afe_gain(demod,
19215 (struct drxj_cfg_afe_gain *) config->cfg_data);
19216 case DRXJ_CFG_SMART_ANT:
19217 return ctrl_set_cfg_smart_ant(demod,
19218 (struct drxj_cfg_smart_ant *) (config->
19219 cfg_data));
19220 case DRXJ_CFG_RESET_PACKET_ERR:
19221 return ctrl_set_cfg_reset_pkt_err(demod);
19222 #if 0
19223 case DRXJ_CFG_OOB_PRE_SAW:
19224 return ctrl_set_cfg_oob_pre_saw(demod, (u16 *)(config->cfg_data));
19225 case DRXJ_CFG_OOB_LO_POW:
19226 return ctrl_set_cfg_oob_lo_power(demod,
19227 (enum drxj_cfg_oob_lo_power *) (config->
19228 cfg_data));
19229 case DRXJ_CFG_ATV_MISC:
19230 return ctrl_set_cfg_atv_misc(demod,
19231 (struct drxj_cfg_atv_misc *) config->cfg_data);
19232 case DRXJ_CFG_ATV_EQU_COEF:
19233 return ctrl_set_cfg_atv_equ_coef(demod,
19234 (struct drxj_cfg_atv_equ_coef *) config->
19235 cfg_data);
19236 case DRXJ_CFG_ATV_OUTPUT:
19237 return ctrl_set_cfg_atv_output(demod,
19238 (struct drxj_cfg_atv_output *) config->
19239 cfg_data);
19240 #endif
19241 case DRXJ_CFG_MPEG_OUTPUT_MISC:
19242 return ctrl_set_cfg_mpeg_output_misc(demod,
19243 (struct drxj_cfg_mpeg_output_misc *)
19244 config->cfg_data);
19245 #ifndef DRXJ_EXCLUDE_AUDIO
19246 case DRX_CFG_AUD_VOLUME:
19247 return aud_ctrl_set_cfg_volume(demod,
19248 (struct drx_cfg_aud_volume *) config->
19249 cfg_data);
19250 case DRX_CFG_I2S_OUTPUT:
19251 return aud_ctrl_set_cfg_output_i2s(demod,
19252 (struct drx_cfg_i2s_output *) config->
19253 cfg_data);
19254 case DRX_CFG_AUD_AUTOSOUND:
19255 return aud_ctr_setl_cfg_auto_sound(demod, (enum drx_cfg_aud_auto_sound *)
19256 config->cfg_data);
19257 case DRX_CFG_AUD_ASS_THRES:
19258 return aud_ctrl_set_cfg_ass_thres(demod, (struct drx_cfg_aud_ass_thres *)
19259 config->cfg_data);
19260 case DRX_CFG_AUD_CARRIER:
19261 return aud_ctrl_set_cfg_carrier(demod,
19262 (struct drx_cfg_aud_carriers *) config->
19263 cfg_data);
19264 case DRX_CFG_AUD_DEVIATION:
19265 return aud_ctrl_set_cfg_dev(demod,
19266 (enum drx_cfg_aud_deviation *) config->
19267 cfg_data);
19268 case DRX_CFG_AUD_PRESCALE:
19269 return aud_ctrl_set_cfg_prescale(demod,
19270 (struct drx_cfg_aud_prescale *) config->
19271 cfg_data);
19272 case DRX_CFG_AUD_MIXER:
19273 return aud_ctrl_set_cfg_mixer(demod,
19274 (struct drx_cfg_aud_mixer *) config->cfg_data);
19275 case DRX_CFG_AUD_AVSYNC:
19276 return aud_ctrl_set_cfg_av_sync(demod,
19277 (enum drx_cfg_aud_av_sync *) config->
19278 cfg_data);
19280 #endif
19281 default:
19282 return -EINVAL;
19285 return 0;
19286 rw_error:
19287 return -EIO;
19290 /*============================================================================*/
19293 * \fn int ctrl_get_cfg()
19294 * \brief Get 'some' configuration of the device.
19295 * \param devmod Pointer to demodulator instance.
19296 * \param config Pointer to configuration parameters (type and data).
19297 * \return int.
19300 static int ctrl_get_cfg(struct drx_demod_instance *demod, struct drx_cfg *config)
19302 int rc;
19304 if (config == NULL)
19305 return -EINVAL;
19307 do {
19308 u16 dummy;
19309 rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, SCU_RAM_VERSION_HI__A, &dummy, 0);
19310 if (rc != 0) {
19311 pr_err("error %d\n", rc);
19312 goto rw_error;
19314 } while (0);
19316 switch (config->cfg_type) {
19317 case DRX_CFG_MPEG_OUTPUT:
19318 return ctrl_get_cfg_mpeg_output(demod,
19319 (struct drx_cfg_mpeg_output *) config->
19320 cfg_data);
19321 case DRX_CFG_PINS_SAFE_MODE:
19322 return ctrl_get_cfg_pdr_safe_mode(demod, (bool *)config->cfg_data);
19323 case DRXJ_CFG_AGC_RF:
19324 return ctrl_get_cfg_agc_rf(demod, (struct drxj_cfg_agc *) config->cfg_data);
19325 case DRXJ_CFG_AGC_IF:
19326 return ctrl_get_cfg_agc_if(demod, (struct drxj_cfg_agc *) config->cfg_data);
19327 case DRXJ_CFG_AGC_INTERNAL:
19328 return ctrl_get_cfg_agc_internal(demod, (u16 *)config->cfg_data);
19329 case DRXJ_CFG_PRE_SAW:
19330 return ctrl_get_cfg_pre_saw(demod,
19331 (struct drxj_cfg_pre_saw *) config->cfg_data);
19332 case DRXJ_CFG_AFE_GAIN:
19333 return ctrl_get_cfg_afe_gain(demod,
19334 (struct drxj_cfg_afe_gain *) config->cfg_data);
19335 case DRXJ_CFG_ACCUM_CR_RS_CW_ERR:
19336 return ctrl_get_accum_cr_rs_cw_err(demod, (u32 *)config->cfg_data);
19337 case DRXJ_CFG_FEC_MERS_SEQ_COUNT:
19338 return ctrl_get_fec_meas_seq_count(demod, (u16 *)config->cfg_data);
19339 case DRXJ_CFG_VSB_MISC:
19340 return ctrl_get_cfg_vsb_misc(demod,
19341 (struct drxj_cfg_vsb_misc *) config->cfg_data);
19342 case DRXJ_CFG_SYMBOL_CLK_OFFSET:
19343 return ctrl_get_cfg_symbol_clock_offset(demod,
19344 (s32 *)config->cfg_data);
19345 #if 0
19346 case DRXJ_CFG_OOB_MISC:
19347 return ctrl_get_cfg_oob_misc(demod,
19348 (struct drxj_cfg_oob_misc *) config->cfg_data);
19349 case DRXJ_CFG_OOB_PRE_SAW:
19350 return ctrl_get_cfg_oob_pre_saw(demod, (u16 *)(config->cfg_data));
19351 case DRXJ_CFG_OOB_LO_POW:
19352 return ctrl_get_cfg_oob_lo_power(demod,
19353 (enum drxj_cfg_oob_lo_power *) (config->
19354 cfg_data));
19355 case DRXJ_CFG_ATV_EQU_COEF:
19356 return ctrl_get_cfg_atv_equ_coef(demod,
19357 (struct drxj_cfg_atv_equ_coef *) config->
19358 cfg_data);
19359 case DRXJ_CFG_ATV_MISC:
19360 return ctrl_get_cfg_atv_misc(demod,
19361 (struct drxj_cfg_atv_misc *) config->cfg_data);
19362 case DRXJ_CFG_ATV_OUTPUT:
19363 return ctrl_get_cfg_atv_output(demod,
19364 (struct drxj_cfg_atv_output *) config->
19365 cfg_data);
19366 case DRXJ_CFG_ATV_AGC_STATUS:
19367 return ctrl_get_cfg_atv_agc_status(demod,
19368 (struct drxj_cfg_atv_agc_status *) config->
19369 cfg_data);
19370 #endif
19371 case DRXJ_CFG_MPEG_OUTPUT_MISC:
19372 return ctrl_get_cfg_mpeg_output_misc(demod,
19373 (struct drxj_cfg_mpeg_output_misc *)
19374 config->cfg_data);
19375 case DRXJ_CFG_HW_CFG:
19376 return ctrl_get_cfg_hw_cfg(demod,
19377 (struct drxj_cfg_hw_cfg *) config->cfg_data);
19378 #ifndef DRXJ_EXCLUDE_AUDIO
19379 case DRX_CFG_AUD_VOLUME:
19380 return aud_ctrl_get_cfg_volume(demod,
19381 (struct drx_cfg_aud_volume *) config->
19382 cfg_data);
19383 case DRX_CFG_I2S_OUTPUT:
19384 return aud_ctrl_get_cfg_output_i2s(demod,
19385 (struct drx_cfg_i2s_output *) config->
19386 cfg_data);
19388 case DRX_CFG_AUD_RDS:
19389 return aud_ctrl_get_cfg_rds(demod,
19390 (struct drx_cfg_aud_rds *) config->cfg_data);
19391 case DRX_CFG_AUD_AUTOSOUND:
19392 return aud_ctrl_get_cfg_auto_sound(demod,
19393 (enum drx_cfg_aud_auto_sound *) config->
19394 cfg_data);
19395 case DRX_CFG_AUD_ASS_THRES:
19396 return aud_ctrl_get_cfg_ass_thres(demod,
19397 (struct drx_cfg_aud_ass_thres *) config->
19398 cfg_data);
19399 case DRX_CFG_AUD_CARRIER:
19400 return aud_ctrl_get_cfg_carrier(demod,
19401 (struct drx_cfg_aud_carriers *) config->
19402 cfg_data);
19403 case DRX_CFG_AUD_DEVIATION:
19404 return aud_ctrl_get_cfg_dev(demod,
19405 (enum drx_cfg_aud_deviation *) config->
19406 cfg_data);
19407 case DRX_CFG_AUD_PRESCALE:
19408 return aud_ctrl_get_cfg_prescale(demod,
19409 (struct drx_cfg_aud_prescale *) config->
19410 cfg_data);
19411 case DRX_CFG_AUD_MIXER:
19412 return aud_ctrl_get_cfg_mixer(demod,
19413 (struct drx_cfg_aud_mixer *) config->cfg_data);
19414 case DRX_CFG_AUD_AVSYNC:
19415 return aud_ctrl_get_cfg_av_sync(demod,
19416 (enum drx_cfg_aud_av_sync *) config->
19417 cfg_data);
19418 #endif
19420 default:
19421 return -EINVAL;
19424 return 0;
19425 rw_error:
19426 return -EIO;
19428 #endif
19430 /*=============================================================================
19431 ===== EXPORTED FUNCTIONS ====================================================*/
19433 static int drx_ctrl_u_code(struct drx_demod_instance *demod,
19434 struct drxu_code_info *mc_info,
19435 enum drxu_code_action action);
19438 * \fn drxj_open()
19439 * \brief Open the demod instance, configure device, configure drxdriver
19440 * \return Status_t Return status.
19442 * drxj_open() can be called with a NULL ucode image => no ucode upload.
19443 * This means that drxj_open() must NOT contain SCU commands or, in general,
19444 * rely on SCU or AUD ucode to be present.
19448 int drxj_open(struct drx_demod_instance *demod)
19450 struct i2c_device_addr *dev_addr = NULL;
19451 struct drxj_data *ext_attr = NULL;
19452 struct drx_common_attr *common_attr = NULL;
19453 u32 driver_version = 0;
19454 struct drxu_code_info ucode_info;
19455 struct drx_cfg_mpeg_output cfg_mpeg_output;
19456 int rc;
19459 if ((demod == NULL) ||
19460 (demod->my_common_attr == NULL) ||
19461 (demod->my_ext_attr == NULL) ||
19462 (demod->my_i2c_dev_addr == NULL) ||
19463 (demod->my_common_attr->is_opened)) {
19464 return -EINVAL;
19467 /* Check arguments */
19468 if (demod->my_ext_attr == NULL)
19469 return -EINVAL;
19471 dev_addr = demod->my_i2c_dev_addr;
19472 ext_attr = (struct drxj_data *) demod->my_ext_attr;
19473 common_attr = (struct drx_common_attr *) demod->my_common_attr;
19475 rc = power_up_device(demod);
19476 if (rc != 0) {
19477 pr_err("error %d\n", rc);
19478 goto rw_error;
19480 common_attr->current_power_mode = DRX_POWER_UP;
19482 /* has to be in front of setIqmAf and setOrxNsuAox */
19483 rc = get_device_capabilities(demod);
19484 if (rc != 0) {
19485 pr_err("error %d\n", rc);
19486 goto rw_error;
19489 /* Soft reset of sys- and osc-clockdomain */
19490 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_CC_SOFT_RST__A, (SIO_CC_SOFT_RST_SYS__M | SIO_CC_SOFT_RST_OSC__M), 0);
19491 if (rc != 0) {
19492 pr_err("error %d\n", rc);
19493 goto rw_error;
19495 rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY, 0);
19496 if (rc != 0) {
19497 pr_err("error %d\n", rc);
19498 goto rw_error;
19500 msleep(1);
19502 /* TODO first make sure that everything keeps working before enabling this */
19503 /* PowerDownAnalogBlocks() */
19504 rc = DRXJ_DAP.write_reg16func(dev_addr, ATV_TOP_STDBY__A, (~ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE) | ATV_TOP_STDBY_SIF_STDBY_STANDBY, 0);
19505 if (rc != 0) {
19506 pr_err("error %d\n", rc);
19507 goto rw_error;
19510 rc = set_iqm_af(demod, false);
19511 if (rc != 0) {
19512 pr_err("error %d\n", rc);
19513 goto rw_error;
19515 rc = set_orx_nsu_aox(demod, false);
19516 if (rc != 0) {
19517 pr_err("error %d\n", rc);
19518 goto rw_error;
19521 rc = init_hi(demod);
19522 if (rc != 0) {
19523 pr_err("error %d\n", rc);
19524 goto rw_error;
19527 /* disable mpegoutput pins */
19528 cfg_mpeg_output.enable_mpeg_output = false;
19529 rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output);
19530 if (rc != 0) {
19531 pr_err("error %d\n", rc);
19532 goto rw_error;
19534 /* Stop AUD Inform SetAudio it will need to do all setting */
19535 rc = power_down_aud(demod);
19536 if (rc != 0) {
19537 pr_err("error %d\n", rc);
19538 goto rw_error;
19540 /* Stop SCU */
19541 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_STOP, 0);
19542 if (rc != 0) {
19543 pr_err("error %d\n", rc);
19544 goto rw_error;
19547 /* Upload microcode */
19548 if (common_attr->microcode_file != NULL) {
19549 /* Dirty trick to use common ucode upload & verify,
19550 pretend device is already open */
19551 common_attr->is_opened = true;
19552 ucode_info.mc_file = common_attr->microcode_file;
19554 if (DRX_ISPOWERDOWNMODE(demod->my_common_attr->current_power_mode)) {
19555 pr_err("Should powerup before loading the firmware.");
19556 return -EINVAL;
19559 rc = drx_ctrl_u_code(demod, &ucode_info, UCODE_UPLOAD);
19560 if (rc != 0) {
19561 pr_err("error %d while uploading the firmware\n", rc);
19562 goto rw_error;
19564 if (common_attr->verify_microcode == true) {
19565 rc = drx_ctrl_u_code(demod, &ucode_info, UCODE_VERIFY);
19566 if (rc != 0) {
19567 pr_err("error %d while verifying the firmware\n",
19568 rc);
19569 goto rw_error;
19572 common_attr->is_opened = false;
19575 /* Run SCU for a little while to initialize microcode version numbers */
19576 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE, 0);
19577 if (rc != 0) {
19578 pr_err("error %d\n", rc);
19579 goto rw_error;
19582 /* Initialize scan timeout */
19583 common_attr->scan_demod_lock_timeout = DRXJ_SCAN_TIMEOUT;
19584 common_attr->scan_desired_lock = DRX_LOCKED;
19586 drxj_reset_mode(ext_attr);
19587 ext_attr->standard = DRX_STANDARD_UNKNOWN;
19589 rc = smart_ant_init(demod);
19590 if (rc != 0) {
19591 pr_err("error %d\n", rc);
19592 goto rw_error;
19595 /* Stamp driver version number in SCU data RAM in BCD code
19596 Done to enable field application engineers to retreive drxdriver version
19597 via I2C from SCU RAM
19599 driver_version = (VERSION_MAJOR / 100) % 10;
19600 driver_version <<= 4;
19601 driver_version += (VERSION_MAJOR / 10) % 10;
19602 driver_version <<= 4;
19603 driver_version += (VERSION_MAJOR % 10);
19604 driver_version <<= 4;
19605 driver_version += (VERSION_MINOR % 10);
19606 driver_version <<= 4;
19607 driver_version += (VERSION_PATCH / 1000) % 10;
19608 driver_version <<= 4;
19609 driver_version += (VERSION_PATCH / 100) % 10;
19610 driver_version <<= 4;
19611 driver_version += (VERSION_PATCH / 10) % 10;
19612 driver_version <<= 4;
19613 driver_version += (VERSION_PATCH % 10);
19614 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_DRIVER_VER_HI__A, (u16)(driver_version >> 16), 0);
19615 if (rc != 0) {
19616 pr_err("error %d\n", rc);
19617 goto rw_error;
19619 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_RAM_DRIVER_VER_LO__A, (u16)(driver_version & 0xFFFF), 0);
19620 if (rc != 0) {
19621 pr_err("error %d\n", rc);
19622 goto rw_error;
19625 /* refresh the audio data structure with default */
19626 ext_attr->aud_data = drxj_default_aud_data_g;
19628 demod->my_common_attr->is_opened = true;
19629 return 0;
19630 rw_error:
19631 common_attr->is_opened = false;
19632 return -EIO;
19635 /*============================================================================*/
19637 * \fn drxj_close()
19638 * \brief Close the demod instance, power down the device
19639 * \return Status_t Return status.
19642 int drxj_close(struct drx_demod_instance *demod)
19644 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
19645 int rc;
19646 enum drx_power_mode power_mode = DRX_POWER_UP;
19648 if ((demod == NULL) ||
19649 (demod->my_common_attr == NULL) ||
19650 (demod->my_ext_attr == NULL) ||
19651 (demod->my_i2c_dev_addr == NULL) ||
19652 (!demod->my_common_attr->is_opened)) {
19653 return -EINVAL;
19656 /* power up */
19657 rc = ctrl_power_mode(demod, &power_mode);
19658 if (rc != 0) {
19659 pr_err("error %d\n", rc);
19660 goto rw_error;
19663 rc = DRXJ_DAP.write_reg16func(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE, 0);
19664 if (rc != 0) {
19665 pr_err("error %d\n", rc);
19666 goto rw_error;
19668 power_mode = DRX_POWER_DOWN;
19669 rc = ctrl_power_mode(demod, &power_mode);
19670 if (rc != 0) {
19671 pr_err("error %d\n", rc);
19672 goto rw_error;
19675 DRX_ATTR_ISOPENED(demod) = false;
19677 return 0;
19678 rw_error:
19679 DRX_ATTR_ISOPENED(demod) = false;
19681 return -EIO;
19685 * Microcode related functions
19689 * drx_u_code_compute_crc - Compute CRC of block of microcode data.
19690 * @block_data: Pointer to microcode data.
19691 * @nr_words: Size of microcode block (number of 16 bits words).
19693 * returns The computed CRC residue.
19695 static u16 drx_u_code_compute_crc(u8 *block_data, u16 nr_words)
19697 u16 i = 0;
19698 u16 j = 0;
19699 u32 crc_word = 0;
19700 u32 carry = 0;
19702 while (i < nr_words) {
19703 crc_word |= (u32)be16_to_cpu(*(u32 *)(block_data));
19704 for (j = 0; j < 16; j++) {
19705 crc_word <<= 1;
19706 if (carry != 0)
19707 crc_word ^= 0x80050000UL;
19708 carry = crc_word & 0x80000000UL;
19710 i++;
19711 block_data += (sizeof(u16));
19713 return (u16)(crc_word >> 16);
19717 * drx_check_firmware - checks if the loaded firmware is valid
19719 * @demod: demod structure
19720 * @mc_data: pointer to the start of the firmware
19721 * @size: firmware size
19723 static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data,
19724 unsigned size)
19726 struct drxu_code_block_hdr block_hdr;
19727 int i;
19728 unsigned count = 2 * sizeof(u16);
19729 u32 mc_dev_type, mc_version, mc_base_version;
19730 u16 mc_nr_of_blks = be16_to_cpu(*(u32 *)(mc_data + sizeof(u16)));
19733 * Scan microcode blocks first for version info
19734 * and firmware check
19737 /* Clear version block */
19738 DRX_ATTR_MCRECORD(demod).aux_type = 0;
19739 DRX_ATTR_MCRECORD(demod).mc_dev_type = 0;
19740 DRX_ATTR_MCRECORD(demod).mc_version = 0;
19741 DRX_ATTR_MCRECORD(demod).mc_base_version = 0;
19743 for (i = 0; i < mc_nr_of_blks; i++) {
19744 if (count + 3 * sizeof(u16) + sizeof(u32) > size)
19745 goto eof;
19747 /* Process block header */
19748 block_hdr.addr = be32_to_cpu(*(u32 *)(mc_data + count));
19749 count += sizeof(u32);
19750 block_hdr.size = be16_to_cpu(*(u32 *)(mc_data + count));
19751 count += sizeof(u16);
19752 block_hdr.flags = be16_to_cpu(*(u32 *)(mc_data + count));
19753 count += sizeof(u16);
19754 block_hdr.CRC = be16_to_cpu(*(u32 *)(mc_data + count));
19755 count += sizeof(u16);
19757 pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n",
19758 count, block_hdr.addr, block_hdr.size, block_hdr.flags,
19759 block_hdr.CRC);
19761 if (block_hdr.flags & 0x8) {
19762 u8 *auxblk = ((void *)mc_data) + block_hdr.addr;
19763 u16 auxtype;
19765 if (block_hdr.addr + sizeof(u16) > size)
19766 goto eof;
19768 auxtype = be16_to_cpu(*(u32 *)(auxblk));
19770 /* Aux block. Check type */
19771 if (DRX_ISMCVERTYPE(auxtype)) {
19772 if (block_hdr.addr + 2 * sizeof(u16) + 2 * sizeof (u32) > size)
19773 goto eof;
19775 auxblk += sizeof(u16);
19776 mc_dev_type = be32_to_cpu(*(u32 *)(auxblk));
19777 auxblk += sizeof(u32);
19778 mc_version = be32_to_cpu(*(u32 *)(auxblk));
19779 auxblk += sizeof(u32);
19780 mc_base_version = be32_to_cpu(*(u32 *)(auxblk));
19782 DRX_ATTR_MCRECORD(demod).aux_type = auxtype;
19783 DRX_ATTR_MCRECORD(demod).mc_dev_type = mc_dev_type;
19784 DRX_ATTR_MCRECORD(demod).mc_version = mc_version;
19785 DRX_ATTR_MCRECORD(demod).mc_base_version = mc_base_version;
19787 pr_info("Firmware dev %x, ver %x, base ver %x\n",
19788 mc_dev_type, mc_version, mc_base_version);
19791 } else if (count + block_hdr.size * sizeof(u16) > size)
19792 goto eof;
19794 count += block_hdr.size * sizeof(u16);
19796 return 0;
19797 eof:
19798 pr_err("Firmware is truncated at pos %u/%u\n", count, size);
19799 return -EINVAL;
19803 * drx_ctrl_u_code - Handle microcode upload or verify.
19804 * @dev_addr: Address of device.
19805 * @mc_info: Pointer to information about microcode data.
19806 * @action: Either UCODE_UPLOAD or UCODE_VERIFY
19808 * This function returns:
19809 * 0:
19810 * - In case of UCODE_UPLOAD: code is successfully uploaded.
19811 * - In case of UCODE_VERIFY: image on device is equal to
19812 * image provided to this control function.
19813 * -EIO:
19814 * - In case of UCODE_UPLOAD: I2C error.
19815 * - In case of UCODE_VERIFY: I2C error or image on device
19816 * is not equal to image provided to this control function.
19817 * -EINVAL:
19818 * - Invalid arguments.
19819 * - Provided image is corrupt
19821 static int drx_ctrl_u_code(struct drx_demod_instance *demod,
19822 struct drxu_code_info *mc_info,
19823 enum drxu_code_action action)
19825 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
19826 int rc;
19827 u16 i = 0;
19828 u16 mc_nr_of_blks = 0;
19829 u16 mc_magic_word = 0;
19830 const u8 *mc_data_init = NULL;
19831 u8 *mc_data = NULL;
19832 unsigned size;
19833 char *mc_file = mc_info->mc_file;
19835 /* Check arguments */
19836 if (!mc_info || !mc_file)
19837 return -EINVAL;
19839 if (!demod->firmware) {
19840 const struct firmware *fw = NULL;
19842 rc = request_firmware(&fw, mc_file, demod->i2c->dev.parent);
19843 if (rc < 0) {
19844 pr_err("Couldn't read firmware %s\n", mc_file);
19845 return -ENOENT;
19847 demod->firmware = fw;
19849 if (demod->firmware->size < 2 * sizeof(u16)) {
19850 rc = -EINVAL;
19851 pr_err("Firmware is too short!\n");
19852 goto release;
19855 pr_info("Firmware %s, size %zu\n",
19856 mc_file, demod->firmware->size);
19859 mc_data_init = demod->firmware->data;
19860 size = demod->firmware->size;
19862 mc_data = (void *)mc_data_init;
19863 /* Check data */
19864 mc_magic_word = be16_to_cpu(*(u32 *)(mc_data));
19865 mc_data += sizeof(u16);
19866 mc_nr_of_blks = be16_to_cpu(*(u32 *)(mc_data));
19867 mc_data += sizeof(u16);
19869 if ((mc_magic_word != DRX_UCODE_MAGIC_WORD) || (mc_nr_of_blks == 0)) {
19870 rc = -EINVAL;
19871 pr_err("Firmware magic word doesn't match\n");
19872 goto release;
19875 if (action == UCODE_UPLOAD) {
19876 rc = drx_check_firmware(demod, (u8 *)mc_data_init, size);
19877 if (rc)
19878 goto release;
19879 pr_info("Uploading firmware %s\n", mc_file);
19880 } else {
19881 pr_info("Verifying if firmware upload was ok.\n");
19884 /* Process microcode blocks */
19885 for (i = 0; i < mc_nr_of_blks; i++) {
19886 struct drxu_code_block_hdr block_hdr;
19887 u16 mc_block_nr_bytes = 0;
19889 /* Process block header */
19890 block_hdr.addr = be32_to_cpu(*(u32 *)(mc_data));
19891 mc_data += sizeof(u32);
19892 block_hdr.size = be16_to_cpu(*(u32 *)(mc_data));
19893 mc_data += sizeof(u16);
19894 block_hdr.flags = be16_to_cpu(*(u32 *)(mc_data));
19895 mc_data += sizeof(u16);
19896 block_hdr.CRC = be16_to_cpu(*(u32 *)(mc_data));
19897 mc_data += sizeof(u16);
19899 pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n",
19900 (unsigned)(mc_data - mc_data_init), block_hdr.addr,
19901 block_hdr.size, block_hdr.flags, block_hdr.CRC);
19903 /* Check block header on:
19904 - data larger than 64Kb
19905 - if CRC enabled check CRC
19907 if ((block_hdr.size > 0x7FFF) ||
19908 (((block_hdr.flags & DRX_UCODE_CRC_FLAG) != 0) &&
19909 (block_hdr.CRC != drx_u_code_compute_crc(mc_data, block_hdr.size)))
19911 /* Wrong data ! */
19912 rc = -EINVAL;
19913 pr_err("firmware CRC is wrong\n");
19914 goto release;
19917 if (!block_hdr.size)
19918 continue;
19920 mc_block_nr_bytes = block_hdr.size * ((u16) sizeof(u16));
19922 /* Perform the desired action */
19923 switch (action) {
19924 case UCODE_UPLOAD: /* Upload microcode */
19925 if (demod->my_access_funct->write_block_func(dev_addr,
19926 block_hdr.addr,
19927 mc_block_nr_bytes,
19928 mc_data, 0x0000)) {
19929 rc = -EIO;
19930 pr_err("error writing firmware at pos %u\n",
19931 (unsigned)(mc_data - mc_data_init));
19932 goto release;
19934 break;
19935 case UCODE_VERIFY: { /* Verify uploaded microcode */
19936 int result = 0;
19937 u8 mc_data_buffer[DRX_UCODE_MAX_BUF_SIZE];
19938 u32 bytes_to_comp = 0;
19939 u32 bytes_left = mc_block_nr_bytes;
19940 u32 curr_addr = block_hdr.addr;
19941 u8 *curr_ptr = mc_data;
19943 while (bytes_left != 0) {
19944 if (bytes_left > DRX_UCODE_MAX_BUF_SIZE)
19945 bytes_to_comp = DRX_UCODE_MAX_BUF_SIZE;
19946 else
19947 bytes_to_comp = bytes_left;
19949 if (demod->my_access_funct->
19950 read_block_func(dev_addr,
19951 curr_addr,
19952 (u16)bytes_to_comp,
19953 (u8 *)mc_data_buffer,
19954 0x0000)) {
19955 pr_err("error reading firmware at pos %u\n",
19956 (unsigned)(mc_data - mc_data_init));
19957 return -EIO;
19960 result = memcmp(curr_ptr, mc_data_buffer,
19961 bytes_to_comp);
19963 if (result) {
19964 pr_err("error verifying firmware at pos %u\n",
19965 (unsigned)(mc_data - mc_data_init));
19966 return -EIO;
19969 curr_addr += ((dr_xaddr_t)(bytes_to_comp / 2));
19970 curr_ptr =&(curr_ptr[bytes_to_comp]);
19971 bytes_left -=((u32) bytes_to_comp);
19973 break;
19975 default:
19976 return -EINVAL;
19977 break;
19980 mc_data += mc_block_nr_bytes;
19983 return 0;
19985 release:
19986 release_firmware(demod->firmware);
19987 demod->firmware = NULL;
19989 return rc;
19993 * The Linux DVB Driver for Micronas DRX39xx family (drx3933j)
19995 * Written by Devin Heitmueller <devin.heitmueller@kernellabs.com>
19998 static int drx39xxj_set_powerstate(struct dvb_frontend *fe, int enable)
20000 struct drx39xxj_state *state = fe->demodulator_priv;
20001 struct drx_demod_instance *demod = state->demod;
20002 int result;
20003 enum drx_power_mode power_mode;
20005 if (enable)
20006 power_mode = DRX_POWER_UP;
20007 else
20008 power_mode = DRX_POWER_DOWN;
20010 result = ctrl_power_mode(demod, &power_mode);
20011 if (result != 0) {
20012 pr_err("Power state change failed\n");
20013 return 0;
20016 state->powered_up = enable;
20017 return 0;
20020 static int drx39xxj_read_status(struct dvb_frontend *fe, fe_status_t *status)
20022 struct drx39xxj_state *state = fe->demodulator_priv;
20023 struct drx_demod_instance *demod = state->demod;
20024 int result;
20025 enum drx_lock_status lock_status;
20027 *status = 0;
20029 result = ctrl_lock_status(demod, &lock_status);
20030 if (result != 0) {
20031 pr_err("drx39xxj: could not get lock status!\n");
20032 *status = 0;
20035 switch (lock_status) {
20036 case DRX_NEVER_LOCK:
20037 *status = 0;
20038 pr_err("drx says NEVER_LOCK\n");
20039 break;
20040 case DRX_NOT_LOCKED:
20041 *status = 0;
20042 break;
20043 case DRX_LOCK_STATE_1:
20044 case DRX_LOCK_STATE_2:
20045 case DRX_LOCK_STATE_3:
20046 case DRX_LOCK_STATE_4:
20047 case DRX_LOCK_STATE_5:
20048 case DRX_LOCK_STATE_6:
20049 case DRX_LOCK_STATE_7:
20050 case DRX_LOCK_STATE_8:
20051 case DRX_LOCK_STATE_9:
20052 *status = FE_HAS_SIGNAL
20053 | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC;
20054 break;
20055 case DRX_LOCKED:
20056 *status = FE_HAS_SIGNAL
20057 | FE_HAS_CARRIER
20058 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
20059 break;
20060 default:
20061 pr_err("Lock state unknown %d\n", lock_status);
20064 return 0;
20067 static int drx39xxj_read_ber(struct dvb_frontend *fe, u32 *ber)
20069 struct drx39xxj_state *state = fe->demodulator_priv;
20070 struct drx_demod_instance *demod = state->demod;
20071 int result;
20072 struct drx_sig_quality sig_quality;
20074 result = ctrl_sig_quality(demod, &sig_quality);
20075 if (result != 0) {
20076 pr_err("drx39xxj: could not get ber!\n");
20077 *ber = 0;
20078 return 0;
20081 *ber = sig_quality.post_reed_solomon_ber;
20082 return 0;
20085 static int drx39xxj_read_signal_strength(struct dvb_frontend *fe,
20086 u16 *strength)
20088 struct drx39xxj_state *state = fe->demodulator_priv;
20089 struct drx_demod_instance *demod = state->demod;
20090 int result;
20091 struct drx_sig_quality sig_quality;
20093 result = ctrl_sig_quality(demod, &sig_quality);
20094 if (result != 0) {
20095 pr_err("drx39xxj: could not get signal strength!\n");
20096 *strength = 0;
20097 return 0;
20100 /* 1-100% scaled to 0-65535 */
20101 *strength = (sig_quality.indicator * 65535 / 100);
20102 return 0;
20105 static int drx39xxj_read_snr(struct dvb_frontend *fe, u16 *snr)
20107 struct drx39xxj_state *state = fe->demodulator_priv;
20108 struct drx_demod_instance *demod = state->demod;
20109 int result;
20110 struct drx_sig_quality sig_quality;
20112 result = ctrl_sig_quality(demod, &sig_quality);
20113 if (result != 0) {
20114 pr_err("drx39xxj: could not read snr!\n");
20115 *snr = 0;
20116 return 0;
20119 *snr = sig_quality.MER;
20120 return 0;
20123 static int drx39xxj_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
20125 struct drx39xxj_state *state = fe->demodulator_priv;
20126 struct drx_demod_instance *demod = state->demod;
20127 int result;
20128 struct drx_sig_quality sig_quality;
20130 result = ctrl_sig_quality(demod, &sig_quality);
20131 if (result != 0) {
20132 pr_err("drx39xxj: could not get uc blocks!\n");
20133 *ucblocks = 0;
20134 return 0;
20137 *ucblocks = sig_quality.packet_error;
20138 return 0;
20141 static int drx39xxj_set_frontend(struct dvb_frontend *fe)
20143 #ifdef DJH_DEBUG
20144 int i;
20145 #endif
20146 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
20147 struct drx39xxj_state *state = fe->demodulator_priv;
20148 struct drx_demod_instance *demod = state->demod;
20149 enum drx_standard standard = DRX_STANDARD_8VSB;
20150 struct drx_channel channel;
20151 int result;
20152 struct drxuio_data uio_data;
20153 static const struct drx_channel def_channel = {
20154 /* frequency */ 0,
20155 /* bandwidth */ DRX_BANDWIDTH_6MHZ,
20156 /* mirror */ DRX_MIRROR_NO,
20157 /* constellation */ DRX_CONSTELLATION_AUTO,
20158 /* hierarchy */ DRX_HIERARCHY_UNKNOWN,
20159 /* priority */ DRX_PRIORITY_UNKNOWN,
20160 /* coderate */ DRX_CODERATE_UNKNOWN,
20161 /* guard */ DRX_GUARD_UNKNOWN,
20162 /* fftmode */ DRX_FFTMODE_UNKNOWN,
20163 /* classification */ DRX_CLASSIFICATION_AUTO,
20164 /* symbolrate */ 5057000,
20165 /* interleavemode */ DRX_INTERLEAVEMODE_UNKNOWN,
20166 /* ldpc */ DRX_LDPC_UNKNOWN,
20167 /* carrier */ DRX_CARRIER_UNKNOWN,
20168 /* frame mode */ DRX_FRAMEMODE_UNKNOWN
20170 u32 constellation = DRX_CONSTELLATION_AUTO;
20172 /* Bring the demod out of sleep */
20173 drx39xxj_set_powerstate(fe, 1);
20175 if (fe->ops.tuner_ops.set_params) {
20176 u32 int_freq;
20178 if (fe->ops.i2c_gate_ctrl)
20179 fe->ops.i2c_gate_ctrl(fe, 1);
20181 /* Set tuner to desired frequency and standard */
20182 fe->ops.tuner_ops.set_params(fe);
20184 /* Use the tuner's IF */
20185 if (fe->ops.tuner_ops.get_if_frequency) {
20186 fe->ops.tuner_ops.get_if_frequency(fe, &int_freq);
20187 demod->my_common_attr->intermediate_freq = int_freq / 1000;
20190 if (fe->ops.i2c_gate_ctrl)
20191 fe->ops.i2c_gate_ctrl(fe, 0);
20194 switch (p->delivery_system) {
20195 case SYS_ATSC:
20196 standard = DRX_STANDARD_8VSB;
20197 break;
20198 case SYS_DVBC_ANNEX_B:
20199 standard = DRX_STANDARD_ITU_B;
20201 switch (p->modulation) {
20202 case QAM_64:
20203 constellation = DRX_CONSTELLATION_QAM64;
20204 break;
20205 case QAM_256:
20206 constellation = DRX_CONSTELLATION_QAM256;
20207 break;
20208 default:
20209 constellation = DRX_CONSTELLATION_AUTO;
20210 break;
20212 break;
20213 default:
20214 return -EINVAL;
20217 if (standard != state->current_standard || state->powered_up == 0) {
20218 /* Set the standard (will be powered up if necessary */
20219 result = ctrl_set_standard(demod, &standard);
20220 if (result != 0) {
20221 pr_err("Failed to set standard! result=%02x\n",
20222 result);
20223 return -EINVAL;
20225 state->powered_up = 1;
20226 state->current_standard = standard;
20229 /* set channel parameters */
20230 channel = def_channel;
20231 channel.frequency = p->frequency / 1000;
20232 channel.bandwidth = DRX_BANDWIDTH_6MHZ;
20233 channel.constellation = constellation;
20235 /* program channel */
20236 result = ctrl_set_channel(demod, &channel);
20237 if (result != 0) {
20238 pr_err("Failed to set channel!\n");
20239 return -EINVAL;
20241 /* Just for giggles, let's shut off the LNA again.... */
20242 uio_data.uio = DRX_UIO1;
20243 uio_data.value = false;
20244 result = ctrl_uio_write(demod, &uio_data);
20245 if (result != 0) {
20246 pr_err("Failed to disable LNA!\n");
20247 return 0;
20249 #ifdef DJH_DEBUG
20250 for (i = 0; i < 2000; i++) {
20251 fe_status_t status;
20252 drx39xxj_read_status(fe, &status);
20253 pr_dbg("i=%d status=%d\n", i, status);
20254 msleep(100);
20255 i += 100;
20257 #endif
20259 return 0;
20262 static int drx39xxj_sleep(struct dvb_frontend *fe)
20264 /* power-down the demodulator */
20265 return drx39xxj_set_powerstate(fe, 0);
20268 static int drx39xxj_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
20270 struct drx39xxj_state *state = fe->demodulator_priv;
20271 struct drx_demod_instance *demod = state->demod;
20272 bool i2c_gate_state;
20273 int result;
20275 #ifdef DJH_DEBUG
20276 pr_dbg("i2c gate call: enable=%d state=%d\n", enable,
20277 state->i2c_gate_open);
20278 #endif
20280 if (enable)
20281 i2c_gate_state = true;
20282 else
20283 i2c_gate_state = false;
20285 if (state->i2c_gate_open == enable) {
20286 /* We're already in the desired state */
20287 return 0;
20290 result = ctrl_i2c_bridge(demod, &i2c_gate_state);
20291 if (result != 0) {
20292 pr_err("drx39xxj: could not open i2c gate [%d]\n",
20293 result);
20294 dump_stack();
20295 } else {
20296 state->i2c_gate_open = enable;
20298 return 0;
20301 static int drx39xxj_init(struct dvb_frontend *fe)
20303 /* Bring the demod out of sleep */
20304 drx39xxj_set_powerstate(fe, 1);
20306 return 0;
20309 static int drx39xxj_get_tune_settings(struct dvb_frontend *fe,
20310 struct dvb_frontend_tune_settings *tune)
20312 tune->min_delay_ms = 1000;
20313 return 0;
20316 static void drx39xxj_release(struct dvb_frontend *fe)
20318 struct drx39xxj_state *state = fe->demodulator_priv;
20319 struct drx_demod_instance *demod = state->demod;
20321 kfree(demod->my_ext_attr);
20322 kfree(demod->my_common_attr);
20323 kfree(demod->my_i2c_dev_addr);
20324 if (demod->firmware)
20325 release_firmware(demod->firmware);
20326 kfree(demod);
20327 kfree(state);
20330 static struct dvb_frontend_ops drx39xxj_ops;
20332 struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c)
20334 struct drx39xxj_state *state = NULL;
20336 struct i2c_device_addr *demod_addr = NULL;
20337 struct drx_common_attr *demod_comm_attr = NULL;
20338 struct drxj_data *demod_ext_attr = NULL;
20339 struct drx_demod_instance *demod = NULL;
20340 struct drxuio_cfg uio_cfg;
20341 struct drxuio_data uio_data;
20342 int result;
20344 /* allocate memory for the internal state */
20345 state = kzalloc(sizeof(struct drx39xxj_state), GFP_KERNEL);
20346 if (state == NULL)
20347 goto error;
20349 demod = kmalloc(sizeof(struct drx_demod_instance), GFP_KERNEL);
20350 if (demod == NULL)
20351 goto error;
20353 demod_addr = kmalloc(sizeof(struct i2c_device_addr), GFP_KERNEL);
20354 if (demod_addr == NULL)
20355 goto error;
20356 memcpy(demod_addr, &drxj_default_addr_g,
20357 sizeof(struct i2c_device_addr));
20359 demod_comm_attr = kmalloc(sizeof(struct drx_common_attr), GFP_KERNEL);
20360 if (demod_comm_attr == NULL)
20361 goto error;
20362 memcpy(demod_comm_attr, &drxj_default_comm_attr_g,
20363 sizeof(struct drx_common_attr));
20365 demod_ext_attr = kmalloc(sizeof(struct drxj_data), GFP_KERNEL);
20366 if (demod_ext_attr == NULL)
20367 goto error;
20368 memcpy(demod_ext_attr, &drxj_data_g, sizeof(struct drxj_data));
20370 /* setup the state */
20371 state->i2c = i2c;
20372 state->demod = demod;
20374 /* setup the demod data */
20375 memcpy(demod, &drxj_default_demod_g, sizeof(struct drx_demod_instance));
20377 demod->my_i2c_dev_addr = demod_addr;
20378 demod->my_common_attr = demod_comm_attr;
20379 demod->my_i2c_dev_addr->user_data = state;
20380 demod->my_common_attr->microcode_file = DRX39XX_MAIN_FIRMWARE;
20381 demod->my_common_attr->verify_microcode = true;
20382 demod->my_common_attr->intermediate_freq = 5000;
20383 demod->my_ext_attr = demod_ext_attr;
20384 ((struct drxj_data *)demod_ext_attr)->uio_sma_tx_mode = DRX_UIO_MODE_READWRITE;
20385 demod->i2c = i2c;
20387 result = drxj_open(demod);
20388 if (result != 0) {
20389 pr_err("DRX open failed! Aborting\n");
20390 goto error;
20393 /* Turn off the LNA */
20394 uio_cfg.uio = DRX_UIO1;
20395 uio_cfg.mode = DRX_UIO_MODE_READWRITE;
20396 /* Configure user-I/O #3: enable read/write */
20397 result = ctrl_set_uio_cfg(demod, &uio_cfg);
20398 if (result) {
20399 pr_err("Failed to setup LNA GPIO!\n");
20400 goto error;
20403 uio_data.uio = DRX_UIO1;
20404 uio_data.value = false;
20405 result = ctrl_uio_write(demod, &uio_data);
20406 if (result != 0) {
20407 pr_err("Failed to disable LNA!\n");
20408 goto error;
20411 /* create dvb_frontend */
20412 memcpy(&state->frontend.ops, &drx39xxj_ops,
20413 sizeof(struct dvb_frontend_ops));
20415 state->frontend.demodulator_priv = state;
20416 return &state->frontend;
20418 error:
20419 kfree(demod_ext_attr);
20420 kfree(demod_comm_attr);
20421 kfree(demod_addr);
20422 kfree(demod);
20423 kfree(state);
20425 return NULL;
20427 EXPORT_SYMBOL(drx39xxj_attach);
20429 static struct dvb_frontend_ops drx39xxj_ops = {
20430 .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
20431 .info = {
20432 .name = "Micronas DRX39xxj family Frontend",
20433 .frequency_stepsize = 62500,
20434 .frequency_min = 51000000,
20435 .frequency_max = 858000000,
20436 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
20439 .init = drx39xxj_init,
20440 .i2c_gate_ctrl = drx39xxj_i2c_gate_ctrl,
20441 .sleep = drx39xxj_sleep,
20442 .set_frontend = drx39xxj_set_frontend,
20443 .get_tune_settings = drx39xxj_get_tune_settings,
20444 .read_status = drx39xxj_read_status,
20445 .read_ber = drx39xxj_read_ber,
20446 .read_signal_strength = drx39xxj_read_signal_strength,
20447 .read_snr = drx39xxj_read_snr,
20448 .read_ucblocks = drx39xxj_read_ucblocks,
20449 .release = drx39xxj_release,
20452 MODULE_DESCRIPTION("Micronas DRX39xxj Frontend");
20453 MODULE_AUTHOR("Devin Heitmueller");
20454 MODULE_LICENSE("GPL");
20455 MODULE_FIRMWARE(DRX39XX_MAIN_FIRMWARE);