Commit | Line | Data |
---|---|---|
ca3355a9 DH |
1 | /* |
2 | Copyright (c), 2004-2005,2007-2010 Trident Microsystems, Inc. | |
3 | All rights reserved. | |
4 | ||
5 | Redistribution and use in source and binary forms, with or without | |
6 | modification, are permitted provided that the following conditions are met: | |
7 | ||
8 | * Redistributions of source code must retain the above copyright notice, | |
9 | this list of conditions and the following disclaimer. | |
10 | * Redistributions in binary form must reproduce the above copyright notice, | |
11 | this list of conditions and the following disclaimer in the documentation | |
12 | and/or other materials provided with the distribution. | |
13 | * Neither the name of Trident Microsystems nor Hauppauge Computer Works | |
14 | nor the names of its contributors may be used to endorse or promote | |
15 | products derived from this software without specific prior written | |
16 | permission. | |
17 | ||
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
21 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | |
22 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
23 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
24 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
25 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
26 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
27 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
28 | POSSIBILITY OF SUCH DAMAGE. | |
ca3355a9 | 29 | |
63713517 MCC |
30 | DRXJ specific implementation of DRX driver |
31 | authors: Dragan Savic, Milos Nikolic, Mihajlo Katona, Tao Ding, Paul Janssen | |
19013747 MCC |
32 | |
33 | The Linux DVB Driver for Micronas DRX39xx family (drx3933j) was | |
34 | written by Devin Heitmueller <devin.heitmueller@kernellabs.com> | |
35 | ||
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. | |
40 | ||
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 | |
44 | ||
45 | GNU General Public License for more details. | |
46 | ||
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. | |
38b2df95 DH |
50 | */ |
51 | ||
38b2df95 DH |
52 | /*----------------------------------------------------------------------------- |
53 | INCLUDE FILES | |
54 | ----------------------------------------------------------------------------*/ | |
55 | ||
935c6654 | 56 | #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ |
068e94ea | 57 | |
19013747 MCC |
58 | #include <linux/module.h> |
59 | #include <linux/init.h> | |
60 | #include <linux/string.h> | |
61 | #include <linux/slab.h> | |
90d9c3e1 | 62 | #include <asm/div64.h> |
19013747 | 63 | |
fada1935 | 64 | #include <media/dvb_frontend.h> |
19013747 MCC |
65 | #include "drx39xxj.h" |
66 | ||
38b2df95 DH |
67 | #include "drxj.h" |
68 | #include "drxj_map.h" | |
69 | ||
38b2df95 DH |
70 | /*============================================================================*/ |
71 | /*=== DEFINES ================================================================*/ | |
72 | /*============================================================================*/ | |
73 | ||
19013747 MCC |
74 | #define DRX39XX_MAIN_FIRMWARE "dvb-fe-drxj-mc-1.0.8.fw" |
75 | ||
34eb9751 | 76 | /* |
43a431e4 | 77 | * \brief Maximum u32 value. |
38b2df95 DH |
78 | */ |
79 | #ifndef MAX_U32 | |
43a431e4 | 80 | #define MAX_U32 ((u32) (0xFFFFFFFFL)) |
38b2df95 DH |
81 | #endif |
82 | ||
83 | /* Customer configurable hardware settings, etc */ | |
84 | #ifndef MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH | |
85 | #define MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH 0x02 | |
86 | #endif | |
87 | ||
88 | #ifndef MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH | |
89 | #define MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH 0x02 | |
90 | #endif | |
91 | ||
92 | #ifndef MPEG_OUTPUT_CLK_DRIVE_STRENGTH | |
93 | #define MPEG_OUTPUT_CLK_DRIVE_STRENGTH 0x06 | |
94 | #endif | |
95 | ||
96 | #ifndef OOB_CRX_DRIVE_STRENGTH | |
97 | #define OOB_CRX_DRIVE_STRENGTH 0x02 | |
98 | #endif | |
99 | ||
100 | #ifndef OOB_DRX_DRIVE_STRENGTH | |
101 | #define OOB_DRX_DRIVE_STRENGTH 0x02 | |
102 | #endif | |
34eb9751 MCC |
103 | /*** START DJCOMBO patches to DRXJ registermap constants *********************/ |
104 | /*** registermap 200706071303 from drxj **************************************/ | |
38b2df95 DH |
105 | #define ATV_TOP_CR_AMP_TH_FM 0x0 |
106 | #define ATV_TOP_CR_AMP_TH_L 0xA | |
107 | #define ATV_TOP_CR_AMP_TH_LP 0xA | |
108 | #define ATV_TOP_CR_AMP_TH_BG 0x8 | |
109 | #define ATV_TOP_CR_AMP_TH_DK 0x8 | |
110 | #define ATV_TOP_CR_AMP_TH_I 0x8 | |
111 | #define ATV_TOP_CR_CONT_CR_D_MN 0x18 | |
112 | #define ATV_TOP_CR_CONT_CR_D_FM 0x0 | |
113 | #define ATV_TOP_CR_CONT_CR_D_L 0x20 | |
114 | #define ATV_TOP_CR_CONT_CR_D_LP 0x20 | |
115 | #define ATV_TOP_CR_CONT_CR_D_BG 0x18 | |
116 | #define ATV_TOP_CR_CONT_CR_D_DK 0x18 | |
117 | #define ATV_TOP_CR_CONT_CR_D_I 0x18 | |
118 | #define ATV_TOP_CR_CONT_CR_I_MN 0x80 | |
119 | #define ATV_TOP_CR_CONT_CR_I_FM 0x0 | |
120 | #define ATV_TOP_CR_CONT_CR_I_L 0x80 | |
121 | #define ATV_TOP_CR_CONT_CR_I_LP 0x80 | |
122 | #define ATV_TOP_CR_CONT_CR_I_BG 0x80 | |
123 | #define ATV_TOP_CR_CONT_CR_I_DK 0x80 | |
124 | #define ATV_TOP_CR_CONT_CR_I_I 0x80 | |
125 | #define ATV_TOP_CR_CONT_CR_P_MN 0x4 | |
126 | #define ATV_TOP_CR_CONT_CR_P_FM 0x0 | |
127 | #define ATV_TOP_CR_CONT_CR_P_L 0x4 | |
128 | #define ATV_TOP_CR_CONT_CR_P_LP 0x4 | |
129 | #define ATV_TOP_CR_CONT_CR_P_BG 0x4 | |
130 | #define ATV_TOP_CR_CONT_CR_P_DK 0x4 | |
131 | #define ATV_TOP_CR_CONT_CR_P_I 0x4 | |
132 | #define ATV_TOP_CR_OVM_TH_MN 0xA0 | |
133 | #define ATV_TOP_CR_OVM_TH_FM 0x0 | |
134 | #define ATV_TOP_CR_OVM_TH_L 0xA0 | |
135 | #define ATV_TOP_CR_OVM_TH_LP 0xA0 | |
136 | #define ATV_TOP_CR_OVM_TH_BG 0xA0 | |
137 | #define ATV_TOP_CR_OVM_TH_DK 0xA0 | |
138 | #define ATV_TOP_CR_OVM_TH_I 0xA0 | |
139 | #define ATV_TOP_EQU0_EQU_C0_FM 0x0 | |
140 | #define ATV_TOP_EQU0_EQU_C0_L 0x3 | |
141 | #define ATV_TOP_EQU0_EQU_C0_LP 0x3 | |
142 | #define ATV_TOP_EQU0_EQU_C0_BG 0x7 | |
143 | #define ATV_TOP_EQU0_EQU_C0_DK 0x0 | |
144 | #define ATV_TOP_EQU0_EQU_C0_I 0x3 | |
145 | #define ATV_TOP_EQU1_EQU_C1_FM 0x0 | |
146 | #define ATV_TOP_EQU1_EQU_C1_L 0x1F6 | |
147 | #define ATV_TOP_EQU1_EQU_C1_LP 0x1F6 | |
148 | #define ATV_TOP_EQU1_EQU_C1_BG 0x197 | |
149 | #define ATV_TOP_EQU1_EQU_C1_DK 0x198 | |
150 | #define ATV_TOP_EQU1_EQU_C1_I 0x1F6 | |
151 | #define ATV_TOP_EQU2_EQU_C2_FM 0x0 | |
152 | #define ATV_TOP_EQU2_EQU_C2_L 0x28 | |
153 | #define ATV_TOP_EQU2_EQU_C2_LP 0x28 | |
154 | #define ATV_TOP_EQU2_EQU_C2_BG 0xC5 | |
155 | #define ATV_TOP_EQU2_EQU_C2_DK 0xB0 | |
156 | #define ATV_TOP_EQU2_EQU_C2_I 0x28 | |
157 | #define ATV_TOP_EQU3_EQU_C3_FM 0x0 | |
158 | #define ATV_TOP_EQU3_EQU_C3_L 0x192 | |
159 | #define ATV_TOP_EQU3_EQU_C3_LP 0x192 | |
160 | #define ATV_TOP_EQU3_EQU_C3_BG 0x12E | |
161 | #define ATV_TOP_EQU3_EQU_C3_DK 0x18E | |
162 | #define ATV_TOP_EQU3_EQU_C3_I 0x192 | |
163 | #define ATV_TOP_STD_MODE_MN 0x0 | |
164 | #define ATV_TOP_STD_MODE_FM 0x1 | |
165 | #define ATV_TOP_STD_MODE_L 0x0 | |
166 | #define ATV_TOP_STD_MODE_LP 0x0 | |
167 | #define ATV_TOP_STD_MODE_BG 0x0 | |
168 | #define ATV_TOP_STD_MODE_DK 0x0 | |
169 | #define ATV_TOP_STD_MODE_I 0x0 | |
170 | #define ATV_TOP_STD_VID_POL_MN 0x0 | |
171 | #define ATV_TOP_STD_VID_POL_FM 0x0 | |
172 | #define ATV_TOP_STD_VID_POL_L 0x2 | |
173 | #define ATV_TOP_STD_VID_POL_LP 0x2 | |
174 | #define ATV_TOP_STD_VID_POL_BG 0x0 | |
175 | #define ATV_TOP_STD_VID_POL_DK 0x0 | |
176 | #define ATV_TOP_STD_VID_POL_I 0x0 | |
177 | #define ATV_TOP_VID_AMP_MN 0x380 | |
178 | #define ATV_TOP_VID_AMP_FM 0x0 | |
179 | #define ATV_TOP_VID_AMP_L 0xF50 | |
180 | #define ATV_TOP_VID_AMP_LP 0xF50 | |
181 | #define ATV_TOP_VID_AMP_BG 0x380 | |
182 | #define ATV_TOP_VID_AMP_DK 0x394 | |
183 | #define ATV_TOP_VID_AMP_I 0x3D8 | |
184 | #define IQM_CF_OUT_ENA_OFDM__M 0x4 | |
185 | #define IQM_FS_ADJ_SEL_B_QAM 0x1 | |
186 | #define IQM_FS_ADJ_SEL_B_OFF 0x0 | |
187 | #define IQM_FS_ADJ_SEL_B_VSB 0x2 | |
188 | #define IQM_RC_ADJ_SEL_B_OFF 0x0 | |
189 | #define IQM_RC_ADJ_SEL_B_QAM 0x1 | |
190 | #define IQM_RC_ADJ_SEL_B_VSB 0x2 | |
34eb9751 | 191 | /*** END DJCOMBO patches to DRXJ registermap *********************************/ |
38b2df95 DH |
192 | |
193 | #include "drx_driver_version.h" | |
194 | ||
7ef66759 | 195 | /* #define DRX_DEBUG */ |
38b2df95 DH |
196 | #ifdef DRX_DEBUG |
197 | #include <stdio.h> | |
198 | #endif | |
199 | ||
200 | /*----------------------------------------------------------------------------- | |
201 | ENUMS | |
202 | ----------------------------------------------------------------------------*/ | |
203 | ||
204 | /*----------------------------------------------------------------------------- | |
205 | DEFINES | |
206 | ----------------------------------------------------------------------------*/ | |
207 | #ifndef DRXJ_WAKE_UP_KEY | |
57afe2f0 | 208 | #define DRXJ_WAKE_UP_KEY (demod->my_i2c_dev_addr->i2c_addr) |
38b2df95 DH |
209 | #endif |
210 | ||
34eb9751 | 211 | /* |
38b2df95 | 212 | * \def DRXJ_DEF_I2C_ADDR |
69bb7ab6 | 213 | * \brief Default I2C address of a demodulator instance. |
38b2df95 DH |
214 | */ |
215 | #define DRXJ_DEF_I2C_ADDR (0x52) | |
216 | ||
34eb9751 | 217 | /* |
38b2df95 DH |
218 | * \def DRXJ_DEF_DEMOD_DEV_ID |
219 | * \brief Default device identifier of a demodultor instance. | |
220 | */ | |
221 | #define DRXJ_DEF_DEMOD_DEV_ID (1) | |
222 | ||
34eb9751 | 223 | /* |
38b2df95 DH |
224 | * \def DRXJ_SCAN_TIMEOUT |
225 | * \brief Timeout value for waiting on demod lock during channel scan (millisec). | |
226 | */ | |
227 | #define DRXJ_SCAN_TIMEOUT 1000 | |
228 | ||
34eb9751 | 229 | /* |
38b2df95 DH |
230 | * \def HI_I2C_DELAY |
231 | * \brief HI timing delay for I2C timing (in nano seconds) | |
232 | * | |
233 | * Used to compute HI_CFG_DIV | |
234 | */ | |
235 | #define HI_I2C_DELAY 42 | |
236 | ||
34eb9751 | 237 | /* |
38b2df95 DH |
238 | * \def HI_I2C_BRIDGE_DELAY |
239 | * \brief HI timing delay for I2C timing (in nano seconds) | |
240 | * | |
241 | * Used to compute HI_CFG_BDL | |
242 | */ | |
243 | #define HI_I2C_BRIDGE_DELAY 750 | |
244 | ||
34eb9751 | 245 | /* |
38b2df95 DH |
246 | * \brief Time Window for MER and SER Measurement in Units of Segment duration. |
247 | */ | |
248 | #define VSB_TOP_MEASUREMENT_PERIOD 64 | |
249 | #define SYMBOLS_PER_SEGMENT 832 | |
250 | ||
34eb9751 | 251 | /* |
38b2df95 DH |
252 | * \brief bit rate and segment rate constants used for SER and BER. |
253 | */ | |
254 | /* values taken from the QAM microcode */ | |
255 | #define DRXJ_QAM_SL_SIG_POWER_QAM_UNKNOWN 0 | |
256 | #define DRXJ_QAM_SL_SIG_POWER_QPSK 32768 | |
257 | #define DRXJ_QAM_SL_SIG_POWER_QAM8 24576 | |
258 | #define DRXJ_QAM_SL_SIG_POWER_QAM16 40960 | |
259 | #define DRXJ_QAM_SL_SIG_POWER_QAM32 20480 | |
260 | #define DRXJ_QAM_SL_SIG_POWER_QAM64 43008 | |
261 | #define DRXJ_QAM_SL_SIG_POWER_QAM128 20992 | |
262 | #define DRXJ_QAM_SL_SIG_POWER_QAM256 43520 | |
34eb9751 | 263 | /* |
38b2df95 DH |
264 | * \brief Min supported symbolrates. |
265 | */ | |
266 | #ifndef DRXJ_QAM_SYMBOLRATE_MIN | |
267 | #define DRXJ_QAM_SYMBOLRATE_MIN (520000) | |
268 | #endif | |
269 | ||
34eb9751 | 270 | /* |
38b2df95 DH |
271 | * \brief Max supported symbolrates. |
272 | */ | |
273 | #ifndef DRXJ_QAM_SYMBOLRATE_MAX | |
274 | #define DRXJ_QAM_SYMBOLRATE_MAX (7233000) | |
275 | #endif | |
276 | ||
34eb9751 | 277 | /* |
38b2df95 DH |
278 | * \def DRXJ_QAM_MAX_WAITTIME |
279 | * \brief Maximal wait time for QAM auto constellation in ms | |
280 | */ | |
281 | #ifndef DRXJ_QAM_MAX_WAITTIME | |
282 | #define DRXJ_QAM_MAX_WAITTIME 900 | |
283 | #endif | |
284 | ||
285 | #ifndef DRXJ_QAM_FEC_LOCK_WAITTIME | |
286 | #define DRXJ_QAM_FEC_LOCK_WAITTIME 150 | |
287 | #endif | |
288 | ||
289 | #ifndef DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME | |
290 | #define DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME 200 | |
291 | #endif | |
292 | ||
34eb9751 | 293 | /* |
38b2df95 DH |
294 | * \def SCU status and results |
295 | * \brief SCU | |
296 | */ | |
297 | #define DRX_SCU_READY 0 | |
443f18d0 MCC |
298 | #define DRXJ_MAX_WAITTIME 100 /* ms */ |
299 | #define FEC_RS_MEASUREMENT_PERIOD 12894 /* 1 sec */ | |
300 | #define FEC_RS_MEASUREMENT_PRESCALE 1 /* n sec */ | |
38b2df95 | 301 | |
34eb9751 | 302 | /* |
38b2df95 DH |
303 | * \def DRX_AUD_MAX_DEVIATION |
304 | * \brief Needed for calculation of prescale feature in AUD | |
305 | */ | |
306 | #ifndef DRXJ_AUD_MAX_FM_DEVIATION | |
443f18d0 | 307 | #define DRXJ_AUD_MAX_FM_DEVIATION 100 /* kHz */ |
38b2df95 DH |
308 | #endif |
309 | ||
34eb9751 | 310 | /* |
38b2df95 DH |
311 | * \brief Needed for calculation of NICAM prescale feature in AUD |
312 | */ | |
313 | #ifndef DRXJ_AUD_MAX_NICAM_PRESCALE | |
443f18d0 | 314 | #define DRXJ_AUD_MAX_NICAM_PRESCALE (9) /* dB */ |
38b2df95 DH |
315 | #endif |
316 | ||
34eb9751 | 317 | /* |
38b2df95 DH |
318 | * \brief Needed for calculation of NICAM prescale feature in AUD |
319 | */ | |
320 | #ifndef DRXJ_AUD_MAX_WAITTIME | |
443f18d0 | 321 | #define DRXJ_AUD_MAX_WAITTIME 250 /* ms */ |
38b2df95 DH |
322 | #endif |
323 | ||
324 | /* ATV config changed flags */ | |
7ef66759 MCC |
325 | #define DRXJ_ATV_CHANGED_COEF (0x00000001UL) |
326 | #define DRXJ_ATV_CHANGED_PEAK_FLT (0x00000008UL) | |
327 | #define DRXJ_ATV_CHANGED_NOISE_FLT (0x00000010UL) | |
328 | #define DRXJ_ATV_CHANGED_OUTPUT (0x00000020UL) | |
329 | #define DRXJ_ATV_CHANGED_SIF_ATT (0x00000040UL) | |
38b2df95 DH |
330 | |
331 | /* UIO define */ | |
332 | #define DRX_UIO_MODE_FIRMWARE_SMA DRX_UIO_MODE_FIRMWARE0 | |
333 | #define DRX_UIO_MODE_FIRMWARE_SAW DRX_UIO_MODE_FIRMWARE1 | |
334 | ||
b240eacd MCC |
335 | /* |
336 | * MICROCODE RELATED DEFINES | |
337 | */ | |
338 | ||
69bb7ab6 | 339 | /* Magic word for checking correct Endianness of microcode data */ |
b240eacd MCC |
340 | #define DRX_UCODE_MAGIC_WORD ((((u16)'H')<<8)+((u16)'L')) |
341 | ||
342 | /* CRC flag in ucode header, flags field. */ | |
343 | #define DRX_UCODE_CRC_FLAG (0x0001) | |
344 | ||
345 | /* | |
346 | * Maximum size of buffer used to verify the microcode. | |
347 | * Must be an even number | |
348 | */ | |
349 | #define DRX_UCODE_MAX_BUF_SIZE (DRXDAP_MAX_RCHUNKSIZE) | |
350 | ||
351 | #if DRX_UCODE_MAX_BUF_SIZE & 1 | |
352 | #error DRX_UCODE_MAX_BUF_SIZE must be an even number | |
353 | #endif | |
354 | ||
355 | /* | |
356 | * Power mode macros | |
357 | */ | |
358 | ||
359 | #define DRX_ISPOWERDOWNMODE(mode) ((mode == DRX_POWER_MODE_9) || \ | |
360 | (mode == DRX_POWER_MODE_10) || \ | |
361 | (mode == DRX_POWER_MODE_11) || \ | |
362 | (mode == DRX_POWER_MODE_12) || \ | |
363 | (mode == DRX_POWER_MODE_13) || \ | |
364 | (mode == DRX_POWER_MODE_14) || \ | |
365 | (mode == DRX_POWER_MODE_15) || \ | |
366 | (mode == DRX_POWER_MODE_16) || \ | |
367 | (mode == DRX_POWER_DOWN)) | |
368 | ||
38b2df95 DH |
369 | /* Pin safe mode macro */ |
370 | #define DRXJ_PIN_SAFE_MODE 0x0000 | |
371 | /*============================================================================*/ | |
372 | /*=== GLOBAL VARIABLEs =======================================================*/ | |
373 | /*============================================================================*/ | |
34eb9751 | 374 | /* |
38b2df95 DH |
375 | */ |
376 | ||
34eb9751 | 377 | /* |
38b2df95 DH |
378 | * \brief Temporary register definitions. |
379 | * (register definitions that are not yet available in register master) | |
380 | */ | |
381 | ||
34eb9751 | 382 | /*****************************************************************************/ |
38b2df95 DH |
383 | /* Audio block 0x103 is write only. To avoid shadowing in driver accessing */ |
384 | /* RAM adresses directly. This must be READ ONLY to avoid problems. */ | |
385 | /* Writing to the interface adresses is more than only writing the RAM */ | |
386 | /* locations */ | |
34eb9751 MCC |
387 | /*****************************************************************************/ |
388 | /* | |
38b2df95 DH |
389 | * \brief RAM location of MODUS registers |
390 | */ | |
391 | #define AUD_DEM_RAM_MODUS_HI__A 0x10204A3 | |
392 | #define AUD_DEM_RAM_MODUS_HI__M 0xF000 | |
393 | ||
394 | #define AUD_DEM_RAM_MODUS_LO__A 0x10204A4 | |
395 | #define AUD_DEM_RAM_MODUS_LO__M 0x0FFF | |
396 | ||
34eb9751 | 397 | /* |
38b2df95 DH |
398 | * \brief RAM location of I2S config registers |
399 | */ | |
400 | #define AUD_DEM_RAM_I2S_CONFIG1__A 0x10204B1 | |
401 | #define AUD_DEM_RAM_I2S_CONFIG2__A 0x10204B2 | |
402 | ||
34eb9751 | 403 | /* |
38b2df95 DH |
404 | * \brief RAM location of DCO config registers |
405 | */ | |
406 | #define AUD_DEM_RAM_DCO_B_HI__A 0x1020461 | |
407 | #define AUD_DEM_RAM_DCO_B_LO__A 0x1020462 | |
408 | #define AUD_DEM_RAM_DCO_A_HI__A 0x1020463 | |
409 | #define AUD_DEM_RAM_DCO_A_LO__A 0x1020464 | |
410 | ||
34eb9751 | 411 | /* |
38b2df95 DH |
412 | * \brief RAM location of Threshold registers |
413 | */ | |
414 | #define AUD_DEM_RAM_NICAM_THRSHLD__A 0x102045A | |
415 | #define AUD_DEM_RAM_A2_THRSHLD__A 0x10204BB | |
416 | #define AUD_DEM_RAM_BTSC_THRSHLD__A 0x10204A6 | |
417 | ||
34eb9751 | 418 | /* |
38b2df95 DH |
419 | * \brief RAM location of Carrier Threshold registers |
420 | */ | |
421 | #define AUD_DEM_RAM_CM_A_THRSHLD__A 0x10204AF | |
422 | #define AUD_DEM_RAM_CM_B_THRSHLD__A 0x10204B0 | |
423 | ||
34eb9751 | 424 | /* |
38b2df95 DH |
425 | * \brief FM Matrix register fix |
426 | */ | |
7ef66759 | 427 | #ifdef AUD_DEM_WR_FM_MATRIX__A |
38b2df95 DH |
428 | #undef AUD_DEM_WR_FM_MATRIX__A |
429 | #endif | |
430 | #define AUD_DEM_WR_FM_MATRIX__A 0x105006F | |
431 | ||
432 | /*============================================================================*/ | |
34eb9751 | 433 | /* |
38b2df95 DH |
434 | * \brief Defines required for audio |
435 | */ | |
436 | #define AUD_VOLUME_ZERO_DB 115 | |
437 | #define AUD_VOLUME_DB_MIN -60 | |
438 | #define AUD_VOLUME_DB_MAX 12 | |
439 | #define AUD_CARRIER_STRENGTH_QP_0DB 0x4000 | |
440 | #define AUD_CARRIER_STRENGTH_QP_0DB_LOG10T100 421 | |
441 | #define AUD_MAX_AVC_REF_LEVEL 15 | |
442 | #define AUD_I2S_FREQUENCY_MAX 48000UL | |
443 | #define AUD_I2S_FREQUENCY_MIN 12000UL | |
444 | #define AUD_RDS_ARRAY_SIZE 18 | |
445 | ||
34eb9751 | 446 | /* |
38b2df95 DH |
447 | * \brief Needed for calculation of prescale feature in AUD |
448 | */ | |
449 | #ifndef DRX_AUD_MAX_FM_DEVIATION | |
443f18d0 | 450 | #define DRX_AUD_MAX_FM_DEVIATION (100) /* kHz */ |
38b2df95 DH |
451 | #endif |
452 | ||
34eb9751 | 453 | /* |
38b2df95 DH |
454 | * \brief Needed for calculation of NICAM prescale feature in AUD |
455 | */ | |
456 | #ifndef DRX_AUD_MAX_NICAM_PRESCALE | |
443f18d0 | 457 | #define DRX_AUD_MAX_NICAM_PRESCALE (9) /* dB */ |
38b2df95 DH |
458 | #endif |
459 | ||
38b2df95 DH |
460 | /*============================================================================*/ |
461 | /* Values for I2S Master/Slave pin configurations */ | |
462 | #define SIO_PDR_I2S_CL_CFG_MODE__MASTER 0x0004 | |
463 | #define SIO_PDR_I2S_CL_CFG_DRIVE__MASTER 0x0008 | |
464 | #define SIO_PDR_I2S_CL_CFG_MODE__SLAVE 0x0004 | |
465 | #define SIO_PDR_I2S_CL_CFG_DRIVE__SLAVE 0x0000 | |
466 | ||
467 | #define SIO_PDR_I2S_DA_CFG_MODE__MASTER 0x0003 | |
468 | #define SIO_PDR_I2S_DA_CFG_DRIVE__MASTER 0x0008 | |
469 | #define SIO_PDR_I2S_DA_CFG_MODE__SLAVE 0x0003 | |
470 | #define SIO_PDR_I2S_DA_CFG_DRIVE__SLAVE 0x0008 | |
471 | ||
472 | #define SIO_PDR_I2S_WS_CFG_MODE__MASTER 0x0004 | |
473 | #define SIO_PDR_I2S_WS_CFG_DRIVE__MASTER 0x0008 | |
474 | #define SIO_PDR_I2S_WS_CFG_MODE__SLAVE 0x0004 | |
475 | #define SIO_PDR_I2S_WS_CFG_DRIVE__SLAVE 0x0000 | |
476 | ||
477 | /*============================================================================*/ | |
478 | /*=== REGISTER ACCESS MACROS =================================================*/ | |
479 | /*============================================================================*/ | |
480 | ||
34eb9751 | 481 | /* |
38b2df95 DH |
482 | * This macro is used to create byte arrays for block writes. |
483 | * Block writes speed up I2C traffic between host and demod. | |
484 | * The macro takes care of the required byte order in a 16 bits word. | |
485 | * x -> lowbyte(x), highbyte(x) | |
486 | */ | |
7ef66759 | 487 | #define DRXJ_16TO8(x) ((u8) (((u16)x) & 0xFF)), \ |
63713517 | 488 | ((u8)((((u16)x)>>8)&0xFF)) |
34eb9751 | 489 | /* |
38b2df95 DH |
490 | * This macro is used to convert byte array to 16 bit register value for block read. |
491 | * Block read speed up I2C traffic between host and demod. | |
492 | * The macro takes care of the required byte order in a 16 bits word. | |
493 | */ | |
7ef66759 | 494 | #define DRXJ_8TO16(x) ((u16) (x[0] | (x[1] << 8))) |
38b2df95 DH |
495 | |
496 | /*============================================================================*/ | |
497 | /*=== MISC DEFINES ===========================================================*/ | |
498 | /*============================================================================*/ | |
499 | ||
500 | /*============================================================================*/ | |
501 | /*=== HI COMMAND RELATED DEFINES =============================================*/ | |
502 | /*============================================================================*/ | |
503 | ||
34eb9751 | 504 | /* |
38b2df95 DH |
505 | * \brief General maximum number of retries for ucode command interfaces |
506 | */ | |
507 | #define DRXJ_MAX_RETRIES (100) | |
508 | ||
509 | /*============================================================================*/ | |
510 | /*=== STANDARD RELATED MACROS ================================================*/ | |
511 | /*============================================================================*/ | |
512 | ||
adc0e258 | 513 | #define DRXJ_ISATVSTD(std) ((std == DRX_STANDARD_PAL_SECAM_BG) || \ |
7ef66759 MCC |
514 | (std == DRX_STANDARD_PAL_SECAM_DK) || \ |
515 | (std == DRX_STANDARD_PAL_SECAM_I) || \ | |
516 | (std == DRX_STANDARD_PAL_SECAM_L) || \ | |
517 | (std == DRX_STANDARD_PAL_SECAM_LP) || \ | |
518 | (std == DRX_STANDARD_NTSC) || \ | |
22892268 | 519 | (std == DRX_STANDARD_FM)) |
38b2df95 | 520 | |
adc0e258 | 521 | #define DRXJ_ISQAMSTD(std) ((std == DRX_STANDARD_ITU_A) || \ |
7ef66759 MCC |
522 | (std == DRX_STANDARD_ITU_B) || \ |
523 | (std == DRX_STANDARD_ITU_C) || \ | |
524 | (std == DRX_STANDARD_ITU_D)) | |
38b2df95 | 525 | |
38b2df95 DH |
526 | /*----------------------------------------------------------------------------- |
527 | GLOBAL VARIABLES | |
528 | ----------------------------------------------------------------------------*/ | |
529 | /* | |
530 | * DRXJ DAP structures | |
531 | */ | |
532 | ||
244c0e06 | 533 | static int drxdap_fasi_read_block(struct i2c_device_addr *dev_addr, |
1bfc9e15 | 534 | u32 addr, |
43a431e4 | 535 | u16 datasize, |
1bfc9e15 | 536 | u8 *data, u32 flags); |
443f18d0 | 537 | |
443f18d0 | 538 | |
57afe2f0 | 539 | static int drxj_dap_read_modify_write_reg16(struct i2c_device_addr *dev_addr, |
1bfc9e15 MCC |
540 | u32 waddr, |
541 | u32 raddr, | |
43a431e4 | 542 | u16 wdata, u16 *rdata); |
443f18d0 | 543 | |
57afe2f0 | 544 | static int drxj_dap_read_reg16(struct i2c_device_addr *dev_addr, |
1bfc9e15 MCC |
545 | u32 addr, |
546 | u16 *data, u32 flags); | |
443f18d0 | 547 | |
244c0e06 | 548 | static int drxdap_fasi_read_reg32(struct i2c_device_addr *dev_addr, |
1bfc9e15 MCC |
549 | u32 addr, |
550 | u32 *data, u32 flags); | |
443f18d0 | 551 | |
244c0e06 | 552 | static int drxdap_fasi_write_block(struct i2c_device_addr *dev_addr, |
1bfc9e15 | 553 | u32 addr, |
43a431e4 | 554 | u16 datasize, |
1bfc9e15 | 555 | u8 *data, u32 flags); |
443f18d0 | 556 | |
57afe2f0 | 557 | static int drxj_dap_write_reg16(struct i2c_device_addr *dev_addr, |
1bfc9e15 MCC |
558 | u32 addr, |
559 | u16 data, u32 flags); | |
443f18d0 | 560 | |
244c0e06 | 561 | static int drxdap_fasi_write_reg32(struct i2c_device_addr *dev_addr, |
1bfc9e15 MCC |
562 | u32 addr, |
563 | u32 data, u32 flags); | |
38b2df95 | 564 | |
01473146 | 565 | static struct drxj_data drxj_data_g = { |
57afe2f0 MCC |
566 | false, /* has_lna : true if LNA (aka PGA) present */ |
567 | false, /* has_oob : true if OOB supported */ | |
568 | false, /* has_ntsc: true if NTSC supported */ | |
569 | false, /* has_btsc: true if BTSC supported */ | |
570 | false, /* has_smatx: true if SMA_TX pin is available */ | |
571 | false, /* has_smarx: true if SMA_RX pin is available */ | |
572 | false, /* has_gpio : true if GPIO pin is available */ | |
573 | false, /* has_irqn : true if IRQN pin is available */ | |
443f18d0 MCC |
574 | 0, /* mfx A1/A2/A... */ |
575 | ||
576 | /* tuner settings */ | |
73f7065b | 577 | false, /* tuner mirrors RF signal */ |
443f18d0 MCC |
578 | /* standard/channel settings */ |
579 | DRX_STANDARD_UNKNOWN, /* current standard */ | |
580 | DRX_CONSTELLATION_AUTO, /* constellation */ | |
581 | 0, /* frequency in KHz */ | |
57afe2f0 | 582 | DRX_BANDWIDTH_UNKNOWN, /* curr_bandwidth */ |
443f18d0 MCC |
583 | DRX_MIRROR_NO, /* mirror */ |
584 | ||
585 | /* signal quality information: */ | |
586 | /* default values taken from the QAM Programming guide */ | |
57afe2f0 MCC |
587 | /* fec_bits_desired should not be less than 4000000 */ |
588 | 4000000, /* fec_bits_desired */ | |
589 | 5, /* fec_vd_plen */ | |
590 | 4, /* qam_vd_prescale */ | |
443f18d0 | 591 | 0xFFFF, /* qamVDPeriod */ |
57afe2f0 MCC |
592 | 204 * 8, /* fec_rs_plen annex A */ |
593 | 1, /* fec_rs_prescale */ | |
594 | FEC_RS_MEASUREMENT_PERIOD, /* fec_rs_period */ | |
595 | true, /* reset_pkt_err_acc */ | |
e33f2193 | 596 | 0, /* pkt_err_acc_start */ |
443f18d0 MCC |
597 | |
598 | /* HI configuration */ | |
57afe2f0 MCC |
599 | 0, /* hi_cfg_timing_div */ |
600 | 0, /* hi_cfg_bridge_delay */ | |
601 | 0, /* hi_cfg_wake_up_key */ | |
602 | 0, /* hi_cfg_ctrl */ | |
443f18d0 | 603 | 0, /* HICfgTimeout */ |
2c149601 | 604 | /* UIO configuration */ |
57afe2f0 MCC |
605 | DRX_UIO_MODE_DISABLE, /* uio_sma_rx_mode */ |
606 | DRX_UIO_MODE_DISABLE, /* uio_sma_tx_mode */ | |
443f18d0 | 607 | DRX_UIO_MODE_DISABLE, /* uioASELMode */ |
57afe2f0 | 608 | DRX_UIO_MODE_DISABLE, /* uio_irqn_mode */ |
443f18d0 | 609 | /* FS setting */ |
57afe2f0 MCC |
610 | 0UL, /* iqm_fs_rate_ofs */ |
611 | false, /* pos_image */ | |
443f18d0 | 612 | /* RC setting */ |
57afe2f0 | 613 | 0UL, /* iqm_rc_rate_ofs */ |
443f18d0 | 614 | /* AUD information */ |
73f7065b MCC |
615 | /* false, * flagSetAUDdone */ |
616 | /* false, * detectedRDS */ | |
617 | /* true, * flagASDRequest */ | |
618 | /* false, * flagHDevClear */ | |
619 | /* false, * flagHDevSet */ | |
43a431e4 | 620 | /* (u16) 0xFFF, * rdsLastCount */ |
38b2df95 | 621 | |
2c149601 | 622 | /* ATV configuration */ |
443f18d0 MCC |
623 | 0UL, /* flags cfg changes */ |
624 | /* shadow of ATV_TOP_EQU0__A */ | |
625 | {-5, | |
626 | ATV_TOP_EQU0_EQU_C0_FM, | |
627 | ATV_TOP_EQU0_EQU_C0_L, | |
628 | ATV_TOP_EQU0_EQU_C0_LP, | |
629 | ATV_TOP_EQU0_EQU_C0_BG, | |
630 | ATV_TOP_EQU0_EQU_C0_DK, | |
631 | ATV_TOP_EQU0_EQU_C0_I}, | |
632 | /* shadow of ATV_TOP_EQU1__A */ | |
633 | {-50, | |
634 | ATV_TOP_EQU1_EQU_C1_FM, | |
635 | ATV_TOP_EQU1_EQU_C1_L, | |
636 | ATV_TOP_EQU1_EQU_C1_LP, | |
637 | ATV_TOP_EQU1_EQU_C1_BG, | |
638 | ATV_TOP_EQU1_EQU_C1_DK, | |
639 | ATV_TOP_EQU1_EQU_C1_I}, | |
640 | /* shadow of ATV_TOP_EQU2__A */ | |
641 | {210, | |
642 | ATV_TOP_EQU2_EQU_C2_FM, | |
643 | ATV_TOP_EQU2_EQU_C2_L, | |
644 | ATV_TOP_EQU2_EQU_C2_LP, | |
645 | ATV_TOP_EQU2_EQU_C2_BG, | |
646 | ATV_TOP_EQU2_EQU_C2_DK, | |
647 | ATV_TOP_EQU2_EQU_C2_I}, | |
648 | /* shadow of ATV_TOP_EQU3__A */ | |
649 | {-160, | |
650 | ATV_TOP_EQU3_EQU_C3_FM, | |
651 | ATV_TOP_EQU3_EQU_C3_L, | |
652 | ATV_TOP_EQU3_EQU_C3_LP, | |
653 | ATV_TOP_EQU3_EQU_C3_BG, | |
654 | ATV_TOP_EQU3_EQU_C3_DK, | |
655 | ATV_TOP_EQU3_EQU_C3_I}, | |
73f7065b | 656 | false, /* flag: true=bypass */ |
443f18d0 MCC |
657 | ATV_TOP_VID_PEAK__PRE, /* shadow of ATV_TOP_VID_PEAK__A */ |
658 | ATV_TOP_NOISE_TH__PRE, /* shadow of ATV_TOP_NOISE_TH__A */ | |
73f7065b MCC |
659 | true, /* flag CVBS ouput enable */ |
660 | false, /* flag SIF ouput enable */ | |
443f18d0 | 661 | DRXJ_SIF_ATTENUATION_0DB, /* current SIF att setting */ |
57afe2f0 | 662 | { /* qam_rf_agc_cfg */ |
443f18d0 | 663 | DRX_STANDARD_ITU_B, /* standard */ |
57afe2f0 MCC |
664 | DRX_AGC_CTRL_AUTO, /* ctrl_mode */ |
665 | 0, /* output_level */ | |
666 | 0, /* min_output_level */ | |
667 | 0xFFFF, /* max_output_level */ | |
443f18d0 MCC |
668 | 0x0000, /* speed */ |
669 | 0x0000, /* top */ | |
670 | 0x0000 /* c.o.c. */ | |
671 | }, | |
57afe2f0 | 672 | { /* qam_if_agc_cfg */ |
443f18d0 | 673 | DRX_STANDARD_ITU_B, /* standard */ |
57afe2f0 MCC |
674 | DRX_AGC_CTRL_AUTO, /* ctrl_mode */ |
675 | 0, /* output_level */ | |
676 | 0, /* min_output_level */ | |
677 | 0xFFFF, /* max_output_level */ | |
443f18d0 MCC |
678 | 0x0000, /* speed */ |
679 | 0x0000, /* top (don't care) */ | |
680 | 0x0000 /* c.o.c. (don't care) */ | |
681 | }, | |
57afe2f0 | 682 | { /* vsb_rf_agc_cfg */ |
443f18d0 | 683 | DRX_STANDARD_8VSB, /* standard */ |
57afe2f0 MCC |
684 | DRX_AGC_CTRL_AUTO, /* ctrl_mode */ |
685 | 0, /* output_level */ | |
686 | 0, /* min_output_level */ | |
687 | 0xFFFF, /* max_output_level */ | |
443f18d0 MCC |
688 | 0x0000, /* speed */ |
689 | 0x0000, /* top (don't care) */ | |
690 | 0x0000 /* c.o.c. (don't care) */ | |
691 | }, | |
57afe2f0 | 692 | { /* vsb_if_agc_cfg */ |
443f18d0 | 693 | DRX_STANDARD_8VSB, /* standard */ |
57afe2f0 MCC |
694 | DRX_AGC_CTRL_AUTO, /* ctrl_mode */ |
695 | 0, /* output_level */ | |
696 | 0, /* min_output_level */ | |
697 | 0xFFFF, /* max_output_level */ | |
443f18d0 MCC |
698 | 0x0000, /* speed */ |
699 | 0x0000, /* top (don't care) */ | |
700 | 0x0000 /* c.o.c. (don't care) */ | |
701 | }, | |
57afe2f0 MCC |
702 | 0, /* qam_pga_cfg */ |
703 | 0, /* vsb_pga_cfg */ | |
704 | { /* qam_pre_saw_cfg */ | |
443f18d0 MCC |
705 | DRX_STANDARD_ITU_B, /* standard */ |
706 | 0, /* reference */ | |
57afe2f0 | 707 | false /* use_pre_saw */ |
443f18d0 | 708 | }, |
57afe2f0 | 709 | { /* vsb_pre_saw_cfg */ |
443f18d0 MCC |
710 | DRX_STANDARD_8VSB, /* standard */ |
711 | 0, /* reference */ | |
57afe2f0 | 712 | false /* use_pre_saw */ |
443f18d0 MCC |
713 | }, |
714 | ||
715 | /* Version information */ | |
38b2df95 | 716 | #ifndef _CH_ |
443f18d0 MCC |
717 | { |
718 | "01234567890", /* human readable version microcode */ | |
719 | "01234567890" /* human readable version device specific code */ | |
720 | }, | |
721 | { | |
1bfc9e15 | 722 | { /* struct drx_version for microcode */ |
443f18d0 MCC |
723 | DRX_MODULE_UNKNOWN, |
724 | (char *)(NULL), | |
725 | 0, | |
726 | 0, | |
727 | 0, | |
728 | (char *)(NULL) | |
729 | }, | |
1bfc9e15 | 730 | { /* struct drx_version for device specific code */ |
443f18d0 MCC |
731 | DRX_MODULE_UNKNOWN, |
732 | (char *)(NULL), | |
733 | 0, | |
734 | 0, | |
735 | 0, | |
736 | (char *)(NULL) | |
737 | } | |
738 | }, | |
739 | { | |
1bfc9e15 MCC |
740 | { /* struct drx_version_list for microcode */ |
741 | (struct drx_version *) (NULL), | |
742 | (struct drx_version_list *) (NULL) | |
443f18d0 | 743 | }, |
1bfc9e15 MCC |
744 | { /* struct drx_version_list for device specific code */ |
745 | (struct drx_version *) (NULL), | |
746 | (struct drx_version_list *) (NULL) | |
443f18d0 MCC |
747 | } |
748 | }, | |
38b2df95 | 749 | #endif |
57afe2f0 | 750 | false, /* smart_ant_inverted */ |
443f18d0 MCC |
751 | /* Tracking filter setting for OOB */ |
752 | { | |
753 | 12000, | |
754 | 9300, | |
755 | 6600, | |
756 | 5280, | |
757 | 3700, | |
758 | 3000, | |
759 | 2000, | |
760 | 0}, | |
57afe2f0 MCC |
761 | false, /* oob_power_on */ |
762 | 0, /* mpeg_ts_static_bitrate */ | |
763 | false, /* disable_te_ihandling */ | |
764 | false, /* bit_reverse_mpeg_outout */ | |
765 | DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO, /* mpeg_output_clock_rate */ | |
766 | DRXJ_MPEG_START_WIDTH_1CLKCYC, /* mpeg_start_width */ | |
443f18d0 MCC |
767 | |
768 | /* Pre SAW & Agc configuration for ATV */ | |
769 | { | |
770 | DRX_STANDARD_NTSC, /* standard */ | |
771 | 7, /* reference */ | |
57afe2f0 | 772 | true /* use_pre_saw */ |
443f18d0 MCC |
773 | }, |
774 | { /* ATV RF-AGC */ | |
775 | DRX_STANDARD_NTSC, /* standard */ | |
57afe2f0 MCC |
776 | DRX_AGC_CTRL_AUTO, /* ctrl_mode */ |
777 | 0, /* output_level */ | |
778 | 0, /* min_output_level (d.c.) */ | |
779 | 0, /* max_output_level (d.c.) */ | |
443f18d0 MCC |
780 | 3, /* speed */ |
781 | 9500, /* top */ | |
782 | 4000 /* cut-off current */ | |
783 | }, | |
784 | { /* ATV IF-AGC */ | |
785 | DRX_STANDARD_NTSC, /* standard */ | |
57afe2f0 MCC |
786 | DRX_AGC_CTRL_AUTO, /* ctrl_mode */ |
787 | 0, /* output_level */ | |
788 | 0, /* min_output_level (d.c.) */ | |
789 | 0, /* max_output_level (d.c.) */ | |
443f18d0 MCC |
790 | 3, /* speed */ |
791 | 2400, /* top */ | |
792 | 0 /* c.o.c. (d.c.) */ | |
793 | }, | |
794 | 140, /* ATV PGA config */ | |
57afe2f0 | 795 | 0, /* curr_symbol_rate */ |
443f18d0 | 796 | |
57afe2f0 MCC |
797 | false, /* pdr_safe_mode */ |
798 | SIO_PDR_GPIO_CFG__PRE, /* pdr_safe_restore_val_gpio */ | |
799 | SIO_PDR_VSYNC_CFG__PRE, /* pdr_safe_restore_val_v_sync */ | |
800 | SIO_PDR_SMA_RX_CFG__PRE, /* pdr_safe_restore_val_sma_rx */ | |
801 | SIO_PDR_SMA_TX_CFG__PRE, /* pdr_safe_restore_val_sma_tx */ | |
443f18d0 | 802 | |
57afe2f0 MCC |
803 | 4, /* oob_pre_saw */ |
804 | DRXJ_OOB_LO_POW_MINUS10DB, /* oob_lo_pow */ | |
443f18d0 | 805 | { |
57afe2f0 | 806 | false /* aud_data, only first member */ |
443f18d0 | 807 | }, |
38b2df95 DH |
808 | }; |
809 | ||
34eb9751 | 810 | /* |
57afe2f0 | 811 | * \var drxj_default_addr_g |
38b2df95 DH |
812 | * \brief Default I2C address and device identifier. |
813 | */ | |
01473146 | 814 | static struct i2c_device_addr drxj_default_addr_g = { |
443f18d0 MCC |
815 | DRXJ_DEF_I2C_ADDR, /* i2c address */ |
816 | DRXJ_DEF_DEMOD_DEV_ID /* device id */ | |
38b2df95 DH |
817 | }; |
818 | ||
34eb9751 | 819 | /* |
57afe2f0 | 820 | * \var drxj_default_comm_attr_g |
38b2df95 DH |
821 | * \brief Default common attributes of a drxj demodulator instance. |
822 | */ | |
01473146 | 823 | static struct drx_common_attr drxj_default_comm_attr_g = { |
b48293db | 824 | NULL, /* ucode file */ |
73f7065b | 825 | true, /* ucode verify switch */ |
443f18d0 MCC |
826 | {0}, /* version record */ |
827 | ||
828 | 44000, /* IF in kHz in case no tuner instance is used */ | |
829 | (151875 - 0), /* system clock frequency in kHz */ | |
830 | 0, /* oscillator frequency kHz */ | |
831 | 0, /* oscillator deviation in ppm, signed */ | |
73f7065b | 832 | false, /* If true mirror frequency spectrum */ |
443f18d0 MCC |
833 | { |
834 | /* MPEG output configuration */ | |
73f7065b MCC |
835 | true, /* If true, enable MPEG ouput */ |
836 | false, /* If true, insert RS byte */ | |
a5e7a67f | 837 | false, /* If true, parallel out otherwise serial */ |
73f7065b MCC |
838 | false, /* If true, invert DATA signals */ |
839 | false, /* If true, invert ERR signal */ | |
840 | false, /* If true, invert STR signals */ | |
841 | false, /* If true, invert VAL signals */ | |
842 | false, /* If true, invert CLK signals */ | |
843 | true, /* If true, static MPEG clockrate will | |
443f18d0 MCC |
844 | be used, otherwise clockrate will |
845 | adapt to the bitrate of the TS */ | |
846 | 19392658UL, /* Maximum bitrate in b/s in case | |
847 | static clockrate is selected */ | |
848 | DRX_MPEG_STR_WIDTH_1 /* MPEG Start width in clock cycles */ | |
849 | }, | |
69bb7ab6 | 850 | /* Initilisations below can be omitted, they require no user input and |
73f7065b | 851 | are initialy 0, NULL or false. The compiler will initialize them to these |
69bb7ab6 | 852 | values when omitted. */ |
57afe2f0 | 853 | false, /* is_opened */ |
443f18d0 MCC |
854 | |
855 | /* SCAN */ | |
856 | NULL, /* no scan params yet */ | |
857 | 0, /* current scan index */ | |
858 | 0, /* next scan frequency */ | |
73f7065b | 859 | false, /* scan ready flag */ |
443f18d0 MCC |
860 | 0, /* max channels to scan */ |
861 | 0, /* nr of channels scanned */ | |
862 | NULL, /* default scan function */ | |
863 | NULL, /* default context pointer */ | |
864 | 0, /* millisec to wait for demod lock */ | |
865 | DRXJ_DEMOD_LOCK, /* desired lock */ | |
73f7065b | 866 | false, |
443f18d0 MCC |
867 | |
868 | /* Power management */ | |
869 | DRX_POWER_UP, | |
870 | ||
871 | /* Tuner */ | |
872 | 1, /* nr of I2C port to wich tuner is */ | |
873 | 0L, /* minimum RF input frequency, in kHz */ | |
874 | 0L, /* maximum RF input frequency, in kHz */ | |
73f7065b MCC |
875 | false, /* Rf Agc Polarity */ |
876 | false, /* If Agc Polarity */ | |
877 | false, /* tuner slow mode */ | |
443f18d0 MCC |
878 | |
879 | { /* current channel (all 0) */ | |
880 | 0UL /* channel.frequency */ | |
881 | }, | |
882 | DRX_STANDARD_UNKNOWN, /* current standard */ | |
883 | DRX_STANDARD_UNKNOWN, /* previous standard */ | |
57afe2f0 MCC |
884 | DRX_STANDARD_UNKNOWN, /* di_cache_standard */ |
885 | false, /* use_bootloader */ | |
443f18d0 MCC |
886 | 0UL, /* capabilities */ |
887 | 0 /* mfx */ | |
38b2df95 DH |
888 | }; |
889 | ||
34eb9751 | 890 | /* |
57afe2f0 | 891 | * \var drxj_default_demod_g |
38b2df95 DH |
892 | * \brief Default drxj demodulator instance. |
893 | */ | |
01473146 | 894 | static struct drx_demod_instance drxj_default_demod_g = { |
57afe2f0 MCC |
895 | &drxj_default_addr_g, /* i2c address & device id */ |
896 | &drxj_default_comm_attr_g, /* demod common attributes */ | |
897 | &drxj_data_g /* demod device specific attributes */ | |
38b2df95 DH |
898 | }; |
899 | ||
34eb9751 | 900 | /* |
38b2df95 DH |
901 | * \brief Default audio data structure for DRK demodulator instance. |
902 | * | |
903 | * This structure is DRXK specific. | |
904 | * | |
905 | */ | |
c4cfb293 | 906 | static struct drx_aud_data drxj_default_aud_data_g = { |
57afe2f0 MCC |
907 | false, /* audio_is_active */ |
908 | DRX_AUD_STANDARD_AUTO, /* audio_standard */ | |
38b2df95 | 909 | |
443f18d0 MCC |
910 | /* i2sdata */ |
911 | { | |
57afe2f0 | 912 | false, /* output_enable */ |
443f18d0 MCC |
913 | 48000, /* frequency */ |
914 | DRX_I2S_MODE_MASTER, /* mode */ | |
57afe2f0 | 915 | DRX_I2S_WORDLENGTH_32, /* word_length */ |
443f18d0 MCC |
916 | DRX_I2S_POLARITY_RIGHT, /* polarity */ |
917 | DRX_I2S_FORMAT_WS_WITH_DATA /* format */ | |
918 | }, | |
919 | /* volume */ | |
920 | { | |
73f7065b | 921 | true, /* mute; */ |
443f18d0 | 922 | 0, /* volume */ |
57afe2f0 MCC |
923 | DRX_AUD_AVC_OFF, /* avc_mode */ |
924 | 0, /* avc_ref_level */ | |
925 | DRX_AUD_AVC_MAX_GAIN_12DB, /* avc_max_gain */ | |
926 | DRX_AUD_AVC_MAX_ATTEN_24DB, /* avc_max_atten */ | |
927 | 0, /* strength_left */ | |
928 | 0 /* strength_right */ | |
443f18d0 | 929 | }, |
57afe2f0 MCC |
930 | DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_ON, /* auto_sound */ |
931 | /* ass_thresholds */ | |
443f18d0 MCC |
932 | { |
933 | 440, /* A2 */ | |
934 | 12, /* BTSC */ | |
935 | 700, /* NICAM */ | |
936 | }, | |
937 | /* carrier */ | |
938 | { | |
939 | /* a */ | |
940 | { | |
941 | 42, /* thres */ | |
942 | DRX_NO_CARRIER_NOISE, /* opt */ | |
943 | 0, /* shift */ | |
944 | 0 /* dco */ | |
945 | }, | |
946 | /* b */ | |
947 | { | |
948 | 42, /* thres */ | |
949 | DRX_NO_CARRIER_MUTE, /* opt */ | |
950 | 0, /* shift */ | |
951 | 0 /* dco */ | |
952 | }, | |
953 | ||
954 | }, | |
955 | /* mixer */ | |
956 | { | |
57afe2f0 MCC |
957 | DRX_AUD_SRC_STEREO_OR_A, /* source_i2s */ |
958 | DRX_AUD_I2S_MATRIX_STEREO, /* matrix_i2s */ | |
959 | DRX_AUD_FM_MATRIX_SOUND_A /* matrix_fm */ | |
443f18d0 MCC |
960 | }, |
961 | DRX_AUD_DEVIATION_NORMAL, /* deviation */ | |
57afe2f0 | 962 | DRX_AUD_AVSYNC_OFF, /* av_sync */ |
443f18d0 MCC |
963 | |
964 | /* prescale */ | |
965 | { | |
57afe2f0 MCC |
966 | DRX_AUD_MAX_FM_DEVIATION, /* fm_deviation */ |
967 | DRX_AUD_MAX_NICAM_PRESCALE /* nicam_gain */ | |
443f18d0 MCC |
968 | }, |
969 | DRX_AUD_FM_DEEMPH_75US, /* deemph */ | |
57afe2f0 MCC |
970 | DRX_BTSC_STEREO, /* btsc_detect */ |
971 | 0, /* rds_data_counter */ | |
972 | false /* rds_data_present */ | |
38b2df95 DH |
973 | }; |
974 | ||
38b2df95 DH |
975 | /*----------------------------------------------------------------------------- |
976 | STRUCTURES | |
977 | ----------------------------------------------------------------------------*/ | |
60d3603b | 978 | struct drxjeq_stat { |
57afe2f0 MCC |
979 | u16 eq_mse; |
980 | u8 eq_mode; | |
981 | u8 eq_ctrl; | |
63713517 MCC |
982 | u8 eq_stat; |
983 | }; | |
38b2df95 DH |
984 | |
985 | /* HI command */ | |
60d3603b | 986 | struct drxj_hi_cmd { |
43a431e4 MCC |
987 | u16 cmd; |
988 | u16 param1; | |
989 | u16 param2; | |
990 | u16 param3; | |
991 | u16 param4; | |
992 | u16 param5; | |
63713517 MCC |
993 | u16 param6; |
994 | }; | |
38b2df95 | 995 | |
38b2df95 DH |
996 | /*============================================================================*/ |
997 | /*=== MICROCODE RELATED STRUCTURES ===========================================*/ | |
998 | /*============================================================================*/ | |
999 | ||
34eb9751 | 1000 | /* |
b240eacd MCC |
1001 | * struct drxu_code_block_hdr - Structure of the microcode block headers |
1002 | * | |
1003 | * @addr: Destination address of the data in this block | |
1004 | * @size: Size of the block data following this header counted in | |
1005 | * 16 bits words | |
1006 | * @CRC: CRC value of the data block, only valid if CRC flag is | |
1007 | * set. | |
1008 | */ | |
60d3603b | 1009 | struct drxu_code_block_hdr { |
43a431e4 MCC |
1010 | u32 addr; |
1011 | u16 size; | |
b240eacd | 1012 | u16 flags; |
63713517 MCC |
1013 | u16 CRC; |
1014 | }; | |
38b2df95 DH |
1015 | |
1016 | /*----------------------------------------------------------------------------- | |
1017 | FUNCTIONS | |
1018 | ----------------------------------------------------------------------------*/ | |
1019 | /* Some prototypes */ | |
61263c75 | 1020 | static int |
57afe2f0 | 1021 | hi_command(struct i2c_device_addr *dev_addr, |
60d3603b | 1022 | const struct drxj_hi_cmd *cmd, u16 *result); |
38b2df95 | 1023 | |
61263c75 | 1024 | static int |
1bfc9e15 | 1025 | ctrl_lock_status(struct drx_demod_instance *demod, enum drx_lock_status *lock_stat); |
38b2df95 | 1026 | |
61263c75 | 1027 | static int |
1bfc9e15 | 1028 | ctrl_power_mode(struct drx_demod_instance *demod, enum drx_power_mode *mode); |
38b2df95 | 1029 | |
1bfc9e15 | 1030 | static int power_down_aud(struct drx_demod_instance *demod); |
38b2df95 | 1031 | |
61263c75 | 1032 | static int |
b3ce3a83 | 1033 | ctrl_set_cfg_pre_saw(struct drx_demod_instance *demod, struct drxj_cfg_pre_saw *pre_saw); |
38b2df95 | 1034 | |
61263c75 | 1035 | static int |
b3ce3a83 | 1036 | ctrl_set_cfg_afe_gain(struct drx_demod_instance *demod, struct drxj_cfg_afe_gain *afe_gain); |
38b2df95 | 1037 | |
38b2df95 DH |
1038 | /*============================================================================*/ |
1039 | /*============================================================================*/ | |
1040 | /*== HELPER FUNCTIONS ==*/ | |
1041 | /*============================================================================*/ | |
1042 | /*============================================================================*/ | |
1043 | ||
38b2df95 DH |
1044 | |
1045 | /*============================================================================*/ | |
1046 | ||
1047 | /* | |
57afe2f0 | 1048 | * \fn u32 frac28(u32 N, u32 D) |
38b2df95 DH |
1049 | * \brief Compute: (1<<28)*N/D |
1050 | * \param N 32 bits | |
1051 | * \param D 32 bits | |
1052 | * \return (1<<28)*N/D | |
1053 | * This function is used to avoid floating-point calculations as they may | |
1054 | * not be present on the target platform. | |
1055 | ||
57afe2f0 | 1056 | * frac28 performs an unsigned 28/28 bits division to 32-bit fixed point |
38b2df95 DH |
1057 | * fraction used for setting the Frequency Shifter registers. |
1058 | * N and D can hold numbers up to width: 28-bits. | |
1059 | * The 4 bits integer part and the 28 bits fractional part are calculated. | |
1060 | ||
1061 | * Usage condition: ((1<<28)*n)/d < ((1<<32)-1) => (n/d) < 15.999 | |
1062 | ||
1063 | * N: 0...(1<<28)-1 = 268435454 | |
1064 | * D: 0...(1<<28)-1 | |
1065 | * Q: 0...(1<<32)-1 | |
1066 | */ | |
57afe2f0 | 1067 | static u32 frac28(u32 N, u32 D) |
38b2df95 | 1068 | { |
443f18d0 | 1069 | int i = 0; |
43a431e4 MCC |
1070 | u32 Q1 = 0; |
1071 | u32 R0 = 0; | |
443f18d0 MCC |
1072 | |
1073 | R0 = (N % D) << 4; /* 32-28 == 4 shifts possible at max */ | |
1074 | Q1 = N / D; /* integer part, only the 4 least significant bits | |
1075 | will be visible in the result */ | |
1076 | ||
1077 | /* division using radix 16, 7 nibbles in the result */ | |
1078 | for (i = 0; i < 7; i++) { | |
1079 | Q1 = (Q1 << 4) | R0 / D; | |
1080 | R0 = (R0 % D) << 4; | |
1081 | } | |
1082 | /* rounding */ | |
1083 | if ((R0 >> 3) >= D) | |
1084 | Q1++; | |
1085 | ||
1086 | return Q1; | |
38b2df95 DH |
1087 | } |
1088 | ||
34eb9751 | 1089 | /* |
57afe2f0 | 1090 | * \fn u32 log1_times100( u32 x) |
38b2df95 DH |
1091 | * \brief Compute: 100*log10(x) |
1092 | * \param x 32 bits | |
1093 | * \return 100*log10(x) | |
1094 | * | |
1095 | * 100*log10(x) | |
1096 | * = 100*(log2(x)/log2(10))) | |
1097 | * = (100*(2^15)*log2(x))/((2^15)*log2(10)) | |
1098 | * = ((200*(2^15)*log2(x))/((2^15)*log2(10)))/2 | |
1099 | * = ((200*(2^15)*(log2(x/y)+log2(y)))/((2^15)*log2(10)))/2 | |
1100 | * = ((200*(2^15)*log2(x/y))+(200*(2^15)*log2(y)))/((2^15)*log2(10)))/2 | |
1101 | * | |
1102 | * where y = 2^k and 1<= (x/y) < 2 | |
1103 | */ | |
1104 | ||
57afe2f0 | 1105 | static u32 log1_times100(u32 x) |
38b2df95 | 1106 | { |
43a431e4 | 1107 | static const u8 scale = 15; |
57afe2f0 | 1108 | static const u8 index_width = 5; |
443f18d0 MCC |
1109 | /* |
1110 | log2lut[n] = (1<<scale) * 200 * log2( 1.0 + ( (1.0/(1<<INDEXWIDTH)) * n )) | |
1111 | 0 <= n < ((1<<INDEXWIDTH)+1) | |
1112 | */ | |
1113 | ||
43a431e4 | 1114 | static const u32 log2lut[] = { |
443f18d0 MCC |
1115 | 0, /* 0.000000 */ |
1116 | 290941, /* 290941.300628 */ | |
1117 | 573196, /* 573196.476418 */ | |
1118 | 847269, /* 847269.179851 */ | |
1119 | 1113620, /* 1113620.489452 */ | |
1120 | 1372674, /* 1372673.576986 */ | |
1121 | 1624818, /* 1624817.752104 */ | |
1122 | 1870412, /* 1870411.981536 */ | |
1123 | 2109788, /* 2109787.962654 */ | |
1124 | 2343253, /* 2343252.817465 */ | |
1125 | 2571091, /* 2571091.461923 */ | |
1126 | 2793569, /* 2793568.696416 */ | |
1127 | 3010931, /* 3010931.055901 */ | |
1128 | 3223408, /* 3223408.452106 */ | |
1129 | 3431216, /* 3431215.635215 */ | |
1130 | 3634553, /* 3634553.498355 */ | |
1131 | 3833610, /* 3833610.244726 */ | |
1132 | 4028562, /* 4028562.434393 */ | |
1133 | 4219576, /* 4219575.925308 */ | |
1134 | 4406807, /* 4406806.721144 */ | |
1135 | 4590402, /* 4590401.736809 */ | |
1136 | 4770499, /* 4770499.491025 */ | |
1137 | 4947231, /* 4947230.734179 */ | |
1138 | 5120719, /* 5120719.018555 */ | |
1139 | 5291081, /* 5291081.217197 */ | |
1140 | 5458428, /* 5458427.996830 */ | |
1141 | 5622864, /* 5622864.249668 */ | |
1142 | 5784489, /* 5784489.488298 */ | |
1143 | 5943398, /* 5943398.207380 */ | |
1144 | 6099680, /* 6099680.215452 */ | |
1145 | 6253421, /* 6253420.939751 */ | |
1146 | 6404702, /* 6404701.706649 */ | |
1147 | 6553600, /* 6553600.000000 */ | |
1148 | }; | |
1149 | ||
43a431e4 MCC |
1150 | u8 i = 0; |
1151 | u32 y = 0; | |
1152 | u32 d = 0; | |
1153 | u32 k = 0; | |
1154 | u32 r = 0; | |
443f18d0 MCC |
1155 | |
1156 | if (x == 0) | |
64e49cb9 | 1157 | return 0; |
443f18d0 MCC |
1158 | |
1159 | /* Scale x (normalize) */ | |
1160 | /* computing y in log(x/y) = log(x) - log(y) */ | |
43a431e4 | 1161 | if ((x & (((u32) (-1)) << (scale + 1))) == 0) { |
443f18d0 | 1162 | for (k = scale; k > 0; k--) { |
43a431e4 | 1163 | if (x & (((u32) 1) << scale)) |
443f18d0 MCC |
1164 | break; |
1165 | x <<= 1; | |
1166 | } | |
1167 | } else { | |
1168 | for (k = scale; k < 31; k++) { | |
43a431e4 | 1169 | if ((x & (((u32) (-1)) << (scale + 1))) == 0) |
443f18d0 MCC |
1170 | break; |
1171 | x >>= 1; | |
1172 | } | |
1173 | } | |
1174 | /* | |
1175 | Now x has binary point between bit[scale] and bit[scale-1] | |
1176 | and 1.0 <= x < 2.0 */ | |
1177 | ||
69bb7ab6 | 1178 | /* correction for division: log(x) = log(x/y)+log(y) */ |
43a431e4 | 1179 | y = k * ((((u32) 1) << scale) * 200); |
443f18d0 MCC |
1180 | |
1181 | /* remove integer part */ | |
43a431e4 | 1182 | x &= ((((u32) 1) << scale) - 1); |
443f18d0 | 1183 | /* get index */ |
57afe2f0 | 1184 | i = (u8) (x >> (scale - index_width)); |
443f18d0 | 1185 | /* compute delta (x-a) */ |
57afe2f0 | 1186 | d = x & ((((u32) 1) << (scale - index_width)) - 1); |
443f18d0 MCC |
1187 | /* compute log, multiplication ( d* (.. )) must be within range ! */ |
1188 | y += log2lut[i] + | |
57afe2f0 | 1189 | ((d * (log2lut[i + 1] - log2lut[i])) >> (scale - index_width)); |
443f18d0 MCC |
1190 | /* Conver to log10() */ |
1191 | y /= 108853; /* (log2(10) << scale) */ | |
1192 | r = (y >> 1); | |
1193 | /* rounding */ | |
63713517 | 1194 | if (y & ((u32)1)) |
443f18d0 MCC |
1195 | r++; |
1196 | ||
64e49cb9 | 1197 | return r; |
38b2df95 DH |
1198 | |
1199 | } | |
1200 | ||
34eb9751 | 1201 | /* |
57afe2f0 | 1202 | * \fn u32 frac_times1e6( u16 N, u32 D) |
38b2df95 DH |
1203 | * \brief Compute: (N/D) * 1000000. |
1204 | * \param N nominator 16-bits. | |
1205 | * \param D denominator 32-bits. | |
43a431e4 | 1206 | * \return u32 |
38b2df95 DH |
1207 | * \retval ((N/D) * 1000000), 32 bits |
1208 | * | |
1209 | * No check on D=0! | |
1210 | */ | |
57afe2f0 | 1211 | static u32 frac_times1e6(u32 N, u32 D) |
38b2df95 | 1212 | { |
43a431e4 MCC |
1213 | u32 remainder = 0; |
1214 | u32 frac = 0; | |
38b2df95 | 1215 | |
443f18d0 MCC |
1216 | /* |
1217 | frac = (N * 1000000) / D | |
1218 | To let it fit in a 32 bits computation: | |
1219 | frac = (N * (1000000 >> 4)) / (D >> 4) | |
1220 | This would result in a problem in case D < 16 (div by 0). | |
1221 | So we do it more elaborate as shown below. | |
1222 | */ | |
43a431e4 | 1223 | frac = (((u32) N) * (1000000 >> 4)) / D; |
443f18d0 | 1224 | frac <<= 4; |
43a431e4 | 1225 | remainder = (((u32) N) * (1000000 >> 4)) % D; |
443f18d0 MCC |
1226 | remainder <<= 4; |
1227 | frac += remainder / D; | |
1228 | remainder = remainder % D; | |
63713517 | 1229 | if ((remainder * 2) > D) |
443f18d0 | 1230 | frac++; |
443f18d0 | 1231 | |
64e49cb9 | 1232 | return frac; |
38b2df95 DH |
1233 | } |
1234 | ||
1235 | /*============================================================================*/ | |
1236 | ||
38b2df95 | 1237 | |
34eb9751 | 1238 | /* |
38b2df95 DH |
1239 | * \brief Values for NICAM prescaler gain. Computed from dB to integer |
1240 | * and rounded. For calc used formula: 16*10^(prescaleGain[dB]/20). | |
1241 | * | |
1242 | */ | |
01d7d436 MCC |
1243 | #if 0 |
1244 | /* Currently, unused as we lack support for analog TV */ | |
63713517 MCC |
1245 | static const u16 nicam_presc_table_val[43] = { |
1246 | 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, | |
443f18d0 MCC |
1247 | 5, 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16, |
1248 | 18, 20, 23, 25, 28, 32, 36, 40, 45, | |
1249 | 51, 57, 64, 71, 80, 90, 101, 113, 127 | |
1250 | }; | |
01d7d436 | 1251 | #endif |
38b2df95 DH |
1252 | |
1253 | /*============================================================================*/ | |
1254 | /*== END HELPER FUNCTIONS ==*/ | |
1255 | /*============================================================================*/ | |
1256 | ||
38b2df95 DH |
1257 | /*============================================================================*/ |
1258 | /*============================================================================*/ | |
1259 | /*== DRXJ DAP FUNCTIONS ==*/ | |
1260 | /*============================================================================*/ | |
1261 | /*============================================================================*/ | |
1262 | ||
1263 | /* | |
1264 | This layer takes care of some device specific register access protocols: | |
1265 | -conversion to short address format | |
1266 | -access to audio block | |
1267 | This layer is placed between the drx_dap_fasi and the rest of the drxj | |
1268 | specific implementation. This layer can use address map knowledge whereas | |
1269 | dap_fasi may not use memory map knowledge. | |
1270 | ||
1271 | * For audio currently only 16 bits read and write register access is | |
1272 | supported. More is not needed. RMW and 32 or 8 bit access on audio | |
1273 | registers will have undefined behaviour. Flags (RMW, CRC reset, broadcast | |
1274 | single/multi master) will be ignored. | |
1275 | ||
38b2df95 DH |
1276 | TODO: check ignoring single/multimaster is ok for AUD access ? |
1277 | */ | |
1278 | ||
22892268 | 1279 | #define DRXJ_ISAUDWRITE(addr) (((((addr)>>16)&1) == 1) ? true : false) |
443f18d0 | 1280 | #define DRXJ_DAP_AUDTRIF_TIMEOUT 80 /* millisec */ |
38b2df95 DH |
1281 | /*============================================================================*/ |
1282 | ||
34eb9751 | 1283 | /* |
1bfc9e15 | 1284 | * \fn bool is_handled_by_aud_tr_if( u32 addr ) |
38b2df95 DH |
1285 | * \brief Check if this address is handled by the audio token ring interface. |
1286 | * \param addr | |
73f7065b MCC |
1287 | * \return bool |
1288 | * \retval true Yes, handled by audio token ring interface | |
1289 | * \retval false No, not handled by audio token ring interface | |
38b2df95 DH |
1290 | * |
1291 | */ | |
1292 | static | |
1bfc9e15 | 1293 | bool is_handled_by_aud_tr_if(u32 addr) |
38b2df95 | 1294 | { |
73f7065b | 1295 | bool retval = false; |
38b2df95 | 1296 | |
443f18d0 MCC |
1297 | if ((DRXDAP_FASI_ADDR2BLOCK(addr) == 4) && |
1298 | (DRXDAP_FASI_ADDR2BANK(addr) > 1) && | |
1299 | (DRXDAP_FASI_ADDR2BANK(addr) < 6)) { | |
73f7065b | 1300 | retval = true; |
443f18d0 | 1301 | } |
38b2df95 | 1302 | |
64e49cb9 | 1303 | return retval; |
38b2df95 DH |
1304 | } |
1305 | ||
1306 | /*============================================================================*/ | |
1307 | ||
73b3fc3d MCC |
1308 | int drxbsp_i2c_write_read(struct i2c_device_addr *w_dev_addr, |
1309 | u16 w_count, | |
1310 | u8 *wData, | |
1311 | struct i2c_device_addr *r_dev_addr, | |
1312 | u16 r_count, u8 *r_data) | |
1313 | { | |
1314 | struct drx39xxj_state *state; | |
1315 | struct i2c_msg msg[2]; | |
1316 | unsigned int num_msgs; | |
1317 | ||
1318 | if (w_dev_addr == NULL) { | |
1319 | /* Read only */ | |
1320 | state = r_dev_addr->user_data; | |
1321 | msg[0].addr = r_dev_addr->i2c_addr >> 1; | |
1322 | msg[0].flags = I2C_M_RD; | |
1323 | msg[0].buf = r_data; | |
1324 | msg[0].len = r_count; | |
1325 | num_msgs = 1; | |
1326 | } else if (r_dev_addr == NULL) { | |
1327 | /* Write only */ | |
1328 | state = w_dev_addr->user_data; | |
1329 | msg[0].addr = w_dev_addr->i2c_addr >> 1; | |
1330 | msg[0].flags = 0; | |
1331 | msg[0].buf = wData; | |
1332 | msg[0].len = w_count; | |
1333 | num_msgs = 1; | |
1334 | } else { | |
1335 | /* Both write and read */ | |
1336 | state = w_dev_addr->user_data; | |
1337 | msg[0].addr = w_dev_addr->i2c_addr >> 1; | |
1338 | msg[0].flags = 0; | |
1339 | msg[0].buf = wData; | |
1340 | msg[0].len = w_count; | |
1341 | msg[1].addr = r_dev_addr->i2c_addr >> 1; | |
1342 | msg[1].flags = I2C_M_RD; | |
1343 | msg[1].buf = r_data; | |
1344 | msg[1].len = r_count; | |
1345 | num_msgs = 2; | |
1346 | } | |
1347 | ||
1348 | if (state->i2c == NULL) { | |
1349 | pr_err("i2c was zero, aborting\n"); | |
1350 | return 0; | |
1351 | } | |
1352 | if (i2c_transfer(state->i2c, msg, num_msgs) != num_msgs) { | |
1353 | pr_warn("drx3933: I2C write/read failed\n"); | |
1354 | return -EREMOTEIO; | |
1355 | } | |
1356 | ||
73b3fc3d | 1357 | #ifdef DJH_DEBUG |
1ad77b5c SK |
1358 | if (w_dev_addr == NULL || r_dev_addr == NULL) |
1359 | return 0; | |
73b3fc3d | 1360 | |
1ad77b5c SK |
1361 | state = w_dev_addr->user_data; |
1362 | ||
1363 | if (state->i2c == NULL) | |
1364 | return 0; | |
1365 | ||
1366 | msg[0].addr = w_dev_addr->i2c_addr; | |
1367 | msg[0].flags = 0; | |
1368 | msg[0].buf = wData; | |
1369 | msg[0].len = w_count; | |
1370 | msg[1].addr = r_dev_addr->i2c_addr; | |
1371 | msg[1].flags = I2C_M_RD; | |
1372 | msg[1].buf = r_data; | |
1373 | msg[1].len = r_count; | |
1374 | num_msgs = 2; | |
73b3fc3d | 1375 | |
6c955b8b | 1376 | pr_debug("drx3933 i2c operation addr=%x i2c=%p, wc=%x rc=%x\n", |
73b3fc3d MCC |
1377 | w_dev_addr->i2c_addr, state->i2c, w_count, r_count); |
1378 | ||
1379 | if (i2c_transfer(state->i2c, msg, 2) != 2) { | |
1380 | pr_warn("drx3933: I2C write/read failed\n"); | |
1381 | return -EREMOTEIO; | |
1382 | } | |
1383 | #endif | |
1384 | return 0; | |
1385 | } | |
1386 | ||
1387 | /*============================================================================*/ | |
1388 | ||
34eb9751 | 1389 | /***************************** |
73b3fc3d MCC |
1390 | * |
1391 | * int drxdap_fasi_read_block ( | |
1392 | * struct i2c_device_addr *dev_addr, -- address of I2C device | |
1393 | * u32 addr, -- address of chip register/memory | |
1394 | * u16 datasize, -- number of bytes to read | |
1395 | * u8 *data, -- data to receive | |
1396 | * u32 flags) -- special device flags | |
1397 | * | |
1398 | * Read block data from chip address. Because the chip is word oriented, | |
1399 | * the number of bytes to read must be even. | |
1400 | * | |
1401 | * Make sure that the buffer to receive the data is large enough. | |
1402 | * | |
1403 | * Although this function expects an even number of bytes, it is still byte | |
1404 | * oriented, and the data read back is NOT translated to the endianness of | |
1405 | * the target platform. | |
1406 | * | |
1407 | * Output: | |
1408 | * - 0 if reading was successful | |
1409 | * in that case: data read is in *data. | |
1410 | * - -EIO if anything went wrong | |
1411 | * | |
1412 | ******************************/ | |
1413 | ||
1414 | static int drxdap_fasi_read_block(struct i2c_device_addr *dev_addr, | |
1415 | u32 addr, | |
1416 | u16 datasize, | |
1417 | u8 *data, u32 flags) | |
1418 | { | |
1419 | u8 buf[4]; | |
1420 | u16 bufx; | |
1421 | int rc; | |
1422 | u16 overhead_size = 0; | |
1423 | ||
1424 | /* Check parameters ******************************************************* */ | |
1425 | if (dev_addr == NULL) | |
1426 | return -EINVAL; | |
1427 | ||
1428 | overhead_size = (IS_I2C_10BIT(dev_addr->i2c_addr) ? 2 : 1) + | |
1429 | (DRXDAP_FASI_LONG_FORMAT(addr) ? 4 : 2); | |
1430 | ||
1431 | if ((DRXDAP_FASI_OFFSET_TOO_LARGE(addr)) || | |
1432 | ((!(DRXDAPFASI_LONG_ADDR_ALLOWED)) && | |
1433 | DRXDAP_FASI_LONG_FORMAT(addr)) || | |
1434 | (overhead_size > (DRXDAP_MAX_WCHUNKSIZE)) || | |
1435 | ((datasize != 0) && (data == NULL)) || ((datasize & 1) == 1)) { | |
1436 | return -EINVAL; | |
1437 | } | |
1438 | ||
1439 | /* ReadModifyWrite & mode flag bits are not allowed */ | |
1440 | flags &= (~DRXDAP_FASI_RMW & ~DRXDAP_FASI_MODEFLAGS); | |
1441 | #if DRXDAP_SINGLE_MASTER | |
1442 | flags |= DRXDAP_FASI_SINGLE_MASTER; | |
1443 | #endif | |
1444 | ||
1445 | /* Read block from I2C **************************************************** */ | |
1446 | do { | |
1447 | u16 todo = (datasize < DRXDAP_MAX_RCHUNKSIZE ? | |
1448 | datasize : DRXDAP_MAX_RCHUNKSIZE); | |
1449 | ||
1450 | bufx = 0; | |
1451 | ||
1452 | addr &= ~DRXDAP_FASI_FLAGS; | |
1453 | addr |= flags; | |
1454 | ||
1455 | #if ((DRXDAPFASI_LONG_ADDR_ALLOWED == 1) && (DRXDAPFASI_SHORT_ADDR_ALLOWED == 1)) | |
1456 | /* short format address preferred but long format otherwise */ | |
1457 | if (DRXDAP_FASI_LONG_FORMAT(addr)) { | |
1458 | #endif | |
1459 | #if (DRXDAPFASI_LONG_ADDR_ALLOWED == 1) | |
1460 | buf[bufx++] = (u8) (((addr << 1) & 0xFF) | 0x01); | |
1461 | buf[bufx++] = (u8) ((addr >> 16) & 0xFF); | |
1462 | buf[bufx++] = (u8) ((addr >> 24) & 0xFF); | |
1463 | buf[bufx++] = (u8) ((addr >> 7) & 0xFF); | |
1464 | #endif | |
1465 | #if ((DRXDAPFASI_LONG_ADDR_ALLOWED == 1) && (DRXDAPFASI_SHORT_ADDR_ALLOWED == 1)) | |
1466 | } else { | |
1467 | #endif | |
1468 | #if (DRXDAPFASI_SHORT_ADDR_ALLOWED == 1) | |
1469 | buf[bufx++] = (u8) ((addr << 1) & 0xFF); | |
1470 | buf[bufx++] = | |
1471 | (u8) (((addr >> 16) & 0x0F) | | |
1472 | ((addr >> 18) & 0xF0)); | |
1473 | #endif | |
1474 | #if ((DRXDAPFASI_LONG_ADDR_ALLOWED == 1) && (DRXDAPFASI_SHORT_ADDR_ALLOWED == 1)) | |
1475 | } | |
1476 | #endif | |
1477 | ||
1478 | #if DRXDAP_SINGLE_MASTER | |
1479 | /* | |
1480 | * In single master mode, split the read and write actions. | |
1481 | * No special action is needed for write chunks here. | |
1482 | */ | |
db5657c5 MCC |
1483 | rc = drxbsp_i2c_write_read(dev_addr, bufx, buf, |
1484 | NULL, 0, NULL); | |
73b3fc3d | 1485 | if (rc == 0) |
db5657c5 | 1486 | rc = drxbsp_i2c_write_read(NULL, 0, NULL, dev_addr, todo, data); |
73b3fc3d MCC |
1487 | #else |
1488 | /* In multi master mode, do everything in one RW action */ | |
1489 | rc = drxbsp_i2c_write_read(dev_addr, bufx, buf, dev_addr, todo, | |
1490 | data); | |
1491 | #endif | |
1492 | data += todo; | |
1493 | addr += (todo >> 1); | |
1494 | datasize -= todo; | |
1495 | } while (datasize && rc == 0); | |
1496 | ||
1497 | return rc; | |
1498 | } | |
1499 | ||
1500 | ||
34eb9751 | 1501 | /***************************** |
73b3fc3d MCC |
1502 | * |
1503 | * int drxdap_fasi_read_reg16 ( | |
1504 | * struct i2c_device_addr *dev_addr, -- address of I2C device | |
1505 | * u32 addr, -- address of chip register/memory | |
1506 | * u16 *data, -- data to receive | |
1507 | * u32 flags) -- special device flags | |
1508 | * | |
1509 | * Read one 16-bit register or memory location. The data received back is | |
1510 | * converted back to the target platform's endianness. | |
1511 | * | |
1512 | * Output: | |
1513 | * - 0 if reading was successful | |
1514 | * in that case: read data is at *data | |
1515 | * - -EIO if anything went wrong | |
1516 | * | |
1517 | ******************************/ | |
1518 | ||
1519 | static int drxdap_fasi_read_reg16(struct i2c_device_addr *dev_addr, | |
1520 | u32 addr, | |
1521 | u16 *data, u32 flags) | |
1522 | { | |
1523 | u8 buf[sizeof(*data)]; | |
1524 | int rc; | |
1525 | ||
1526 | if (!data) | |
1527 | return -EINVAL; | |
1528 | ||
1529 | rc = drxdap_fasi_read_block(dev_addr, addr, sizeof(*data), buf, flags); | |
1530 | *data = buf[0] + (((u16) buf[1]) << 8); | |
1531 | return rc; | |
1532 | } | |
1533 | ||
34eb9751 | 1534 | /***************************** |
73b3fc3d MCC |
1535 | * |
1536 | * int drxdap_fasi_read_reg32 ( | |
1537 | * struct i2c_device_addr *dev_addr, -- address of I2C device | |
1538 | * u32 addr, -- address of chip register/memory | |
1539 | * u32 *data, -- data to receive | |
1540 | * u32 flags) -- special device flags | |
1541 | * | |
1542 | * Read one 32-bit register or memory location. The data received back is | |
1543 | * converted back to the target platform's endianness. | |
1544 | * | |
1545 | * Output: | |
1546 | * - 0 if reading was successful | |
1547 | * in that case: read data is at *data | |
1548 | * - -EIO if anything went wrong | |
1549 | * | |
1550 | ******************************/ | |
1551 | ||
1552 | static int drxdap_fasi_read_reg32(struct i2c_device_addr *dev_addr, | |
1553 | u32 addr, | |
1554 | u32 *data, u32 flags) | |
1555 | { | |
1556 | u8 buf[sizeof(*data)]; | |
1557 | int rc; | |
1558 | ||
1559 | if (!data) | |
1560 | return -EINVAL; | |
1561 | ||
1562 | rc = drxdap_fasi_read_block(dev_addr, addr, sizeof(*data), buf, flags); | |
1563 | *data = (((u32) buf[0]) << 0) + | |
1564 | (((u32) buf[1]) << 8) + | |
1565 | (((u32) buf[2]) << 16) + (((u32) buf[3]) << 24); | |
1566 | return rc; | |
1567 | } | |
1568 | ||
34eb9751 | 1569 | /***************************** |
73b3fc3d MCC |
1570 | * |
1571 | * int drxdap_fasi_write_block ( | |
1572 | * struct i2c_device_addr *dev_addr, -- address of I2C device | |
1573 | * u32 addr, -- address of chip register/memory | |
1574 | * u16 datasize, -- number of bytes to read | |
1575 | * u8 *data, -- data to receive | |
1576 | * u32 flags) -- special device flags | |
1577 | * | |
1578 | * Write block data to chip address. Because the chip is word oriented, | |
1579 | * the number of bytes to write must be even. | |
1580 | * | |
1581 | * Although this function expects an even number of bytes, it is still byte | |
1582 | * oriented, and the data being written is NOT translated from the endianness of | |
1583 | * the target platform. | |
1584 | * | |
1585 | * Output: | |
1586 | * - 0 if writing was successful | |
1587 | * - -EIO if anything went wrong | |
1588 | * | |
1589 | ******************************/ | |
1590 | ||
1591 | static int drxdap_fasi_write_block(struct i2c_device_addr *dev_addr, | |
1592 | u32 addr, | |
1593 | u16 datasize, | |
1594 | u8 *data, u32 flags) | |
1595 | { | |
1596 | u8 buf[DRXDAP_MAX_WCHUNKSIZE]; | |
1597 | int st = -EIO; | |
1598 | int first_err = 0; | |
1599 | u16 overhead_size = 0; | |
1600 | u16 block_size = 0; | |
1601 | ||
1602 | /* Check parameters ******************************************************* */ | |
1603 | if (dev_addr == NULL) | |
1604 | return -EINVAL; | |
1605 | ||
1606 | overhead_size = (IS_I2C_10BIT(dev_addr->i2c_addr) ? 2 : 1) + | |
1607 | (DRXDAP_FASI_LONG_FORMAT(addr) ? 4 : 2); | |
1608 | ||
1609 | if ((DRXDAP_FASI_OFFSET_TOO_LARGE(addr)) || | |
1610 | ((!(DRXDAPFASI_LONG_ADDR_ALLOWED)) && | |
1611 | DRXDAP_FASI_LONG_FORMAT(addr)) || | |
1612 | (overhead_size > (DRXDAP_MAX_WCHUNKSIZE)) || | |
1613 | ((datasize != 0) && (data == NULL)) || ((datasize & 1) == 1)) | |
1614 | return -EINVAL; | |
1615 | ||
1616 | flags &= DRXDAP_FASI_FLAGS; | |
1617 | flags &= ~DRXDAP_FASI_MODEFLAGS; | |
1618 | #if DRXDAP_SINGLE_MASTER | |
1619 | flags |= DRXDAP_FASI_SINGLE_MASTER; | |
1620 | #endif | |
1621 | ||
1622 | /* Write block to I2C ***************************************************** */ | |
1623 | block_size = ((DRXDAP_MAX_WCHUNKSIZE) - overhead_size) & ~1; | |
1624 | do { | |
1625 | u16 todo = 0; | |
1626 | u16 bufx = 0; | |
1627 | ||
1628 | /* Buffer device address */ | |
1629 | addr &= ~DRXDAP_FASI_FLAGS; | |
1630 | addr |= flags; | |
1631 | #if (((DRXDAPFASI_LONG_ADDR_ALLOWED) == 1) && ((DRXDAPFASI_SHORT_ADDR_ALLOWED) == 1)) | |
1632 | /* short format address preferred but long format otherwise */ | |
1633 | if (DRXDAP_FASI_LONG_FORMAT(addr)) { | |
1634 | #endif | |
1635 | #if ((DRXDAPFASI_LONG_ADDR_ALLOWED) == 1) | |
1636 | buf[bufx++] = (u8) (((addr << 1) & 0xFF) | 0x01); | |
1637 | buf[bufx++] = (u8) ((addr >> 16) & 0xFF); | |
1638 | buf[bufx++] = (u8) ((addr >> 24) & 0xFF); | |
1639 | buf[bufx++] = (u8) ((addr >> 7) & 0xFF); | |
1640 | #endif | |
1641 | #if (((DRXDAPFASI_LONG_ADDR_ALLOWED) == 1) && ((DRXDAPFASI_SHORT_ADDR_ALLOWED) == 1)) | |
1642 | } else { | |
1643 | #endif | |
1644 | #if ((DRXDAPFASI_SHORT_ADDR_ALLOWED) == 1) | |
1645 | buf[bufx++] = (u8) ((addr << 1) & 0xFF); | |
1646 | buf[bufx++] = | |
1647 | (u8) (((addr >> 16) & 0x0F) | | |
1648 | ((addr >> 18) & 0xF0)); | |
1649 | #endif | |
1650 | #if (((DRXDAPFASI_LONG_ADDR_ALLOWED) == 1) && ((DRXDAPFASI_SHORT_ADDR_ALLOWED) == 1)) | |
1651 | } | |
1652 | #endif | |
1653 | ||
1654 | /* | |
1655 | In single master mode block_size can be 0. In such a case this I2C | |
1656 | sequense will be visible: (1) write address {i2c addr, | |
1657 | 4 bytes chip address} (2) write data {i2c addr, 4 bytes data } | |
1658 | (3) write address (4) write data etc... | |
69bb7ab6 | 1659 | Address must be rewriten because HI is reset after data transport and |
73b3fc3d MCC |
1660 | expects an address. |
1661 | */ | |
1662 | todo = (block_size < datasize ? block_size : datasize); | |
1663 | if (todo == 0) { | |
1664 | u16 overhead_size_i2c_addr = 0; | |
1665 | u16 data_block_size = 0; | |
1666 | ||
1667 | overhead_size_i2c_addr = | |
1668 | (IS_I2C_10BIT(dev_addr->i2c_addr) ? 2 : 1); | |
1669 | data_block_size = | |
1670 | (DRXDAP_MAX_WCHUNKSIZE - overhead_size_i2c_addr) & ~1; | |
1671 | ||
1672 | /* write device address */ | |
1673 | st = drxbsp_i2c_write_read(dev_addr, | |
1674 | (u16) (bufx), | |
1675 | buf, | |
1676 | (struct i2c_device_addr *)(NULL), | |
1677 | 0, (u8 *)(NULL)); | |
1678 | ||
1679 | if ((st != 0) && (first_err == 0)) { | |
1680 | /* at the end, return the first error encountered */ | |
1681 | first_err = st; | |
1682 | } | |
1683 | bufx = 0; | |
1684 | todo = | |
1685 | (data_block_size < | |
1686 | datasize ? data_block_size : datasize); | |
1687 | } | |
1688 | memcpy(&buf[bufx], data, todo); | |
1689 | /* write (address if can do and) data */ | |
1690 | st = drxbsp_i2c_write_read(dev_addr, | |
1691 | (u16) (bufx + todo), | |
1692 | buf, | |
1693 | (struct i2c_device_addr *)(NULL), | |
1694 | 0, (u8 *)(NULL)); | |
1695 | ||
1696 | if ((st != 0) && (first_err == 0)) { | |
1697 | /* at the end, return the first error encountered */ | |
1698 | first_err = st; | |
1699 | } | |
1700 | datasize -= todo; | |
1701 | data += todo; | |
1702 | addr += (todo >> 1); | |
1703 | } while (datasize); | |
1704 | ||
1705 | return first_err; | |
1706 | } | |
1707 | ||
34eb9751 | 1708 | /***************************** |
73b3fc3d MCC |
1709 | * |
1710 | * int drxdap_fasi_write_reg16 ( | |
1711 | * struct i2c_device_addr *dev_addr, -- address of I2C device | |
1712 | * u32 addr, -- address of chip register/memory | |
1713 | * u16 data, -- data to send | |
1714 | * u32 flags) -- special device flags | |
1715 | * | |
1716 | * Write one 16-bit register or memory location. The data being written is | |
1717 | * converted from the target platform's endianness to little endian. | |
1718 | * | |
1719 | * Output: | |
1720 | * - 0 if writing was successful | |
1721 | * - -EIO if anything went wrong | |
1722 | * | |
1723 | ******************************/ | |
1724 | ||
1725 | static int drxdap_fasi_write_reg16(struct i2c_device_addr *dev_addr, | |
1726 | u32 addr, | |
1727 | u16 data, u32 flags) | |
1728 | { | |
1729 | u8 buf[sizeof(data)]; | |
1730 | ||
1731 | buf[0] = (u8) ((data >> 0) & 0xFF); | |
1732 | buf[1] = (u8) ((data >> 8) & 0xFF); | |
1733 | ||
1734 | return drxdap_fasi_write_block(dev_addr, addr, sizeof(data), buf, flags); | |
1735 | } | |
1736 | ||
34eb9751 | 1737 | /***************************** |
73b3fc3d MCC |
1738 | * |
1739 | * int drxdap_fasi_read_modify_write_reg16 ( | |
1740 | * struct i2c_device_addr *dev_addr, -- address of I2C device | |
1741 | * u32 waddr, -- address of chip register/memory | |
1742 | * u32 raddr, -- chip address to read back from | |
1743 | * u16 wdata, -- data to send | |
1744 | * u16 *rdata) -- data to receive back | |
1745 | * | |
1746 | * Write 16-bit data, then read back the original contents of that location. | |
1747 | * Requires long addressing format to be allowed. | |
1748 | * | |
1749 | * Before sending data, the data is converted to little endian. The | |
1750 | * data received back is converted back to the target platform's endianness. | |
1751 | * | |
1752 | * WARNING: This function is only guaranteed to work if there is one | |
1753 | * master on the I2C bus. | |
1754 | * | |
1755 | * Output: | |
1756 | * - 0 if reading was successful | |
1757 | * in that case: read back data is at *rdata | |
1758 | * - -EIO if anything went wrong | |
1759 | * | |
1760 | ******************************/ | |
1761 | ||
1762 | static int drxdap_fasi_read_modify_write_reg16(struct i2c_device_addr *dev_addr, | |
1763 | u32 waddr, | |
1764 | u32 raddr, | |
1765 | u16 wdata, u16 *rdata) | |
1766 | { | |
1767 | int rc = -EIO; | |
1768 | ||
1769 | #if (DRXDAPFASI_LONG_ADDR_ALLOWED == 1) | |
1770 | if (rdata == NULL) | |
1771 | return -EINVAL; | |
1772 | ||
1773 | rc = drxdap_fasi_write_reg16(dev_addr, waddr, wdata, DRXDAP_FASI_RMW); | |
1774 | if (rc == 0) | |
1775 | rc = drxdap_fasi_read_reg16(dev_addr, raddr, rdata, 0); | |
1776 | #endif | |
1777 | ||
1778 | return rc; | |
1779 | } | |
1780 | ||
34eb9751 | 1781 | /***************************** |
73b3fc3d MCC |
1782 | * |
1783 | * int drxdap_fasi_write_reg32 ( | |
1784 | * struct i2c_device_addr *dev_addr, -- address of I2C device | |
1785 | * u32 addr, -- address of chip register/memory | |
1786 | * u32 data, -- data to send | |
1787 | * u32 flags) -- special device flags | |
1788 | * | |
1789 | * Write one 32-bit register or memory location. The data being written is | |
1790 | * converted from the target platform's endianness to little endian. | |
1791 | * | |
1792 | * Output: | |
1793 | * - 0 if writing was successful | |
1794 | * - -EIO if anything went wrong | |
1795 | * | |
1796 | ******************************/ | |
1797 | ||
1798 | static int drxdap_fasi_write_reg32(struct i2c_device_addr *dev_addr, | |
1799 | u32 addr, | |
1800 | u32 data, u32 flags) | |
1801 | { | |
1802 | u8 buf[sizeof(data)]; | |
1803 | ||
1804 | buf[0] = (u8) ((data >> 0) & 0xFF); | |
1805 | buf[1] = (u8) ((data >> 8) & 0xFF); | |
1806 | buf[2] = (u8) ((data >> 16) & 0xFF); | |
1807 | buf[3] = (u8) ((data >> 24) & 0xFF); | |
1808 | ||
1809 | return drxdap_fasi_write_block(dev_addr, addr, sizeof(data), buf, flags); | |
1810 | } | |
1811 | ||
38b2df95 DH |
1812 | /*============================================================================*/ |
1813 | ||
34eb9751 | 1814 | /* |
57afe2f0 | 1815 | * \fn int drxj_dap_rm_write_reg16short |
38b2df95 | 1816 | * \brief Read modify write 16 bits audio register using short format only. |
57afe2f0 | 1817 | * \param dev_addr |
38b2df95 DH |
1818 | * \param waddr Address to write to |
1819 | * \param raddr Address to read from (usually SIO_HI_RA_RAM_S0_RMWBUF__A) | |
1820 | * \param wdata Data to write | |
1821 | * \param rdata Buffer for data to read | |
61263c75 | 1822 | * \return int |
9482354f MCC |
1823 | * \retval 0 Succes |
1824 | * \retval -EIO Timeout, I2C error, illegal bank | |
38b2df95 DH |
1825 | * |
1826 | * 16 bits register read modify write access using short addressing format only. | |
1827 | * Requires knowledge of the registermap, thus device dependent. | |
1828 | * Using DAP FASI directly to avoid endless recursion of RMWs to audio registers. | |
1829 | * | |
1830 | */ | |
1831 | ||
1832 | /* TODO correct define should be #if ( DRXDAPFASI_SHORT_ADDR_ALLOWED==1 ) | |
57afe2f0 | 1833 | See comments drxj_dap_read_modify_write_reg16 */ |
7ef66759 | 1834 | #if (DRXDAPFASI_LONG_ADDR_ALLOWED == 0) |
57afe2f0 | 1835 | static int drxj_dap_rm_write_reg16short(struct i2c_device_addr *dev_addr, |
1bfc9e15 MCC |
1836 | u32 waddr, |
1837 | u32 raddr, | |
43a431e4 | 1838 | u16 wdata, u16 *rdata) |
38b2df95 | 1839 | { |
61263c75 | 1840 | int rc; |
443f18d0 | 1841 | |
63713517 | 1842 | if (rdata == NULL) |
9482354f | 1843 | return -EINVAL; |
443f18d0 MCC |
1844 | |
1845 | /* Set RMW flag */ | |
80bff4b0 | 1846 | rc = drxdap_fasi_write_reg16(dev_addr, |
38b2df95 | 1847 | SIO_HI_RA_RAM_S0_FLG_ACC__A, |
443f18d0 | 1848 | SIO_HI_RA_RAM_S0_FLG_ACC_S0_RWM__M, |
38b2df95 | 1849 | 0x0000); |
9482354f | 1850 | if (rc == 0) { |
443f18d0 | 1851 | /* Write new data: triggers RMW */ |
80bff4b0 | 1852 | rc = drxdap_fasi_write_reg16(dev_addr, waddr, wdata, |
443f18d0 MCC |
1853 | 0x0000); |
1854 | } | |
9482354f | 1855 | if (rc == 0) { |
443f18d0 | 1856 | /* Read old data */ |
80bff4b0 | 1857 | rc = drxdap_fasi_read_reg16(dev_addr, raddr, rdata, |
443f18d0 MCC |
1858 | 0x0000); |
1859 | } | |
9482354f | 1860 | if (rc == 0) { |
443f18d0 | 1861 | /* Reset RMW flag */ |
80bff4b0 | 1862 | rc = drxdap_fasi_write_reg16(dev_addr, |
443f18d0 MCC |
1863 | SIO_HI_RA_RAM_S0_FLG_ACC__A, |
1864 | 0, 0x0000); | |
1865 | } | |
38b2df95 | 1866 | |
443f18d0 | 1867 | return rc; |
38b2df95 DH |
1868 | } |
1869 | #endif | |
1870 | ||
1871 | /*============================================================================*/ | |
1872 | ||
57afe2f0 | 1873 | static int drxj_dap_read_modify_write_reg16(struct i2c_device_addr *dev_addr, |
1bfc9e15 MCC |
1874 | u32 waddr, |
1875 | u32 raddr, | |
43a431e4 | 1876 | u16 wdata, u16 *rdata) |
38b2df95 | 1877 | { |
443f18d0 MCC |
1878 | /* TODO: correct short/long addressing format decision, |
1879 | now long format has higher prio then short because short also | |
1880 | needs virt bnks (not impl yet) for certain audio registers */ | |
7ef66759 | 1881 | #if (DRXDAPFASI_LONG_ADDR_ALLOWED == 1) |
80bff4b0 | 1882 | return drxdap_fasi_read_modify_write_reg16(dev_addr, |
443f18d0 MCC |
1883 | waddr, |
1884 | raddr, wdata, rdata); | |
38b2df95 | 1885 | #else |
57afe2f0 | 1886 | return drxj_dap_rm_write_reg16short(dev_addr, waddr, raddr, wdata, rdata); |
38b2df95 DH |
1887 | #endif |
1888 | } | |
1889 | ||
38b2df95 DH |
1890 | |
1891 | /*============================================================================*/ | |
1892 | ||
34eb9751 | 1893 | /* |
57afe2f0 | 1894 | * \fn int drxj_dap_read_aud_reg16 |
38b2df95 | 1895 | * \brief Read 16 bits audio register |
57afe2f0 | 1896 | * \param dev_addr |
38b2df95 DH |
1897 | * \param addr |
1898 | * \param data | |
61263c75 | 1899 | * \return int |
9482354f MCC |
1900 | * \retval 0 Succes |
1901 | * \retval -EIO Timeout, I2C error, illegal bank | |
38b2df95 DH |
1902 | * |
1903 | * 16 bits register read access via audio token ring interface. | |
1904 | * | |
1905 | */ | |
57afe2f0 | 1906 | static int drxj_dap_read_aud_reg16(struct i2c_device_addr *dev_addr, |
1bfc9e15 | 1907 | u32 addr, u16 *data) |
443f18d0 | 1908 | { |
57afe2f0 MCC |
1909 | u32 start_timer = 0; |
1910 | u32 current_timer = 0; | |
1911 | u32 delta_timer = 0; | |
1912 | u16 tr_status = 0; | |
9482354f | 1913 | int stat = -EIO; |
443f18d0 MCC |
1914 | |
1915 | /* No read possible for bank 3, return with error */ | |
1916 | if (DRXDAP_FASI_ADDR2BANK(addr) == 3) { | |
9482354f | 1917 | stat = -EINVAL; |
443f18d0 | 1918 | } else { |
1bfc9e15 | 1919 | const u32 write_bit = ((dr_xaddr_t) 1) << 16; |
443f18d0 MCC |
1920 | |
1921 | /* Force reset write bit */ | |
57afe2f0 | 1922 | addr &= (~write_bit); |
443f18d0 MCC |
1923 | |
1924 | /* Set up read */ | |
d7b0631e | 1925 | start_timer = jiffies_to_msecs(jiffies); |
443f18d0 MCC |
1926 | do { |
1927 | /* RMW to aud TR IF until request is granted or timeout */ | |
57afe2f0 | 1928 | stat = drxj_dap_read_modify_write_reg16(dev_addr, |
443f18d0 MCC |
1929 | addr, |
1930 | SIO_HI_RA_RAM_S0_RMWBUF__A, | |
57afe2f0 | 1931 | 0x0000, &tr_status); |
443f18d0 | 1932 | |
9482354f | 1933 | if (stat != 0) |
443f18d0 | 1934 | break; |
443f18d0 | 1935 | |
d7b0631e | 1936 | current_timer = jiffies_to_msecs(jiffies); |
57afe2f0 MCC |
1937 | delta_timer = current_timer - start_timer; |
1938 | if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) { | |
9482354f | 1939 | stat = -EIO; |
443f18d0 | 1940 | break; |
259f380e | 1941 | } |
443f18d0 | 1942 | |
57afe2f0 | 1943 | } while (((tr_status & AUD_TOP_TR_CTR_FIFO_LOCK__M) == |
443f18d0 | 1944 | AUD_TOP_TR_CTR_FIFO_LOCK_LOCKED) || |
57afe2f0 | 1945 | ((tr_status & AUD_TOP_TR_CTR_FIFO_FULL__M) == |
443f18d0 MCC |
1946 | AUD_TOP_TR_CTR_FIFO_FULL_FULL)); |
1947 | } /* if ( DRXDAP_FASI_ADDR2BANK(addr)!=3 ) */ | |
1948 | ||
1949 | /* Wait for read ready status or timeout */ | |
9482354f | 1950 | if (stat == 0) { |
d7b0631e | 1951 | start_timer = jiffies_to_msecs(jiffies); |
443f18d0 | 1952 | |
57afe2f0 | 1953 | while ((tr_status & AUD_TOP_TR_CTR_FIFO_RD_RDY__M) != |
443f18d0 | 1954 | AUD_TOP_TR_CTR_FIFO_RD_RDY_READY) { |
57afe2f0 | 1955 | stat = drxj_dap_read_reg16(dev_addr, |
443f18d0 | 1956 | AUD_TOP_TR_CTR__A, |
57afe2f0 | 1957 | &tr_status, 0x0000); |
9482354f | 1958 | if (stat != 0) |
443f18d0 | 1959 | break; |
443f18d0 | 1960 | |
d7b0631e | 1961 | current_timer = jiffies_to_msecs(jiffies); |
57afe2f0 MCC |
1962 | delta_timer = current_timer - start_timer; |
1963 | if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) { | |
9482354f | 1964 | stat = -EIO; |
443f18d0 | 1965 | break; |
259f380e | 1966 | } |
443f18d0 MCC |
1967 | } /* while ( ... ) */ |
1968 | } | |
38b2df95 | 1969 | |
443f18d0 | 1970 | /* Read value */ |
9482354f | 1971 | if (stat == 0) |
57afe2f0 | 1972 | stat = drxj_dap_read_modify_write_reg16(dev_addr, |
443f18d0 MCC |
1973 | AUD_TOP_TR_RD_REG__A, |
1974 | SIO_HI_RA_RAM_S0_RMWBUF__A, | |
1975 | 0x0000, data); | |
443f18d0 | 1976 | return stat; |
38b2df95 DH |
1977 | } |
1978 | ||
1979 | /*============================================================================*/ | |
1980 | ||
57afe2f0 | 1981 | static int drxj_dap_read_reg16(struct i2c_device_addr *dev_addr, |
1bfc9e15 MCC |
1982 | u32 addr, |
1983 | u16 *data, u32 flags) | |
38b2df95 | 1984 | { |
9482354f | 1985 | int stat = -EIO; |
38b2df95 | 1986 | |
443f18d0 | 1987 | /* Check param */ |
63713517 | 1988 | if ((dev_addr == NULL) || (data == NULL)) |
9482354f | 1989 | return -EINVAL; |
38b2df95 | 1990 | |
63713517 | 1991 | if (is_handled_by_aud_tr_if(addr)) |
57afe2f0 | 1992 | stat = drxj_dap_read_aud_reg16(dev_addr, addr, data); |
63713517 | 1993 | else |
244c0e06 | 1994 | stat = drxdap_fasi_read_reg16(dev_addr, addr, data, flags); |
443f18d0 MCC |
1995 | |
1996 | return stat; | |
38b2df95 | 1997 | } |
38b2df95 DH |
1998 | /*============================================================================*/ |
1999 | ||
34eb9751 | 2000 | /* |
57afe2f0 | 2001 | * \fn int drxj_dap_write_aud_reg16 |
38b2df95 | 2002 | * \brief Write 16 bits audio register |
57afe2f0 | 2003 | * \param dev_addr |
38b2df95 DH |
2004 | * \param addr |
2005 | * \param data | |
61263c75 | 2006 | * \return int |
9482354f MCC |
2007 | * \retval 0 Succes |
2008 | * \retval -EIO Timeout, I2C error, illegal bank | |
38b2df95 DH |
2009 | * |
2010 | * 16 bits register write access via audio token ring interface. | |
2011 | * | |
2012 | */ | |
57afe2f0 | 2013 | static int drxj_dap_write_aud_reg16(struct i2c_device_addr *dev_addr, |
1bfc9e15 | 2014 | u32 addr, u16 data) |
38b2df95 | 2015 | { |
9482354f | 2016 | int stat = -EIO; |
38b2df95 | 2017 | |
443f18d0 MCC |
2018 | /* No write possible for bank 2, return with error */ |
2019 | if (DRXDAP_FASI_ADDR2BANK(addr) == 2) { | |
9482354f | 2020 | stat = -EINVAL; |
443f18d0 | 2021 | } else { |
57afe2f0 MCC |
2022 | u32 start_timer = 0; |
2023 | u32 current_timer = 0; | |
2024 | u32 delta_timer = 0; | |
2025 | u16 tr_status = 0; | |
1bfc9e15 | 2026 | const u32 write_bit = ((dr_xaddr_t) 1) << 16; |
38b2df95 | 2027 | |
443f18d0 | 2028 | /* Force write bit */ |
57afe2f0 | 2029 | addr |= write_bit; |
d7b0631e | 2030 | start_timer = jiffies_to_msecs(jiffies); |
443f18d0 MCC |
2031 | do { |
2032 | /* RMW to aud TR IF until request is granted or timeout */ | |
57afe2f0 | 2033 | stat = drxj_dap_read_modify_write_reg16(dev_addr, |
443f18d0 MCC |
2034 | addr, |
2035 | SIO_HI_RA_RAM_S0_RMWBUF__A, | |
57afe2f0 | 2036 | data, &tr_status); |
9482354f | 2037 | if (stat != 0) |
443f18d0 | 2038 | break; |
38b2df95 | 2039 | |
d7b0631e | 2040 | current_timer = jiffies_to_msecs(jiffies); |
57afe2f0 MCC |
2041 | delta_timer = current_timer - start_timer; |
2042 | if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) { | |
9482354f | 2043 | stat = -EIO; |
443f18d0 | 2044 | break; |
259f380e | 2045 | } |
38b2df95 | 2046 | |
57afe2f0 | 2047 | } while (((tr_status & AUD_TOP_TR_CTR_FIFO_LOCK__M) == |
443f18d0 | 2048 | AUD_TOP_TR_CTR_FIFO_LOCK_LOCKED) || |
57afe2f0 | 2049 | ((tr_status & AUD_TOP_TR_CTR_FIFO_FULL__M) == |
443f18d0 | 2050 | AUD_TOP_TR_CTR_FIFO_FULL_FULL)); |
38b2df95 | 2051 | |
443f18d0 MCC |
2052 | } /* if ( DRXDAP_FASI_ADDR2BANK(addr)!=2 ) */ |
2053 | ||
2054 | return stat; | |
38b2df95 DH |
2055 | } |
2056 | ||
2057 | /*============================================================================*/ | |
2058 | ||
57afe2f0 | 2059 | static int drxj_dap_write_reg16(struct i2c_device_addr *dev_addr, |
1bfc9e15 MCC |
2060 | u32 addr, |
2061 | u16 data, u32 flags) | |
38b2df95 | 2062 | { |
9482354f | 2063 | int stat = -EIO; |
38b2df95 | 2064 | |
443f18d0 | 2065 | /* Check param */ |
63713517 | 2066 | if (dev_addr == NULL) |
9482354f | 2067 | return -EINVAL; |
38b2df95 | 2068 | |
63713517 | 2069 | if (is_handled_by_aud_tr_if(addr)) |
57afe2f0 | 2070 | stat = drxj_dap_write_aud_reg16(dev_addr, addr, data); |
63713517 | 2071 | else |
80bff4b0 | 2072 | stat = drxdap_fasi_write_reg16(dev_addr, |
63713517 | 2073 | addr, data, flags); |
38b2df95 | 2074 | |
443f18d0 | 2075 | return stat; |
38b2df95 DH |
2076 | } |
2077 | ||
2078 | /*============================================================================*/ | |
2079 | ||
38b2df95 DH |
2080 | /* Free data ram in SIO HI */ |
2081 | #define SIO_HI_RA_RAM_USR_BEGIN__A 0x420040 | |
2082 | #define SIO_HI_RA_RAM_USR_END__A 0x420060 | |
2083 | ||
2084 | #define DRXJ_HI_ATOMIC_BUF_START (SIO_HI_RA_RAM_USR_BEGIN__A) | |
2085 | #define DRXJ_HI_ATOMIC_BUF_END (SIO_HI_RA_RAM_USR_BEGIN__A + 7) | |
2086 | #define DRXJ_HI_ATOMIC_READ SIO_HI_RA_RAM_PAR_3_ACP_RW_READ | |
2087 | #define DRXJ_HI_ATOMIC_WRITE SIO_HI_RA_RAM_PAR_3_ACP_RW_WRITE | |
2088 | ||
34eb9751 | 2089 | /* |
57afe2f0 | 2090 | * \fn int drxj_dap_atomic_read_write_block() |
38b2df95 | 2091 | * \brief Basic access routine for atomic read or write access |
57afe2f0 | 2092 | * \param dev_addr pointer to i2c dev address |
38b2df95 DH |
2093 | * \param addr destination/source address |
2094 | * \param datasize size of data buffer in bytes | |
2095 | * \param data pointer to data buffer | |
61263c75 | 2096 | * \return int |
9482354f MCC |
2097 | * \retval 0 Succes |
2098 | * \retval -EIO Timeout, I2C error, illegal bank | |
38b2df95 DH |
2099 | * |
2100 | */ | |
2101 | static | |
57afe2f0 | 2102 | int drxj_dap_atomic_read_write_block(struct i2c_device_addr *dev_addr, |
1bfc9e15 | 2103 | u32 addr, |
43a431e4 | 2104 | u16 datasize, |
57afe2f0 | 2105 | u8 *data, bool read_flag) |
443f18d0 | 2106 | { |
60d3603b | 2107 | struct drxj_hi_cmd hi_cmd; |
068e94ea | 2108 | int rc; |
43a431e4 MCC |
2109 | u16 word; |
2110 | u16 dummy = 0; | |
2111 | u16 i = 0; | |
443f18d0 MCC |
2112 | |
2113 | /* Parameter check */ | |
63713517 | 2114 | if (!data || !dev_addr || ((datasize % 2)) || ((datasize / 2) > 8)) |
9482354f | 2115 | return -EINVAL; |
38b2df95 | 2116 | |
443f18d0 | 2117 | /* Set up HI parameters to read or write n bytes */ |
57afe2f0 MCC |
2118 | hi_cmd.cmd = SIO_HI_RA_RAM_CMD_ATOMIC_COPY; |
2119 | hi_cmd.param1 = | |
43a431e4 | 2120 | (u16) ((DRXDAP_FASI_ADDR2BLOCK(DRXJ_HI_ATOMIC_BUF_START) << 6) + |
443f18d0 | 2121 | DRXDAP_FASI_ADDR2BANK(DRXJ_HI_ATOMIC_BUF_START)); |
57afe2f0 | 2122 | hi_cmd.param2 = |
43a431e4 | 2123 | (u16) DRXDAP_FASI_ADDR2OFFSET(DRXJ_HI_ATOMIC_BUF_START); |
57afe2f0 | 2124 | hi_cmd.param3 = (u16) ((datasize / 2) - 1); |
63713517 | 2125 | if (!read_flag) |
57afe2f0 | 2126 | hi_cmd.param3 |= DRXJ_HI_ATOMIC_WRITE; |
63713517 | 2127 | else |
57afe2f0 | 2128 | hi_cmd.param3 |= DRXJ_HI_ATOMIC_READ; |
57afe2f0 | 2129 | hi_cmd.param4 = (u16) ((DRXDAP_FASI_ADDR2BLOCK(addr) << 6) + |
443f18d0 | 2130 | DRXDAP_FASI_ADDR2BANK(addr)); |
57afe2f0 | 2131 | hi_cmd.param5 = (u16) DRXDAP_FASI_ADDR2OFFSET(addr); |
443f18d0 | 2132 | |
259f380e | 2133 | if (!read_flag) { |
443f18d0 MCC |
2134 | /* write data to buffer */ |
2135 | for (i = 0; i < (datasize / 2); i++) { | |
2136 | ||
43a431e4 MCC |
2137 | word = ((u16) data[2 * i]); |
2138 | word += (((u16) data[(2 * i) + 1]) << 8); | |
57afe2f0 | 2139 | drxj_dap_write_reg16(dev_addr, |
22892268 | 2140 | (DRXJ_HI_ATOMIC_BUF_START + i), |
443f18d0 MCC |
2141 | word, 0); |
2142 | } | |
2143 | } | |
38b2df95 | 2144 | |
068e94ea | 2145 | rc = hi_command(dev_addr, &hi_cmd, &dummy); |
9482354f | 2146 | if (rc != 0) { |
068e94ea MCC |
2147 | pr_err("error %d\n", rc); |
2148 | goto rw_error; | |
2149 | } | |
443f18d0 | 2150 | |
259f380e | 2151 | if (read_flag) { |
443f18d0 MCC |
2152 | /* read data from buffer */ |
2153 | for (i = 0; i < (datasize / 2); i++) { | |
452c6446 MCC |
2154 | rc = drxj_dap_read_reg16(dev_addr, |
2155 | (DRXJ_HI_ATOMIC_BUF_START + i), | |
2156 | &word, 0); | |
2157 | if (rc) { | |
2158 | pr_err("error %d\n", rc); | |
2159 | goto rw_error; | |
2160 | } | |
43a431e4 MCC |
2161 | data[2 * i] = (u8) (word & 0xFF); |
2162 | data[(2 * i) + 1] = (u8) (word >> 8); | |
443f18d0 MCC |
2163 | } |
2164 | } | |
38b2df95 | 2165 | |
9482354f | 2166 | return 0; |
38b2df95 | 2167 | |
443f18d0 | 2168 | rw_error: |
30741871 | 2169 | return rc; |
38b2df95 DH |
2170 | |
2171 | } | |
2172 | ||
2173 | /*============================================================================*/ | |
2174 | ||
34eb9751 | 2175 | /* |
57afe2f0 | 2176 | * \fn int drxj_dap_atomic_read_reg32() |
38b2df95 DH |
2177 | * \brief Atomic read of 32 bits words |
2178 | */ | |
2179 | static | |
57afe2f0 | 2180 | int drxj_dap_atomic_read_reg32(struct i2c_device_addr *dev_addr, |
1bfc9e15 MCC |
2181 | u32 addr, |
2182 | u32 *data, u32 flags) | |
38b2df95 | 2183 | { |
4182438e | 2184 | u8 buf[sizeof(*data)] = { 0 }; |
9482354f | 2185 | int rc = -EIO; |
43a431e4 | 2186 | u32 word = 0; |
38b2df95 | 2187 | |
63713517 | 2188 | if (!data) |
9482354f | 2189 | return -EINVAL; |
38b2df95 | 2190 | |
57afe2f0 | 2191 | rc = drxj_dap_atomic_read_write_block(dev_addr, addr, |
63713517 | 2192 | sizeof(*data), buf, true); |
38b2df95 | 2193 | |
b1d0a596 MCC |
2194 | if (rc < 0) |
2195 | return 0; | |
2196 | ||
43a431e4 | 2197 | word = (u32) buf[3]; |
443f18d0 | 2198 | word <<= 8; |
43a431e4 | 2199 | word |= (u32) buf[2]; |
443f18d0 | 2200 | word <<= 8; |
43a431e4 | 2201 | word |= (u32) buf[1]; |
443f18d0 | 2202 | word <<= 8; |
43a431e4 | 2203 | word |= (u32) buf[0]; |
38b2df95 | 2204 | |
443f18d0 | 2205 | *data = word; |
38b2df95 | 2206 | |
443f18d0 | 2207 | return rc; |
38b2df95 DH |
2208 | } |
2209 | ||
38b2df95 DH |
2210 | /*============================================================================*/ |
2211 | ||
38b2df95 DH |
2212 | /*============================================================================*/ |
2213 | /*== END DRXJ DAP FUNCTIONS ==*/ | |
2214 | /*============================================================================*/ | |
2215 | ||
2216 | /*============================================================================*/ | |
2217 | /*============================================================================*/ | |
2218 | /*== HOST INTERFACE FUNCTIONS ==*/ | |
2219 | /*============================================================================*/ | |
2220 | /*============================================================================*/ | |
2221 | ||
34eb9751 | 2222 | /* |
57afe2f0 | 2223 | * \fn int hi_cfg_command() |
38b2df95 DH |
2224 | * \brief Configure HI with settings stored in the demod structure. |
2225 | * \param demod Demodulator. | |
61263c75 | 2226 | * \return int. |
38b2df95 DH |
2227 | * |
2228 | * This routine was created because to much orthogonal settings have | |
2229 | * been put into one HI API function (configure). Especially the I2C bridge | |
2230 | * enable/disable should not need re-configuration of the HI. | |
2231 | * | |
2232 | */ | |
1bfc9e15 | 2233 | static int hi_cfg_command(const struct drx_demod_instance *demod) |
38b2df95 | 2234 | { |
b3ce3a83 | 2235 | struct drxj_data *ext_attr = (struct drxj_data *) (NULL); |
60d3603b | 2236 | struct drxj_hi_cmd hi_cmd; |
43a431e4 | 2237 | u16 result = 0; |
068e94ea | 2238 | int rc; |
38b2df95 | 2239 | |
b3ce3a83 | 2240 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
38b2df95 | 2241 | |
57afe2f0 MCC |
2242 | hi_cmd.cmd = SIO_HI_RA_RAM_CMD_CONFIG; |
2243 | hi_cmd.param1 = SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY; | |
2244 | hi_cmd.param2 = ext_attr->hi_cfg_timing_div; | |
2245 | hi_cmd.param3 = ext_attr->hi_cfg_bridge_delay; | |
2246 | hi_cmd.param4 = ext_attr->hi_cfg_wake_up_key; | |
2247 | hi_cmd.param5 = ext_attr->hi_cfg_ctrl; | |
2248 | hi_cmd.param6 = ext_attr->hi_cfg_transmit; | |
38b2df95 | 2249 | |
068e94ea | 2250 | rc = hi_command(demod->my_i2c_dev_addr, &hi_cmd, &result); |
9482354f | 2251 | if (rc != 0) { |
068e94ea MCC |
2252 | pr_err("error %d\n", rc); |
2253 | goto rw_error; | |
2254 | } | |
38b2df95 | 2255 | |
443f18d0 | 2256 | /* Reset power down flag (set one call only) */ |
57afe2f0 | 2257 | ext_attr->hi_cfg_ctrl &= (~(SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ)); |
38b2df95 | 2258 | |
9482354f | 2259 | return 0; |
38b2df95 | 2260 | |
443f18d0 | 2261 | rw_error: |
30741871 | 2262 | return rc; |
38b2df95 DH |
2263 | } |
2264 | ||
34eb9751 | 2265 | /* |
57afe2f0 | 2266 | * \fn int hi_command() |
38b2df95 | 2267 | * \brief Configure HI with settings stored in the demod structure. |
57afe2f0 | 2268 | * \param dev_addr I2C address. |
38b2df95 DH |
2269 | * \param cmd HI command. |
2270 | * \param result HI command result. | |
61263c75 | 2271 | * \return int. |
38b2df95 DH |
2272 | * |
2273 | * Sends command to HI | |
2274 | * | |
2275 | */ | |
61263c75 | 2276 | static int |
60d3603b | 2277 | hi_command(struct i2c_device_addr *dev_addr, const struct drxj_hi_cmd *cmd, u16 *result) |
38b2df95 | 2278 | { |
57afe2f0 MCC |
2279 | u16 wait_cmd = 0; |
2280 | u16 nr_retries = 0; | |
73f7065b | 2281 | bool powerdown_cmd = false; |
068e94ea | 2282 | int rc; |
38b2df95 | 2283 | |
443f18d0 MCC |
2284 | /* Write parameters */ |
2285 | switch (cmd->cmd) { | |
38b2df95 | 2286 | |
443f18d0 MCC |
2287 | case SIO_HI_RA_RAM_CMD_CONFIG: |
2288 | case SIO_HI_RA_RAM_CMD_ATOMIC_COPY: | |
244c0e06 | 2289 | rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_6__A, cmd->param6, 0); |
9482354f | 2290 | if (rc != 0) { |
068e94ea MCC |
2291 | pr_err("error %d\n", rc); |
2292 | goto rw_error; | |
2293 | } | |
244c0e06 | 2294 | rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_5__A, cmd->param5, 0); |
9482354f | 2295 | if (rc != 0) { |
068e94ea MCC |
2296 | pr_err("error %d\n", rc); |
2297 | goto rw_error; | |
2298 | } | |
244c0e06 | 2299 | rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_4__A, cmd->param4, 0); |
9482354f | 2300 | if (rc != 0) { |
068e94ea MCC |
2301 | pr_err("error %d\n", rc); |
2302 | goto rw_error; | |
2303 | } | |
244c0e06 | 2304 | rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_3__A, cmd->param3, 0); |
9482354f | 2305 | if (rc != 0) { |
068e94ea MCC |
2306 | pr_err("error %d\n", rc); |
2307 | goto rw_error; | |
2308 | } | |
443f18d0 MCC |
2309 | /* fallthrough */ |
2310 | case SIO_HI_RA_RAM_CMD_BRDCTRL: | |
244c0e06 | 2311 | rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_2__A, cmd->param2, 0); |
9482354f | 2312 | if (rc != 0) { |
068e94ea MCC |
2313 | pr_err("error %d\n", rc); |
2314 | goto rw_error; | |
2315 | } | |
244c0e06 | 2316 | rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_1__A, cmd->param1, 0); |
9482354f | 2317 | if (rc != 0) { |
068e94ea MCC |
2318 | pr_err("error %d\n", rc); |
2319 | goto rw_error; | |
2320 | } | |
443f18d0 MCC |
2321 | /* fallthrough */ |
2322 | case SIO_HI_RA_RAM_CMD_NULL: | |
2323 | /* No parameters */ | |
2324 | break; | |
38b2df95 | 2325 | |
443f18d0 | 2326 | default: |
9482354f | 2327 | return -EINVAL; |
443f18d0 MCC |
2328 | break; |
2329 | } | |
2330 | ||
2331 | /* Write command */ | |
244c0e06 | 2332 | rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_CMD__A, cmd->cmd, 0); |
9482354f | 2333 | if (rc != 0) { |
068e94ea MCC |
2334 | pr_err("error %d\n", rc); |
2335 | goto rw_error; | |
2336 | } | |
443f18d0 | 2337 | |
63713517 | 2338 | if ((cmd->cmd) == SIO_HI_RA_RAM_CMD_RESET) |
d7b0631e | 2339 | msleep(1); |
38b2df95 | 2340 | |
443f18d0 | 2341 | /* Detect power down to ommit reading result */ |
73f7065b | 2342 | powerdown_cmd = (bool) ((cmd->cmd == SIO_HI_RA_RAM_CMD_CONFIG) && |
443f18d0 MCC |
2343 | (((cmd-> |
2344 | param5) & SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M) | |
2345 | == SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ)); | |
259f380e | 2346 | if (!powerdown_cmd) { |
443f18d0 MCC |
2347 | /* Wait until command rdy */ |
2348 | do { | |
57afe2f0 MCC |
2349 | nr_retries++; |
2350 | if (nr_retries > DRXJ_MAX_RETRIES) { | |
63713517 | 2351 | pr_err("timeout\n"); |
443f18d0 | 2352 | goto rw_error; |
259f380e | 2353 | } |
443f18d0 | 2354 | |
244c0e06 | 2355 | rc = drxj_dap_read_reg16(dev_addr, SIO_HI_RA_RAM_CMD__A, &wait_cmd, 0); |
9482354f | 2356 | if (rc != 0) { |
068e94ea MCC |
2357 | pr_err("error %d\n", rc); |
2358 | goto rw_error; | |
2359 | } | |
57afe2f0 | 2360 | } while (wait_cmd != 0); |
443f18d0 MCC |
2361 | |
2362 | /* Read result */ | |
244c0e06 | 2363 | rc = drxj_dap_read_reg16(dev_addr, SIO_HI_RA_RAM_RES__A, result, 0); |
9482354f | 2364 | if (rc != 0) { |
068e94ea MCC |
2365 | pr_err("error %d\n", rc); |
2366 | goto rw_error; | |
2367 | } | |
443f18d0 MCC |
2368 | |
2369 | } | |
73f7065b | 2370 | /* if ( powerdown_cmd == true ) */ |
9482354f | 2371 | return 0; |
38b2df95 | 2372 | rw_error: |
30741871 | 2373 | return rc; |
38b2df95 DH |
2374 | } |
2375 | ||
34eb9751 | 2376 | /* |
1bfc9e15 | 2377 | * \fn int init_hi( const struct drx_demod_instance *demod ) |
38b2df95 DH |
2378 | * \brief Initialise and configurate HI. |
2379 | * \param demod pointer to demod data. | |
61263c75 | 2380 | * \return int Return status. |
9482354f MCC |
2381 | * \retval 0 Success. |
2382 | * \retval -EIO Failure. | |
38b2df95 DH |
2383 | * |
2384 | * Needs to know Psys (System Clock period) and Posc (Osc Clock period) | |
2385 | * Need to store configuration in driver because of the way I2C | |
2386 | * bridging is controlled. | |
2387 | * | |
2388 | */ | |
1bfc9e15 | 2389 | static int init_hi(const struct drx_demod_instance *demod) |
38b2df95 | 2390 | { |
b3ce3a83 | 2391 | struct drxj_data *ext_attr = (struct drxj_data *) (NULL); |
1bfc9e15 | 2392 | struct drx_common_attr *common_attr = (struct drx_common_attr *) (NULL); |
22892268 | 2393 | struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL); |
068e94ea | 2394 | int rc; |
443f18d0 | 2395 | |
b3ce3a83 | 2396 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
1bfc9e15 | 2397 | common_attr = (struct drx_common_attr *) demod->my_common_attr; |
57afe2f0 | 2398 | dev_addr = demod->my_i2c_dev_addr; |
443f18d0 MCC |
2399 | |
2400 | /* PATCH for bug 5003, HI ucode v3.1.0 */ | |
244c0e06 | 2401 | rc = drxj_dap_write_reg16(dev_addr, 0x4301D7, 0x801, 0); |
9482354f | 2402 | if (rc != 0) { |
068e94ea MCC |
2403 | pr_err("error %d\n", rc); |
2404 | goto rw_error; | |
2405 | } | |
38b2df95 | 2406 | |
443f18d0 MCC |
2407 | /* Timing div, 250ns/Psys */ |
2408 | /* Timing div, = ( delay (nano seconds) * sysclk (kHz) )/ 1000 */ | |
57afe2f0 MCC |
2409 | ext_attr->hi_cfg_timing_div = |
2410 | (u16) ((common_attr->sys_clock_freq / 1000) * HI_I2C_DELAY) / 1000; | |
443f18d0 | 2411 | /* Clipping */ |
63713517 | 2412 | if ((ext_attr->hi_cfg_timing_div) > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M) |
57afe2f0 | 2413 | ext_attr->hi_cfg_timing_div = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M; |
443f18d0 MCC |
2414 | /* Bridge delay, uses oscilator clock */ |
2415 | /* Delay = ( delay (nano seconds) * oscclk (kHz) )/ 1000 */ | |
2416 | /* SDA brdige delay */ | |
57afe2f0 MCC |
2417 | ext_attr->hi_cfg_bridge_delay = |
2418 | (u16) ((common_attr->osc_clock_freq / 1000) * HI_I2C_BRIDGE_DELAY) / | |
443f18d0 MCC |
2419 | 1000; |
2420 | /* Clipping */ | |
63713517 | 2421 | if ((ext_attr->hi_cfg_bridge_delay) > SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M) |
57afe2f0 | 2422 | ext_attr->hi_cfg_bridge_delay = SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M; |
443f18d0 | 2423 | /* SCL bridge delay, same as SDA for now */ |
57afe2f0 | 2424 | ext_attr->hi_cfg_bridge_delay += ((ext_attr->hi_cfg_bridge_delay) << |
443f18d0 MCC |
2425 | SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B); |
2426 | /* Wakeup key, setting the read flag (as suggest in the documentation) does | |
2427 | not always result into a working solution (barebones worked VI2C failed). | |
2428 | Not setting the bit works in all cases . */ | |
57afe2f0 | 2429 | ext_attr->hi_cfg_wake_up_key = DRXJ_WAKE_UP_KEY; |
443f18d0 | 2430 | /* port/bridge/power down ctrl */ |
57afe2f0 | 2431 | ext_attr->hi_cfg_ctrl = (SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE); |
443f18d0 | 2432 | /* transit mode time out delay and watch dog divider */ |
57afe2f0 | 2433 | ext_attr->hi_cfg_transmit = SIO_HI_RA_RAM_PAR_6__PRE; |
443f18d0 | 2434 | |
068e94ea | 2435 | rc = hi_cfg_command(demod); |
9482354f | 2436 | if (rc != 0) { |
068e94ea MCC |
2437 | pr_err("error %d\n", rc); |
2438 | goto rw_error; | |
2439 | } | |
443f18d0 | 2440 | |
9482354f | 2441 | return 0; |
443f18d0 MCC |
2442 | |
2443 | rw_error: | |
30741871 | 2444 | return rc; |
443f18d0 | 2445 | } |
38b2df95 DH |
2446 | |
2447 | /*============================================================================*/ | |
2448 | /*== END HOST INTERFACE FUNCTIONS ==*/ | |
2449 | /*============================================================================*/ | |
2450 | ||
2451 | /*============================================================================*/ | |
2452 | /*============================================================================*/ | |
2453 | /*== AUXILIARY FUNCTIONS ==*/ | |
2454 | /*============================================================================*/ | |
2455 | /*============================================================================*/ | |
2456 | ||
34eb9751 | 2457 | /* |
57afe2f0 | 2458 | * \fn int get_device_capabilities() |
38b2df95 DH |
2459 | * \brief Get and store device capabilities. |
2460 | * \param demod Pointer to demodulator instance. | |
61263c75 | 2461 | * \return int. |
9482354f MCC |
2462 | * \return 0 Success |
2463 | * \retval -EIO Failure | |
38b2df95 DH |
2464 | * |
2465 | * Depending on pulldowns on MDx pins the following internals are set: | |
57afe2f0 MCC |
2466 | * * common_attr->osc_clock_freq |
2467 | * * ext_attr->has_lna | |
2468 | * * ext_attr->has_ntsc | |
2469 | * * ext_attr->has_btsc | |
2470 | * * ext_attr->has_oob | |
38b2df95 DH |
2471 | * |
2472 | */ | |
1bfc9e15 | 2473 | static int get_device_capabilities(struct drx_demod_instance *demod) |
38b2df95 | 2474 | { |
1bfc9e15 | 2475 | struct drx_common_attr *common_attr = (struct drx_common_attr *) (NULL); |
b3ce3a83 | 2476 | struct drxj_data *ext_attr = (struct drxj_data *) NULL; |
22892268 | 2477 | struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL); |
57afe2f0 MCC |
2478 | u16 sio_pdr_ohw_cfg = 0; |
2479 | u32 sio_top_jtagid_lo = 0; | |
43a431e4 | 2480 | u16 bid = 0; |
068e94ea | 2481 | int rc; |
443f18d0 | 2482 | |
1bfc9e15 | 2483 | common_attr = (struct drx_common_attr *) demod->my_common_attr; |
b3ce3a83 | 2484 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
57afe2f0 | 2485 | dev_addr = demod->my_i2c_dev_addr; |
443f18d0 | 2486 | |
244c0e06 | 2487 | rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0); |
9482354f | 2488 | if (rc != 0) { |
068e94ea MCC |
2489 | pr_err("error %d\n", rc); |
2490 | goto rw_error; | |
2491 | } | |
244c0e06 | 2492 | rc = drxj_dap_read_reg16(dev_addr, SIO_PDR_OHW_CFG__A, &sio_pdr_ohw_cfg, 0); |
9482354f | 2493 | if (rc != 0) { |
068e94ea MCC |
2494 | pr_err("error %d\n", rc); |
2495 | goto rw_error; | |
2496 | } | |
244c0e06 | 2497 | rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY__PRE, 0); |
9482354f | 2498 | if (rc != 0) { |
068e94ea MCC |
2499 | pr_err("error %d\n", rc); |
2500 | goto rw_error; | |
2501 | } | |
443f18d0 | 2502 | |
57afe2f0 | 2503 | switch ((sio_pdr_ohw_cfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) { |
443f18d0 MCC |
2504 | case 0: |
2505 | /* ignore (bypass ?) */ | |
2506 | break; | |
2507 | case 1: | |
2508 | /* 27 MHz */ | |
57afe2f0 | 2509 | common_attr->osc_clock_freq = 27000; |
443f18d0 MCC |
2510 | break; |
2511 | case 2: | |
2512 | /* 20.25 MHz */ | |
57afe2f0 | 2513 | common_attr->osc_clock_freq = 20250; |
443f18d0 MCC |
2514 | break; |
2515 | case 3: | |
2516 | /* 4 MHz */ | |
57afe2f0 | 2517 | common_attr->osc_clock_freq = 4000; |
443f18d0 MCC |
2518 | break; |
2519 | default: | |
9482354f | 2520 | return -EIO; |
443f18d0 MCC |
2521 | } |
2522 | ||
2523 | /* | |
2524 | Determine device capabilities | |
2525 | Based on pinning v47 | |
2526 | */ | |
244c0e06 | 2527 | rc = drxdap_fasi_read_reg32(dev_addr, SIO_TOP_JTAGID_LO__A, &sio_top_jtagid_lo, 0); |
9482354f | 2528 | if (rc != 0) { |
068e94ea MCC |
2529 | pr_err("error %d\n", rc); |
2530 | goto rw_error; | |
2531 | } | |
57afe2f0 | 2532 | ext_attr->mfx = (u8) ((sio_top_jtagid_lo >> 29) & 0xF); |
443f18d0 | 2533 | |
57afe2f0 | 2534 | switch ((sio_top_jtagid_lo >> 12) & 0xFF) { |
443f18d0 | 2535 | case 0x31: |
244c0e06 | 2536 | rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0); |
9482354f | 2537 | if (rc != 0) { |
068e94ea MCC |
2538 | pr_err("error %d\n", rc); |
2539 | goto rw_error; | |
2540 | } | |
244c0e06 | 2541 | rc = drxj_dap_read_reg16(dev_addr, SIO_PDR_UIO_IN_HI__A, &bid, 0); |
9482354f | 2542 | if (rc != 0) { |
068e94ea MCC |
2543 | pr_err("error %d\n", rc); |
2544 | goto rw_error; | |
2545 | } | |
443f18d0 | 2546 | bid = (bid >> 10) & 0xf; |
244c0e06 | 2547 | rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY__PRE, 0); |
9482354f | 2548 | if (rc != 0) { |
068e94ea MCC |
2549 | pr_err("error %d\n", rc); |
2550 | goto rw_error; | |
2551 | } | |
443f18d0 | 2552 | |
57afe2f0 MCC |
2553 | ext_attr->has_lna = true; |
2554 | ext_attr->has_ntsc = false; | |
2555 | ext_attr->has_btsc = false; | |
2556 | ext_attr->has_oob = false; | |
2557 | ext_attr->has_smatx = true; | |
2558 | ext_attr->has_smarx = false; | |
2559 | ext_attr->has_gpio = false; | |
2560 | ext_attr->has_irqn = false; | |
443f18d0 MCC |
2561 | break; |
2562 | case 0x33: | |
57afe2f0 MCC |
2563 | ext_attr->has_lna = false; |
2564 | ext_attr->has_ntsc = false; | |
2565 | ext_attr->has_btsc = false; | |
2566 | ext_attr->has_oob = false; | |
2567 | ext_attr->has_smatx = true; | |
2568 | ext_attr->has_smarx = false; | |
2569 | ext_attr->has_gpio = false; | |
2570 | ext_attr->has_irqn = false; | |
443f18d0 MCC |
2571 | break; |
2572 | case 0x45: | |
57afe2f0 MCC |
2573 | ext_attr->has_lna = true; |
2574 | ext_attr->has_ntsc = true; | |
2575 | ext_attr->has_btsc = false; | |
2576 | ext_attr->has_oob = false; | |
2577 | ext_attr->has_smatx = true; | |
2578 | ext_attr->has_smarx = true; | |
2579 | ext_attr->has_gpio = true; | |
2580 | ext_attr->has_irqn = false; | |
443f18d0 MCC |
2581 | break; |
2582 | case 0x46: | |
57afe2f0 MCC |
2583 | ext_attr->has_lna = false; |
2584 | ext_attr->has_ntsc = true; | |
2585 | ext_attr->has_btsc = false; | |
2586 | ext_attr->has_oob = false; | |
2587 | ext_attr->has_smatx = true; | |
2588 | ext_attr->has_smarx = true; | |
2589 | ext_attr->has_gpio = true; | |
2590 | ext_attr->has_irqn = false; | |
443f18d0 MCC |
2591 | break; |
2592 | case 0x41: | |
57afe2f0 MCC |
2593 | ext_attr->has_lna = true; |
2594 | ext_attr->has_ntsc = true; | |
2595 | ext_attr->has_btsc = true; | |
2596 | ext_attr->has_oob = false; | |
2597 | ext_attr->has_smatx = true; | |
2598 | ext_attr->has_smarx = true; | |
2599 | ext_attr->has_gpio = true; | |
2600 | ext_attr->has_irqn = false; | |
443f18d0 MCC |
2601 | break; |
2602 | case 0x43: | |
57afe2f0 MCC |
2603 | ext_attr->has_lna = false; |
2604 | ext_attr->has_ntsc = true; | |
2605 | ext_attr->has_btsc = true; | |
2606 | ext_attr->has_oob = false; | |
2607 | ext_attr->has_smatx = true; | |
2608 | ext_attr->has_smarx = true; | |
2609 | ext_attr->has_gpio = true; | |
2610 | ext_attr->has_irqn = false; | |
443f18d0 MCC |
2611 | break; |
2612 | case 0x32: | |
57afe2f0 MCC |
2613 | ext_attr->has_lna = true; |
2614 | ext_attr->has_ntsc = false; | |
2615 | ext_attr->has_btsc = false; | |
2616 | ext_attr->has_oob = true; | |
2617 | ext_attr->has_smatx = true; | |
2618 | ext_attr->has_smarx = true; | |
2619 | ext_attr->has_gpio = true; | |
2620 | ext_attr->has_irqn = true; | |
443f18d0 MCC |
2621 | break; |
2622 | case 0x34: | |
57afe2f0 MCC |
2623 | ext_attr->has_lna = false; |
2624 | ext_attr->has_ntsc = true; | |
2625 | ext_attr->has_btsc = true; | |
2626 | ext_attr->has_oob = true; | |
2627 | ext_attr->has_smatx = true; | |
2628 | ext_attr->has_smarx = true; | |
2629 | ext_attr->has_gpio = true; | |
2630 | ext_attr->has_irqn = true; | |
443f18d0 MCC |
2631 | break; |
2632 | case 0x42: | |
57afe2f0 MCC |
2633 | ext_attr->has_lna = true; |
2634 | ext_attr->has_ntsc = true; | |
2635 | ext_attr->has_btsc = true; | |
2636 | ext_attr->has_oob = true; | |
2637 | ext_attr->has_smatx = true; | |
2638 | ext_attr->has_smarx = true; | |
2639 | ext_attr->has_gpio = true; | |
2640 | ext_attr->has_irqn = true; | |
443f18d0 MCC |
2641 | break; |
2642 | case 0x44: | |
57afe2f0 MCC |
2643 | ext_attr->has_lna = false; |
2644 | ext_attr->has_ntsc = true; | |
2645 | ext_attr->has_btsc = true; | |
2646 | ext_attr->has_oob = true; | |
2647 | ext_attr->has_smatx = true; | |
2648 | ext_attr->has_smarx = true; | |
2649 | ext_attr->has_gpio = true; | |
2650 | ext_attr->has_irqn = true; | |
443f18d0 MCC |
2651 | break; |
2652 | default: | |
2653 | /* Unknown device variant */ | |
9482354f | 2654 | return -EIO; |
443f18d0 MCC |
2655 | break; |
2656 | } | |
2657 | ||
9482354f | 2658 | return 0; |
38b2df95 | 2659 | rw_error: |
30741871 | 2660 | return rc; |
38b2df95 DH |
2661 | } |
2662 | ||
34eb9751 | 2663 | /* |
57afe2f0 | 2664 | * \fn int power_up_device() |
38b2df95 DH |
2665 | * \brief Power up device. |
2666 | * \param demod Pointer to demodulator instance. | |
61263c75 | 2667 | * \return int. |
9482354f MCC |
2668 | * \return 0 Success |
2669 | * \retval -EIO Failure, I2C or max retries reached | |
38b2df95 DH |
2670 | * |
2671 | */ | |
2672 | ||
2673 | #ifndef DRXJ_MAX_RETRIES_POWERUP | |
2674 | #define DRXJ_MAX_RETRIES_POWERUP 10 | |
2675 | #endif | |
2676 | ||
1bfc9e15 | 2677 | static int power_up_device(struct drx_demod_instance *demod) |
443f18d0 | 2678 | { |
22892268 | 2679 | struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL); |
43a431e4 | 2680 | u8 data = 0; |
57afe2f0 MCC |
2681 | u16 retry_count = 0; |
2682 | struct i2c_device_addr wake_up_addr; | |
443f18d0 | 2683 | |
57afe2f0 MCC |
2684 | dev_addr = demod->my_i2c_dev_addr; |
2685 | wake_up_addr.i2c_addr = DRXJ_WAKE_UP_KEY; | |
2686 | wake_up_addr.i2c_dev_id = dev_addr->i2c_dev_id; | |
2687 | wake_up_addr.user_data = dev_addr->user_data; | |
068e94ea MCC |
2688 | /* |
2689 | * I2C access may fail in this case: no ack | |
2690 | * dummy write must be used to wake uop device, dummy read must be used to | |
2691 | * reset HI state machine (avoiding actual writes) | |
2692 | */ | |
443f18d0 MCC |
2693 | do { |
2694 | data = 0; | |
57afe2f0 | 2695 | drxbsp_i2c_write_read(&wake_up_addr, 1, &data, |
22892268 MCC |
2696 | (struct i2c_device_addr *)(NULL), 0, |
2697 | (u8 *)(NULL)); | |
d7b0631e | 2698 | msleep(10); |
57afe2f0 MCC |
2699 | retry_count++; |
2700 | } while ((drxbsp_i2c_write_read | |
22892268 | 2701 | ((struct i2c_device_addr *) (NULL), 0, (u8 *)(NULL), dev_addr, 1, |
443f18d0 | 2702 | &data) |
9482354f | 2703 | != 0) && (retry_count < DRXJ_MAX_RETRIES_POWERUP)); |
443f18d0 MCC |
2704 | |
2705 | /* Need some recovery time .... */ | |
d7b0631e | 2706 | msleep(10); |
443f18d0 | 2707 | |
63713517 | 2708 | if (retry_count == DRXJ_MAX_RETRIES_POWERUP) |
9482354f | 2709 | return -EIO; |
38b2df95 | 2710 | |
9482354f | 2711 | return 0; |
38b2df95 DH |
2712 | } |
2713 | ||
2714 | /*----------------------------------------------------------------------------*/ | |
2715 | /* MPEG Output Configuration Functions - begin */ | |
2716 | /*----------------------------------------------------------------------------*/ | |
34eb9751 | 2717 | /* |
57afe2f0 | 2718 | * \fn int ctrl_set_cfg_mpeg_output() |
38b2df95 DH |
2719 | * \brief Set MPEG output configuration of the device. |
2720 | * \param devmod Pointer to demodulator instance. | |
57afe2f0 | 2721 | * \param cfg_data Pointer to mpeg output configuaration. |
61263c75 | 2722 | * \return int. |
38b2df95 DH |
2723 | * |
2724 | * Configure MPEG output parameters. | |
2725 | * | |
2726 | */ | |
61263c75 | 2727 | static int |
1bfc9e15 | 2728 | ctrl_set_cfg_mpeg_output(struct drx_demod_instance *demod, struct drx_cfg_mpeg_output *cfg_data) |
57afe2f0 | 2729 | { |
22892268 | 2730 | struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL); |
b3ce3a83 | 2731 | struct drxj_data *ext_attr = (struct drxj_data *) (NULL); |
1bfc9e15 | 2732 | struct drx_common_attr *common_attr = (struct drx_common_attr *) (NULL); |
068e94ea | 2733 | int rc; |
57afe2f0 MCC |
2734 | u16 fec_oc_reg_mode = 0; |
2735 | u16 fec_oc_reg_ipr_mode = 0; | |
2736 | u16 fec_oc_reg_ipr_invert = 0; | |
2737 | u32 max_bit_rate = 0; | |
2738 | u32 rcn_rate = 0; | |
2739 | u32 nr_bits = 0; | |
2740 | u16 sio_pdr_md_cfg = 0; | |
443f18d0 | 2741 | /* data mask for the output data byte */ |
57afe2f0 | 2742 | u16 invert_data_mask = |
443f18d0 MCC |
2743 | FEC_OC_IPR_INVERT_MD7__M | FEC_OC_IPR_INVERT_MD6__M | |
2744 | FEC_OC_IPR_INVERT_MD5__M | FEC_OC_IPR_INVERT_MD4__M | | |
2745 | FEC_OC_IPR_INVERT_MD3__M | FEC_OC_IPR_INVERT_MD2__M | | |
2746 | FEC_OC_IPR_INVERT_MD1__M | FEC_OC_IPR_INVERT_MD0__M; | |
068e94ea | 2747 | |
443f18d0 | 2748 | /* check arguments */ |
63713517 | 2749 | if ((demod == NULL) || (cfg_data == NULL)) |
9482354f | 2750 | return -EINVAL; |
38b2df95 | 2751 | |
57afe2f0 | 2752 | dev_addr = demod->my_i2c_dev_addr; |
b3ce3a83 | 2753 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
1bfc9e15 | 2754 | common_attr = (struct drx_common_attr *) demod->my_common_attr; |
443f18d0 | 2755 | |
57afe2f0 | 2756 | if (cfg_data->enable_mpeg_output == true) { |
443f18d0 MCC |
2757 | /* quick and dirty patch to set MPEG incase current std is not |
2758 | producing MPEG */ | |
57afe2f0 | 2759 | switch (ext_attr->standard) { |
443f18d0 MCC |
2760 | case DRX_STANDARD_8VSB: |
2761 | case DRX_STANDARD_ITU_A: | |
2762 | case DRX_STANDARD_ITU_B: | |
2763 | case DRX_STANDARD_ITU_C: | |
2764 | break; | |
2765 | default: | |
9482354f | 2766 | return 0; |
443f18d0 MCC |
2767 | } |
2768 | ||
244c0e06 | 2769 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_OCR_INVERT__A, 0, 0); |
9482354f | 2770 | if (rc != 0) { |
068e94ea MCC |
2771 | pr_err("error %d\n", rc); |
2772 | goto rw_error; | |
2773 | } | |
57afe2f0 | 2774 | switch (ext_attr->standard) { |
443f18d0 | 2775 | case DRX_STANDARD_8VSB: |
244c0e06 | 2776 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_FCT_USAGE__A, 7, 0); |
9482354f | 2777 | if (rc != 0) { |
068e94ea MCC |
2778 | pr_err("error %d\n", rc); |
2779 | goto rw_error; | |
2780 | } /* 2048 bytes fifo ram */ | |
244c0e06 | 2781 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_TMD_CTL_UPD_RATE__A, 10, 0); |
9482354f | 2782 | if (rc != 0) { |
068e94ea MCC |
2783 | pr_err("error %d\n", rc); |
2784 | goto rw_error; | |
2785 | } | |
244c0e06 | 2786 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_TMD_INT_UPD_RATE__A, 10, 0); |
9482354f | 2787 | if (rc != 0) { |
068e94ea MCC |
2788 | pr_err("error %d\n", rc); |
2789 | goto rw_error; | |
2790 | } | |
244c0e06 | 2791 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_AVR_PARM_A__A, 5, 0); |
9482354f | 2792 | if (rc != 0) { |
068e94ea MCC |
2793 | pr_err("error %d\n", rc); |
2794 | goto rw_error; | |
2795 | } | |
244c0e06 | 2796 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_AVR_PARM_B__A, 7, 0); |
9482354f | 2797 | if (rc != 0) { |
068e94ea MCC |
2798 | pr_err("error %d\n", rc); |
2799 | goto rw_error; | |
2800 | } | |
244c0e06 | 2801 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_RCN_GAIN__A, 10, 0); |
9482354f | 2802 | if (rc != 0) { |
068e94ea MCC |
2803 | pr_err("error %d\n", rc); |
2804 | goto rw_error; | |
2805 | } | |
443f18d0 | 2806 | /* Low Water Mark for synchronization */ |
244c0e06 | 2807 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_LWM__A, 3, 0); |
9482354f | 2808 | if (rc != 0) { |
068e94ea MCC |
2809 | pr_err("error %d\n", rc); |
2810 | goto rw_error; | |
2811 | } | |
443f18d0 | 2812 | /* High Water Mark for synchronization */ |
244c0e06 | 2813 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_HWM__A, 5, 0); |
9482354f | 2814 | if (rc != 0) { |
068e94ea MCC |
2815 | pr_err("error %d\n", rc); |
2816 | goto rw_error; | |
2817 | } | |
443f18d0 MCC |
2818 | break; |
2819 | case DRX_STANDARD_ITU_A: | |
2820 | case DRX_STANDARD_ITU_C: | |
57afe2f0 | 2821 | switch (ext_attr->constellation) { |
443f18d0 | 2822 | case DRX_CONSTELLATION_QAM256: |
57afe2f0 | 2823 | nr_bits = 8; |
443f18d0 MCC |
2824 | break; |
2825 | case DRX_CONSTELLATION_QAM128: | |
57afe2f0 | 2826 | nr_bits = 7; |
443f18d0 MCC |
2827 | break; |
2828 | case DRX_CONSTELLATION_QAM64: | |
57afe2f0 | 2829 | nr_bits = 6; |
443f18d0 MCC |
2830 | break; |
2831 | case DRX_CONSTELLATION_QAM32: | |
57afe2f0 | 2832 | nr_bits = 5; |
443f18d0 MCC |
2833 | break; |
2834 | case DRX_CONSTELLATION_QAM16: | |
57afe2f0 | 2835 | nr_bits = 4; |
443f18d0 MCC |
2836 | break; |
2837 | default: | |
9482354f | 2838 | return -EIO; |
57afe2f0 MCC |
2839 | } /* ext_attr->constellation */ |
2840 | /* max_bit_rate = symbol_rate * nr_bits * coef */ | |
443f18d0 | 2841 | /* coef = 188/204 */ |
57afe2f0 MCC |
2842 | max_bit_rate = |
2843 | (ext_attr->curr_symbol_rate / 8) * nr_bits * 188; | |
40e43111 | 2844 | /* fall-through - as b/c Annex A/C need following settings */ |
443f18d0 | 2845 | case DRX_STANDARD_ITU_B: |
244c0e06 | 2846 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_FCT_USAGE__A, FEC_OC_FCT_USAGE__PRE, 0); |
9482354f | 2847 | if (rc != 0) { |
068e94ea MCC |
2848 | pr_err("error %d\n", rc); |
2849 | goto rw_error; | |
2850 | } | |
244c0e06 | 2851 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_TMD_CTL_UPD_RATE__A, FEC_OC_TMD_CTL_UPD_RATE__PRE, 0); |
9482354f | 2852 | if (rc != 0) { |
068e94ea MCC |
2853 | pr_err("error %d\n", rc); |
2854 | goto rw_error; | |
2855 | } | |
244c0e06 | 2856 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_TMD_INT_UPD_RATE__A, 5, 0); |
9482354f | 2857 | if (rc != 0) { |
068e94ea MCC |
2858 | pr_err("error %d\n", rc); |
2859 | goto rw_error; | |
2860 | } | |
244c0e06 | 2861 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_AVR_PARM_A__A, FEC_OC_AVR_PARM_A__PRE, 0); |
9482354f | 2862 | if (rc != 0) { |
068e94ea MCC |
2863 | pr_err("error %d\n", rc); |
2864 | goto rw_error; | |
2865 | } | |
244c0e06 | 2866 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_AVR_PARM_B__A, FEC_OC_AVR_PARM_B__PRE, 0); |
9482354f | 2867 | if (rc != 0) { |
068e94ea MCC |
2868 | pr_err("error %d\n", rc); |
2869 | goto rw_error; | |
2870 | } | |
57afe2f0 | 2871 | if (cfg_data->static_clk == true) { |
244c0e06 | 2872 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_RCN_GAIN__A, 0xD, 0); |
9482354f | 2873 | if (rc != 0) { |
068e94ea MCC |
2874 | pr_err("error %d\n", rc); |
2875 | goto rw_error; | |
2876 | } | |
443f18d0 | 2877 | } else { |
244c0e06 | 2878 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_RCN_GAIN__A, FEC_OC_RCN_GAIN__PRE, 0); |
9482354f | 2879 | if (rc != 0) { |
068e94ea MCC |
2880 | pr_err("error %d\n", rc); |
2881 | goto rw_error; | |
2882 | } | |
2883 | } | |
244c0e06 | 2884 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_LWM__A, 2, 0); |
9482354f | 2885 | if (rc != 0) { |
068e94ea MCC |
2886 | pr_err("error %d\n", rc); |
2887 | goto rw_error; | |
2888 | } | |
244c0e06 | 2889 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_HWM__A, 12, 0); |
9482354f | 2890 | if (rc != 0) { |
068e94ea MCC |
2891 | pr_err("error %d\n", rc); |
2892 | goto rw_error; | |
443f18d0 | 2893 | } |
443f18d0 MCC |
2894 | break; |
2895 | default: | |
2896 | break; | |
2897 | } /* swtich (standard) */ | |
2898 | ||
2899 | /* Check insertion of the Reed-Solomon parity bytes */ | |
244c0e06 | 2900 | rc = drxj_dap_read_reg16(dev_addr, FEC_OC_MODE__A, &fec_oc_reg_mode, 0); |
9482354f | 2901 | if (rc != 0) { |
068e94ea MCC |
2902 | pr_err("error %d\n", rc); |
2903 | goto rw_error; | |
2904 | } | |
244c0e06 | 2905 | rc = drxj_dap_read_reg16(dev_addr, FEC_OC_IPR_MODE__A, &fec_oc_reg_ipr_mode, 0); |
9482354f | 2906 | if (rc != 0) { |
068e94ea MCC |
2907 | pr_err("error %d\n", rc); |
2908 | goto rw_error; | |
2909 | } | |
57afe2f0 | 2910 | if (cfg_data->insert_rs_byte == true) { |
443f18d0 | 2911 | /* enable parity symbol forward */ |
57afe2f0 | 2912 | fec_oc_reg_mode |= FEC_OC_MODE_PARITY__M; |
443f18d0 | 2913 | /* MVAL disable during parity bytes */ |
57afe2f0 MCC |
2914 | fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M; |
2915 | switch (ext_attr->standard) { | |
443f18d0 | 2916 | case DRX_STANDARD_8VSB: |
57afe2f0 | 2917 | rcn_rate = 0x004854D3; |
443f18d0 MCC |
2918 | break; |
2919 | case DRX_STANDARD_ITU_B: | |
57afe2f0 MCC |
2920 | fec_oc_reg_mode |= FEC_OC_MODE_TRANSPARENT__M; |
2921 | switch (ext_attr->constellation) { | |
443f18d0 | 2922 | case DRX_CONSTELLATION_QAM256: |
57afe2f0 | 2923 | rcn_rate = 0x008945E7; |
443f18d0 MCC |
2924 | break; |
2925 | case DRX_CONSTELLATION_QAM64: | |
57afe2f0 | 2926 | rcn_rate = 0x005F64D4; |
443f18d0 MCC |
2927 | break; |
2928 | default: | |
9482354f | 2929 | return -EIO; |
443f18d0 MCC |
2930 | } |
2931 | break; | |
2932 | case DRX_STANDARD_ITU_A: | |
2933 | case DRX_STANDARD_ITU_C: | |
57afe2f0 MCC |
2934 | /* insert_rs_byte = true -> coef = 188/188 -> 1, RS bits are in MPEG output */ |
2935 | rcn_rate = | |
2936 | (frac28 | |
2937 | (max_bit_rate, | |
2938 | (u32) (common_attr->sys_clock_freq / 8))) / | |
443f18d0 MCC |
2939 | 188; |
2940 | break; | |
2941 | default: | |
9482354f | 2942 | return -EIO; |
57afe2f0 MCC |
2943 | } /* ext_attr->standard */ |
2944 | } else { /* insert_rs_byte == false */ | |
443f18d0 MCC |
2945 | |
2946 | /* disable parity symbol forward */ | |
57afe2f0 | 2947 | fec_oc_reg_mode &= (~FEC_OC_MODE_PARITY__M); |
443f18d0 | 2948 | /* MVAL enable during parity bytes */ |
57afe2f0 MCC |
2949 | fec_oc_reg_ipr_mode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M); |
2950 | switch (ext_attr->standard) { | |
443f18d0 | 2951 | case DRX_STANDARD_8VSB: |
57afe2f0 | 2952 | rcn_rate = 0x0041605C; |
443f18d0 MCC |
2953 | break; |
2954 | case DRX_STANDARD_ITU_B: | |
57afe2f0 MCC |
2955 | fec_oc_reg_mode &= (~FEC_OC_MODE_TRANSPARENT__M); |
2956 | switch (ext_attr->constellation) { | |
443f18d0 | 2957 | case DRX_CONSTELLATION_QAM256: |
57afe2f0 | 2958 | rcn_rate = 0x0082D6A0; |
443f18d0 MCC |
2959 | break; |
2960 | case DRX_CONSTELLATION_QAM64: | |
57afe2f0 | 2961 | rcn_rate = 0x005AEC1A; |
443f18d0 MCC |
2962 | break; |
2963 | default: | |
9482354f | 2964 | return -EIO; |
443f18d0 MCC |
2965 | } |
2966 | break; | |
2967 | case DRX_STANDARD_ITU_A: | |
2968 | case DRX_STANDARD_ITU_C: | |
57afe2f0 MCC |
2969 | /* insert_rs_byte = false -> coef = 188/204, RS bits not in MPEG output */ |
2970 | rcn_rate = | |
2971 | (frac28 | |
2972 | (max_bit_rate, | |
2973 | (u32) (common_attr->sys_clock_freq / 8))) / | |
443f18d0 MCC |
2974 | 204; |
2975 | break; | |
2976 | default: | |
9482354f | 2977 | return -EIO; |
57afe2f0 | 2978 | } /* ext_attr->standard */ |
443f18d0 MCC |
2979 | } |
2980 | ||
69bb7ab6 | 2981 | if (cfg_data->enable_parallel == true) { /* MPEG data output is parallel -> clear ipr_mode[0] */ |
57afe2f0 | 2982 | fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M)); |
443f18d0 | 2983 | } else { /* MPEG data output is serial -> set ipr_mode[0] */ |
57afe2f0 | 2984 | fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M; |
443f18d0 MCC |
2985 | } |
2986 | ||
2987 | /* Control slective inversion of output bits */ | |
63713517 | 2988 | if (cfg_data->invert_data == true) |
57afe2f0 | 2989 | fec_oc_reg_ipr_invert |= invert_data_mask; |
63713517 | 2990 | else |
57afe2f0 | 2991 | fec_oc_reg_ipr_invert &= (~(invert_data_mask)); |
443f18d0 | 2992 | |
63713517 | 2993 | if (cfg_data->invert_err == true) |
57afe2f0 | 2994 | fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MERR__M; |
63713517 | 2995 | else |
57afe2f0 | 2996 | fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MERR__M)); |
443f18d0 | 2997 | |
63713517 | 2998 | if (cfg_data->invert_str == true) |
57afe2f0 | 2999 | fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MSTRT__M; |
63713517 | 3000 | else |
57afe2f0 | 3001 | fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MSTRT__M)); |
443f18d0 | 3002 | |
63713517 | 3003 | if (cfg_data->invert_val == true) |
57afe2f0 | 3004 | fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MVAL__M; |
63713517 | 3005 | else |
57afe2f0 | 3006 | fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MVAL__M)); |
443f18d0 | 3007 | |
63713517 | 3008 | if (cfg_data->invert_clk == true) |
57afe2f0 | 3009 | fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MCLK__M; |
63713517 | 3010 | else |
57afe2f0 | 3011 | fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MCLK__M)); |
443f18d0 | 3012 | |
41b5cc0c | 3013 | |
57afe2f0 MCC |
3014 | if (cfg_data->static_clk == true) { /* Static mode */ |
3015 | u32 dto_rate = 0; | |
3016 | u32 bit_rate = 0; | |
3017 | u16 fec_oc_dto_burst_len = 0; | |
3018 | u16 fec_oc_dto_period = 0; | |
443f18d0 | 3019 | |
57afe2f0 | 3020 | fec_oc_dto_burst_len = FEC_OC_DTO_BURST_LEN__PRE; |
443f18d0 | 3021 | |
57afe2f0 | 3022 | switch (ext_attr->standard) { |
443f18d0 | 3023 | case DRX_STANDARD_8VSB: |
57afe2f0 | 3024 | fec_oc_dto_period = 4; |
63713517 | 3025 | if (cfg_data->insert_rs_byte == true) |
57afe2f0 | 3026 | fec_oc_dto_burst_len = 208; |
443f18d0 MCC |
3027 | break; |
3028 | case DRX_STANDARD_ITU_A: | |
3029 | { | |
57afe2f0 MCC |
3030 | u32 symbol_rate_th = 6400000; |
3031 | if (cfg_data->insert_rs_byte == true) { | |
3032 | fec_oc_dto_burst_len = 204; | |
3033 | symbol_rate_th = 5900000; | |
443f18d0 | 3034 | } |
57afe2f0 MCC |
3035 | if (ext_attr->curr_symbol_rate >= |
3036 | symbol_rate_th) { | |
3037 | fec_oc_dto_period = 0; | |
443f18d0 | 3038 | } else { |
57afe2f0 | 3039 | fec_oc_dto_period = 1; |
443f18d0 MCC |
3040 | } |
3041 | } | |
3042 | break; | |
3043 | case DRX_STANDARD_ITU_B: | |
57afe2f0 | 3044 | fec_oc_dto_period = 1; |
63713517 | 3045 | if (cfg_data->insert_rs_byte == true) |
57afe2f0 | 3046 | fec_oc_dto_burst_len = 128; |
443f18d0 MCC |
3047 | break; |
3048 | case DRX_STANDARD_ITU_C: | |
57afe2f0 | 3049 | fec_oc_dto_period = 1; |
63713517 | 3050 | if (cfg_data->insert_rs_byte == true) |
57afe2f0 | 3051 | fec_oc_dto_burst_len = 204; |
443f18d0 MCC |
3052 | break; |
3053 | default: | |
9482354f | 3054 | return -EIO; |
443f18d0 | 3055 | } |
57afe2f0 MCC |
3056 | bit_rate = |
3057 | common_attr->sys_clock_freq * 1000 / (fec_oc_dto_period + | |
443f18d0 | 3058 | 2); |
57afe2f0 MCC |
3059 | dto_rate = |
3060 | frac28(bit_rate, common_attr->sys_clock_freq * 1000); | |
3061 | dto_rate >>= 3; | |
244c0e06 | 3062 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DTO_RATE_HI__A, (u16)((dto_rate >> 16) & FEC_OC_DTO_RATE_HI__M), 0); |
9482354f | 3063 | if (rc != 0) { |
068e94ea MCC |
3064 | pr_err("error %d\n", rc); |
3065 | goto rw_error; | |
3066 | } | |
244c0e06 | 3067 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DTO_RATE_LO__A, (u16)(dto_rate & FEC_OC_DTO_RATE_LO_RATE_LO__M), 0); |
9482354f | 3068 | if (rc != 0) { |
068e94ea MCC |
3069 | pr_err("error %d\n", rc); |
3070 | goto rw_error; | |
3071 | } | |
244c0e06 | 3072 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DTO_MODE__A, FEC_OC_DTO_MODE_DYNAMIC__M | FEC_OC_DTO_MODE_OFFSET_ENABLE__M, 0); |
9482354f | 3073 | if (rc != 0) { |
068e94ea MCC |
3074 | pr_err("error %d\n", rc); |
3075 | goto rw_error; | |
3076 | } | |
244c0e06 | 3077 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_FCT_MODE__A, FEC_OC_FCT_MODE_RAT_ENA__M | FEC_OC_FCT_MODE_VIRT_ENA__M, 0); |
9482354f | 3078 | if (rc != 0) { |
068e94ea MCC |
3079 | pr_err("error %d\n", rc); |
3080 | goto rw_error; | |
3081 | } | |
244c0e06 | 3082 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DTO_BURST_LEN__A, fec_oc_dto_burst_len, 0); |
9482354f | 3083 | if (rc != 0) { |
068e94ea MCC |
3084 | pr_err("error %d\n", rc); |
3085 | goto rw_error; | |
3086 | } | |
63713517 MCC |
3087 | if (ext_attr->mpeg_output_clock_rate != DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO) |
3088 | fec_oc_dto_period = ext_attr->mpeg_output_clock_rate - 1; | |
244c0e06 | 3089 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DTO_PERIOD__A, fec_oc_dto_period, 0); |
9482354f | 3090 | if (rc != 0) { |
068e94ea MCC |
3091 | pr_err("error %d\n", rc); |
3092 | goto rw_error; | |
3093 | } | |
443f18d0 MCC |
3094 | } else { /* Dynamic mode */ |
3095 | ||
244c0e06 | 3096 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DTO_MODE__A, FEC_OC_DTO_MODE_DYNAMIC__M, 0); |
9482354f | 3097 | if (rc != 0) { |
068e94ea MCC |
3098 | pr_err("error %d\n", rc); |
3099 | goto rw_error; | |
3100 | } | |
244c0e06 | 3101 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_FCT_MODE__A, 0, 0); |
9482354f | 3102 | if (rc != 0) { |
068e94ea MCC |
3103 | pr_err("error %d\n", rc); |
3104 | goto rw_error; | |
3105 | } | |
443f18d0 MCC |
3106 | } |
3107 | ||
244c0e06 | 3108 | rc = drxdap_fasi_write_reg32(dev_addr, FEC_OC_RCN_CTL_RATE_LO__A, rcn_rate, 0); |
9482354f | 3109 | if (rc != 0) { |
068e94ea MCC |
3110 | pr_err("error %d\n", rc); |
3111 | goto rw_error; | |
3112 | } | |
443f18d0 MCC |
3113 | |
3114 | /* Write appropriate registers with requested configuration */ | |
244c0e06 | 3115 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_MODE__A, fec_oc_reg_mode, 0); |
9482354f | 3116 | if (rc != 0) { |
068e94ea MCC |
3117 | pr_err("error %d\n", rc); |
3118 | goto rw_error; | |
3119 | } | |
244c0e06 | 3120 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_IPR_MODE__A, fec_oc_reg_ipr_mode, 0); |
9482354f | 3121 | if (rc != 0) { |
068e94ea MCC |
3122 | pr_err("error %d\n", rc); |
3123 | goto rw_error; | |
3124 | } | |
244c0e06 | 3125 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_IPR_INVERT__A, fec_oc_reg_ipr_invert, 0); |
9482354f | 3126 | if (rc != 0) { |
068e94ea MCC |
3127 | pr_err("error %d\n", rc); |
3128 | goto rw_error; | |
3129 | } | |
443f18d0 MCC |
3130 | |
3131 | /* enabling for both parallel and serial now */ | |
3132 | /* Write magic word to enable pdr reg write */ | |
244c0e06 | 3133 | rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA, 0); |
9482354f | 3134 | if (rc != 0) { |
068e94ea MCC |
3135 | pr_err("error %d\n", rc); |
3136 | goto rw_error; | |
3137 | } | |
443f18d0 | 3138 | /* Set MPEG TS pads to outputmode */ |
244c0e06 | 3139 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MSTRT_CFG__A, 0x0013, 0); |
9482354f | 3140 | if (rc != 0) { |
068e94ea MCC |
3141 | pr_err("error %d\n", rc); |
3142 | goto rw_error; | |
3143 | } | |
244c0e06 | 3144 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MERR_CFG__A, 0x0013, 0); |
9482354f | 3145 | if (rc != 0) { |
068e94ea MCC |
3146 | pr_err("error %d\n", rc); |
3147 | goto rw_error; | |
3148 | } | |
244c0e06 | 3149 | rc = drxj_dap_write_reg16(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); |
9482354f | 3150 | if (rc != 0) { |
068e94ea MCC |
3151 | pr_err("error %d\n", rc); |
3152 | goto rw_error; | |
3153 | } | |
244c0e06 | 3154 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MVAL_CFG__A, 0x0013, 0); |
9482354f | 3155 | if (rc != 0) { |
068e94ea MCC |
3156 | pr_err("error %d\n", rc); |
3157 | goto rw_error; | |
3158 | } | |
57afe2f0 | 3159 | sio_pdr_md_cfg = |
443f18d0 MCC |
3160 | MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH << |
3161 | SIO_PDR_MD0_CFG_DRIVE__B | 0x03 << SIO_PDR_MD0_CFG_MODE__B; | |
244c0e06 | 3162 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD0_CFG__A, sio_pdr_md_cfg, 0); |
9482354f | 3163 | if (rc != 0) { |
068e94ea MCC |
3164 | pr_err("error %d\n", rc); |
3165 | goto rw_error; | |
3166 | } | |
69bb7ab6 | 3167 | if (cfg_data->enable_parallel == true) { /* MPEG data output is parallel -> set MD1 to MD7 to output mode */ |
57afe2f0 | 3168 | sio_pdr_md_cfg = |
443f18d0 MCC |
3169 | MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH << |
3170 | SIO_PDR_MD0_CFG_DRIVE__B | 0x03 << | |
3171 | SIO_PDR_MD0_CFG_MODE__B; | |
244c0e06 | 3172 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD0_CFG__A, sio_pdr_md_cfg, 0); |
9482354f | 3173 | if (rc != 0) { |
068e94ea MCC |
3174 | pr_err("error %d\n", rc); |
3175 | goto rw_error; | |
3176 | } | |
244c0e06 | 3177 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD1_CFG__A, sio_pdr_md_cfg, 0); |
9482354f | 3178 | if (rc != 0) { |
068e94ea MCC |
3179 | pr_err("error %d\n", rc); |
3180 | goto rw_error; | |
3181 | } | |
244c0e06 | 3182 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD2_CFG__A, sio_pdr_md_cfg, 0); |
9482354f | 3183 | if (rc != 0) { |
068e94ea MCC |
3184 | pr_err("error %d\n", rc); |
3185 | goto rw_error; | |
3186 | } | |
244c0e06 | 3187 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD3_CFG__A, sio_pdr_md_cfg, 0); |
9482354f | 3188 | if (rc != 0) { |
068e94ea MCC |
3189 | pr_err("error %d\n", rc); |
3190 | goto rw_error; | |
3191 | } | |
244c0e06 | 3192 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD4_CFG__A, sio_pdr_md_cfg, 0); |
9482354f | 3193 | if (rc != 0) { |
068e94ea MCC |
3194 | pr_err("error %d\n", rc); |
3195 | goto rw_error; | |
3196 | } | |
244c0e06 | 3197 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD5_CFG__A, sio_pdr_md_cfg, 0); |
9482354f | 3198 | if (rc != 0) { |
068e94ea MCC |
3199 | pr_err("error %d\n", rc); |
3200 | goto rw_error; | |
3201 | } | |
244c0e06 | 3202 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD6_CFG__A, sio_pdr_md_cfg, 0); |
9482354f | 3203 | if (rc != 0) { |
068e94ea MCC |
3204 | pr_err("error %d\n", rc); |
3205 | goto rw_error; | |
3206 | } | |
244c0e06 | 3207 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD7_CFG__A, sio_pdr_md_cfg, 0); |
9482354f | 3208 | if (rc != 0) { |
068e94ea MCC |
3209 | pr_err("error %d\n", rc); |
3210 | goto rw_error; | |
3211 | } | |
443f18d0 | 3212 | } else { /* MPEG data output is serial -> set MD1 to MD7 to tri-state */ |
244c0e06 | 3213 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD1_CFG__A, 0x0000, 0); |
9482354f | 3214 | if (rc != 0) { |
068e94ea MCC |
3215 | pr_err("error %d\n", rc); |
3216 | goto rw_error; | |
3217 | } | |
244c0e06 | 3218 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD2_CFG__A, 0x0000, 0); |
9482354f | 3219 | if (rc != 0) { |
068e94ea MCC |
3220 | pr_err("error %d\n", rc); |
3221 | goto rw_error; | |
3222 | } | |
244c0e06 | 3223 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD3_CFG__A, 0x0000, 0); |
9482354f | 3224 | if (rc != 0) { |
068e94ea MCC |
3225 | pr_err("error %d\n", rc); |
3226 | goto rw_error; | |
3227 | } | |
244c0e06 | 3228 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD4_CFG__A, 0x0000, 0); |
9482354f | 3229 | if (rc != 0) { |
068e94ea MCC |
3230 | pr_err("error %d\n", rc); |
3231 | goto rw_error; | |
3232 | } | |
244c0e06 | 3233 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD5_CFG__A, 0x0000, 0); |
9482354f | 3234 | if (rc != 0) { |
068e94ea MCC |
3235 | pr_err("error %d\n", rc); |
3236 | goto rw_error; | |
3237 | } | |
244c0e06 | 3238 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD6_CFG__A, 0x0000, 0); |
9482354f | 3239 | if (rc != 0) { |
068e94ea MCC |
3240 | pr_err("error %d\n", rc); |
3241 | goto rw_error; | |
3242 | } | |
244c0e06 | 3243 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD7_CFG__A, 0x0000, 0); |
9482354f | 3244 | if (rc != 0) { |
068e94ea MCC |
3245 | pr_err("error %d\n", rc); |
3246 | goto rw_error; | |
3247 | } | |
443f18d0 MCC |
3248 | } |
3249 | /* Enable Monitor Bus output over MPEG pads and ctl input */ | |
244c0e06 | 3250 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MON_CFG__A, 0x0000, 0); |
9482354f | 3251 | if (rc != 0) { |
068e94ea MCC |
3252 | pr_err("error %d\n", rc); |
3253 | goto rw_error; | |
3254 | } | |
443f18d0 | 3255 | /* Write nomagic word to enable pdr reg write */ |
244c0e06 | 3256 | rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0); |
9482354f | 3257 | if (rc != 0) { |
068e94ea MCC |
3258 | pr_err("error %d\n", rc); |
3259 | goto rw_error; | |
3260 | } | |
443f18d0 MCC |
3261 | } else { |
3262 | /* Write magic word to enable pdr reg write */ | |
244c0e06 | 3263 | rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA, 0); |
9482354f | 3264 | if (rc != 0) { |
068e94ea MCC |
3265 | pr_err("error %d\n", rc); |
3266 | goto rw_error; | |
3267 | } | |
443f18d0 | 3268 | /* Set MPEG TS pads to inputmode */ |
244c0e06 | 3269 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MSTRT_CFG__A, 0x0000, 0); |
9482354f | 3270 | if (rc != 0) { |
068e94ea MCC |
3271 | pr_err("error %d\n", rc); |
3272 | goto rw_error; | |
3273 | } | |
244c0e06 | 3274 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MERR_CFG__A, 0x0000, 0); |
9482354f | 3275 | if (rc != 0) { |
068e94ea MCC |
3276 | pr_err("error %d\n", rc); |
3277 | goto rw_error; | |
3278 | } | |
244c0e06 | 3279 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MCLK_CFG__A, 0x0000, 0); |
9482354f | 3280 | if (rc != 0) { |
068e94ea MCC |
3281 | pr_err("error %d\n", rc); |
3282 | goto rw_error; | |
3283 | } | |
244c0e06 | 3284 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MVAL_CFG__A, 0x0000, 0); |
9482354f | 3285 | if (rc != 0) { |
068e94ea MCC |
3286 | pr_err("error %d\n", rc); |
3287 | goto rw_error; | |
3288 | } | |
244c0e06 | 3289 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD0_CFG__A, 0x0000, 0); |
9482354f | 3290 | if (rc != 0) { |
068e94ea MCC |
3291 | pr_err("error %d\n", rc); |
3292 | goto rw_error; | |
3293 | } | |
244c0e06 | 3294 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD1_CFG__A, 0x0000, 0); |
9482354f | 3295 | if (rc != 0) { |
068e94ea MCC |
3296 | pr_err("error %d\n", rc); |
3297 | goto rw_error; | |
3298 | } | |
244c0e06 | 3299 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD2_CFG__A, 0x0000, 0); |
9482354f | 3300 | if (rc != 0) { |
068e94ea MCC |
3301 | pr_err("error %d\n", rc); |
3302 | goto rw_error; | |
3303 | } | |
244c0e06 | 3304 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD3_CFG__A, 0x0000, 0); |
9482354f | 3305 | if (rc != 0) { |
068e94ea MCC |
3306 | pr_err("error %d\n", rc); |
3307 | goto rw_error; | |
3308 | } | |
244c0e06 | 3309 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD4_CFG__A, 0x0000, 0); |
9482354f | 3310 | if (rc != 0) { |
068e94ea MCC |
3311 | pr_err("error %d\n", rc); |
3312 | goto rw_error; | |
3313 | } | |
244c0e06 | 3314 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD5_CFG__A, 0x0000, 0); |
9482354f | 3315 | if (rc != 0) { |
068e94ea MCC |
3316 | pr_err("error %d\n", rc); |
3317 | goto rw_error; | |
3318 | } | |
244c0e06 | 3319 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD6_CFG__A, 0x0000, 0); |
9482354f | 3320 | if (rc != 0) { |
068e94ea MCC |
3321 | pr_err("error %d\n", rc); |
3322 | goto rw_error; | |
3323 | } | |
244c0e06 | 3324 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD7_CFG__A, 0x0000, 0); |
9482354f | 3325 | if (rc != 0) { |
068e94ea MCC |
3326 | pr_err("error %d\n", rc); |
3327 | goto rw_error; | |
3328 | } | |
443f18d0 | 3329 | /* Enable Monitor Bus output over MPEG pads and ctl input */ |
244c0e06 | 3330 | rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MON_CFG__A, 0x0000, 0); |
9482354f | 3331 | if (rc != 0) { |
068e94ea MCC |
3332 | pr_err("error %d\n", rc); |
3333 | goto rw_error; | |
3334 | } | |
443f18d0 | 3335 | /* Write nomagic word to enable pdr reg write */ |
244c0e06 | 3336 | rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0); |
9482354f | 3337 | if (rc != 0) { |
068e94ea MCC |
3338 | pr_err("error %d\n", rc); |
3339 | goto rw_error; | |
3340 | } | |
443f18d0 MCC |
3341 | } |
3342 | ||
3343 | /* save values for restore after re-acquire */ | |
57afe2f0 | 3344 | common_attr->mpeg_cfg.enable_mpeg_output = cfg_data->enable_mpeg_output; |
443f18d0 | 3345 | |
9482354f | 3346 | return 0; |
38b2df95 | 3347 | rw_error: |
30741871 | 3348 | return rc; |
38b2df95 DH |
3349 | } |
3350 | ||
3351 | /*----------------------------------------------------------------------------*/ | |
3352 | ||
38b2df95 DH |
3353 | |
3354 | /*----------------------------------------------------------------------------*/ | |
3355 | /* MPEG Output Configuration Functions - end */ | |
3356 | /*----------------------------------------------------------------------------*/ | |
3357 | ||
3358 | /*----------------------------------------------------------------------------*/ | |
2c149601 | 3359 | /* miscellaneous configurations - begin */ |
38b2df95 DH |
3360 | /*----------------------------------------------------------------------------*/ |
3361 | ||
34eb9751 | 3362 | /* |
57afe2f0 | 3363 | * \fn int set_mpegtei_handling() |
38b2df95 DH |
3364 | * \brief Activate MPEG TEI handling settings. |
3365 | * \param devmod Pointer to demodulator instance. | |
61263c75 | 3366 | * \return int. |
38b2df95 DH |
3367 | * |
3368 | * This routine should be called during a set channel of QAM/VSB | |
3369 | * | |
3370 | */ | |
1bfc9e15 | 3371 | static int set_mpegtei_handling(struct drx_demod_instance *demod) |
38b2df95 | 3372 | { |
b3ce3a83 | 3373 | struct drxj_data *ext_attr = (struct drxj_data *) (NULL); |
22892268 | 3374 | struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL); |
068e94ea | 3375 | int rc; |
57afe2f0 MCC |
3376 | u16 fec_oc_dpr_mode = 0; |
3377 | u16 fec_oc_snc_mode = 0; | |
3378 | u16 fec_oc_ems_mode = 0; | |
443f18d0 | 3379 | |
57afe2f0 | 3380 | dev_addr = demod->my_i2c_dev_addr; |
b3ce3a83 | 3381 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
443f18d0 | 3382 | |
244c0e06 | 3383 | rc = drxj_dap_read_reg16(dev_addr, FEC_OC_DPR_MODE__A, &fec_oc_dpr_mode, 0); |
9482354f | 3384 | if (rc != 0) { |
068e94ea MCC |
3385 | pr_err("error %d\n", rc); |
3386 | goto rw_error; | |
3387 | } | |
244c0e06 | 3388 | rc = drxj_dap_read_reg16(dev_addr, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode, 0); |
9482354f | 3389 | if (rc != 0) { |
068e94ea MCC |
3390 | pr_err("error %d\n", rc); |
3391 | goto rw_error; | |
3392 | } | |
244c0e06 | 3393 | rc = drxj_dap_read_reg16(dev_addr, FEC_OC_EMS_MODE__A, &fec_oc_ems_mode, 0); |
9482354f | 3394 | if (rc != 0) { |
068e94ea MCC |
3395 | pr_err("error %d\n", rc); |
3396 | goto rw_error; | |
3397 | } | |
443f18d0 MCC |
3398 | |
3399 | /* reset to default, allow TEI bit to be changed */ | |
57afe2f0 MCC |
3400 | fec_oc_dpr_mode &= (~FEC_OC_DPR_MODE_ERR_DISABLE__M); |
3401 | fec_oc_snc_mode &= (~(FEC_OC_SNC_MODE_ERROR_CTL__M | | |
443f18d0 | 3402 | FEC_OC_SNC_MODE_CORR_DISABLE__M)); |
57afe2f0 | 3403 | fec_oc_ems_mode &= (~FEC_OC_EMS_MODE_MODE__M); |
443f18d0 | 3404 | |
259f380e | 3405 | if (ext_attr->disable_te_ihandling) { |
443f18d0 | 3406 | /* do not change TEI bit */ |
57afe2f0 MCC |
3407 | fec_oc_dpr_mode |= FEC_OC_DPR_MODE_ERR_DISABLE__M; |
3408 | fec_oc_snc_mode |= FEC_OC_SNC_MODE_CORR_DISABLE__M | | |
443f18d0 | 3409 | ((0x2) << (FEC_OC_SNC_MODE_ERROR_CTL__B)); |
57afe2f0 | 3410 | fec_oc_ems_mode |= ((0x01) << (FEC_OC_EMS_MODE_MODE__B)); |
443f18d0 MCC |
3411 | } |
3412 | ||
244c0e06 | 3413 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DPR_MODE__A, fec_oc_dpr_mode, 0); |
9482354f | 3414 | if (rc != 0) { |
068e94ea MCC |
3415 | pr_err("error %d\n", rc); |
3416 | goto rw_error; | |
3417 | } | |
244c0e06 | 3418 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_MODE__A, fec_oc_snc_mode, 0); |
9482354f | 3419 | if (rc != 0) { |
068e94ea MCC |
3420 | pr_err("error %d\n", rc); |
3421 | goto rw_error; | |
3422 | } | |
244c0e06 | 3423 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_EMS_MODE__A, fec_oc_ems_mode, 0); |
9482354f | 3424 | if (rc != 0) { |
068e94ea MCC |
3425 | pr_err("error %d\n", rc); |
3426 | goto rw_error; | |
3427 | } | |
443f18d0 | 3428 | |
9482354f | 3429 | return 0; |
38b2df95 | 3430 | rw_error: |
30741871 | 3431 | return rc; |
38b2df95 DH |
3432 | } |
3433 | ||
3434 | /*----------------------------------------------------------------------------*/ | |
34eb9751 | 3435 | /* |
57afe2f0 | 3436 | * \fn int bit_reverse_mpeg_output() |
38b2df95 DH |
3437 | * \brief Set MPEG output bit-endian settings. |
3438 | * \param devmod Pointer to demodulator instance. | |
61263c75 | 3439 | * \return int. |
38b2df95 DH |
3440 | * |
3441 | * This routine should be called during a set channel of QAM/VSB | |
3442 | * | |
3443 | */ | |
1bfc9e15 | 3444 | static int bit_reverse_mpeg_output(struct drx_demod_instance *demod) |
38b2df95 | 3445 | { |
b3ce3a83 | 3446 | struct drxj_data *ext_attr = (struct drxj_data *) (NULL); |
22892268 | 3447 | struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL); |
068e94ea | 3448 | int rc; |
57afe2f0 | 3449 | u16 fec_oc_ipr_mode = 0; |
38b2df95 | 3450 | |
57afe2f0 | 3451 | dev_addr = demod->my_i2c_dev_addr; |
b3ce3a83 | 3452 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
38b2df95 | 3453 | |
244c0e06 | 3454 | rc = drxj_dap_read_reg16(dev_addr, FEC_OC_IPR_MODE__A, &fec_oc_ipr_mode, 0); |
9482354f | 3455 | if (rc != 0) { |
068e94ea MCC |
3456 | pr_err("error %d\n", rc); |
3457 | goto rw_error; | |
3458 | } | |
38b2df95 | 3459 | |
443f18d0 | 3460 | /* reset to default (normal bit order) */ |
57afe2f0 | 3461 | fec_oc_ipr_mode &= (~FEC_OC_IPR_MODE_REVERSE_ORDER__M); |
38b2df95 | 3462 | |
63713517 | 3463 | if (ext_attr->bit_reverse_mpeg_outout) |
57afe2f0 | 3464 | fec_oc_ipr_mode |= FEC_OC_IPR_MODE_REVERSE_ORDER__M; |
38b2df95 | 3465 | |
244c0e06 | 3466 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_IPR_MODE__A, fec_oc_ipr_mode, 0); |
9482354f | 3467 | if (rc != 0) { |
068e94ea MCC |
3468 | pr_err("error %d\n", rc); |
3469 | goto rw_error; | |
3470 | } | |
38b2df95 | 3471 | |
9482354f | 3472 | return 0; |
38b2df95 | 3473 | rw_error: |
30741871 | 3474 | return rc; |
38b2df95 DH |
3475 | } |
3476 | ||
38b2df95 | 3477 | /*----------------------------------------------------------------------------*/ |
34eb9751 | 3478 | /* |
57afe2f0 | 3479 | * \fn int set_mpeg_start_width() |
38b2df95 DH |
3480 | * \brief Set MPEG start width. |
3481 | * \param devmod Pointer to demodulator instance. | |
61263c75 | 3482 | * \return int. |
38b2df95 DH |
3483 | * |
3484 | * This routine should be called during a set channel of QAM/VSB | |
3485 | * | |
3486 | */ | |
1bfc9e15 | 3487 | static int set_mpeg_start_width(struct drx_demod_instance *demod) |
38b2df95 | 3488 | { |
b3ce3a83 | 3489 | struct drxj_data *ext_attr = (struct drxj_data *) (NULL); |
22892268 | 3490 | struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL); |
1bfc9e15 | 3491 | struct drx_common_attr *common_attr = (struct drx_common_attr *) NULL; |
068e94ea MCC |
3492 | int rc; |
3493 | u16 fec_oc_comm_mb = 0; | |
38b2df95 | 3494 | |
57afe2f0 | 3495 | dev_addr = demod->my_i2c_dev_addr; |
b3ce3a83 | 3496 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
57afe2f0 | 3497 | common_attr = demod->my_common_attr; |
38b2df95 | 3498 | |
57afe2f0 MCC |
3499 | if ((common_attr->mpeg_cfg.static_clk == true) |
3500 | && (common_attr->mpeg_cfg.enable_parallel == false)) { | |
244c0e06 | 3501 | rc = drxj_dap_read_reg16(dev_addr, FEC_OC_COMM_MB__A, &fec_oc_comm_mb, 0); |
9482354f | 3502 | if (rc != 0) { |
068e94ea MCC |
3503 | pr_err("error %d\n", rc); |
3504 | goto rw_error; | |
3505 | } | |
57afe2f0 | 3506 | fec_oc_comm_mb &= ~FEC_OC_COMM_MB_CTL_ON; |
63713517 | 3507 | if (ext_attr->mpeg_start_width == DRXJ_MPEG_START_WIDTH_8CLKCYC) |
57afe2f0 | 3508 | fec_oc_comm_mb |= FEC_OC_COMM_MB_CTL_ON; |
244c0e06 | 3509 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_COMM_MB__A, fec_oc_comm_mb, 0); |
9482354f | 3510 | if (rc != 0) { |
068e94ea MCC |
3511 | pr_err("error %d\n", rc); |
3512 | goto rw_error; | |
3513 | } | |
443f18d0 MCC |
3514 | } |
3515 | ||
9482354f | 3516 | return 0; |
38b2df95 | 3517 | rw_error: |
30741871 | 3518 | return rc; |
38b2df95 DH |
3519 | } |
3520 | ||
38b2df95 | 3521 | /*----------------------------------------------------------------------------*/ |
2c149601 | 3522 | /* miscellaneous configurations - end */ |
38b2df95 DH |
3523 | /*----------------------------------------------------------------------------*/ |
3524 | ||
3525 | /*----------------------------------------------------------------------------*/ | |
3526 | /* UIO Configuration Functions - begin */ | |
3527 | /*----------------------------------------------------------------------------*/ | |
34eb9751 | 3528 | /* |
57afe2f0 | 3529 | * \fn int ctrl_set_uio_cfg() |
38b2df95 DH |
3530 | * \brief Configure modus oprandi UIO. |
3531 | * \param demod Pointer to demodulator instance. | |
57afe2f0 | 3532 | * \param uio_cfg Pointer to a configuration setting for a certain UIO. |
61263c75 | 3533 | * \return int. |
38b2df95 | 3534 | */ |
1bfc9e15 | 3535 | static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg *uio_cfg) |
38b2df95 | 3536 | { |
b3ce3a83 | 3537 | struct drxj_data *ext_attr = (struct drxj_data *) (NULL); |
068e94ea | 3538 | int rc; |
38b2df95 | 3539 | |
63713517 | 3540 | if ((uio_cfg == NULL) || (demod == NULL)) |
9482354f | 3541 | return -EINVAL; |
63713517 | 3542 | |
b3ce3a83 | 3543 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
38b2df95 | 3544 | |
443f18d0 | 3545 | /* Write magic word to enable pdr reg write */ |
244c0e06 | 3546 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0); |
9482354f | 3547 | if (rc != 0) { |
068e94ea MCC |
3548 | pr_err("error %d\n", rc); |
3549 | goto rw_error; | |
3550 | } | |
57afe2f0 | 3551 | switch (uio_cfg->uio) { |
38b2df95 | 3552 | /*====================================================================*/ |
443f18d0 MCC |
3553 | case DRX_UIO1: |
3554 | /* DRX_UIO1: SMA_TX UIO-1 */ | |
259f380e | 3555 | if (!ext_attr->has_smatx) |
9482354f | 3556 | return -EIO; |
57afe2f0 | 3557 | switch (uio_cfg->mode) { |
78cf8c84 GS |
3558 | case DRX_UIO_MODE_FIRMWARE_SMA: /* fall through */ |
3559 | case DRX_UIO_MODE_FIRMWARE_SAW: /* fall through */ | |
443f18d0 | 3560 | case DRX_UIO_MODE_READWRITE: |
57afe2f0 | 3561 | ext_attr->uio_sma_tx_mode = uio_cfg->mode; |
443f18d0 MCC |
3562 | break; |
3563 | case DRX_UIO_MODE_DISABLE: | |
57afe2f0 | 3564 | ext_attr->uio_sma_tx_mode = uio_cfg->mode; |
443f18d0 | 3565 | /* pad configuration register is set 0 - input mode */ |
244c0e06 | 3566 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, 0, 0); |
9482354f | 3567 | if (rc != 0) { |
068e94ea MCC |
3568 | pr_err("error %d\n", rc); |
3569 | goto rw_error; | |
3570 | } | |
443f18d0 MCC |
3571 | break; |
3572 | default: | |
9482354f | 3573 | return -EINVAL; |
57afe2f0 | 3574 | } /* switch ( uio_cfg->mode ) */ |
443f18d0 | 3575 | break; |
38b2df95 | 3576 | /*====================================================================*/ |
443f18d0 MCC |
3577 | case DRX_UIO2: |
3578 | /* DRX_UIO2: SMA_RX UIO-2 */ | |
259f380e | 3579 | if (!ext_attr->has_smarx) |
9482354f | 3580 | return -EIO; |
57afe2f0 | 3581 | switch (uio_cfg->mode) { |
78cf8c84 | 3582 | case DRX_UIO_MODE_FIRMWARE0: /* fall through */ |
443f18d0 | 3583 | case DRX_UIO_MODE_READWRITE: |
57afe2f0 | 3584 | ext_attr->uio_sma_rx_mode = uio_cfg->mode; |
443f18d0 MCC |
3585 | break; |
3586 | case DRX_UIO_MODE_DISABLE: | |
57afe2f0 | 3587 | ext_attr->uio_sma_rx_mode = uio_cfg->mode; |
443f18d0 | 3588 | /* pad configuration register is set 0 - input mode */ |
244c0e06 | 3589 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_RX_CFG__A, 0, 0); |
9482354f | 3590 | if (rc != 0) { |
068e94ea MCC |
3591 | pr_err("error %d\n", rc); |
3592 | goto rw_error; | |
3593 | } | |
443f18d0 MCC |
3594 | break; |
3595 | default: | |
9482354f | 3596 | return -EINVAL; |
443f18d0 | 3597 | break; |
57afe2f0 | 3598 | } /* switch ( uio_cfg->mode ) */ |
443f18d0 | 3599 | break; |
38b2df95 | 3600 | /*====================================================================*/ |
443f18d0 MCC |
3601 | case DRX_UIO3: |
3602 | /* DRX_UIO3: GPIO UIO-3 */ | |
259f380e | 3603 | if (!ext_attr->has_gpio) |
9482354f | 3604 | return -EIO; |
57afe2f0 | 3605 | switch (uio_cfg->mode) { |
78cf8c84 | 3606 | case DRX_UIO_MODE_FIRMWARE0: /* fall through */ |
443f18d0 | 3607 | case DRX_UIO_MODE_READWRITE: |
57afe2f0 | 3608 | ext_attr->uio_gpio_mode = uio_cfg->mode; |
443f18d0 MCC |
3609 | break; |
3610 | case DRX_UIO_MODE_DISABLE: | |
57afe2f0 | 3611 | ext_attr->uio_gpio_mode = uio_cfg->mode; |
443f18d0 | 3612 | /* pad configuration register is set 0 - input mode */ |
244c0e06 | 3613 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_GPIO_CFG__A, 0, 0); |
9482354f | 3614 | if (rc != 0) { |
068e94ea MCC |
3615 | pr_err("error %d\n", rc); |
3616 | goto rw_error; | |
3617 | } | |
443f18d0 MCC |
3618 | break; |
3619 | default: | |
9482354f | 3620 | return -EINVAL; |
443f18d0 | 3621 | break; |
57afe2f0 | 3622 | } /* switch ( uio_cfg->mode ) */ |
443f18d0 | 3623 | break; |
38b2df95 | 3624 | /*====================================================================*/ |
443f18d0 MCC |
3625 | case DRX_UIO4: |
3626 | /* DRX_UIO4: IRQN UIO-4 */ | |
259f380e | 3627 | if (!ext_attr->has_irqn) |
9482354f | 3628 | return -EIO; |
57afe2f0 | 3629 | switch (uio_cfg->mode) { |
443f18d0 | 3630 | case DRX_UIO_MODE_READWRITE: |
57afe2f0 | 3631 | ext_attr->uio_irqn_mode = uio_cfg->mode; |
443f18d0 MCC |
3632 | break; |
3633 | case DRX_UIO_MODE_DISABLE: | |
3634 | /* pad configuration register is set 0 - input mode */ | |
244c0e06 | 3635 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_IRQN_CFG__A, 0, 0); |
9482354f | 3636 | if (rc != 0) { |
068e94ea MCC |
3637 | pr_err("error %d\n", rc); |
3638 | goto rw_error; | |
3639 | } | |
57afe2f0 | 3640 | ext_attr->uio_irqn_mode = uio_cfg->mode; |
443f18d0 | 3641 | break; |
78cf8c84 | 3642 | case DRX_UIO_MODE_FIRMWARE0: /* fall through */ |
443f18d0 | 3643 | default: |
9482354f | 3644 | return -EINVAL; |
443f18d0 | 3645 | break; |
57afe2f0 | 3646 | } /* switch ( uio_cfg->mode ) */ |
443f18d0 | 3647 | break; |
38b2df95 | 3648 | /*====================================================================*/ |
443f18d0 | 3649 | default: |
9482354f | 3650 | return -EINVAL; |
57afe2f0 | 3651 | } /* switch ( uio_cfg->uio ) */ |
38b2df95 | 3652 | |
443f18d0 | 3653 | /* Write magic word to disable pdr reg write */ |
244c0e06 | 3654 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0); |
9482354f | 3655 | if (rc != 0) { |
068e94ea MCC |
3656 | pr_err("error %d\n", rc); |
3657 | goto rw_error; | |
3658 | } | |
38b2df95 | 3659 | |
9482354f | 3660 | return 0; |
443f18d0 | 3661 | rw_error: |
30741871 | 3662 | return rc; |
38b2df95 DH |
3663 | } |
3664 | ||
34eb9751 | 3665 | /* |
b6c4065e MCC |
3666 | * \fn int ctrl_uio_write() |
3667 | * \brief Write to a UIO. | |
38b2df95 | 3668 | * \param demod Pointer to demodulator instance. |
b6c4065e | 3669 | * \param uio_data Pointer to data container for a certain UIO. |
61263c75 | 3670 | * \return int. |
38b2df95 | 3671 | */ |
b6c4065e MCC |
3672 | static int |
3673 | ctrl_uio_write(struct drx_demod_instance *demod, struct drxuio_data *uio_data) | |
38b2df95 | 3674 | { |
b6c4065e MCC |
3675 | struct drxj_data *ext_attr = (struct drxj_data *) (NULL); |
3676 | int rc; | |
3677 | u16 pin_cfg_value = 0; | |
3678 | u16 value = 0; | |
38b2df95 | 3679 | |
b6c4065e | 3680 | if ((uio_data == NULL) || (demod == NULL)) |
9482354f | 3681 | return -EINVAL; |
38b2df95 | 3682 | |
b6c4065e | 3683 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
38b2df95 | 3684 | |
443f18d0 | 3685 | /* Write magic word to enable pdr reg write */ |
244c0e06 | 3686 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0); |
9482354f | 3687 | if (rc != 0) { |
068e94ea MCC |
3688 | pr_err("error %d\n", rc); |
3689 | goto rw_error; | |
3690 | } | |
57afe2f0 | 3691 | switch (uio_data->uio) { |
38b2df95 | 3692 | /*====================================================================*/ |
443f18d0 MCC |
3693 | case DRX_UIO1: |
3694 | /* DRX_UIO1: SMA_TX UIO-1 */ | |
259f380e | 3695 | if (!ext_attr->has_smatx) |
9482354f | 3696 | return -EIO; |
57afe2f0 MCC |
3697 | if ((ext_attr->uio_sma_tx_mode != DRX_UIO_MODE_READWRITE) |
3698 | && (ext_attr->uio_sma_tx_mode != DRX_UIO_MODE_FIRMWARE_SAW)) { | |
9482354f | 3699 | return -EIO; |
443f18d0 | 3700 | } |
57afe2f0 | 3701 | pin_cfg_value = 0; |
443f18d0 | 3702 | /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */ |
57afe2f0 | 3703 | pin_cfg_value |= 0x0113; |
443f18d0 MCC |
3704 | /* io_pad_cfg_mode output mode is drive always */ |
3705 | /* io_pad_cfg_drive is set to power 2 (23 mA) */ | |
3706 | ||
3707 | /* write to io pad configuration register - output mode */ | |
244c0e06 | 3708 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, pin_cfg_value, 0); |
9482354f | 3709 | if (rc != 0) { |
068e94ea MCC |
3710 | pr_err("error %d\n", rc); |
3711 | goto rw_error; | |
3712 | } | |
443f18d0 MCC |
3713 | |
3714 | /* use corresponding bit in io data output registar */ | |
244c0e06 | 3715 | rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, &value, 0); |
9482354f | 3716 | if (rc != 0) { |
068e94ea MCC |
3717 | pr_err("error %d\n", rc); |
3718 | goto rw_error; | |
3719 | } | |
63713517 | 3720 | if (!uio_data->value) |
443f18d0 | 3721 | value &= 0x7FFF; /* write zero to 15th bit - 1st UIO */ |
63713517 | 3722 | else |
443f18d0 | 3723 | value |= 0x8000; /* write one to 15th bit - 1st UIO */ |
63713517 | 3724 | |
443f18d0 | 3725 | /* write back to io data output register */ |
244c0e06 | 3726 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value, 0); |
9482354f | 3727 | if (rc != 0) { |
068e94ea MCC |
3728 | pr_err("error %d\n", rc); |
3729 | goto rw_error; | |
3730 | } | |
443f18d0 | 3731 | break; |
38b2df95 | 3732 | /*======================================================================*/ |
443f18d0 MCC |
3733 | case DRX_UIO2: |
3734 | /* DRX_UIO2: SMA_RX UIO-2 */ | |
259f380e | 3735 | if (!ext_attr->has_smarx) |
9482354f | 3736 | return -EIO; |
63713517 | 3737 | if (ext_attr->uio_sma_rx_mode != DRX_UIO_MODE_READWRITE) |
9482354f | 3738 | return -EIO; |
63713517 | 3739 | |
57afe2f0 | 3740 | pin_cfg_value = 0; |
443f18d0 | 3741 | /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */ |
57afe2f0 | 3742 | pin_cfg_value |= 0x0113; |
443f18d0 MCC |
3743 | /* io_pad_cfg_mode output mode is drive always */ |
3744 | /* io_pad_cfg_drive is set to power 2 (23 mA) */ | |
3745 | ||
3746 | /* write to io pad configuration register - output mode */ | |
244c0e06 | 3747 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_RX_CFG__A, pin_cfg_value, 0); |
9482354f | 3748 | if (rc != 0) { |
068e94ea MCC |
3749 | pr_err("error %d\n", rc); |
3750 | goto rw_error; | |
3751 | } | |
443f18d0 MCC |
3752 | |
3753 | /* use corresponding bit in io data output registar */ | |
244c0e06 | 3754 | rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, &value, 0); |
9482354f | 3755 | if (rc != 0) { |
068e94ea MCC |
3756 | pr_err("error %d\n", rc); |
3757 | goto rw_error; | |
3758 | } | |
63713517 | 3759 | if (!uio_data->value) |
443f18d0 | 3760 | value &= 0xBFFF; /* write zero to 14th bit - 2nd UIO */ |
63713517 | 3761 | else |
443f18d0 | 3762 | value |= 0x4000; /* write one to 14th bit - 2nd UIO */ |
63713517 | 3763 | |
443f18d0 | 3764 | /* write back to io data output register */ |
244c0e06 | 3765 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value, 0); |
9482354f | 3766 | if (rc != 0) { |
068e94ea MCC |
3767 | pr_err("error %d\n", rc); |
3768 | goto rw_error; | |
3769 | } | |
443f18d0 | 3770 | break; |
38b2df95 | 3771 | /*====================================================================*/ |
443f18d0 MCC |
3772 | case DRX_UIO3: |
3773 | /* DRX_UIO3: ASEL UIO-3 */ | |
259f380e | 3774 | if (!ext_attr->has_gpio) |
9482354f | 3775 | return -EIO; |
63713517 | 3776 | if (ext_attr->uio_gpio_mode != DRX_UIO_MODE_READWRITE) |
9482354f | 3777 | return -EIO; |
63713517 | 3778 | |
57afe2f0 | 3779 | pin_cfg_value = 0; |
443f18d0 | 3780 | /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */ |
57afe2f0 | 3781 | pin_cfg_value |= 0x0113; |
443f18d0 MCC |
3782 | /* io_pad_cfg_mode output mode is drive always */ |
3783 | /* io_pad_cfg_drive is set to power 2 (23 mA) */ | |
3784 | ||
3785 | /* write to io pad configuration register - output mode */ | |
244c0e06 | 3786 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_GPIO_CFG__A, pin_cfg_value, 0); |
9482354f | 3787 | if (rc != 0) { |
068e94ea MCC |
3788 | pr_err("error %d\n", rc); |
3789 | goto rw_error; | |
3790 | } | |
443f18d0 MCC |
3791 | |
3792 | /* use corresponding bit in io data output registar */ | |
244c0e06 | 3793 | rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_HI__A, &value, 0); |
9482354f | 3794 | if (rc != 0) { |
068e94ea MCC |
3795 | pr_err("error %d\n", rc); |
3796 | goto rw_error; | |
3797 | } | |
63713517 | 3798 | if (!uio_data->value) |
443f18d0 | 3799 | value &= 0xFFFB; /* write zero to 2nd bit - 3rd UIO */ |
63713517 | 3800 | else |
443f18d0 | 3801 | value |= 0x0004; /* write one to 2nd bit - 3rd UIO */ |
63713517 | 3802 | |
443f18d0 | 3803 | /* write back to io data output register */ |
244c0e06 | 3804 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_HI__A, value, 0); |
9482354f | 3805 | if (rc != 0) { |
068e94ea MCC |
3806 | pr_err("error %d\n", rc); |
3807 | goto rw_error; | |
3808 | } | |
443f18d0 | 3809 | break; |
38b2df95 | 3810 | /*=====================================================================*/ |
443f18d0 MCC |
3811 | case DRX_UIO4: |
3812 | /* DRX_UIO4: IRQN UIO-4 */ | |
259f380e | 3813 | if (!ext_attr->has_irqn) |
9482354f | 3814 | return -EIO; |
443f18d0 | 3815 | |
63713517 | 3816 | if (ext_attr->uio_irqn_mode != DRX_UIO_MODE_READWRITE) |
9482354f | 3817 | return -EIO; |
63713517 | 3818 | |
57afe2f0 | 3819 | pin_cfg_value = 0; |
443f18d0 | 3820 | /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */ |
57afe2f0 | 3821 | pin_cfg_value |= 0x0113; |
443f18d0 MCC |
3822 | /* io_pad_cfg_mode output mode is drive always */ |
3823 | /* io_pad_cfg_drive is set to power 2 (23 mA) */ | |
3824 | ||
3825 | /* write to io pad configuration register - output mode */ | |
244c0e06 | 3826 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_IRQN_CFG__A, pin_cfg_value, 0); |
9482354f | 3827 | if (rc != 0) { |
068e94ea MCC |
3828 | pr_err("error %d\n", rc); |
3829 | goto rw_error; | |
3830 | } | |
443f18d0 MCC |
3831 | |
3832 | /* use corresponding bit in io data output registar */ | |
244c0e06 | 3833 | rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, &value, 0); |
9482354f | 3834 | if (rc != 0) { |
068e94ea MCC |
3835 | pr_err("error %d\n", rc); |
3836 | goto rw_error; | |
3837 | } | |
63713517 | 3838 | if (uio_data->value == false) |
443f18d0 | 3839 | value &= 0xEFFF; /* write zero to 12th bit - 4th UIO */ |
63713517 | 3840 | else |
443f18d0 | 3841 | value |= 0x1000; /* write one to 12th bit - 4th UIO */ |
63713517 | 3842 | |
443f18d0 | 3843 | /* write back to io data output register */ |
244c0e06 | 3844 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value, 0); |
9482354f | 3845 | if (rc != 0) { |
068e94ea MCC |
3846 | pr_err("error %d\n", rc); |
3847 | goto rw_error; | |
3848 | } | |
443f18d0 | 3849 | break; |
38b2df95 | 3850 | /*=====================================================================*/ |
443f18d0 | 3851 | default: |
9482354f | 3852 | return -EINVAL; |
57afe2f0 | 3853 | } /* switch ( uio_data->uio ) */ |
38b2df95 | 3854 | |
443f18d0 | 3855 | /* Write magic word to disable pdr reg write */ |
244c0e06 | 3856 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0); |
9482354f | 3857 | if (rc != 0) { |
068e94ea MCC |
3858 | pr_err("error %d\n", rc); |
3859 | goto rw_error; | |
3860 | } | |
38b2df95 | 3861 | |
9482354f | 3862 | return 0; |
443f18d0 | 3863 | rw_error: |
30741871 | 3864 | return rc; |
38b2df95 DH |
3865 | } |
3866 | ||
38b2df95 DH |
3867 | /*---------------------------------------------------------------------------*/ |
3868 | /* UIO Configuration Functions - end */ | |
3869 | /*---------------------------------------------------------------------------*/ | |
3870 | ||
3871 | /*----------------------------------------------------------------------------*/ | |
3872 | /* I2C Bridge Functions - begin */ | |
3873 | /*----------------------------------------------------------------------------*/ | |
34eb9751 | 3874 | /* |
57afe2f0 | 3875 | * \fn int ctrl_i2c_bridge() |
38b2df95 DH |
3876 | * \brief Open or close the I2C switch to tuner. |
3877 | * \param demod Pointer to demodulator instance. | |
57afe2f0 | 3878 | * \param bridge_closed Pointer to bool indication if bridge is closed not. |
61263c75 | 3879 | * \return int. |
38b2df95 DH |
3880 | |
3881 | */ | |
61263c75 | 3882 | static int |
1bfc9e15 | 3883 | ctrl_i2c_bridge(struct drx_demod_instance *demod, bool *bridge_closed) |
38b2df95 | 3884 | { |
60d3603b | 3885 | struct drxj_hi_cmd hi_cmd; |
43a431e4 | 3886 | u16 result = 0; |
38b2df95 | 3887 | |
443f18d0 | 3888 | /* check arguments */ |
63713517 | 3889 | if (bridge_closed == NULL) |
9482354f | 3890 | return -EINVAL; |
38b2df95 | 3891 | |
57afe2f0 MCC |
3892 | hi_cmd.cmd = SIO_HI_RA_RAM_CMD_BRDCTRL; |
3893 | hi_cmd.param1 = SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY; | |
63713517 | 3894 | if (*bridge_closed) |
57afe2f0 | 3895 | hi_cmd.param2 = SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED; |
63713517 | 3896 | else |
57afe2f0 | 3897 | hi_cmd.param2 = SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN; |
38b2df95 | 3898 | |
57afe2f0 | 3899 | return hi_command(demod->my_i2c_dev_addr, &hi_cmd, &result); |
38b2df95 | 3900 | } |
443f18d0 | 3901 | |
38b2df95 DH |
3902 | /*----------------------------------------------------------------------------*/ |
3903 | /* I2C Bridge Functions - end */ | |
3904 | /*----------------------------------------------------------------------------*/ | |
3905 | ||
3906 | /*----------------------------------------------------------------------------*/ | |
3907 | /* Smart antenna Functions - begin */ | |
3908 | /*----------------------------------------------------------------------------*/ | |
34eb9751 | 3909 | /* |
57afe2f0 | 3910 | * \fn int smart_ant_init() |
38b2df95 | 3911 | * \brief Initialize Smart Antenna. |
1bfc9e15 | 3912 | * \param pointer to struct drx_demod_instance. |
61263c75 | 3913 | * \return int. |
38b2df95 DH |
3914 | * |
3915 | */ | |
1bfc9e15 | 3916 | static int smart_ant_init(struct drx_demod_instance *demod) |
38b2df95 | 3917 | { |
b3ce3a83 | 3918 | struct drxj_data *ext_attr = NULL; |
57afe2f0 | 3919 | struct i2c_device_addr *dev_addr = NULL; |
1bfc9e15 | 3920 | struct drxuio_cfg uio_cfg = { DRX_UIO1, DRX_UIO_MODE_FIRMWARE_SMA }; |
068e94ea MCC |
3921 | int rc; |
3922 | u16 data = 0; | |
443f18d0 | 3923 | |
57afe2f0 | 3924 | dev_addr = demod->my_i2c_dev_addr; |
b3ce3a83 | 3925 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
443f18d0 MCC |
3926 | |
3927 | /* Write magic word to enable pdr reg write */ | |
244c0e06 | 3928 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0); |
9482354f | 3929 | if (rc != 0) { |
068e94ea MCC |
3930 | pr_err("error %d\n", rc); |
3931 | goto rw_error; | |
3932 | } | |
443f18d0 | 3933 | /* init smart antenna */ |
244c0e06 | 3934 | rc = drxj_dap_read_reg16(dev_addr, SIO_SA_TX_COMMAND__A, &data, 0); |
9482354f | 3935 | if (rc != 0) { |
068e94ea MCC |
3936 | pr_err("error %d\n", rc); |
3937 | goto rw_error; | |
3938 | } | |
63713517 | 3939 | if (ext_attr->smart_ant_inverted) { |
244c0e06 | 3940 | rc = drxj_dap_write_reg16(dev_addr, SIO_SA_TX_COMMAND__A, (data | SIO_SA_TX_COMMAND_TX_INVERT__M) | SIO_SA_TX_COMMAND_TX_ENABLE__M, 0); |
9482354f | 3941 | if (rc != 0) { |
63713517 MCC |
3942 | pr_err("error %d\n", rc); |
3943 | goto rw_error; | |
068e94ea | 3944 | } |
63713517 | 3945 | } else { |
244c0e06 | 3946 | rc = drxj_dap_write_reg16(dev_addr, SIO_SA_TX_COMMAND__A, (data & (~SIO_SA_TX_COMMAND_TX_INVERT__M)) | SIO_SA_TX_COMMAND_TX_ENABLE__M, 0); |
9482354f | 3947 | if (rc != 0) { |
63713517 MCC |
3948 | pr_err("error %d\n", rc); |
3949 | goto rw_error; | |
068e94ea | 3950 | } |
63713517 | 3951 | } |
443f18d0 MCC |
3952 | |
3953 | /* config SMA_TX pin to smart antenna mode */ | |
068e94ea | 3954 | rc = ctrl_set_uio_cfg(demod, &uio_cfg); |
9482354f | 3955 | if (rc != 0) { |
068e94ea MCC |
3956 | pr_err("error %d\n", rc); |
3957 | goto rw_error; | |
3958 | } | |
244c0e06 | 3959 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, 0x13, 0); |
9482354f | 3960 | if (rc != 0) { |
068e94ea MCC |
3961 | pr_err("error %d\n", rc); |
3962 | goto rw_error; | |
3963 | } | |
244c0e06 | 3964 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_GPIO_FNC__A, 0x03, 0); |
9482354f | 3965 | if (rc != 0) { |
068e94ea MCC |
3966 | pr_err("error %d\n", rc); |
3967 | goto rw_error; | |
3968 | } | |
443f18d0 MCC |
3969 | |
3970 | /* Write magic word to disable pdr reg write */ | |
244c0e06 | 3971 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0); |
9482354f | 3972 | if (rc != 0) { |
068e94ea MCC |
3973 | pr_err("error %d\n", rc); |
3974 | goto rw_error; | |
3975 | } | |
443f18d0 | 3976 | |
9482354f | 3977 | return 0; |
38b2df95 | 3978 | rw_error: |
30741871 | 3979 | return rc; |
38b2df95 DH |
3980 | } |
3981 | ||
b3ce3a83 | 3982 | static int scu_command(struct i2c_device_addr *dev_addr, struct drxjscu_cmd *cmd) |
38b2df95 | 3983 | { |
068e94ea | 3984 | int rc; |
068e94ea | 3985 | u16 cur_cmd = 0; |
ceea5e2d | 3986 | unsigned long timeout; |
38b2df95 | 3987 | |
443f18d0 MCC |
3988 | /* Check param */ |
3989 | if (cmd == NULL) | |
9482354f | 3990 | return -EINVAL; |
38b2df95 | 3991 | |
443f18d0 | 3992 | /* Wait until SCU command interface is ready to receive command */ |
244c0e06 | 3993 | rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_COMMAND__A, &cur_cmd, 0); |
9482354f | 3994 | if (rc != 0) { |
068e94ea MCC |
3995 | pr_err("error %d\n", rc); |
3996 | goto rw_error; | |
3997 | } | |
63713517 | 3998 | if (cur_cmd != DRX_SCU_READY) |
9482354f | 3999 | return -EIO; |
38b2df95 | 4000 | |
57afe2f0 | 4001 | switch (cmd->parameter_len) { |
443f18d0 | 4002 | case 5: |
244c0e06 | 4003 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_4__A, *(cmd->parameter + 4), 0); |
9482354f | 4004 | if (rc != 0) { |
068e94ea MCC |
4005 | pr_err("error %d\n", rc); |
4006 | goto rw_error; | |
4007 | } /* fallthrough */ | |
443f18d0 | 4008 | case 4: |
244c0e06 | 4009 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_3__A, *(cmd->parameter + 3), 0); |
9482354f | 4010 | if (rc != 0) { |
068e94ea MCC |
4011 | pr_err("error %d\n", rc); |
4012 | goto rw_error; | |
4013 | } /* fallthrough */ | |
443f18d0 | 4014 | case 3: |
244c0e06 | 4015 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_2__A, *(cmd->parameter + 2), 0); |
9482354f | 4016 | if (rc != 0) { |
068e94ea MCC |
4017 | pr_err("error %d\n", rc); |
4018 | goto rw_error; | |
4019 | } /* fallthrough */ | |
443f18d0 | 4020 | case 2: |
244c0e06 | 4021 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_1__A, *(cmd->parameter + 1), 0); |
9482354f | 4022 | if (rc != 0) { |
068e94ea MCC |
4023 | pr_err("error %d\n", rc); |
4024 | goto rw_error; | |
4025 | } /* fallthrough */ | |
443f18d0 | 4026 | case 1: |
244c0e06 | 4027 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_0__A, *(cmd->parameter + 0), 0); |
9482354f | 4028 | if (rc != 0) { |
068e94ea MCC |
4029 | pr_err("error %d\n", rc); |
4030 | goto rw_error; | |
4031 | } /* fallthrough */ | |
443f18d0 MCC |
4032 | case 0: |
4033 | /* do nothing */ | |
4034 | break; | |
4035 | default: | |
4036 | /* this number of parameters is not supported */ | |
9482354f | 4037 | return -EIO; |
443f18d0 | 4038 | } |
244c0e06 | 4039 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_COMMAND__A, cmd->command, 0); |
9482354f | 4040 | if (rc != 0) { |
068e94ea MCC |
4041 | pr_err("error %d\n", rc); |
4042 | goto rw_error; | |
4043 | } | |
38b2df95 | 4044 | |
443f18d0 | 4045 | /* Wait until SCU has processed command */ |
ceea5e2d MCC |
4046 | timeout = jiffies + msecs_to_jiffies(DRXJ_MAX_WAITTIME); |
4047 | while (time_is_after_jiffies(timeout)) { | |
244c0e06 | 4048 | rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_COMMAND__A, &cur_cmd, 0); |
9482354f | 4049 | if (rc != 0) { |
068e94ea MCC |
4050 | pr_err("error %d\n", rc); |
4051 | goto rw_error; | |
4052 | } | |
ceea5e2d MCC |
4053 | if (cur_cmd == DRX_SCU_READY) |
4054 | break; | |
4055 | usleep_range(1000, 2000); | |
4056 | } | |
443f18d0 | 4057 | |
63713517 | 4058 | if (cur_cmd != DRX_SCU_READY) |
9482354f | 4059 | return -EIO; |
443f18d0 MCC |
4060 | |
4061 | /* read results */ | |
57afe2f0 | 4062 | if ((cmd->result_len > 0) && (cmd->result != NULL)) { |
43a431e4 | 4063 | s16 err; |
443f18d0 | 4064 | |
57afe2f0 | 4065 | switch (cmd->result_len) { |
443f18d0 | 4066 | case 4: |
244c0e06 | 4067 | rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_PARAM_3__A, cmd->result + 3, 0); |
9482354f | 4068 | if (rc != 0) { |
068e94ea MCC |
4069 | pr_err("error %d\n", rc); |
4070 | goto rw_error; | |
4071 | } /* fallthrough */ | |
443f18d0 | 4072 | case 3: |
244c0e06 | 4073 | rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_PARAM_2__A, cmd->result + 2, 0); |
9482354f | 4074 | if (rc != 0) { |
068e94ea MCC |
4075 | pr_err("error %d\n", rc); |
4076 | goto rw_error; | |
4077 | } /* fallthrough */ | |
443f18d0 | 4078 | case 2: |
244c0e06 | 4079 | rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_PARAM_1__A, cmd->result + 1, 0); |
9482354f | 4080 | if (rc != 0) { |
068e94ea MCC |
4081 | pr_err("error %d\n", rc); |
4082 | goto rw_error; | |
4083 | } /* fallthrough */ | |
443f18d0 | 4084 | case 1: |
244c0e06 | 4085 | rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_PARAM_0__A, cmd->result + 0, 0); |
9482354f | 4086 | if (rc != 0) { |
068e94ea MCC |
4087 | pr_err("error %d\n", rc); |
4088 | goto rw_error; | |
4089 | } /* fallthrough */ | |
443f18d0 MCC |
4090 | case 0: |
4091 | /* do nothing */ | |
4092 | break; | |
4093 | default: | |
4094 | /* this number of parameters is not supported */ | |
9482354f | 4095 | return -EIO; |
443f18d0 MCC |
4096 | } |
4097 | ||
4098 | /* Check if an error was reported by SCU */ | |
4099 | err = cmd->result[0]; | |
4100 | ||
4101 | /* check a few fixed error codes */ | |
43a431e4 MCC |
4102 | if ((err == (s16) SCU_RAM_PARAM_0_RESULT_UNKSTD) |
4103 | || (err == (s16) SCU_RAM_PARAM_0_RESULT_UNKCMD) | |
4104 | || (err == (s16) SCU_RAM_PARAM_0_RESULT_INVPAR) | |
4105 | || (err == (s16) SCU_RAM_PARAM_0_RESULT_SIZE) | |
443f18d0 | 4106 | ) { |
9482354f | 4107 | return -EINVAL; |
443f18d0 MCC |
4108 | } |
4109 | /* here it is assumed that negative means error, and positive no error */ | |
63713517 | 4110 | else if (err < 0) |
9482354f | 4111 | return -EIO; |
63713517 | 4112 | else |
9482354f | 4113 | return 0; |
443f18d0 MCC |
4114 | } |
4115 | ||
9482354f | 4116 | return 0; |
443f18d0 MCC |
4117 | |
4118 | rw_error: | |
30741871 | 4119 | return rc; |
38b2df95 | 4120 | } |
443f18d0 | 4121 | |
34eb9751 | 4122 | /* |
61263c75 | 4123 | * \fn int DRXJ_DAP_SCUAtomicReadWriteBlock() |
38b2df95 | 4124 | * \brief Basic access routine for SCU atomic read or write access |
57afe2f0 | 4125 | * \param dev_addr pointer to i2c dev address |
38b2df95 DH |
4126 | * \param addr destination/source address |
4127 | * \param datasize size of data buffer in bytes | |
4128 | * \param data pointer to data buffer | |
61263c75 | 4129 | * \return int |
9482354f MCC |
4130 | * \retval 0 Succes |
4131 | * \retval -EIO Timeout, I2C error, illegal bank | |
38b2df95 DH |
4132 | * |
4133 | */ | |
4134 | #define ADDR_AT_SCU_SPACE(x) ((x - 0x82E000) * 2) | |
4135 | static | |
1bfc9e15 | 4136 | 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 */ |
57afe2f0 | 4137 | u8 *data, bool read_flag) |
443f18d0 | 4138 | { |
b3ce3a83 | 4139 | struct drxjscu_cmd scu_cmd; |
068e94ea | 4140 | int rc; |
54c8cdd4 | 4141 | u16 set_param_parameters[18]; |
57afe2f0 | 4142 | u16 cmd_result[15]; |
443f18d0 MCC |
4143 | |
4144 | /* Parameter check */ | |
63713517 | 4145 | if (!data || !dev_addr || (datasize % 2) || ((datasize / 2) > 16)) |
9482354f | 4146 | return -EINVAL; |
38b2df95 | 4147 | |
57afe2f0 MCC |
4148 | set_param_parameters[1] = (u16) ADDR_AT_SCU_SPACE(addr); |
4149 | if (read_flag) { /* read */ | |
4150 | set_param_parameters[0] = ((~(0x0080)) & datasize); | |
4151 | scu_cmd.parameter_len = 2; | |
4152 | scu_cmd.result_len = datasize / 2 + 2; | |
443f18d0 MCC |
4153 | } else { |
4154 | int i = 0; | |
4155 | ||
57afe2f0 | 4156 | set_param_parameters[0] = 0x0080 | datasize; |
443f18d0 | 4157 | for (i = 0; i < (datasize / 2); i++) { |
57afe2f0 | 4158 | set_param_parameters[i + 2] = |
443f18d0 MCC |
4159 | (data[2 * i] | (data[(2 * i) + 1] << 8)); |
4160 | } | |
57afe2f0 MCC |
4161 | scu_cmd.parameter_len = datasize / 2 + 2; |
4162 | scu_cmd.result_len = 1; | |
443f18d0 MCC |
4163 | } |
4164 | ||
57afe2f0 | 4165 | scu_cmd.command = |
443f18d0 MCC |
4166 | SCU_RAM_COMMAND_STANDARD_TOP | |
4167 | SCU_RAM_COMMAND_CMD_AUX_SCU_ATOMIC_ACCESS; | |
57afe2f0 MCC |
4168 | scu_cmd.result = cmd_result; |
4169 | scu_cmd.parameter = set_param_parameters; | |
068e94ea | 4170 | rc = scu_command(dev_addr, &scu_cmd); |
9482354f | 4171 | if (rc != 0) { |
068e94ea MCC |
4172 | pr_err("error %d\n", rc); |
4173 | goto rw_error; | |
4174 | } | |
443f18d0 | 4175 | |
259f380e | 4176 | if (read_flag) { |
443f18d0 MCC |
4177 | int i = 0; |
4178 | /* read data from buffer */ | |
4179 | for (i = 0; i < (datasize / 2); i++) { | |
57afe2f0 MCC |
4180 | data[2 * i] = (u8) (scu_cmd.result[i + 2] & 0xFF); |
4181 | data[(2 * i) + 1] = (u8) (scu_cmd.result[i + 2] >> 8); | |
443f18d0 MCC |
4182 | } |
4183 | } | |
38b2df95 | 4184 | |
9482354f | 4185 | return 0; |
38b2df95 | 4186 | |
443f18d0 | 4187 | rw_error: |
30741871 | 4188 | return rc; |
38b2df95 DH |
4189 | |
4190 | } | |
4191 | ||
4192 | /*============================================================================*/ | |
4193 | ||
34eb9751 | 4194 | /* |
61263c75 | 4195 | * \fn int DRXJ_DAP_AtomicReadReg16() |
38b2df95 DH |
4196 | * \brief Atomic read of 16 bits words |
4197 | */ | |
4198 | static | |
57afe2f0 | 4199 | int drxj_dap_scu_atomic_read_reg16(struct i2c_device_addr *dev_addr, |
1bfc9e15 MCC |
4200 | u32 addr, |
4201 | u16 *data, u32 flags) | |
38b2df95 | 4202 | { |
4182438e | 4203 | u8 buf[2] = { 0 }; |
9482354f | 4204 | int rc = -EIO; |
43a431e4 | 4205 | u16 word = 0; |
38b2df95 | 4206 | |
63713517 | 4207 | if (!data) |
9482354f | 4208 | return -EINVAL; |
38b2df95 | 4209 | |
57afe2f0 | 4210 | rc = drxj_dap_scu_atomic_read_write_block(dev_addr, addr, 2, buf, true); |
b1d0a596 MCC |
4211 | if (rc < 0) |
4212 | return rc; | |
38b2df95 | 4213 | |
43a431e4 | 4214 | word = (u16) (buf[0] + (buf[1] << 8)); |
38b2df95 | 4215 | |
443f18d0 | 4216 | *data = word; |
38b2df95 | 4217 | |
443f18d0 | 4218 | return rc; |
38b2df95 | 4219 | } |
443f18d0 | 4220 | |
38b2df95 | 4221 | /*============================================================================*/ |
34eb9751 | 4222 | /* |
57afe2f0 | 4223 | * \fn int drxj_dap_scu_atomic_write_reg16() |
38b2df95 DH |
4224 | * \brief Atomic read of 16 bits words |
4225 | */ | |
4226 | static | |
57afe2f0 | 4227 | int drxj_dap_scu_atomic_write_reg16(struct i2c_device_addr *dev_addr, |
1bfc9e15 MCC |
4228 | u32 addr, |
4229 | u16 data, u32 flags) | |
38b2df95 | 4230 | { |
43a431e4 | 4231 | u8 buf[2]; |
9482354f | 4232 | int rc = -EIO; |
38b2df95 | 4233 | |
43a431e4 MCC |
4234 | buf[0] = (u8) (data & 0xff); |
4235 | buf[1] = (u8) ((data >> 8) & 0xff); | |
38b2df95 | 4236 | |
57afe2f0 | 4237 | rc = drxj_dap_scu_atomic_read_write_block(dev_addr, addr, 2, buf, false); |
38b2df95 | 4238 | |
443f18d0 | 4239 | return rc; |
38b2df95 DH |
4240 | } |
4241 | ||
38b2df95 | 4242 | /* -------------------------------------------------------------------------- */ |
34eb9751 | 4243 | /* |
38b2df95 DH |
4244 | * \brief Measure result of ADC synchronisation |
4245 | * \param demod demod instance | |
4246 | * \param count (returned) count | |
61263c75 | 4247 | * \return int. |
9482354f MCC |
4248 | * \retval 0 Success |
4249 | * \retval -EIO Failure: I2C error | |
38b2df95 DH |
4250 | * |
4251 | */ | |
1bfc9e15 | 4252 | static int adc_sync_measurement(struct drx_demod_instance *demod, u16 *count) |
38b2df95 | 4253 | { |
57afe2f0 | 4254 | struct i2c_device_addr *dev_addr = NULL; |
068e94ea MCC |
4255 | int rc; |
4256 | u16 data = 0; | |
38b2df95 | 4257 | |
57afe2f0 | 4258 | dev_addr = demod->my_i2c_dev_addr; |
38b2df95 | 4259 | |
443f18d0 | 4260 | /* Start measurement */ |
244c0e06 | 4261 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_COMM_EXEC__A, IQM_AF_COMM_EXEC_ACTIVE, 0); |
9482354f | 4262 | if (rc != 0) { |
068e94ea MCC |
4263 | pr_err("error %d\n", rc); |
4264 | goto rw_error; | |
4265 | } | |
244c0e06 | 4266 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_START_LOCK__A, 1, 0); |
9482354f | 4267 | if (rc != 0) { |
068e94ea MCC |
4268 | pr_err("error %d\n", rc); |
4269 | goto rw_error; | |
4270 | } | |
38b2df95 | 4271 | |
443f18d0 | 4272 | /* Wait at least 3*128*(1/sysclk) <<< 1 millisec */ |
d7b0631e | 4273 | msleep(1); |
38b2df95 | 4274 | |
443f18d0 | 4275 | *count = 0; |
244c0e06 | 4276 | rc = drxj_dap_read_reg16(dev_addr, IQM_AF_PHASE0__A, &data, 0); |
9482354f | 4277 | if (rc != 0) { |
068e94ea MCC |
4278 | pr_err("error %d\n", rc); |
4279 | goto rw_error; | |
4280 | } | |
63713517 | 4281 | if (data == 127) |
443f18d0 | 4282 | *count = *count + 1; |
244c0e06 | 4283 | rc = drxj_dap_read_reg16(dev_addr, IQM_AF_PHASE1__A, &data, 0); |
9482354f | 4284 | if (rc != 0) { |
068e94ea MCC |
4285 | pr_err("error %d\n", rc); |
4286 | goto rw_error; | |
4287 | } | |
63713517 | 4288 | if (data == 127) |
443f18d0 | 4289 | *count = *count + 1; |
244c0e06 | 4290 | rc = drxj_dap_read_reg16(dev_addr, IQM_AF_PHASE2__A, &data, 0); |
9482354f | 4291 | if (rc != 0) { |
068e94ea MCC |
4292 | pr_err("error %d\n", rc); |
4293 | goto rw_error; | |
4294 | } | |
63713517 | 4295 | if (data == 127) |
443f18d0 | 4296 | *count = *count + 1; |
38b2df95 | 4297 | |
9482354f | 4298 | return 0; |
38b2df95 | 4299 | rw_error: |
30741871 | 4300 | return rc; |
38b2df95 DH |
4301 | } |
4302 | ||
34eb9751 | 4303 | /* |
38b2df95 DH |
4304 | * \brief Synchronize analog and digital clock domains |
4305 | * \param demod demod instance | |
61263c75 | 4306 | * \return int. |
9482354f MCC |
4307 | * \retval 0 Success |
4308 | * \retval -EIO Failure: I2C error or failure to synchronize | |
38b2df95 DH |
4309 | * |
4310 | * An IQM reset will also reset the results of this synchronization. | |
4311 | * After an IQM reset this routine needs to be called again. | |
4312 | * | |
4313 | */ | |
4314 | ||
1bfc9e15 | 4315 | static int adc_synchronization(struct drx_demod_instance *demod) |
38b2df95 | 4316 | { |
57afe2f0 | 4317 | struct i2c_device_addr *dev_addr = NULL; |
068e94ea MCC |
4318 | int rc; |
4319 | u16 count = 0; | |
38b2df95 | 4320 | |
57afe2f0 | 4321 | dev_addr = demod->my_i2c_dev_addr; |
38b2df95 | 4322 | |
068e94ea | 4323 | rc = adc_sync_measurement(demod, &count); |
9482354f | 4324 | if (rc != 0) { |
068e94ea MCC |
4325 | pr_err("error %d\n", rc); |
4326 | goto rw_error; | |
4327 | } | |
38b2df95 | 4328 | |
443f18d0 | 4329 | if (count == 1) { |
69bb7ab6 | 4330 | /* Try sampling on a different edge */ |
57afe2f0 | 4331 | u16 clk_neg = 0; |
38b2df95 | 4332 | |
244c0e06 | 4333 | rc = drxj_dap_read_reg16(dev_addr, IQM_AF_CLKNEG__A, &clk_neg, 0); |
9482354f | 4334 | if (rc != 0) { |
068e94ea MCC |
4335 | pr_err("error %d\n", rc); |
4336 | goto rw_error; | |
4337 | } | |
38b2df95 | 4338 | |
57afe2f0 | 4339 | clk_neg ^= IQM_AF_CLKNEG_CLKNEGDATA__M; |
244c0e06 | 4340 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_CLKNEG__A, clk_neg, 0); |
9482354f | 4341 | if (rc != 0) { |
068e94ea MCC |
4342 | pr_err("error %d\n", rc); |
4343 | goto rw_error; | |
4344 | } | |
38b2df95 | 4345 | |
068e94ea | 4346 | rc = adc_sync_measurement(demod, &count); |
9482354f | 4347 | if (rc != 0) { |
068e94ea MCC |
4348 | pr_err("error %d\n", rc); |
4349 | goto rw_error; | |
4350 | } | |
443f18d0 | 4351 | } |
38b2df95 | 4352 | |
63713517 MCC |
4353 | /* TODO: implement fallback scenarios */ |
4354 | if (count < 2) | |
9482354f | 4355 | return -EIO; |
38b2df95 | 4356 | |
9482354f | 4357 | return 0; |
38b2df95 | 4358 | rw_error: |
30741871 | 4359 | return rc; |
38b2df95 DH |
4360 | } |
4361 | ||
38b2df95 DH |
4362 | /*============================================================================*/ |
4363 | /*== END AUXILIARY FUNCTIONS ==*/ | |
4364 | /*============================================================================*/ | |
4365 | ||
4366 | /*============================================================================*/ | |
4367 | /*============================================================================*/ | |
4368 | /*== 8VSB & QAM COMMON DATAPATH FUNCTIONS ==*/ | |
4369 | /*============================================================================*/ | |
4370 | /*============================================================================*/ | |
34eb9751 | 4371 | /* |
57afe2f0 | 4372 | * \fn int init_agc () |
38b2df95 DH |
4373 | * \brief Initialize AGC for all standards. |
4374 | * \param demod instance of demodulator. | |
4375 | * \param channel pointer to channel data. | |
61263c75 | 4376 | * \return int. |
38b2df95 | 4377 | */ |
1bfc9e15 | 4378 | static int init_agc(struct drx_demod_instance *demod) |
57afe2f0 MCC |
4379 | { |
4380 | struct i2c_device_addr *dev_addr = NULL; | |
1bfc9e15 | 4381 | struct drx_common_attr *common_attr = NULL; |
b3ce3a83 MCC |
4382 | struct drxj_data *ext_attr = NULL; |
4383 | struct drxj_cfg_agc *p_agc_rf_settings = NULL; | |
4384 | struct drxj_cfg_agc *p_agc_if_settings = NULL; | |
068e94ea | 4385 | int rc; |
57afe2f0 MCC |
4386 | u16 ingain_tgt_max = 0; |
4387 | u16 clp_dir_to = 0; | |
4388 | u16 sns_sum_max = 0; | |
4389 | u16 clp_sum_max = 0; | |
4390 | u16 sns_dir_to = 0; | |
4391 | u16 ki_innergain_min = 0; | |
4392 | u16 agc_ki = 0; | |
4393 | u16 ki_max = 0; | |
4394 | u16 if_iaccu_hi_tgt_min = 0; | |
43a431e4 | 4395 | u16 data = 0; |
e33f2193 | 4396 | u16 agc_ki_dgain = 0; |
57afe2f0 MCC |
4397 | u16 ki_min = 0; |
4398 | u16 clp_ctrl_mode = 0; | |
4399 | u16 agc_rf = 0; | |
4400 | u16 agc_if = 0; | |
068e94ea | 4401 | |
57afe2f0 | 4402 | dev_addr = demod->my_i2c_dev_addr; |
1bfc9e15 | 4403 | common_attr = (struct drx_common_attr *) demod->my_common_attr; |
b3ce3a83 | 4404 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
57afe2f0 MCC |
4405 | |
4406 | switch (ext_attr->standard) { | |
443f18d0 | 4407 | case DRX_STANDARD_8VSB: |
57afe2f0 MCC |
4408 | clp_sum_max = 1023; |
4409 | clp_dir_to = (u16) (-9); | |
4410 | sns_sum_max = 1023; | |
4411 | sns_dir_to = (u16) (-9); | |
4412 | ki_innergain_min = (u16) (-32768); | |
4413 | ki_max = 0x032C; | |
e33f2193 | 4414 | agc_ki_dgain = 0xC; |
57afe2f0 MCC |
4415 | if_iaccu_hi_tgt_min = 2047; |
4416 | ki_min = 0x0117; | |
4417 | ingain_tgt_max = 16383; | |
4418 | clp_ctrl_mode = 0; | |
244c0e06 | 4419 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff, 0); |
9482354f | 4420 | if (rc != 0) { |
068e94ea MCC |
4421 | pr_err("error %d\n", rc); |
4422 | goto rw_error; | |
4423 | } | |
244c0e06 | 4424 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0, 0); |
9482354f | 4425 | if (rc != 0) { |
068e94ea MCC |
4426 | pr_err("error %d\n", rc); |
4427 | goto rw_error; | |
4428 | } | |
244c0e06 | 4429 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_SUM__A, 0, 0); |
9482354f | 4430 | if (rc != 0) { |
068e94ea MCC |
4431 | pr_err("error %d\n", rc); |
4432 | goto rw_error; | |
4433 | } | |
244c0e06 | 4434 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_CYCCNT__A, 0, 0); |
9482354f | 4435 | if (rc != 0) { |
068e94ea MCC |
4436 | pr_err("error %d\n", rc); |
4437 | goto rw_error; | |
4438 | } | |
244c0e06 | 4439 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_DIR_WD__A, 0, 0); |
9482354f | 4440 | if (rc != 0) { |
068e94ea MCC |
4441 | pr_err("error %d\n", rc); |
4442 | goto rw_error; | |
4443 | } | |
244c0e06 | 4444 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_DIR_STP__A, 1, 0); |
9482354f | 4445 | if (rc != 0) { |
068e94ea MCC |
4446 | pr_err("error %d\n", rc); |
4447 | goto rw_error; | |
4448 | } | |
244c0e06 | 4449 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_SUM__A, 0, 0); |
9482354f | 4450 | if (rc != 0) { |
068e94ea MCC |
4451 | pr_err("error %d\n", rc); |
4452 | goto rw_error; | |
4453 | } | |
244c0e06 | 4454 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_CYCCNT__A, 0, 0); |
9482354f | 4455 | if (rc != 0) { |
068e94ea MCC |
4456 | pr_err("error %d\n", rc); |
4457 | goto rw_error; | |
4458 | } | |
244c0e06 | 4459 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_DIR_WD__A, 0, 0); |
9482354f | 4460 | if (rc != 0) { |
068e94ea MCC |
4461 | pr_err("error %d\n", rc); |
4462 | goto rw_error; | |
4463 | } | |
244c0e06 | 4464 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_DIR_STP__A, 1, 0); |
9482354f | 4465 | if (rc != 0) { |
068e94ea MCC |
4466 | pr_err("error %d\n", rc); |
4467 | goto rw_error; | |
4468 | } | |
244c0e06 | 4469 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN__A, 1024, 0); |
9482354f | 4470 | if (rc != 0) { |
068e94ea MCC |
4471 | pr_err("error %d\n", rc); |
4472 | goto rw_error; | |
4473 | } | |
244c0e06 | 4474 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_VSB_AGC_POW_TGT__A, 22600, 0); |
9482354f | 4475 | if (rc != 0) { |
068e94ea MCC |
4476 | pr_err("error %d\n", rc); |
4477 | goto rw_error; | |
4478 | } | |
244c0e06 | 4479 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, 13200, 0); |
9482354f | 4480 | if (rc != 0) { |
068e94ea MCC |
4481 | pr_err("error %d\n", rc); |
4482 | goto rw_error; | |
4483 | } | |
57afe2f0 MCC |
4484 | p_agc_if_settings = &(ext_attr->vsb_if_agc_cfg); |
4485 | p_agc_rf_settings = &(ext_attr->vsb_rf_agc_cfg); | |
443f18d0 | 4486 | break; |
38b2df95 | 4487 | #ifndef DRXJ_VSB_ONLY |
443f18d0 MCC |
4488 | case DRX_STANDARD_ITU_A: |
4489 | case DRX_STANDARD_ITU_C: | |
4490 | case DRX_STANDARD_ITU_B: | |
57afe2f0 MCC |
4491 | ingain_tgt_max = 5119; |
4492 | clp_sum_max = 1023; | |
4493 | clp_dir_to = (u16) (-5); | |
4494 | sns_sum_max = 127; | |
4495 | sns_dir_to = (u16) (-3); | |
4496 | ki_innergain_min = 0; | |
4497 | ki_max = 0x0657; | |
4498 | if_iaccu_hi_tgt_min = 2047; | |
e33f2193 | 4499 | agc_ki_dgain = 0x7; |
57afe2f0 MCC |
4500 | ki_min = 0x0117; |
4501 | clp_ctrl_mode = 0; | |
244c0e06 | 4502 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff, 0); |
9482354f | 4503 | if (rc != 0) { |
068e94ea MCC |
4504 | pr_err("error %d\n", rc); |
4505 | goto rw_error; | |
4506 | } | |
244c0e06 | 4507 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0, 0); |
9482354f | 4508 | if (rc != 0) { |
068e94ea MCC |
4509 | pr_err("error %d\n", rc); |
4510 | goto rw_error; | |
4511 | } | |
244c0e06 | 4512 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_SUM__A, 0, 0); |
9482354f | 4513 | if (rc != 0) { |
068e94ea MCC |
4514 | pr_err("error %d\n", rc); |
4515 | goto rw_error; | |
4516 | } | |
244c0e06 | 4517 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_CYCCNT__A, 0, 0); |
9482354f | 4518 | if (rc != 0) { |
068e94ea MCC |
4519 | pr_err("error %d\n", rc); |
4520 | goto rw_error; | |
4521 | } | |
244c0e06 | 4522 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_DIR_WD__A, 0, 0); |
9482354f | 4523 | if (rc != 0) { |
068e94ea MCC |
4524 | pr_err("error %d\n", rc); |
4525 | goto rw_error; | |
4526 | } | |
244c0e06 | 4527 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_DIR_STP__A, 1, 0); |
9482354f | 4528 | if (rc != 0) { |
068e94ea MCC |
4529 | pr_err("error %d\n", rc); |
4530 | goto rw_error; | |
4531 | } | |
244c0e06 | 4532 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_SUM__A, 0, 0); |
9482354f | 4533 | if (rc != 0) { |
068e94ea MCC |
4534 | pr_err("error %d\n", rc); |
4535 | goto rw_error; | |
4536 | } | |
244c0e06 | 4537 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_CYCCNT__A, 0, 0); |
9482354f | 4538 | if (rc != 0) { |
068e94ea MCC |
4539 | pr_err("error %d\n", rc); |
4540 | goto rw_error; | |
4541 | } | |
244c0e06 | 4542 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_DIR_WD__A, 0, 0); |
9482354f | 4543 | if (rc != 0) { |
068e94ea MCC |
4544 | pr_err("error %d\n", rc); |
4545 | goto rw_error; | |
4546 | } | |
244c0e06 | 4547 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_DIR_STP__A, 1, 0); |
9482354f | 4548 | if (rc != 0) { |
068e94ea MCC |
4549 | pr_err("error %d\n", rc); |
4550 | goto rw_error; | |
4551 | } | |
57afe2f0 MCC |
4552 | p_agc_if_settings = &(ext_attr->qam_if_agc_cfg); |
4553 | p_agc_rf_settings = &(ext_attr->qam_rf_agc_cfg); | |
244c0e06 | 4554 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, p_agc_if_settings->top, 0); |
9482354f | 4555 | if (rc != 0) { |
068e94ea MCC |
4556 | pr_err("error %d\n", rc); |
4557 | goto rw_error; | |
4558 | } | |
57afe2f0 | 4559 | |
244c0e06 | 4560 | rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_AGC_KI__A, &agc_ki, 0); |
9482354f | 4561 | if (rc != 0) { |
068e94ea MCC |
4562 | pr_err("error %d\n", rc); |
4563 | goto rw_error; | |
4564 | } | |
57afe2f0 | 4565 | agc_ki &= 0xf000; |
244c0e06 | 4566 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI__A, agc_ki, 0); |
9482354f | 4567 | if (rc != 0) { |
068e94ea MCC |
4568 | pr_err("error %d\n", rc); |
4569 | goto rw_error; | |
4570 | } | |
443f18d0 | 4571 | break; |
38b2df95 | 4572 | #endif |
443f18d0 | 4573 | default: |
9482354f | 4574 | return -EINVAL; |
443f18d0 | 4575 | } |
38b2df95 | 4576 | |
443f18d0 | 4577 | /* for new AGC interface */ |
244c0e06 | 4578 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN_TGT_MIN__A, p_agc_if_settings->top, 0); |
9482354f | 4579 | if (rc != 0) { |
068e94ea MCC |
4580 | pr_err("error %d\n", rc); |
4581 | goto rw_error; | |
4582 | } | |
244c0e06 | 4583 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN__A, p_agc_if_settings->top, 0); |
9482354f | 4584 | if (rc != 0) { |
068e94ea MCC |
4585 | pr_err("error %d\n", rc); |
4586 | goto rw_error; | |
4587 | } /* Gain fed from inner to outer AGC */ | |
244c0e06 | 4588 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingain_tgt_max, 0); |
9482354f | 4589 | if (rc != 0) { |
068e94ea MCC |
4590 | pr_err("error %d\n", rc); |
4591 | goto rw_error; | |
4592 | } | |
244c0e06 | 4593 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, if_iaccu_hi_tgt_min, 0); |
9482354f | 4594 | if (rc != 0) { |
068e94ea MCC |
4595 | pr_err("error %d\n", rc); |
4596 | goto rw_error; | |
4597 | } | |
244c0e06 | 4598 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_IF_IACCU_HI__A, 0, 0); |
9482354f | 4599 | if (rc != 0) { |
068e94ea MCC |
4600 | pr_err("error %d\n", rc); |
4601 | goto rw_error; | |
4602 | } /* set to p_agc_settings->top before */ | |
244c0e06 | 4603 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_IF_IACCU_LO__A, 0, 0); |
9482354f | 4604 | if (rc != 0) { |
068e94ea MCC |
4605 | pr_err("error %d\n", rc); |
4606 | goto rw_error; | |
4607 | } | |
244c0e06 | 4608 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_RF_IACCU_HI__A, 0, 0); |
9482354f | 4609 | if (rc != 0) { |
068e94ea MCC |
4610 | pr_err("error %d\n", rc); |
4611 | goto rw_error; | |
4612 | } | |
244c0e06 | 4613 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_RF_IACCU_LO__A, 0, 0); |
9482354f | 4614 | if (rc != 0) { |
068e94ea MCC |
4615 | pr_err("error %d\n", rc); |
4616 | goto rw_error; | |
4617 | } | |
244c0e06 | 4618 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_RF_MAX__A, 32767, 0); |
9482354f | 4619 | if (rc != 0) { |
068e94ea MCC |
4620 | pr_err("error %d\n", rc); |
4621 | goto rw_error; | |
4622 | } | |
244c0e06 | 4623 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_SUM_MAX__A, clp_sum_max, 0); |
9482354f | 4624 | if (rc != 0) { |
068e94ea MCC |
4625 | pr_err("error %d\n", rc); |
4626 | goto rw_error; | |
4627 | } | |
244c0e06 | 4628 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_SUM_MAX__A, sns_sum_max, 0); |
9482354f | 4629 | if (rc != 0) { |
068e94ea MCC |
4630 | pr_err("error %d\n", rc); |
4631 | goto rw_error; | |
4632 | } | |
244c0e06 | 4633 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, ki_innergain_min, 0); |
9482354f | 4634 | if (rc != 0) { |
068e94ea MCC |
4635 | pr_err("error %d\n", rc); |
4636 | goto rw_error; | |
4637 | } | |
244c0e06 | 4638 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_FAST_SNS_CTRL_DELAY__A, 50, 0); |
9482354f | 4639 | if (rc != 0) { |
068e94ea MCC |
4640 | pr_err("error %d\n", rc); |
4641 | goto rw_error; | |
4642 | } | |
244c0e06 | 4643 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_CYCLEN__A, 500, 0); |
9482354f | 4644 | if (rc != 0) { |
068e94ea MCC |
4645 | pr_err("error %d\n", rc); |
4646 | goto rw_error; | |
4647 | } | |
244c0e06 | 4648 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_CYCLEN__A, 500, 0); |
9482354f | 4649 | if (rc != 0) { |
068e94ea MCC |
4650 | pr_err("error %d\n", rc); |
4651 | goto rw_error; | |
4652 | } | |
244c0e06 | 4653 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MAXMINGAIN_TH__A, 20, 0); |
9482354f | 4654 | if (rc != 0) { |
068e94ea MCC |
4655 | pr_err("error %d\n", rc); |
4656 | goto rw_error; | |
4657 | } | |
244c0e06 | 4658 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MIN__A, ki_min, 0); |
9482354f | 4659 | if (rc != 0) { |
068e94ea MCC |
4660 | pr_err("error %d\n", rc); |
4661 | goto rw_error; | |
4662 | } | |
244c0e06 | 4663 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MAX__A, ki_max, 0); |
9482354f | 4664 | if (rc != 0) { |
068e94ea MCC |
4665 | pr_err("error %d\n", rc); |
4666 | goto rw_error; | |
4667 | } | |
244c0e06 | 4668 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_RED__A, 0, 0); |
9482354f | 4669 | if (rc != 0) { |
068e94ea MCC |
4670 | pr_err("error %d\n", rc); |
4671 | goto rw_error; | |
4672 | } | |
244c0e06 | 4673 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_SUM_MIN__A, 8, 0); |
9482354f | 4674 | if (rc != 0) { |
068e94ea MCC |
4675 | pr_err("error %d\n", rc); |
4676 | goto rw_error; | |
4677 | } | |
244c0e06 | 4678 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_CYCLEN__A, 500, 0); |
9482354f | 4679 | if (rc != 0) { |
068e94ea MCC |
4680 | pr_err("error %d\n", rc); |
4681 | goto rw_error; | |
4682 | } | |
244c0e06 | 4683 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_DIR_TO__A, clp_dir_to, 0); |
9482354f | 4684 | if (rc != 0) { |
068e94ea MCC |
4685 | pr_err("error %d\n", rc); |
4686 | goto rw_error; | |
4687 | } | |
244c0e06 | 4688 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_SUM_MIN__A, 8, 0); |
9482354f | 4689 | if (rc != 0) { |
068e94ea MCC |
4690 | pr_err("error %d\n", rc); |
4691 | goto rw_error; | |
4692 | } | |
244c0e06 | 4693 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_DIR_TO__A, sns_dir_to, 0); |
9482354f | 4694 | if (rc != 0) { |
068e94ea MCC |
4695 | pr_err("error %d\n", rc); |
4696 | goto rw_error; | |
4697 | } | |
244c0e06 | 4698 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, 50, 0); |
9482354f | 4699 | if (rc != 0) { |
068e94ea MCC |
4700 | pr_err("error %d\n", rc); |
4701 | goto rw_error; | |
4702 | } | |
244c0e06 | 4703 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_CTRL_MODE__A, clp_ctrl_mode, 0); |
9482354f | 4704 | if (rc != 0) { |
068e94ea MCC |
4705 | pr_err("error %d\n", rc); |
4706 | goto rw_error; | |
4707 | } | |
57afe2f0 MCC |
4708 | |
4709 | agc_rf = 0x800 + p_agc_rf_settings->cut_off_current; | |
63713517 | 4710 | if (common_attr->tuner_rf_agc_pol == true) |
57afe2f0 | 4711 | agc_rf = 0x87ff - agc_rf; |
57afe2f0 MCC |
4712 | |
4713 | agc_if = 0x800; | |
63713517 | 4714 | if (common_attr->tuner_if_agc_pol == true) |
57afe2f0 | 4715 | agc_rf = 0x87ff - agc_rf; |
57afe2f0 | 4716 | |
244c0e06 | 4717 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_AGC_RF__A, agc_rf, 0); |
9482354f | 4718 | if (rc != 0) { |
068e94ea MCC |
4719 | pr_err("error %d\n", rc); |
4720 | goto rw_error; | |
4721 | } | |
244c0e06 | 4722 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_AGC_IF__A, agc_if, 0); |
9482354f | 4723 | if (rc != 0) { |
068e94ea MCC |
4724 | pr_err("error %d\n", rc); |
4725 | goto rw_error; | |
4726 | } | |
38b2df95 | 4727 | |
443f18d0 | 4728 | /* Set/restore Ki DGAIN factor */ |
244c0e06 | 4729 | rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_AGC_KI__A, &data, 0); |
9482354f | 4730 | if (rc != 0) { |
068e94ea MCC |
4731 | pr_err("error %d\n", rc); |
4732 | goto rw_error; | |
4733 | } | |
443f18d0 | 4734 | data &= ~SCU_RAM_AGC_KI_DGAIN__M; |
e33f2193 | 4735 | data |= (agc_ki_dgain << SCU_RAM_AGC_KI_DGAIN__B); |
244c0e06 | 4736 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI__A, data, 0); |
9482354f | 4737 | if (rc != 0) { |
068e94ea MCC |
4738 | pr_err("error %d\n", rc); |
4739 | goto rw_error; | |
4740 | } | |
38b2df95 | 4741 | |
9482354f | 4742 | return 0; |
38b2df95 | 4743 | rw_error: |
30741871 | 4744 | return rc; |
38b2df95 DH |
4745 | } |
4746 | ||
34eb9751 | 4747 | /* |
57afe2f0 | 4748 | * \fn int set_frequency () |
38b2df95 DH |
4749 | * \brief Set frequency shift. |
4750 | * \param demod instance of demodulator. | |
4751 | * \param channel pointer to channel data. | |
57afe2f0 | 4752 | * \param tuner_freq_offset residual frequency from tuner. |
61263c75 | 4753 | * \return int. |
38b2df95 | 4754 | */ |
61263c75 | 4755 | static int |
1bfc9e15 MCC |
4756 | set_frequency(struct drx_demod_instance *demod, |
4757 | struct drx_channel *channel, s32 tuner_freq_offset) | |
57afe2f0 | 4758 | { |
4d7bb0eb | 4759 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; |
b3ce3a83 | 4760 | struct drxj_data *ext_attr = demod->my_ext_attr; |
068e94ea | 4761 | int rc; |
57afe2f0 MCC |
4762 | s32 sampling_frequency = 0; |
4763 | s32 frequency_shift = 0; | |
4764 | s32 if_freq_actual = 0; | |
4d7bb0eb | 4765 | s32 rf_freq_residual = -1 * tuner_freq_offset; |
57afe2f0 MCC |
4766 | s32 adc_freq = 0; |
4767 | s32 intermediate_freq = 0; | |
4768 | u32 iqm_fs_rate_ofs = 0; | |
57afe2f0 MCC |
4769 | bool adc_flip = true; |
4770 | bool select_pos_image = false; | |
4d7bb0eb MCC |
4771 | bool rf_mirror; |
4772 | bool tuner_mirror; | |
57afe2f0 MCC |
4773 | bool image_to_select = true; |
4774 | s32 fm_frequency_shift = 0; | |
4775 | ||
57afe2f0 MCC |
4776 | rf_mirror = (ext_attr->mirror == DRX_MIRROR_YES) ? true : false; |
4777 | tuner_mirror = demod->my_common_attr->mirror_freq_spect ? false : true; | |
443f18d0 MCC |
4778 | /* |
4779 | Program frequency shifter | |
4780 | No need to account for mirroring on RF | |
4781 | */ | |
57afe2f0 | 4782 | switch (ext_attr->standard) { |
06eeefe8 MCC |
4783 | case DRX_STANDARD_ITU_A: |
4784 | case DRX_STANDARD_ITU_C: | |
4785 | case DRX_STANDARD_PAL_SECAM_LP: | |
443f18d0 | 4786 | case DRX_STANDARD_8VSB: |
57afe2f0 | 4787 | select_pos_image = true; |
443f18d0 MCC |
4788 | break; |
4789 | case DRX_STANDARD_FM: | |
4790 | /* After IQM FS sound carrier must appear at 4 Mhz in spect. | |
4791 | Sound carrier is already 3Mhz above centre frequency due | |
4792 | to tuner setting so now add an extra shift of 1MHz... */ | |
57afe2f0 | 4793 | fm_frequency_shift = 1000; |
06eeefe8 MCC |
4794 | /*fall through */ |
4795 | case DRX_STANDARD_ITU_B: | |
4796 | case DRX_STANDARD_NTSC: | |
4797 | case DRX_STANDARD_PAL_SECAM_BG: | |
4798 | case DRX_STANDARD_PAL_SECAM_DK: | |
4799 | case DRX_STANDARD_PAL_SECAM_I: | |
443f18d0 | 4800 | case DRX_STANDARD_PAL_SECAM_L: |
57afe2f0 | 4801 | select_pos_image = false; |
443f18d0 MCC |
4802 | break; |
4803 | default: | |
9482354f | 4804 | return -EINVAL; |
443f18d0 | 4805 | } |
57afe2f0 MCC |
4806 | intermediate_freq = demod->my_common_attr->intermediate_freq; |
4807 | sampling_frequency = demod->my_common_attr->sys_clock_freq / 3; | |
63713517 MCC |
4808 | if (tuner_mirror) |
4809 | if_freq_actual = intermediate_freq + rf_freq_residual + fm_frequency_shift; | |
4810 | else | |
4811 | if_freq_actual = intermediate_freq - rf_freq_residual - fm_frequency_shift; | |
57afe2f0 | 4812 | if (if_freq_actual > sampling_frequency / 2) { |
443f18d0 | 4813 | /* adc mirrors */ |
57afe2f0 MCC |
4814 | adc_freq = sampling_frequency - if_freq_actual; |
4815 | adc_flip = true; | |
443f18d0 MCC |
4816 | } else { |
4817 | /* adc doesn't mirror */ | |
57afe2f0 MCC |
4818 | adc_freq = if_freq_actual; |
4819 | adc_flip = false; | |
443f18d0 MCC |
4820 | } |
4821 | ||
57afe2f0 MCC |
4822 | frequency_shift = adc_freq; |
4823 | image_to_select = | |
4824 | (bool) (rf_mirror ^ tuner_mirror ^ adc_flip ^ select_pos_image); | |
4825 | iqm_fs_rate_ofs = frac28(frequency_shift, sampling_frequency); | |
443f18d0 | 4826 | |
57afe2f0 MCC |
4827 | if (image_to_select) |
4828 | iqm_fs_rate_ofs = ~iqm_fs_rate_ofs + 1; | |
443f18d0 MCC |
4829 | |
4830 | /* Program frequency shifter with tuner offset compensation */ | |
57afe2f0 | 4831 | /* frequency_shift += tuner_freq_offset; TODO */ |
244c0e06 | 4832 | rc = drxdap_fasi_write_reg32(dev_addr, IQM_FS_RATE_OFS_LO__A, iqm_fs_rate_ofs, 0); |
9482354f | 4833 | if (rc != 0) { |
068e94ea MCC |
4834 | pr_err("error %d\n", rc); |
4835 | goto rw_error; | |
4836 | } | |
57afe2f0 MCC |
4837 | ext_attr->iqm_fs_rate_ofs = iqm_fs_rate_ofs; |
4838 | ext_attr->pos_image = (bool) (rf_mirror ^ tuner_mirror ^ select_pos_image); | |
443f18d0 | 4839 | |
9482354f | 4840 | return 0; |
38b2df95 | 4841 | rw_error: |
30741871 | 4842 | return rc; |
38b2df95 DH |
4843 | } |
4844 | ||
34eb9751 | 4845 | /* |
57afe2f0 | 4846 | * \fn int get_acc_pkt_err() |
38b2df95 DH |
4847 | * \brief Retrieve signal strength for VSB and QAM. |
4848 | * \param demod Pointer to demod instance | |
57afe2f0 | 4849 | * \param packet_err Pointer to packet error |
61263c75 | 4850 | * \return int. |
9482354f MCC |
4851 | * \retval 0 sig_strength contains valid data. |
4852 | * \retval -EINVAL sig_strength is NULL. | |
4853 | * \retval -EIO Erroneous data, sig_strength contains invalid data. | |
38b2df95 DH |
4854 | */ |
4855 | #ifdef DRXJ_SIGNAL_ACCUM_ERR | |
1bfc9e15 | 4856 | static int get_acc_pkt_err(struct drx_demod_instance *demod, u16 *packet_err) |
443f18d0 | 4857 | { |
068e94ea | 4858 | int rc; |
57afe2f0 MCC |
4859 | static u16 pkt_err; |
4860 | static u16 last_pkt_err; | |
43a431e4 | 4861 | u16 data = 0; |
b3ce3a83 | 4862 | struct drxj_data *ext_attr = NULL; |
57afe2f0 | 4863 | struct i2c_device_addr *dev_addr = NULL; |
443f18d0 | 4864 | |
b3ce3a83 | 4865 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
57afe2f0 | 4866 | dev_addr = demod->my_i2c_dev_addr; |
443f18d0 | 4867 | |
244c0e06 | 4868 | rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, &data, 0); |
9482354f | 4869 | if (rc != 0) { |
068e94ea MCC |
4870 | pr_err("error %d\n", rc); |
4871 | goto rw_error; | |
4872 | } | |
259f380e | 4873 | if (ext_attr->reset_pkt_err_acc) { |
57afe2f0 MCC |
4874 | last_pkt_err = data; |
4875 | pkt_err = 0; | |
4876 | ext_attr->reset_pkt_err_acc = false; | |
443f18d0 | 4877 | } |
38b2df95 | 4878 | |
57afe2f0 MCC |
4879 | if (data < last_pkt_err) { |
4880 | pkt_err += 0xffff - last_pkt_err; | |
4881 | pkt_err += data; | |
443f18d0 | 4882 | } else { |
57afe2f0 | 4883 | pkt_err += (data - last_pkt_err); |
443f18d0 | 4884 | } |
57afe2f0 MCC |
4885 | *packet_err = pkt_err; |
4886 | last_pkt_err = data; | |
38b2df95 | 4887 | |
9482354f | 4888 | return 0; |
38b2df95 | 4889 | rw_error: |
30741871 | 4890 | return rc; |
38b2df95 DH |
4891 | } |
4892 | #endif | |
4893 | ||
38b2df95 DH |
4894 | |
4895 | /*============================================================================*/ | |
4896 | ||
34eb9751 | 4897 | /* |
57afe2f0 | 4898 | * \fn int set_agc_rf () |
38b2df95 DH |
4899 | * \brief Configure RF AGC |
4900 | * \param demod instance of demodulator. | |
57afe2f0 | 4901 | * \param agc_settings AGC configuration structure |
61263c75 | 4902 | * \return int. |
38b2df95 | 4903 | */ |
61263c75 | 4904 | static int |
b3ce3a83 | 4905 | set_agc_rf(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings, bool atomic) |
38b2df95 | 4906 | { |
57afe2f0 | 4907 | struct i2c_device_addr *dev_addr = NULL; |
b3ce3a83 MCC |
4908 | struct drxj_data *ext_attr = NULL; |
4909 | struct drxj_cfg_agc *p_agc_settings = NULL; | |
1bfc9e15 | 4910 | struct drx_common_attr *common_attr = NULL; |
068e94ea | 4911 | int rc; |
57afe2f0 MCC |
4912 | drx_write_reg16func_t scu_wr16 = NULL; |
4913 | drx_read_reg16func_t scu_rr16 = NULL; | |
443f18d0 | 4914 | |
1bfc9e15 | 4915 | common_attr = (struct drx_common_attr *) demod->my_common_attr; |
57afe2f0 | 4916 | dev_addr = demod->my_i2c_dev_addr; |
b3ce3a83 | 4917 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
443f18d0 MCC |
4918 | |
4919 | if (atomic) { | |
57afe2f0 MCC |
4920 | scu_rr16 = drxj_dap_scu_atomic_read_reg16; |
4921 | scu_wr16 = drxj_dap_scu_atomic_write_reg16; | |
443f18d0 | 4922 | } else { |
244c0e06 MCC |
4923 | scu_rr16 = drxj_dap_read_reg16; |
4924 | scu_wr16 = drxj_dap_write_reg16; | |
443f18d0 MCC |
4925 | } |
4926 | ||
4927 | /* Configure AGC only if standard is currently active */ | |
57afe2f0 MCC |
4928 | if ((ext_attr->standard == agc_settings->standard) || |
4929 | (DRXJ_ISQAMSTD(ext_attr->standard) && | |
4930 | DRXJ_ISQAMSTD(agc_settings->standard)) || | |
4931 | (DRXJ_ISATVSTD(ext_attr->standard) && | |
4932 | DRXJ_ISATVSTD(agc_settings->standard))) { | |
43a431e4 | 4933 | u16 data = 0; |
443f18d0 | 4934 | |
57afe2f0 | 4935 | switch (agc_settings->ctrl_mode) { |
443f18d0 MCC |
4936 | case DRX_AGC_CTRL_AUTO: |
4937 | ||
4938 | /* Enable RF AGC DAC */ | |
244c0e06 | 4939 | rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0); |
9482354f | 4940 | if (rc != 0) { |
068e94ea MCC |
4941 | pr_err("error %d\n", rc); |
4942 | goto rw_error; | |
4943 | } | |
443f18d0 | 4944 | data |= IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE; |
244c0e06 | 4945 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0); |
9482354f | 4946 | if (rc != 0) { |
068e94ea MCC |
4947 | pr_err("error %d\n", rc); |
4948 | goto rw_error; | |
4949 | } | |
443f18d0 MCC |
4950 | |
4951 | /* Enable SCU RF AGC loop */ | |
068e94ea | 4952 | rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0); |
9482354f | 4953 | if (rc != 0) { |
068e94ea MCC |
4954 | pr_err("error %d\n", rc); |
4955 | goto rw_error; | |
4956 | } | |
443f18d0 | 4957 | data &= ~SCU_RAM_AGC_KI_RF__M; |
63713517 | 4958 | if (ext_attr->standard == DRX_STANDARD_8VSB) |
443f18d0 | 4959 | data |= (2 << SCU_RAM_AGC_KI_RF__B); |
63713517 | 4960 | else if (DRXJ_ISQAMSTD(ext_attr->standard)) |
443f18d0 | 4961 | data |= (5 << SCU_RAM_AGC_KI_RF__B); |
63713517 | 4962 | else |
443f18d0 | 4963 | data |= (4 << SCU_RAM_AGC_KI_RF__B); |
443f18d0 | 4964 | |
63713517 | 4965 | if (common_attr->tuner_rf_agc_pol) |
443f18d0 | 4966 | data |= SCU_RAM_AGC_KI_INV_RF_POL__M; |
63713517 | 4967 | else |
443f18d0 | 4968 | data &= ~SCU_RAM_AGC_KI_INV_RF_POL__M; |
068e94ea | 4969 | rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0); |
9482354f | 4970 | if (rc != 0) { |
068e94ea MCC |
4971 | pr_err("error %d\n", rc); |
4972 | goto rw_error; | |
4973 | } | |
443f18d0 MCC |
4974 | |
4975 | /* Set speed ( using complementary reduction value ) */ | |
068e94ea | 4976 | rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI_RED__A, &data, 0); |
9482354f | 4977 | if (rc != 0) { |
068e94ea MCC |
4978 | pr_err("error %d\n", rc); |
4979 | goto rw_error; | |
4980 | } | |
443f18d0 | 4981 | data &= ~SCU_RAM_AGC_KI_RED_RAGC_RED__M; |
63713517 | 4982 | 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); |
9482354f | 4983 | if (rc != 0) { |
068e94ea MCC |
4984 | pr_err("error %d\n", rc); |
4985 | goto rw_error; | |
4986 | } | |
443f18d0 | 4987 | |
57afe2f0 MCC |
4988 | if (agc_settings->standard == DRX_STANDARD_8VSB) |
4989 | p_agc_settings = &(ext_attr->vsb_if_agc_cfg); | |
4990 | else if (DRXJ_ISQAMSTD(agc_settings->standard)) | |
4991 | p_agc_settings = &(ext_attr->qam_if_agc_cfg); | |
4992 | else if (DRXJ_ISATVSTD(agc_settings->standard)) | |
4993 | p_agc_settings = &(ext_attr->atv_if_agc_cfg); | |
443f18d0 | 4994 | else |
9482354f | 4995 | return -EINVAL; |
443f18d0 MCC |
4996 | |
4997 | /* Set TOP, only if IF-AGC is in AUTO mode */ | |
57afe2f0 | 4998 | if (p_agc_settings->ctrl_mode == DRX_AGC_CTRL_AUTO) { |
068e94ea | 4999 | rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, agc_settings->top, 0); |
9482354f | 5000 | if (rc != 0) { |
068e94ea MCC |
5001 | pr_err("error %d\n", rc); |
5002 | goto rw_error; | |
5003 | } | |
5004 | rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, agc_settings->top, 0); | |
9482354f | 5005 | if (rc != 0) { |
068e94ea MCC |
5006 | pr_err("error %d\n", rc); |
5007 | goto rw_error; | |
5008 | } | |
443f18d0 MCC |
5009 | } |
5010 | ||
5011 | /* Cut-Off current */ | |
068e94ea | 5012 | rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_RF_IACCU_HI_CO__A, agc_settings->cut_off_current, 0); |
9482354f | 5013 | if (rc != 0) { |
068e94ea MCC |
5014 | pr_err("error %d\n", rc); |
5015 | goto rw_error; | |
5016 | } | |
443f18d0 MCC |
5017 | break; |
5018 | case DRX_AGC_CTRL_USER: | |
5019 | ||
5020 | /* Enable RF AGC DAC */ | |
244c0e06 | 5021 | rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0); |
9482354f | 5022 | if (rc != 0) { |
068e94ea MCC |
5023 | pr_err("error %d\n", rc); |
5024 | goto rw_error; | |
5025 | } | |
443f18d0 | 5026 | data |= IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE; |
244c0e06 | 5027 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0); |
9482354f | 5028 | if (rc != 0) { |
068e94ea MCC |
5029 | pr_err("error %d\n", rc); |
5030 | goto rw_error; | |
5031 | } | |
443f18d0 MCC |
5032 | |
5033 | /* Disable SCU RF AGC loop */ | |
068e94ea | 5034 | rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0); |
9482354f | 5035 | if (rc != 0) { |
068e94ea MCC |
5036 | pr_err("error %d\n", rc); |
5037 | goto rw_error; | |
5038 | } | |
443f18d0 | 5039 | data &= ~SCU_RAM_AGC_KI_RF__M; |
63713517 | 5040 | if (common_attr->tuner_rf_agc_pol) |
443f18d0 | 5041 | data |= SCU_RAM_AGC_KI_INV_RF_POL__M; |
63713517 | 5042 | else |
443f18d0 | 5043 | data &= ~SCU_RAM_AGC_KI_INV_RF_POL__M; |
068e94ea | 5044 | rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0); |
9482354f | 5045 | if (rc != 0) { |
068e94ea MCC |
5046 | pr_err("error %d\n", rc); |
5047 | goto rw_error; | |
5048 | } | |
443f18d0 MCC |
5049 | |
5050 | /* Write value to output pin */ | |
068e94ea | 5051 | rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_RF_IACCU_HI__A, agc_settings->output_level, 0); |
9482354f | 5052 | if (rc != 0) { |
068e94ea MCC |
5053 | pr_err("error %d\n", rc); |
5054 | goto rw_error; | |
5055 | } | |
443f18d0 MCC |
5056 | break; |
5057 | case DRX_AGC_CTRL_OFF: | |
5058 | ||
5059 | /* Disable RF AGC DAC */ | |
244c0e06 | 5060 | rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0); |
9482354f | 5061 | if (rc != 0) { |
068e94ea MCC |
5062 | pr_err("error %d\n", rc); |
5063 | goto rw_error; | |
5064 | } | |
443f18d0 | 5065 | data &= (~IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE); |
244c0e06 | 5066 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0); |
9482354f | 5067 | if (rc != 0) { |
068e94ea MCC |
5068 | pr_err("error %d\n", rc); |
5069 | goto rw_error; | |
5070 | } | |
443f18d0 MCC |
5071 | |
5072 | /* Disable SCU RF AGC loop */ | |
068e94ea | 5073 | rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0); |
9482354f | 5074 | if (rc != 0) { |
068e94ea MCC |
5075 | pr_err("error %d\n", rc); |
5076 | goto rw_error; | |
5077 | } | |
443f18d0 | 5078 | data &= ~SCU_RAM_AGC_KI_RF__M; |
068e94ea | 5079 | rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0); |
9482354f | 5080 | if (rc != 0) { |
068e94ea MCC |
5081 | pr_err("error %d\n", rc); |
5082 | goto rw_error; | |
5083 | } | |
443f18d0 MCC |
5084 | break; |
5085 | default: | |
9482354f | 5086 | return -EINVAL; |
57afe2f0 | 5087 | } /* switch ( agcsettings->ctrl_mode ) */ |
443f18d0 MCC |
5088 | } |
5089 | ||
5090 | /* Store rf agc settings */ | |
57afe2f0 | 5091 | switch (agc_settings->standard) { |
443f18d0 | 5092 | case DRX_STANDARD_8VSB: |
57afe2f0 | 5093 | ext_attr->vsb_rf_agc_cfg = *agc_settings; |
443f18d0 | 5094 | break; |
38b2df95 | 5095 | #ifndef DRXJ_VSB_ONLY |
443f18d0 MCC |
5096 | case DRX_STANDARD_ITU_A: |
5097 | case DRX_STANDARD_ITU_B: | |
5098 | case DRX_STANDARD_ITU_C: | |
57afe2f0 | 5099 | ext_attr->qam_rf_agc_cfg = *agc_settings; |
443f18d0 | 5100 | break; |
38b2df95 | 5101 | #endif |
443f18d0 | 5102 | default: |
9482354f | 5103 | return -EIO; |
443f18d0 | 5104 | } |
38b2df95 | 5105 | |
9482354f | 5106 | return 0; |
38b2df95 | 5107 | rw_error: |
30741871 | 5108 | return rc; |
38b2df95 DH |
5109 | } |
5110 | ||
34eb9751 | 5111 | /* |
57afe2f0 | 5112 | * \fn int set_agc_if () |
38b2df95 DH |
5113 | * \brief Configure If AGC |
5114 | * \param demod instance of demodulator. | |
57afe2f0 | 5115 | * \param agc_settings AGC configuration structure |
61263c75 | 5116 | * \return int. |
38b2df95 | 5117 | */ |
61263c75 | 5118 | static int |
b3ce3a83 | 5119 | set_agc_if(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings, bool atomic) |
38b2df95 | 5120 | { |
57afe2f0 | 5121 | struct i2c_device_addr *dev_addr = NULL; |
b3ce3a83 MCC |
5122 | struct drxj_data *ext_attr = NULL; |
5123 | struct drxj_cfg_agc *p_agc_settings = NULL; | |
1bfc9e15 | 5124 | struct drx_common_attr *common_attr = NULL; |
57afe2f0 MCC |
5125 | drx_write_reg16func_t scu_wr16 = NULL; |
5126 | drx_read_reg16func_t scu_rr16 = NULL; | |
068e94ea | 5127 | int rc; |
443f18d0 | 5128 | |
1bfc9e15 | 5129 | common_attr = (struct drx_common_attr *) demod->my_common_attr; |
57afe2f0 | 5130 | dev_addr = demod->my_i2c_dev_addr; |
b3ce3a83 | 5131 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
443f18d0 MCC |
5132 | |
5133 | if (atomic) { | |
57afe2f0 MCC |
5134 | scu_rr16 = drxj_dap_scu_atomic_read_reg16; |
5135 | scu_wr16 = drxj_dap_scu_atomic_write_reg16; | |
443f18d0 | 5136 | } else { |
244c0e06 MCC |
5137 | scu_rr16 = drxj_dap_read_reg16; |
5138 | scu_wr16 = drxj_dap_write_reg16; | |
443f18d0 MCC |
5139 | } |
5140 | ||
5141 | /* Configure AGC only if standard is currently active */ | |
57afe2f0 MCC |
5142 | if ((ext_attr->standard == agc_settings->standard) || |
5143 | (DRXJ_ISQAMSTD(ext_attr->standard) && | |
5144 | DRXJ_ISQAMSTD(agc_settings->standard)) || | |
5145 | (DRXJ_ISATVSTD(ext_attr->standard) && | |
5146 | DRXJ_ISATVSTD(agc_settings->standard))) { | |
43a431e4 | 5147 | u16 data = 0; |
443f18d0 | 5148 | |
57afe2f0 | 5149 | switch (agc_settings->ctrl_mode) { |
443f18d0 MCC |
5150 | case DRX_AGC_CTRL_AUTO: |
5151 | /* Enable IF AGC DAC */ | |
244c0e06 | 5152 | rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0); |
9482354f | 5153 | if (rc != 0) { |
068e94ea MCC |
5154 | pr_err("error %d\n", rc); |
5155 | goto rw_error; | |
5156 | } | |
443f18d0 | 5157 | data |= IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE; |
244c0e06 | 5158 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0); |
9482354f | 5159 | if (rc != 0) { |
068e94ea MCC |
5160 | pr_err("error %d\n", rc); |
5161 | goto rw_error; | |
5162 | } | |
443f18d0 MCC |
5163 | |
5164 | /* Enable SCU IF AGC loop */ | |
068e94ea | 5165 | rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0); |
9482354f | 5166 | if (rc != 0) { |
068e94ea MCC |
5167 | pr_err("error %d\n", rc); |
5168 | goto rw_error; | |
5169 | } | |
443f18d0 MCC |
5170 | data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M; |
5171 | data &= ~SCU_RAM_AGC_KI_IF__M; | |
63713517 | 5172 | if (ext_attr->standard == DRX_STANDARD_8VSB) |
443f18d0 | 5173 | data |= (3 << SCU_RAM_AGC_KI_IF__B); |
63713517 | 5174 | else if (DRXJ_ISQAMSTD(ext_attr->standard)) |
443f18d0 | 5175 | data |= (6 << SCU_RAM_AGC_KI_IF__B); |
63713517 | 5176 | else |
443f18d0 | 5177 | data |= (5 << SCU_RAM_AGC_KI_IF__B); |
443f18d0 | 5178 | |
63713517 | 5179 | if (common_attr->tuner_if_agc_pol) |
443f18d0 | 5180 | data |= SCU_RAM_AGC_KI_INV_IF_POL__M; |
63713517 | 5181 | else |
443f18d0 | 5182 | data &= ~SCU_RAM_AGC_KI_INV_IF_POL__M; |
068e94ea | 5183 | rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0); |
9482354f | 5184 | if (rc != 0) { |
068e94ea MCC |
5185 | pr_err("error %d\n", rc); |
5186 | goto rw_error; | |
5187 | } | |
443f18d0 MCC |
5188 | |
5189 | /* Set speed (using complementary reduction value) */ | |
068e94ea | 5190 | rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI_RED__A, &data, 0); |
9482354f | 5191 | if (rc != 0) { |
068e94ea MCC |
5192 | pr_err("error %d\n", rc); |
5193 | goto rw_error; | |
5194 | } | |
443f18d0 | 5195 | data &= ~SCU_RAM_AGC_KI_RED_IAGC_RED__M; |
068e94ea | 5196 | 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); |
9482354f | 5197 | if (rc != 0) { |
068e94ea MCC |
5198 | pr_err("error %d\n", rc); |
5199 | goto rw_error; | |
5200 | } | |
443f18d0 | 5201 | |
57afe2f0 MCC |
5202 | if (agc_settings->standard == DRX_STANDARD_8VSB) |
5203 | p_agc_settings = &(ext_attr->vsb_rf_agc_cfg); | |
5204 | else if (DRXJ_ISQAMSTD(agc_settings->standard)) | |
5205 | p_agc_settings = &(ext_attr->qam_rf_agc_cfg); | |
5206 | else if (DRXJ_ISATVSTD(agc_settings->standard)) | |
5207 | p_agc_settings = &(ext_attr->atv_rf_agc_cfg); | |
443f18d0 | 5208 | else |
9482354f | 5209 | return -EINVAL; |
443f18d0 MCC |
5210 | |
5211 | /* Restore TOP */ | |
57afe2f0 | 5212 | if (p_agc_settings->ctrl_mode == DRX_AGC_CTRL_AUTO) { |
068e94ea | 5213 | rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, p_agc_settings->top, 0); |
9482354f | 5214 | if (rc != 0) { |
068e94ea MCC |
5215 | pr_err("error %d\n", rc); |
5216 | goto rw_error; | |
5217 | } | |
5218 | rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, p_agc_settings->top, 0); | |
9482354f | 5219 | if (rc != 0) { |
068e94ea MCC |
5220 | pr_err("error %d\n", rc); |
5221 | goto rw_error; | |
5222 | } | |
443f18d0 | 5223 | } else { |
068e94ea | 5224 | rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, 0, 0); |
9482354f | 5225 | if (rc != 0) { |
068e94ea MCC |
5226 | pr_err("error %d\n", rc); |
5227 | goto rw_error; | |
5228 | } | |
5229 | rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, 0, 0); | |
9482354f | 5230 | if (rc != 0) { |
068e94ea MCC |
5231 | pr_err("error %d\n", rc); |
5232 | goto rw_error; | |
5233 | } | |
443f18d0 MCC |
5234 | } |
5235 | break; | |
5236 | ||
5237 | case DRX_AGC_CTRL_USER: | |
5238 | ||
5239 | /* Enable IF AGC DAC */ | |
244c0e06 | 5240 | rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0); |
9482354f | 5241 | if (rc != 0) { |
068e94ea MCC |
5242 | pr_err("error %d\n", rc); |
5243 | goto rw_error; | |
5244 | } | |
443f18d0 | 5245 | data |= IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE; |
244c0e06 | 5246 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0); |
9482354f | 5247 | if (rc != 0) { |
068e94ea MCC |
5248 | pr_err("error %d\n", rc); |
5249 | goto rw_error; | |
5250 | } | |
443f18d0 MCC |
5251 | |
5252 | /* Disable SCU IF AGC loop */ | |
068e94ea | 5253 | rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0); |
9482354f | 5254 | if (rc != 0) { |
068e94ea MCC |
5255 | pr_err("error %d\n", rc); |
5256 | goto rw_error; | |
5257 | } | |
443f18d0 MCC |
5258 | data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M; |
5259 | data |= SCU_RAM_AGC_KI_IF_AGC_DISABLE__M; | |
63713517 | 5260 | if (common_attr->tuner_if_agc_pol) |
443f18d0 | 5261 | data |= SCU_RAM_AGC_KI_INV_IF_POL__M; |
63713517 | 5262 | else |
443f18d0 | 5263 | data &= ~SCU_RAM_AGC_KI_INV_IF_POL__M; |
068e94ea | 5264 | rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0); |
9482354f | 5265 | if (rc != 0) { |
068e94ea MCC |
5266 | pr_err("error %d\n", rc); |
5267 | goto rw_error; | |
5268 | } | |
443f18d0 MCC |
5269 | |
5270 | /* Write value to output pin */ | |
068e94ea | 5271 | rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, agc_settings->output_level, 0); |
9482354f | 5272 | if (rc != 0) { |
068e94ea MCC |
5273 | pr_err("error %d\n", rc); |
5274 | goto rw_error; | |
5275 | } | |
443f18d0 MCC |
5276 | break; |
5277 | ||
5278 | case DRX_AGC_CTRL_OFF: | |
5279 | ||
5280 | /* Disable If AGC DAC */ | |
244c0e06 | 5281 | rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0); |
9482354f | 5282 | if (rc != 0) { |
068e94ea MCC |
5283 | pr_err("error %d\n", rc); |
5284 | goto rw_error; | |
5285 | } | |
443f18d0 | 5286 | data &= (~IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE); |
244c0e06 | 5287 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0); |
9482354f | 5288 | if (rc != 0) { |
068e94ea MCC |
5289 | pr_err("error %d\n", rc); |
5290 | goto rw_error; | |
5291 | } | |
443f18d0 MCC |
5292 | |
5293 | /* Disable SCU IF AGC loop */ | |
068e94ea | 5294 | rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0); |
9482354f | 5295 | if (rc != 0) { |
068e94ea MCC |
5296 | pr_err("error %d\n", rc); |
5297 | goto rw_error; | |
5298 | } | |
443f18d0 MCC |
5299 | data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M; |
5300 | data |= SCU_RAM_AGC_KI_IF_AGC_DISABLE__M; | |
068e94ea | 5301 | rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0); |
9482354f | 5302 | if (rc != 0) { |
068e94ea MCC |
5303 | pr_err("error %d\n", rc); |
5304 | goto rw_error; | |
5305 | } | |
443f18d0 MCC |
5306 | break; |
5307 | default: | |
9482354f | 5308 | return -EINVAL; |
57afe2f0 | 5309 | } /* switch ( agcsettings->ctrl_mode ) */ |
443f18d0 MCC |
5310 | |
5311 | /* always set the top to support configurations without if-loop */ | |
068e94ea | 5312 | rc = (*scu_wr16) (dev_addr, SCU_RAM_AGC_INGAIN_TGT_MIN__A, agc_settings->top, 0); |
9482354f | 5313 | if (rc != 0) { |
068e94ea MCC |
5314 | pr_err("error %d\n", rc); |
5315 | goto rw_error; | |
5316 | } | |
443f18d0 MCC |
5317 | } |
5318 | ||
5319 | /* Store if agc settings */ | |
57afe2f0 | 5320 | switch (agc_settings->standard) { |
443f18d0 | 5321 | case DRX_STANDARD_8VSB: |
57afe2f0 | 5322 | ext_attr->vsb_if_agc_cfg = *agc_settings; |
443f18d0 | 5323 | break; |
38b2df95 | 5324 | #ifndef DRXJ_VSB_ONLY |
443f18d0 MCC |
5325 | case DRX_STANDARD_ITU_A: |
5326 | case DRX_STANDARD_ITU_B: | |
5327 | case DRX_STANDARD_ITU_C: | |
57afe2f0 | 5328 | ext_attr->qam_if_agc_cfg = *agc_settings; |
443f18d0 | 5329 | break; |
38b2df95 | 5330 | #endif |
443f18d0 | 5331 | default: |
9482354f | 5332 | return -EIO; |
443f18d0 | 5333 | } |
38b2df95 | 5334 | |
9482354f | 5335 | return 0; |
38b2df95 | 5336 | rw_error: |
30741871 | 5337 | return rc; |
38b2df95 DH |
5338 | } |
5339 | ||
34eb9751 | 5340 | /* |
57afe2f0 | 5341 | * \fn int set_iqm_af () |
38b2df95 DH |
5342 | * \brief Configure IQM AF registers |
5343 | * \param demod instance of demodulator. | |
5344 | * \param active | |
61263c75 | 5345 | * \return int. |
38b2df95 | 5346 | */ |
1bfc9e15 | 5347 | static int set_iqm_af(struct drx_demod_instance *demod, bool active) |
38b2df95 | 5348 | { |
43a431e4 | 5349 | u16 data = 0; |
57afe2f0 | 5350 | struct i2c_device_addr *dev_addr = NULL; |
068e94ea | 5351 | int rc; |
38b2df95 | 5352 | |
57afe2f0 | 5353 | dev_addr = demod->my_i2c_dev_addr; |
38b2df95 | 5354 | |
443f18d0 | 5355 | /* Configure IQM */ |
244c0e06 | 5356 | rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0); |
9482354f | 5357 | if (rc != 0) { |
068e94ea MCC |
5358 | pr_err("error %d\n", rc); |
5359 | goto rw_error; | |
5360 | } | |
63713517 MCC |
5361 | if (!active) |
5362 | 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)); | |
5363 | else | |
5364 | 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); | |
244c0e06 | 5365 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0); |
9482354f | 5366 | if (rc != 0) { |
068e94ea MCC |
5367 | pr_err("error %d\n", rc); |
5368 | goto rw_error; | |
5369 | } | |
443f18d0 | 5370 | |
9482354f | 5371 | return 0; |
38b2df95 | 5372 | rw_error: |
30741871 | 5373 | return rc; |
38b2df95 DH |
5374 | } |
5375 | ||
5376 | /*============================================================================*/ | |
5377 | /*== END 8VSB & QAM COMMON DATAPATH FUNCTIONS ==*/ | |
5378 | /*============================================================================*/ | |
5379 | ||
5380 | /*============================================================================*/ | |
5381 | /*============================================================================*/ | |
5382 | /*== 8VSB DATAPATH FUNCTIONS ==*/ | |
5383 | /*============================================================================*/ | |
5384 | /*============================================================================*/ | |
5385 | ||
34eb9751 | 5386 | /* |
57afe2f0 | 5387 | * \fn int power_down_vsb () |
38b2df95 DH |
5388 | * \brief Powr down QAM related blocks. |
5389 | * \param demod instance of demodulator. | |
5390 | * \param channel pointer to channel data. | |
61263c75 | 5391 | * \return int. |
38b2df95 | 5392 | */ |
1bfc9e15 | 5393 | static int power_down_vsb(struct drx_demod_instance *demod, bool primary) |
443f18d0 | 5394 | { |
4d7bb0eb | 5395 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; |
b3ce3a83 | 5396 | struct drxjscu_cmd cmd_scu = { /* command */ 0, |
57afe2f0 MCC |
5397 | /* parameter_len */ 0, |
5398 | /* result_len */ 0, | |
443f18d0 MCC |
5399 | /* *parameter */ NULL, |
5400 | /* *result */ NULL | |
5401 | }; | |
1bfc9e15 | 5402 | struct drx_cfg_mpeg_output cfg_mpeg_output; |
068e94ea MCC |
5403 | int rc; |
5404 | u16 cmd_result = 0; | |
443f18d0 | 5405 | |
443f18d0 MCC |
5406 | /* |
5407 | STOP demodulator | |
5408 | reset of FEC and VSB HW | |
5409 | */ | |
57afe2f0 | 5410 | cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB | |
443f18d0 | 5411 | SCU_RAM_COMMAND_CMD_DEMOD_STOP; |
57afe2f0 MCC |
5412 | cmd_scu.parameter_len = 0; |
5413 | cmd_scu.result_len = 1; | |
5414 | cmd_scu.parameter = NULL; | |
5415 | cmd_scu.result = &cmd_result; | |
068e94ea | 5416 | rc = scu_command(dev_addr, &cmd_scu); |
9482354f | 5417 | if (rc != 0) { |
068e94ea MCC |
5418 | pr_err("error %d\n", rc); |
5419 | goto rw_error; | |
5420 | } | |
443f18d0 MCC |
5421 | |
5422 | /* stop all comm_exec */ | |
244c0e06 | 5423 | rc = drxj_dap_write_reg16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP, 0); |
9482354f | 5424 | if (rc != 0) { |
068e94ea MCC |
5425 | pr_err("error %d\n", rc); |
5426 | goto rw_error; | |
5427 | } | |
244c0e06 | 5428 | rc = drxj_dap_write_reg16(dev_addr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_STOP, 0); |
9482354f | 5429 | if (rc != 0) { |
068e94ea MCC |
5430 | pr_err("error %d\n", rc); |
5431 | goto rw_error; | |
5432 | } | |
259f380e | 5433 | if (primary) { |
244c0e06 | 5434 | rc = drxj_dap_write_reg16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP, 0); |
9482354f | 5435 | if (rc != 0) { |
068e94ea MCC |
5436 | pr_err("error %d\n", rc); |
5437 | goto rw_error; | |
5438 | } | |
5439 | rc = set_iqm_af(demod, false); | |
9482354f | 5440 | if (rc != 0) { |
068e94ea MCC |
5441 | pr_err("error %d\n", rc); |
5442 | goto rw_error; | |
5443 | } | |
443f18d0 | 5444 | } else { |
244c0e06 | 5445 | rc = drxj_dap_write_reg16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0); |
9482354f | 5446 | if (rc != 0) { |
068e94ea MCC |
5447 | pr_err("error %d\n", rc); |
5448 | goto rw_error; | |
5449 | } | |
244c0e06 | 5450 | rc = drxj_dap_write_reg16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0); |
9482354f | 5451 | if (rc != 0) { |
068e94ea MCC |
5452 | pr_err("error %d\n", rc); |
5453 | goto rw_error; | |
5454 | } | |
244c0e06 | 5455 | rc = drxj_dap_write_reg16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0); |
9482354f | 5456 | if (rc != 0) { |
068e94ea MCC |
5457 | pr_err("error %d\n", rc); |
5458 | goto rw_error; | |
5459 | } | |
244c0e06 | 5460 | rc = drxj_dap_write_reg16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0); |
9482354f | 5461 | if (rc != 0) { |
068e94ea MCC |
5462 | pr_err("error %d\n", rc); |
5463 | goto rw_error; | |
5464 | } | |
244c0e06 | 5465 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0); |
9482354f | 5466 | if (rc != 0) { |
068e94ea MCC |
5467 | pr_err("error %d\n", rc); |
5468 | goto rw_error; | |
5469 | } | |
443f18d0 | 5470 | } |
38b2df95 | 5471 | |
57afe2f0 | 5472 | cfg_mpeg_output.enable_mpeg_output = false; |
068e94ea | 5473 | rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output); |
9482354f | 5474 | if (rc != 0) { |
068e94ea MCC |
5475 | pr_err("error %d\n", rc); |
5476 | goto rw_error; | |
5477 | } | |
38b2df95 | 5478 | |
9482354f | 5479 | return 0; |
38b2df95 | 5480 | rw_error: |
30741871 | 5481 | return rc; |
38b2df95 | 5482 | } |
443f18d0 | 5483 | |
34eb9751 | 5484 | /* |
57afe2f0 | 5485 | * \fn int set_vsb_leak_n_gain () |
38b2df95 DH |
5486 | * \brief Set ATSC demod. |
5487 | * \param demod instance of demodulator. | |
61263c75 | 5488 | * \return int. |
38b2df95 | 5489 | */ |
1bfc9e15 | 5490 | static int set_vsb_leak_n_gain(struct drx_demod_instance *demod) |
443f18d0 | 5491 | { |
57afe2f0 | 5492 | struct i2c_device_addr *dev_addr = NULL; |
068e94ea | 5493 | int rc; |
443f18d0 | 5494 | |
679cfbb1 | 5495 | static const u8 vsb_ffe_leak_gain_ram0[] = { |
443f18d0 MCC |
5496 | DRXJ_16TO8(0x8), /* FFETRAINLKRATIO1 */ |
5497 | DRXJ_16TO8(0x8), /* FFETRAINLKRATIO2 */ | |
5498 | DRXJ_16TO8(0x8), /* FFETRAINLKRATIO3 */ | |
5499 | DRXJ_16TO8(0xf), /* FFETRAINLKRATIO4 */ | |
5500 | DRXJ_16TO8(0xf), /* FFETRAINLKRATIO5 */ | |
5501 | DRXJ_16TO8(0xf), /* FFETRAINLKRATIO6 */ | |
5502 | DRXJ_16TO8(0xf), /* FFETRAINLKRATIO7 */ | |
5503 | DRXJ_16TO8(0xf), /* FFETRAINLKRATIO8 */ | |
5504 | DRXJ_16TO8(0xf), /* FFETRAINLKRATIO9 */ | |
5505 | DRXJ_16TO8(0x8), /* FFETRAINLKRATIO10 */ | |
5506 | DRXJ_16TO8(0x8), /* FFETRAINLKRATIO11 */ | |
5507 | DRXJ_16TO8(0x8), /* FFETRAINLKRATIO12 */ | |
5508 | DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO1 */ | |
5509 | DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO2 */ | |
5510 | DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO3 */ | |
5511 | DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO4 */ | |
5512 | DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO5 */ | |
5513 | DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO6 */ | |
5514 | DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO7 */ | |
5515 | DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO8 */ | |
5516 | DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO9 */ | |
5517 | DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO10 */ | |
5518 | DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO11 */ | |
5519 | DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO12 */ | |
5520 | DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO1 */ | |
5521 | DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO2 */ | |
5522 | DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO3 */ | |
5523 | DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO4 */ | |
5524 | DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO5 */ | |
5525 | DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO6 */ | |
5526 | DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO7 */ | |
5527 | DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO8 */ | |
5528 | DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO9 */ | |
5529 | DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO10 */ | |
5530 | DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO11 */ | |
5531 | DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO12 */ | |
5532 | DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO1 */ | |
5533 | DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO2 */ | |
5534 | DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO3 */ | |
5535 | DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO4 */ | |
5536 | DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO5 */ | |
5537 | DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO6 */ | |
5538 | DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO7 */ | |
5539 | DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO8 */ | |
5540 | DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO9 */ | |
5541 | DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO10 */ | |
5542 | DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO11 */ | |
5543 | DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO12 */ | |
5544 | DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO1 */ | |
5545 | DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO2 */ | |
5546 | DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO3 */ | |
5547 | DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO4 */ | |
5548 | DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO5 */ | |
5549 | DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO6 */ | |
5550 | DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO7 */ | |
5551 | DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO8 */ | |
5552 | DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO9 */ | |
5553 | DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO10 */ | |
5554 | DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO11 */ | |
5555 | DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO12 */ | |
5556 | DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO1 */ | |
5557 | DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO2 */ | |
5558 | DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO3 */ | |
5559 | DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO4 */ | |
5560 | DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO5 */ | |
5561 | DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO6 */ | |
5562 | DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO7 */ | |
5563 | DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO8 */ | |
5564 | DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO9 */ | |
5565 | DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO10 */ | |
5566 | DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO11 */ | |
5567 | DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO12 */ | |
5568 | DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO1 */ | |
5569 | DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO2 */ | |
5570 | DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO3 */ | |
5571 | DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO4 */ | |
5572 | DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO5 */ | |
5573 | DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO6 */ | |
5574 | DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO7 */ | |
5575 | DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO8 */ | |
5576 | DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO9 */ | |
5577 | DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO10 */ | |
5578 | DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO11 */ | |
5579 | DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO12 */ | |
5580 | DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO1 */ | |
5581 | DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO2 */ | |
5582 | DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO3 */ | |
5583 | DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO4 */ | |
5584 | DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO5 */ | |
5585 | DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO6 */ | |
5586 | DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO7 */ | |
5587 | DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO8 */ | |
5588 | DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO9 */ | |
5589 | DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO10 */ | |
5590 | DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO11 */ | |
5591 | DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO12 */ | |
5592 | DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO1 */ | |
5593 | DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO2 */ | |
5594 | DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO3 */ | |
5595 | DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO4 */ | |
5596 | DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO5 */ | |
5597 | DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO6 */ | |
5598 | DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO7 */ | |
5599 | DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO8 */ | |
5600 | DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO9 */ | |
5601 | DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO10 */ | |
5602 | DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO11 */ | |
5603 | DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO12 */ | |
5604 | DRXJ_16TO8(0x2020), /* FIRTRAINGAIN1 */ | |
5605 | DRXJ_16TO8(0x2020), /* FIRTRAINGAIN2 */ | |
5606 | DRXJ_16TO8(0x2020), /* FIRTRAINGAIN3 */ | |
5607 | DRXJ_16TO8(0x4040), /* FIRTRAINGAIN4 */ | |
5608 | DRXJ_16TO8(0x4040), /* FIRTRAINGAIN5 */ | |
5609 | DRXJ_16TO8(0x4040), /* FIRTRAINGAIN6 */ | |
5610 | DRXJ_16TO8(0x4040), /* FIRTRAINGAIN7 */ | |
5611 | DRXJ_16TO8(0x4040), /* FIRTRAINGAIN8 */ | |
5612 | DRXJ_16TO8(0x4040), /* FIRTRAINGAIN9 */ | |
5613 | DRXJ_16TO8(0x2020), /* FIRTRAINGAIN10 */ | |
5614 | DRXJ_16TO8(0x2020), /* FIRTRAINGAIN11 */ | |
5615 | DRXJ_16TO8(0x2020), /* FIRTRAINGAIN12 */ | |
5616 | DRXJ_16TO8(0x0808), /* FIRRCA1GAIN1 */ | |
5617 | DRXJ_16TO8(0x0808), /* FIRRCA1GAIN2 */ | |
5618 | DRXJ_16TO8(0x0808), /* FIRRCA1GAIN3 */ | |
5619 | DRXJ_16TO8(0x1010), /* FIRRCA1GAIN4 */ | |
5620 | DRXJ_16TO8(0x1010), /* FIRRCA1GAIN5 */ | |
5621 | DRXJ_16TO8(0x1010), /* FIRRCA1GAIN6 */ | |
5622 | DRXJ_16TO8(0x1010), /* FIRRCA1GAIN7 */ | |
5623 | DRXJ_16TO8(0x1010) /* FIRRCA1GAIN8 */ | |
5624 | }; | |
5625 | ||
679cfbb1 | 5626 | static const u8 vsb_ffe_leak_gain_ram1[] = { |
443f18d0 MCC |
5627 | DRXJ_16TO8(0x1010), /* FIRRCA1GAIN9 */ |
5628 | DRXJ_16TO8(0x0808), /* FIRRCA1GAIN10 */ | |
5629 | DRXJ_16TO8(0x0808), /* FIRRCA1GAIN11 */ | |
5630 | DRXJ_16TO8(0x0808), /* FIRRCA1GAIN12 */ | |
5631 | DRXJ_16TO8(0x0808), /* FIRRCA2GAIN1 */ | |
5632 | DRXJ_16TO8(0x0808), /* FIRRCA2GAIN2 */ | |
5633 | DRXJ_16TO8(0x0808), /* FIRRCA2GAIN3 */ | |
5634 | DRXJ_16TO8(0x1010), /* FIRRCA2GAIN4 */ | |
5635 | DRXJ_16TO8(0x1010), /* FIRRCA2GAIN5 */ | |
5636 | DRXJ_16TO8(0x1010), /* FIRRCA2GAIN6 */ | |
5637 | DRXJ_16TO8(0x1010), /* FIRRCA2GAIN7 */ | |
5638 | DRXJ_16TO8(0x1010), /* FIRRCA2GAIN8 */ | |
5639 | DRXJ_16TO8(0x1010), /* FIRRCA2GAIN9 */ | |
5640 | DRXJ_16TO8(0x0808), /* FIRRCA2GAIN10 */ | |
5641 | DRXJ_16TO8(0x0808), /* FIRRCA2GAIN11 */ | |
5642 | DRXJ_16TO8(0x0808), /* FIRRCA2GAIN12 */ | |
5643 | DRXJ_16TO8(0x0303), /* FIRDDM1GAIN1 */ | |
5644 | DRXJ_16TO8(0x0303), /* FIRDDM1GAIN2 */ | |
5645 | DRXJ_16TO8(0x0303), /* FIRDDM1GAIN3 */ | |
5646 | DRXJ_16TO8(0x0606), /* FIRDDM1GAIN4 */ | |
5647 | DRXJ_16TO8(0x0606), /* FIRDDM1GAIN5 */ | |
5648 | DRXJ_16TO8(0x0606), /* FIRDDM1GAIN6 */ | |
5649 | DRXJ_16TO8(0x0606), /* FIRDDM1GAIN7 */ | |
5650 | DRXJ_16TO8(0x0606), /* FIRDDM1GAIN8 */ | |
5651 | DRXJ_16TO8(0x0606), /* FIRDDM1GAIN9 */ | |
5652 | DRXJ_16TO8(0x0303), /* FIRDDM1GAIN10 */ | |
5653 | DRXJ_16TO8(0x0303), /* FIRDDM1GAIN11 */ | |
5654 | DRXJ_16TO8(0x0303), /* FIRDDM1GAIN12 */ | |
5655 | DRXJ_16TO8(0x0303), /* FIRDDM2GAIN1 */ | |
5656 | DRXJ_16TO8(0x0303), /* FIRDDM2GAIN2 */ | |
5657 | DRXJ_16TO8(0x0303), /* FIRDDM2GAIN3 */ | |
5658 | DRXJ_16TO8(0x0505), /* FIRDDM2GAIN4 */ | |
5659 | DRXJ_16TO8(0x0505), /* FIRDDM2GAIN5 */ | |
5660 | DRXJ_16TO8(0x0505), /* FIRDDM2GAIN6 */ | |
5661 | DRXJ_16TO8(0x0505), /* FIRDDM2GAIN7 */ | |
5662 | DRXJ_16TO8(0x0505), /* FIRDDM2GAIN8 */ | |
5663 | DRXJ_16TO8(0x0505), /* FIRDDM2GAIN9 */ | |
5664 | DRXJ_16TO8(0x0303), /* FIRDDM2GAIN10 */ | |
5665 | DRXJ_16TO8(0x0303), /* FIRDDM2GAIN11 */ | |
5666 | DRXJ_16TO8(0x0303), /* FIRDDM2GAIN12 */ | |
5667 | DRXJ_16TO8(0x001f), /* DFETRAINLKRATIO */ | |
5668 | DRXJ_16TO8(0x01ff), /* DFERCA1TRAINLKRATIO */ | |
5669 | DRXJ_16TO8(0x01ff), /* DFERCA1DATALKRATIO */ | |
5670 | DRXJ_16TO8(0x004f), /* DFERCA2TRAINLKRATIO */ | |
5671 | DRXJ_16TO8(0x004f), /* DFERCA2DATALKRATIO */ | |
5672 | DRXJ_16TO8(0x01ff), /* DFEDDM1TRAINLKRATIO */ | |
5673 | DRXJ_16TO8(0x01ff), /* DFEDDM1DATALKRATIO */ | |
5674 | DRXJ_16TO8(0x0352), /* DFEDDM2TRAINLKRATIO */ | |
5675 | DRXJ_16TO8(0x0352), /* DFEDDM2DATALKRATIO */ | |
5676 | DRXJ_16TO8(0x0000), /* DFETRAINGAIN */ | |
5677 | DRXJ_16TO8(0x2020), /* DFERCA1GAIN */ | |
5678 | DRXJ_16TO8(0x1010), /* DFERCA2GAIN */ | |
5679 | DRXJ_16TO8(0x1818), /* DFEDDM1GAIN */ | |
5680 | DRXJ_16TO8(0x1212) /* DFEDDM2GAIN */ | |
5681 | }; | |
5682 | ||
57afe2f0 | 5683 | dev_addr = demod->my_i2c_dev_addr; |
244c0e06 | 5684 | rc = drxdap_fasi_write_block(dev_addr, VSB_SYSCTRL_RAM0_FFETRAINLKRATIO1__A, sizeof(vsb_ffe_leak_gain_ram0), ((u8 *)vsb_ffe_leak_gain_ram0), 0); |
9482354f | 5685 | if (rc != 0) { |
068e94ea MCC |
5686 | pr_err("error %d\n", rc); |
5687 | goto rw_error; | |
5688 | } | |
244c0e06 | 5689 | rc = drxdap_fasi_write_block(dev_addr, VSB_SYSCTRL_RAM1_FIRRCA1GAIN9__A, sizeof(vsb_ffe_leak_gain_ram1), ((u8 *)vsb_ffe_leak_gain_ram1), 0); |
9482354f | 5690 | if (rc != 0) { |
068e94ea MCC |
5691 | pr_err("error %d\n", rc); |
5692 | goto rw_error; | |
5693 | } | |
443f18d0 | 5694 | |
9482354f | 5695 | return 0; |
38b2df95 | 5696 | rw_error: |
30741871 | 5697 | return rc; |
38b2df95 DH |
5698 | } |
5699 | ||
34eb9751 | 5700 | /* |
57afe2f0 | 5701 | * \fn int set_vsb() |
38b2df95 DH |
5702 | * \brief Set 8VSB demod. |
5703 | * \param demod instance of demodulator. | |
61263c75 | 5704 | * \return int. |
38b2df95 DH |
5705 | * |
5706 | */ | |
1bfc9e15 | 5707 | static int set_vsb(struct drx_demod_instance *demod) |
443f18d0 | 5708 | { |
57afe2f0 | 5709 | struct i2c_device_addr *dev_addr = NULL; |
068e94ea | 5710 | int rc; |
1bfc9e15 | 5711 | struct drx_common_attr *common_attr = NULL; |
b3ce3a83 MCC |
5712 | struct drxjscu_cmd cmd_scu; |
5713 | struct drxj_data *ext_attr = NULL; | |
068e94ea MCC |
5714 | u16 cmd_result = 0; |
5715 | u16 cmd_param = 0; | |
679cfbb1 | 5716 | static const u8 vsb_taps_re[] = { |
443f18d0 MCC |
5717 | DRXJ_16TO8(-2), /* re0 */ |
5718 | DRXJ_16TO8(4), /* re1 */ | |
5719 | DRXJ_16TO8(1), /* re2 */ | |
5720 | DRXJ_16TO8(-4), /* re3 */ | |
5721 | DRXJ_16TO8(1), /* re4 */ | |
5722 | DRXJ_16TO8(4), /* re5 */ | |
5723 | DRXJ_16TO8(-3), /* re6 */ | |
5724 | DRXJ_16TO8(-3), /* re7 */ | |
5725 | DRXJ_16TO8(6), /* re8 */ | |
5726 | DRXJ_16TO8(1), /* re9 */ | |
5727 | DRXJ_16TO8(-9), /* re10 */ | |
5728 | DRXJ_16TO8(3), /* re11 */ | |
5729 | DRXJ_16TO8(12), /* re12 */ | |
5730 | DRXJ_16TO8(-9), /* re13 */ | |
5731 | DRXJ_16TO8(-15), /* re14 */ | |
5732 | DRXJ_16TO8(17), /* re15 */ | |
5733 | DRXJ_16TO8(19), /* re16 */ | |
5734 | DRXJ_16TO8(-29), /* re17 */ | |
5735 | DRXJ_16TO8(-22), /* re18 */ | |
5736 | DRXJ_16TO8(45), /* re19 */ | |
5737 | DRXJ_16TO8(25), /* re20 */ | |
5738 | DRXJ_16TO8(-70), /* re21 */ | |
5739 | DRXJ_16TO8(-28), /* re22 */ | |
5740 | DRXJ_16TO8(111), /* re23 */ | |
5741 | DRXJ_16TO8(30), /* re24 */ | |
5742 | DRXJ_16TO8(-201), /* re25 */ | |
5743 | DRXJ_16TO8(-31), /* re26 */ | |
5744 | DRXJ_16TO8(629) /* re27 */ | |
5745 | }; | |
5746 | ||
57afe2f0 | 5747 | dev_addr = demod->my_i2c_dev_addr; |
1bfc9e15 | 5748 | common_attr = (struct drx_common_attr *) demod->my_common_attr; |
b3ce3a83 | 5749 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
443f18d0 MCC |
5750 | |
5751 | /* stop all comm_exec */ | |
244c0e06 | 5752 | rc = drxj_dap_write_reg16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP, 0); |
9482354f | 5753 | if (rc != 0) { |
068e94ea MCC |
5754 | pr_err("error %d\n", rc); |
5755 | goto rw_error; | |
5756 | } | |
244c0e06 | 5757 | rc = drxj_dap_write_reg16(dev_addr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_STOP, 0); |
9482354f | 5758 | if (rc != 0) { |
068e94ea MCC |
5759 | pr_err("error %d\n", rc); |
5760 | goto rw_error; | |
5761 | } | |
244c0e06 | 5762 | rc = drxj_dap_write_reg16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0); |
9482354f | 5763 | if (rc != 0) { |
068e94ea MCC |
5764 | pr_err("error %d\n", rc); |
5765 | goto rw_error; | |
5766 | } | |
244c0e06 | 5767 | rc = drxj_dap_write_reg16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0); |
9482354f | 5768 | if (rc != 0) { |
068e94ea MCC |
5769 | pr_err("error %d\n", rc); |
5770 | goto rw_error; | |
5771 | } | |
244c0e06 | 5772 | rc = drxj_dap_write_reg16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0); |
9482354f | 5773 | if (rc != 0) { |
068e94ea MCC |
5774 | pr_err("error %d\n", rc); |
5775 | goto rw_error; | |
5776 | } | |
244c0e06 | 5777 | rc = drxj_dap_write_reg16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0); |
9482354f | 5778 | if (rc != 0) { |
068e94ea MCC |
5779 | pr_err("error %d\n", rc); |
5780 | goto rw_error; | |
5781 | } | |
244c0e06 | 5782 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0); |
9482354f | 5783 | if (rc != 0) { |
068e94ea MCC |
5784 | pr_err("error %d\n", rc); |
5785 | goto rw_error; | |
5786 | } | |
443f18d0 MCC |
5787 | |
5788 | /* reset demodulator */ | |
57afe2f0 | 5789 | cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB |
443f18d0 | 5790 | | SCU_RAM_COMMAND_CMD_DEMOD_RESET; |
57afe2f0 MCC |
5791 | cmd_scu.parameter_len = 0; |
5792 | cmd_scu.result_len = 1; | |
5793 | cmd_scu.parameter = NULL; | |
5794 | cmd_scu.result = &cmd_result; | |
068e94ea | 5795 | rc = scu_command(dev_addr, &cmd_scu); |
9482354f | 5796 | if (rc != 0) { |
068e94ea MCC |
5797 | pr_err("error %d\n", rc); |
5798 | goto rw_error; | |
5799 | } | |
57afe2f0 | 5800 | |
244c0e06 | 5801 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_DCF_BYPASS__A, 1, 0); |
9482354f | 5802 | if (rc != 0) { |
068e94ea MCC |
5803 | pr_err("error %d\n", rc); |
5804 | goto rw_error; | |
5805 | } | |
244c0e06 | 5806 | rc = drxj_dap_write_reg16(dev_addr, IQM_FS_ADJ_SEL__A, IQM_FS_ADJ_SEL_B_VSB, 0); |
9482354f | 5807 | if (rc != 0) { |
068e94ea MCC |
5808 | pr_err("error %d\n", rc); |
5809 | goto rw_error; | |
5810 | } | |
244c0e06 | 5811 | rc = drxj_dap_write_reg16(dev_addr, IQM_RC_ADJ_SEL__A, IQM_RC_ADJ_SEL_B_VSB, 0); |
9482354f | 5812 | if (rc != 0) { |
068e94ea MCC |
5813 | pr_err("error %d\n", rc); |
5814 | goto rw_error; | |
5815 | } | |
57afe2f0 | 5816 | ext_attr->iqm_rc_rate_ofs = 0x00AD0D79; |
244c0e06 | 5817 | rc = drxdap_fasi_write_reg32(dev_addr, IQM_RC_RATE_OFS_LO__A, ext_attr->iqm_rc_rate_ofs, 0); |
9482354f | 5818 | if (rc != 0) { |
068e94ea MCC |
5819 | pr_err("error %d\n", rc); |
5820 | goto rw_error; | |
5821 | } | |
244c0e06 | 5822 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CFAGC_GAINSHIFT__A, 4, 0); |
9482354f | 5823 | if (rc != 0) { |
068e94ea MCC |
5824 | pr_err("error %d\n", rc); |
5825 | goto rw_error; | |
5826 | } | |
244c0e06 | 5827 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CYGN1TRK__A, 1, 0); |
9482354f | 5828 | if (rc != 0) { |
068e94ea MCC |
5829 | pr_err("error %d\n", rc); |
5830 | goto rw_error; | |
5831 | } | |
5832 | ||
244c0e06 | 5833 | rc = drxj_dap_write_reg16(dev_addr, IQM_RC_CROUT_ENA__A, 1, 0); |
9482354f | 5834 | if (rc != 0) { |
068e94ea MCC |
5835 | pr_err("error %d\n", rc); |
5836 | goto rw_error; | |
5837 | } | |
244c0e06 | 5838 | rc = drxj_dap_write_reg16(dev_addr, IQM_RC_STRETCH__A, 28, 0); |
9482354f | 5839 | if (rc != 0) { |
068e94ea MCC |
5840 | pr_err("error %d\n", rc); |
5841 | goto rw_error; | |
5842 | } | |
244c0e06 | 5843 | rc = drxj_dap_write_reg16(dev_addr, IQM_RT_ACTIVE__A, 0, 0); |
9482354f | 5844 | if (rc != 0) { |
068e94ea MCC |
5845 | pr_err("error %d\n", rc); |
5846 | goto rw_error; | |
5847 | } | |
244c0e06 | 5848 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_SYMMETRIC__A, 0, 0); |
9482354f | 5849 | if (rc != 0) { |
068e94ea MCC |
5850 | pr_err("error %d\n", rc); |
5851 | goto rw_error; | |
5852 | } | |
244c0e06 | 5853 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_MIDTAP__A, 3, 0); |
9482354f | 5854 | if (rc != 0) { |
068e94ea MCC |
5855 | pr_err("error %d\n", rc); |
5856 | goto rw_error; | |
5857 | } | |
244c0e06 | 5858 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_OUT_ENA__A, IQM_CF_OUT_ENA_VSB__M, 0); |
9482354f | 5859 | if (rc != 0) { |
068e94ea MCC |
5860 | pr_err("error %d\n", rc); |
5861 | goto rw_error; | |
5862 | } | |
244c0e06 | 5863 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_SCALE__A, 1393, 0); |
9482354f | 5864 | if (rc != 0) { |
068e94ea MCC |
5865 | pr_err("error %d\n", rc); |
5866 | goto rw_error; | |
5867 | } | |
244c0e06 | 5868 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_SCALE_SH__A, 0, 0); |
9482354f | 5869 | if (rc != 0) { |
068e94ea MCC |
5870 | pr_err("error %d\n", rc); |
5871 | goto rw_error; | |
5872 | } | |
244c0e06 | 5873 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_POW_MEAS_LEN__A, 1, 0); |
9482354f | 5874 | if (rc != 0) { |
068e94ea MCC |
5875 | pr_err("error %d\n", rc); |
5876 | goto rw_error; | |
5877 | } | |
5878 | ||
244c0e06 | 5879 | rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_RE0__A, sizeof(vsb_taps_re), ((u8 *)vsb_taps_re), 0); |
9482354f | 5880 | if (rc != 0) { |
068e94ea MCC |
5881 | pr_err("error %d\n", rc); |
5882 | goto rw_error; | |
5883 | } | |
244c0e06 | 5884 | rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_IM0__A, sizeof(vsb_taps_re), ((u8 *)vsb_taps_re), 0); |
9482354f | 5885 | if (rc != 0) { |
068e94ea MCC |
5886 | pr_err("error %d\n", rc); |
5887 | goto rw_error; | |
5888 | } | |
5889 | ||
244c0e06 | 5890 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_BNTHRESH__A, 330, 0); |
9482354f | 5891 | if (rc != 0) { |
068e94ea MCC |
5892 | pr_err("error %d\n", rc); |
5893 | goto rw_error; | |
5894 | } /* set higher threshold */ | |
244c0e06 | 5895 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CLPLASTNUM__A, 90, 0); |
9482354f | 5896 | if (rc != 0) { |
068e94ea MCC |
5897 | pr_err("error %d\n", rc); |
5898 | goto rw_error; | |
5899 | } /* burst detection on */ | |
244c0e06 | 5900 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_SNRTH_RCA1__A, 0x0042, 0); |
9482354f | 5901 | if (rc != 0) { |
068e94ea MCC |
5902 | pr_err("error %d\n", rc); |
5903 | goto rw_error; | |
5904 | } /* drop thresholds by 1 dB */ | |
244c0e06 | 5905 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_SNRTH_RCA2__A, 0x0053, 0); |
9482354f | 5906 | if (rc != 0) { |
068e94ea MCC |
5907 | pr_err("error %d\n", rc); |
5908 | goto rw_error; | |
5909 | } /* drop thresholds by 2 dB */ | |
244c0e06 | 5910 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_EQCTRL__A, 0x1, 0); |
9482354f | 5911 | if (rc != 0) { |
068e94ea MCC |
5912 | pr_err("error %d\n", rc); |
5913 | goto rw_error; | |
5914 | } /* cma on */ | |
244c0e06 | 5915 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_GPIO__A, 0, 0); |
9482354f | 5916 | if (rc != 0) { |
068e94ea MCC |
5917 | pr_err("error %d\n", rc); |
5918 | goto rw_error; | |
5919 | } /* GPIO */ | |
443f18d0 MCC |
5920 | |
5921 | /* Initialize the FEC Subsystem */ | |
244c0e06 | 5922 | rc = drxj_dap_write_reg16(dev_addr, FEC_TOP_ANNEX__A, FEC_TOP_ANNEX_D, 0); |
9482354f | 5923 | if (rc != 0) { |
068e94ea MCC |
5924 | pr_err("error %d\n", rc); |
5925 | goto rw_error; | |
5926 | } | |
443f18d0 | 5927 | { |
57afe2f0 | 5928 | u16 fec_oc_snc_mode = 0; |
244c0e06 | 5929 | rc = drxj_dap_read_reg16(dev_addr, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode, 0); |
9482354f | 5930 | if (rc != 0) { |
068e94ea MCC |
5931 | pr_err("error %d\n", rc); |
5932 | goto rw_error; | |
5933 | } | |
443f18d0 | 5934 | /* output data even when not locked */ |
244c0e06 | 5935 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_MODE__A, fec_oc_snc_mode | FEC_OC_SNC_MODE_UNLOCK_ENABLE__M, 0); |
9482354f | 5936 | if (rc != 0) { |
068e94ea MCC |
5937 | pr_err("error %d\n", rc); |
5938 | goto rw_error; | |
5939 | } | |
443f18d0 | 5940 | } |
38b2df95 | 5941 | |
443f18d0 | 5942 | /* set clip */ |
244c0e06 | 5943 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_CLP_LEN__A, 0, 0); |
9482354f | 5944 | if (rc != 0) { |
068e94ea MCC |
5945 | pr_err("error %d\n", rc); |
5946 | goto rw_error; | |
5947 | } | |
244c0e06 | 5948 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_CLP_TH__A, 470, 0); |
9482354f | 5949 | if (rc != 0) { |
068e94ea MCC |
5950 | pr_err("error %d\n", rc); |
5951 | goto rw_error; | |
5952 | } | |
244c0e06 | 5953 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_SNS_LEN__A, 0, 0); |
9482354f | 5954 | if (rc != 0) { |
068e94ea MCC |
5955 | pr_err("error %d\n", rc); |
5956 | goto rw_error; | |
5957 | } | |
244c0e06 | 5958 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_SNRTH_PT__A, 0xD4, 0); |
9482354f | 5959 | if (rc != 0) { |
068e94ea MCC |
5960 | pr_err("error %d\n", rc); |
5961 | goto rw_error; | |
5962 | } | |
443f18d0 MCC |
5963 | /* no transparent, no A&C framing; parity is set in mpegoutput */ |
5964 | { | |
57afe2f0 | 5965 | u16 fec_oc_reg_mode = 0; |
244c0e06 | 5966 | rc = drxj_dap_read_reg16(dev_addr, FEC_OC_MODE__A, &fec_oc_reg_mode, 0); |
9482354f | 5967 | if (rc != 0) { |
068e94ea MCC |
5968 | pr_err("error %d\n", rc); |
5969 | goto rw_error; | |
5970 | } | |
244c0e06 | 5971 | rc = drxj_dap_write_reg16(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); |
9482354f | 5972 | if (rc != 0) { |
068e94ea MCC |
5973 | pr_err("error %d\n", rc); |
5974 | goto rw_error; | |
5975 | } | |
443f18d0 | 5976 | } |
38b2df95 | 5977 | |
244c0e06 | 5978 | rc = drxj_dap_write_reg16(dev_addr, FEC_DI_TIMEOUT_LO__A, 0, 0); |
9482354f | 5979 | if (rc != 0) { |
068e94ea MCC |
5980 | pr_err("error %d\n", rc); |
5981 | goto rw_error; | |
5982 | } /* timeout counter for restarting */ | |
244c0e06 | 5983 | rc = drxj_dap_write_reg16(dev_addr, FEC_DI_TIMEOUT_HI__A, 3, 0); |
9482354f | 5984 | if (rc != 0) { |
068e94ea MCC |
5985 | pr_err("error %d\n", rc); |
5986 | goto rw_error; | |
5987 | } | |
244c0e06 | 5988 | rc = drxj_dap_write_reg16(dev_addr, FEC_RS_MODE__A, 0, 0); |
9482354f | 5989 | if (rc != 0) { |
068e94ea MCC |
5990 | pr_err("error %d\n", rc); |
5991 | goto rw_error; | |
5992 | } /* bypass disabled */ | |
443f18d0 | 5993 | /* initialize RS packet error measurement parameters */ |
244c0e06 | 5994 | rc = drxj_dap_write_reg16(dev_addr, FEC_RS_MEASUREMENT_PERIOD__A, FEC_RS_MEASUREMENT_PERIOD, 0); |
9482354f | 5995 | if (rc != 0) { |
068e94ea MCC |
5996 | pr_err("error %d\n", rc); |
5997 | goto rw_error; | |
5998 | } | |
244c0e06 | 5999 | rc = drxj_dap_write_reg16(dev_addr, FEC_RS_MEASUREMENT_PRESCALE__A, FEC_RS_MEASUREMENT_PRESCALE, 0); |
9482354f | 6000 | if (rc != 0) { |
068e94ea MCC |
6001 | pr_err("error %d\n", rc); |
6002 | goto rw_error; | |
6003 | } | |
443f18d0 MCC |
6004 | |
6005 | /* init measurement period of MER/SER */ | |
244c0e06 | 6006 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_MEASUREMENT_PERIOD__A, VSB_TOP_MEASUREMENT_PERIOD, 0); |
9482354f | 6007 | if (rc != 0) { |
068e94ea MCC |
6008 | pr_err("error %d\n", rc); |
6009 | goto rw_error; | |
6010 | } | |
244c0e06 | 6011 | rc = drxdap_fasi_write_reg32(dev_addr, SCU_RAM_FEC_ACCUM_CW_CORRECTED_LO__A, 0, 0); |
9482354f | 6012 | if (rc != 0) { |
068e94ea MCC |
6013 | pr_err("error %d\n", rc); |
6014 | goto rw_error; | |
6015 | } | |
244c0e06 | 6016 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_FEC_MEAS_COUNT__A, 0, 0); |
9482354f | 6017 | if (rc != 0) { |
068e94ea MCC |
6018 | pr_err("error %d\n", rc); |
6019 | goto rw_error; | |
6020 | } | |
244c0e06 | 6021 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0, 0); |
9482354f | 6022 | if (rc != 0) { |
068e94ea MCC |
6023 | pr_err("error %d\n", rc); |
6024 | goto rw_error; | |
6025 | } | |
443f18d0 | 6026 | |
244c0e06 | 6027 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CKGN1TRK__A, 128, 0); |
9482354f | 6028 | if (rc != 0) { |
068e94ea MCC |
6029 | pr_err("error %d\n", rc); |
6030 | goto rw_error; | |
6031 | } | |
443f18d0 | 6032 | /* B-Input to ADC, PGA+filter in standby */ |
259f380e | 6033 | if (!ext_attr->has_lna) { |
244c0e06 | 6034 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_AMUX__A, 0x02, 0); |
9482354f | 6035 | if (rc != 0) { |
068e94ea MCC |
6036 | pr_err("error %d\n", rc); |
6037 | goto rw_error; | |
6038 | } | |
259f380e | 6039 | } |
443f18d0 MCC |
6040 | |
6041 | /* turn on IQMAF. It has to be in front of setAgc**() */ | |
068e94ea | 6042 | rc = set_iqm_af(demod, true); |
9482354f | 6043 | if (rc != 0) { |
068e94ea MCC |
6044 | pr_err("error %d\n", rc); |
6045 | goto rw_error; | |
6046 | } | |
6047 | rc = adc_synchronization(demod); | |
9482354f | 6048 | if (rc != 0) { |
068e94ea MCC |
6049 | pr_err("error %d\n", rc); |
6050 | goto rw_error; | |
6051 | } | |
443f18d0 | 6052 | |
068e94ea | 6053 | rc = init_agc(demod); |
9482354f | 6054 | if (rc != 0) { |
068e94ea MCC |
6055 | pr_err("error %d\n", rc); |
6056 | goto rw_error; | |
6057 | } | |
6058 | rc = set_agc_if(demod, &(ext_attr->vsb_if_agc_cfg), false); | |
9482354f | 6059 | if (rc != 0) { |
068e94ea MCC |
6060 | pr_err("error %d\n", rc); |
6061 | goto rw_error; | |
6062 | } | |
6063 | rc = set_agc_rf(demod, &(ext_attr->vsb_rf_agc_cfg), false); | |
9482354f | 6064 | if (rc != 0) { |
068e94ea MCC |
6065 | pr_err("error %d\n", rc); |
6066 | goto rw_error; | |
6067 | } | |
443f18d0 | 6068 | { |
b3ce3a83 | 6069 | /* TODO fix this, store a struct drxj_cfg_afe_gain structure in struct drxj_data instead |
443f18d0 | 6070 | of only the gain */ |
b3ce3a83 | 6071 | struct drxj_cfg_afe_gain vsb_pga_cfg = { DRX_STANDARD_8VSB, 0 }; |
443f18d0 | 6072 | |
57afe2f0 | 6073 | vsb_pga_cfg.gain = ext_attr->vsb_pga_cfg; |
068e94ea | 6074 | rc = ctrl_set_cfg_afe_gain(demod, &vsb_pga_cfg); |
9482354f | 6075 | if (rc != 0) { |
068e94ea MCC |
6076 | pr_err("error %d\n", rc); |
6077 | goto rw_error; | |
6078 | } | |
6079 | } | |
6080 | rc = ctrl_set_cfg_pre_saw(demod, &(ext_attr->vsb_pre_saw_cfg)); | |
9482354f | 6081 | if (rc != 0) { |
068e94ea MCC |
6082 | pr_err("error %d\n", rc); |
6083 | goto rw_error; | |
443f18d0 | 6084 | } |
443f18d0 MCC |
6085 | |
6086 | /* Mpeg output has to be in front of FEC active */ | |
068e94ea | 6087 | rc = set_mpegtei_handling(demod); |
9482354f | 6088 | if (rc != 0) { |
068e94ea MCC |
6089 | pr_err("error %d\n", rc); |
6090 | goto rw_error; | |
6091 | } | |
6092 | rc = bit_reverse_mpeg_output(demod); | |
9482354f | 6093 | if (rc != 0) { |
068e94ea MCC |
6094 | pr_err("error %d\n", rc); |
6095 | goto rw_error; | |
6096 | } | |
6097 | rc = set_mpeg_start_width(demod); | |
9482354f | 6098 | if (rc != 0) { |
068e94ea MCC |
6099 | pr_err("error %d\n", rc); |
6100 | goto rw_error; | |
6101 | } | |
443f18d0 | 6102 | { |
57afe2f0 | 6103 | /* TODO: move to set_standard after hardware reset value problem is solved */ |
443f18d0 | 6104 | /* Configure initial MPEG output */ |
1bfc9e15 | 6105 | struct drx_cfg_mpeg_output cfg_mpeg_output; |
41b5cc0c MCC |
6106 | |
6107 | memcpy(&cfg_mpeg_output, &common_attr->mpeg_cfg, sizeof(cfg_mpeg_output)); | |
57afe2f0 | 6108 | cfg_mpeg_output.enable_mpeg_output = true; |
41b5cc0c | 6109 | |
068e94ea | 6110 | rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output); |
9482354f | 6111 | if (rc != 0) { |
068e94ea MCC |
6112 | pr_err("error %d\n", rc); |
6113 | goto rw_error; | |
6114 | } | |
443f18d0 MCC |
6115 | } |
6116 | ||
6117 | /* TBD: what parameters should be set */ | |
57afe2f0 MCC |
6118 | cmd_param = 0x00; /* Default mode AGC on, etc */ |
6119 | cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB | |
443f18d0 | 6120 | | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM; |
57afe2f0 MCC |
6121 | cmd_scu.parameter_len = 1; |
6122 | cmd_scu.result_len = 1; | |
6123 | cmd_scu.parameter = &cmd_param; | |
6124 | cmd_scu.result = &cmd_result; | |
068e94ea | 6125 | rc = scu_command(dev_addr, &cmd_scu); |
9482354f | 6126 | if (rc != 0) { |
068e94ea MCC |
6127 | pr_err("error %d\n", rc); |
6128 | goto rw_error; | |
6129 | } | |
443f18d0 | 6130 | |
244c0e06 | 6131 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_BEAGC_GAINSHIFT__A, 0x0004, 0); |
9482354f | 6132 | if (rc != 0) { |
068e94ea MCC |
6133 | pr_err("error %d\n", rc); |
6134 | goto rw_error; | |
6135 | } | |
244c0e06 | 6136 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_SNRTH_PT__A, 0x00D2, 0); |
9482354f | 6137 | if (rc != 0) { |
068e94ea MCC |
6138 | pr_err("error %d\n", rc); |
6139 | goto rw_error; | |
6140 | } | |
244c0e06 | 6141 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_SYSSMTRNCTRL__A, VSB_TOP_SYSSMTRNCTRL__PRE | VSB_TOP_SYSSMTRNCTRL_NCOTIMEOUTCNTEN__M, 0); |
9482354f | 6142 | if (rc != 0) { |
068e94ea MCC |
6143 | pr_err("error %d\n", rc); |
6144 | goto rw_error; | |
6145 | } | |
244c0e06 | 6146 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_BEDETCTRL__A, 0x142, 0); |
9482354f | 6147 | if (rc != 0) { |
068e94ea MCC |
6148 | pr_err("error %d\n", rc); |
6149 | goto rw_error; | |
6150 | } | |
244c0e06 | 6151 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_LBAGCREFLVL__A, 640, 0); |
9482354f | 6152 | if (rc != 0) { |
068e94ea MCC |
6153 | pr_err("error %d\n", rc); |
6154 | goto rw_error; | |
6155 | } | |
244c0e06 | 6156 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CYGN1ACQ__A, 4, 0); |
9482354f | 6157 | if (rc != 0) { |
068e94ea MCC |
6158 | pr_err("error %d\n", rc); |
6159 | goto rw_error; | |
6160 | } | |
244c0e06 | 6161 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CYGN1TRK__A, 2, 0); |
9482354f | 6162 | if (rc != 0) { |
068e94ea MCC |
6163 | pr_err("error %d\n", rc); |
6164 | goto rw_error; | |
6165 | } | |
244c0e06 | 6166 | rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CYGN2TRK__A, 3, 0); |
9482354f | 6167 | if (rc != 0) { |
068e94ea MCC |
6168 | pr_err("error %d\n", rc); |
6169 | goto rw_error; | |
6170 | } | |
6171 | ||
6172 | /* start demodulator */ | |
6173 | cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB | |
6174 | | SCU_RAM_COMMAND_CMD_DEMOD_START; | |
57afe2f0 MCC |
6175 | cmd_scu.parameter_len = 0; |
6176 | cmd_scu.result_len = 1; | |
6177 | cmd_scu.parameter = NULL; | |
6178 | cmd_scu.result = &cmd_result; | |
068e94ea | 6179 | rc = scu_command(dev_addr, &cmd_scu); |
9482354f | 6180 | if (rc != 0) { |
068e94ea MCC |
6181 | pr_err("error %d\n", rc); |
6182 | goto rw_error; | |
6183 | } | |
443f18d0 | 6184 | |
244c0e06 | 6185 | rc = drxj_dap_write_reg16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_ACTIVE, 0); |
9482354f | 6186 | if (rc != 0) { |
068e94ea MCC |
6187 | pr_err("error %d\n", rc); |
6188 | goto rw_error; | |
6189 | } | |
244c0e06 | 6190 | rc = drxj_dap_write_reg16(dev_addr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_ACTIVE, 0); |
9482354f | 6191 | if (rc != 0) { |
068e94ea MCC |
6192 | pr_err("error %d\n", rc); |
6193 | goto rw_error; | |
6194 | } | |
244c0e06 | 6195 | rc = drxj_dap_write_reg16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE, 0); |
9482354f | 6196 | if (rc != 0) { |
068e94ea MCC |
6197 | pr_err("error %d\n", rc); |
6198 | goto rw_error; | |
6199 | } | |
443f18d0 | 6200 | |
9482354f | 6201 | return 0; |
38b2df95 | 6202 | rw_error: |
30741871 | 6203 | return rc; |
38b2df95 DH |
6204 | } |
6205 | ||
34eb9751 | 6206 | /* |
57afe2f0 | 6207 | * \fn static short get_vsb_post_rs_pck_err(struct i2c_device_addr *dev_addr, u16 *PckErrs) |
38b2df95 DH |
6208 | * \brief Get the values of packet error in 8VSB mode |
6209 | * \return Error code | |
6210 | */ | |
69832578 | 6211 | static int get_vsb_post_rs_pck_err(struct i2c_device_addr *dev_addr, |
d591590e | 6212 | u32 *pck_errs, u32 *pck_count) |
443f18d0 | 6213 | { |
068e94ea | 6214 | int rc; |
43a431e4 MCC |
6215 | u16 data = 0; |
6216 | u16 period = 0; | |
6217 | u16 prescale = 0; | |
e33f2193 MCC |
6218 | u16 packet_errors_mant = 0; |
6219 | u16 packet_errors_exp = 0; | |
443f18d0 | 6220 | |
244c0e06 | 6221 | rc = drxj_dap_read_reg16(dev_addr, FEC_RS_NR_FAILURES__A, &data, 0); |
9482354f | 6222 | if (rc != 0) { |
068e94ea MCC |
6223 | pr_err("error %d\n", rc); |
6224 | goto rw_error; | |
6225 | } | |
e33f2193 MCC |
6226 | packet_errors_mant = data & FEC_RS_NR_FAILURES_FIXED_MANT__M; |
6227 | packet_errors_exp = (data & FEC_RS_NR_FAILURES_EXP__M) | |
443f18d0 MCC |
6228 | >> FEC_RS_NR_FAILURES_EXP__B; |
6229 | period = FEC_RS_MEASUREMENT_PERIOD; | |
6230 | prescale = FEC_RS_MEASUREMENT_PRESCALE; | |
6231 | /* packet error rate = (error packet number) per second */ | |
6232 | /* 77.3 us is time for per packet */ | |
068e94ea MCC |
6233 | if (period * prescale == 0) { |
6234 | pr_err("error: period and/or prescale is zero!\n"); | |
9482354f | 6235 | return -EIO; |
068e94ea | 6236 | } |
69832578 MCC |
6237 | *pck_errs = packet_errors_mant * (1 << packet_errors_exp); |
6238 | *pck_count = period * prescale * 77; | |
443f18d0 | 6239 | |
9482354f | 6240 | return 0; |
38b2df95 | 6241 | rw_error: |
30741871 | 6242 | return rc; |
38b2df95 DH |
6243 | } |
6244 | ||
34eb9751 | 6245 | /* |
57afe2f0 | 6246 | * \fn static short GetVSBBer(struct i2c_device_addr *dev_addr, u32 *ber) |
38b2df95 DH |
6247 | * \brief Get the values of ber in VSB mode |
6248 | * \return Error code | |
6249 | */ | |
69832578 MCC |
6250 | static int get_vs_bpost_viterbi_ber(struct i2c_device_addr *dev_addr, |
6251 | u32 *ber, u32 *cnt) | |
443f18d0 | 6252 | { |
068e94ea | 6253 | int rc; |
43a431e4 MCC |
6254 | u16 data = 0; |
6255 | u16 period = 0; | |
6256 | u16 prescale = 0; | |
57afe2f0 MCC |
6257 | u16 bit_errors_mant = 0; |
6258 | u16 bit_errors_exp = 0; | |
443f18d0 | 6259 | |
244c0e06 | 6260 | rc = drxj_dap_read_reg16(dev_addr, FEC_RS_NR_BIT_ERRORS__A, &data, 0); |
9482354f | 6261 | if (rc != 0) { |
068e94ea MCC |
6262 | pr_err("error %d\n", rc); |
6263 | goto rw_error; | |
6264 | } | |
443f18d0 MCC |
6265 | period = FEC_RS_MEASUREMENT_PERIOD; |
6266 | prescale = FEC_RS_MEASUREMENT_PRESCALE; | |
6267 | ||
57afe2f0 MCC |
6268 | bit_errors_mant = data & FEC_RS_NR_BIT_ERRORS_FIXED_MANT__M; |
6269 | bit_errors_exp = (data & FEC_RS_NR_BIT_ERRORS_EXP__M) | |
443f18d0 MCC |
6270 | >> FEC_RS_NR_BIT_ERRORS_EXP__B; |
6271 | ||
69832578 MCC |
6272 | *cnt = period * prescale * 207 * ((bit_errors_exp > 2) ? 1 : 8); |
6273 | ||
57afe2f0 | 6274 | if (((bit_errors_mant << bit_errors_exp) >> 3) > 68700) |
69832578 | 6275 | *ber = (*cnt) * 26570; |
443f18d0 | 6276 | else { |
068e94ea MCC |
6277 | if (period * prescale == 0) { |
6278 | pr_err("error: period and/or prescale is zero!\n"); | |
9482354f | 6279 | return -EIO; |
068e94ea | 6280 | } |
69832578 MCC |
6281 | *ber = bit_errors_mant << ((bit_errors_exp > 2) ? |
6282 | (bit_errors_exp - 3) : bit_errors_exp); | |
443f18d0 | 6283 | } |
38b2df95 | 6284 | |
9482354f | 6285 | return 0; |
38b2df95 | 6286 | rw_error: |
30741871 | 6287 | return rc; |
38b2df95 DH |
6288 | } |
6289 | ||
34eb9751 | 6290 | /* |
57afe2f0 | 6291 | * \fn static short get_vs_bpre_viterbi_ber(struct i2c_device_addr *dev_addr, u32 *ber) |
38b2df95 DH |
6292 | * \brief Get the values of ber in VSB mode |
6293 | * \return Error code | |
6294 | */ | |
69832578 MCC |
6295 | static int get_vs_bpre_viterbi_ber(struct i2c_device_addr *dev_addr, |
6296 | u32 *ber, u32 *cnt) | |
38b2df95 | 6297 | { |
43a431e4 | 6298 | u16 data = 0; |
068e94ea | 6299 | int rc; |
38b2df95 | 6300 | |
244c0e06 | 6301 | rc = drxj_dap_read_reg16(dev_addr, VSB_TOP_NR_SYM_ERRS__A, &data, 0); |
9482354f | 6302 | if (rc != 0) { |
068e94ea | 6303 | pr_err("error %d\n", rc); |
69832578 | 6304 | return -EIO; |
068e94ea | 6305 | } |
69832578 MCC |
6306 | *ber = data; |
6307 | *cnt = VSB_TOP_MEASUREMENT_PERIOD * SYMBOLS_PER_SEGMENT; | |
38b2df95 | 6308 | |
9482354f | 6309 | return 0; |
38b2df95 DH |
6310 | } |
6311 | ||
34eb9751 | 6312 | /* |
b6c4065e MCC |
6313 | * \fn static int get_vsbmer(struct i2c_device_addr *dev_addr, u16 *mer) |
6314 | * \brief Get the values of MER | |
38b2df95 DH |
6315 | * \return Error code |
6316 | */ | |
b6c4065e | 6317 | static int get_vsbmer(struct i2c_device_addr *dev_addr, u16 *mer) |
38b2df95 | 6318 | { |
068e94ea | 6319 | int rc; |
b6c4065e | 6320 | u16 data_hi = 0; |
38b2df95 | 6321 | |
b6c4065e | 6322 | rc = drxj_dap_read_reg16(dev_addr, VSB_TOP_ERR_ENERGY_H__A, &data_hi, 0); |
9482354f | 6323 | if (rc != 0) { |
068e94ea MCC |
6324 | pr_err("error %d\n", rc); |
6325 | goto rw_error; | |
6326 | } | |
b6c4065e MCC |
6327 | *mer = |
6328 | (u16) (log1_times100(21504) - log1_times100((data_hi << 6) / 52)); | |
38b2df95 | 6329 | |
9482354f | 6330 | return 0; |
38b2df95 | 6331 | rw_error: |
30741871 | 6332 | return rc; |
38b2df95 | 6333 | } |
38b2df95 | 6334 | |
443f18d0 | 6335 | |
38b2df95 DH |
6336 | /*============================================================================*/ |
6337 | /*== END 8VSB DATAPATH FUNCTIONS ==*/ | |
6338 | /*============================================================================*/ | |
6339 | ||
6340 | /*============================================================================*/ | |
6341 | /*============================================================================*/ | |
6342 | /*== QAM DATAPATH FUNCTIONS ==*/ | |
6343 | /*============================================================================*/ | |
6344 | /*============================================================================*/ | |
6345 | ||
34eb9751 | 6346 | /* |
57afe2f0 | 6347 | * \fn int power_down_qam () |
38b2df95 DH |
6348 | * \brief Powr down QAM related blocks. |
6349 | * \param demod instance of demodulator. | |
6350 | * \param channel pointer to channel data. | |
61263c75 | 6351 | * \return int. |
38b2df95 | 6352 | */ |
1bfc9e15 | 6353 | static int power_down_qam(struct drx_demod_instance *demod, bool primary) |
38b2df95 | 6354 | { |
b3ce3a83 | 6355 | struct drxjscu_cmd cmd_scu = { /* command */ 0, |
57afe2f0 MCC |
6356 | /* parameter_len */ 0, |
6357 | /* result_len */ 0, | |
443f18d0 MCC |
6358 | /* *parameter */ NULL, |
6359 | /* *result */ NULL | |
6360 | }; | |
068e94ea | 6361 | int rc; |
4d7bb0eb | 6362 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; |
1bfc9e15 | 6363 | struct drx_cfg_mpeg_output cfg_mpeg_output; |
41b5cc0c | 6364 | struct drx_common_attr *common_attr = demod->my_common_attr; |
068e94ea | 6365 | u16 cmd_result = 0; |
443f18d0 | 6366 | |
443f18d0 MCC |
6367 | /* |
6368 | STOP demodulator | |
6369 | resets IQM, QAM and FEC HW blocks | |
6370 | */ | |
6371 | /* stop all comm_exec */ | |
244c0e06 | 6372 | rc = drxj_dap_write_reg16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP, 0); |
9482354f | 6373 | if (rc != 0) { |
068e94ea MCC |
6374 | pr_err("error %d\n", rc); |
6375 | goto rw_error; | |
6376 | } | |
244c0e06 | 6377 | rc = drxj_dap_write_reg16(dev_addr, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP, 0); |
9482354f | 6378 | if (rc != 0) { |
068e94ea MCC |
6379 | pr_err("error %d\n", rc); |
6380 | goto rw_error; | |
6381 | } | |
443f18d0 | 6382 | |
57afe2f0 | 6383 | cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM | |
443f18d0 | 6384 | SCU_RAM_COMMAND_CMD_DEMOD_STOP; |
57afe2f0 MCC |
6385 | cmd_scu.parameter_len = 0; |
6386 | cmd_scu.result_len = 1; | |
6387 | cmd_scu.parameter = NULL; | |
6388 | cmd_scu.result = &cmd_result; | |
068e94ea | 6389 | rc = scu_command(dev_addr, &cmd_scu); |
9482354f | 6390 | if (rc != 0) { |
068e94ea MCC |
6391 | pr_err("error %d\n", rc); |
6392 | goto rw_error; | |
6393 | } | |
443f18d0 | 6394 | |
259f380e | 6395 | if (primary) { |
244c0e06 | 6396 | rc = drxj_dap_write_reg16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP, 0); |
9482354f | 6397 | if (rc != 0) { |
068e94ea MCC |
6398 | pr_err("error %d\n", rc); |
6399 | goto rw_error; | |
6400 | } | |
6401 | rc = set_iqm_af(demod, false); | |
9482354f | 6402 | if (rc != 0) { |
068e94ea MCC |
6403 | pr_err("error %d\n", rc); |
6404 | goto rw_error; | |
6405 | } | |
443f18d0 | 6406 | } else { |
244c0e06 | 6407 | rc = drxj_dap_write_reg16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0); |
9482354f | 6408 | if (rc != 0) { |
068e94ea MCC |
6409 | pr_err("error %d\n", rc); |
6410 | goto rw_error; | |
6411 | } | |
244c0e06 | 6412 | rc = drxj_dap_write_reg16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0); |
9482354f | 6413 | if (rc != 0) { |
068e94ea MCC |
6414 | pr_err("error %d\n", rc); |
6415 | goto rw_error; | |
6416 | } | |
244c0e06 | 6417 | rc = drxj_dap_write_reg16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0); |
9482354f | 6418 | if (rc != 0) { |
068e94ea MCC |
6419 | pr_err("error %d\n", rc); |
6420 | goto rw_error; | |
6421 | } | |
244c0e06 | 6422 | rc = drxj_dap_write_reg16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0); |
9482354f | 6423 | if (rc != 0) { |
068e94ea MCC |
6424 | pr_err("error %d\n", rc); |
6425 | goto rw_error; | |
6426 | } | |
244c0e06 | 6427 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0); |
9482354f | 6428 | if (rc != 0) { |
068e94ea MCC |
6429 | pr_err("error %d\n", rc); |
6430 | goto rw_error; | |
6431 | } | |
443f18d0 MCC |
6432 | } |
6433 | ||
41b5cc0c | 6434 | memcpy(&cfg_mpeg_output, &common_attr->mpeg_cfg, sizeof(cfg_mpeg_output)); |
57afe2f0 | 6435 | cfg_mpeg_output.enable_mpeg_output = false; |
41b5cc0c | 6436 | |
068e94ea | 6437 | rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output); |
9482354f | 6438 | if (rc != 0) { |
068e94ea MCC |
6439 | pr_err("error %d\n", rc); |
6440 | goto rw_error; | |
6441 | } | |
38b2df95 | 6442 | |
9482354f | 6443 | return 0; |
38b2df95 | 6444 | rw_error: |
30741871 | 6445 | return rc; |
38b2df95 DH |
6446 | } |
6447 | ||
6448 | /*============================================================================*/ | |
6449 | ||
34eb9751 | 6450 | /* |
57afe2f0 | 6451 | * \fn int set_qam_measurement () |
38b2df95 DH |
6452 | * \brief Setup of the QAM Measuremnt intervals for signal quality |
6453 | * \param demod instance of demod. | |
6454 | * \param constellation current constellation. | |
61263c75 | 6455 | * \return int. |
38b2df95 DH |
6456 | * |
6457 | * NOTE: | |
6458 | * Take into account that for certain settings the errorcounters can overflow. | |
6459 | * The implementation does not check this. | |
6460 | * | |
57afe2f0 MCC |
6461 | * TODO: overriding the ext_attr->fec_bits_desired by constellation dependent |
6462 | * constants to get a measurement period of approx. 1 sec. Remove fec_bits_desired | |
38b2df95 DH |
6463 | * field ? |
6464 | * | |
6465 | */ | |
6466 | #ifndef DRXJ_VSB_ONLY | |
61263c75 | 6467 | static int |
1bfc9e15 | 6468 | set_qam_measurement(struct drx_demod_instance *demod, |
22892268 | 6469 | enum drx_modulation constellation, u32 symbol_rate) |
57afe2f0 MCC |
6470 | { |
6471 | struct i2c_device_addr *dev_addr = NULL; /* device address for I2C writes */ | |
69bb7ab6 | 6472 | struct drxj_data *ext_attr = NULL; /* Global data container for DRXJ specific data */ |
068e94ea | 6473 | int rc; |
57afe2f0 MCC |
6474 | u32 fec_bits_desired = 0; /* BER accounting period */ |
6475 | u16 fec_rs_plen = 0; /* defines RS BER measurement period */ | |
6476 | u16 fec_rs_prescale = 0; /* ReedSolomon Measurement Prescale */ | |
6477 | u32 fec_rs_period = 0; /* Value for corresponding I2C register */ | |
6478 | u32 fec_rs_bit_cnt = 0; /* Actual precise amount of bits */ | |
6479 | u32 fec_oc_snc_fail_period = 0; /* Value for corresponding I2C register */ | |
6480 | u32 qam_vd_period = 0; /* Value for corresponding I2C register */ | |
6481 | u32 qam_vd_bit_cnt = 0; /* Actual precise amount of bits */ | |
6482 | u16 fec_vd_plen = 0; /* no of trellis symbols: VD SER measur period */ | |
6483 | u16 qam_vd_prescale = 0; /* Viterbi Measurement Prescale */ | |
6484 | ||
6485 | dev_addr = demod->my_i2c_dev_addr; | |
b3ce3a83 | 6486 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
57afe2f0 MCC |
6487 | |
6488 | fec_bits_desired = ext_attr->fec_bits_desired; | |
6489 | fec_rs_prescale = ext_attr->fec_rs_prescale; | |
443f18d0 MCC |
6490 | |
6491 | switch (constellation) { | |
6492 | case DRX_CONSTELLATION_QAM16: | |
57afe2f0 | 6493 | fec_bits_desired = 4 * symbol_rate; |
443f18d0 MCC |
6494 | break; |
6495 | case DRX_CONSTELLATION_QAM32: | |
57afe2f0 | 6496 | fec_bits_desired = 5 * symbol_rate; |
443f18d0 MCC |
6497 | break; |
6498 | case DRX_CONSTELLATION_QAM64: | |
57afe2f0 | 6499 | fec_bits_desired = 6 * symbol_rate; |
443f18d0 MCC |
6500 | break; |
6501 | case DRX_CONSTELLATION_QAM128: | |
57afe2f0 | 6502 | fec_bits_desired = 7 * symbol_rate; |
443f18d0 MCC |
6503 | break; |
6504 | case DRX_CONSTELLATION_QAM256: | |
57afe2f0 | 6505 | fec_bits_desired = 8 * symbol_rate; |
443f18d0 MCC |
6506 | break; |
6507 | default: | |
9482354f | 6508 | return -EINVAL; |
443f18d0 MCC |
6509 | } |
6510 | ||
6511 | /* Parameters for Reed-Solomon Decoder */ | |
6512 | /* fecrs_period = (int)ceil(FEC_BITS_DESIRED/(fecrs_prescale*plen)) */ | |
6513 | /* rs_bit_cnt = fecrs_period*fecrs_prescale*plen */ | |
6514 | /* result is within 32 bit arithmetic -> */ | |
6515 | /* no need for mult or frac functions */ | |
6516 | ||
57afe2f0 MCC |
6517 | /* TODO: use constant instead of calculation and remove the fec_rs_plen in ext_attr */ |
6518 | switch (ext_attr->standard) { | |
443f18d0 MCC |
6519 | case DRX_STANDARD_ITU_A: |
6520 | case DRX_STANDARD_ITU_C: | |
57afe2f0 | 6521 | fec_rs_plen = 204 * 8; |
443f18d0 MCC |
6522 | break; |
6523 | case DRX_STANDARD_ITU_B: | |
57afe2f0 | 6524 | fec_rs_plen = 128 * 7; |
443f18d0 MCC |
6525 | break; |
6526 | default: | |
9482354f | 6527 | return -EINVAL; |
443f18d0 MCC |
6528 | } |
6529 | ||
57afe2f0 MCC |
6530 | ext_attr->fec_rs_plen = fec_rs_plen; /* for getSigQual */ |
6531 | fec_rs_bit_cnt = fec_rs_prescale * fec_rs_plen; /* temp storage */ | |
068e94ea MCC |
6532 | if (fec_rs_bit_cnt == 0) { |
6533 | pr_err("error: fec_rs_bit_cnt is zero!\n"); | |
9482354f | 6534 | return -EIO; |
068e94ea | 6535 | } |
57afe2f0 MCC |
6536 | fec_rs_period = fec_bits_desired / fec_rs_bit_cnt + 1; /* ceil */ |
6537 | if (ext_attr->standard != DRX_STANDARD_ITU_B) | |
6538 | fec_oc_snc_fail_period = fec_rs_period; | |
443f18d0 MCC |
6539 | |
6540 | /* limit to max 16 bit value (I2C register width) if needed */ | |
57afe2f0 MCC |
6541 | if (fec_rs_period > 0xFFFF) |
6542 | fec_rs_period = 0xFFFF; | |
443f18d0 MCC |
6543 | |
6544 | /* write corresponding registers */ | |
57afe2f0 | 6545 | switch (ext_attr->standard) { |
443f18d0 MCC |
6546 | case DRX_STANDARD_ITU_A: |
6547 | case DRX_STANDARD_ITU_C: | |
6548 | break; | |
6549 | case DRX_STANDARD_ITU_B: | |
6550 | switch (constellation) { | |
6551 | case DRX_CONSTELLATION_QAM64: | |
57afe2f0 MCC |
6552 | fec_rs_period = 31581; |
6553 | fec_oc_snc_fail_period = 17932; | |
443f18d0 MCC |
6554 | break; |
6555 | case DRX_CONSTELLATION_QAM256: | |
57afe2f0 MCC |
6556 | fec_rs_period = 45446; |
6557 | fec_oc_snc_fail_period = 25805; | |
443f18d0 MCC |
6558 | break; |
6559 | default: | |
9482354f | 6560 | return -EINVAL; |
443f18d0 MCC |
6561 | } |
6562 | break; | |
6563 | default: | |
9482354f | 6564 | return -EINVAL; |
443f18d0 MCC |
6565 | } |
6566 | ||
244c0e06 | 6567 | rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_FAIL_PERIOD__A, (u16)fec_oc_snc_fail_period, 0); |
9482354f | 6568 | if (rc != 0) { |
068e94ea MCC |
6569 | pr_err("error %d\n", rc); |
6570 | goto rw_error; | |
6571 | } | |
244c0e06 | 6572 | rc = drxj_dap_write_reg16(dev_addr, FEC_RS_MEASUREMENT_PERIOD__A, (u16)fec_rs_period, 0); |
9482354f | 6573 | if (rc != 0) { |
068e94ea MCC |
6574 | pr_err("error %d\n", rc); |
6575 | goto rw_error; | |
6576 | } | |
244c0e06 | 6577 | rc = drxj_dap_write_reg16(dev_addr, FEC_RS_MEASUREMENT_PRESCALE__A, fec_rs_prescale, 0); |
9482354f | 6578 | if (rc != 0) { |
068e94ea MCC |
6579 | pr_err("error %d\n", rc); |
6580 | goto rw_error; | |
6581 | } | |
57afe2f0 MCC |
6582 | ext_attr->fec_rs_period = (u16) fec_rs_period; |
6583 | ext_attr->fec_rs_prescale = fec_rs_prescale; | |
244c0e06 | 6584 | rc = drxdap_fasi_write_reg32(dev_addr, SCU_RAM_FEC_ACCUM_CW_CORRECTED_LO__A, 0, 0); |
9482354f | 6585 | if (rc != 0) { |
068e94ea MCC |
6586 | pr_err("error %d\n", rc); |
6587 | goto rw_error; | |
6588 | } | |
244c0e06 | 6589 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_FEC_MEAS_COUNT__A, 0, 0); |
9482354f | 6590 | if (rc != 0) { |
068e94ea MCC |
6591 | pr_err("error %d\n", rc); |
6592 | goto rw_error; | |
6593 | } | |
244c0e06 | 6594 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0, 0); |
9482354f | 6595 | if (rc != 0) { |
068e94ea MCC |
6596 | pr_err("error %d\n", rc); |
6597 | goto rw_error; | |
6598 | } | |
443f18d0 | 6599 | |
57afe2f0 | 6600 | if (ext_attr->standard == DRX_STANDARD_ITU_B) { |
443f18d0 MCC |
6601 | /* Parameters for Viterbi Decoder */ |
6602 | /* qamvd_period = (int)ceil(FEC_BITS_DESIRED/ */ | |
6603 | /* (qamvd_prescale*plen*(qam_constellation+1))) */ | |
6604 | /* vd_bit_cnt = qamvd_period*qamvd_prescale*plen */ | |
6605 | /* result is within 32 bit arithmetic -> */ | |
6606 | /* no need for mult or frac functions */ | |
6607 | ||
57afe2f0 MCC |
6608 | /* a(8 bit) * b(8 bit) = 16 bit result => mult32 not needed */ |
6609 | fec_vd_plen = ext_attr->fec_vd_plen; | |
6610 | qam_vd_prescale = ext_attr->qam_vd_prescale; | |
6611 | qam_vd_bit_cnt = qam_vd_prescale * fec_vd_plen; /* temp storage */ | |
443f18d0 MCC |
6612 | |
6613 | switch (constellation) { | |
6614 | case DRX_CONSTELLATION_QAM64: | |
57afe2f0 MCC |
6615 | /* a(16 bit) * b(4 bit) = 20 bit result => mult32 not needed */ |
6616 | qam_vd_period = | |
6617 | qam_vd_bit_cnt * (QAM_TOP_CONSTELLATION_QAM64 + 1) | |
443f18d0 MCC |
6618 | * (QAM_TOP_CONSTELLATION_QAM64 + 1); |
6619 | break; | |
6620 | case DRX_CONSTELLATION_QAM256: | |
57afe2f0 MCC |
6621 | /* a(16 bit) * b(5 bit) = 21 bit result => mult32 not needed */ |
6622 | qam_vd_period = | |
6623 | qam_vd_bit_cnt * (QAM_TOP_CONSTELLATION_QAM256 + 1) | |
443f18d0 MCC |
6624 | * (QAM_TOP_CONSTELLATION_QAM256 + 1); |
6625 | break; | |
6626 | default: | |
9482354f | 6627 | return -EINVAL; |
443f18d0 | 6628 | } |
068e94ea MCC |
6629 | if (qam_vd_period == 0) { |
6630 | pr_err("error: qam_vd_period is zero!\n"); | |
9482354f | 6631 | return -EIO; |
068e94ea | 6632 | } |
57afe2f0 | 6633 | qam_vd_period = fec_bits_desired / qam_vd_period; |
443f18d0 | 6634 | /* limit to max 16 bit value (I2C register width) if needed */ |
57afe2f0 MCC |
6635 | if (qam_vd_period > 0xFFFF) |
6636 | qam_vd_period = 0xFFFF; | |
443f18d0 | 6637 | |
57afe2f0 MCC |
6638 | /* a(16 bit) * b(16 bit) = 32 bit result => mult32 not needed */ |
6639 | qam_vd_bit_cnt *= qam_vd_period; | |
443f18d0 | 6640 | |
244c0e06 | 6641 | rc = drxj_dap_write_reg16(dev_addr, QAM_VD_MEASUREMENT_PERIOD__A, (u16)qam_vd_period, 0); |
9482354f | 6642 | if (rc != 0) { |
068e94ea MCC |
6643 | pr_err("error %d\n", rc); |
6644 | goto rw_error; | |
6645 | } | |
244c0e06 | 6646 | rc = drxj_dap_write_reg16(dev_addr, QAM_VD_MEASUREMENT_PRESCALE__A, qam_vd_prescale, 0); |
9482354f | 6647 | if (rc != 0) { |
068e94ea MCC |
6648 | pr_err("error %d\n", rc); |
6649 | goto rw_error; | |
6650 | } | |
57afe2f0 MCC |
6651 | ext_attr->qam_vd_period = (u16) qam_vd_period; |
6652 | ext_attr->qam_vd_prescale = qam_vd_prescale; | |
443f18d0 MCC |
6653 | } |
6654 | ||
9482354f | 6655 | return 0; |
38b2df95 | 6656 | rw_error: |
30741871 | 6657 | return rc; |
38b2df95 DH |
6658 | } |
6659 | ||
6660 | /*============================================================================*/ | |
6661 | ||
34eb9751 | 6662 | /* |
57afe2f0 | 6663 | * \fn int set_qam16 () |
38b2df95 DH |
6664 | * \brief QAM16 specific setup |
6665 | * \param demod instance of demod. | |
61263c75 | 6666 | * \return int. |
38b2df95 | 6667 | */ |
1bfc9e15 | 6668 | static int set_qam16(struct drx_demod_instance *demod) |
443f18d0 | 6669 | { |
57afe2f0 | 6670 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; |
068e94ea | 6671 | int rc; |
679cfbb1 | 6672 | static const u8 qam_dq_qual_fun[] = { |
443f18d0 MCC |
6673 | DRXJ_16TO8(2), /* fun0 */ |
6674 | DRXJ_16TO8(2), /* fun1 */ | |
6675 | DRXJ_16TO8(2), /* fun2 */ | |
6676 | DRXJ_16TO8(2), /* fun3 */ | |
6677 | DRXJ_16TO8(3), /* fun4 */ | |
6678 | DRXJ_16TO8(3), /* fun5 */ | |
6679 | }; | |
679cfbb1 | 6680 | static const u8 qam_eq_cma_rad[] = { |
443f18d0 MCC |
6681 | DRXJ_16TO8(13517), /* RAD0 */ |
6682 | DRXJ_16TO8(13517), /* RAD1 */ | |
6683 | DRXJ_16TO8(13517), /* RAD2 */ | |
6684 | DRXJ_16TO8(13517), /* RAD3 */ | |
6685 | DRXJ_16TO8(13517), /* RAD4 */ | |
6686 | DRXJ_16TO8(13517), /* RAD5 */ | |
6687 | }; | |
6688 | ||
244c0e06 | 6689 | rc = drxdap_fasi_write_block(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun), ((u8 *)qam_dq_qual_fun), 0); |
9482354f | 6690 | if (rc != 0) { |
068e94ea MCC |
6691 | pr_err("error %d\n", rc); |
6692 | goto rw_error; | |
6693 | } | |
244c0e06 | 6694 | rc = drxdap_fasi_write_block(dev_addr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qam_eq_cma_rad), ((u8 *)qam_eq_cma_rad), 0); |
9482354f | 6695 | if (rc != 0) { |
068e94ea MCC |
6696 | pr_err("error %d\n", rc); |
6697 | goto rw_error; | |
6698 | } | |
6699 | ||
244c0e06 | 6700 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 140, 0); |
9482354f | 6701 | if (rc != 0) { |
068e94ea MCC |
6702 | pr_err("error %d\n", rc); |
6703 | goto rw_error; | |
6704 | } | |
244c0e06 | 6705 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 50, 0); |
9482354f | 6706 | if (rc != 0) { |
068e94ea MCC |
6707 | pr_err("error %d\n", rc); |
6708 | goto rw_error; | |
6709 | } | |
244c0e06 | 6710 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 120, 0); |
9482354f | 6711 | if (rc != 0) { |
068e94ea MCC |
6712 | pr_err("error %d\n", rc); |
6713 | goto rw_error; | |
6714 | } | |
244c0e06 | 6715 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 230, 0); |
9482354f | 6716 | if (rc != 0) { |
068e94ea MCC |
6717 | pr_err("error %d\n", rc); |
6718 | goto rw_error; | |
6719 | } | |
244c0e06 | 6720 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 95, 0); |
9482354f | 6721 | if (rc != 0) { |
068e94ea MCC |
6722 | pr_err("error %d\n", rc); |
6723 | goto rw_error; | |
6724 | } | |
244c0e06 | 6725 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 105, 0); |
9482354f | 6726 | if (rc != 0) { |
068e94ea MCC |
6727 | pr_err("error %d\n", rc); |
6728 | goto rw_error; | |
6729 | } | |
6730 | ||
244c0e06 | 6731 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40, 0); |
9482354f | 6732 | if (rc != 0) { |
068e94ea MCC |
6733 | pr_err("error %d\n", rc); |
6734 | goto rw_error; | |
6735 | } | |
244c0e06 | 6736 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 56, 0); |
9482354f | 6737 | if (rc != 0) { |
068e94ea MCC |
6738 | pr_err("error %d\n", rc); |
6739 | goto rw_error; | |
6740 | } | |
244c0e06 | 6741 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3, 0); |
9482354f | 6742 | if (rc != 0) { |
068e94ea MCC |
6743 | pr_err("error %d\n", rc); |
6744 | goto rw_error; | |
6745 | } | |
6746 | ||
244c0e06 | 6747 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 16, 0); |
9482354f | 6748 | if (rc != 0) { |
068e94ea MCC |
6749 | pr_err("error %d\n", rc); |
6750 | goto rw_error; | |
6751 | } | |
244c0e06 | 6752 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 220, 0); |
9482354f | 6753 | if (rc != 0) { |
068e94ea MCC |
6754 | pr_err("error %d\n", rc); |
6755 | goto rw_error; | |
6756 | } | |
244c0e06 | 6757 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 25, 0); |
9482354f | 6758 | if (rc != 0) { |
068e94ea MCC |
6759 | pr_err("error %d\n", rc); |
6760 | goto rw_error; | |
6761 | } | |
244c0e06 | 6762 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 6, 0); |
9482354f | 6763 | if (rc != 0) { |
068e94ea MCC |
6764 | pr_err("error %d\n", rc); |
6765 | goto rw_error; | |
6766 | } | |
244c0e06 | 6767 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16)(-24), 0); |
9482354f | 6768 | if (rc != 0) { |
068e94ea MCC |
6769 | pr_err("error %d\n", rc); |
6770 | goto rw_error; | |
6771 | } | |
244c0e06 | 6772 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16)(-65), 0); |
9482354f | 6773 | if (rc != 0) { |
068e94ea MCC |
6774 | pr_err("error %d\n", rc); |
6775 | goto rw_error; | |
6776 | } | |
244c0e06 | 6777 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16)(-127), 0); |
9482354f | 6778 | if (rc != 0) { |
068e94ea MCC |
6779 | pr_err("error %d\n", rc); |
6780 | goto rw_error; | |
6781 | } | |
6782 | ||
244c0e06 | 6783 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15, 0); |
9482354f | 6784 | if (rc != 0) { |
068e94ea MCC |
6785 | pr_err("error %d\n", rc); |
6786 | goto rw_error; | |
6787 | } | |
244c0e06 | 6788 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40, 0); |
9482354f | 6789 | if (rc != 0) { |
068e94ea MCC |
6790 | pr_err("error %d\n", rc); |
6791 | goto rw_error; | |
6792 | } | |
244c0e06 | 6793 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2, 0); |
9482354f | 6794 | if (rc != 0) { |
068e94ea MCC |
6795 | pr_err("error %d\n", rc); |
6796 | goto rw_error; | |
6797 | } | |
244c0e06 | 6798 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20, 0); |
9482354f | 6799 | if (rc != 0) { |
068e94ea MCC |
6800 | pr_err("error %d\n", rc); |
6801 | goto rw_error; | |
6802 | } | |
244c0e06 | 6803 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255, 0); |
9482354f | 6804 | if (rc != 0) { |
068e94ea MCC |
6805 | pr_err("error %d\n", rc); |
6806 | goto rw_error; | |
6807 | } | |
244c0e06 | 6808 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2, 0); |
9482354f | 6809 | if (rc != 0) { |
068e94ea MCC |
6810 | pr_err("error %d\n", rc); |
6811 | goto rw_error; | |
6812 | } | |
244c0e06 | 6813 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 10, 0); |
9482354f | 6814 | if (rc != 0) { |
068e94ea MCC |
6815 | pr_err("error %d\n", rc); |
6816 | goto rw_error; | |
6817 | } | |
244c0e06 | 6818 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 50, 0); |
9482354f | 6819 | if (rc != 0) { |
068e94ea MCC |
6820 | pr_err("error %d\n", rc); |
6821 | goto rw_error; | |
6822 | } | |
244c0e06 | 6823 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12, 0); |
9482354f | 6824 | if (rc != 0) { |
068e94ea MCC |
6825 | pr_err("error %d\n", rc); |
6826 | goto rw_error; | |
6827 | } | |
244c0e06 | 6828 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24, 0); |
9482354f | 6829 | if (rc != 0) { |
068e94ea MCC |
6830 | pr_err("error %d\n", rc); |
6831 | goto rw_error; | |
6832 | } | |
244c0e06 | 6833 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24, 0); |
9482354f | 6834 | if (rc != 0) { |
068e94ea MCC |
6835 | pr_err("error %d\n", rc); |
6836 | goto rw_error; | |
6837 | } | |
244c0e06 | 6838 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12, 0); |
9482354f | 6839 | if (rc != 0) { |
068e94ea MCC |
6840 | pr_err("error %d\n", rc); |
6841 | goto rw_error; | |
6842 | } | |
244c0e06 | 6843 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16, 0); |
9482354f | 6844 | if (rc != 0) { |
068e94ea MCC |
6845 | pr_err("error %d\n", rc); |
6846 | goto rw_error; | |
6847 | } | |
244c0e06 | 6848 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16, 0); |
9482354f | 6849 | if (rc != 0) { |
068e94ea MCC |
6850 | pr_err("error %d\n", rc); |
6851 | goto rw_error; | |
6852 | } | |
244c0e06 | 6853 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16, 0); |
9482354f | 6854 | if (rc != 0) { |
068e94ea MCC |
6855 | pr_err("error %d\n", rc); |
6856 | goto rw_error; | |
6857 | } | |
244c0e06 | 6858 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 32, 0); |
9482354f | 6859 | if (rc != 0) { |
068e94ea MCC |
6860 | pr_err("error %d\n", rc); |
6861 | goto rw_error; | |
6862 | } | |
244c0e06 | 6863 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 240, 0); |
9482354f | 6864 | if (rc != 0) { |
068e94ea MCC |
6865 | pr_err("error %d\n", rc); |
6866 | goto rw_error; | |
6867 | } | |
244c0e06 | 6868 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5, 0); |
9482354f | 6869 | if (rc != 0) { |
068e94ea MCC |
6870 | pr_err("error %d\n", rc); |
6871 | goto rw_error; | |
6872 | } | |
244c0e06 | 6873 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15, 0); |
9482354f | 6874 | if (rc != 0) { |
068e94ea MCC |
6875 | pr_err("error %d\n", rc); |
6876 | goto rw_error; | |
6877 | } | |
244c0e06 | 6878 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 32, 0); |
9482354f | 6879 | if (rc != 0) { |
068e94ea MCC |
6880 | pr_err("error %d\n", rc); |
6881 | goto rw_error; | |
6882 | } | |
6883 | ||
244c0e06 | 6884 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 40960, 0); |
9482354f | 6885 | if (rc != 0) { |
068e94ea MCC |
6886 | pr_err("error %d\n", rc); |
6887 | goto rw_error; | |
6888 | } | |
443f18d0 | 6889 | |
9482354f | 6890 | return 0; |
38b2df95 | 6891 | rw_error: |
30741871 | 6892 | return rc; |
38b2df95 DH |
6893 | } |
6894 | ||
6895 | /*============================================================================*/ | |
6896 | ||
34eb9751 | 6897 | /* |
57afe2f0 | 6898 | * \fn int set_qam32 () |
38b2df95 DH |
6899 | * \brief QAM32 specific setup |
6900 | * \param demod instance of demod. | |
61263c75 | 6901 | * \return int. |
38b2df95 | 6902 | */ |
1bfc9e15 | 6903 | static int set_qam32(struct drx_demod_instance *demod) |
443f18d0 | 6904 | { |
57afe2f0 | 6905 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; |
068e94ea | 6906 | int rc; |
679cfbb1 | 6907 | static const u8 qam_dq_qual_fun[] = { |
443f18d0 MCC |
6908 | DRXJ_16TO8(3), /* fun0 */ |
6909 | DRXJ_16TO8(3), /* fun1 */ | |
6910 | DRXJ_16TO8(3), /* fun2 */ | |
6911 | DRXJ_16TO8(3), /* fun3 */ | |
6912 | DRXJ_16TO8(4), /* fun4 */ | |
6913 | DRXJ_16TO8(4), /* fun5 */ | |
6914 | }; | |
679cfbb1 | 6915 | static const u8 qam_eq_cma_rad[] = { |
443f18d0 MCC |
6916 | DRXJ_16TO8(6707), /* RAD0 */ |
6917 | DRXJ_16TO8(6707), /* RAD1 */ | |
6918 | DRXJ_16TO8(6707), /* RAD2 */ | |
6919 | DRXJ_16TO8(6707), /* RAD3 */ | |
6920 | DRXJ_16TO8(6707), /* RAD4 */ | |
6921 | DRXJ_16TO8(6707), /* RAD5 */ | |
6922 | }; | |
6923 | ||
244c0e06 | 6924 | rc = drxdap_fasi_write_block(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun), ((u8 *)qam_dq_qual_fun), 0); |
9482354f | 6925 | if (rc != 0) { |
068e94ea MCC |
6926 | pr_err("error %d\n", rc); |
6927 | goto rw_error; | |
6928 | } | |
244c0e06 | 6929 | rc = drxdap_fasi_write_block(dev_addr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qam_eq_cma_rad), ((u8 *)qam_eq_cma_rad), 0); |
9482354f | 6930 | if (rc != 0) { |
068e94ea MCC |
6931 | pr_err("error %d\n", rc); |
6932 | goto rw_error; | |
6933 | } | |
6934 | ||
244c0e06 | 6935 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 90, 0); |
9482354f | 6936 | if (rc != 0) { |
068e94ea MCC |
6937 | pr_err("error %d\n", rc); |
6938 | goto rw_error; | |
6939 | } | |
244c0e06 | 6940 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 50, 0); |
9482354f | 6941 | if (rc != 0) { |
068e94ea MCC |
6942 | pr_err("error %d\n", rc); |
6943 | goto rw_error; | |
6944 | } | |
244c0e06 | 6945 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 100, 0); |
9482354f | 6946 | if (rc != 0) { |
068e94ea MCC |
6947 | pr_err("error %d\n", rc); |
6948 | goto rw_error; | |
6949 | } | |
244c0e06 | 6950 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 170, 0); |
9482354f | 6951 | if (rc != 0) { |
068e94ea MCC |
6952 | pr_err("error %d\n", rc); |
6953 | goto rw_error; | |
6954 | } | |
244c0e06 | 6955 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 80, 0); |
9482354f | 6956 | if (rc != 0) { |
068e94ea MCC |
6957 | pr_err("error %d\n", rc); |
6958 | goto rw_error; | |
6959 | } | |
244c0e06 | 6960 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 100, 0); |
9482354f | 6961 | if (rc != 0) { |
068e94ea MCC |
6962 | pr_err("error %d\n", rc); |
6963 | goto rw_error; | |
6964 | } | |
6965 | ||
244c0e06 | 6966 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40, 0); |
9482354f | 6967 | if (rc != 0) { |
068e94ea MCC |
6968 | pr_err("error %d\n", rc); |
6969 | goto rw_error; | |
6970 | } | |
244c0e06 | 6971 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 56, 0); |
9482354f | 6972 | if (rc != 0) { |
068e94ea MCC |
6973 | pr_err("error %d\n", rc); |
6974 | goto rw_error; | |
6975 | } | |
244c0e06 | 6976 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3, 0); |
9482354f | 6977 | if (rc != 0) { |
068e94ea MCC |
6978 | pr_err("error %d\n", rc); |
6979 | goto rw_error; | |
6980 | } | |
6981 | ||
244c0e06 | 6982 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 12, 0); |
9482354f | 6983 | if (rc != 0) { |
068e94ea MCC |
6984 | pr_err("error %d\n", rc); |
6985 | goto rw_error; | |
6986 | } | |
244c0e06 | 6987 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 140, 0); |
9482354f | 6988 | if (rc != 0) { |
068e94ea MCC |
6989 | pr_err("error %d\n", rc); |
6990 | goto rw_error; | |
6991 | } | |
244c0e06 | 6992 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16)(-8), 0); |
9482354f | 6993 | if (rc != 0) { |
068e94ea MCC |
6994 | pr_err("error %d\n", rc); |
6995 | goto rw_error; | |
6996 | } | |
244c0e06 | 6997 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16)(-16), 0); |
9482354f | 6998 | if (rc != 0) { |
068e94ea MCC |
6999 | pr_err("error %d\n", rc); |
7000 | goto rw_error; | |
7001 | } | |
244c0e06 | 7002 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16)(-26), 0); |
9482354f | 7003 | if (rc != 0) { |
068e94ea MCC |
7004 | pr_err("error %d\n", rc); |
7005 | goto rw_error; | |
7006 | } | |
244c0e06 | 7007 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16)(-56), 0); |
9482354f | 7008 | if (rc != 0) { |
068e94ea MCC |
7009 | pr_err("error %d\n", rc); |
7010 | goto rw_error; | |
7011 | } | |
244c0e06 | 7012 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16)(-86), 0); |
9482354f | 7013 | if (rc != 0) { |
068e94ea MCC |
7014 | pr_err("error %d\n", rc); |
7015 | goto rw_error; | |
7016 | } | |
7017 | ||
244c0e06 | 7018 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15, 0); |
9482354f | 7019 | if (rc != 0) { |
068e94ea MCC |
7020 | pr_err("error %d\n", rc); |
7021 | goto rw_error; | |
7022 | } | |
244c0e06 | 7023 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40, 0); |
9482354f | 7024 | if (rc != 0) { |
068e94ea MCC |
7025 | pr_err("error %d\n", rc); |
7026 | goto rw_error; | |
7027 | } | |
244c0e06 | 7028 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2, 0); |
9482354f | 7029 | if (rc != 0) { |
068e94ea MCC |
7030 | pr_err("error %d\n", rc); |
7031 | goto rw_error; | |
7032 | } | |
244c0e06 | 7033 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20, 0); |
9482354f | 7034 | if (rc != 0) { |
068e94ea MCC |
7035 | pr_err("error %d\n", rc); |
7036 | goto rw_error; | |
7037 | } | |
244c0e06 | 7038 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255, 0); |
9482354f | 7039 | if (rc != 0) { |
068e94ea MCC |
7040 | pr_err("error %d\n", rc); |
7041 | goto rw_error; | |
7042 | } | |
244c0e06 | 7043 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2, 0); |
9482354f | 7044 | if (rc != 0) { |
068e94ea MCC |
7045 | pr_err("error %d\n", rc); |
7046 | goto rw_error; | |
7047 | } | |
244c0e06 | 7048 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 10, 0); |
9482354f | 7049 | if (rc != 0) { |
068e94ea MCC |
7050 | pr_err("error %d\n", rc); |
7051 | goto rw_error; | |
7052 | } | |
244c0e06 | 7053 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 50, 0); |
9482354f | 7054 | if (rc != 0) { |
068e94ea MCC |
7055 | pr_err("error %d\n", rc); |
7056 | goto rw_error; | |
7057 | } | |
244c0e06 | 7058 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12, 0); |
9482354f | 7059 | if (rc != 0) { |
068e94ea MCC |
7060 | pr_err("error %d\n", rc); |
7061 | goto rw_error; | |
7062 | } | |
244c0e06 | 7063 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24, 0); |
9482354f | 7064 | if (rc != 0) { |
068e94ea MCC |
7065 | pr_err("error %d\n", rc); |
7066 | goto rw_error; | |
7067 | } | |
244c0e06 | 7068 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24, 0); |
9482354f | 7069 | if (rc != 0) { |
068e94ea MCC |
7070 | pr_err("error %d\n", rc); |
7071 | goto rw_error; | |
7072 | } | |
244c0e06 | 7073 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12, 0); |
9482354f | 7074 | if (rc != 0) { |
068e94ea MCC |
7075 | pr_err("error %d\n", rc); |
7076 | goto rw_error; | |
7077 | } | |
244c0e06 | 7078 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16, 0); |
9482354f | 7079 | if (rc != 0) { |
068e94ea MCC |
7080 | pr_err("error %d\n", rc); |
7081 | goto rw_error; | |
7082 | } | |
244c0e06 | 7083 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16, 0); |
9482354f | 7084 | if (rc != 0) { |
068e94ea MCC |
7085 | pr_err("error %d\n", rc); |
7086 | goto rw_error; | |
7087 | } | |
244c0e06 | 7088 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16, 0); |
9482354f | 7089 | if (rc != 0) { |
068e94ea MCC |
7090 | pr_err("error %d\n", rc); |
7091 | goto rw_error; | |
7092 | } | |
244c0e06 | 7093 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 32, 0); |
9482354f | 7094 | if (rc != 0) { |
068e94ea MCC |
7095 | pr_err("error %d\n", rc); |
7096 | goto rw_error; | |
7097 | } | |
244c0e06 | 7098 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 176, 0); |
9482354f | 7099 | if (rc != 0) { |
068e94ea MCC |
7100 | pr_err("error %d\n", rc); |
7101 | goto rw_error; | |
7102 | } | |
244c0e06 | 7103 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5, 0); |
9482354f | 7104 | if (rc != 0) { |
068e94ea MCC |
7105 | pr_err("error %d\n", rc); |
7106 | goto rw_error; | |
7107 | } | |
244c0e06 | 7108 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15, 0); |
9482354f | 7109 | if (rc != 0) { |
068e94ea MCC |
7110 | pr_err("error %d\n", rc); |
7111 | goto rw_error; | |
7112 | } | |
244c0e06 | 7113 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 8, 0); |
9482354f | 7114 | if (rc != 0) { |
068e94ea MCC |
7115 | pr_err("error %d\n", rc); |
7116 | goto rw_error; | |
7117 | } | |
7118 | ||
244c0e06 | 7119 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 20480, 0); |
9482354f | 7120 | if (rc != 0) { |
068e94ea MCC |
7121 | pr_err("error %d\n", rc); |
7122 | goto rw_error; | |
7123 | } | |
443f18d0 | 7124 | |
9482354f | 7125 | return 0; |
38b2df95 | 7126 | rw_error: |
30741871 | 7127 | return rc; |
38b2df95 DH |
7128 | } |
7129 | ||
7130 | /*============================================================================*/ | |
7131 | ||
34eb9751 | 7132 | /* |
57afe2f0 | 7133 | * \fn int set_qam64 () |
38b2df95 DH |
7134 | * \brief QAM64 specific setup |
7135 | * \param demod instance of demod. | |
61263c75 | 7136 | * \return int. |
38b2df95 | 7137 | */ |
1bfc9e15 | 7138 | static int set_qam64(struct drx_demod_instance *demod) |
443f18d0 | 7139 | { |
57afe2f0 | 7140 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; |
068e94ea | 7141 | int rc; |
679cfbb1 CIK |
7142 | static const u8 qam_dq_qual_fun[] = { |
7143 | /* this is hw reset value. no necessary to re-write */ | |
443f18d0 MCC |
7144 | DRXJ_16TO8(4), /* fun0 */ |
7145 | DRXJ_16TO8(4), /* fun1 */ | |
7146 | DRXJ_16TO8(4), /* fun2 */ | |
7147 | DRXJ_16TO8(4), /* fun3 */ | |
7148 | DRXJ_16TO8(6), /* fun4 */ | |
7149 | DRXJ_16TO8(6), /* fun5 */ | |
7150 | }; | |
679cfbb1 | 7151 | static const u8 qam_eq_cma_rad[] = { |
443f18d0 MCC |
7152 | DRXJ_16TO8(13336), /* RAD0 */ |
7153 | DRXJ_16TO8(12618), /* RAD1 */ | |
7154 | DRXJ_16TO8(11988), /* RAD2 */ | |
7155 | DRXJ_16TO8(13809), /* RAD3 */ | |
7156 | DRXJ_16TO8(13809), /* RAD4 */ | |
7157 | DRXJ_16TO8(15609), /* RAD5 */ | |
7158 | }; | |
7159 | ||
244c0e06 | 7160 | rc = drxdap_fasi_write_block(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun), ((u8 *)qam_dq_qual_fun), 0); |
9482354f | 7161 | if (rc != 0) { |
068e94ea MCC |
7162 | pr_err("error %d\n", rc); |
7163 | goto rw_error; | |
7164 | } | |
244c0e06 | 7165 | rc = drxdap_fasi_write_block(dev_addr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qam_eq_cma_rad), ((u8 *)qam_eq_cma_rad), 0); |
9482354f | 7166 | if (rc != 0) { |
068e94ea MCC |
7167 | pr_err("error %d\n", rc); |
7168 | goto rw_error; | |
7169 | } | |
7170 | ||
244c0e06 | 7171 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 105, 0); |
9482354f | 7172 | if (rc != 0) { |
068e94ea MCC |
7173 | pr_err("error %d\n", rc); |
7174 | goto rw_error; | |
7175 | } | |
244c0e06 | 7176 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 60, 0); |
9482354f | 7177 | if (rc != 0) { |
068e94ea MCC |
7178 | pr_err("error %d\n", rc); |
7179 | goto rw_error; | |
7180 | } | |
244c0e06 | 7181 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 100, 0); |
9482354f | 7182 | if (rc != 0) { |
068e94ea MCC |
7183 | pr_err("error %d\n", rc); |
7184 | goto rw_error; | |
7185 | } | |
244c0e06 | 7186 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 195, 0); |
9482354f | 7187 | if (rc != 0) { |
068e94ea MCC |
7188 | pr_err("error %d\n", rc); |
7189 | goto rw_error; | |
7190 | } | |
244c0e06 | 7191 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 80, 0); |
9482354f | 7192 | if (rc != 0) { |
068e94ea MCC |
7193 | pr_err("error %d\n", rc); |
7194 | goto rw_error; | |
7195 | } | |
244c0e06 | 7196 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 84, 0); |
9482354f | 7197 | if (rc != 0) { |
068e94ea MCC |
7198 | pr_err("error %d\n", rc); |
7199 | goto rw_error; | |
7200 | } | |
7201 | ||
244c0e06 | 7202 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40, 0); |
9482354f | 7203 | if (rc != 0) { |
068e94ea MCC |
7204 | pr_err("error %d\n", rc); |
7205 | goto rw_error; | |
7206 | } | |
244c0e06 | 7207 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 32, 0); |
9482354f | 7208 | if (rc != 0) { |
068e94ea MCC |
7209 | pr_err("error %d\n", rc); |
7210 | goto rw_error; | |
7211 | } | |
244c0e06 | 7212 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3, 0); |
9482354f | 7213 | if (rc != 0) { |
068e94ea MCC |
7214 | pr_err("error %d\n", rc); |
7215 | goto rw_error; | |
7216 | } | |
7217 | ||
244c0e06 | 7218 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 12, 0); |
9482354f | 7219 | if (rc != 0) { |
068e94ea MCC |
7220 | pr_err("error %d\n", rc); |
7221 | goto rw_error; | |
7222 | } | |
244c0e06 | 7223 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 141, 0); |
9482354f | 7224 | if (rc != 0) { |
068e94ea MCC |
7225 | pr_err("error %d\n", rc); |
7226 | goto rw_error; | |
7227 | } | |
244c0e06 | 7228 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 7, 0); |
9482354f | 7229 | if (rc != 0) { |
068e94ea MCC |
7230 | pr_err("error %d\n", rc); |
7231 | goto rw_error; | |
7232 | } | |
244c0e06 | 7233 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 0, 0); |
9482354f | 7234 | if (rc != 0) { |
068e94ea MCC |
7235 | pr_err("error %d\n", rc); |
7236 | goto rw_error; | |
7237 | } | |
244c0e06 | 7238 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16)(-15), 0); |
9482354f | 7239 | if (rc != 0) { |
068e94ea MCC |
7240 | pr_err("error %d\n", rc); |
7241 | goto rw_error; | |
7242 | } | |
244c0e06 | 7243 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16)(-45), 0); |
9482354f | 7244 | if (rc != 0) { |
068e94ea MCC |
7245 | pr_err("error %d\n", rc); |
7246 | goto rw_error; | |
7247 | } | |
244c0e06 | 7248 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16)(-80), 0); |
9482354f | 7249 | if (rc != 0) { |
068e94ea MCC |
7250 | pr_err("error %d\n", rc); |
7251 | goto rw_error; | |
7252 | } | |
7253 | ||
244c0e06 | 7254 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15, 0); |
9482354f | 7255 | if (rc != 0) { |
068e94ea MCC |
7256 | pr_err("error %d\n", rc); |
7257 | goto rw_error; | |
7258 | } | |
244c0e06 | 7259 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40, 0); |
9482354f | 7260 | if (rc != 0) { |
068e94ea MCC |
7261 | pr_err("error %d\n", rc); |
7262 | goto rw_error; | |
7263 | } | |
244c0e06 | 7264 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2, 0); |
9482354f | 7265 | if (rc != 0) { |
068e94ea MCC |
7266 | pr_err("error %d\n", rc); |
7267 | goto rw_error; | |
7268 | } | |
244c0e06 | 7269 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 30, 0); |
9482354f | 7270 | if (rc != 0) { |
068e94ea MCC |
7271 | pr_err("error %d\n", rc); |
7272 | goto rw_error; | |
7273 | } | |
244c0e06 | 7274 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255, 0); |
9482354f | 7275 | if (rc != 0) { |
068e94ea MCC |
7276 | pr_err("error %d\n", rc); |
7277 | goto rw_error; | |
7278 | } | |
244c0e06 | 7279 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2, 0); |
9482354f | 7280 | if (rc != 0) { |
068e94ea MCC |
7281 | pr_err("error %d\n", rc); |
7282 | goto rw_error; | |
7283 | } | |
244c0e06 | 7284 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 15, 0); |
9482354f | 7285 | if (rc != 0) { |
068e94ea MCC |
7286 | pr_err("error %d\n", rc); |
7287 | goto rw_error; | |
7288 | } | |
244c0e06 | 7289 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 80, 0); |
9482354f | 7290 | if (rc != 0) { |
068e94ea MCC |
7291 | pr_err("error %d\n", rc); |
7292 | goto rw_error; | |
7293 | } | |
244c0e06 | 7294 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12, 0); |
9482354f | 7295 | if (rc != 0) { |
068e94ea MCC |
7296 | pr_err("error %d\n", rc); |
7297 | goto rw_error; | |
7298 | } | |
244c0e06 | 7299 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24, 0); |
9482354f | 7300 | if (rc != 0) { |
068e94ea MCC |
7301 | pr_err("error %d\n", rc); |
7302 | goto rw_error; | |
7303 | } | |
244c0e06 | 7304 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24, 0); |
9482354f | 7305 | if (rc != 0) { |
068e94ea MCC |
7306 | pr_err("error %d\n", rc); |
7307 | goto rw_error; | |
7308 | } | |
244c0e06 | 7309 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12, 0); |
9482354f | 7310 | if (rc != 0) { |
068e94ea MCC |
7311 | pr_err("error %d\n", rc); |
7312 | goto rw_error; | |
7313 | } | |
244c0e06 | 7314 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16, 0); |
9482354f | 7315 | if (rc != 0) { |
068e94ea MCC |
7316 | pr_err("error %d\n", rc); |
7317 | goto rw_error; | |
7318 | } | |
244c0e06 | 7319 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16, 0); |
9482354f | 7320 | if (rc != 0) { |
068e94ea MCC |
7321 | pr_err("error %d\n", rc); |
7322 | goto rw_error; | |
7323 | } | |
244c0e06 | 7324 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16, 0); |
9482354f | 7325 | if (rc != 0) { |
068e94ea MCC |
7326 | pr_err("error %d\n", rc); |
7327 | goto rw_error; | |
7328 | } | |
244c0e06 | 7329 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 48, 0); |
9482354f | 7330 | if (rc != 0) { |
068e94ea MCC |
7331 | pr_err("error %d\n", rc); |
7332 | goto rw_error; | |
7333 | } | |
244c0e06 | 7334 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 160, 0); |
9482354f | 7335 | if (rc != 0) { |
068e94ea MCC |
7336 | pr_err("error %d\n", rc); |
7337 | goto rw_error; | |
7338 | } | |
244c0e06 | 7339 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5, 0); |
9482354f | 7340 | if (rc != 0) { |
068e94ea MCC |
7341 | pr_err("error %d\n", rc); |
7342 | goto rw_error; | |
7343 | } | |
244c0e06 | 7344 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15, 0); |
9482354f | 7345 | if (rc != 0) { |
068e94ea MCC |
7346 | pr_err("error %d\n", rc); |
7347 | goto rw_error; | |
7348 | } | |
244c0e06 | 7349 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 32, 0); |
9482354f | 7350 | if (rc != 0) { |
068e94ea MCC |
7351 | pr_err("error %d\n", rc); |
7352 | goto rw_error; | |
7353 | } | |
7354 | ||
244c0e06 | 7355 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 43008, 0); |
9482354f | 7356 | if (rc != 0) { |
068e94ea MCC |
7357 | pr_err("error %d\n", rc); |
7358 | goto rw_error; | |
7359 | } | |
443f18d0 | 7360 | |
9482354f | 7361 | return 0; |
38b2df95 | 7362 | rw_error: |
30741871 | 7363 | return rc; |
38b2df95 DH |
7364 | } |
7365 | ||
7366 | /*============================================================================*/ | |
7367 | ||
34eb9751 | 7368 | /* |
57afe2f0 | 7369 | * \fn int set_qam128 () |
38b2df95 DH |
7370 | * \brief QAM128 specific setup |
7371 | * \param demod: instance of demod. | |
61263c75 | 7372 | * \return int. |
38b2df95 | 7373 | */ |
1bfc9e15 | 7374 | static int set_qam128(struct drx_demod_instance *demod) |
443f18d0 | 7375 | { |
57afe2f0 | 7376 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; |
068e94ea | 7377 | int rc; |
679cfbb1 | 7378 | static const u8 qam_dq_qual_fun[] = { |
443f18d0 MCC |
7379 | DRXJ_16TO8(6), /* fun0 */ |
7380 | DRXJ_16TO8(6), /* fun1 */ | |
7381 | DRXJ_16TO8(6), /* fun2 */ | |
7382 | DRXJ_16TO8(6), /* fun3 */ | |
7383 | DRXJ_16TO8(9), /* fun4 */ | |
7384 | DRXJ_16TO8(9), /* fun5 */ | |
7385 | }; | |
679cfbb1 | 7386 | static const u8 qam_eq_cma_rad[] = { |
443f18d0 MCC |
7387 | DRXJ_16TO8(6164), /* RAD0 */ |
7388 | DRXJ_16TO8(6598), /* RAD1 */ | |
7389 | DRXJ_16TO8(6394), /* RAD2 */ | |
7390 | DRXJ_16TO8(6409), /* RAD3 */ | |
7391 | DRXJ_16TO8(6656), /* RAD4 */ | |
7392 | DRXJ_16TO8(7238), /* RAD5 */ | |
7393 | }; | |
7394 | ||
244c0e06 | 7395 | rc = drxdap_fasi_write_block(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun), ((u8 *)qam_dq_qual_fun), 0); |
9482354f | 7396 | if (rc != 0) { |
068e94ea MCC |
7397 | pr_err("error %d\n", rc); |
7398 | goto rw_error; | |
7399 | } | |
244c0e06 | 7400 | rc = drxdap_fasi_write_block(dev_addr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qam_eq_cma_rad), ((u8 *)qam_eq_cma_rad), 0); |
9482354f | 7401 | if (rc != 0) { |
068e94ea MCC |
7402 | pr_err("error %d\n", rc); |
7403 | goto rw_error; | |
7404 | } | |
7405 | ||
244c0e06 | 7406 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 50, 0); |
9482354f | 7407 | if (rc != 0) { |
068e94ea MCC |
7408 | pr_err("error %d\n", rc); |
7409 | goto rw_error; | |
7410 | } | |
244c0e06 | 7411 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 60, 0); |
9482354f | 7412 | if (rc != 0) { |
068e94ea MCC |
7413 | pr_err("error %d\n", rc); |
7414 | goto rw_error; | |
7415 | } | |
244c0e06 | 7416 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 100, 0); |
9482354f | 7417 | if (rc != 0) { |
068e94ea MCC |
7418 | pr_err("error %d\n", rc); |
7419 | goto rw_error; | |
7420 | } | |
244c0e06 | 7421 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 140, 0); |
9482354f | 7422 | if (rc != 0) { |
068e94ea MCC |
7423 | pr_err("error %d\n", rc); |
7424 | goto rw_error; | |
7425 | } | |
244c0e06 | 7426 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 80, 0); |
9482354f | 7427 | if (rc != 0) { |
068e94ea MCC |
7428 | pr_err("error %d\n", rc); |
7429 | goto rw_error; | |
7430 | } | |
244c0e06 | 7431 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 100, 0); |
9482354f | 7432 | if (rc != 0) { |
068e94ea MCC |
7433 | pr_err("error %d\n", rc); |
7434 | goto rw_error; | |
7435 | } | |
7436 | ||
244c0e06 | 7437 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40, 0); |
9482354f | 7438 | if (rc != 0) { |
068e94ea MCC |
7439 | pr_err("error %d\n", rc); |
7440 | goto rw_error; | |
7441 | } | |
244c0e06 | 7442 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 32, 0); |
9482354f | 7443 | if (rc != 0) { |
068e94ea MCC |
7444 | pr_err("error %d\n", rc); |
7445 | goto rw_error; | |
7446 | } | |
244c0e06 | 7447 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3, 0); |
9482354f | 7448 | if (rc != 0) { |
068e94ea MCC |
7449 | pr_err("error %d\n", rc); |
7450 | goto rw_error; | |
7451 | } | |
7452 | ||
244c0e06 | 7453 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 8, 0); |
9482354f | 7454 | if (rc != 0) { |
068e94ea MCC |
7455 | pr_err("error %d\n", rc); |
7456 | goto rw_error; | |
7457 | } | |
244c0e06 | 7458 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 65, 0); |
9482354f | 7459 | if (rc != 0) { |
068e94ea MCC |
7460 | pr_err("error %d\n", rc); |
7461 | goto rw_error; | |
7462 | } | |
244c0e06 | 7463 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 5, 0); |
9482354f | 7464 | if (rc != 0) { |
068e94ea MCC |
7465 | pr_err("error %d\n", rc); |
7466 | goto rw_error; | |
7467 | } | |
244c0e06 | 7468 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 3, 0); |
9482354f | 7469 | if (rc != 0) { |
068e94ea MCC |
7470 | pr_err("error %d\n", rc); |
7471 | goto rw_error; | |
7472 | } | |
244c0e06 | 7473 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16)(-1), 0); |
9482354f | 7474 | if (rc != 0) { |
068e94ea MCC |
7475 | pr_err("error %d\n", rc); |
7476 | goto rw_error; | |
7477 | } | |
244c0e06 | 7478 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, 12, 0); |
9482354f | 7479 | if (rc != 0) { |
068e94ea MCC |
7480 | pr_err("error %d\n", rc); |
7481 | goto rw_error; | |
7482 | } | |
244c0e06 | 7483 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16)(-23), 0); |
9482354f | 7484 | if (rc != 0) { |
068e94ea MCC |
7485 | pr_err("error %d\n", rc); |
7486 | goto rw_error; | |
7487 | } | |
7488 | ||
244c0e06 | 7489 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15, 0); |
9482354f | 7490 | if (rc != 0) { |
068e94ea MCC |
7491 | pr_err("error %d\n", rc); |
7492 | goto rw_error; | |
7493 | } | |
244c0e06 | 7494 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40, 0); |
9482354f | 7495 | if (rc != 0) { |
068e94ea MCC |
7496 | pr_err("error %d\n", rc); |
7497 | goto rw_error; | |
7498 | } | |
244c0e06 | 7499 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2, 0); |
9482354f | 7500 | if (rc != 0) { |
068e94ea MCC |
7501 | pr_err("error %d\n", rc); |
7502 | goto rw_error; | |
7503 | } | |
244c0e06 | 7504 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 40, 0); |
9482354f | 7505 | if (rc != 0) { |
068e94ea MCC |
7506 | pr_err("error %d\n", rc); |
7507 | goto rw_error; | |
7508 | } | |
244c0e06 | 7509 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255, 0); |
9482354f | 7510 | if (rc != 0) { |
068e94ea MCC |
7511 | pr_err("error %d\n", rc); |
7512 | goto rw_error; | |
7513 | } | |
244c0e06 | 7514 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2, 0); |
9482354f | 7515 | if (rc != 0) { |
068e94ea MCC |
7516 | pr_err("error %d\n", rc); |
7517 | goto rw_error; | |
7518 | } | |
244c0e06 | 7519 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 20, 0); |
9482354f | 7520 | if (rc != 0) { |
068e94ea MCC |
7521 | pr_err("error %d\n", rc); |
7522 | goto rw_error; | |
7523 | } | |
244c0e06 | 7524 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 80, 0); |
9482354f | 7525 | if (rc != 0) { |
068e94ea MCC |
7526 | pr_err("error %d\n", rc); |
7527 | goto rw_error; | |
7528 | } | |
244c0e06 | 7529 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12, 0); |
9482354f | 7530 | if (rc != 0) { |
068e94ea MCC |
7531 | pr_err("error %d\n", rc); |
7532 | goto rw_error; | |
7533 | } | |
244c0e06 | 7534 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24, 0); |
9482354f | 7535 | if (rc != 0) { |
068e94ea MCC |
7536 | pr_err("error %d\n", rc); |
7537 | goto rw_error; | |
7538 | } | |
244c0e06 | 7539 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24, 0); |
9482354f | 7540 | if (rc != 0) { |
068e94ea MCC |
7541 | pr_err("error %d\n", rc); |
7542 | goto rw_error; | |
7543 | } | |
244c0e06 | 7544 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12, 0); |
9482354f | 7545 | if (rc != 0) { |
068e94ea MCC |
7546 | pr_err("error %d\n", rc); |
7547 | goto rw_error; | |
7548 | } | |
244c0e06 | 7549 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16, 0); |
9482354f | 7550 | if (rc != 0) { |
068e94ea MCC |
7551 | pr_err("error %d\n", rc); |
7552 | goto rw_error; | |
7553 | } | |
244c0e06 | 7554 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16, 0); |
9482354f | 7555 | if (rc != 0) { |
068e94ea MCC |
7556 | pr_err("error %d\n", rc); |
7557 | goto rw_error; | |
7558 | } | |
244c0e06 | 7559 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16, 0); |
9482354f | 7560 | if (rc != 0) { |
068e94ea MCC |
7561 | pr_err("error %d\n", rc); |
7562 | goto rw_error; | |
7563 | } | |
244c0e06 | 7564 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 32, 0); |
9482354f | 7565 | if (rc != 0) { |
068e94ea MCC |
7566 | pr_err("error %d\n", rc); |
7567 | goto rw_error; | |
7568 | } | |
244c0e06 | 7569 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 144, 0); |
9482354f | 7570 | if (rc != 0) { |
068e94ea MCC |
7571 | pr_err("error %d\n", rc); |
7572 | goto rw_error; | |
7573 | } | |
244c0e06 | 7574 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5, 0); |
9482354f | 7575 | if (rc != 0) { |
068e94ea MCC |
7576 | pr_err("error %d\n", rc); |
7577 | goto rw_error; | |
7578 | } | |
244c0e06 | 7579 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15, 0); |
9482354f | 7580 | if (rc != 0) { |
068e94ea MCC |
7581 | pr_err("error %d\n", rc); |
7582 | goto rw_error; | |
7583 | } | |
244c0e06 | 7584 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 16, 0); |
9482354f | 7585 | if (rc != 0) { |
068e94ea MCC |
7586 | pr_err("error %d\n", rc); |
7587 | goto rw_error; | |
7588 | } | |
7589 | ||
244c0e06 | 7590 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 20992, 0); |
9482354f | 7591 | if (rc != 0) { |
068e94ea MCC |
7592 | pr_err("error %d\n", rc); |
7593 | goto rw_error; | |
7594 | } | |
443f18d0 | 7595 | |
9482354f | 7596 | return 0; |
38b2df95 | 7597 | rw_error: |
30741871 | 7598 | return rc; |
38b2df95 DH |
7599 | } |
7600 | ||
7601 | /*============================================================================*/ | |
7602 | ||
34eb9751 | 7603 | /* |
57afe2f0 | 7604 | * \fn int set_qam256 () |
38b2df95 DH |
7605 | * \brief QAM256 specific setup |
7606 | * \param demod: instance of demod. | |
61263c75 | 7607 | * \return int. |
38b2df95 | 7608 | */ |
1bfc9e15 | 7609 | static int set_qam256(struct drx_demod_instance *demod) |
443f18d0 | 7610 | { |
57afe2f0 | 7611 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; |
068e94ea | 7612 | int rc; |
679cfbb1 | 7613 | static const u8 qam_dq_qual_fun[] = { |
443f18d0 MCC |
7614 | DRXJ_16TO8(8), /* fun0 */ |
7615 | DRXJ_16TO8(8), /* fun1 */ | |
7616 | DRXJ_16TO8(8), /* fun2 */ | |
7617 | DRXJ_16TO8(8), /* fun3 */ | |
7618 | DRXJ_16TO8(12), /* fun4 */ | |
7619 | DRXJ_16TO8(12), /* fun5 */ | |
7620 | }; | |
679cfbb1 | 7621 | static const u8 qam_eq_cma_rad[] = { |
443f18d0 MCC |
7622 | DRXJ_16TO8(12345), /* RAD0 */ |
7623 | DRXJ_16TO8(12345), /* RAD1 */ | |
7624 | DRXJ_16TO8(13626), /* RAD2 */ | |
7625 | DRXJ_16TO8(12931), /* RAD3 */ | |
7626 | DRXJ_16TO8(14719), /* RAD4 */ | |
7627 | DRXJ_16TO8(15356), /* RAD5 */ | |
7628 | }; | |
7629 | ||
244c0e06 | 7630 | rc = drxdap_fasi_write_block(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun), ((u8 *)qam_dq_qual_fun), 0); |
9482354f | 7631 | if (rc != 0) { |
068e94ea MCC |
7632 | pr_err("error %d\n", rc); |
7633 | goto rw_error; | |
7634 | } | |
244c0e06 | 7635 | rc = drxdap_fasi_write_block(dev_addr, SCU_RAM_QAM_EQ_CMA_RAD0__A, sizeof(qam_eq_cma_rad), ((u8 *)qam_eq_cma_rad), 0); |
9482354f | 7636 | if (rc != 0) { |
068e94ea MCC |
7637 | pr_err("error %d\n", rc); |
7638 | goto rw_error; | |
7639 | } | |
7640 | ||
244c0e06 | 7641 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 50, 0); |
9482354f | 7642 | if (rc != 0) { |
068e94ea MCC |
7643 | pr_err("error %d\n", rc); |
7644 | goto rw_error; | |
7645 | } | |
244c0e06 | 7646 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 60, 0); |
9482354f | 7647 | if (rc != 0) { |
068e94ea MCC |
7648 | pr_err("error %d\n", rc); |
7649 | goto rw_error; | |
7650 | } | |
244c0e06 | 7651 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 100, 0); |
9482354f | 7652 | if (rc != 0) { |
068e94ea MCC |
7653 | pr_err("error %d\n", rc); |
7654 | goto rw_error; | |
7655 | } | |
244c0e06 | 7656 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 150, 0); |
9482354f | 7657 | if (rc != 0) { |
068e94ea MCC |
7658 | pr_err("error %d\n", rc); |
7659 | goto rw_error; | |
7660 | } | |
244c0e06 | 7661 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 80, 0); |
9482354f | 7662 | if (rc != 0) { |
068e94ea MCC |
7663 | pr_err("error %d\n", rc); |
7664 | goto rw_error; | |
7665 | } | |
244c0e06 | 7666 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 110, 0); |
9482354f | 7667 | if (rc != 0) { |
068e94ea MCC |
7668 | pr_err("error %d\n", rc); |
7669 | goto rw_error; | |
7670 | } | |
7671 | ||
244c0e06 | 7672 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40, 0); |
9482354f | 7673 | if (rc != 0) { |
068e94ea MCC |
7674 | pr_err("error %d\n", rc); |
7675 | goto rw_error; | |
7676 | } | |
244c0e06 | 7677 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 16, 0); |
9482354f | 7678 | if (rc != 0) { |
068e94ea MCC |
7679 | pr_err("error %d\n", rc); |
7680 | goto rw_error; | |
7681 | } | |
244c0e06 | 7682 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3, 0); |
9482354f | 7683 | if (rc != 0) { |
068e94ea MCC |
7684 | pr_err("error %d\n", rc); |
7685 | goto rw_error; | |
7686 | } | |
7687 | ||
244c0e06 | 7688 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 8, 0); |
9482354f | 7689 | if (rc != 0) { |
068e94ea MCC |
7690 | pr_err("error %d\n", rc); |
7691 | goto rw_error; | |
7692 | } | |
244c0e06 | 7693 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 74, 0); |
9482354f | 7694 | if (rc != 0) { |
068e94ea MCC |
7695 | pr_err("error %d\n", rc); |
7696 | goto rw_error; | |
7697 | } | |
244c0e06 | 7698 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 18, 0); |
9482354f | 7699 | if (rc != 0) { |
068e94ea MCC |
7700 | pr_err("error %d\n", rc); |
7701 | goto rw_error; | |
7702 | } | |
244c0e06 | 7703 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 13, 0); |
9482354f | 7704 | if (rc != 0) { |
068e94ea MCC |
7705 | pr_err("error %d\n", rc); |
7706 | goto rw_error; | |
7707 | } | |
244c0e06 | 7708 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, 7, 0); |
9482354f | 7709 | if (rc != 0) { |
068e94ea MCC |
7710 | pr_err("error %d\n", rc); |
7711 | goto rw_error; | |
7712 | } | |
244c0e06 | 7713 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, 0, 0); |
9482354f | 7714 | if (rc != 0) { |
068e94ea MCC |
7715 | pr_err("error %d\n", rc); |
7716 | goto rw_error; | |
7717 | } | |
244c0e06 | 7718 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16)(-8), 0); |
9482354f | 7719 | if (rc != 0) { |
068e94ea MCC |
7720 | pr_err("error %d\n", rc); |
7721 | goto rw_error; | |
7722 | } | |
7723 | ||
244c0e06 | 7724 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15, 0); |
9482354f | 7725 | if (rc != 0) { |
068e94ea MCC |
7726 | pr_err("error %d\n", rc); |
7727 | goto rw_error; | |
7728 | } | |
244c0e06 | 7729 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40, 0); |
9482354f | 7730 | if (rc != 0) { |
068e94ea MCC |
7731 | pr_err("error %d\n", rc); |
7732 | goto rw_error; | |
7733 | } | |
244c0e06 | 7734 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2, 0); |
9482354f | 7735 | if (rc != 0) { |
068e94ea MCC |
7736 | pr_err("error %d\n", rc); |
7737 | goto rw_error; | |
7738 | } | |
244c0e06 | 7739 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 50, 0); |
9482354f | 7740 | if (rc != 0) { |
068e94ea MCC |
7741 | pr_err("error %d\n", rc); |
7742 | goto rw_error; | |
7743 | } | |
244c0e06 | 7744 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255, 0); |
9482354f | 7745 | if (rc != 0) { |
068e94ea MCC |
7746 | pr_err("error %d\n", rc); |
7747 | goto rw_error; | |
7748 | } | |
244c0e06 | 7749 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2, 0); |
9482354f | 7750 | if (rc != 0) { |
068e94ea MCC |
7751 | pr_err("error %d\n", rc); |
7752 | goto rw_error; | |
7753 | } | |
244c0e06 | 7754 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 25, 0); |
9482354f | 7755 | if (rc != 0) { |
068e94ea MCC |
7756 | pr_err("error %d\n", rc); |
7757 | goto rw_error; | |
7758 | } | |
244c0e06 | 7759 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 80, 0); |
9482354f | 7760 | if (rc != 0) { |
068e94ea MCC |
7761 | pr_err("error %d\n", rc); |
7762 | goto rw_error; | |
7763 | } | |
244c0e06 | 7764 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12, 0); |
9482354f | 7765 | if (rc != 0) { |
068e94ea MCC |
7766 | pr_err("error %d\n", rc); |
7767 | goto rw_error; | |
7768 | } | |
244c0e06 | 7769 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24, 0); |
9482354f | 7770 | if (rc != 0) { |
068e94ea MCC |
7771 | pr_err("error %d\n", rc); |
7772 | goto rw_error; | |
7773 | } | |
244c0e06 | 7774 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24, 0); |
9482354f | 7775 | if (rc != 0) { |
068e94ea MCC |
7776 | pr_err("error %d\n", rc); |
7777 | goto rw_error; | |
7778 | } | |
244c0e06 | 7779 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12, 0); |
9482354f | 7780 | if (rc != 0) { |
068e94ea MCC |
7781 | pr_err("error %d\n", rc); |
7782 | goto rw_error; | |
7783 | } | |
244c0e06 | 7784 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16, 0); |
9482354f | 7785 | if (rc != 0) { |
068e94ea MCC |
7786 | pr_err("error %d\n", rc); |
7787 | goto rw_error; | |
7788 | } | |
244c0e06 | 7789 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16, 0); |
9482354f | 7790 | if (rc != 0) { |
068e94ea MCC |
7791 | pr_err("error %d\n", rc); |
7792 | goto rw_error; | |
7793 | } | |
244c0e06 | 7794 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16, 0); |
9482354f | 7795 | if (rc != 0) { |
068e94ea MCC |
7796 | pr_err("error %d\n", rc); |
7797 | goto rw_error; | |
7798 | } | |
244c0e06 | 7799 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 48, 0); |
9482354f | 7800 | if (rc != 0) { |
068e94ea MCC |
7801 | pr_err("error %d\n", rc); |
7802 | goto rw_error; | |
7803 | } | |
244c0e06 | 7804 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 80, 0); |
9482354f | 7805 | if (rc != 0) { |
068e94ea MCC |
7806 | pr_err("error %d\n", rc); |
7807 | goto rw_error; | |
7808 | } | |
244c0e06 | 7809 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5, 0); |
9482354f | 7810 | if (rc != 0) { |
068e94ea MCC |
7811 | pr_err("error %d\n", rc); |
7812 | goto rw_error; | |
7813 | } | |
244c0e06 | 7814 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15, 0); |
9482354f | 7815 | if (rc != 0) { |
068e94ea MCC |
7816 | pr_err("error %d\n", rc); |
7817 | goto rw_error; | |
7818 | } | |
244c0e06 | 7819 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 16, 0); |
9482354f | 7820 | if (rc != 0) { |
068e94ea MCC |
7821 | pr_err("error %d\n", rc); |
7822 | goto rw_error; | |
7823 | } | |
7824 | ||
244c0e06 | 7825 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 43520, 0); |
9482354f | 7826 | if (rc != 0) { |
068e94ea MCC |
7827 | pr_err("error %d\n", rc); |
7828 | goto rw_error; | |
7829 | } | |
443f18d0 | 7830 | |
9482354f | 7831 | return 0; |
38b2df95 | 7832 | rw_error: |
30741871 | 7833 | return rc; |
38b2df95 DH |
7834 | } |
7835 | ||
7836 | /*============================================================================*/ | |
7837 | #define QAM_SET_OP_ALL 0x1 | |
7838 | #define QAM_SET_OP_CONSTELLATION 0x2 | |
7839 | #define QAM_SET_OP_SPECTRUM 0X4 | |
7840 | ||
34eb9751 | 7841 | /* |
57afe2f0 | 7842 | * \fn int set_qam () |
38b2df95 DH |
7843 | * \brief Set QAM demod. |
7844 | * \param demod: instance of demod. | |
7845 | * \param channel: pointer to channel data. | |
61263c75 | 7846 | * \return int. |
38b2df95 | 7847 | */ |
61263c75 | 7848 | static int |
1bfc9e15 MCC |
7849 | set_qam(struct drx_demod_instance *demod, |
7850 | struct drx_channel *channel, s32 tuner_freq_offset, u32 op) | |
57afe2f0 MCC |
7851 | { |
7852 | struct i2c_device_addr *dev_addr = NULL; | |
b3ce3a83 | 7853 | struct drxj_data *ext_attr = NULL; |
1bfc9e15 | 7854 | struct drx_common_attr *common_attr = NULL; |
068e94ea | 7855 | int rc; |
57afe2f0 MCC |
7856 | u32 adc_frequency = 0; |
7857 | u32 iqm_rc_rate = 0; | |
068e94ea | 7858 | u16 cmd_result = 0; |
57afe2f0 MCC |
7859 | u16 lc_symbol_freq = 0; |
7860 | u16 iqm_rc_stretch = 0; | |
7861 | u16 set_env_parameters = 0; | |
7862 | u16 set_param_parameters[2] = { 0 }; | |
b3ce3a83 | 7863 | struct drxjscu_cmd cmd_scu = { /* command */ 0, |
57afe2f0 MCC |
7864 | /* parameter_len */ 0, |
7865 | /* result_len */ 0, | |
443f18d0 MCC |
7866 | /* parameter */ NULL, |
7867 | /* result */ NULL | |
7868 | }; | |
679cfbb1 | 7869 | static const u8 qam_a_taps[] = { |
443f18d0 MCC |
7870 | DRXJ_16TO8(-1), /* re0 */ |
7871 | DRXJ_16TO8(1), /* re1 */ | |
7872 | DRXJ_16TO8(1), /* re2 */ | |
7873 | DRXJ_16TO8(-1), /* re3 */ | |
7874 | DRXJ_16TO8(-1), /* re4 */ | |
7875 | DRXJ_16TO8(2), /* re5 */ | |
7876 | DRXJ_16TO8(1), /* re6 */ | |
7877 | DRXJ_16TO8(-2), /* re7 */ | |
7878 | DRXJ_16TO8(0), /* re8 */ | |
7879 | DRXJ_16TO8(3), /* re9 */ | |
7880 | DRXJ_16TO8(-1), /* re10 */ | |
7881 | DRXJ_16TO8(-3), /* re11 */ | |
7882 | DRXJ_16TO8(4), /* re12 */ | |
7883 | DRXJ_16TO8(1), /* re13 */ | |
7884 | DRXJ_16TO8(-8), /* re14 */ | |
7885 | DRXJ_16TO8(4), /* re15 */ | |
7886 | DRXJ_16TO8(13), /* re16 */ | |
7887 | DRXJ_16TO8(-13), /* re17 */ | |
7888 | DRXJ_16TO8(-19), /* re18 */ | |
7889 | DRXJ_16TO8(28), /* re19 */ | |
7890 | DRXJ_16TO8(25), /* re20 */ | |
7891 | DRXJ_16TO8(-53), /* re21 */ | |
7892 | DRXJ_16TO8(-31), /* re22 */ | |
7893 | DRXJ_16TO8(96), /* re23 */ | |
7894 | DRXJ_16TO8(37), /* re24 */ | |
7895 | DRXJ_16TO8(-190), /* re25 */ | |
7896 | DRXJ_16TO8(-40), /* re26 */ | |
7897 | DRXJ_16TO8(619) /* re27 */ | |
7898 | }; | |
679cfbb1 | 7899 | static const u8 qam_b64_taps[] = { |
443f18d0 MCC |
7900 | DRXJ_16TO8(0), /* re0 */ |
7901 | DRXJ_16TO8(-2), /* re1 */ | |
7902 | DRXJ_16TO8(1), /* re2 */ | |
7903 | DRXJ_16TO8(2), /* re3 */ | |
7904 | DRXJ_16TO8(-2), /* re4 */ | |
7905 | DRXJ_16TO8(0), /* re5 */ | |
7906 | DRXJ_16TO8(4), /* re6 */ | |
7907 | DRXJ_16TO8(-2), /* re7 */ | |
7908 | DRXJ_16TO8(-4), /* re8 */ | |
7909 | DRXJ_16TO8(4), /* re9 */ | |
7910 | DRXJ_16TO8(3), /* re10 */ | |
7911 | DRXJ_16TO8(-6), /* re11 */ | |
7912 | DRXJ_16TO8(0), /* re12 */ | |
7913 | DRXJ_16TO8(6), /* re13 */ | |
7914 | DRXJ_16TO8(-5), /* re14 */ | |
7915 | DRXJ_16TO8(-3), /* re15 */ | |
7916 | DRXJ_16TO8(11), /* re16 */ | |
7917 | DRXJ_16TO8(-4), /* re17 */ | |
7918 | DRXJ_16TO8(-19), /* re18 */ | |
7919 | DRXJ_16TO8(19), /* re19 */ | |
7920 | DRXJ_16TO8(28), /* re20 */ | |
7921 | DRXJ_16TO8(-45), /* re21 */ | |
7922 | DRXJ_16TO8(-36), /* re22 */ | |
7923 | DRXJ_16TO8(90), /* re23 */ | |
7924 | DRXJ_16TO8(42), /* re24 */ | |
7925 | DRXJ_16TO8(-185), /* re25 */ | |
7926 | DRXJ_16TO8(-46), /* re26 */ | |
7927 | DRXJ_16TO8(614) /* re27 */ | |
7928 | }; | |
679cfbb1 | 7929 | static const u8 qam_b256_taps[] = { |
443f18d0 MCC |
7930 | DRXJ_16TO8(-2), /* re0 */ |
7931 | DRXJ_16TO8(4), /* re1 */ | |
7932 | DRXJ_16TO8(1), /* re2 */ | |
7933 | DRXJ_16TO8(-4), /* re3 */ | |
7934 | DRXJ_16TO8(0), /* re4 */ | |
7935 | DRXJ_16TO8(4), /* re5 */ | |
7936 | DRXJ_16TO8(-2), /* re6 */ | |
7937 | DRXJ_16TO8(-4), /* re7 */ | |
7938 | DRXJ_16TO8(5), /* re8 */ | |
7939 | DRXJ_16TO8(2), /* re9 */ | |
7940 | DRXJ_16TO8(-8), /* re10 */ | |
7941 | DRXJ_16TO8(2), /* re11 */ | |
7942 | DRXJ_16TO8(11), /* re12 */ | |
7943 | DRXJ_16TO8(-8), /* re13 */ | |
7944 | DRXJ_16TO8(-15), /* re14 */ | |
7945 | DRXJ_16TO8(16), /* re15 */ | |
7946 | DRXJ_16TO8(19), /* re16 */ | |
7947 | DRXJ_16TO8(-27), /* re17 */ | |
7948 | DRXJ_16TO8(-22), /* re18 */ | |
7949 | DRXJ_16TO8(44), /* re19 */ | |
7950 | DRXJ_16TO8(26), /* re20 */ | |
7951 | DRXJ_16TO8(-69), /* re21 */ | |
7952 | DRXJ_16TO8(-28), /* re22 */ | |
7953 | DRXJ_16TO8(110), /* re23 */ | |
7954 | DRXJ_16TO8(31), /* re24 */ | |
7955 | DRXJ_16TO8(-201), /* re25 */ | |
7956 | DRXJ_16TO8(-32), /* re26 */ | |
7957 | DRXJ_16TO8(628) /* re27 */ | |
7958 | }; | |
679cfbb1 | 7959 | static const u8 qam_c_taps[] = { |
443f18d0 MCC |
7960 | DRXJ_16TO8(-3), /* re0 */ |
7961 | DRXJ_16TO8(3), /* re1 */ | |
7962 | DRXJ_16TO8(2), /* re2 */ | |
7963 | DRXJ_16TO8(-4), /* re3 */ | |
7964 | DRXJ_16TO8(0), /* re4 */ | |
7965 | DRXJ_16TO8(4), /* re5 */ | |
7966 | DRXJ_16TO8(-1), /* re6 */ | |
7967 | DRXJ_16TO8(-4), /* re7 */ | |
7968 | DRXJ_16TO8(3), /* re8 */ | |
7969 | DRXJ_16TO8(3), /* re9 */ | |
7970 | DRXJ_16TO8(-5), /* re10 */ | |
7971 | DRXJ_16TO8(0), /* re11 */ | |
7972 | DRXJ_16TO8(9), /* re12 */ | |
7973 | DRXJ_16TO8(-4), /* re13 */ | |
7974 | DRXJ_16TO8(-12), /* re14 */ | |
7975 | DRXJ_16TO8(10), /* re15 */ | |
7976 | DRXJ_16TO8(16), /* re16 */ | |
7977 | DRXJ_16TO8(-21), /* re17 */ | |
7978 | DRXJ_16TO8(-20), /* re18 */ | |
7979 | DRXJ_16TO8(37), /* re19 */ | |
7980 | DRXJ_16TO8(25), /* re20 */ | |
7981 | DRXJ_16TO8(-62), /* re21 */ | |
7982 | DRXJ_16TO8(-28), /* re22 */ | |
7983 | DRXJ_16TO8(105), /* re23 */ | |
7984 | DRXJ_16TO8(31), /* re24 */ | |
7985 | DRXJ_16TO8(-197), /* re25 */ | |
7986 | DRXJ_16TO8(-33), /* re26 */ | |
7987 | DRXJ_16TO8(626) /* re27 */ | |
7988 | }; | |
7989 | ||
57afe2f0 | 7990 | dev_addr = demod->my_i2c_dev_addr; |
b3ce3a83 | 7991 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
1bfc9e15 | 7992 | common_attr = (struct drx_common_attr *) demod->my_common_attr; |
443f18d0 MCC |
7993 | |
7994 | if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) { | |
57afe2f0 | 7995 | if (ext_attr->standard == DRX_STANDARD_ITU_B) { |
443f18d0 MCC |
7996 | switch (channel->constellation) { |
7997 | case DRX_CONSTELLATION_QAM256: | |
57afe2f0 MCC |
7998 | iqm_rc_rate = 0x00AE3562; |
7999 | lc_symbol_freq = | |
443f18d0 MCC |
8000 | QAM_LC_SYMBOL_FREQ_FREQ_QAM_B_256; |
8001 | channel->symbolrate = 5360537; | |
57afe2f0 | 8002 | iqm_rc_stretch = IQM_RC_STRETCH_QAM_B_256; |
443f18d0 MCC |
8003 | break; |
8004 | case DRX_CONSTELLATION_QAM64: | |
57afe2f0 MCC |
8005 | iqm_rc_rate = 0x00C05A0E; |
8006 | lc_symbol_freq = 409; | |
443f18d0 | 8007 | channel->symbolrate = 5056941; |
57afe2f0 | 8008 | iqm_rc_stretch = IQM_RC_STRETCH_QAM_B_64; |
443f18d0 MCC |
8009 | break; |
8010 | default: | |
9482354f | 8011 | return -EINVAL; |
443f18d0 MCC |
8012 | } |
8013 | } else { | |
57afe2f0 | 8014 | adc_frequency = (common_attr->sys_clock_freq * 1000) / 3; |
068e94ea MCC |
8015 | if (channel->symbolrate == 0) { |
8016 | pr_err("error: channel symbolrate is zero!\n"); | |
9482354f | 8017 | return -EIO; |
068e94ea | 8018 | } |
57afe2f0 MCC |
8019 | iqm_rc_rate = |
8020 | (adc_frequency / channel->symbolrate) * (1 << 21) + | |
8021 | (frac28 | |
8022 | ((adc_frequency % channel->symbolrate), | |
443f18d0 | 8023 | channel->symbolrate) >> 7) - (1 << 23); |
57afe2f0 MCC |
8024 | lc_symbol_freq = |
8025 | (u16) (frac28 | |
443f18d0 | 8026 | (channel->symbolrate + |
57afe2f0 MCC |
8027 | (adc_frequency >> 13), |
8028 | adc_frequency) >> 16); | |
8029 | if (lc_symbol_freq > 511) | |
8030 | lc_symbol_freq = 511; | |
8031 | ||
8032 | iqm_rc_stretch = 21; | |
8033 | } | |
8034 | ||
8035 | if (ext_attr->standard == DRX_STANDARD_ITU_A) { | |
8036 | set_env_parameters = QAM_TOP_ANNEX_A; /* annex */ | |
8037 | set_param_parameters[0] = channel->constellation; /* constellation */ | |
8038 | set_param_parameters[1] = DRX_INTERLEAVEMODE_I12_J17; /* interleave mode */ | |
8039 | } else if (ext_attr->standard == DRX_STANDARD_ITU_B) { | |
8040 | set_env_parameters = QAM_TOP_ANNEX_B; /* annex */ | |
8041 | set_param_parameters[0] = channel->constellation; /* constellation */ | |
8042 | set_param_parameters[1] = channel->interleavemode; /* interleave mode */ | |
8043 | } else if (ext_attr->standard == DRX_STANDARD_ITU_C) { | |
8044 | set_env_parameters = QAM_TOP_ANNEX_C; /* annex */ | |
8045 | set_param_parameters[0] = channel->constellation; /* constellation */ | |
8046 | set_param_parameters[1] = DRX_INTERLEAVEMODE_I12_J17; /* interleave mode */ | |
443f18d0 | 8047 | } else { |
9482354f | 8048 | return -EINVAL; |
443f18d0 MCC |
8049 | } |
8050 | } | |
38b2df95 | 8051 | |
443f18d0 MCC |
8052 | if (op & QAM_SET_OP_ALL) { |
8053 | /* | |
8054 | STEP 1: reset demodulator | |
8055 | resets IQM, QAM and FEC HW blocks | |
8056 | resets SCU variables | |
8057 | */ | |
8058 | /* stop all comm_exec */ | |
244c0e06 | 8059 | rc = drxj_dap_write_reg16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP, 0); |
9482354f | 8060 | if (rc != 0) { |
068e94ea MCC |
8061 | pr_err("error %d\n", rc); |
8062 | goto rw_error; | |
8063 | } | |
244c0e06 | 8064 | rc = drxj_dap_write_reg16(dev_addr, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP, 0); |
9482354f | 8065 | if (rc != 0) { |
068e94ea MCC |
8066 | pr_err("error %d\n", rc); |
8067 | goto rw_error; | |
8068 | } | |
244c0e06 | 8069 | rc = drxj_dap_write_reg16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0); |
9482354f | 8070 | if (rc != 0) { |
068e94ea MCC |
8071 | pr_err("error %d\n", rc); |
8072 | goto rw_error; | |
8073 | } | |
244c0e06 | 8074 | rc = drxj_dap_write_reg16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0); |
9482354f | 8075 | if (rc != 0) { |
068e94ea MCC |
8076 | pr_err("error %d\n", rc); |
8077 | goto rw_error; | |
8078 | } | |
244c0e06 | 8079 | rc = drxj_dap_write_reg16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0); |
9482354f | 8080 | if (rc != 0) { |
068e94ea MCC |
8081 | pr_err("error %d\n", rc); |
8082 | goto rw_error; | |
8083 | } | |
244c0e06 | 8084 | rc = drxj_dap_write_reg16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0); |
9482354f | 8085 | if (rc != 0) { |
068e94ea MCC |
8086 | pr_err("error %d\n", rc); |
8087 | goto rw_error; | |
8088 | } | |
244c0e06 | 8089 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0); |
9482354f | 8090 | if (rc != 0) { |
068e94ea MCC |
8091 | pr_err("error %d\n", rc); |
8092 | goto rw_error; | |
8093 | } | |
57afe2f0 MCC |
8094 | |
8095 | cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM | | |
443f18d0 | 8096 | SCU_RAM_COMMAND_CMD_DEMOD_RESET; |
57afe2f0 MCC |
8097 | cmd_scu.parameter_len = 0; |
8098 | cmd_scu.result_len = 1; | |
8099 | cmd_scu.parameter = NULL; | |
8100 | cmd_scu.result = &cmd_result; | |
068e94ea | 8101 | rc = scu_command(dev_addr, &cmd_scu); |
9482354f | 8102 | if (rc != 0) { |
068e94ea MCC |
8103 | pr_err("error %d\n", rc); |
8104 | goto rw_error; | |
8105 | } | |
443f18d0 | 8106 | } |
38b2df95 | 8107 | |
443f18d0 MCC |
8108 | if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) { |
8109 | /* | |
8110 | STEP 2: configure demodulator | |
8111 | -set env | |
8112 | -set params (resets IQM,QAM,FEC HW; initializes some SCU variables ) | |
8113 | */ | |
57afe2f0 | 8114 | cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM | |
443f18d0 | 8115 | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV; |
57afe2f0 MCC |
8116 | cmd_scu.parameter_len = 1; |
8117 | cmd_scu.result_len = 1; | |
8118 | cmd_scu.parameter = &set_env_parameters; | |
8119 | cmd_scu.result = &cmd_result; | |
068e94ea | 8120 | rc = scu_command(dev_addr, &cmd_scu); |
9482354f | 8121 | if (rc != 0) { |
068e94ea MCC |
8122 | pr_err("error %d\n", rc); |
8123 | goto rw_error; | |
8124 | } | |
443f18d0 | 8125 | |
57afe2f0 | 8126 | cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM | |
443f18d0 | 8127 | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM; |
57afe2f0 MCC |
8128 | cmd_scu.parameter_len = 2; |
8129 | cmd_scu.result_len = 1; | |
8130 | cmd_scu.parameter = set_param_parameters; | |
8131 | cmd_scu.result = &cmd_result; | |
068e94ea | 8132 | rc = scu_command(dev_addr, &cmd_scu); |
9482354f | 8133 | if (rc != 0) { |
068e94ea MCC |
8134 | pr_err("error %d\n", rc); |
8135 | goto rw_error; | |
8136 | } | |
443f18d0 | 8137 | /* set symbol rate */ |
244c0e06 | 8138 | rc = drxdap_fasi_write_reg32(dev_addr, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate, 0); |
9482354f | 8139 | if (rc != 0) { |
068e94ea MCC |
8140 | pr_err("error %d\n", rc); |
8141 | goto rw_error; | |
8142 | } | |
57afe2f0 | 8143 | ext_attr->iqm_rc_rate_ofs = iqm_rc_rate; |
068e94ea | 8144 | rc = set_qam_measurement(demod, channel->constellation, channel->symbolrate); |
9482354f | 8145 | if (rc != 0) { |
068e94ea MCC |
8146 | pr_err("error %d\n", rc); |
8147 | goto rw_error; | |
8148 | } | |
443f18d0 MCC |
8149 | } |
8150 | /* STEP 3: enable the system in a mode where the ADC provides valid signal | |
8151 | setup constellation independent registers */ | |
8152 | /* from qam_cmd.py script (qam_driver_b) */ | |
8153 | /* TODO: remove re-writes of HW reset values */ | |
8154 | if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_SPECTRUM)) { | |
068e94ea | 8155 | rc = set_frequency(demod, channel, tuner_freq_offset); |
9482354f | 8156 | if (rc != 0) { |
068e94ea MCC |
8157 | pr_err("error %d\n", rc); |
8158 | goto rw_error; | |
8159 | } | |
443f18d0 | 8160 | } |
38b2df95 | 8161 | |
443f18d0 | 8162 | if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) { |
38b2df95 | 8163 | |
244c0e06 | 8164 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_SYMBOL_FREQ__A, lc_symbol_freq, 0); |
9482354f | 8165 | if (rc != 0) { |
068e94ea MCC |
8166 | pr_err("error %d\n", rc); |
8167 | goto rw_error; | |
8168 | } | |
244c0e06 | 8169 | rc = drxj_dap_write_reg16(dev_addr, IQM_RC_STRETCH__A, iqm_rc_stretch, 0); |
9482354f | 8170 | if (rc != 0) { |
068e94ea MCC |
8171 | pr_err("error %d\n", rc); |
8172 | goto rw_error; | |
8173 | } | |
443f18d0 | 8174 | } |
38b2df95 | 8175 | |
443f18d0 | 8176 | if (op & QAM_SET_OP_ALL) { |
259f380e | 8177 | if (!ext_attr->has_lna) { |
244c0e06 | 8178 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_AMUX__A, 0x02, 0); |
9482354f | 8179 | if (rc != 0) { |
068e94ea MCC |
8180 | pr_err("error %d\n", rc); |
8181 | goto rw_error; | |
8182 | } | |
8183 | } | |
244c0e06 | 8184 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_SYMMETRIC__A, 0, 0); |
9482354f | 8185 | if (rc != 0) { |
068e94ea MCC |
8186 | pr_err("error %d\n", rc); |
8187 | goto rw_error; | |
8188 | } | |
244c0e06 | 8189 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_MIDTAP__A, 3, 0); |
9482354f | 8190 | if (rc != 0) { |
068e94ea MCC |
8191 | pr_err("error %d\n", rc); |
8192 | goto rw_error; | |
8193 | } | |
244c0e06 | 8194 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_OUT_ENA__A, IQM_CF_OUT_ENA_QAM__M, 0); |
9482354f | 8195 | if (rc != 0) { |
068e94ea MCC |
8196 | pr_err("error %d\n", rc); |
8197 | goto rw_error; | |
57afe2f0 | 8198 | } |
57afe2f0 | 8199 | |
244c0e06 | 8200 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_WR_RSV_0__A, 0x5f, 0); |
9482354f | 8201 | if (rc != 0) { |
068e94ea MCC |
8202 | pr_err("error %d\n", rc); |
8203 | goto rw_error; | |
8204 | } /* scu temporary shut down agc */ | |
57afe2f0 | 8205 | |
244c0e06 | 8206 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_SYNC_SEL__A, 3, 0); |
9482354f | 8207 | if (rc != 0) { |
068e94ea MCC |
8208 | pr_err("error %d\n", rc); |
8209 | goto rw_error; | |
8210 | } | |
244c0e06 | 8211 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_CLP_LEN__A, 0, 0); |
9482354f | 8212 | if (rc != 0) { |
068e94ea MCC |
8213 | pr_err("error %d\n", rc); |
8214 | goto rw_error; | |
8215 | } | |
244c0e06 | 8216 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_CLP_TH__A, 448, 0); |
9482354f | 8217 | if (rc != 0) { |
068e94ea MCC |
8218 | pr_err("error %d\n", rc); |
8219 | goto rw_error; | |
8220 | } | |
244c0e06 | 8221 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_SNS_LEN__A, 0, 0); |
9482354f | 8222 | if (rc != 0) { |
068e94ea MCC |
8223 | pr_err("error %d\n", rc); |
8224 | goto rw_error; | |
8225 | } | |
244c0e06 | 8226 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_PDREF__A, 4, 0); |
9482354f | 8227 | if (rc != 0) { |
068e94ea MCC |
8228 | pr_err("error %d\n", rc); |
8229 | goto rw_error; | |
8230 | } | |
244c0e06 | 8231 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, 0x10, 0); |
9482354f | 8232 | if (rc != 0) { |
068e94ea MCC |
8233 | pr_err("error %d\n", rc); |
8234 | goto rw_error; | |
8235 | } | |
244c0e06 | 8236 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_PGA_GAIN__A, 11, 0); |
9482354f | 8237 | if (rc != 0) { |
068e94ea MCC |
8238 | pr_err("error %d\n", rc); |
8239 | goto rw_error; | |
8240 | } | |
57afe2f0 | 8241 | |
244c0e06 | 8242 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_POW_MEAS_LEN__A, 1, 0); |
9482354f | 8243 | if (rc != 0) { |
068e94ea MCC |
8244 | pr_err("error %d\n", rc); |
8245 | goto rw_error; | |
8246 | } | |
244c0e06 | 8247 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_SCALE_SH__A, IQM_CF_SCALE_SH__PRE, 0); |
9482354f | 8248 | if (rc != 0) { |
068e94ea MCC |
8249 | pr_err("error %d\n", rc); |
8250 | goto rw_error; | |
8251 | } /*! reset default val ! */ | |
8252 | ||
244c0e06 | 8253 | rc = drxj_dap_write_reg16(dev_addr, QAM_SY_TIMEOUT__A, QAM_SY_TIMEOUT__PRE, 0); |
9482354f | 8254 | if (rc != 0) { |
068e94ea MCC |
8255 | pr_err("error %d\n", rc); |
8256 | goto rw_error; | |
8257 | } /*! reset default val ! */ | |
57afe2f0 | 8258 | if (ext_attr->standard == DRX_STANDARD_ITU_B) { |
244c0e06 | 8259 | rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_LWM__A, QAM_SY_SYNC_LWM__PRE, 0); |
9482354f | 8260 | if (rc != 0) { |
068e94ea MCC |
8261 | pr_err("error %d\n", rc); |
8262 | goto rw_error; | |
8263 | } /*! reset default val ! */ | |
244c0e06 | 8264 | rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_AWM__A, QAM_SY_SYNC_AWM__PRE, 0); |
9482354f | 8265 | if (rc != 0) { |
068e94ea MCC |
8266 | pr_err("error %d\n", rc); |
8267 | goto rw_error; | |
8268 | } /*! reset default val ! */ | |
244c0e06 | 8269 | rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_HWM__A, QAM_SY_SYNC_HWM__PRE, 0); |
9482354f | 8270 | if (rc != 0) { |
068e94ea MCC |
8271 | pr_err("error %d\n", rc); |
8272 | goto rw_error; | |
8273 | } /*! reset default val ! */ | |
443f18d0 MCC |
8274 | } else { |
8275 | switch (channel->constellation) { | |
8276 | case DRX_CONSTELLATION_QAM16: | |
8277 | case DRX_CONSTELLATION_QAM64: | |
8278 | case DRX_CONSTELLATION_QAM256: | |
244c0e06 | 8279 | rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_LWM__A, 0x03, 0); |
9482354f | 8280 | if (rc != 0) { |
068e94ea MCC |
8281 | pr_err("error %d\n", rc); |
8282 | goto rw_error; | |
8283 | } | |
244c0e06 | 8284 | rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_AWM__A, 0x04, 0); |
9482354f | 8285 | if (rc != 0) { |
068e94ea MCC |
8286 | pr_err("error %d\n", rc); |
8287 | goto rw_error; | |
8288 | } | |
244c0e06 | 8289 | rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_HWM__A, QAM_SY_SYNC_HWM__PRE, 0); |
9482354f | 8290 | if (rc != 0) { |
068e94ea MCC |
8291 | pr_err("error %d\n", rc); |
8292 | goto rw_error; | |
8293 | } /*! reset default val ! */ | |
443f18d0 MCC |
8294 | break; |
8295 | case DRX_CONSTELLATION_QAM32: | |
8296 | case DRX_CONSTELLATION_QAM128: | |
244c0e06 | 8297 | rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_LWM__A, 0x03, 0); |
9482354f | 8298 | if (rc != 0) { |
068e94ea MCC |
8299 | pr_err("error %d\n", rc); |
8300 | goto rw_error; | |
8301 | } | |
244c0e06 | 8302 | rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_AWM__A, 0x05, 0); |
9482354f | 8303 | if (rc != 0) { |
068e94ea MCC |
8304 | pr_err("error %d\n", rc); |
8305 | goto rw_error; | |
8306 | } | |
244c0e06 | 8307 | rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_HWM__A, 0x06, 0); |
9482354f | 8308 | if (rc != 0) { |
068e94ea MCC |
8309 | pr_err("error %d\n", rc); |
8310 | goto rw_error; | |
8311 | } | |
443f18d0 MCC |
8312 | break; |
8313 | default: | |
9482354f | 8314 | return -EIO; |
443f18d0 MCC |
8315 | } /* switch */ |
8316 | } | |
8317 | ||
244c0e06 | 8318 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_MODE__A, QAM_LC_MODE__PRE, 0); |
9482354f | 8319 | if (rc != 0) { |
068e94ea MCC |
8320 | pr_err("error %d\n", rc); |
8321 | goto rw_error; | |
8322 | } /*! reset default val ! */ | |
244c0e06 | 8323 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_RATE_LIMIT__A, 3, 0); |
9482354f | 8324 | if (rc != 0) { |
068e94ea MCC |
8325 | pr_err("error %d\n", rc); |
8326 | goto rw_error; | |
8327 | } | |
244c0e06 | 8328 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_LPF_FACTORP__A, 4, 0); |
9482354f | 8329 | if (rc != 0) { |
068e94ea MCC |
8330 | pr_err("error %d\n", rc); |
8331 | goto rw_error; | |
8332 | } | |
244c0e06 | 8333 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_LPF_FACTORI__A, 4, 0); |
9482354f | 8334 | if (rc != 0) { |
068e94ea MCC |
8335 | pr_err("error %d\n", rc); |
8336 | goto rw_error; | |
8337 | } | |
244c0e06 | 8338 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_MODE__A, 7, 0); |
9482354f | 8339 | if (rc != 0) { |
068e94ea MCC |
8340 | pr_err("error %d\n", rc); |
8341 | goto rw_error; | |
8342 | } | |
244c0e06 | 8343 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB0__A, 1, 0); |
9482354f | 8344 | if (rc != 0) { |
068e94ea MCC |
8345 | pr_err("error %d\n", rc); |
8346 | goto rw_error; | |
8347 | } | |
244c0e06 | 8348 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB1__A, 1, 0); |
9482354f | 8349 | if (rc != 0) { |
068e94ea MCC |
8350 | pr_err("error %d\n", rc); |
8351 | goto rw_error; | |
8352 | } | |
244c0e06 | 8353 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB2__A, 1, 0); |
9482354f | 8354 | if (rc != 0) { |
068e94ea MCC |
8355 | pr_err("error %d\n", rc); |
8356 | goto rw_error; | |
8357 | } | |
244c0e06 | 8358 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB3__A, 1, 0); |
9482354f | 8359 | if (rc != 0) { |
068e94ea MCC |
8360 | pr_err("error %d\n", rc); |
8361 | goto rw_error; | |
8362 | } | |
244c0e06 | 8363 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB4__A, 2, 0); |
9482354f | 8364 | if (rc != 0) { |
068e94ea MCC |
8365 | pr_err("error %d\n", rc); |
8366 | goto rw_error; | |
8367 | } | |
244c0e06 | 8368 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB5__A, 2, 0); |
9482354f | 8369 | if (rc != 0) { |
068e94ea MCC |
8370 | pr_err("error %d\n", rc); |
8371 | goto rw_error; | |
8372 | } | |
244c0e06 | 8373 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB6__A, 2, 0); |
9482354f | 8374 | if (rc != 0) { |
068e94ea MCC |
8375 | pr_err("error %d\n", rc); |
8376 | goto rw_error; | |
8377 | } | |
244c0e06 | 8378 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB8__A, 2, 0); |
9482354f | 8379 | if (rc != 0) { |
068e94ea MCC |
8380 | pr_err("error %d\n", rc); |
8381 | goto rw_error; | |
8382 | } | |
244c0e06 | 8383 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB9__A, 2, 0); |
9482354f | 8384 | if (rc != 0) { |
068e94ea MCC |
8385 | pr_err("error %d\n", rc); |
8386 | goto rw_error; | |
8387 | } | |
244c0e06 | 8388 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB10__A, 2, 0); |
9482354f | 8389 | if (rc != 0) { |
068e94ea MCC |
8390 | pr_err("error %d\n", rc); |
8391 | goto rw_error; | |
8392 | } | |
244c0e06 | 8393 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB12__A, 2, 0); |
9482354f | 8394 | if (rc != 0) { |
068e94ea MCC |
8395 | pr_err("error %d\n", rc); |
8396 | goto rw_error; | |
8397 | } | |
244c0e06 | 8398 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB15__A, 3, 0); |
9482354f | 8399 | if (rc != 0) { |
068e94ea MCC |
8400 | pr_err("error %d\n", rc); |
8401 | goto rw_error; | |
8402 | } | |
244c0e06 | 8403 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB16__A, 3, 0); |
9482354f | 8404 | if (rc != 0) { |
068e94ea MCC |
8405 | pr_err("error %d\n", rc); |
8406 | goto rw_error; | |
8407 | } | |
244c0e06 | 8408 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB20__A, 4, 0); |
9482354f | 8409 | if (rc != 0) { |
068e94ea MCC |
8410 | pr_err("error %d\n", rc); |
8411 | goto rw_error; | |
8412 | } | |
244c0e06 | 8413 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB25__A, 4, 0); |
9482354f | 8414 | if (rc != 0) { |
068e94ea MCC |
8415 | pr_err("error %d\n", rc); |
8416 | goto rw_error; | |
8417 | } | |
8418 | ||
244c0e06 | 8419 | rc = drxj_dap_write_reg16(dev_addr, IQM_FS_ADJ_SEL__A, 1, 0); |
9482354f | 8420 | if (rc != 0) { |
068e94ea MCC |
8421 | pr_err("error %d\n", rc); |
8422 | goto rw_error; | |
8423 | } | |
244c0e06 | 8424 | rc = drxj_dap_write_reg16(dev_addr, IQM_RC_ADJ_SEL__A, 1, 0); |
9482354f | 8425 | if (rc != 0) { |
068e94ea MCC |
8426 | pr_err("error %d\n", rc); |
8427 | goto rw_error; | |
8428 | } | |
244c0e06 | 8429 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_ADJ_SEL__A, 1, 0); |
9482354f | 8430 | if (rc != 0) { |
068e94ea MCC |
8431 | pr_err("error %d\n", rc); |
8432 | goto rw_error; | |
8433 | } | |
244c0e06 | 8434 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_POW_MEAS_LEN__A, 0, 0); |
9482354f | 8435 | if (rc != 0) { |
068e94ea MCC |
8436 | pr_err("error %d\n", rc); |
8437 | goto rw_error; | |
8438 | } | |
244c0e06 | 8439 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_GPIO__A, 0, 0); |
9482354f | 8440 | if (rc != 0) { |
068e94ea MCC |
8441 | pr_err("error %d\n", rc); |
8442 | goto rw_error; | |
8443 | } | |
443f18d0 MCC |
8444 | |
8445 | /* No more resets of the IQM, current standard correctly set => | |
8446 | now AGCs can be configured. */ | |
8447 | /* turn on IQMAF. It has to be in front of setAgc**() */ | |
068e94ea | 8448 | rc = set_iqm_af(demod, true); |
9482354f | 8449 | if (rc != 0) { |
068e94ea MCC |
8450 | pr_err("error %d\n", rc); |
8451 | goto rw_error; | |
8452 | } | |
8453 | rc = adc_synchronization(demod); | |
9482354f | 8454 | if (rc != 0) { |
068e94ea MCC |
8455 | pr_err("error %d\n", rc); |
8456 | goto rw_error; | |
8457 | } | |
443f18d0 | 8458 | |
068e94ea | 8459 | rc = init_agc(demod); |
9482354f | 8460 | if (rc != 0) { |
068e94ea MCC |
8461 | pr_err("error %d\n", rc); |
8462 | goto rw_error; | |
8463 | } | |
8464 | rc = set_agc_if(demod, &(ext_attr->qam_if_agc_cfg), false); | |
9482354f | 8465 | if (rc != 0) { |
068e94ea MCC |
8466 | pr_err("error %d\n", rc); |
8467 | goto rw_error; | |
8468 | } | |
8469 | rc = set_agc_rf(demod, &(ext_attr->qam_rf_agc_cfg), false); | |
9482354f | 8470 | if (rc != 0) { |
068e94ea MCC |
8471 | pr_err("error %d\n", rc); |
8472 | goto rw_error; | |
8473 | } | |
443f18d0 | 8474 | { |
b3ce3a83 | 8475 | /* TODO fix this, store a struct drxj_cfg_afe_gain structure in struct drxj_data instead |
443f18d0 | 8476 | of only the gain */ |
b3ce3a83 | 8477 | struct drxj_cfg_afe_gain qam_pga_cfg = { DRX_STANDARD_ITU_B, 0 }; |
443f18d0 | 8478 | |
57afe2f0 | 8479 | qam_pga_cfg.gain = ext_attr->qam_pga_cfg; |
068e94ea | 8480 | rc = ctrl_set_cfg_afe_gain(demod, &qam_pga_cfg); |
9482354f | 8481 | if (rc != 0) { |
068e94ea MCC |
8482 | pr_err("error %d\n", rc); |
8483 | goto rw_error; | |
8484 | } | |
8485 | } | |
8486 | rc = ctrl_set_cfg_pre_saw(demod, &(ext_attr->qam_pre_saw_cfg)); | |
9482354f | 8487 | if (rc != 0) { |
068e94ea MCC |
8488 | pr_err("error %d\n", rc); |
8489 | goto rw_error; | |
443f18d0 | 8490 | } |
443f18d0 | 8491 | } |
38b2df95 | 8492 | |
443f18d0 | 8493 | if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) { |
57afe2f0 | 8494 | if (ext_attr->standard == DRX_STANDARD_ITU_A) { |
244c0e06 | 8495 | rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_RE0__A, sizeof(qam_a_taps), ((u8 *)qam_a_taps), 0); |
9482354f | 8496 | if (rc != 0) { |
068e94ea MCC |
8497 | pr_err("error %d\n", rc); |
8498 | goto rw_error; | |
8499 | } | |
244c0e06 | 8500 | rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_IM0__A, sizeof(qam_a_taps), ((u8 *)qam_a_taps), 0); |
9482354f | 8501 | if (rc != 0) { |
068e94ea MCC |
8502 | pr_err("error %d\n", rc); |
8503 | goto rw_error; | |
8504 | } | |
57afe2f0 | 8505 | } else if (ext_attr->standard == DRX_STANDARD_ITU_B) { |
443f18d0 MCC |
8506 | switch (channel->constellation) { |
8507 | case DRX_CONSTELLATION_QAM64: | |
244c0e06 | 8508 | rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_RE0__A, sizeof(qam_b64_taps), ((u8 *)qam_b64_taps), 0); |
9482354f | 8509 | if (rc != 0) { |
068e94ea MCC |
8510 | pr_err("error %d\n", rc); |
8511 | goto rw_error; | |
8512 | } | |
244c0e06 | 8513 | rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_IM0__A, sizeof(qam_b64_taps), ((u8 *)qam_b64_taps), 0); |
9482354f | 8514 | if (rc != 0) { |
068e94ea MCC |
8515 | pr_err("error %d\n", rc); |
8516 | goto rw_error; | |
8517 | } | |
443f18d0 MCC |
8518 | break; |
8519 | case DRX_CONSTELLATION_QAM256: | |
244c0e06 | 8520 | rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_RE0__A, sizeof(qam_b256_taps), ((u8 *)qam_b256_taps), 0); |
9482354f | 8521 | if (rc != 0) { |
068e94ea MCC |
8522 | pr_err("error %d\n", rc); |
8523 | goto rw_error; | |
8524 | } | |
244c0e06 | 8525 | rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_IM0__A, sizeof(qam_b256_taps), ((u8 *)qam_b256_taps), 0); |
9482354f | 8526 | if (rc != 0) { |
068e94ea MCC |
8527 | pr_err("error %d\n", rc); |
8528 | goto rw_error; | |
8529 | } | |
443f18d0 MCC |
8530 | break; |
8531 | default: | |
9482354f | 8532 | return -EIO; |
443f18d0 | 8533 | } |
57afe2f0 | 8534 | } else if (ext_attr->standard == DRX_STANDARD_ITU_C) { |
244c0e06 | 8535 | rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_RE0__A, sizeof(qam_c_taps), ((u8 *)qam_c_taps), 0); |
9482354f | 8536 | if (rc != 0) { |
068e94ea MCC |
8537 | pr_err("error %d\n", rc); |
8538 | goto rw_error; | |
8539 | } | |
244c0e06 | 8540 | rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_IM0__A, sizeof(qam_c_taps), ((u8 *)qam_c_taps), 0); |
9482354f | 8541 | if (rc != 0) { |
068e94ea MCC |
8542 | pr_err("error %d\n", rc); |
8543 | goto rw_error; | |
8544 | } | |
443f18d0 MCC |
8545 | } |
8546 | ||
8547 | /* SETP 4: constellation specific setup */ | |
8548 | switch (channel->constellation) { | |
8549 | case DRX_CONSTELLATION_QAM16: | |
068e94ea | 8550 | rc = set_qam16(demod); |
9482354f | 8551 | if (rc != 0) { |
068e94ea MCC |
8552 | pr_err("error %d\n", rc); |
8553 | goto rw_error; | |
8554 | } | |
443f18d0 MCC |
8555 | break; |
8556 | case DRX_CONSTELLATION_QAM32: | |
068e94ea | 8557 | rc = set_qam32(demod); |
9482354f | 8558 | if (rc != 0) { |
068e94ea MCC |
8559 | pr_err("error %d\n", rc); |
8560 | goto rw_error; | |
8561 | } | |
443f18d0 MCC |
8562 | break; |
8563 | case DRX_CONSTELLATION_QAM64: | |
068e94ea | 8564 | rc = set_qam64(demod); |
9482354f | 8565 | if (rc != 0) { |
068e94ea MCC |
8566 | pr_err("error %d\n", rc); |
8567 | goto rw_error; | |
8568 | } | |
443f18d0 MCC |
8569 | break; |
8570 | case DRX_CONSTELLATION_QAM128: | |
068e94ea | 8571 | rc = set_qam128(demod); |
9482354f | 8572 | if (rc != 0) { |
068e94ea MCC |
8573 | pr_err("error %d\n", rc); |
8574 | goto rw_error; | |
8575 | } | |
443f18d0 MCC |
8576 | break; |
8577 | case DRX_CONSTELLATION_QAM256: | |
068e94ea | 8578 | rc = set_qam256(demod); |
9482354f | 8579 | if (rc != 0) { |
068e94ea MCC |
8580 | pr_err("error %d\n", rc); |
8581 | goto rw_error; | |
8582 | } | |
443f18d0 MCC |
8583 | break; |
8584 | default: | |
9482354f | 8585 | return -EIO; |
443f18d0 MCC |
8586 | } /* switch */ |
8587 | } | |
38b2df95 | 8588 | |
443f18d0 | 8589 | if ((op & QAM_SET_OP_ALL)) { |
244c0e06 | 8590 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_SCALE_SH__A, 0, 0); |
9482354f | 8591 | if (rc != 0) { |
068e94ea MCC |
8592 | pr_err("error %d\n", rc); |
8593 | goto rw_error; | |
8594 | } | |
443f18d0 MCC |
8595 | |
8596 | /* Mpeg output has to be in front of FEC active */ | |
068e94ea | 8597 | rc = set_mpegtei_handling(demod); |
9482354f | 8598 | if (rc != 0) { |
068e94ea MCC |
8599 | pr_err("error %d\n", rc); |
8600 | goto rw_error; | |
8601 | } | |
8602 | rc = bit_reverse_mpeg_output(demod); | |
9482354f | 8603 | if (rc != 0) { |
068e94ea MCC |
8604 | pr_err("error %d\n", rc); |
8605 | goto rw_error; | |
8606 | } | |
8607 | rc = set_mpeg_start_width(demod); | |
9482354f | 8608 | if (rc != 0) { |
068e94ea MCC |
8609 | pr_err("error %d\n", rc); |
8610 | goto rw_error; | |
8611 | } | |
443f18d0 | 8612 | { |
57afe2f0 | 8613 | /* TODO: move to set_standard after hardware reset value problem is solved */ |
443f18d0 | 8614 | /* Configure initial MPEG output */ |
1bfc9e15 | 8615 | struct drx_cfg_mpeg_output cfg_mpeg_output; |
443f18d0 | 8616 | |
41b5cc0c | 8617 | memcpy(&cfg_mpeg_output, &common_attr->mpeg_cfg, sizeof(cfg_mpeg_output)); |
57afe2f0 | 8618 | cfg_mpeg_output.enable_mpeg_output = true; |
41b5cc0c | 8619 | |
068e94ea | 8620 | rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output); |
9482354f | 8621 | if (rc != 0) { |
068e94ea MCC |
8622 | pr_err("error %d\n", rc); |
8623 | goto rw_error; | |
8624 | } | |
443f18d0 MCC |
8625 | } |
8626 | } | |
38b2df95 | 8627 | |
443f18d0 | 8628 | if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) { |
38b2df95 | 8629 | |
443f18d0 | 8630 | /* STEP 5: start QAM demodulator (starts FEC, QAM and IQM HW) */ |
57afe2f0 | 8631 | cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM | |
443f18d0 | 8632 | SCU_RAM_COMMAND_CMD_DEMOD_START; |
57afe2f0 MCC |
8633 | cmd_scu.parameter_len = 0; |
8634 | cmd_scu.result_len = 1; | |
8635 | cmd_scu.parameter = NULL; | |
8636 | cmd_scu.result = &cmd_result; | |
068e94ea | 8637 | rc = scu_command(dev_addr, &cmd_scu); |
9482354f | 8638 | if (rc != 0) { |
068e94ea MCC |
8639 | pr_err("error %d\n", rc); |
8640 | goto rw_error; | |
8641 | } | |
443f18d0 MCC |
8642 | } |
8643 | ||
244c0e06 | 8644 | rc = drxj_dap_write_reg16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_ACTIVE, 0); |
9482354f | 8645 | if (rc != 0) { |
068e94ea MCC |
8646 | pr_err("error %d\n", rc); |
8647 | goto rw_error; | |
8648 | } | |
244c0e06 | 8649 | rc = drxj_dap_write_reg16(dev_addr, QAM_COMM_EXEC__A, QAM_COMM_EXEC_ACTIVE, 0); |
9482354f | 8650 | if (rc != 0) { |
068e94ea MCC |
8651 | pr_err("error %d\n", rc); |
8652 | goto rw_error; | |
8653 | } | |
244c0e06 | 8654 | rc = drxj_dap_write_reg16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE, 0); |
9482354f | 8655 | if (rc != 0) { |
068e94ea MCC |
8656 | pr_err("error %d\n", rc); |
8657 | goto rw_error; | |
8658 | } | |
443f18d0 | 8659 | |
9482354f | 8660 | return 0; |
443f18d0 | 8661 | rw_error: |
30741871 | 8662 | return rc; |
443f18d0 MCC |
8663 | } |
8664 | ||
8665 | /*============================================================================*/ | |
03fdfbfd MCC |
8666 | static int ctrl_get_qam_sig_quality(struct drx_demod_instance *demod); |
8667 | ||
1bfc9e15 | 8668 | static int qam_flip_spec(struct drx_demod_instance *demod, struct drx_channel *channel) |
443f18d0 | 8669 | { |
03fdfbfd MCC |
8670 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; |
8671 | struct drxj_data *ext_attr = demod->my_ext_attr; | |
068e94ea | 8672 | int rc; |
57afe2f0 MCC |
8673 | u32 iqm_fs_rate_ofs = 0; |
8674 | u32 iqm_fs_rate_lo = 0; | |
8675 | u16 qam_ctl_ena = 0; | |
43a431e4 | 8676 | u16 data = 0; |
57afe2f0 MCC |
8677 | u16 equ_mode = 0; |
8678 | u16 fsm_state = 0; | |
443f18d0 MCC |
8679 | int i = 0; |
8680 | int ofsofs = 0; | |
443f18d0 MCC |
8681 | |
8682 | /* Silence the controlling of lc, equ, and the acquisition state machine */ | |
244c0e06 | 8683 | rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_QAM_CTL_ENA__A, &qam_ctl_ena, 0); |
9482354f | 8684 | if (rc != 0) { |
068e94ea MCC |
8685 | pr_err("error %d\n", rc); |
8686 | goto rw_error; | |
8687 | } | |
244c0e06 | 8688 | rc = drxj_dap_write_reg16(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); |
9482354f | 8689 | if (rc != 0) { |
068e94ea MCC |
8690 | pr_err("error %d\n", rc); |
8691 | goto rw_error; | |
8692 | } | |
443f18d0 MCC |
8693 | |
8694 | /* freeze the frequency control loop */ | |
244c0e06 | 8695 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_CF__A, 0, 0); |
9482354f | 8696 | if (rc != 0) { |
068e94ea MCC |
8697 | pr_err("error %d\n", rc); |
8698 | goto rw_error; | |
8699 | } | |
244c0e06 | 8700 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_CF1__A, 0, 0); |
9482354f | 8701 | if (rc != 0) { |
068e94ea MCC |
8702 | pr_err("error %d\n", rc); |
8703 | goto rw_error; | |
8704 | } | |
443f18d0 | 8705 | |
068e94ea | 8706 | rc = drxj_dap_atomic_read_reg32(dev_addr, IQM_FS_RATE_OFS_LO__A, &iqm_fs_rate_ofs, 0); |
9482354f | 8707 | if (rc != 0) { |
068e94ea MCC |
8708 | pr_err("error %d\n", rc); |
8709 | goto rw_error; | |
8710 | } | |
8711 | rc = drxj_dap_atomic_read_reg32(dev_addr, IQM_FS_RATE_LO__A, &iqm_fs_rate_lo, 0); | |
9482354f | 8712 | if (rc != 0) { |
068e94ea MCC |
8713 | pr_err("error %d\n", rc); |
8714 | goto rw_error; | |
8715 | } | |
57afe2f0 MCC |
8716 | ofsofs = iqm_fs_rate_lo - iqm_fs_rate_ofs; |
8717 | iqm_fs_rate_ofs = ~iqm_fs_rate_ofs + 1; | |
8718 | iqm_fs_rate_ofs -= 2 * ofsofs; | |
443f18d0 MCC |
8719 | |
8720 | /* freeze dq/fq updating */ | |
244c0e06 | 8721 | rc = drxj_dap_read_reg16(dev_addr, QAM_DQ_MODE__A, &data, 0); |
9482354f | 8722 | if (rc != 0) { |
068e94ea MCC |
8723 | pr_err("error %d\n", rc); |
8724 | goto rw_error; | |
8725 | } | |
443f18d0 | 8726 | data = (data & 0xfff9); |
244c0e06 | 8727 | rc = drxj_dap_write_reg16(dev_addr, QAM_DQ_MODE__A, data, 0); |
9482354f | 8728 | if (rc != 0) { |
068e94ea MCC |
8729 | pr_err("error %d\n", rc); |
8730 | goto rw_error; | |
8731 | } | |
244c0e06 | 8732 | rc = drxj_dap_write_reg16(dev_addr, QAM_FQ_MODE__A, data, 0); |
9482354f | 8733 | if (rc != 0) { |
068e94ea MCC |
8734 | pr_err("error %d\n", rc); |
8735 | goto rw_error; | |
8736 | } | |
443f18d0 MCC |
8737 | |
8738 | /* lc_cp / _ci / _ca */ | |
244c0e06 | 8739 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_CI__A, 0, 0); |
9482354f | 8740 | if (rc != 0) { |
068e94ea MCC |
8741 | pr_err("error %d\n", rc); |
8742 | goto rw_error; | |
8743 | } | |
244c0e06 | 8744 | rc = drxj_dap_write_reg16(dev_addr, QAM_LC_EP__A, 0, 0); |
9482354f | 8745 | if (rc != 0) { |
068e94ea MCC |
8746 | pr_err("error %d\n", rc); |
8747 | goto rw_error; | |
8748 | } | |
244c0e06 | 8749 | rc = drxj_dap_write_reg16(dev_addr, QAM_FQ_LA_FACTOR__A, 0, 0); |
9482354f | 8750 | if (rc != 0) { |
068e94ea MCC |
8751 | pr_err("error %d\n", rc); |
8752 | goto rw_error; | |
8753 | } | |
443f18d0 MCC |
8754 | |
8755 | /* flip the spec */ | |
244c0e06 | 8756 | rc = drxdap_fasi_write_reg32(dev_addr, IQM_FS_RATE_OFS_LO__A, iqm_fs_rate_ofs, 0); |
9482354f | 8757 | if (rc != 0) { |
068e94ea MCC |
8758 | pr_err("error %d\n", rc); |
8759 | goto rw_error; | |
8760 | } | |
57afe2f0 MCC |
8761 | ext_attr->iqm_fs_rate_ofs = iqm_fs_rate_ofs; |
8762 | ext_attr->pos_image = (ext_attr->pos_image) ? false : true; | |
443f18d0 MCC |
8763 | |
8764 | /* freeze dq/fq updating */ | |
244c0e06 | 8765 | rc = drxj_dap_read_reg16(dev_addr, QAM_DQ_MODE__A, &data, 0); |
9482354f | 8766 | if (rc != 0) { |
068e94ea MCC |
8767 | pr_err("error %d\n", rc); |
8768 | goto rw_error; | |
8769 | } | |
57afe2f0 | 8770 | equ_mode = data; |
443f18d0 | 8771 | data = (data & 0xfff9); |
244c0e06 | 8772 | rc = drxj_dap_write_reg16(dev_addr, QAM_DQ_MODE__A, data, 0); |
9482354f | 8773 | if (rc != 0) { |
068e94ea MCC |
8774 | pr_err("error %d\n", rc); |
8775 | goto rw_error; | |
8776 | } | |
244c0e06 | 8777 | rc = drxj_dap_write_reg16(dev_addr, QAM_FQ_MODE__A, data, 0); |
9482354f | 8778 | if (rc != 0) { |
068e94ea MCC |
8779 | pr_err("error %d\n", rc); |
8780 | goto rw_error; | |
8781 | } | |
443f18d0 MCC |
8782 | |
8783 | for (i = 0; i < 28; i++) { | |
244c0e06 | 8784 | rc = drxj_dap_read_reg16(dev_addr, QAM_DQ_TAP_IM_EL0__A + (2 * i), &data, 0); |
9482354f | 8785 | if (rc != 0) { |
068e94ea MCC |
8786 | pr_err("error %d\n", rc); |
8787 | goto rw_error; | |
8788 | } | |
244c0e06 | 8789 | rc = drxj_dap_write_reg16(dev_addr, QAM_DQ_TAP_IM_EL0__A + (2 * i), -data, 0); |
9482354f | 8790 | if (rc != 0) { |
068e94ea MCC |
8791 | pr_err("error %d\n", rc); |
8792 | goto rw_error; | |
8793 | } | |
443f18d0 MCC |
8794 | } |
8795 | ||
8796 | for (i = 0; i < 24; i++) { | |
244c0e06 | 8797 | rc = drxj_dap_read_reg16(dev_addr, QAM_FQ_TAP_IM_EL0__A + (2 * i), &data, 0); |
9482354f | 8798 | if (rc != 0) { |
068e94ea MCC |
8799 | pr_err("error %d\n", rc); |
8800 | goto rw_error; | |
8801 | } | |
244c0e06 | 8802 | rc = drxj_dap_write_reg16(dev_addr, QAM_FQ_TAP_IM_EL0__A + (2 * i), -data, 0); |
9482354f | 8803 | if (rc != 0) { |
068e94ea MCC |
8804 | pr_err("error %d\n", rc); |
8805 | goto rw_error; | |
8806 | } | |
443f18d0 MCC |
8807 | } |
8808 | ||
57afe2f0 | 8809 | data = equ_mode; |
244c0e06 | 8810 | rc = drxj_dap_write_reg16(dev_addr, QAM_DQ_MODE__A, data, 0); |
9482354f | 8811 | if (rc != 0) { |
068e94ea MCC |
8812 | pr_err("error %d\n", rc); |
8813 | goto rw_error; | |
8814 | } | |
244c0e06 | 8815 | rc = drxj_dap_write_reg16(dev_addr, QAM_FQ_MODE__A, data, 0); |
9482354f | 8816 | if (rc != 0) { |
068e94ea MCC |
8817 | pr_err("error %d\n", rc); |
8818 | goto rw_error; | |
8819 | } | |
443f18d0 | 8820 | |
244c0e06 | 8821 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_STATE_TGT__A, 4, 0); |
9482354f | 8822 | if (rc != 0) { |
068e94ea MCC |
8823 | pr_err("error %d\n", rc); |
8824 | goto rw_error; | |
8825 | } | |
38b2df95 | 8826 | |
443f18d0 | 8827 | i = 0; |
57afe2f0 | 8828 | while ((fsm_state != 4) && (i++ < 100)) { |
244c0e06 | 8829 | rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_QAM_FSM_STATE__A, &fsm_state, 0); |
9482354f | 8830 | if (rc != 0) { |
068e94ea MCC |
8831 | pr_err("error %d\n", rc); |
8832 | goto rw_error; | |
8833 | } | |
8834 | } | |
244c0e06 | 8835 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_CTL_ENA__A, (qam_ctl_ena | 0x0016), 0); |
9482354f | 8836 | if (rc != 0) { |
068e94ea MCC |
8837 | pr_err("error %d\n", rc); |
8838 | goto rw_error; | |
443f18d0 | 8839 | } |
443f18d0 | 8840 | |
9482354f | 8841 | return 0; |
38b2df95 | 8842 | rw_error: |
30741871 | 8843 | return rc; |
38b2df95 DH |
8844 | |
8845 | } | |
8846 | ||
8847 | #define NO_LOCK 0x0 | |
8848 | #define DEMOD_LOCKED 0x1 | |
8849 | #define SYNC_FLIPPED 0x2 | |
8850 | #define SPEC_MIRRORED 0x4 | |
34eb9751 | 8851 | /* |
57afe2f0 | 8852 | * \fn int qam64auto () |
38b2df95 DH |
8853 | * \brief auto do sync pattern switching and mirroring. |
8854 | * \param demod: instance of demod. | |
8855 | * \param channel: pointer to channel data. | |
57afe2f0 MCC |
8856 | * \param tuner_freq_offset: tuner frequency offset. |
8857 | * \param lock_status: pointer to lock status. | |
61263c75 | 8858 | * \return int. |
38b2df95 | 8859 | */ |
61263c75 | 8860 | static int |
1bfc9e15 MCC |
8861 | qam64auto(struct drx_demod_instance *demod, |
8862 | struct drx_channel *channel, | |
8863 | s32 tuner_freq_offset, enum drx_lock_status *lock_status) | |
443f18d0 | 8864 | { |
03fdfbfd MCC |
8865 | struct drxj_data *ext_attr = demod->my_ext_attr; |
8866 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; | |
8867 | struct drx39xxj_state *state = dev_addr->user_data; | |
8868 | struct dtv_frontend_properties *p = &state->frontend.dtv_property_cache; | |
068e94ea | 8869 | int rc; |
6f64c522 | 8870 | u32 lck_state = NO_LOCK; |
57afe2f0 MCC |
8871 | u32 start_time = 0; |
8872 | u32 d_locked_time = 0; | |
57afe2f0 | 8873 | u32 timeout_ofs = 0; |
068e94ea | 8874 | u16 data = 0; |
443f18d0 | 8875 | |
69bb7ab6 | 8876 | /* external attributes for storing acquired channel constellation */ |
57afe2f0 | 8877 | *lock_status = DRX_NOT_LOCKED; |
d7b0631e | 8878 | start_time = jiffies_to_msecs(jiffies); |
6f64c522 | 8879 | lck_state = NO_LOCK; |
443f18d0 | 8880 | do { |
068e94ea | 8881 | rc = ctrl_lock_status(demod, lock_status); |
9482354f | 8882 | if (rc != 0) { |
068e94ea MCC |
8883 | pr_err("error %d\n", rc); |
8884 | goto rw_error; | |
8885 | } | |
443f18d0 | 8886 | |
6f64c522 | 8887 | switch (lck_state) { |
443f18d0 | 8888 | case NO_LOCK: |
57afe2f0 | 8889 | if (*lock_status == DRXJ_DEMOD_LOCK) { |
03fdfbfd | 8890 | rc = ctrl_get_qam_sig_quality(demod); |
9482354f | 8891 | if (rc != 0) { |
068e94ea MCC |
8892 | pr_err("error %d\n", rc); |
8893 | goto rw_error; | |
8894 | } | |
03fdfbfd | 8895 | if (p->cnr.stat[0].svalue > 20800) { |
6f64c522 | 8896 | lck_state = DEMOD_LOCKED; |
443f18d0 | 8897 | /* some delay to see if fec_lock possible TODO find the right value */ |
57afe2f0 | 8898 | timeout_ofs += DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME; /* see something, waiting longer */ |
d7b0631e | 8899 | d_locked_time = jiffies_to_msecs(jiffies); |
443f18d0 MCC |
8900 | } |
8901 | } | |
8902 | break; | |
8903 | case DEMOD_LOCKED: | |
57afe2f0 | 8904 | if ((*lock_status == DRXJ_DEMOD_LOCK) && /* still demod_lock in 150ms */ |
d7b0631e | 8905 | ((jiffies_to_msecs(jiffies) - d_locked_time) > |
443f18d0 | 8906 | DRXJ_QAM_FEC_LOCK_WAITTIME)) { |
244c0e06 | 8907 | rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, &data, 0); |
9482354f | 8908 | if (rc != 0) { |
068e94ea MCC |
8909 | pr_err("error %d\n", rc); |
8910 | goto rw_error; | |
8911 | } | |
244c0e06 | 8912 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, data | 0x1, 0); |
9482354f | 8913 | if (rc != 0) { |
068e94ea MCC |
8914 | pr_err("error %d\n", rc); |
8915 | goto rw_error; | |
8916 | } | |
6f64c522 | 8917 | lck_state = SYNC_FLIPPED; |
d7b0631e | 8918 | msleep(10); |
443f18d0 MCC |
8919 | } |
8920 | break; | |
8921 | case SYNC_FLIPPED: | |
57afe2f0 | 8922 | if (*lock_status == DRXJ_DEMOD_LOCK) { |
443f18d0 MCC |
8923 | if (channel->mirror == DRX_MIRROR_AUTO) { |
8924 | /* flip sync pattern back */ | |
244c0e06 | 8925 | rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, &data, 0); |
9482354f | 8926 | if (rc != 0) { |
068e94ea MCC |
8927 | pr_err("error %d\n", rc); |
8928 | goto rw_error; | |
8929 | } | |
244c0e06 | 8930 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, data & 0xFFFE, 0); |
9482354f | 8931 | if (rc != 0) { |
068e94ea MCC |
8932 | pr_err("error %d\n", rc); |
8933 | goto rw_error; | |
8934 | } | |
443f18d0 | 8935 | /* flip spectrum */ |
57afe2f0 | 8936 | ext_attr->mirror = DRX_MIRROR_YES; |
068e94ea | 8937 | rc = qam_flip_spec(demod, channel); |
9482354f | 8938 | if (rc != 0) { |
068e94ea MCC |
8939 | pr_err("error %d\n", rc); |
8940 | goto rw_error; | |
8941 | } | |
6f64c522 | 8942 | lck_state = SPEC_MIRRORED; |
443f18d0 | 8943 | /* reset timer TODO: still need 500ms? */ |
57afe2f0 | 8944 | start_time = d_locked_time = |
d7b0631e | 8945 | jiffies_to_msecs(jiffies); |
57afe2f0 | 8946 | timeout_ofs = 0; |
443f18d0 MCC |
8947 | } else { /* no need to wait lock */ |
8948 | ||
57afe2f0 | 8949 | start_time = |
d7b0631e | 8950 | jiffies_to_msecs(jiffies) - |
57afe2f0 | 8951 | DRXJ_QAM_MAX_WAITTIME - timeout_ofs; |
443f18d0 MCC |
8952 | } |
8953 | } | |
8954 | break; | |
8955 | case SPEC_MIRRORED: | |
57afe2f0 | 8956 | if ((*lock_status == DRXJ_DEMOD_LOCK) && /* still demod_lock in 150ms */ |
d7b0631e | 8957 | ((jiffies_to_msecs(jiffies) - d_locked_time) > |
443f18d0 | 8958 | DRXJ_QAM_FEC_LOCK_WAITTIME)) { |
03fdfbfd | 8959 | rc = ctrl_get_qam_sig_quality(demod); |
9482354f | 8960 | if (rc != 0) { |
068e94ea MCC |
8961 | pr_err("error %d\n", rc); |
8962 | goto rw_error; | |
8963 | } | |
03fdfbfd | 8964 | if (p->cnr.stat[0].svalue > 20800) { |
244c0e06 | 8965 | rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, &data, 0); |
9482354f | 8966 | if (rc != 0) { |
068e94ea MCC |
8967 | pr_err("error %d\n", rc); |
8968 | goto rw_error; | |
8969 | } | |
244c0e06 | 8970 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, data | 0x1, 0); |
9482354f | 8971 | if (rc != 0) { |
068e94ea MCC |
8972 | pr_err("error %d\n", rc); |
8973 | goto rw_error; | |
8974 | } | |
443f18d0 | 8975 | /* no need to wait lock */ |
57afe2f0 | 8976 | start_time = |
d7b0631e | 8977 | jiffies_to_msecs(jiffies) - |
57afe2f0 | 8978 | DRXJ_QAM_MAX_WAITTIME - timeout_ofs; |
443f18d0 MCC |
8979 | } |
8980 | } | |
8981 | break; | |
8982 | default: | |
8983 | break; | |
8984 | } | |
d7b0631e | 8985 | msleep(10); |
443f18d0 | 8986 | } while |
57afe2f0 MCC |
8987 | ((*lock_status != DRX_LOCKED) && |
8988 | (*lock_status != DRX_NEVER_LOCK) && | |
d7b0631e | 8989 | ((jiffies_to_msecs(jiffies) - start_time) < |
57afe2f0 | 8990 | (DRXJ_QAM_MAX_WAITTIME + timeout_ofs)) |
443f18d0 MCC |
8991 | ); |
8992 | /* Returning control to apllication ... */ | |
8993 | ||
9482354f | 8994 | return 0; |
38b2df95 | 8995 | rw_error: |
30741871 | 8996 | return rc; |
38b2df95 DH |
8997 | } |
8998 | ||
34eb9751 | 8999 | /* |
57afe2f0 | 9000 | * \fn int qam256auto () |
38b2df95 DH |
9001 | * \brief auto do sync pattern switching and mirroring. |
9002 | * \param demod: instance of demod. | |
9003 | * \param channel: pointer to channel data. | |
57afe2f0 MCC |
9004 | * \param tuner_freq_offset: tuner frequency offset. |
9005 | * \param lock_status: pointer to lock status. | |
61263c75 | 9006 | * \return int. |
38b2df95 | 9007 | */ |
61263c75 | 9008 | static int |
1bfc9e15 MCC |
9009 | qam256auto(struct drx_demod_instance *demod, |
9010 | struct drx_channel *channel, | |
9011 | s32 tuner_freq_offset, enum drx_lock_status *lock_status) | |
443f18d0 | 9012 | { |
03fdfbfd MCC |
9013 | struct drxj_data *ext_attr = demod->my_ext_attr; |
9014 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; | |
9015 | struct drx39xxj_state *state = dev_addr->user_data; | |
9016 | struct dtv_frontend_properties *p = &state->frontend.dtv_property_cache; | |
068e94ea | 9017 | int rc; |
6f64c522 | 9018 | u32 lck_state = NO_LOCK; |
57afe2f0 MCC |
9019 | u32 start_time = 0; |
9020 | u32 d_locked_time = 0; | |
57afe2f0 | 9021 | u32 timeout_ofs = DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME; |
443f18d0 | 9022 | |
69bb7ab6 | 9023 | /* external attributes for storing acquired channel constellation */ |
57afe2f0 | 9024 | *lock_status = DRX_NOT_LOCKED; |
d7b0631e | 9025 | start_time = jiffies_to_msecs(jiffies); |
6f64c522 | 9026 | lck_state = NO_LOCK; |
443f18d0 | 9027 | do { |
068e94ea | 9028 | rc = ctrl_lock_status(demod, lock_status); |
9482354f | 9029 | if (rc != 0) { |
068e94ea MCC |
9030 | pr_err("error %d\n", rc); |
9031 | goto rw_error; | |
9032 | } | |
6f64c522 | 9033 | switch (lck_state) { |
443f18d0 | 9034 | case NO_LOCK: |
57afe2f0 | 9035 | if (*lock_status == DRXJ_DEMOD_LOCK) { |
03fdfbfd | 9036 | rc = ctrl_get_qam_sig_quality(demod); |
9482354f | 9037 | if (rc != 0) { |
068e94ea MCC |
9038 | pr_err("error %d\n", rc); |
9039 | goto rw_error; | |
9040 | } | |
03fdfbfd | 9041 | if (p->cnr.stat[0].svalue > 26800) { |
6f64c522 | 9042 | lck_state = DEMOD_LOCKED; |
57afe2f0 | 9043 | timeout_ofs += DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME; /* see something, wait longer */ |
d7b0631e | 9044 | d_locked_time = jiffies_to_msecs(jiffies); |
443f18d0 MCC |
9045 | } |
9046 | } | |
9047 | break; | |
9048 | case DEMOD_LOCKED: | |
57afe2f0 | 9049 | if (*lock_status == DRXJ_DEMOD_LOCK) { |
443f18d0 | 9050 | if ((channel->mirror == DRX_MIRROR_AUTO) && |
d7b0631e | 9051 | ((jiffies_to_msecs(jiffies) - d_locked_time) > |
443f18d0 | 9052 | DRXJ_QAM_FEC_LOCK_WAITTIME)) { |
57afe2f0 | 9053 | ext_attr->mirror = DRX_MIRROR_YES; |
068e94ea | 9054 | rc = qam_flip_spec(demod, channel); |
9482354f | 9055 | if (rc != 0) { |
068e94ea MCC |
9056 | pr_err("error %d\n", rc); |
9057 | goto rw_error; | |
9058 | } | |
6f64c522 | 9059 | lck_state = SPEC_MIRRORED; |
443f18d0 | 9060 | /* reset timer TODO: still need 300ms? */ |
d7b0631e | 9061 | start_time = jiffies_to_msecs(jiffies); |
57afe2f0 | 9062 | timeout_ofs = -DRXJ_QAM_MAX_WAITTIME / 2; |
443f18d0 MCC |
9063 | } |
9064 | } | |
9065 | break; | |
9066 | case SPEC_MIRRORED: | |
9067 | break; | |
9068 | default: | |
9069 | break; | |
9070 | } | |
d7b0631e | 9071 | msleep(10); |
443f18d0 | 9072 | } while |
57afe2f0 MCC |
9073 | ((*lock_status < DRX_LOCKED) && |
9074 | (*lock_status != DRX_NEVER_LOCK) && | |
d7b0631e | 9075 | ((jiffies_to_msecs(jiffies) - start_time) < |
57afe2f0 | 9076 | (DRXJ_QAM_MAX_WAITTIME + timeout_ofs))); |
443f18d0 | 9077 | |
9482354f | 9078 | return 0; |
38b2df95 | 9079 | rw_error: |
30741871 | 9080 | return rc; |
38b2df95 DH |
9081 | } |
9082 | ||
34eb9751 | 9083 | /* |
e33f2193 | 9084 | * \fn int set_qam_channel () |
38b2df95 DH |
9085 | * \brief Set QAM channel according to the requested constellation. |
9086 | * \param demod: instance of demod. | |
9087 | * \param channel: pointer to channel data. | |
61263c75 | 9088 | * \return int. |
38b2df95 | 9089 | */ |
61263c75 | 9090 | static int |
e33f2193 | 9091 | set_qam_channel(struct drx_demod_instance *demod, |
1bfc9e15 | 9092 | struct drx_channel *channel, s32 tuner_freq_offset) |
443f18d0 | 9093 | { |
b3ce3a83 | 9094 | struct drxj_data *ext_attr = NULL; |
068e94ea MCC |
9095 | int rc; |
9096 | enum drx_lock_status lock_status = DRX_NOT_LOCKED; | |
57afe2f0 | 9097 | bool auto_flag = false; |
443f18d0 | 9098 | |
69bb7ab6 | 9099 | /* external attributes for storing acquired channel constellation */ |
b3ce3a83 | 9100 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
443f18d0 MCC |
9101 | |
9102 | /* set QAM channel constellation */ | |
9103 | switch (channel->constellation) { | |
9104 | case DRX_CONSTELLATION_QAM16: | |
9105 | case DRX_CONSTELLATION_QAM32: | |
443f18d0 | 9106 | case DRX_CONSTELLATION_QAM128: |
938f11fa MCC |
9107 | return -EINVAL; |
9108 | case DRX_CONSTELLATION_QAM64: | |
443f18d0 | 9109 | case DRX_CONSTELLATION_QAM256: |
938f11fa MCC |
9110 | if (ext_attr->standard != DRX_STANDARD_ITU_B) |
9111 | return -EINVAL; | |
9112 | ||
57afe2f0 | 9113 | ext_attr->constellation = channel->constellation; |
63713517 | 9114 | if (channel->mirror == DRX_MIRROR_AUTO) |
57afe2f0 | 9115 | ext_attr->mirror = DRX_MIRROR_NO; |
63713517 | 9116 | else |
57afe2f0 | 9117 | ext_attr->mirror = channel->mirror; |
938f11fa | 9118 | |
068e94ea | 9119 | rc = set_qam(demod, channel, tuner_freq_offset, QAM_SET_OP_ALL); |
9482354f | 9120 | if (rc != 0) { |
068e94ea MCC |
9121 | pr_err("error %d\n", rc); |
9122 | goto rw_error; | |
9123 | } | |
443f18d0 | 9124 | |
938f11fa MCC |
9125 | if (channel->constellation == DRX_CONSTELLATION_QAM64) |
9126 | rc = qam64auto(demod, channel, tuner_freq_offset, | |
9127 | &lock_status); | |
9128 | else | |
9129 | rc = qam256auto(demod, channel, tuner_freq_offset, | |
9130 | &lock_status); | |
9131 | if (rc != 0) { | |
9132 | pr_err("error %d\n", rc); | |
9133 | goto rw_error; | |
9134 | } | |
9135 | break; | |
9136 | case DRX_CONSTELLATION_AUTO: /* for channel scan */ | |
9137 | if (ext_attr->standard == DRX_STANDARD_ITU_B) { | |
9138 | u16 qam_ctl_ena = 0; | |
9139 | ||
9140 | auto_flag = true; | |
9141 | ||
9142 | /* try to lock default QAM constellation: QAM256 */ | |
9143 | channel->constellation = DRX_CONSTELLATION_QAM256; | |
9144 | ext_attr->constellation = DRX_CONSTELLATION_QAM256; | |
9145 | if (channel->mirror == DRX_MIRROR_AUTO) | |
9146 | ext_attr->mirror = DRX_MIRROR_NO; | |
9147 | else | |
9148 | ext_attr->mirror = channel->mirror; | |
9149 | rc = set_qam(demod, channel, tuner_freq_offset, | |
9150 | QAM_SET_OP_ALL); | |
9482354f | 9151 | if (rc != 0) { |
068e94ea MCC |
9152 | pr_err("error %d\n", rc); |
9153 | goto rw_error; | |
9154 | } | |
938f11fa MCC |
9155 | rc = qam256auto(demod, channel, tuner_freq_offset, |
9156 | &lock_status); | |
9482354f | 9157 | if (rc != 0) { |
068e94ea MCC |
9158 | pr_err("error %d\n", rc); |
9159 | goto rw_error; | |
9160 | } | |
938f11fa MCC |
9161 | |
9162 | if (lock_status >= DRX_LOCKED) { | |
9163 | channel->constellation = DRX_CONSTELLATION_AUTO; | |
9164 | break; | |
9165 | } | |
9166 | ||
9167 | /* QAM254 not locked. Try QAM64 constellation */ | |
9168 | channel->constellation = DRX_CONSTELLATION_QAM64; | |
9169 | ext_attr->constellation = DRX_CONSTELLATION_QAM64; | |
63713517 | 9170 | if (channel->mirror == DRX_MIRROR_AUTO) |
57afe2f0 | 9171 | ext_attr->mirror = DRX_MIRROR_NO; |
63713517 | 9172 | else |
57afe2f0 | 9173 | ext_attr->mirror = channel->mirror; |
938f11fa | 9174 | |
244c0e06 | 9175 | rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, |
938f11fa MCC |
9176 | SCU_RAM_QAM_CTL_ENA__A, |
9177 | &qam_ctl_ena, 0); | |
9482354f | 9178 | if (rc != 0) { |
068e94ea MCC |
9179 | pr_err("error %d\n", rc); |
9180 | goto rw_error; | |
9181 | } | |
244c0e06 | 9182 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, |
938f11fa MCC |
9183 | SCU_RAM_QAM_CTL_ENA__A, |
9184 | qam_ctl_ena & ~SCU_RAM_QAM_CTL_ENA_ACQ__M, 0); | |
9482354f | 9185 | if (rc != 0) { |
068e94ea MCC |
9186 | pr_err("error %d\n", rc); |
9187 | goto rw_error; | |
9188 | } | |
244c0e06 | 9189 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, |
938f11fa MCC |
9190 | SCU_RAM_QAM_FSM_STATE_TGT__A, |
9191 | 0x2, 0); | |
9192 | if (rc != 0) { | |
9193 | pr_err("error %d\n", rc); | |
9194 | goto rw_error; | |
9195 | } /* force to rate hunting */ | |
443f18d0 | 9196 | |
938f11fa MCC |
9197 | rc = set_qam(demod, channel, tuner_freq_offset, |
9198 | QAM_SET_OP_CONSTELLATION); | |
9199 | if (rc != 0) { | |
9200 | pr_err("error %d\n", rc); | |
9201 | goto rw_error; | |
9202 | } | |
244c0e06 | 9203 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, |
938f11fa MCC |
9204 | SCU_RAM_QAM_CTL_ENA__A, |
9205 | qam_ctl_ena, 0); | |
9206 | if (rc != 0) { | |
9207 | pr_err("error %d\n", rc); | |
9208 | goto rw_error; | |
9209 | } | |
068e94ea | 9210 | |
938f11fa MCC |
9211 | rc = qam64auto(demod, channel, tuner_freq_offset, |
9212 | &lock_status); | |
9213 | if (rc != 0) { | |
9214 | pr_err("error %d\n", rc); | |
9215 | goto rw_error; | |
443f18d0 | 9216 | } |
938f11fa | 9217 | |
443f18d0 | 9218 | channel->constellation = DRX_CONSTELLATION_AUTO; |
57afe2f0 | 9219 | } else if (ext_attr->standard == DRX_STANDARD_ITU_C) { |
938f11fa MCC |
9220 | u16 qam_ctl_ena = 0; |
9221 | ||
443f18d0 | 9222 | channel->constellation = DRX_CONSTELLATION_QAM64; |
57afe2f0 MCC |
9223 | ext_attr->constellation = DRX_CONSTELLATION_QAM64; |
9224 | auto_flag = true; | |
443f18d0 | 9225 | |
63713517 | 9226 | if (channel->mirror == DRX_MIRROR_AUTO) |
57afe2f0 | 9227 | ext_attr->mirror = DRX_MIRROR_NO; |
63713517 | 9228 | else |
57afe2f0 | 9229 | ext_attr->mirror = channel->mirror; |
244c0e06 | 9230 | rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, |
938f11fa MCC |
9231 | SCU_RAM_QAM_CTL_ENA__A, |
9232 | &qam_ctl_ena, 0); | |
9233 | if (rc != 0) { | |
9234 | pr_err("error %d\n", rc); | |
9235 | goto rw_error; | |
9236 | } | |
244c0e06 | 9237 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, |
938f11fa MCC |
9238 | SCU_RAM_QAM_CTL_ENA__A, |
9239 | qam_ctl_ena & ~SCU_RAM_QAM_CTL_ENA_ACQ__M, 0); | |
9240 | if (rc != 0) { | |
9241 | pr_err("error %d\n", rc); | |
9242 | goto rw_error; | |
9243 | } | |
244c0e06 | 9244 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, |
938f11fa MCC |
9245 | SCU_RAM_QAM_FSM_STATE_TGT__A, |
9246 | 0x2, 0); | |
9247 | if (rc != 0) { | |
9248 | pr_err("error %d\n", rc); | |
9249 | goto rw_error; | |
9250 | } /* force to rate hunting */ | |
068e94ea | 9251 | |
938f11fa MCC |
9252 | rc = set_qam(demod, channel, tuner_freq_offset, |
9253 | QAM_SET_OP_CONSTELLATION); | |
9254 | if (rc != 0) { | |
9255 | pr_err("error %d\n", rc); | |
9256 | goto rw_error; | |
068e94ea | 9257 | } |
244c0e06 | 9258 | rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, |
938f11fa MCC |
9259 | SCU_RAM_QAM_CTL_ENA__A, |
9260 | qam_ctl_ena, 0); | |
9261 | if (rc != 0) { | |
9262 | pr_err("error %d\n", rc); | |
9263 | goto rw_error; | |
9264 | } | |
9265 | rc = qam64auto(demod, channel, tuner_freq_offset, | |
9266 | &lock_status); | |
9482354f | 9267 | if (rc != 0) { |
068e94ea MCC |
9268 | pr_err("error %d\n", rc); |
9269 | goto rw_error; | |
9270 | } | |
443f18d0 MCC |
9271 | channel->constellation = DRX_CONSTELLATION_AUTO; |
9272 | } else { | |
9482354f | 9273 | return -EINVAL; |
443f18d0 MCC |
9274 | } |
9275 | break; | |
9276 | default: | |
9482354f | 9277 | return -EINVAL; |
443f18d0 | 9278 | } |
38b2df95 | 9279 | |
9482354f | 9280 | return 0; |
38b2df95 | 9281 | rw_error: |
443f18d0 | 9282 | /* restore starting value */ |
57afe2f0 | 9283 | if (auto_flag) |
443f18d0 | 9284 | channel->constellation = DRX_CONSTELLATION_AUTO; |
30741871 | 9285 | return rc; |
38b2df95 DH |
9286 | } |
9287 | ||
9288 | /*============================================================================*/ | |
9289 | ||
34eb9751 | 9290 | /* |
e33f2193 | 9291 | * \fn static short get_qamrs_err_count(struct i2c_device_addr *dev_addr) |
38b2df95 DH |
9292 | * \brief Get RS error count in QAM mode (used for post RS BER calculation) |
9293 | * \return Error code | |
9294 | * | |
9295 | * precondition: measurement period & measurement prescale must be set | |
9296 | * | |
9297 | */ | |
61263c75 | 9298 | static int |
69832578 MCC |
9299 | get_qamrs_err_count(struct i2c_device_addr *dev_addr, |
9300 | struct drxjrs_errors *rs_errors) | |
38b2df95 | 9301 | { |
068e94ea | 9302 | int rc; |
57afe2f0 MCC |
9303 | u16 nr_bit_errors = 0, |
9304 | nr_symbol_errors = 0, | |
9305 | nr_packet_errors = 0, nr_failures = 0, nr_snc_par_fail_count = 0; | |
443f18d0 MCC |
9306 | |
9307 | /* check arguments */ | |
63713517 | 9308 | if (dev_addr == NULL) |
9482354f | 9309 | return -EINVAL; |
443f18d0 MCC |
9310 | |
9311 | /* all reported errors are received in the */ | |
9312 | /* most recently finished measurment period */ | |
9313 | /* no of pre RS bit errors */ | |
244c0e06 | 9314 | rc = drxj_dap_read_reg16(dev_addr, FEC_RS_NR_BIT_ERRORS__A, &nr_bit_errors, 0); |
9482354f | 9315 | if (rc != 0) { |
068e94ea MCC |
9316 | pr_err("error %d\n", rc); |
9317 | goto rw_error; | |
9318 | } | |
443f18d0 | 9319 | /* no of symbol errors */ |
244c0e06 | 9320 | rc = drxj_dap_read_reg16(dev_addr, FEC_RS_NR_SYMBOL_ERRORS__A, &nr_symbol_errors, 0); |
9482354f | 9321 | if (rc != 0) { |
068e94ea MCC |
9322 | pr_err("error %d\n", rc); |
9323 | goto rw_error; | |
9324 | } | |
443f18d0 | 9325 | /* no of packet errors */ |
244c0e06 | 9326 | rc = drxj_dap_read_reg16(dev_addr, FEC_RS_NR_PACKET_ERRORS__A, &nr_packet_errors, 0); |
9482354f | 9327 | if (rc != 0) { |
068e94ea MCC |
9328 | pr_err("error %d\n", rc); |
9329 | goto rw_error; | |
9330 | } | |
443f18d0 | 9331 | /* no of failures to decode */ |
244c0e06 | 9332 | rc = drxj_dap_read_reg16(dev_addr, FEC_RS_NR_FAILURES__A, &nr_failures, 0); |
9482354f | 9333 | if (rc != 0) { |
068e94ea MCC |
9334 | pr_err("error %d\n", rc); |
9335 | goto rw_error; | |
9336 | } | |
443f18d0 | 9337 | /* no of post RS bit erros */ |
244c0e06 | 9338 | rc = drxj_dap_read_reg16(dev_addr, FEC_OC_SNC_FAIL_COUNT__A, &nr_snc_par_fail_count, 0); |
9482354f | 9339 | if (rc != 0) { |
068e94ea MCC |
9340 | pr_err("error %d\n", rc); |
9341 | goto rw_error; | |
9342 | } | |
443f18d0 MCC |
9343 | /* TODO: NOTE */ |
9344 | /* These register values are fetched in non-atomic fashion */ | |
9345 | /* It is possible that the read values contain unrelated information */ | |
9346 | ||
57afe2f0 MCC |
9347 | rs_errors->nr_bit_errors = nr_bit_errors & FEC_RS_NR_BIT_ERRORS__M; |
9348 | rs_errors->nr_symbol_errors = nr_symbol_errors & FEC_RS_NR_SYMBOL_ERRORS__M; | |
9349 | rs_errors->nr_packet_errors = nr_packet_errors & FEC_RS_NR_PACKET_ERRORS__M; | |
9350 | rs_errors->nr_failures = nr_failures & FEC_RS_NR_FAILURES__M; | |
9351 | rs_errors->nr_snc_par_fail_count = | |
9352 | nr_snc_par_fail_count & FEC_OC_SNC_FAIL_COUNT__M; | |
443f18d0 | 9353 | |
9482354f | 9354 | return 0; |
38b2df95 | 9355 | rw_error: |
30741871 | 9356 | return rc; |
38b2df95 DH |
9357 | } |
9358 | ||
9359 | /*============================================================================*/ | |
9360 | ||
34eb9751 | 9361 | /* |
80e5ed14 MCC |
9362 | * \fn int get_sig_strength() |
9363 | * \brief Retrieve signal strength for VSB and QAM. | |
9364 | * \param demod Pointer to demod instance | |
9365 | * \param u16-t Pointer to signal strength data; range 0, .. , 100. | |
9366 | * \return int. | |
9367 | * \retval 0 sig_strength contains valid data. | |
9368 | * \retval -EINVAL sig_strength is NULL. | |
9369 | * \retval -EIO Erroneous data, sig_strength contains invalid data. | |
9370 | */ | |
9371 | #define DRXJ_AGC_TOP 0x2800 | |
9372 | #define DRXJ_AGC_SNS 0x1600 | |
9373 | #define DRXJ_RFAGC_MAX 0x3fff | |
9374 | #define DRXJ_RFAGC_MIN 0x800 | |
9375 | ||
9376 | static int get_sig_strength(struct drx_demod_instance *demod, u16 *sig_strength) | |
9377 | { | |
9378 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; | |
9379 | int rc; | |
9380 | u16 rf_gain = 0; | |
9381 | u16 if_gain = 0; | |
9382 | u16 if_agc_sns = 0; | |
9383 | u16 if_agc_top = 0; | |
9384 | u16 rf_agc_max = 0; | |
9385 | u16 rf_agc_min = 0; | |
9386 | ||
9387 | rc = drxj_dap_read_reg16(dev_addr, IQM_AF_AGC_IF__A, &if_gain, 0); | |
9388 | if (rc != 0) { | |
9389 | pr_err("error %d\n", rc); | |
9390 | goto rw_error; | |
9391 | } | |
9392 | if_gain &= IQM_AF_AGC_IF__M; | |
9393 | rc = drxj_dap_read_reg16(dev_addr, IQM_AF_AGC_RF__A, &rf_gain, 0); | |
9394 | if (rc != 0) { | |
9395 | pr_err("error %d\n", rc); | |
9396 | goto rw_error; | |
9397 | } | |
9398 | rf_gain &= IQM_AF_AGC_RF__M; | |
9399 | ||
9400 | if_agc_sns = DRXJ_AGC_SNS; | |
9401 | if_agc_top = DRXJ_AGC_TOP; | |
9402 | rf_agc_max = DRXJ_RFAGC_MAX; | |
9403 | rf_agc_min = DRXJ_RFAGC_MIN; | |
9404 | ||
9405 | if (if_gain > if_agc_top) { | |
9406 | if (rf_gain > rf_agc_max) | |
9407 | *sig_strength = 100; | |
9408 | else if (rf_gain > rf_agc_min) { | |
9409 | if (rf_agc_max == rf_agc_min) { | |
9410 | pr_err("error: rf_agc_max == rf_agc_min\n"); | |
9411 | return -EIO; | |
9412 | } | |
9413 | *sig_strength = | |
9414 | 75 + 25 * (rf_gain - rf_agc_min) / (rf_agc_max - | |
9415 | rf_agc_min); | |
9416 | } else | |
9417 | *sig_strength = 75; | |
9418 | } else if (if_gain > if_agc_sns) { | |
9419 | if (if_agc_top == if_agc_sns) { | |
9420 | pr_err("error: if_agc_top == if_agc_sns\n"); | |
9421 | return -EIO; | |
9422 | } | |
9423 | *sig_strength = | |
9424 | 20 + 55 * (if_gain - if_agc_sns) / (if_agc_top - if_agc_sns); | |
9425 | } else { | |
9426 | if (!if_agc_sns) { | |
9427 | pr_err("error: if_agc_sns is zero!\n"); | |
9428 | return -EIO; | |
9429 | } | |
9430 | *sig_strength = (20 * if_gain / if_agc_sns); | |
9431 | } | |
9432 | ||
80846a5c MCC |
9433 | if (*sig_strength <= 7) |
9434 | *sig_strength = 0; | |
9435 | ||
80e5ed14 | 9436 | return 0; |
30741871 SK |
9437 | rw_error: |
9438 | return rc; | |
80e5ed14 MCC |
9439 | } |
9440 | ||
34eb9751 | 9441 | /* |
57afe2f0 | 9442 | * \fn int ctrl_get_qam_sig_quality() |
69bb7ab6 | 9443 | * \brief Retrieve QAM signal quality from device. |
38b2df95 | 9444 | * \param devmod Pointer to demodulator instance. |
57afe2f0 | 9445 | * \param sig_quality Pointer to signal quality data. |
61263c75 | 9446 | * \return int. |
9482354f MCC |
9447 | * \retval 0 sig_quality contains valid data. |
9448 | * \retval -EINVAL sig_quality is NULL. | |
9449 | * \retval -EIO Erroneous data, sig_quality contains invalid data. | |
38b2df95 DH |
9450 | |
9451 | * Pre-condition: Device must be started and in lock. | |
9452 | */ | |
61263c75 | 9453 | static int |
03fdfbfd | 9454 | ctrl_get_qam_sig_quality(struct drx_demod_instance *demod) |
443f18d0 | 9455 | { |
03fdfbfd MCC |
9456 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; |
9457 | struct drxj_data *ext_attr = demod->my_ext_attr; | |
9458 | struct drx39xxj_state *state = dev_addr->user_data; | |
9459 | struct dtv_frontend_properties *p = &state->frontend.dtv_property_cache; | |
b3ce3a83 | 9460 | struct drxjrs_errors measuredrs_errors = { 0, 0, 0, 0, 0 }; |
03fdfbfd MCC |
9461 | enum drx_modulation constellation = ext_attr->constellation; |
9462 | int rc; | |
57afe2f0 MCC |
9463 | |
9464 | u32 pre_bit_err_rs = 0; /* pre RedSolomon Bit Error Rate */ | |
9465 | u32 post_bit_err_rs = 0; /* post RedSolomon Bit Error Rate */ | |
9466 | u32 pkt_errs = 0; /* no of packet errors in RS */ | |
9467 | u16 qam_sl_err_power = 0; /* accumulated error between raw and sliced symbols */ | |
9468 | u16 qsym_err_vd = 0; /* quadrature symbol errors in QAM_VD */ | |
9469 | u16 fec_oc_period = 0; /* SNC sync failure measurement period */ | |
9470 | u16 fec_rs_prescale = 0; /* ReedSolomon Measurement Prescale */ | |
9471 | u16 fec_rs_period = 0; /* Value for corresponding I2C register */ | |
443f18d0 | 9472 | /* calculation constants */ |
57afe2f0 MCC |
9473 | u32 rs_bit_cnt = 0; /* RedSolomon Bit Count */ |
9474 | u32 qam_sl_sig_power = 0; /* used for MER, depends of QAM constellation */ | |
443f18d0 | 9475 | /* intermediate results */ |
43a431e4 MCC |
9476 | u32 e = 0; /* exponent value used for QAM BER/SER */ |
9477 | u32 m = 0; /* mantisa value used for QAM BER/SER */ | |
57afe2f0 | 9478 | u32 ber_cnt = 0; /* BER count */ |
443f18d0 | 9479 | /* signal quality info */ |
57afe2f0 MCC |
9480 | u32 qam_sl_mer = 0; /* QAM MER */ |
9481 | u32 qam_pre_rs_ber = 0; /* Pre RedSolomon BER */ | |
9482 | u32 qam_post_rs_ber = 0; /* Post RedSolomon BER */ | |
9483 | u32 qam_vd_ser = 0; /* ViterbiDecoder SER */ | |
9484 | u16 qam_vd_prescale = 0; /* Viterbi Measurement Prescale */ | |
9485 | u16 qam_vd_period = 0; /* Viterbi Measurement period */ | |
9486 | u32 vd_bit_cnt = 0; /* ViterbiDecoder Bit Count */ | |
443f18d0 | 9487 | |
69832578 MCC |
9488 | p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
9489 | ||
443f18d0 MCC |
9490 | /* read the physical registers */ |
9491 | /* Get the RS error data */ | |
e33f2193 | 9492 | rc = get_qamrs_err_count(dev_addr, &measuredrs_errors); |
9482354f | 9493 | if (rc != 0) { |
068e94ea MCC |
9494 | pr_err("error %d\n", rc); |
9495 | goto rw_error; | |
9496 | } | |
443f18d0 | 9497 | /* get the register value needed for MER */ |
244c0e06 | 9498 | rc = drxj_dap_read_reg16(dev_addr, QAM_SL_ERR_POWER__A, &qam_sl_err_power, 0); |
9482354f | 9499 | if (rc != 0) { |
068e94ea MCC |
9500 | pr_err("error %d\n", rc); |
9501 | goto rw_error; | |
9502 | } | |
443f18d0 | 9503 | /* get the register value needed for post RS BER */ |
244c0e06 | 9504 | rc = drxj_dap_read_reg16(dev_addr, FEC_OC_SNC_FAIL_PERIOD__A, &fec_oc_period, 0); |
9482354f | 9505 | if (rc != 0) { |
068e94ea MCC |
9506 | pr_err("error %d\n", rc); |
9507 | goto rw_error; | |
9508 | } | |
443f18d0 MCC |
9509 | |
9510 | /* get constants needed for signal quality calculation */ | |
57afe2f0 MCC |
9511 | fec_rs_period = ext_attr->fec_rs_period; |
9512 | fec_rs_prescale = ext_attr->fec_rs_prescale; | |
9513 | rs_bit_cnt = fec_rs_period * fec_rs_prescale * ext_attr->fec_rs_plen; | |
9514 | qam_vd_period = ext_attr->qam_vd_period; | |
9515 | qam_vd_prescale = ext_attr->qam_vd_prescale; | |
9516 | vd_bit_cnt = qam_vd_period * qam_vd_prescale * ext_attr->fec_vd_plen; | |
443f18d0 MCC |
9517 | |
9518 | /* DRXJ_QAM_SL_SIG_POWER_QAMxxx * 4 */ | |
9519 | switch (constellation) { | |
9520 | case DRX_CONSTELLATION_QAM16: | |
57afe2f0 | 9521 | qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM16 << 2; |
443f18d0 MCC |
9522 | break; |
9523 | case DRX_CONSTELLATION_QAM32: | |
57afe2f0 | 9524 | qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM32 << 2; |
443f18d0 MCC |
9525 | break; |
9526 | case DRX_CONSTELLATION_QAM64: | |
57afe2f0 | 9527 | qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM64 << 2; |
443f18d0 MCC |
9528 | break; |
9529 | case DRX_CONSTELLATION_QAM128: | |
57afe2f0 | 9530 | qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM128 << 2; |
443f18d0 MCC |
9531 | break; |
9532 | case DRX_CONSTELLATION_QAM256: | |
57afe2f0 | 9533 | qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM256 << 2; |
443f18d0 MCC |
9534 | break; |
9535 | default: | |
9482354f | 9536 | return -EIO; |
443f18d0 | 9537 | } |
38b2df95 | 9538 | |
443f18d0 MCC |
9539 | /* ------------------------------ */ |
9540 | /* MER Calculation */ | |
9541 | /* ------------------------------ */ | |
9542 | /* MER is good if it is above 27.5 for QAM256 or 21.5 for QAM64 */ | |
9543 | ||
9544 | /* 10.0*log10(qam_sl_sig_power * 4.0 / qam_sl_err_power); */ | |
57afe2f0 MCC |
9545 | if (qam_sl_err_power == 0) |
9546 | qam_sl_mer = 0; | |
443f18d0 | 9547 | else |
63713517 | 9548 | qam_sl_mer = log1_times100(qam_sl_sig_power) - log1_times100((u32)qam_sl_err_power); |
443f18d0 MCC |
9549 | |
9550 | /* ----------------------------------------- */ | |
9551 | /* Pre Viterbi Symbol Error Rate Calculation */ | |
9552 | /* ----------------------------------------- */ | |
5a13e40b | 9553 | /* pre viterbi SER is good if it is below 0.025 */ |
443f18d0 MCC |
9554 | |
9555 | /* get the register value */ | |
9556 | /* no of quadrature symbol errors */ | |
244c0e06 | 9557 | rc = drxj_dap_read_reg16(dev_addr, QAM_VD_NR_QSYM_ERRORS__A, &qsym_err_vd, 0); |
9482354f | 9558 | if (rc != 0) { |
068e94ea MCC |
9559 | pr_err("error %d\n", rc); |
9560 | goto rw_error; | |
9561 | } | |
443f18d0 MCC |
9562 | /* Extract the Exponent and the Mantisa */ |
9563 | /* of number of quadrature symbol errors */ | |
57afe2f0 | 9564 | e = (qsym_err_vd & QAM_VD_NR_QSYM_ERRORS_EXP__M) >> |
443f18d0 | 9565 | QAM_VD_NR_QSYM_ERRORS_EXP__B; |
57afe2f0 | 9566 | m = (qsym_err_vd & QAM_VD_NR_SYMBOL_ERRORS_FIXED_MANT__M) >> |
443f18d0 MCC |
9567 | QAM_VD_NR_SYMBOL_ERRORS_FIXED_MANT__B; |
9568 | ||
63713517 | 9569 | if ((m << e) >> 3 > 549752) |
69832578 | 9570 | qam_vd_ser = 500000 * vd_bit_cnt * ((e > 2) ? 1 : 8) / 8; |
63713517 | 9571 | else |
69832578 | 9572 | qam_vd_ser = m << ((e > 2) ? (e - 3) : e); |
38b2df95 | 9573 | |
443f18d0 MCC |
9574 | /* --------------------------------------- */ |
9575 | /* pre and post RedSolomon BER Calculation */ | |
9576 | /* --------------------------------------- */ | |
9577 | /* pre RS BER is good if it is below 3.5e-4 */ | |
9578 | ||
9579 | /* get the register values */ | |
57afe2f0 MCC |
9580 | pre_bit_err_rs = (u32) measuredrs_errors.nr_bit_errors; |
9581 | pkt_errs = post_bit_err_rs = (u32) measuredrs_errors.nr_snc_par_fail_count; | |
443f18d0 MCC |
9582 | |
9583 | /* Extract the Exponent and the Mantisa of the */ | |
9584 | /* pre Reed-Solomon bit error count */ | |
57afe2f0 | 9585 | e = (pre_bit_err_rs & FEC_RS_NR_BIT_ERRORS_EXP__M) >> |
443f18d0 | 9586 | FEC_RS_NR_BIT_ERRORS_EXP__B; |
57afe2f0 | 9587 | m = (pre_bit_err_rs & FEC_RS_NR_BIT_ERRORS_FIXED_MANT__M) >> |
443f18d0 MCC |
9588 | FEC_RS_NR_BIT_ERRORS_FIXED_MANT__B; |
9589 | ||
57afe2f0 | 9590 | ber_cnt = m << e; |
443f18d0 | 9591 | |
57afe2f0 | 9592 | /*qam_pre_rs_ber = frac_times1e6( ber_cnt, rs_bit_cnt ); */ |
63713517 | 9593 | if (m > (rs_bit_cnt >> (e + 1)) || (rs_bit_cnt >> e) == 0) |
69832578 | 9594 | qam_pre_rs_ber = 500000 * rs_bit_cnt >> e; |
63713517 | 9595 | else |
ee0f4a14 | 9596 | qam_pre_rs_ber = ber_cnt; |
38b2df95 | 9597 | |
443f18d0 MCC |
9598 | /* post RS BER = 1000000* (11.17 * FEC_OC_SNC_FAIL_COUNT__A) / */ |
9599 | /* (1504.0 * FEC_OC_SNC_FAIL_PERIOD__A) */ | |
9600 | /* | |
9601 | => c = (1000000*100*11.17)/1504 = | |
9602 | post RS BER = (( c* FEC_OC_SNC_FAIL_COUNT__A) / | |
9603 | (100 * FEC_OC_SNC_FAIL_PERIOD__A) | |
9604 | *100 and /100 is for more precision. | |
9605 | => (20 bits * 12 bits) /(16 bits * 7 bits) => safe in 32 bits computation | |
38b2df95 | 9606 | |
443f18d0 MCC |
9607 | Precision errors still possible. |
9608 | */ | |
b6554ea5 | 9609 | if (!fec_oc_period) { |
57afe2f0 | 9610 | qam_post_rs_ber = 0xFFFFFFFF; |
b6554ea5 MCC |
9611 | } else { |
9612 | e = post_bit_err_rs * 742686; | |
9613 | m = fec_oc_period * 100; | |
57afe2f0 | 9614 | qam_post_rs_ber = e / m; |
b6554ea5 | 9615 | } |
443f18d0 MCC |
9616 | |
9617 | /* fill signal quality data structure */ | |
03fdfbfd MCC |
9618 | p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; |
9619 | p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; | |
9620 | p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; | |
9621 | p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; | |
9622 | p->block_error.stat[0].scale = FE_SCALE_COUNTER; | |
9623 | p->cnr.stat[0].scale = FE_SCALE_DECIBEL; | |
9624 | ||
9625 | p->cnr.stat[0].svalue = ((u16) qam_sl_mer) * 100; | |
69832578 | 9626 | if (ext_attr->standard == DRX_STANDARD_ITU_B) { |
03fdfbfd | 9627 | p->pre_bit_error.stat[0].uvalue += qam_vd_ser; |
69832578 MCC |
9628 | p->pre_bit_count.stat[0].uvalue += vd_bit_cnt * ((e > 2) ? 1 : 8) / 8; |
9629 | } else { | |
03fdfbfd | 9630 | p->pre_bit_error.stat[0].uvalue += qam_pre_rs_ber; |
69832578 MCC |
9631 | p->pre_bit_count.stat[0].uvalue += rs_bit_cnt >> e; |
9632 | } | |
03fdfbfd | 9633 | |
0d49e776 MCC |
9634 | p->post_bit_error.stat[0].uvalue += qam_post_rs_ber; |
9635 | p->post_bit_count.stat[0].uvalue += rs_bit_cnt >> e; | |
03fdfbfd | 9636 | |
03fdfbfd MCC |
9637 | p->block_error.stat[0].uvalue += pkt_errs; |
9638 | ||
38b2df95 | 9639 | #ifdef DRXJ_SIGNAL_ACCUM_ERR |
068e94ea | 9640 | rc = get_acc_pkt_err(demod, &sig_quality->packet_error); |
9482354f | 9641 | if (rc != 0) { |
068e94ea MCC |
9642 | pr_err("error %d\n", rc); |
9643 | goto rw_error; | |
9644 | } | |
38b2df95 DH |
9645 | #endif |
9646 | ||
9482354f | 9647 | return 0; |
443f18d0 | 9648 | rw_error: |
03fdfbfd MCC |
9649 | p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
9650 | p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
9651 | p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
9652 | p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
9653 | p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
9654 | p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
9655 | ||
30741871 | 9656 | return rc; |
38b2df95 DH |
9657 | } |
9658 | ||
38b2df95 DH |
9659 | #endif /* #ifndef DRXJ_VSB_ONLY */ |
9660 | ||
9661 | /*============================================================================*/ | |
9662 | /*== END QAM DATAPATH FUNCTIONS ==*/ | |
9663 | /*============================================================================*/ | |
9664 | ||
9665 | /*============================================================================*/ | |
9666 | /*============================================================================*/ | |
9667 | /*== ATV DATAPATH FUNCTIONS ==*/ | |
9668 | /*============================================================================*/ | |
9669 | /*============================================================================*/ | |
9670 | ||
9671 | /* | |
9672 | Implementation notes. | |
9673 | ||
9674 | NTSC/FM AGCs | |
9675 | ||
9676 | Four AGCs are used for NTSC: | |
9677 | (1) RF (used to attenuate the input signal in case of to much power) | |
9678 | (2) IF (used to attenuate the input signal in case of to much power) | |
9679 | (3) Video AGC (used to amplify the output signal in case input to low) | |
9680 | (4) SIF AGC (used to amplify the output signal in case input to low) | |
9681 | ||
9682 | Video AGC is coupled to RF and IF. SIF AGC is not coupled. It is assumed | |
9683 | that the coupling between Video AGC and the RF and IF AGCs also works in | |
9684 | favor of the SIF AGC. | |
9685 | ||
9686 | Three AGCs are used for FM: | |
9687 | (1) RF (used to attenuate the input signal in case of to much power) | |
9688 | (2) IF (used to attenuate the input signal in case of to much power) | |
9689 | (3) SIF AGC (used to amplify the output signal in case input to low) | |
9690 | ||
9691 | The SIF AGC is now coupled to the RF/IF AGCs. | |
9692 | The SIF AGC is needed for both SIF ouput and the internal SIF signal to | |
9693 | the AUD block. | |
9694 | ||
9695 | RF and IF AGCs DACs are part of AFE, Video and SIF AGC DACs are part of | |
9696 | the ATV block. The AGC control algorithms are all implemented in | |
9697 | microcode. | |
9698 | ||
9699 | ATV SETTINGS | |
9700 | ||
9701 | (Shadow settings will not be used for now, they will be implemented | |
9702 | later on because of the schedule) | |
9703 | ||
9704 | Several HW/SCU "settings" can be used for ATV. The standard selection | |
9705 | will reset most of these settings. To avoid that the end user apllication | |
9706 | has to perform these settings each time the ATV or FM standards is | |
9707 | selected the driver will shadow these settings. This enables the end user | |
57afe2f0 | 9708 | to perform the settings only once after a drx_open(). The driver must |
38b2df95 DH |
9709 | write the shadow settings to HW/SCU incase: |
9710 | ( setstandard FM/ATV) || | |
9711 | ( settings have changed && FM/ATV standard is active) | |
9712 | The shadow settings will be stored in the device specific data container. | |
9713 | A set of flags will be defined to flag changes in shadow settings. | |
9714 | A routine will be implemented to write all changed shadow settings to | |
9715 | HW/SCU. | |
9716 | ||
9717 | The "settings" will consist of: AGC settings, filter settings etc. | |
9718 | ||
9719 | Disadvantage of use of shadow settings: | |
9720 | Direct changes in HW/SCU registers will not be reflected in the | |
9721 | shadow settings and these changes will be overwritten during a next | |
9722 | update. This can happen during evaluation. This will not be a problem | |
9723 | for normal customer usage. | |
9724 | */ | |
9725 | /* -------------------------------------------------------------------------- */ | |
9726 | ||
34eb9751 | 9727 | /* |
b6c4065e MCC |
9728 | * \fn int power_down_atv () |
9729 | * \brief Power down ATV. | |
38b2df95 | 9730 | * \param demod instance of demodulator |
b6c4065e | 9731 | * \param standard either NTSC or FM (sub strandard for ATV ) |
61263c75 | 9732 | * \return int. |
38b2df95 | 9733 | * |
b6c4065e MCC |
9734 | * Stops and thus resets ATV and IQM block |
9735 | * SIF and CVBS ADC are powered down | |
9736 | * Calls audio power down | |
38b2df95 | 9737 | */ |
61263c75 | 9738 | static int |
b6c4065e | 9739 | power_down_atv(struct drx_demod_instance *demod, enum drx_standard standard, bool primary) |
38b2df95 | 9740 | { |
b6c4065e MCC |
9741 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; |
9742 | struct drxjscu_cmd cmd_scu = { /* command */ 0, | |
9743 | /* parameter_len */ 0, | |
9744 | /* result_len */ 0, | |
9745 | /* *parameter */ NULL, | |
9746 | /* *result */ NULL | |
9747 | }; | |
068e94ea | 9748 | int rc; |
b6c4065e | 9749 | u16 cmd_result = 0; |
38b2df95 | 9750 | |
b6c4065e | 9751 | /* ATV NTSC */ |
38b2df95 | 9752 | |
b6c4065e MCC |
9753 | /* Stop ATV SCU (will reset ATV and IQM hardware */ |
9754 | cmd_scu.command = SCU_RAM_COMMAND_STANDARD_ATV | | |
9755 | SCU_RAM_COMMAND_CMD_DEMOD_STOP; | |
9756 | cmd_scu.parameter_len = 0; | |
9757 | cmd_scu.result_len = 1; | |
9758 | cmd_scu.parameter = NULL; | |
9759 | cmd_scu.result = &cmd_result; | |
9760 | rc = scu_command(dev_addr, &cmd_scu); | |
9761 | if (rc != 0) { | |
9762 | pr_err("error %d\n", rc); | |
9763 | goto rw_error; | |
9764 | } | |
9765 | /* Disable ATV outputs (ATV reset enables CVBS, undo this) */ | |
9766 | rc = drxj_dap_write_reg16(dev_addr, ATV_TOP_STDBY__A, (ATV_TOP_STDBY_SIF_STDBY_STANDBY & (~ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE)), 0); | |
9767 | if (rc != 0) { | |
9768 | pr_err("error %d\n", rc); | |
9769 | goto rw_error; | |
443f18d0 | 9770 | } |
38b2df95 | 9771 | |
b6c4065e MCC |
9772 | rc = drxj_dap_write_reg16(dev_addr, ATV_COMM_EXEC__A, ATV_COMM_EXEC_STOP, 0); |
9773 | if (rc != 0) { | |
9774 | pr_err("error %d\n", rc); | |
9775 | goto rw_error; | |
9776 | } | |
9777 | if (primary) { | |
9778 | rc = drxj_dap_write_reg16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP, 0); | |
9482354f | 9779 | if (rc != 0) { |
068e94ea MCC |
9780 | pr_err("error %d\n", rc); |
9781 | goto rw_error; | |
9782 | } | |
b6c4065e | 9783 | rc = set_iqm_af(demod, false); |
9482354f | 9784 | if (rc != 0) { |
068e94ea MCC |
9785 | pr_err("error %d\n", rc); |
9786 | goto rw_error; | |
9787 | } | |
b6c4065e MCC |
9788 | } else { |
9789 | rc = drxj_dap_write_reg16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0); | |
9482354f | 9790 | if (rc != 0) { |
068e94ea MCC |
9791 | pr_err("error %d\n", rc); |
9792 | goto rw_error; | |
9793 | } | |
b6c4065e | 9794 | rc = drxj_dap_write_reg16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0); |
9482354f | 9795 | if (rc != 0) { |
068e94ea MCC |
9796 | pr_err("error %d\n", rc); |
9797 | goto rw_error; | |
9798 | } | |
b6c4065e | 9799 | rc = drxj_dap_write_reg16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0); |
9482354f | 9800 | if (rc != 0) { |
068e94ea MCC |
9801 | pr_err("error %d\n", rc); |
9802 | goto rw_error; | |
9803 | } | |
b6c4065e | 9804 | rc = drxj_dap_write_reg16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0); |
9482354f | 9805 | if (rc != 0) { |
068e94ea MCC |
9806 | pr_err("error %d\n", rc); |
9807 | goto rw_error; | |
9808 | } | |
b6c4065e | 9809 | rc = drxj_dap_write_reg16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0); |
9482354f | 9810 | if (rc != 0) { |
068e94ea MCC |
9811 | pr_err("error %d\n", rc); |
9812 | goto rw_error; | |
9813 | } | |
443f18d0 | 9814 | } |
b6c4065e MCC |
9815 | rc = power_down_aud(demod); |
9816 | if (rc != 0) { | |
9817 | pr_err("error %d\n", rc); | |
9818 | goto rw_error; | |
9819 | } | |
443f18d0 | 9820 | |
9482354f | 9821 | return 0; |
38b2df95 | 9822 | rw_error: |
30741871 | 9823 | return rc; |
38b2df95 DH |
9824 | } |
9825 | ||
b6c4065e MCC |
9826 | /*============================================================================*/ |
9827 | ||
34eb9751 | 9828 | /* |
b6c4065e | 9829 | * \brief Power up AUD. |
38b2df95 | 9830 | * \param demod instance of demodulator |
61263c75 | 9831 | * \return int. |
38b2df95 DH |
9832 | * |
9833 | */ | |
b6c4065e | 9834 | static int power_down_aud(struct drx_demod_instance *demod) |
38b2df95 | 9835 | { |
b6c4065e | 9836 | struct i2c_device_addr *dev_addr = NULL; |
b3ce3a83 | 9837 | struct drxj_data *ext_attr = NULL; |
068e94ea | 9838 | int rc; |
38b2df95 | 9839 | |
b6c4065e | 9840 | dev_addr = (struct i2c_device_addr *)demod->my_i2c_dev_addr; |
b3ce3a83 | 9841 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
443f18d0 | 9842 | |
b6c4065e | 9843 | rc = drxj_dap_write_reg16(dev_addr, AUD_COMM_EXEC__A, AUD_COMM_EXEC_STOP, 0); |
9482354f | 9844 | if (rc != 0) { |
068e94ea MCC |
9845 | pr_err("error %d\n", rc); |
9846 | goto rw_error; | |
9847 | } | |
38b2df95 | 9848 | |
b6c4065e MCC |
9849 | ext_attr->aud_data.audio_is_active = false; |
9850 | ||
9482354f | 9851 | return 0; |
38b2df95 | 9852 | rw_error: |
30741871 | 9853 | return rc; |
38b2df95 DH |
9854 | } |
9855 | ||
34eb9751 | 9856 | /* |
b6c4065e MCC |
9857 | * \fn int set_orx_nsu_aox() |
9858 | * \brief Configure OrxNsuAox for OOB | |
9859 | * \param demod instance of demodulator. | |
9860 | * \param active | |
61263c75 | 9861 | * \return int. |
38b2df95 | 9862 | */ |
b6c4065e | 9863 | static int set_orx_nsu_aox(struct drx_demod_instance *demod, bool active) |
38b2df95 | 9864 | { |
b6c4065e | 9865 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; |
068e94ea | 9866 | int rc; |
b6c4065e | 9867 | u16 data = 0; |
38b2df95 | 9868 | |
b6c4065e MCC |
9869 | /* Configure NSU_AOX */ |
9870 | rc = drxj_dap_read_reg16(dev_addr, ORX_NSU_AOX_STDBY_W__A, &data, 0); | |
9482354f | 9871 | if (rc != 0) { |
068e94ea MCC |
9872 | pr_err("error %d\n", rc); |
9873 | goto rw_error; | |
9874 | } | |
b6c4065e MCC |
9875 | if (!active) |
9876 | 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)); | |
9877 | else | |
9878 | 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); | |
9879 | rc = drxj_dap_write_reg16(dev_addr, ORX_NSU_AOX_STDBY_W__A, data, 0); | |
9482354f | 9880 | if (rc != 0) { |
068e94ea MCC |
9881 | pr_err("error %d\n", rc); |
9882 | goto rw_error; | |
9883 | } | |
38b2df95 | 9884 | |
9482354f | 9885 | return 0; |
38b2df95 | 9886 | rw_error: |
30741871 | 9887 | return rc; |
38b2df95 DH |
9888 | } |
9889 | ||
34eb9751 | 9890 | /* |
b6c4065e MCC |
9891 | * \fn int ctrl_set_oob() |
9892 | * \brief Set OOB channel to be used. | |
38b2df95 | 9893 | * \param demod instance of demodulator |
b6c4065e MCC |
9894 | * \param oob_param OOB parameters for channel setting. |
9895 | * \frequency should be in KHz | |
61263c75 | 9896 | * \return int. |
38b2df95 | 9897 | * |
b6c4065e MCC |
9898 | * Accepts only. Returns error otherwise. |
9899 | * Demapper value is written after scu_command START | |
9900 | * because START command causes COMM_EXEC transition | |
9901 | * from 0 to 1 which causes all registers to be | |
9902 | * overwritten with initial value | |
38b2df95 DH |
9903 | * |
9904 | */ | |
38b2df95 | 9905 | |
b6c4065e MCC |
9906 | /* Nyquist filter impulse response */ |
9907 | #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 */ | |
9908 | #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 */ | |
9909 | #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) */ | |
38b2df95 | 9910 | |
b6c4065e MCC |
9911 | /* Coefficients for the nyquist fitler (total: 27 taps) */ |
9912 | #define NYQFILTERLEN 27 | |
38b2df95 | 9913 | |
b6c4065e | 9914 | static int ctrl_set_oob(struct drx_demod_instance *demod, struct drxoob *oob_param) |
38b2df95 | 9915 | { |
068e94ea | 9916 | int rc; |
b6c4065e MCC |
9917 | s32 freq = 0; /* KHz */ |
9918 | struct i2c_device_addr *dev_addr = NULL; | |
b3ce3a83 | 9919 | struct drxj_data *ext_attr = NULL; |
b6c4065e MCC |
9920 | u16 i = 0; |
9921 | bool mirror_freq_spect_oob = false; | |
9922 | u16 trk_filter_value = 0; | |
9923 | struct drxjscu_cmd scu_cmd; | |
9924 | u16 set_param_parameters[3]; | |
9925 | u16 cmd_result[2] = { 0, 0 }; | |
9926 | s16 nyquist_coeffs[4][(NYQFILTERLEN + 1) / 2] = { | |
9927 | IMPULSE_COSINE_ALPHA_0_3, /* Target Mode 0 */ | |
9928 | IMPULSE_COSINE_ALPHA_0_3, /* Target Mode 1 */ | |
9929 | IMPULSE_COSINE_ALPHA_0_5, /* Target Mode 2 */ | |
9930 | IMPULSE_COSINE_ALPHA_RO_0_5 /* Target Mode 3 */ | |
9931 | }; | |
9932 | u8 mode_val[4] = { 2, 2, 0, 1 }; | |
9933 | u8 pfi_coeffs[4][6] = { | |
9934 | {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) */ | |
9935 | {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) */ | |
9936 | {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) */ | |
9937 | {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) */ | |
9938 | }; | |
9939 | u16 mode_index; | |
38b2df95 | 9940 | |
b6c4065e | 9941 | dev_addr = demod->my_i2c_dev_addr; |
b3ce3a83 | 9942 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
b6c4065e | 9943 | mirror_freq_spect_oob = ext_attr->mirror_freq_spect_oob; |
38b2df95 | 9944 | |
b6c4065e MCC |
9945 | /* Check parameters */ |
9946 | if (oob_param == NULL) { | |
9947 | /* power off oob module */ | |
9948 | scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB | |
9949 | | SCU_RAM_COMMAND_CMD_DEMOD_STOP; | |
9950 | scu_cmd.parameter_len = 0; | |
9951 | scu_cmd.result_len = 1; | |
9952 | scu_cmd.result = cmd_result; | |
9953 | rc = scu_command(dev_addr, &scu_cmd); | |
9954 | if (rc != 0) { | |
9955 | pr_err("error %d\n", rc); | |
9956 | goto rw_error; | |
9957 | } | |
9958 | rc = set_orx_nsu_aox(demod, false); | |
9959 | if (rc != 0) { | |
9960 | pr_err("error %d\n", rc); | |
9961 | goto rw_error; | |
9962 | } | |
9963 | rc = drxj_dap_write_reg16(dev_addr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_STOP, 0); | |
9482354f | 9964 | if (rc != 0) { |
068e94ea MCC |
9965 | pr_err("error %d\n", rc); |
9966 | goto rw_error; | |
9967 | } | |
38b2df95 | 9968 | |
b6c4065e MCC |
9969 | ext_attr->oob_power_on = false; |
9970 | return 0; | |
9971 | } | |
443f18d0 | 9972 | |
b6c4065e MCC |
9973 | freq = oob_param->frequency; |
9974 | if ((freq < 70000) || (freq > 130000)) | |
9975 | return -EIO; | |
9976 | freq = (freq - 50000) / 50; | |
443f18d0 | 9977 | |
b6c4065e MCC |
9978 | { |
9979 | u16 index = 0; | |
9980 | u16 remainder = 0; | |
9981 | u16 *trk_filtercfg = ext_attr->oob_trk_filter_cfg; | |
443f18d0 | 9982 | |
b6c4065e MCC |
9983 | index = (u16) ((freq - 400) / 200); |
9984 | remainder = (u16) ((freq - 400) % 200); | |
9985 | trk_filter_value = | |
9986 | trk_filtercfg[index] - (trk_filtercfg[index] - | |
9987 | trk_filtercfg[index + | |
9988 | 1]) / 10 * remainder / | |
9989 | 20; | |
068e94ea | 9990 | } |
443f18d0 | 9991 | |
34eb9751 | 9992 | /********/ |
b6c4065e | 9993 | /* Stop */ |
34eb9751 | 9994 | /********/ |
b6c4065e | 9995 | rc = drxj_dap_write_reg16(dev_addr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_STOP, 0); |
9482354f | 9996 | if (rc != 0) { |
068e94ea MCC |
9997 | pr_err("error %d\n", rc); |
9998 | goto rw_error; | |
9999 | } | |
b6c4065e MCC |
10000 | scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB |
10001 | | SCU_RAM_COMMAND_CMD_DEMOD_STOP; | |
10002 | scu_cmd.parameter_len = 0; | |
10003 | scu_cmd.result_len = 1; | |
10004 | scu_cmd.result = cmd_result; | |
10005 | rc = scu_command(dev_addr, &scu_cmd); | |
9482354f | 10006 | if (rc != 0) { |
068e94ea MCC |
10007 | pr_err("error %d\n", rc); |
10008 | goto rw_error; | |
10009 | } | |
34eb9751 | 10010 | /********/ |
b6c4065e | 10011 | /* Reset */ |
34eb9751 | 10012 | /********/ |
b6c4065e MCC |
10013 | scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB |
10014 | | SCU_RAM_COMMAND_CMD_DEMOD_RESET; | |
10015 | scu_cmd.parameter_len = 0; | |
10016 | scu_cmd.result_len = 1; | |
10017 | scu_cmd.result = cmd_result; | |
10018 | rc = scu_command(dev_addr, &scu_cmd); | |
10019 | if (rc != 0) { | |
068e94ea MCC |
10020 | pr_err("error %d\n", rc); |
10021 | goto rw_error; | |
10022 | } | |
34eb9751 | 10023 | /**********/ |
b6c4065e | 10024 | /* SET_ENV */ |
34eb9751 | 10025 | /**********/ |
b6c4065e MCC |
10026 | /* set frequency, spectrum inversion and data rate */ |
10027 | scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB | |
10028 | | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV; | |
10029 | scu_cmd.parameter_len = 3; | |
10030 | /* 1-data rate;2-frequency */ | |
10031 | switch (oob_param->standard) { | |
10032 | case DRX_OOB_MODE_A: | |
10033 | if ( | |
10034 | /* signal is transmitted inverted */ | |
10035 | ((oob_param->spectrum_inverted == true) && | |
10036 | /* and tuner is not mirroring the signal */ | |
10037 | (!mirror_freq_spect_oob)) | | |
10038 | /* or */ | |
10039 | /* signal is transmitted noninverted */ | |
10040 | ((oob_param->spectrum_inverted == false) && | |
10041 | /* and tuner is mirroring the signal */ | |
10042 | (mirror_freq_spect_oob)) | |
10043 | ) | |
10044 | set_param_parameters[0] = | |
10045 | SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC; | |
10046 | else | |
10047 | set_param_parameters[0] = | |
10048 | SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC; | |
10049 | break; | |
10050 | case DRX_OOB_MODE_B_GRADE_A: | |
10051 | if ( | |
10052 | /* signal is transmitted inverted */ | |
10053 | ((oob_param->spectrum_inverted == true) && | |
10054 | /* and tuner is not mirroring the signal */ | |
10055 | (!mirror_freq_spect_oob)) | | |
10056 | /* or */ | |
10057 | /* signal is transmitted noninverted */ | |
10058 | ((oob_param->spectrum_inverted == false) && | |
10059 | /* and tuner is mirroring the signal */ | |
10060 | (mirror_freq_spect_oob)) | |
10061 | ) | |
10062 | set_param_parameters[0] = | |
10063 | SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_INVSPEC; | |
10064 | else | |
10065 | set_param_parameters[0] = | |
10066 | SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_REGSPEC; | |
10067 | break; | |
10068 | case DRX_OOB_MODE_B_GRADE_B: | |
10069 | default: | |
10070 | if ( | |
10071 | /* signal is transmitted inverted */ | |
10072 | ((oob_param->spectrum_inverted == true) && | |
10073 | /* and tuner is not mirroring the signal */ | |
10074 | (!mirror_freq_spect_oob)) | | |
10075 | /* or */ | |
10076 | /* signal is transmitted noninverted */ | |
10077 | ((oob_param->spectrum_inverted == false) && | |
10078 | /* and tuner is mirroring the signal */ | |
10079 | (mirror_freq_spect_oob)) | |
10080 | ) | |
10081 | set_param_parameters[0] = | |
10082 | SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_INVSPEC; | |
10083 | else | |
10084 | set_param_parameters[0] = | |
10085 | SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_REGSPEC; | |
10086 | break; | |
10087 | } | |
10088 | set_param_parameters[1] = (u16) (freq & 0xFFFF); | |
10089 | set_param_parameters[2] = trk_filter_value; | |
10090 | scu_cmd.parameter = set_param_parameters; | |
10091 | scu_cmd.result_len = 1; | |
10092 | scu_cmd.result = cmd_result; | |
10093 | mode_index = mode_val[(set_param_parameters[0] & 0xC0) >> 6]; | |
10094 | rc = scu_command(dev_addr, &scu_cmd); | |
9482354f | 10095 | if (rc != 0) { |
068e94ea MCC |
10096 | pr_err("error %d\n", rc); |
10097 | goto rw_error; | |
10098 | } | |
38b2df95 | 10099 | |
b6c4065e MCC |
10100 | rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA, 0); |
10101 | if (rc != 0) { | |
10102 | pr_err("error %d\n", rc); | |
10103 | goto rw_error; | |
10104 | } /* Write magic word to enable pdr reg write */ | |
10105 | rc = drxj_dap_write_reg16(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); | |
10106 | if (rc != 0) { | |
10107 | pr_err("error %d\n", rc); | |
10108 | goto rw_error; | |
10109 | } | |
10110 | rc = drxj_dap_write_reg16(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); | |
10111 | if (rc != 0) { | |
10112 | pr_err("error %d\n", rc); | |
10113 | goto rw_error; | |
10114 | } | |
10115 | rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0); | |
10116 | if (rc != 0) { | |
10117 | pr_err("error %d\n", rc); | |
10118 | goto rw_error; | |
10119 | } /* Write magic word to disable pdr reg write */ | |
38b2df95 | 10120 | |
b6c4065e | 10121 | rc = drxj_dap_write_reg16(dev_addr, ORX_TOP_COMM_KEY__A, 0, 0); |
9482354f | 10122 | if (rc != 0) { |
068e94ea MCC |
10123 | pr_err("error %d\n", rc); |
10124 | goto rw_error; | |
10125 | } | |
b6c4065e | 10126 | rc = drxj_dap_write_reg16(dev_addr, ORX_FWP_AAG_LEN_W__A, 16000, 0); |
9482354f | 10127 | if (rc != 0) { |
068e94ea MCC |
10128 | pr_err("error %d\n", rc); |
10129 | goto rw_error; | |
10130 | } | |
b6c4065e | 10131 | rc = drxj_dap_write_reg16(dev_addr, ORX_FWP_AAG_THR_W__A, 40, 0); |
9482354f | 10132 | if (rc != 0) { |
068e94ea MCC |
10133 | pr_err("error %d\n", rc); |
10134 | goto rw_error; | |
10135 | } | |
38b2df95 | 10136 | |
b6c4065e MCC |
10137 | /* ddc */ |
10138 | rc = drxj_dap_write_reg16(dev_addr, ORX_DDC_OFO_SET_W__A, ORX_DDC_OFO_SET_W__PRE, 0); | |
9482354f | 10139 | if (rc != 0) { |
068e94ea MCC |
10140 | pr_err("error %d\n", rc); |
10141 | goto rw_error; | |
10142 | } | |
38b2df95 | 10143 | |
b6c4065e MCC |
10144 | /* nsu */ |
10145 | rc = drxj_dap_write_reg16(dev_addr, ORX_NSU_AOX_LOPOW_W__A, ext_attr->oob_lo_pow, 0); | |
10146 | if (rc != 0) { | |
10147 | pr_err("error %d\n", rc); | |
10148 | goto rw_error; | |
10149 | } | |
443f18d0 | 10150 | |
b6c4065e MCC |
10151 | /* initialization for target mode */ |
10152 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_TARGET_MODE__A, SCU_RAM_ORX_TARGET_MODE_2048KBPS_SQRT, 0); | |
9482354f | 10153 | if (rc != 0) { |
068e94ea MCC |
10154 | pr_err("error %d\n", rc); |
10155 | goto rw_error; | |
10156 | } | |
b6c4065e | 10157 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_FREQ_GAIN_CORR__A, SCU_RAM_ORX_FREQ_GAIN_CORR_2048KBPS, 0); |
9482354f | 10158 | if (rc != 0) { |
068e94ea MCC |
10159 | pr_err("error %d\n", rc); |
10160 | goto rw_error; | |
10161 | } | |
443f18d0 | 10162 | |
b6c4065e MCC |
10163 | /* Reset bits for timing and freq. recovery */ |
10164 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_RST_CPH__A, 0x0001, 0); | |
9482354f | 10165 | if (rc != 0) { |
068e94ea MCC |
10166 | pr_err("error %d\n", rc); |
10167 | goto rw_error; | |
10168 | } | |
b6c4065e MCC |
10169 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_RST_CTI__A, 0x0002, 0); |
10170 | if (rc != 0) { | |
10171 | pr_err("error %d\n", rc); | |
10172 | goto rw_error; | |
068e94ea | 10173 | } |
b6c4065e MCC |
10174 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_RST_KRN__A, 0x0004, 0); |
10175 | if (rc != 0) { | |
10176 | pr_err("error %d\n", rc); | |
10177 | goto rw_error; | |
10178 | } | |
10179 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_RST_KRP__A, 0x0008, 0); | |
9482354f | 10180 | if (rc != 0) { |
068e94ea MCC |
10181 | pr_err("error %d\n", rc); |
10182 | goto rw_error; | |
443f18d0 | 10183 | } |
443f18d0 | 10184 | |
b6c4065e MCC |
10185 | /* AGN_LOCK = {2048>>3, -2048, 8, -8, 0, 1}; */ |
10186 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_AGN_LOCK_TH__A, 2048 >> 3, 0); | |
10187 | if (rc != 0) { | |
10188 | pr_err("error %d\n", rc); | |
10189 | goto rw_error; | |
10190 | } | |
10191 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_AGN_LOCK_TOTH__A, (u16)(-2048), 0); | |
10192 | if (rc != 0) { | |
10193 | pr_err("error %d\n", rc); | |
10194 | goto rw_error; | |
10195 | } | |
10196 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_AGN_ONLOCK_TTH__A, 8, 0); | |
10197 | if (rc != 0) { | |
10198 | pr_err("error %d\n", rc); | |
10199 | goto rw_error; | |
10200 | } | |
10201 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_AGN_UNLOCK_TTH__A, (u16)(-8), 0); | |
10202 | if (rc != 0) { | |
10203 | pr_err("error %d\n", rc); | |
10204 | goto rw_error; | |
10205 | } | |
10206 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_AGN_LOCK_MASK__A, 1, 0); | |
10207 | if (rc != 0) { | |
10208 | pr_err("error %d\n", rc); | |
10209 | goto rw_error; | |
10210 | } | |
443f18d0 | 10211 | |
b6c4065e MCC |
10212 | /* DGN_LOCK = {10, -2048, 8, -8, 0, 1<<1}; */ |
10213 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_DGN_LOCK_TH__A, 10, 0); | |
10214 | if (rc != 0) { | |
10215 | pr_err("error %d\n", rc); | |
10216 | goto rw_error; | |
10217 | } | |
10218 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_DGN_LOCK_TOTH__A, (u16)(-2048), 0); | |
10219 | if (rc != 0) { | |
10220 | pr_err("error %d\n", rc); | |
10221 | goto rw_error; | |
10222 | } | |
10223 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_DGN_ONLOCK_TTH__A, 8, 0); | |
10224 | if (rc != 0) { | |
10225 | pr_err("error %d\n", rc); | |
10226 | goto rw_error; | |
10227 | } | |
10228 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_DGN_UNLOCK_TTH__A, (u16)(-8), 0); | |
10229 | if (rc != 0) { | |
10230 | pr_err("error %d\n", rc); | |
10231 | goto rw_error; | |
10232 | } | |
10233 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_DGN_LOCK_MASK__A, 1 << 1, 0); | |
10234 | if (rc != 0) { | |
10235 | pr_err("error %d\n", rc); | |
10236 | goto rw_error; | |
10237 | } | |
38b2df95 | 10238 | |
b6c4065e MCC |
10239 | /* FRQ_LOCK = {15,-2048, 8, -8, 0, 1<<2}; */ |
10240 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_FRQ_LOCK_TH__A, 17, 0); | |
10241 | if (rc != 0) { | |
10242 | pr_err("error %d\n", rc); | |
10243 | goto rw_error; | |
10244 | } | |
10245 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_FRQ_LOCK_TOTH__A, (u16)(-2048), 0); | |
10246 | if (rc != 0) { | |
10247 | pr_err("error %d\n", rc); | |
10248 | goto rw_error; | |
10249 | } | |
10250 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_FRQ_ONLOCK_TTH__A, 8, 0); | |
10251 | if (rc != 0) { | |
10252 | pr_err("error %d\n", rc); | |
10253 | goto rw_error; | |
10254 | } | |
10255 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_FRQ_UNLOCK_TTH__A, (u16)(-8), 0); | |
10256 | if (rc != 0) { | |
10257 | pr_err("error %d\n", rc); | |
10258 | goto rw_error; | |
10259 | } | |
10260 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_FRQ_LOCK_MASK__A, 1 << 2, 0); | |
10261 | if (rc != 0) { | |
10262 | pr_err("error %d\n", rc); | |
10263 | goto rw_error; | |
10264 | } | |
38b2df95 | 10265 | |
b6c4065e MCC |
10266 | /* PHA_LOCK = {5000, -2048, 8, -8, 0, 1<<3}; */ |
10267 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_PHA_LOCK_TH__A, 3000, 0); | |
9482354f | 10268 | if (rc != 0) { |
63713517 MCC |
10269 | pr_err("error %d\n", rc); |
10270 | goto rw_error; | |
068e94ea | 10271 | } |
b6c4065e | 10272 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_PHA_LOCK_TOTH__A, (u16)(-2048), 0); |
9482354f | 10273 | if (rc != 0) { |
63713517 MCC |
10274 | pr_err("error %d\n", rc); |
10275 | goto rw_error; | |
068e94ea | 10276 | } |
b6c4065e | 10277 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_PHA_ONLOCK_TTH__A, 8, 0); |
9482354f | 10278 | if (rc != 0) { |
63713517 MCC |
10279 | pr_err("error %d\n", rc); |
10280 | goto rw_error; | |
068e94ea | 10281 | } |
b6c4065e | 10282 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_PHA_UNLOCK_TTH__A, (u16)(-8), 0); |
9482354f | 10283 | if (rc != 0) { |
63713517 MCC |
10284 | pr_err("error %d\n", rc); |
10285 | goto rw_error; | |
068e94ea | 10286 | } |
b6c4065e | 10287 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_PHA_LOCK_MASK__A, 1 << 3, 0); |
9482354f | 10288 | if (rc != 0) { |
63713517 MCC |
10289 | pr_err("error %d\n", rc); |
10290 | goto rw_error; | |
068e94ea | 10291 | } |
b6c4065e MCC |
10292 | |
10293 | /* TIM_LOCK = {300, -2048, 8, -8, 0, 1<<4}; */ | |
10294 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_TIM_LOCK_TH__A, 400, 0); | |
9482354f | 10295 | if (rc != 0) { |
63713517 MCC |
10296 | pr_err("error %d\n", rc); |
10297 | goto rw_error; | |
068e94ea | 10298 | } |
b6c4065e MCC |
10299 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_TIM_LOCK_TOTH__A, (u16)(-2048), 0); |
10300 | if (rc != 0) { | |
10301 | pr_err("error %d\n", rc); | |
10302 | goto rw_error; | |
10303 | } | |
10304 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_TIM_ONLOCK_TTH__A, 8, 0); | |
10305 | if (rc != 0) { | |
10306 | pr_err("error %d\n", rc); | |
10307 | goto rw_error; | |
10308 | } | |
10309 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_TIM_UNLOCK_TTH__A, (u16)(-8), 0); | |
10310 | if (rc != 0) { | |
10311 | pr_err("error %d\n", rc); | |
10312 | goto rw_error; | |
10313 | } | |
10314 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_TIM_LOCK_MASK__A, 1 << 4, 0); | |
9482354f | 10315 | if (rc != 0) { |
068e94ea MCC |
10316 | pr_err("error %d\n", rc); |
10317 | goto rw_error; | |
10318 | } | |
443f18d0 | 10319 | |
b6c4065e MCC |
10320 | /* EQU_LOCK = {20, -2048, 8, -8, 0, 1<<5}; */ |
10321 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_EQU_LOCK_TH__A, 20, 0); | |
10322 | if (rc != 0) { | |
10323 | pr_err("error %d\n", rc); | |
10324 | goto rw_error; | |
10325 | } | |
10326 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_EQU_LOCK_TOTH__A, (u16)(-2048), 0); | |
10327 | if (rc != 0) { | |
10328 | pr_err("error %d\n", rc); | |
10329 | goto rw_error; | |
10330 | } | |
10331 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_EQU_ONLOCK_TTH__A, 4, 0); | |
10332 | if (rc != 0) { | |
10333 | pr_err("error %d\n", rc); | |
10334 | goto rw_error; | |
10335 | } | |
10336 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_EQU_UNLOCK_TTH__A, (u16)(-4), 0); | |
10337 | if (rc != 0) { | |
10338 | pr_err("error %d\n", rc); | |
10339 | goto rw_error; | |
10340 | } | |
10341 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_EQU_LOCK_MASK__A, 1 << 5, 0); | |
9482354f | 10342 | if (rc != 0) { |
63713517 MCC |
10343 | pr_err("error %d\n", rc); |
10344 | goto rw_error; | |
068e94ea | 10345 | } |
443f18d0 | 10346 | |
b6c4065e MCC |
10347 | /* PRE-Filter coefficients (PFI) */ |
10348 | rc = drxdap_fasi_write_block(dev_addr, ORX_FWP_PFI_A_W__A, sizeof(pfi_coeffs[mode_index]), ((u8 *)pfi_coeffs[mode_index]), 0); | |
10349 | if (rc != 0) { | |
10350 | pr_err("error %d\n", rc); | |
10351 | goto rw_error; | |
10352 | } | |
10353 | rc = drxj_dap_write_reg16(dev_addr, ORX_TOP_MDE_W__A, mode_index, 0); | |
10354 | if (rc != 0) { | |
10355 | pr_err("error %d\n", rc); | |
10356 | goto rw_error; | |
10357 | } | |
443f18d0 | 10358 | |
b6c4065e MCC |
10359 | /* NYQUIST-Filter coefficients (NYQ) */ |
10360 | for (i = 0; i < (NYQFILTERLEN + 1) / 2; i++) { | |
10361 | rc = drxj_dap_write_reg16(dev_addr, ORX_FWP_NYQ_ADR_W__A, i, 0); | |
9482354f | 10362 | if (rc != 0) { |
63713517 MCC |
10363 | pr_err("error %d\n", rc); |
10364 | goto rw_error; | |
068e94ea | 10365 | } |
b6c4065e | 10366 | rc = drxj_dap_write_reg16(dev_addr, ORX_FWP_NYQ_COF_RW__A, nyquist_coeffs[mode_index][i], 0); |
9482354f | 10367 | if (rc != 0) { |
63713517 MCC |
10368 | pr_err("error %d\n", rc); |
10369 | goto rw_error; | |
068e94ea | 10370 | } |
b6c4065e MCC |
10371 | } |
10372 | rc = drxj_dap_write_reg16(dev_addr, ORX_FWP_NYQ_ADR_W__A, 31, 0); | |
10373 | if (rc != 0) { | |
10374 | pr_err("error %d\n", rc); | |
10375 | goto rw_error; | |
10376 | } | |
10377 | rc = drxj_dap_write_reg16(dev_addr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_ACTIVE, 0); | |
10378 | if (rc != 0) { | |
10379 | pr_err("error %d\n", rc); | |
10380 | goto rw_error; | |
10381 | } | |
34eb9751 | 10382 | /********/ |
b6c4065e | 10383 | /* Start */ |
34eb9751 | 10384 | /********/ |
b6c4065e MCC |
10385 | scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB |
10386 | | SCU_RAM_COMMAND_CMD_DEMOD_START; | |
10387 | scu_cmd.parameter_len = 0; | |
10388 | scu_cmd.result_len = 1; | |
10389 | scu_cmd.result = cmd_result; | |
10390 | rc = scu_command(dev_addr, &scu_cmd); | |
10391 | if (rc != 0) { | |
10392 | pr_err("error %d\n", rc); | |
10393 | goto rw_error; | |
10394 | } | |
068e94ea | 10395 | |
b6c4065e MCC |
10396 | rc = set_orx_nsu_aox(demod, true); |
10397 | if (rc != 0) { | |
10398 | pr_err("error %d\n", rc); | |
10399 | goto rw_error; | |
10400 | } | |
10401 | rc = drxj_dap_write_reg16(dev_addr, ORX_NSU_AOX_STHR_W__A, ext_attr->oob_pre_saw, 0); | |
10402 | if (rc != 0) { | |
10403 | pr_err("error %d\n", rc); | |
10404 | goto rw_error; | |
10405 | } | |
068e94ea | 10406 | |
b6c4065e | 10407 | ext_attr->oob_power_on = true; |
aafdbaa6 | 10408 | |
b6c4065e MCC |
10409 | return 0; |
10410 | rw_error: | |
30741871 | 10411 | return rc; |
aafdbaa6 MCC |
10412 | } |
10413 | ||
b6c4065e MCC |
10414 | /*============================================================================*/ |
10415 | /*== END OOB DATAPATH FUNCTIONS ==*/ | |
10416 | /*============================================================================*/ | |
10417 | ||
10418 | /*============================================================================= | |
10419 | ===== MC command related functions ========================================== | |
10420 | ===========================================================================*/ | |
10421 | ||
10422 | /*============================================================================= | |
10423 | ===== ctrl_set_channel() ========================================================== | |
10424 | ===========================================================================*/ | |
34eb9751 | 10425 | /* |
b6c4065e MCC |
10426 | * \fn int ctrl_set_channel() |
10427 | * \brief Select a new transmission channel. | |
10428 | * \param demod instance of demod. | |
10429 | * \param channel Pointer to channel data. | |
61263c75 | 10430 | * \return int. |
38b2df95 | 10431 | * |
b6c4065e MCC |
10432 | * In case the tuner module is not used and in case of NTSC/FM the pogrammer |
10433 | * must tune the tuner to the centre frequency of the NTSC/FM channel. | |
38b2df95 DH |
10434 | * |
10435 | */ | |
61263c75 | 10436 | static int |
b6c4065e | 10437 | ctrl_set_channel(struct drx_demod_instance *demod, struct drx_channel *channel) |
38b2df95 | 10438 | { |
068e94ea | 10439 | int rc; |
b6c4065e | 10440 | s32 tuner_freq_offset = 0; |
b6c4065e MCC |
10441 | struct drxj_data *ext_attr = NULL; |
10442 | struct i2c_device_addr *dev_addr = NULL; | |
10443 | enum drx_standard standard = DRX_STANDARD_UNKNOWN; | |
b6c4065e MCC |
10444 | #ifndef DRXJ_VSB_ONLY |
10445 | u32 min_symbol_rate = 0; | |
10446 | u32 max_symbol_rate = 0; | |
10447 | int bandwidth_temp = 0; | |
10448 | int bandwidth = 0; | |
10449 | #endif | |
10450 | /*== check arguments ======================================================*/ | |
10451 | if ((demod == NULL) || (channel == NULL)) | |
10452 | return -EINVAL; | |
38b2df95 | 10453 | |
57afe2f0 | 10454 | dev_addr = demod->my_i2c_dev_addr; |
b6c4065e MCC |
10455 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
10456 | standard = ext_attr->standard; | |
38b2df95 | 10457 | |
b6c4065e MCC |
10458 | /* check valid standards */ |
10459 | switch (standard) { | |
10460 | case DRX_STANDARD_8VSB: | |
10461 | #ifndef DRXJ_VSB_ONLY | |
10462 | case DRX_STANDARD_ITU_A: | |
10463 | case DRX_STANDARD_ITU_B: | |
10464 | case DRX_STANDARD_ITU_C: | |
10465 | #endif /* DRXJ_VSB_ONLY */ | |
443f18d0 | 10466 | break; |
b6c4065e | 10467 | case DRX_STANDARD_UNKNOWN: |
443f18d0 | 10468 | default: |
9482354f | 10469 | return -EINVAL; |
443f18d0 | 10470 | } |
38b2df95 | 10471 | |
b6c4065e MCC |
10472 | /* check bandwidth QAM annex B, NTSC and 8VSB */ |
10473 | if ((standard == DRX_STANDARD_ITU_B) || | |
10474 | (standard == DRX_STANDARD_8VSB) || | |
10475 | (standard == DRX_STANDARD_NTSC)) { | |
10476 | switch (channel->bandwidth) { | |
10477 | case DRX_BANDWIDTH_6MHZ: | |
10478 | case DRX_BANDWIDTH_UNKNOWN: /* fall through */ | |
10479 | channel->bandwidth = DRX_BANDWIDTH_6MHZ; | |
10480 | break; | |
10481 | case DRX_BANDWIDTH_8MHZ: /* fall through */ | |
10482 | case DRX_BANDWIDTH_7MHZ: /* fall through */ | |
10483 | default: | |
10484 | return -EINVAL; | |
10485 | } | |
10486 | } | |
10487 | ||
10488 | /* For QAM annex A and annex C: | |
10489 | -check symbolrate and constellation | |
10490 | -derive bandwidth from symbolrate (input bandwidth is ignored) | |
10491 | */ | |
10492 | #ifndef DRXJ_VSB_ONLY | |
10493 | if ((standard == DRX_STANDARD_ITU_A) || | |
10494 | (standard == DRX_STANDARD_ITU_C)) { | |
10495 | struct drxuio_cfg uio_cfg = { DRX_UIO1, DRX_UIO_MODE_FIRMWARE_SAW }; | |
10496 | int bw_rolloff_factor = 0; | |
10497 | ||
10498 | bw_rolloff_factor = (standard == DRX_STANDARD_ITU_A) ? 115 : 113; | |
10499 | min_symbol_rate = DRXJ_QAM_SYMBOLRATE_MIN; | |
10500 | max_symbol_rate = DRXJ_QAM_SYMBOLRATE_MAX; | |
10501 | /* config SMA_TX pin to SAW switch mode */ | |
10502 | rc = ctrl_set_uio_cfg(demod, &uio_cfg); | |
9482354f | 10503 | if (rc != 0) { |
068e94ea MCC |
10504 | pr_err("error %d\n", rc); |
10505 | goto rw_error; | |
10506 | } | |
443f18d0 | 10507 | |
b6c4065e MCC |
10508 | if (channel->symbolrate < min_symbol_rate || |
10509 | channel->symbolrate > max_symbol_rate) { | |
10510 | return -EINVAL; | |
10511 | } | |
aafdbaa6 | 10512 | |
b6c4065e MCC |
10513 | switch (channel->constellation) { |
10514 | case DRX_CONSTELLATION_QAM16: /* fall through */ | |
10515 | case DRX_CONSTELLATION_QAM32: /* fall through */ | |
10516 | case DRX_CONSTELLATION_QAM64: /* fall through */ | |
10517 | case DRX_CONSTELLATION_QAM128: /* fall through */ | |
10518 | case DRX_CONSTELLATION_QAM256: | |
10519 | bandwidth_temp = channel->symbolrate * bw_rolloff_factor; | |
10520 | bandwidth = bandwidth_temp / 100; | |
443f18d0 | 10521 | |
b6c4065e MCC |
10522 | if ((bandwidth_temp % 100) >= 50) |
10523 | bandwidth++; | |
10524 | ||
10525 | if (bandwidth <= 6100000) { | |
10526 | channel->bandwidth = DRX_BANDWIDTH_6MHZ; | |
10527 | } else if ((bandwidth > 6100000) | |
10528 | && (bandwidth <= 7100000)) { | |
10529 | channel->bandwidth = DRX_BANDWIDTH_7MHZ; | |
10530 | } else if (bandwidth > 7100000) { | |
10531 | channel->bandwidth = DRX_BANDWIDTH_8MHZ; | |
068e94ea | 10532 | } |
443f18d0 | 10533 | break; |
b6c4065e MCC |
10534 | default: |
10535 | return -EINVAL; | |
10536 | } | |
10537 | } | |
10538 | ||
10539 | /* For QAM annex B: | |
10540 | -check constellation | |
10541 | */ | |
10542 | if (standard == DRX_STANDARD_ITU_B) { | |
10543 | switch (channel->constellation) { | |
10544 | case DRX_CONSTELLATION_AUTO: | |
10545 | case DRX_CONSTELLATION_QAM256: | |
10546 | case DRX_CONSTELLATION_QAM64: | |
443f18d0 | 10547 | break; |
b6c4065e MCC |
10548 | default: |
10549 | return -EINVAL; | |
10550 | } | |
10551 | ||
10552 | switch (channel->interleavemode) { | |
10553 | case DRX_INTERLEAVEMODE_I128_J1: | |
10554 | case DRX_INTERLEAVEMODE_I128_J1_V2: | |
10555 | case DRX_INTERLEAVEMODE_I128_J2: | |
10556 | case DRX_INTERLEAVEMODE_I64_J2: | |
10557 | case DRX_INTERLEAVEMODE_I128_J3: | |
10558 | case DRX_INTERLEAVEMODE_I32_J4: | |
10559 | case DRX_INTERLEAVEMODE_I128_J4: | |
10560 | case DRX_INTERLEAVEMODE_I16_J8: | |
10561 | case DRX_INTERLEAVEMODE_I128_J5: | |
10562 | case DRX_INTERLEAVEMODE_I8_J16: | |
10563 | case DRX_INTERLEAVEMODE_I128_J6: | |
10564 | case DRX_INTERLEAVEMODE_I128_J7: | |
10565 | case DRX_INTERLEAVEMODE_I128_J8: | |
10566 | case DRX_INTERLEAVEMODE_I12_J17: | |
10567 | case DRX_INTERLEAVEMODE_I5_J4: | |
10568 | case DRX_INTERLEAVEMODE_B52_M240: | |
10569 | case DRX_INTERLEAVEMODE_B52_M720: | |
10570 | case DRX_INTERLEAVEMODE_UNKNOWN: | |
10571 | case DRX_INTERLEAVEMODE_AUTO: | |
443f18d0 | 10572 | break; |
443f18d0 | 10573 | default: |
b6c4065e | 10574 | return -EINVAL; |
443f18d0 | 10575 | } |
d7a5478a | 10576 | } |
443f18d0 | 10577 | |
b6c4065e MCC |
10578 | if ((ext_attr->uio_sma_tx_mode) == DRX_UIO_MODE_FIRMWARE_SAW) { |
10579 | /* SAW SW, user UIO is used for switchable SAW */ | |
10580 | struct drxuio_data uio1 = { DRX_UIO1, false }; | |
10581 | ||
10582 | switch (channel->bandwidth) { | |
10583 | case DRX_BANDWIDTH_8MHZ: | |
10584 | uio1.value = true; | |
10585 | break; | |
10586 | case DRX_BANDWIDTH_7MHZ: | |
10587 | uio1.value = false; | |
10588 | break; | |
10589 | case DRX_BANDWIDTH_6MHZ: | |
10590 | uio1.value = false; | |
10591 | break; | |
10592 | case DRX_BANDWIDTH_UNKNOWN: | |
10593 | default: | |
10594 | return -EINVAL; | |
d7a5478a | 10595 | } |
b6c4065e MCC |
10596 | |
10597 | rc = ctrl_uio_write(demod, &uio1); | |
d7a5478a MCC |
10598 | if (rc != 0) { |
10599 | pr_err("error %d\n", rc); | |
10600 | goto rw_error; | |
10601 | } | |
b6c4065e MCC |
10602 | } |
10603 | #endif /* DRXJ_VSB_ONLY */ | |
10604 | rc = drxj_dap_write_reg16(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE, 0); | |
10605 | if (rc != 0) { | |
10606 | pr_err("error %d\n", rc); | |
10607 | goto rw_error; | |
443f18d0 MCC |
10608 | } |
10609 | ||
b6c4065e | 10610 | tuner_freq_offset = 0; |
443f18d0 | 10611 | |
b6c4065e MCC |
10612 | /*== Setup demod for specific standard ====================================*/ |
10613 | switch (standard) { | |
10614 | case DRX_STANDARD_8VSB: | |
10615 | if (channel->mirror == DRX_MIRROR_AUTO) | |
10616 | ext_attr->mirror = DRX_MIRROR_NO; | |
10617 | else | |
10618 | ext_attr->mirror = channel->mirror; | |
10619 | rc = set_vsb(demod); | |
9482354f | 10620 | if (rc != 0) { |
068e94ea MCC |
10621 | pr_err("error %d\n", rc); |
10622 | goto rw_error; | |
10623 | } | |
b6c4065e | 10624 | rc = set_frequency(demod, channel, tuner_freq_offset); |
9482354f | 10625 | if (rc != 0) { |
068e94ea MCC |
10626 | pr_err("error %d\n", rc); |
10627 | goto rw_error; | |
10628 | } | |
b6c4065e MCC |
10629 | break; |
10630 | #ifndef DRXJ_VSB_ONLY | |
10631 | case DRX_STANDARD_ITU_A: /* fallthrough */ | |
10632 | case DRX_STANDARD_ITU_B: /* fallthrough */ | |
10633 | case DRX_STANDARD_ITU_C: | |
10634 | rc = set_qam_channel(demod, channel, tuner_freq_offset); | |
9482354f | 10635 | if (rc != 0) { |
068e94ea MCC |
10636 | pr_err("error %d\n", rc); |
10637 | goto rw_error; | |
10638 | } | |
b6c4065e MCC |
10639 | break; |
10640 | #endif | |
10641 | case DRX_STANDARD_UNKNOWN: | |
10642 | default: | |
10643 | return -EIO; | |
443f18d0 | 10644 | } |
38b2df95 | 10645 | |
b6c4065e MCC |
10646 | /* flag the packet error counter reset */ |
10647 | ext_attr->reset_pkt_err_acc = true; | |
38b2df95 | 10648 | |
b6c4065e | 10649 | return 0; |
443f18d0 | 10650 | rw_error: |
30741871 | 10651 | return rc; |
38b2df95 DH |
10652 | } |
10653 | ||
b6c4065e MCC |
10654 | /*============================================================================= |
10655 | ===== SigQuality() ========================================================== | |
10656 | ===========================================================================*/ | |
10657 | ||
34eb9751 | 10658 | /* |
b6c4065e | 10659 | * \fn int ctrl_sig_quality() |
69bb7ab6 | 10660 | * \brief Retrieve signal quality form device. |
38b2df95 | 10661 | * \param devmod Pointer to demodulator instance. |
b6c4065e | 10662 | * \param sig_quality Pointer to signal quality data. |
61263c75 | 10663 | * \return int. |
b6c4065e MCC |
10664 | * \retval 0 sig_quality contains valid data. |
10665 | * \retval -EINVAL sig_quality is NULL. | |
10666 | * \retval -EIO Erroneous data, sig_quality contains invalid data. | |
38b2df95 DH |
10667 | |
10668 | */ | |
61263c75 | 10669 | static int |
03fdfbfd MCC |
10670 | ctrl_sig_quality(struct drx_demod_instance *demod, |
10671 | enum drx_lock_status lock_status) | |
38b2df95 | 10672 | { |
03fdfbfd MCC |
10673 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; |
10674 | struct drxj_data *ext_attr = demod->my_ext_attr; | |
10675 | struct drx39xxj_state *state = dev_addr->user_data; | |
10676 | struct dtv_frontend_properties *p = &state->frontend.dtv_property_cache; | |
10677 | enum drx_standard standard = ext_attr->standard; | |
068e94ea | 10678 | int rc; |
d591590e | 10679 | u32 ber, cnt, err, pkt; |
4182438e | 10680 | u16 mer, strength = 0; |
38b2df95 | 10681 | |
03fdfbfd MCC |
10682 | rc = get_sig_strength(demod, &strength); |
10683 | if (rc < 0) { | |
10684 | pr_err("error getting signal strength %d\n", rc); | |
10685 | p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
10686 | } else { | |
10687 | p->strength.stat[0].scale = FE_SCALE_RELATIVE; | |
10688 | p->strength.stat[0].uvalue = 65535UL * strength/ 100; | |
b6c4065e | 10689 | } |
03fdfbfd | 10690 | |
443f18d0 | 10691 | switch (standard) { |
b6c4065e MCC |
10692 | case DRX_STANDARD_8VSB: |
10693 | #ifdef DRXJ_SIGNAL_ACCUM_ERR | |
03fdfbfd | 10694 | rc = get_acc_pkt_err(demod, &pkt); |
b6c4065e MCC |
10695 | if (rc != 0) { |
10696 | pr_err("error %d\n", rc); | |
10697 | goto rw_error; | |
10698 | } | |
10699 | #endif | |
10700 | if (lock_status != DRXJ_DEMOD_LOCK && lock_status != DRX_LOCKED) { | |
03fdfbfd | 10701 | p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
03fdfbfd | 10702 | p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
69832578 | 10703 | p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
03fdfbfd | 10704 | p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
69832578 | 10705 | p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
03fdfbfd MCC |
10706 | p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
10707 | p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
b6c4065e | 10708 | } else { |
69832578 | 10709 | rc = get_vsb_post_rs_pck_err(dev_addr, &err, &pkt); |
03fdfbfd MCC |
10710 | if (rc != 0) { |
10711 | pr_err("error %d getting UCB\n", rc); | |
10712 | p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
10713 | } else { | |
10714 | p->block_error.stat[0].scale = FE_SCALE_COUNTER; | |
69832578 MCC |
10715 | p->block_error.stat[0].uvalue += err; |
10716 | p->block_count.stat[0].scale = FE_SCALE_COUNTER; | |
10717 | p->block_count.stat[0].uvalue += pkt; | |
03fdfbfd MCC |
10718 | } |
10719 | ||
b6c4065e | 10720 | /* PostViterbi is compute in steps of 10^(-6) */ |
69832578 | 10721 | rc = get_vs_bpre_viterbi_ber(dev_addr, &ber, &cnt); |
b6c4065e | 10722 | if (rc != 0) { |
03fdfbfd MCC |
10723 | pr_err("error %d getting pre-ber\n", rc); |
10724 | p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
10725 | } else { | |
10726 | p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; | |
10727 | p->pre_bit_error.stat[0].uvalue += ber; | |
10728 | p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; | |
69832578 | 10729 | p->pre_bit_count.stat[0].uvalue += cnt; |
b6c4065e | 10730 | } |
03fdfbfd | 10731 | |
69832578 | 10732 | rc = get_vs_bpost_viterbi_ber(dev_addr, &ber, &cnt); |
b6c4065e | 10733 | if (rc != 0) { |
03fdfbfd MCC |
10734 | pr_err("error %d getting post-ber\n", rc); |
10735 | p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
10736 | } else { | |
10737 | p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; | |
10738 | p->post_bit_error.stat[0].uvalue += ber; | |
10739 | p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; | |
69832578 | 10740 | p->post_bit_count.stat[0].uvalue += cnt; |
b6c4065e | 10741 | } |
03fdfbfd | 10742 | rc = get_vsbmer(dev_addr, &mer); |
b6c4065e | 10743 | if (rc != 0) { |
03fdfbfd MCC |
10744 | pr_err("error %d getting MER\n", rc); |
10745 | p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
10746 | } else { | |
10747 | p->cnr.stat[0].svalue = mer * 100; | |
10748 | p->cnr.stat[0].scale = FE_SCALE_DECIBEL; | |
b6c4065e MCC |
10749 | } |
10750 | } | |
b6c4065e | 10751 | break; |
38b2df95 | 10752 | #ifndef DRXJ_VSB_ONLY |
b6c4065e MCC |
10753 | case DRX_STANDARD_ITU_A: |
10754 | case DRX_STANDARD_ITU_B: | |
443f18d0 | 10755 | case DRX_STANDARD_ITU_C: |
03fdfbfd | 10756 | rc = ctrl_get_qam_sig_quality(demod); |
9482354f | 10757 | if (rc != 0) { |
068e94ea MCC |
10758 | pr_err("error %d\n", rc); |
10759 | goto rw_error; | |
10760 | } | |
443f18d0 | 10761 | break; |
b6c4065e | 10762 | #endif |
443f18d0 | 10763 | default: |
b6c4065e | 10764 | return -EIO; |
443f18d0 MCC |
10765 | } |
10766 | ||
9482354f | 10767 | return 0; |
443f18d0 | 10768 | rw_error: |
30741871 | 10769 | return rc; |
38b2df95 DH |
10770 | } |
10771 | ||
10772 | /*============================================================================*/ | |
38b2df95 | 10773 | |
34eb9751 | 10774 | /* |
b6c4065e | 10775 | * \fn int ctrl_lock_status() |
69bb7ab6 | 10776 | * \brief Retrieve lock status . |
b6c4065e MCC |
10777 | * \param dev_addr Pointer to demodulator device address. |
10778 | * \param lock_stat Pointer to lock status structure. | |
61263c75 | 10779 | * \return int. |
38b2df95 DH |
10780 | * |
10781 | */ | |
61263c75 | 10782 | static int |
b6c4065e | 10783 | ctrl_lock_status(struct drx_demod_instance *demod, enum drx_lock_status *lock_stat) |
38b2df95 | 10784 | { |
b6c4065e MCC |
10785 | enum drx_standard standard = DRX_STANDARD_UNKNOWN; |
10786 | struct drxj_data *ext_attr = NULL; | |
57afe2f0 | 10787 | struct i2c_device_addr *dev_addr = NULL; |
b6c4065e MCC |
10788 | struct drxjscu_cmd cmd_scu = { /* command */ 0, |
10789 | /* parameter_len */ 0, | |
10790 | /* result_len */ 0, | |
10791 | /* *parameter */ NULL, | |
10792 | /* *result */ NULL | |
10793 | }; | |
068e94ea | 10794 | int rc; |
b6c4065e MCC |
10795 | u16 cmd_result[2] = { 0, 0 }; |
10796 | u16 demod_lock = SCU_RAM_PARAM_1_RES_DEMOD_GET_LOCK_DEMOD_LOCKED; | |
38b2df95 | 10797 | |
443f18d0 | 10798 | /* check arguments */ |
b6c4065e | 10799 | if ((demod == NULL) || (lock_stat == NULL)) |
9482354f | 10800 | return -EINVAL; |
63713517 | 10801 | |
57afe2f0 | 10802 | dev_addr = demod->my_i2c_dev_addr; |
b6c4065e MCC |
10803 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
10804 | standard = ext_attr->standard; | |
38b2df95 | 10805 | |
b6c4065e | 10806 | *lock_stat = DRX_NOT_LOCKED; |
443f18d0 | 10807 | |
b6c4065e MCC |
10808 | /* define the SCU command code */ |
10809 | switch (standard) { | |
10810 | case DRX_STANDARD_8VSB: | |
10811 | cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB | | |
10812 | SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK; | |
10813 | demod_lock |= 0x6; | |
443f18d0 | 10814 | break; |
38b2df95 | 10815 | #ifndef DRXJ_VSB_ONLY |
b6c4065e MCC |
10816 | case DRX_STANDARD_ITU_A: |
10817 | case DRX_STANDARD_ITU_B: | |
443f18d0 | 10818 | case DRX_STANDARD_ITU_C: |
b6c4065e MCC |
10819 | cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM | |
10820 | SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK; | |
10821 | break; | |
38b2df95 | 10822 | #endif |
b6c4065e | 10823 | case DRX_STANDARD_UNKNOWN: /* fallthrough */ |
443f18d0 | 10824 | default: |
b6c4065e | 10825 | return -EIO; |
443f18d0 | 10826 | } |
38b2df95 | 10827 | |
69bb7ab6 | 10828 | /* define the SCU command parameters and execute the command */ |
b6c4065e MCC |
10829 | cmd_scu.parameter_len = 0; |
10830 | cmd_scu.result_len = 2; | |
10831 | cmd_scu.parameter = NULL; | |
10832 | cmd_scu.result = cmd_result; | |
10833 | rc = scu_command(dev_addr, &cmd_scu); | |
10834 | if (rc != 0) { | |
10835 | pr_err("error %d\n", rc); | |
10836 | goto rw_error; | |
443f18d0 MCC |
10837 | } |
10838 | ||
b6c4065e MCC |
10839 | /* set the lock status */ |
10840 | if (cmd_scu.result[1] < demod_lock) { | |
10841 | /* 0x0000 NOT LOCKED */ | |
10842 | *lock_stat = DRX_NOT_LOCKED; | |
10843 | } else if (cmd_scu.result[1] < SCU_RAM_PARAM_1_RES_DEMOD_GET_LOCK_LOCKED) { | |
10844 | *lock_stat = DRXJ_DEMOD_LOCK; | |
10845 | } else if (cmd_scu.result[1] < | |
10846 | SCU_RAM_PARAM_1_RES_DEMOD_GET_LOCK_NEVER_LOCK) { | |
10847 | /* 0x8000 DEMOD + FEC LOCKED (system lock) */ | |
10848 | *lock_stat = DRX_LOCKED; | |
10849 | } else { | |
10850 | /* 0xC000 NEVER LOCKED */ | |
10851 | /* (system will never be able to lock to the signal) */ | |
10852 | *lock_stat = DRX_NEVER_LOCK; | |
443f18d0 | 10853 | } |
38b2df95 | 10854 | |
9482354f | 10855 | return 0; |
b6c4065e | 10856 | rw_error: |
30741871 | 10857 | return rc; |
38b2df95 DH |
10858 | } |
10859 | ||
10860 | /*============================================================================*/ | |
10861 | ||
34eb9751 | 10862 | /* |
b6c4065e MCC |
10863 | * \fn int ctrl_set_standard() |
10864 | * \brief Set modulation standard to be used. | |
10865 | * \param standard Modulation standard. | |
61263c75 | 10866 | * \return int. |
38b2df95 | 10867 | * |
b6c4065e MCC |
10868 | * Setup stuff for the desired demodulation standard. |
10869 | * Disable and power down the previous selected demodulation standard | |
38b2df95 DH |
10870 | * |
10871 | */ | |
61263c75 | 10872 | static int |
b6c4065e | 10873 | ctrl_set_standard(struct drx_demod_instance *demod, enum drx_standard *standard) |
38b2df95 | 10874 | { |
b6c4065e MCC |
10875 | struct drxj_data *ext_attr = NULL; |
10876 | int rc; | |
10877 | enum drx_standard prev_standard; | |
10878 | ||
443f18d0 | 10879 | /* check arguments */ |
b6c4065e | 10880 | if ((standard == NULL) || (demod == NULL)) |
9482354f | 10881 | return -EINVAL; |
38b2df95 | 10882 | |
b6c4065e MCC |
10883 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
10884 | prev_standard = ext_attr->standard; | |
10885 | ||
10886 | /* | |
10887 | Stop and power down previous standard | |
10888 | */ | |
10889 | switch (prev_standard) { | |
38b2df95 | 10890 | #ifndef DRXJ_VSB_ONLY |
443f18d0 MCC |
10891 | case DRX_STANDARD_ITU_A: /* fallthrough */ |
10892 | case DRX_STANDARD_ITU_B: /* fallthrough */ | |
10893 | case DRX_STANDARD_ITU_C: | |
b6c4065e MCC |
10894 | rc = power_down_qam(demod, false); |
10895 | if (rc != 0) { | |
10896 | pr_err("error %d\n", rc); | |
10897 | goto rw_error; | |
10898 | } | |
10899 | break; | |
38b2df95 | 10900 | #endif |
b6c4065e MCC |
10901 | case DRX_STANDARD_8VSB: |
10902 | rc = power_down_vsb(demod, false); | |
10903 | if (rc != 0) { | |
10904 | pr_err("error %d\n", rc); | |
10905 | goto rw_error; | |
10906 | } | |
10907 | break; | |
443f18d0 | 10908 | case DRX_STANDARD_UNKNOWN: |
b6c4065e MCC |
10909 | /* Do nothing */ |
10910 | break; | |
10911 | case DRX_STANDARD_AUTO: /* fallthrough */ | |
10912 | default: | |
10913 | return -EINVAL; | |
10914 | } | |
10915 | ||
10916 | /* | |
10917 | Initialize channel independent registers | |
10918 | Power up new standard | |
10919 | */ | |
10920 | ext_attr->standard = *standard; | |
10921 | ||
10922 | switch (*standard) { | |
10923 | #ifndef DRXJ_VSB_ONLY | |
10924 | case DRX_STANDARD_ITU_A: /* fallthrough */ | |
10925 | case DRX_STANDARD_ITU_B: /* fallthrough */ | |
10926 | case DRX_STANDARD_ITU_C: | |
10927 | do { | |
10928 | u16 dummy; | |
10929 | rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, SCU_RAM_VERSION_HI__A, &dummy, 0); | |
10930 | if (rc != 0) { | |
10931 | pr_err("error %d\n", rc); | |
10932 | goto rw_error; | |
10933 | } | |
10934 | } while (0); | |
10935 | break; | |
10936 | #endif | |
10937 | case DRX_STANDARD_8VSB: | |
10938 | rc = set_vsb_leak_n_gain(demod); | |
10939 | if (rc != 0) { | |
10940 | pr_err("error %d\n", rc); | |
10941 | goto rw_error; | |
10942 | } | |
10943 | break; | |
443f18d0 | 10944 | default: |
b6c4065e | 10945 | ext_attr->standard = DRX_STANDARD_UNKNOWN; |
9482354f | 10946 | return -EINVAL; |
b6c4065e | 10947 | break; |
443f18d0 | 10948 | } |
38b2df95 | 10949 | |
9482354f | 10950 | return 0; |
b6c4065e MCC |
10951 | rw_error: |
10952 | /* Don't know what the standard is now ... try again */ | |
10953 | ext_attr->standard = DRX_STANDARD_UNKNOWN; | |
30741871 | 10954 | return rc; |
38b2df95 DH |
10955 | } |
10956 | ||
38b2df95 DH |
10957 | /*============================================================================*/ |
10958 | ||
b6c4065e MCC |
10959 | static void drxj_reset_mode(struct drxj_data *ext_attr) |
10960 | { | |
2c149601 | 10961 | /* Initialize default AFE configuration for QAM */ |
b6c4065e MCC |
10962 | if (ext_attr->has_lna) { |
10963 | /* IF AGC off, PGA active */ | |
10964 | #ifndef DRXJ_VSB_ONLY | |
10965 | ext_attr->qam_if_agc_cfg.standard = DRX_STANDARD_ITU_B; | |
10966 | ext_attr->qam_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_OFF; | |
10967 | ext_attr->qam_pga_cfg = 140 + (11 * 13); | |
10968 | #endif | |
10969 | ext_attr->vsb_if_agc_cfg.standard = DRX_STANDARD_8VSB; | |
10970 | ext_attr->vsb_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_OFF; | |
10971 | ext_attr->vsb_pga_cfg = 140 + (11 * 13); | |
10972 | } else { | |
10973 | /* IF AGC on, PGA not active */ | |
10974 | #ifndef DRXJ_VSB_ONLY | |
10975 | ext_attr->qam_if_agc_cfg.standard = DRX_STANDARD_ITU_B; | |
10976 | ext_attr->qam_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO; | |
10977 | ext_attr->qam_if_agc_cfg.min_output_level = 0; | |
10978 | ext_attr->qam_if_agc_cfg.max_output_level = 0x7FFF; | |
10979 | ext_attr->qam_if_agc_cfg.speed = 3; | |
10980 | ext_attr->qam_if_agc_cfg.top = 1297; | |
10981 | ext_attr->qam_pga_cfg = 140; | |
10982 | #endif | |
10983 | ext_attr->vsb_if_agc_cfg.standard = DRX_STANDARD_8VSB; | |
10984 | ext_attr->vsb_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO; | |
10985 | ext_attr->vsb_if_agc_cfg.min_output_level = 0; | |
10986 | ext_attr->vsb_if_agc_cfg.max_output_level = 0x7FFF; | |
10987 | ext_attr->vsb_if_agc_cfg.speed = 3; | |
10988 | ext_attr->vsb_if_agc_cfg.top = 1024; | |
10989 | ext_attr->vsb_pga_cfg = 140; | |
10990 | } | |
10991 | /* TODO: remove min_output_level and max_output_level for both QAM and VSB after */ | |
10992 | /* mc has not used them */ | |
10993 | #ifndef DRXJ_VSB_ONLY | |
10994 | ext_attr->qam_rf_agc_cfg.standard = DRX_STANDARD_ITU_B; | |
10995 | ext_attr->qam_rf_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO; | |
10996 | ext_attr->qam_rf_agc_cfg.min_output_level = 0; | |
10997 | ext_attr->qam_rf_agc_cfg.max_output_level = 0x7FFF; | |
10998 | ext_attr->qam_rf_agc_cfg.speed = 3; | |
10999 | ext_attr->qam_rf_agc_cfg.top = 9500; | |
11000 | ext_attr->qam_rf_agc_cfg.cut_off_current = 4000; | |
11001 | ext_attr->qam_pre_saw_cfg.standard = DRX_STANDARD_ITU_B; | |
11002 | ext_attr->qam_pre_saw_cfg.reference = 0x07; | |
11003 | ext_attr->qam_pre_saw_cfg.use_pre_saw = true; | |
11004 | #endif | |
2c149601 | 11005 | /* Initialize default AFE configuration for VSB */ |
b6c4065e MCC |
11006 | ext_attr->vsb_rf_agc_cfg.standard = DRX_STANDARD_8VSB; |
11007 | ext_attr->vsb_rf_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO; | |
11008 | ext_attr->vsb_rf_agc_cfg.min_output_level = 0; | |
11009 | ext_attr->vsb_rf_agc_cfg.max_output_level = 0x7FFF; | |
11010 | ext_attr->vsb_rf_agc_cfg.speed = 3; | |
11011 | ext_attr->vsb_rf_agc_cfg.top = 9500; | |
11012 | ext_attr->vsb_rf_agc_cfg.cut_off_current = 4000; | |
11013 | ext_attr->vsb_pre_saw_cfg.standard = DRX_STANDARD_8VSB; | |
11014 | ext_attr->vsb_pre_saw_cfg.reference = 0x07; | |
11015 | ext_attr->vsb_pre_saw_cfg.use_pre_saw = true; | |
11016 | } | |
11017 | ||
34eb9751 | 11018 | /* |
b6c4065e MCC |
11019 | * \fn int ctrl_power_mode() |
11020 | * \brief Set the power mode of the device to the specified power mode | |
11021 | * \param demod Pointer to demodulator instance. | |
11022 | * \param mode Pointer to new power mode. | |
61263c75 | 11023 | * \return int. |
b6c4065e MCC |
11024 | * \retval 0 Success |
11025 | * \retval -EIO I2C error or other failure | |
11026 | * \retval -EINVAL Invalid mode argument. | |
38b2df95 | 11027 | * |
38b2df95 DH |
11028 | * |
11029 | */ | |
61263c75 | 11030 | static int |
b6c4065e | 11031 | ctrl_power_mode(struct drx_demod_instance *demod, enum drx_power_mode *mode) |
38b2df95 | 11032 | { |
b6c4065e MCC |
11033 | struct drx_common_attr *common_attr = (struct drx_common_attr *) NULL; |
11034 | struct drxj_data *ext_attr = (struct drxj_data *) NULL; | |
11035 | struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)NULL; | |
068e94ea | 11036 | int rc; |
b6c4065e | 11037 | u16 sio_cc_pwd_mode = 0; |
38b2df95 | 11038 | |
b6c4065e | 11039 | common_attr = (struct drx_common_attr *) demod->my_common_attr; |
b3ce3a83 | 11040 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
b6c4065e | 11041 | dev_addr = demod->my_i2c_dev_addr; |
443f18d0 | 11042 | |
b6c4065e MCC |
11043 | /* Check arguments */ |
11044 | if (mode == NULL) | |
11045 | return -EINVAL; | |
11046 | ||
11047 | /* If already in requested power mode, do nothing */ | |
11048 | if (common_attr->current_power_mode == *mode) | |
9482354f | 11049 | return 0; |
443f18d0 | 11050 | |
b6c4065e MCC |
11051 | switch (*mode) { |
11052 | case DRX_POWER_UP: | |
11053 | case DRXJ_POWER_DOWN_MAIN_PATH: | |
11054 | sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_NONE; | |
443f18d0 | 11055 | break; |
b6c4065e MCC |
11056 | case DRXJ_POWER_DOWN_CORE: |
11057 | sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_CLOCK; | |
11058 | break; | |
11059 | case DRXJ_POWER_DOWN_PLL: | |
11060 | sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_PLL; | |
11061 | break; | |
11062 | case DRX_POWER_DOWN: | |
11063 | sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC; | |
11064 | break; | |
11065 | default: | |
11066 | /* Unknow sleep mode */ | |
11067 | return -EINVAL; | |
11068 | break; | |
11069 | } | |
11070 | ||
11071 | /* Check if device needs to be powered up */ | |
11072 | if ((common_attr->current_power_mode != DRX_POWER_UP)) { | |
11073 | rc = power_up_device(demod); | |
11074 | if (rc != 0) { | |
11075 | pr_err("error %d\n", rc); | |
11076 | goto rw_error; | |
11077 | } | |
11078 | } | |
11079 | ||
7369bbf2 | 11080 | if (*mode == DRX_POWER_UP) { |
2c149601 | 11081 | /* Restore analog & pin configuration */ |
b6c4065e | 11082 | |
2c149601 | 11083 | /* Initialize default AFE configuration for VSB */ |
b6c4065e MCC |
11084 | drxj_reset_mode(ext_attr); |
11085 | } else { | |
11086 | /* Power down to requested mode */ | |
11087 | /* Backup some register settings */ | |
11088 | /* Set pins with possible pull-ups connected to them in input mode */ | |
11089 | /* Analog power down */ | |
11090 | /* ADC power down */ | |
11091 | /* Power down device */ | |
11092 | /* stop all comm_exec */ | |
11093 | /* | |
11094 | Stop and power down previous standard | |
11095 | */ | |
11096 | ||
11097 | switch (ext_attr->standard) { | |
11098 | case DRX_STANDARD_ITU_A: | |
11099 | case DRX_STANDARD_ITU_B: | |
11100 | case DRX_STANDARD_ITU_C: | |
11101 | rc = power_down_qam(demod, true); | |
11102 | if (rc != 0) { | |
11103 | pr_err("error %d\n", rc); | |
11104 | goto rw_error; | |
11105 | } | |
11106 | break; | |
11107 | case DRX_STANDARD_8VSB: | |
11108 | rc = power_down_vsb(demod, true); | |
11109 | if (rc != 0) { | |
11110 | pr_err("error %d\n", rc); | |
11111 | goto rw_error; | |
11112 | } | |
11113 | break; | |
11114 | case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */ | |
11115 | case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */ | |
11116 | case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */ | |
11117 | case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */ | |
11118 | case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */ | |
11119 | case DRX_STANDARD_NTSC: /* fallthrough */ | |
11120 | case DRX_STANDARD_FM: | |
11121 | rc = power_down_atv(demod, ext_attr->standard, true); | |
11122 | if (rc != 0) { | |
11123 | pr_err("error %d\n", rc); | |
11124 | goto rw_error; | |
11125 | } | |
443f18d0 | 11126 | break; |
b6c4065e MCC |
11127 | case DRX_STANDARD_UNKNOWN: |
11128 | /* Do nothing */ | |
443f18d0 | 11129 | break; |
b6c4065e | 11130 | case DRX_STANDARD_AUTO: /* fallthrough */ |
443f18d0 | 11131 | default: |
9482354f | 11132 | return -EIO; |
443f18d0 | 11133 | } |
b6c4065e | 11134 | ext_attr->standard = DRX_STANDARD_UNKNOWN; |
443f18d0 MCC |
11135 | } |
11136 | ||
b6c4065e MCC |
11137 | if (*mode != DRXJ_POWER_DOWN_MAIN_PATH) { |
11138 | rc = drxj_dap_write_reg16(dev_addr, SIO_CC_PWD_MODE__A, sio_cc_pwd_mode, 0); | |
11139 | if (rc != 0) { | |
11140 | pr_err("error %d\n", rc); | |
11141 | goto rw_error; | |
11142 | } | |
11143 | rc = drxj_dap_write_reg16(dev_addr, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY, 0); | |
11144 | if (rc != 0) { | |
11145 | pr_err("error %d\n", rc); | |
11146 | goto rw_error; | |
11147 | } | |
11148 | ||
11149 | if ((*mode != DRX_POWER_UP)) { | |
11150 | /* Initialize HI, wakeup key especially before put IC to sleep */ | |
11151 | rc = init_hi(demod); | |
11152 | if (rc != 0) { | |
11153 | pr_err("error %d\n", rc); | |
11154 | goto rw_error; | |
11155 | } | |
11156 | ||
11157 | ext_attr->hi_cfg_ctrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; | |
11158 | rc = hi_cfg_command(demod); | |
11159 | if (rc != 0) { | |
11160 | pr_err("error %d\n", rc); | |
11161 | goto rw_error; | |
11162 | } | |
11163 | } | |
068e94ea | 11164 | } |
b6c4065e MCC |
11165 | |
11166 | common_attr->current_power_mode = *mode; | |
443f18d0 | 11167 | |
9482354f | 11168 | return 0; |
38b2df95 | 11169 | rw_error: |
b6c4065e | 11170 | return rc; |
38b2df95 DH |
11171 | } |
11172 | ||
11173 | /*============================================================================*/ | |
b6c4065e MCC |
11174 | /*== CTRL Set/Get Config related functions ===================================*/ |
11175 | /*============================================================================*/ | |
38b2df95 | 11176 | |
34eb9751 | 11177 | /* |
57afe2f0 | 11178 | * \fn int ctrl_set_cfg_pre_saw() |
38b2df95 DH |
11179 | * \brief Set Pre-saw reference. |
11180 | * \param demod demod instance | |
43a431e4 | 11181 | * \param u16 * |
61263c75 | 11182 | * \return int. |
38b2df95 DH |
11183 | * |
11184 | * Check arguments | |
11185 | * Dispatch handling to standard specific function. | |
11186 | * | |
11187 | */ | |
61263c75 | 11188 | static int |
b3ce3a83 | 11189 | ctrl_set_cfg_pre_saw(struct drx_demod_instance *demod, struct drxj_cfg_pre_saw *pre_saw) |
38b2df95 | 11190 | { |
57afe2f0 | 11191 | struct i2c_device_addr *dev_addr = NULL; |
b3ce3a83 | 11192 | struct drxj_data *ext_attr = NULL; |
068e94ea | 11193 | int rc; |
38b2df95 | 11194 | |
57afe2f0 | 11195 | dev_addr = demod->my_i2c_dev_addr; |
b3ce3a83 | 11196 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
38b2df95 | 11197 | |
443f18d0 | 11198 | /* check arguments */ |
57afe2f0 | 11199 | if ((pre_saw == NULL) || (pre_saw->reference > IQM_AF_PDREF__M) |
443f18d0 | 11200 | ) { |
9482354f | 11201 | return -EINVAL; |
443f18d0 MCC |
11202 | } |
11203 | ||
11204 | /* Only if standard is currently active */ | |
57afe2f0 MCC |
11205 | if ((ext_attr->standard == pre_saw->standard) || |
11206 | (DRXJ_ISQAMSTD(ext_attr->standard) && | |
11207 | DRXJ_ISQAMSTD(pre_saw->standard)) || | |
11208 | (DRXJ_ISATVSTD(ext_attr->standard) && | |
11209 | DRXJ_ISATVSTD(pre_saw->standard))) { | |
244c0e06 | 11210 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_PDREF__A, pre_saw->reference, 0); |
9482354f | 11211 | if (rc != 0) { |
068e94ea MCC |
11212 | pr_err("error %d\n", rc); |
11213 | goto rw_error; | |
11214 | } | |
443f18d0 MCC |
11215 | } |
11216 | ||
11217 | /* Store pre-saw settings */ | |
57afe2f0 | 11218 | switch (pre_saw->standard) { |
443f18d0 | 11219 | case DRX_STANDARD_8VSB: |
57afe2f0 | 11220 | ext_attr->vsb_pre_saw_cfg = *pre_saw; |
443f18d0 | 11221 | break; |
38b2df95 | 11222 | #ifndef DRXJ_VSB_ONLY |
443f18d0 MCC |
11223 | case DRX_STANDARD_ITU_A: /* fallthrough */ |
11224 | case DRX_STANDARD_ITU_B: /* fallthrough */ | |
11225 | case DRX_STANDARD_ITU_C: | |
57afe2f0 | 11226 | ext_attr->qam_pre_saw_cfg = *pre_saw; |
443f18d0 | 11227 | break; |
38b2df95 | 11228 | #endif |
443f18d0 | 11229 | default: |
9482354f | 11230 | return -EINVAL; |
443f18d0 | 11231 | } |
38b2df95 | 11232 | |
9482354f | 11233 | return 0; |
38b2df95 | 11234 | rw_error: |
30741871 | 11235 | return rc; |
38b2df95 DH |
11236 | } |
11237 | ||
11238 | /*============================================================================*/ | |
11239 | ||
34eb9751 | 11240 | /* |
57afe2f0 | 11241 | * \fn int ctrl_set_cfg_afe_gain() |
38b2df95 DH |
11242 | * \brief Set AFE Gain. |
11243 | * \param demod demod instance | |
43a431e4 | 11244 | * \param u16 * |
61263c75 | 11245 | * \return int. |
38b2df95 DH |
11246 | * |
11247 | * Check arguments | |
11248 | * Dispatch handling to standard specific function. | |
11249 | * | |
11250 | */ | |
61263c75 | 11251 | static int |
b3ce3a83 | 11252 | ctrl_set_cfg_afe_gain(struct drx_demod_instance *demod, struct drxj_cfg_afe_gain *afe_gain) |
38b2df95 | 11253 | { |
57afe2f0 | 11254 | struct i2c_device_addr *dev_addr = NULL; |
b3ce3a83 | 11255 | struct drxj_data *ext_attr = NULL; |
068e94ea | 11256 | int rc; |
43a431e4 | 11257 | u8 gain = 0; |
38b2df95 | 11258 | |
443f18d0 | 11259 | /* check arguments */ |
63713517 | 11260 | if (afe_gain == NULL) |
9482354f | 11261 | return -EINVAL; |
38b2df95 | 11262 | |
57afe2f0 | 11263 | dev_addr = demod->my_i2c_dev_addr; |
b3ce3a83 | 11264 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
38b2df95 | 11265 | |
57afe2f0 | 11266 | switch (afe_gain->standard) { |
443f18d0 | 11267 | case DRX_STANDARD_8VSB: /* fallthrough */ |
38b2df95 | 11268 | #ifndef DRXJ_VSB_ONLY |
443f18d0 MCC |
11269 | case DRX_STANDARD_ITU_A: /* fallthrough */ |
11270 | case DRX_STANDARD_ITU_B: /* fallthrough */ | |
11271 | case DRX_STANDARD_ITU_C: | |
38b2df95 | 11272 | #endif |
443f18d0 MCC |
11273 | /* Do nothing */ |
11274 | break; | |
11275 | default: | |
9482354f | 11276 | return -EINVAL; |
443f18d0 | 11277 | } |
38b2df95 | 11278 | |
443f18d0 | 11279 | /* TODO PGA gain is also written by microcode (at least by QAM and VSB) |
38b2df95 DH |
11280 | So I (PJ) think interface requires choice between auto, user mode */ |
11281 | ||
57afe2f0 | 11282 | if (afe_gain->gain >= 329) |
443f18d0 | 11283 | gain = 15; |
57afe2f0 | 11284 | else if (afe_gain->gain <= 147) |
443f18d0 MCC |
11285 | gain = 0; |
11286 | else | |
57afe2f0 | 11287 | gain = (afe_gain->gain - 140 + 6) / 13; |
443f18d0 MCC |
11288 | |
11289 | /* Only if standard is currently active */ | |
63713517 | 11290 | if (ext_attr->standard == afe_gain->standard) { |
244c0e06 | 11291 | rc = drxj_dap_write_reg16(dev_addr, IQM_AF_PGA_GAIN__A, gain, 0); |
9482354f | 11292 | if (rc != 0) { |
068e94ea MCC |
11293 | pr_err("error %d\n", rc); |
11294 | goto rw_error; | |
11295 | } | |
11296 | } | |
443f18d0 MCC |
11297 | |
11298 | /* Store AFE Gain settings */ | |
57afe2f0 | 11299 | switch (afe_gain->standard) { |
443f18d0 | 11300 | case DRX_STANDARD_8VSB: |
57afe2f0 | 11301 | ext_attr->vsb_pga_cfg = gain * 13 + 140; |
443f18d0 | 11302 | break; |
38b2df95 | 11303 | #ifndef DRXJ_VSB_ONLY |
443f18d0 MCC |
11304 | case DRX_STANDARD_ITU_A: /* fallthrough */ |
11305 | case DRX_STANDARD_ITU_B: /* fallthrough */ | |
11306 | case DRX_STANDARD_ITU_C: | |
57afe2f0 | 11307 | ext_attr->qam_pga_cfg = gain * 13 + 140; |
443f18d0 | 11308 | break; |
38b2df95 | 11309 | #endif |
443f18d0 | 11310 | default: |
9482354f | 11311 | return -EIO; |
443f18d0 | 11312 | } |
38b2df95 | 11313 | |
9482354f | 11314 | return 0; |
38b2df95 | 11315 | rw_error: |
30741871 | 11316 | return rc; |
38b2df95 DH |
11317 | } |
11318 | ||
11319 | /*============================================================================*/ | |
11320 | ||
38b2df95 DH |
11321 | |
11322 | /*============================================================================= | |
11323 | ===== EXPORTED FUNCTIONS ====================================================*/ | |
aafdbaa6 | 11324 | |
dc5a91d4 MCC |
11325 | static int drx_ctrl_u_code(struct drx_demod_instance *demod, |
11326 | struct drxu_code_info *mc_info, | |
11327 | enum drxu_code_action action); | |
998819d2 | 11328 | static int drxj_set_lna_state(struct drx_demod_instance *demod, bool state); |
dc5a91d4 | 11329 | |
34eb9751 | 11330 | /* |
57afe2f0 | 11331 | * \fn drxj_open() |
38b2df95 DH |
11332 | * \brief Open the demod instance, configure device, configure drxdriver |
11333 | * \return Status_t Return status. | |
11334 | * | |
57afe2f0 MCC |
11335 | * drxj_open() can be called with a NULL ucode image => no ucode upload. |
11336 | * This means that drxj_open() must NOT contain SCU commands or, in general, | |
38b2df95 DH |
11337 | * rely on SCU or AUD ucode to be present. |
11338 | * | |
11339 | */ | |
dc5a91d4 | 11340 | |
01473146 | 11341 | static int drxj_open(struct drx_demod_instance *demod) |
38b2df95 | 11342 | { |
57afe2f0 | 11343 | struct i2c_device_addr *dev_addr = NULL; |
b3ce3a83 | 11344 | struct drxj_data *ext_attr = NULL; |
1bfc9e15 | 11345 | struct drx_common_attr *common_attr = NULL; |
57afe2f0 | 11346 | u32 driver_version = 0; |
1bfc9e15 MCC |
11347 | struct drxu_code_info ucode_info; |
11348 | struct drx_cfg_mpeg_output cfg_mpeg_output; | |
068e94ea | 11349 | int rc; |
d7a5478a | 11350 | enum drx_power_mode power_mode = DRX_POWER_UP; |
b78359a6 MCC |
11351 | |
11352 | if ((demod == NULL) || | |
11353 | (demod->my_common_attr == NULL) || | |
11354 | (demod->my_ext_attr == NULL) || | |
11355 | (demod->my_i2c_dev_addr == NULL) || | |
11356 | (demod->my_common_attr->is_opened)) { | |
11357 | return -EINVAL; | |
11358 | } | |
11359 | ||
443f18d0 | 11360 | /* Check arguments */ |
068e94ea | 11361 | if (demod->my_ext_attr == NULL) |
9482354f | 11362 | return -EINVAL; |
38b2df95 | 11363 | |
57afe2f0 | 11364 | dev_addr = demod->my_i2c_dev_addr; |
b3ce3a83 | 11365 | ext_attr = (struct drxj_data *) demod->my_ext_attr; |
1bfc9e15 | 11366 | common_attr = (struct drx_common_attr *) demod->my_common_attr; |
38b2df95 | 11367 | |
d7a5478a | 11368 | rc = ctrl_power_mode(demod, &power_mode); |
9482354f | 11369 | if (rc != 0) { |
068e94ea MCC |
11370 | pr_err("error %d\n", rc); |
11371 | goto rw_error; | |
11372 | } | |
d7a5478a MCC |
11373 | if (power_mode != DRX_POWER_UP) { |
11374 | rc = -EINVAL; | |
11375 | pr_err("failed to powerup device\n"); | |
11376 | goto rw_error; | |
11377 | } | |
38b2df95 | 11378 | |
443f18d0 | 11379 | /* has to be in front of setIqmAf and setOrxNsuAox */ |
068e94ea | 11380 | rc = get_device_capabilities(demod); |
9482354f | 11381 | if (rc != 0) { |
068e94ea MCC |
11382 | pr_err("error %d\n", rc); |
11383 | goto rw_error; | |
11384 | } | |
38b2df95 | 11385 | |
8afff9a2 MCC |
11386 | /* |
11387 | * Soft reset of sys- and osc-clockdomain | |
11388 | * | |
11389 | * HACK: On windows, it writes a 0x07 here, instead of just 0x03. | |
11390 | * As we didn't load the firmware here yet, we should do the same. | |
11391 | * Btw, this is coherent with DRX-K, where we send reset codes | |
11392 | * for modulation (OFTM, in DRX-k), SYS and OSC clock domains. | |
11393 | */ | |
11394 | rc = drxj_dap_write_reg16(dev_addr, SIO_CC_SOFT_RST__A, (0x04 | SIO_CC_SOFT_RST_SYS__M | SIO_CC_SOFT_RST_OSC__M), 0); | |
9482354f | 11395 | if (rc != 0) { |
068e94ea MCC |
11396 | pr_err("error %d\n", rc); |
11397 | goto rw_error; | |
11398 | } | |
244c0e06 | 11399 | rc = drxj_dap_write_reg16(dev_addr, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY, 0); |
9482354f | 11400 | if (rc != 0) { |
068e94ea MCC |
11401 | pr_err("error %d\n", rc); |
11402 | goto rw_error; | |
11403 | } | |
d7b0631e | 11404 | msleep(1); |
38b2df95 | 11405 | |
443f18d0 MCC |
11406 | /* TODO first make sure that everything keeps working before enabling this */ |
11407 | /* PowerDownAnalogBlocks() */ | |
244c0e06 | 11408 | rc = drxj_dap_write_reg16(dev_addr, ATV_TOP_STDBY__A, (~ATV_TOP_STDBY_CVBS_STDBY_A2_ACTIVE) | ATV_TOP_STDBY_SIF_STDBY_STANDBY, 0); |
9482354f | 11409 | if (rc != 0) { |
068e94ea MCC |
11410 | pr_err("error %d\n", rc); |
11411 | goto rw_error; | |
11412 | } | |
38b2df95 | 11413 | |
068e94ea | 11414 | rc = set_iqm_af(demod, false); |
9482354f | 11415 | if (rc != 0) { |
068e94ea MCC |
11416 | pr_err("error %d\n", rc); |
11417 | goto rw_error; | |
11418 | } | |
11419 | rc = set_orx_nsu_aox(demod, false); | |
9482354f | 11420 | if (rc != 0) { |
068e94ea MCC |
11421 | pr_err("error %d\n", rc); |
11422 | goto rw_error; | |
11423 | } | |
38b2df95 | 11424 | |
068e94ea | 11425 | rc = init_hi(demod); |
9482354f | 11426 | if (rc != 0) { |
068e94ea MCC |
11427 | pr_err("error %d\n", rc); |
11428 | goto rw_error; | |
11429 | } | |
38b2df95 | 11430 | |
443f18d0 | 11431 | /* disable mpegoutput pins */ |
41b5cc0c | 11432 | memcpy(&cfg_mpeg_output, &common_attr->mpeg_cfg, sizeof(cfg_mpeg_output)); |
57afe2f0 | 11433 | cfg_mpeg_output.enable_mpeg_output = false; |
41b5cc0c | 11434 | |
068e94ea | 11435 | rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output); |
9482354f | 11436 | if (rc != 0) { |
068e94ea MCC |
11437 | pr_err("error %d\n", rc); |
11438 | goto rw_error; | |
11439 | } | |
443f18d0 | 11440 | /* Stop AUD Inform SetAudio it will need to do all setting */ |
068e94ea | 11441 | rc = power_down_aud(demod); |
9482354f | 11442 | if (rc != 0) { |
068e94ea MCC |
11443 | pr_err("error %d\n", rc); |
11444 | goto rw_error; | |
11445 | } | |
443f18d0 | 11446 | /* Stop SCU */ |
244c0e06 | 11447 | rc = drxj_dap_write_reg16(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_STOP, 0); |
9482354f | 11448 | if (rc != 0) { |
068e94ea MCC |
11449 | pr_err("error %d\n", rc); |
11450 | goto rw_error; | |
11451 | } | |
38b2df95 | 11452 | |
443f18d0 | 11453 | /* Upload microcode */ |
b48293db | 11454 | if (common_attr->microcode_file != NULL) { |
443f18d0 MCC |
11455 | /* Dirty trick to use common ucode upload & verify, |
11456 | pretend device is already open */ | |
57afe2f0 | 11457 | common_attr->is_opened = true; |
b48293db | 11458 | ucode_info.mc_file = common_attr->microcode_file; |
38b2df95 | 11459 | |
dc5a91d4 MCC |
11460 | if (DRX_ISPOWERDOWNMODE(demod->my_common_attr->current_power_mode)) { |
11461 | pr_err("Should powerup before loading the firmware."); | |
11462 | return -EINVAL; | |
11463 | } | |
11464 | ||
11465 | rc = drx_ctrl_u_code(demod, &ucode_info, UCODE_UPLOAD); | |
9482354f | 11466 | if (rc != 0) { |
dc5a91d4 | 11467 | pr_err("error %d while uploading the firmware\n", rc); |
068e94ea MCC |
11468 | goto rw_error; |
11469 | } | |
57afe2f0 | 11470 | if (common_attr->verify_microcode == true) { |
dc5a91d4 | 11471 | rc = drx_ctrl_u_code(demod, &ucode_info, UCODE_VERIFY); |
9482354f | 11472 | if (rc != 0) { |
dc5a91d4 MCC |
11473 | pr_err("error %d while verifying the firmware\n", |
11474 | rc); | |
068e94ea MCC |
11475 | goto rw_error; |
11476 | } | |
443f18d0 | 11477 | } |
57afe2f0 | 11478 | common_attr->is_opened = false; |
443f18d0 | 11479 | } |
38b2df95 | 11480 | |
443f18d0 | 11481 | /* Run SCU for a little while to initialize microcode version numbers */ |
244c0e06 | 11482 | rc = drxj_dap_write_reg16(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE, 0); |
9482354f | 11483 | if (rc != 0) { |
068e94ea MCC |
11484 | pr_err("error %d\n", rc); |
11485 | goto rw_error; | |
11486 | } | |
38b2df95 | 11487 | |
443f18d0 | 11488 | /* Initialize scan timeout */ |
57afe2f0 MCC |
11489 | common_attr->scan_demod_lock_timeout = DRXJ_SCAN_TIMEOUT; |
11490 | common_attr->scan_desired_lock = DRX_LOCKED; | |
443f18d0 | 11491 | |
aafdbaa6 | 11492 | drxj_reset_mode(ext_attr); |
57afe2f0 | 11493 | ext_attr->standard = DRX_STANDARD_UNKNOWN; |
443f18d0 | 11494 | |
068e94ea | 11495 | rc = smart_ant_init(demod); |
9482354f | 11496 | if (rc != 0) { |
068e94ea MCC |
11497 | pr_err("error %d\n", rc); |
11498 | goto rw_error; | |
11499 | } | |
443f18d0 MCC |
11500 | |
11501 | /* Stamp driver version number in SCU data RAM in BCD code | |
69bb7ab6 | 11502 | Done to enable field application engineers to retrieve drxdriver version |
443f18d0 MCC |
11503 | via I2C from SCU RAM |
11504 | */ | |
57afe2f0 MCC |
11505 | driver_version = (VERSION_MAJOR / 100) % 10; |
11506 | driver_version <<= 4; | |
11507 | driver_version += (VERSION_MAJOR / 10) % 10; | |
11508 | driver_version <<= 4; | |
11509 | driver_version += (VERSION_MAJOR % 10); | |
11510 | driver_version <<= 4; | |
11511 | driver_version += (VERSION_MINOR % 10); | |
11512 | driver_version <<= 4; | |
11513 | driver_version += (VERSION_PATCH / 1000) % 10; | |
11514 | driver_version <<= 4; | |
11515 | driver_version += (VERSION_PATCH / 100) % 10; | |
11516 | driver_version <<= 4; | |
11517 | driver_version += (VERSION_PATCH / 10) % 10; | |
11518 | driver_version <<= 4; | |
11519 | driver_version += (VERSION_PATCH % 10); | |
244c0e06 | 11520 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_DRIVER_VER_HI__A, (u16)(driver_version >> 16), 0); |
9482354f | 11521 | if (rc != 0) { |
068e94ea MCC |
11522 | pr_err("error %d\n", rc); |
11523 | goto rw_error; | |
11524 | } | |
244c0e06 | 11525 | rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_DRIVER_VER_LO__A, (u16)(driver_version & 0xFFFF), 0); |
9482354f | 11526 | if (rc != 0) { |
068e94ea MCC |
11527 | pr_err("error %d\n", rc); |
11528 | goto rw_error; | |
11529 | } | |
443f18d0 | 11530 | |
bf9b94ab MCC |
11531 | rc = ctrl_set_oob(demod, NULL); |
11532 | if (rc != 0) { | |
11533 | pr_err("error %d\n", rc); | |
11534 | goto rw_error; | |
11535 | } | |
11536 | ||
443f18d0 | 11537 | /* refresh the audio data structure with default */ |
57afe2f0 | 11538 | ext_attr->aud_data = drxj_default_aud_data_g; |
443f18d0 | 11539 | |
b78359a6 | 11540 | demod->my_common_attr->is_opened = true; |
998819d2 | 11541 | drxj_set_lna_state(demod, false); |
9482354f | 11542 | return 0; |
38b2df95 | 11543 | rw_error: |
57afe2f0 | 11544 | common_attr->is_opened = false; |
30741871 | 11545 | return rc; |
38b2df95 DH |
11546 | } |
11547 | ||
11548 | /*============================================================================*/ | |
34eb9751 | 11549 | /* |
57afe2f0 | 11550 | * \fn drxj_close() |
38b2df95 DH |
11551 | * \brief Close the demod instance, power down the device |
11552 | * \return Status_t Return status. | |
11553 | * | |
11554 | */ | |
01473146 | 11555 | static int drxj_close(struct drx_demod_instance *demod) |
38b2df95 | 11556 | { |
4d7bb0eb | 11557 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; |
068e94ea | 11558 | int rc; |
1bfc9e15 | 11559 | enum drx_power_mode power_mode = DRX_POWER_UP; |
38b2df95 | 11560 | |
1e5ec31a | 11561 | if ((demod->my_common_attr == NULL) || |
b78359a6 MCC |
11562 | (demod->my_ext_attr == NULL) || |
11563 | (demod->my_i2c_dev_addr == NULL) || | |
11564 | (!demod->my_common_attr->is_opened)) { | |
11565 | return -EINVAL; | |
11566 | } | |
11567 | ||
443f18d0 | 11568 | /* power up */ |
068e94ea | 11569 | rc = ctrl_power_mode(demod, &power_mode); |
9482354f | 11570 | if (rc != 0) { |
068e94ea MCC |
11571 | pr_err("error %d\n", rc); |
11572 | goto rw_error; | |
11573 | } | |
38b2df95 | 11574 | |
244c0e06 | 11575 | rc = drxj_dap_write_reg16(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE, 0); |
9482354f | 11576 | if (rc != 0) { |
068e94ea MCC |
11577 | pr_err("error %d\n", rc); |
11578 | goto rw_error; | |
11579 | } | |
57afe2f0 | 11580 | power_mode = DRX_POWER_DOWN; |
068e94ea | 11581 | rc = ctrl_power_mode(demod, &power_mode); |
9482354f | 11582 | if (rc != 0) { |
068e94ea MCC |
11583 | pr_err("error %d\n", rc); |
11584 | goto rw_error; | |
11585 | } | |
443f18d0 | 11586 | |
b78359a6 MCC |
11587 | DRX_ATTR_ISOPENED(demod) = false; |
11588 | ||
9482354f | 11589 | return 0; |
38b2df95 | 11590 | rw_error: |
b78359a6 MCC |
11591 | DRX_ATTR_ISOPENED(demod) = false; |
11592 | ||
30741871 | 11593 | return rc; |
38b2df95 DH |
11594 | } |
11595 | ||
b240eacd MCC |
11596 | /* |
11597 | * Microcode related functions | |
11598 | */ | |
11599 | ||
34eb9751 | 11600 | /* |
b240eacd MCC |
11601 | * drx_u_code_compute_crc - Compute CRC of block of microcode data. |
11602 | * @block_data: Pointer to microcode data. | |
11603 | * @nr_words: Size of microcode block (number of 16 bits words). | |
11604 | * | |
11605 | * returns The computed CRC residue. | |
11606 | */ | |
11607 | static u16 drx_u_code_compute_crc(u8 *block_data, u16 nr_words) | |
11608 | { | |
11609 | u16 i = 0; | |
11610 | u16 j = 0; | |
11611 | u32 crc_word = 0; | |
11612 | u32 carry = 0; | |
11613 | ||
11614 | while (i < nr_words) { | |
4182438e | 11615 | crc_word |= (u32)be16_to_cpu(*(__be16 *)(block_data)); |
b240eacd MCC |
11616 | for (j = 0; j < 16; j++) { |
11617 | crc_word <<= 1; | |
11618 | if (carry != 0) | |
11619 | crc_word ^= 0x80050000UL; | |
11620 | carry = crc_word & 0x80000000UL; | |
11621 | } | |
11622 | i++; | |
11623 | block_data += (sizeof(u16)); | |
11624 | } | |
11625 | return (u16)(crc_word >> 16); | |
11626 | } | |
11627 | ||
34eb9751 | 11628 | /* |
b240eacd MCC |
11629 | * drx_check_firmware - checks if the loaded firmware is valid |
11630 | * | |
11631 | * @demod: demod structure | |
11632 | * @mc_data: pointer to the start of the firmware | |
11633 | * @size: firmware size | |
11634 | */ | |
11635 | static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data, | |
11636 | unsigned size) | |
11637 | { | |
11638 | struct drxu_code_block_hdr block_hdr; | |
11639 | int i; | |
11640 | unsigned count = 2 * sizeof(u16); | |
11641 | u32 mc_dev_type, mc_version, mc_base_version; | |
4182438e | 11642 | u16 mc_nr_of_blks = be16_to_cpu(*(__be16 *)(mc_data + sizeof(u16))); |
b240eacd MCC |
11643 | |
11644 | /* | |
11645 | * Scan microcode blocks first for version info | |
11646 | * and firmware check | |
11647 | */ | |
11648 | ||
11649 | /* Clear version block */ | |
11650 | DRX_ATTR_MCRECORD(demod).aux_type = 0; | |
11651 | DRX_ATTR_MCRECORD(demod).mc_dev_type = 0; | |
11652 | DRX_ATTR_MCRECORD(demod).mc_version = 0; | |
11653 | DRX_ATTR_MCRECORD(demod).mc_base_version = 0; | |
11654 | ||
11655 | for (i = 0; i < mc_nr_of_blks; i++) { | |
11656 | if (count + 3 * sizeof(u16) + sizeof(u32) > size) | |
11657 | goto eof; | |
11658 | ||
11659 | /* Process block header */ | |
4182438e | 11660 | block_hdr.addr = be32_to_cpu(*(__be32 *)(mc_data + count)); |
b240eacd | 11661 | count += sizeof(u32); |
4182438e | 11662 | block_hdr.size = be16_to_cpu(*(__be16 *)(mc_data + count)); |
b240eacd | 11663 | count += sizeof(u16); |
4182438e | 11664 | block_hdr.flags = be16_to_cpu(*(__be16 *)(mc_data + count)); |
b240eacd | 11665 | count += sizeof(u16); |
4182438e | 11666 | block_hdr.CRC = be16_to_cpu(*(__be16 *)(mc_data + count)); |
b240eacd MCC |
11667 | count += sizeof(u16); |
11668 | ||
11669 | pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n", | |
11670 | count, block_hdr.addr, block_hdr.size, block_hdr.flags, | |
11671 | block_hdr.CRC); | |
11672 | ||
11673 | if (block_hdr.flags & 0x8) { | |
11674 | u8 *auxblk = ((void *)mc_data) + block_hdr.addr; | |
11675 | u16 auxtype; | |
11676 | ||
11677 | if (block_hdr.addr + sizeof(u16) > size) | |
11678 | goto eof; | |
11679 | ||
4182438e | 11680 | auxtype = be16_to_cpu(*(__be16 *)(auxblk)); |
b240eacd MCC |
11681 | |
11682 | /* Aux block. Check type */ | |
11683 | if (DRX_ISMCVERTYPE(auxtype)) { | |
11684 | if (block_hdr.addr + 2 * sizeof(u16) + 2 * sizeof (u32) > size) | |
11685 | goto eof; | |
11686 | ||
11687 | auxblk += sizeof(u16); | |
4182438e | 11688 | mc_dev_type = be32_to_cpu(*(__be32 *)(auxblk)); |
b240eacd | 11689 | auxblk += sizeof(u32); |
4182438e | 11690 | mc_version = be32_to_cpu(*(__be32 *)(auxblk)); |
b240eacd | 11691 | auxblk += sizeof(u32); |
4182438e | 11692 | mc_base_version = be32_to_cpu(*(__be32 *)(auxblk)); |
b240eacd MCC |
11693 | |
11694 | DRX_ATTR_MCRECORD(demod).aux_type = auxtype; | |
11695 | DRX_ATTR_MCRECORD(demod).mc_dev_type = mc_dev_type; | |
11696 | DRX_ATTR_MCRECORD(demod).mc_version = mc_version; | |
11697 | DRX_ATTR_MCRECORD(demod).mc_base_version = mc_base_version; | |
11698 | ||
11699 | pr_info("Firmware dev %x, ver %x, base ver %x\n", | |
11700 | mc_dev_type, mc_version, mc_base_version); | |
11701 | ||
11702 | } | |
11703 | } else if (count + block_hdr.size * sizeof(u16) > size) | |
11704 | goto eof; | |
11705 | ||
11706 | count += block_hdr.size * sizeof(u16); | |
11707 | } | |
11708 | return 0; | |
11709 | eof: | |
11710 | pr_err("Firmware is truncated at pos %u/%u\n", count, size); | |
11711 | return -EINVAL; | |
11712 | } | |
11713 | ||
34eb9751 | 11714 | /* |
b240eacd MCC |
11715 | * drx_ctrl_u_code - Handle microcode upload or verify. |
11716 | * @dev_addr: Address of device. | |
11717 | * @mc_info: Pointer to information about microcode data. | |
11718 | * @action: Either UCODE_UPLOAD or UCODE_VERIFY | |
11719 | * | |
11720 | * This function returns: | |
11721 | * 0: | |
11722 | * - In case of UCODE_UPLOAD: code is successfully uploaded. | |
11723 | * - In case of UCODE_VERIFY: image on device is equal to | |
11724 | * image provided to this control function. | |
11725 | * -EIO: | |
11726 | * - In case of UCODE_UPLOAD: I2C error. | |
11727 | * - In case of UCODE_VERIFY: I2C error or image on device | |
11728 | * is not equal to image provided to this control function. | |
4a3fad70 | 11729 | * -EINVAL: |
b240eacd MCC |
11730 | * - Invalid arguments. |
11731 | * - Provided image is corrupt | |
11732 | */ | |
11733 | static int drx_ctrl_u_code(struct drx_demod_instance *demod, | |
11734 | struct drxu_code_info *mc_info, | |
11735 | enum drxu_code_action action) | |
11736 | { | |
11737 | struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr; | |
11738 | int rc; | |
11739 | u16 i = 0; | |
11740 | u16 mc_nr_of_blks = 0; | |
11741 | u16 mc_magic_word = 0; | |
11742 | const u8 *mc_data_init = NULL; | |
11743 | u8 *mc_data = NULL; | |
11744 | unsigned size; | |
1d001c3f | 11745 | char *mc_file; |
b240eacd MCC |
11746 | |
11747 | /* Check arguments */ | |
1d001c3f | 11748 | if (!mc_info || !mc_info->mc_file) |
b240eacd MCC |
11749 | return -EINVAL; |
11750 | ||
1d001c3f MCC |
11751 | mc_file = mc_info->mc_file; |
11752 | ||
b240eacd MCC |
11753 | if (!demod->firmware) { |
11754 | const struct firmware *fw = NULL; | |
11755 | ||
11756 | rc = request_firmware(&fw, mc_file, demod->i2c->dev.parent); | |
11757 | if (rc < 0) { | |
11758 | pr_err("Couldn't read firmware %s\n", mc_file); | |
691cbbe3 | 11759 | return rc; |
b240eacd MCC |
11760 | } |
11761 | demod->firmware = fw; | |
11762 | ||
11763 | if (demod->firmware->size < 2 * sizeof(u16)) { | |
11764 | rc = -EINVAL; | |
11765 | pr_err("Firmware is too short!\n"); | |
11766 | goto release; | |
11767 | } | |
11768 | ||
11769 | pr_info("Firmware %s, size %zu\n", | |
11770 | mc_file, demod->firmware->size); | |
11771 | } | |
11772 | ||
11773 | mc_data_init = demod->firmware->data; | |
11774 | size = demod->firmware->size; | |
11775 | ||
11776 | mc_data = (void *)mc_data_init; | |
11777 | /* Check data */ | |
4182438e | 11778 | mc_magic_word = be16_to_cpu(*(__be16 *)(mc_data)); |
b240eacd | 11779 | mc_data += sizeof(u16); |
4182438e | 11780 | mc_nr_of_blks = be16_to_cpu(*(__be16 *)(mc_data)); |
b240eacd MCC |
11781 | mc_data += sizeof(u16); |
11782 | ||
11783 | if ((mc_magic_word != DRX_UCODE_MAGIC_WORD) || (mc_nr_of_blks == 0)) { | |
11784 | rc = -EINVAL; | |
11785 | pr_err("Firmware magic word doesn't match\n"); | |
11786 | goto release; | |
11787 | } | |
11788 | ||
11789 | if (action == UCODE_UPLOAD) { | |
11790 | rc = drx_check_firmware(demod, (u8 *)mc_data_init, size); | |
11791 | if (rc) | |
11792 | goto release; | |
b240eacd | 11793 | pr_info("Uploading firmware %s\n", mc_file); |
dc5a91d4 | 11794 | } else { |
b240eacd MCC |
11795 | pr_info("Verifying if firmware upload was ok.\n"); |
11796 | } | |
11797 | ||
11798 | /* Process microcode blocks */ | |
11799 | for (i = 0; i < mc_nr_of_blks; i++) { | |
11800 | struct drxu_code_block_hdr block_hdr; | |
11801 | u16 mc_block_nr_bytes = 0; | |
11802 | ||
11803 | /* Process block header */ | |
4182438e | 11804 | block_hdr.addr = be32_to_cpu(*(__be32 *)(mc_data)); |
b240eacd | 11805 | mc_data += sizeof(u32); |
4182438e | 11806 | block_hdr.size = be16_to_cpu(*(__be16 *)(mc_data)); |
b240eacd | 11807 | mc_data += sizeof(u16); |
4182438e | 11808 | block_hdr.flags = be16_to_cpu(*(__be16 *)(mc_data)); |
b240eacd | 11809 | mc_data += sizeof(u16); |
4182438e | 11810 | block_hdr.CRC = be16_to_cpu(*(__be16 *)(mc_data)); |
b240eacd MCC |
11811 | mc_data += sizeof(u16); |
11812 | ||
c4f04796 MCC |
11813 | pr_debug("%zd: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n", |
11814 | (mc_data - mc_data_init), block_hdr.addr, | |
b240eacd MCC |
11815 | block_hdr.size, block_hdr.flags, block_hdr.CRC); |
11816 | ||
11817 | /* Check block header on: | |
11818 | - data larger than 64Kb | |
11819 | - if CRC enabled check CRC | |
11820 | */ | |
11821 | if ((block_hdr.size > 0x7FFF) || | |
11822 | (((block_hdr.flags & DRX_UCODE_CRC_FLAG) != 0) && | |
11823 | (block_hdr.CRC != drx_u_code_compute_crc(mc_data, block_hdr.size))) | |
11824 | ) { | |
11825 | /* Wrong data ! */ | |
11826 | rc = -EINVAL; | |
11827 | pr_err("firmware CRC is wrong\n"); | |
11828 | goto release; | |
11829 | } | |
11830 | ||
11831 | if (!block_hdr.size) | |
11832 | continue; | |
11833 | ||
11834 | mc_block_nr_bytes = block_hdr.size * ((u16) sizeof(u16)); | |
11835 | ||
11836 | /* Perform the desired action */ | |
11837 | switch (action) { | |
11838 | case UCODE_UPLOAD: /* Upload microcode */ | |
244c0e06 | 11839 | if (drxdap_fasi_write_block(dev_addr, |
b240eacd MCC |
11840 | block_hdr.addr, |
11841 | mc_block_nr_bytes, | |
11842 | mc_data, 0x0000)) { | |
11843 | rc = -EIO; | |
c4f04796 MCC |
11844 | pr_err("error writing firmware at pos %zd\n", |
11845 | mc_data - mc_data_init); | |
b240eacd MCC |
11846 | goto release; |
11847 | } | |
11848 | break; | |
11849 | case UCODE_VERIFY: { /* Verify uploaded microcode */ | |
11850 | int result = 0; | |
11851 | u8 mc_data_buffer[DRX_UCODE_MAX_BUF_SIZE]; | |
11852 | u32 bytes_to_comp = 0; | |
11853 | u32 bytes_left = mc_block_nr_bytes; | |
11854 | u32 curr_addr = block_hdr.addr; | |
11855 | u8 *curr_ptr = mc_data; | |
11856 | ||
11857 | while (bytes_left != 0) { | |
11858 | if (bytes_left > DRX_UCODE_MAX_BUF_SIZE) | |
11859 | bytes_to_comp = DRX_UCODE_MAX_BUF_SIZE; | |
11860 | else | |
11861 | bytes_to_comp = bytes_left; | |
11862 | ||
244c0e06 | 11863 | if (drxdap_fasi_read_block(dev_addr, |
b240eacd MCC |
11864 | curr_addr, |
11865 | (u16)bytes_to_comp, | |
11866 | (u8 *)mc_data_buffer, | |
11867 | 0x0000)) { | |
c4f04796 MCC |
11868 | pr_err("error reading firmware at pos %zd\n", |
11869 | mc_data - mc_data_init); | |
b240eacd MCC |
11870 | return -EIO; |
11871 | } | |
11872 | ||
d7b0631e MCC |
11873 | result = memcmp(curr_ptr, mc_data_buffer, |
11874 | bytes_to_comp); | |
b240eacd MCC |
11875 | |
11876 | if (result) { | |
c4f04796 MCC |
11877 | pr_err("error verifying firmware at pos %zd\n", |
11878 | mc_data - mc_data_init); | |
b240eacd MCC |
11879 | return -EIO; |
11880 | } | |
11881 | ||
11882 | curr_addr += ((dr_xaddr_t)(bytes_to_comp / 2)); | |
11883 | curr_ptr =&(curr_ptr[bytes_to_comp]); | |
11884 | bytes_left -=((u32) bytes_to_comp); | |
11885 | } | |
11886 | break; | |
11887 | } | |
11888 | default: | |
11889 | return -EINVAL; | |
11890 | break; | |
11891 | ||
11892 | } | |
11893 | mc_data += mc_block_nr_bytes; | |
11894 | } | |
11895 | ||
11896 | return 0; | |
11897 | ||
11898 | release: | |
11899 | release_firmware(demod->firmware); | |
11900 | demod->firmware = NULL; | |
11901 | ||
11902 | return rc; | |
11903 | } | |
19013747 | 11904 | |
69bb7ab6 | 11905 | /* caller is expected to check if lna is supported before enabling */ |
998819d2 SK |
11906 | static int drxj_set_lna_state(struct drx_demod_instance *demod, bool state) |
11907 | { | |
11908 | struct drxuio_cfg uio_cfg; | |
11909 | struct drxuio_data uio_data; | |
11910 | int result; | |
11911 | ||
11912 | uio_cfg.uio = DRX_UIO1; | |
11913 | uio_cfg.mode = DRX_UIO_MODE_READWRITE; | |
11914 | /* Configure user-I/O #3: enable read/write */ | |
11915 | result = ctrl_set_uio_cfg(demod, &uio_cfg); | |
11916 | if (result) { | |
11917 | pr_err("Failed to setup LNA GPIO!\n"); | |
11918 | return result; | |
11919 | } | |
11920 | ||
11921 | uio_data.uio = DRX_UIO1; | |
11922 | uio_data.value = state; | |
11923 | result = ctrl_uio_write(demod, &uio_data); | |
11924 | if (result != 0) { | |
11925 | pr_err("Failed to %sable LNA!\n", | |
11926 | state ? "en" : "dis"); | |
11927 | return result; | |
11928 | } | |
11929 | return 0; | |
11930 | } | |
11931 | ||
19013747 MCC |
11932 | /* |
11933 | * The Linux DVB Driver for Micronas DRX39xx family (drx3933j) | |
11934 | * | |
11935 | * Written by Devin Heitmueller <devin.heitmueller@kernellabs.com> | |
11936 | */ | |
11937 | ||
11938 | static int drx39xxj_set_powerstate(struct dvb_frontend *fe, int enable) | |
11939 | { | |
11940 | struct drx39xxj_state *state = fe->demodulator_priv; | |
11941 | struct drx_demod_instance *demod = state->demod; | |
11942 | int result; | |
11943 | enum drx_power_mode power_mode; | |
11944 | ||
11945 | if (enable) | |
11946 | power_mode = DRX_POWER_UP; | |
11947 | else | |
11948 | power_mode = DRX_POWER_DOWN; | |
11949 | ||
b0baeb49 | 11950 | result = ctrl_power_mode(demod, &power_mode); |
19013747 MCC |
11951 | if (result != 0) { |
11952 | pr_err("Power state change failed\n"); | |
11953 | return 0; | |
11954 | } | |
11955 | ||
19013747 MCC |
11956 | return 0; |
11957 | } | |
11958 | ||
0df289a2 | 11959 | static int drx39xxj_read_status(struct dvb_frontend *fe, enum fe_status *status) |
19013747 MCC |
11960 | { |
11961 | struct drx39xxj_state *state = fe->demodulator_priv; | |
11962 | struct drx_demod_instance *demod = state->demod; | |
11963 | int result; | |
11964 | enum drx_lock_status lock_status; | |
11965 | ||
11966 | *status = 0; | |
11967 | ||
b0baeb49 | 11968 | result = ctrl_lock_status(demod, &lock_status); |
19013747 MCC |
11969 | if (result != 0) { |
11970 | pr_err("drx39xxj: could not get lock status!\n"); | |
11971 | *status = 0; | |
11972 | } | |
11973 | ||
11974 | switch (lock_status) { | |
11975 | case DRX_NEVER_LOCK: | |
11976 | *status = 0; | |
11977 | pr_err("drx says NEVER_LOCK\n"); | |
11978 | break; | |
11979 | case DRX_NOT_LOCKED: | |
11980 | *status = 0; | |
11981 | break; | |
11982 | case DRX_LOCK_STATE_1: | |
11983 | case DRX_LOCK_STATE_2: | |
11984 | case DRX_LOCK_STATE_3: | |
11985 | case DRX_LOCK_STATE_4: | |
11986 | case DRX_LOCK_STATE_5: | |
11987 | case DRX_LOCK_STATE_6: | |
11988 | case DRX_LOCK_STATE_7: | |
11989 | case DRX_LOCK_STATE_8: | |
11990 | case DRX_LOCK_STATE_9: | |
11991 | *status = FE_HAS_SIGNAL | |
11992 | | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC; | |
11993 | break; | |
11994 | case DRX_LOCKED: | |
11995 | *status = FE_HAS_SIGNAL | |
11996 | | FE_HAS_CARRIER | |
11997 | | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | |
11998 | break; | |
11999 | default: | |
12000 | pr_err("Lock state unknown %d\n", lock_status); | |
12001 | } | |
03fdfbfd | 12002 | ctrl_sig_quality(demod, lock_status); |
19013747 MCC |
12003 | |
12004 | return 0; | |
12005 | } | |
12006 | ||
12007 | static int drx39xxj_read_ber(struct dvb_frontend *fe, u32 *ber) | |
12008 | { | |
03fdfbfd | 12009 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
19013747 | 12010 | |
03fdfbfd | 12011 | if (p->pre_bit_error.stat[0].scale == FE_SCALE_NOT_AVAILABLE) { |
19013747 MCC |
12012 | *ber = 0; |
12013 | return 0; | |
12014 | } | |
12015 | ||
69832578 MCC |
12016 | if (!p->pre_bit_count.stat[0].uvalue) { |
12017 | if (!p->pre_bit_error.stat[0].uvalue) | |
12018 | *ber = 0; | |
12019 | else | |
12020 | *ber = 1000000; | |
12021 | } else { | |
12022 | *ber = frac_times1e6(p->pre_bit_error.stat[0].uvalue, | |
12023 | p->pre_bit_count.stat[0].uvalue); | |
12024 | } | |
19013747 MCC |
12025 | return 0; |
12026 | } | |
12027 | ||
12028 | static int drx39xxj_read_signal_strength(struct dvb_frontend *fe, | |
12029 | u16 *strength) | |
12030 | { | |
03fdfbfd | 12031 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
19013747 | 12032 | |
03fdfbfd | 12033 | if (p->strength.stat[0].scale == FE_SCALE_NOT_AVAILABLE) { |
19013747 MCC |
12034 | *strength = 0; |
12035 | return 0; | |
12036 | } | |
12037 | ||
03fdfbfd | 12038 | *strength = p->strength.stat[0].uvalue; |
19013747 MCC |
12039 | return 0; |
12040 | } | |
12041 | ||
12042 | static int drx39xxj_read_snr(struct dvb_frontend *fe, u16 *snr) | |
12043 | { | |
03fdfbfd | 12044 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
90d9c3e1 | 12045 | u64 tmp64; |
19013747 | 12046 | |
03fdfbfd | 12047 | if (p->cnr.stat[0].scale == FE_SCALE_NOT_AVAILABLE) { |
19013747 MCC |
12048 | *snr = 0; |
12049 | return 0; | |
12050 | } | |
12051 | ||
90d9c3e1 GG |
12052 | tmp64 = p->cnr.stat[0].svalue; |
12053 | do_div(tmp64, 10); | |
12054 | *snr = tmp64; | |
19013747 MCC |
12055 | return 0; |
12056 | } | |
12057 | ||
03fdfbfd | 12058 | static int drx39xxj_read_ucblocks(struct dvb_frontend *fe, u32 *ucb) |
19013747 | 12059 | { |
03fdfbfd | 12060 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
19013747 | 12061 | |
03fdfbfd MCC |
12062 | if (p->block_error.stat[0].scale == FE_SCALE_NOT_AVAILABLE) { |
12063 | *ucb = 0; | |
19013747 MCC |
12064 | return 0; |
12065 | } | |
12066 | ||
03fdfbfd | 12067 | *ucb = p->block_error.stat[0].uvalue; |
19013747 MCC |
12068 | return 0; |
12069 | } | |
12070 | ||
12071 | static int drx39xxj_set_frontend(struct dvb_frontend *fe) | |
12072 | { | |
12073 | #ifdef DJH_DEBUG | |
12074 | int i; | |
12075 | #endif | |
12076 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; | |
12077 | struct drx39xxj_state *state = fe->demodulator_priv; | |
12078 | struct drx_demod_instance *demod = state->demod; | |
12079 | enum drx_standard standard = DRX_STANDARD_8VSB; | |
12080 | struct drx_channel channel; | |
12081 | int result; | |
19013747 MCC |
12082 | static const struct drx_channel def_channel = { |
12083 | /* frequency */ 0, | |
12084 | /* bandwidth */ DRX_BANDWIDTH_6MHZ, | |
12085 | /* mirror */ DRX_MIRROR_NO, | |
12086 | /* constellation */ DRX_CONSTELLATION_AUTO, | |
12087 | /* hierarchy */ DRX_HIERARCHY_UNKNOWN, | |
12088 | /* priority */ DRX_PRIORITY_UNKNOWN, | |
12089 | /* coderate */ DRX_CODERATE_UNKNOWN, | |
12090 | /* guard */ DRX_GUARD_UNKNOWN, | |
12091 | /* fftmode */ DRX_FFTMODE_UNKNOWN, | |
12092 | /* classification */ DRX_CLASSIFICATION_AUTO, | |
12093 | /* symbolrate */ 5057000, | |
12094 | /* interleavemode */ DRX_INTERLEAVEMODE_UNKNOWN, | |
12095 | /* ldpc */ DRX_LDPC_UNKNOWN, | |
12096 | /* carrier */ DRX_CARRIER_UNKNOWN, | |
12097 | /* frame mode */ DRX_FRAMEMODE_UNKNOWN | |
12098 | }; | |
12099 | u32 constellation = DRX_CONSTELLATION_AUTO; | |
12100 | ||
12101 | /* Bring the demod out of sleep */ | |
12102 | drx39xxj_set_powerstate(fe, 1); | |
12103 | ||
19013747 | 12104 | if (fe->ops.tuner_ops.set_params) { |
7abc7a54 MCC |
12105 | u32 int_freq; |
12106 | ||
19013747 MCC |
12107 | if (fe->ops.i2c_gate_ctrl) |
12108 | fe->ops.i2c_gate_ctrl(fe, 1); | |
7abc7a54 MCC |
12109 | |
12110 | /* Set tuner to desired frequency and standard */ | |
19013747 | 12111 | fe->ops.tuner_ops.set_params(fe); |
7abc7a54 MCC |
12112 | |
12113 | /* Use the tuner's IF */ | |
12114 | if (fe->ops.tuner_ops.get_if_frequency) { | |
12115 | fe->ops.tuner_ops.get_if_frequency(fe, &int_freq); | |
12116 | demod->my_common_attr->intermediate_freq = int_freq / 1000; | |
12117 | } | |
12118 | ||
19013747 MCC |
12119 | if (fe->ops.i2c_gate_ctrl) |
12120 | fe->ops.i2c_gate_ctrl(fe, 0); | |
12121 | } | |
12122 | ||
12123 | switch (p->delivery_system) { | |
12124 | case SYS_ATSC: | |
12125 | standard = DRX_STANDARD_8VSB; | |
12126 | break; | |
12127 | case SYS_DVBC_ANNEX_B: | |
12128 | standard = DRX_STANDARD_ITU_B; | |
12129 | ||
12130 | switch (p->modulation) { | |
12131 | case QAM_64: | |
12132 | constellation = DRX_CONSTELLATION_QAM64; | |
12133 | break; | |
12134 | case QAM_256: | |
12135 | constellation = DRX_CONSTELLATION_QAM256; | |
12136 | break; | |
12137 | default: | |
12138 | constellation = DRX_CONSTELLATION_AUTO; | |
12139 | break; | |
12140 | } | |
12141 | break; | |
12142 | default: | |
12143 | return -EINVAL; | |
12144 | } | |
c4dc6f92 MCC |
12145 | /* Set the standard (will be powered up if necessary */ |
12146 | result = ctrl_set_standard(demod, &standard); | |
12147 | if (result != 0) { | |
12148 | pr_err("Failed to set standard! result=%02x\n", | |
12149 | result); | |
12150 | return -EINVAL; | |
19013747 MCC |
12151 | } |
12152 | ||
12153 | /* set channel parameters */ | |
12154 | channel = def_channel; | |
12155 | channel.frequency = p->frequency / 1000; | |
12156 | channel.bandwidth = DRX_BANDWIDTH_6MHZ; | |
12157 | channel.constellation = constellation; | |
12158 | ||
12159 | /* program channel */ | |
b0baeb49 | 12160 | result = ctrl_set_channel(demod, &channel); |
19013747 MCC |
12161 | if (result != 0) { |
12162 | pr_err("Failed to set channel!\n"); | |
12163 | return -EINVAL; | |
12164 | } | |
12165 | /* Just for giggles, let's shut off the LNA again.... */ | |
b601fe56 | 12166 | drxj_set_lna_state(demod, false); |
03fdfbfd MCC |
12167 | |
12168 | /* After set_frontend, except for strength, stats aren't available */ | |
12169 | p->strength.stat[0].scale = FE_SCALE_RELATIVE; | |
19013747 MCC |
12170 | |
12171 | return 0; | |
12172 | } | |
12173 | ||
12174 | static int drx39xxj_sleep(struct dvb_frontend *fe) | |
12175 | { | |
12176 | /* power-down the demodulator */ | |
12177 | return drx39xxj_set_powerstate(fe, 0); | |
12178 | } | |
12179 | ||
12180 | static int drx39xxj_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | |
12181 | { | |
12182 | struct drx39xxj_state *state = fe->demodulator_priv; | |
12183 | struct drx_demod_instance *demod = state->demod; | |
12184 | bool i2c_gate_state; | |
12185 | int result; | |
12186 | ||
12187 | #ifdef DJH_DEBUG | |
6c955b8b | 12188 | pr_debug("i2c gate call: enable=%d state=%d\n", enable, |
19013747 MCC |
12189 | state->i2c_gate_open); |
12190 | #endif | |
12191 | ||
12192 | if (enable) | |
12193 | i2c_gate_state = true; | |
12194 | else | |
12195 | i2c_gate_state = false; | |
12196 | ||
12197 | if (state->i2c_gate_open == enable) { | |
12198 | /* We're already in the desired state */ | |
12199 | return 0; | |
12200 | } | |
12201 | ||
b0baeb49 | 12202 | result = ctrl_i2c_bridge(demod, &i2c_gate_state); |
19013747 MCC |
12203 | if (result != 0) { |
12204 | pr_err("drx39xxj: could not open i2c gate [%d]\n", | |
12205 | result); | |
12206 | dump_stack(); | |
12207 | } else { | |
12208 | state->i2c_gate_open = enable; | |
12209 | } | |
12210 | return 0; | |
12211 | } | |
12212 | ||
12213 | static int drx39xxj_init(struct dvb_frontend *fe) | |
12214 | { | |
998819d2 SK |
12215 | struct drx39xxj_state *state = fe->demodulator_priv; |
12216 | struct drx_demod_instance *demod = state->demod; | |
12217 | int rc = 0; | |
19013747 | 12218 | |
998819d2 SK |
12219 | if (fe->exit == DVB_FE_DEVICE_RESUME) { |
12220 | /* so drxj_open() does what it needs to do */ | |
12221 | demod->my_common_attr->is_opened = false; | |
12222 | rc = drxj_open(demod); | |
12223 | if (rc != 0) | |
12224 | pr_err("drx39xxj_init(): DRX open failed rc=%d!\n", rc); | |
12225 | } else | |
12226 | drx39xxj_set_powerstate(fe, 1); | |
12227 | ||
12228 | return rc; | |
19013747 MCC |
12229 | } |
12230 | ||
ea8f3c2c MCC |
12231 | static int drx39xxj_set_lna(struct dvb_frontend *fe) |
12232 | { | |
ea8f3c2c MCC |
12233 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
12234 | struct drx39xxj_state *state = fe->demodulator_priv; | |
12235 | struct drx_demod_instance *demod = state->demod; | |
12236 | struct drxj_data *ext_attr = demod->my_ext_attr; | |
ea8f3c2c MCC |
12237 | |
12238 | if (c->lna) { | |
12239 | if (!ext_attr->has_lna) { | |
12240 | pr_err("LNA is not supported on this device!\n"); | |
12241 | return -EINVAL; | |
12242 | ||
12243 | } | |
12244 | } | |
12245 | ||
b601fe56 | 12246 | return drxj_set_lna_state(demod, c->lna); |
ea8f3c2c MCC |
12247 | } |
12248 | ||
19013747 MCC |
12249 | static int drx39xxj_get_tune_settings(struct dvb_frontend *fe, |
12250 | struct dvb_frontend_tune_settings *tune) | |
12251 | { | |
12252 | tune->min_delay_ms = 1000; | |
12253 | return 0; | |
12254 | } | |
12255 | ||
12256 | static void drx39xxj_release(struct dvb_frontend *fe) | |
12257 | { | |
12258 | struct drx39xxj_state *state = fe->demodulator_priv; | |
12259 | struct drx_demod_instance *demod = state->demod; | |
12260 | ||
5b22b1a4 SK |
12261 | /* if device is removed don't access it */ |
12262 | if (fe->exit != DVB_FE_DEVICE_REMOVED) | |
12263 | drxj_close(demod); | |
1e5ec31a | 12264 | |
19013747 MCC |
12265 | kfree(demod->my_ext_attr); |
12266 | kfree(demod->my_common_attr); | |
12267 | kfree(demod->my_i2c_dev_addr); | |
9bc2dd7e | 12268 | release_firmware(demod->firmware); |
19013747 MCC |
12269 | kfree(demod); |
12270 | kfree(state); | |
12271 | } | |
12272 | ||
bd336e63 | 12273 | static const struct dvb_frontend_ops drx39xxj_ops; |
19013747 MCC |
12274 | |
12275 | struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c) | |
12276 | { | |
12277 | struct drx39xxj_state *state = NULL; | |
19013747 MCC |
12278 | struct i2c_device_addr *demod_addr = NULL; |
12279 | struct drx_common_attr *demod_comm_attr = NULL; | |
12280 | struct drxj_data *demod_ext_attr = NULL; | |
12281 | struct drx_demod_instance *demod = NULL; | |
d591590e | 12282 | struct dtv_frontend_properties *p; |
19013747 MCC |
12283 | int result; |
12284 | ||
12285 | /* allocate memory for the internal state */ | |
12286 | state = kzalloc(sizeof(struct drx39xxj_state), GFP_KERNEL); | |
12287 | if (state == NULL) | |
12288 | goto error; | |
12289 | ||
12290 | demod = kmalloc(sizeof(struct drx_demod_instance), GFP_KERNEL); | |
12291 | if (demod == NULL) | |
12292 | goto error; | |
12293 | ||
20f63150 BT |
12294 | demod_addr = kmemdup(&drxj_default_addr_g, |
12295 | sizeof(struct i2c_device_addr), GFP_KERNEL); | |
19013747 MCC |
12296 | if (demod_addr == NULL) |
12297 | goto error; | |
19013747 | 12298 | |
20f63150 BT |
12299 | demod_comm_attr = kmemdup(&drxj_default_comm_attr_g, |
12300 | sizeof(struct drx_common_attr), GFP_KERNEL); | |
19013747 MCC |
12301 | if (demod_comm_attr == NULL) |
12302 | goto error; | |
19013747 | 12303 | |
20f63150 BT |
12304 | demod_ext_attr = kmemdup(&drxj_data_g, sizeof(struct drxj_data), |
12305 | GFP_KERNEL); | |
19013747 MCC |
12306 | if (demod_ext_attr == NULL) |
12307 | goto error; | |
19013747 MCC |
12308 | |
12309 | /* setup the state */ | |
12310 | state->i2c = i2c; | |
12311 | state->demod = demod; | |
12312 | ||
12313 | /* setup the demod data */ | |
12314 | memcpy(demod, &drxj_default_demod_g, sizeof(struct drx_demod_instance)); | |
12315 | ||
12316 | demod->my_i2c_dev_addr = demod_addr; | |
12317 | demod->my_common_attr = demod_comm_attr; | |
12318 | demod->my_i2c_dev_addr->user_data = state; | |
12319 | demod->my_common_attr->microcode_file = DRX39XX_MAIN_FIRMWARE; | |
12320 | demod->my_common_attr->verify_microcode = true; | |
12321 | demod->my_common_attr->intermediate_freq = 5000; | |
d7a5478a | 12322 | demod->my_common_attr->current_power_mode = DRX_POWER_DOWN; |
19013747 MCC |
12323 | demod->my_ext_attr = demod_ext_attr; |
12324 | ((struct drxj_data *)demod_ext_attr)->uio_sma_tx_mode = DRX_UIO_MODE_READWRITE; | |
19013747 MCC |
12325 | demod->i2c = i2c; |
12326 | ||
12327 | result = drxj_open(demod); | |
12328 | if (result != 0) { | |
12329 | pr_err("DRX open failed! Aborting\n"); | |
12330 | goto error; | |
12331 | } | |
12332 | ||
19013747 MCC |
12333 | /* create dvb_frontend */ |
12334 | memcpy(&state->frontend.ops, &drx39xxj_ops, | |
12335 | sizeof(struct dvb_frontend_ops)); | |
12336 | ||
12337 | state->frontend.demodulator_priv = state; | |
d591590e MCC |
12338 | |
12339 | /* Initialize stats - needed for DVBv5 stats to work */ | |
12340 | p = &state->frontend.dtv_property_cache; | |
12341 | p->strength.len = 1; | |
12342 | p->pre_bit_count.len = 1; | |
12343 | p->pre_bit_error.len = 1; | |
12344 | p->post_bit_count.len = 1; | |
12345 | p->post_bit_error.len = 1; | |
12346 | p->block_count.len = 1; | |
12347 | p->block_error.len = 1; | |
12348 | p->cnr.len = 1; | |
12349 | ||
12350 | p->strength.stat[0].scale = FE_SCALE_RELATIVE; | |
12351 | p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
12352 | p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
12353 | p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
12354 | p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
12355 | p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
12356 | p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
12357 | p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | |
12358 | ||
19013747 MCC |
12359 | return &state->frontend; |
12360 | ||
12361 | error: | |
12362 | kfree(demod_ext_attr); | |
12363 | kfree(demod_comm_attr); | |
12364 | kfree(demod_addr); | |
12365 | kfree(demod); | |
12366 | kfree(state); | |
12367 | ||
12368 | return NULL; | |
12369 | } | |
12370 | EXPORT_SYMBOL(drx39xxj_attach); | |
12371 | ||
bd336e63 | 12372 | static const struct dvb_frontend_ops drx39xxj_ops = { |
19013747 MCC |
12373 | .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B }, |
12374 | .info = { | |
12375 | .name = "Micronas DRX39xxj family Frontend", | |
f1b1eabf MCC |
12376 | .frequency_min_hz = 51 * MHz, |
12377 | .frequency_max_hz = 858 * MHz, | |
12378 | .frequency_stepsize_hz = 62500, | |
19013747 MCC |
12379 | .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB |
12380 | }, | |
12381 | ||
12382 | .init = drx39xxj_init, | |
12383 | .i2c_gate_ctrl = drx39xxj_i2c_gate_ctrl, | |
12384 | .sleep = drx39xxj_sleep, | |
12385 | .set_frontend = drx39xxj_set_frontend, | |
12386 | .get_tune_settings = drx39xxj_get_tune_settings, | |
12387 | .read_status = drx39xxj_read_status, | |
12388 | .read_ber = drx39xxj_read_ber, | |
12389 | .read_signal_strength = drx39xxj_read_signal_strength, | |
12390 | .read_snr = drx39xxj_read_snr, | |
12391 | .read_ucblocks = drx39xxj_read_ucblocks, | |
12392 | .release = drx39xxj_release, | |
ea8f3c2c | 12393 | .set_lna = drx39xxj_set_lna, |
19013747 MCC |
12394 | }; |
12395 | ||
12396 | MODULE_DESCRIPTION("Micronas DRX39xxj Frontend"); | |
12397 | MODULE_AUTHOR("Devin Heitmueller"); | |
12398 | MODULE_LICENSE("GPL"); | |
12399 | MODULE_FIRMWARE(DRX39XX_MAIN_FIRMWARE); |