blob: 9482954fd453bbda66805a40a6b1aceab6adbfb9 [file] [log] [blame]
Devin Heitmuellerca3355a2010-07-04 18:42:11 -03001/*
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.
Devin Heitmuellerca3355a2010-07-04 18:42:11 -030029
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030030 DRXJ specific implementation of DRX driver
31 authors: Dragan Savic, Milos Nikolic, Mihajlo Katona, Tao Ding, Paul Janssen
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030032
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.
Devin Heitmueller38b2df92012-08-13 21:18:02 -030050*/
51
Devin Heitmueller38b2df92012-08-13 21:18:02 -030052/*-----------------------------------------------------------------------------
53INCLUDE FILES
54----------------------------------------------------------------------------*/
55
Mauro Carvalho Chehab935c6652014-01-17 11:36:17 -030056#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030057
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030058#include <linux/module.h>
59#include <linux/init.h>
60#include <linux/string.h>
61#include <linux/slab.h>
Gianluca Gennari90d9c3e2014-03-11 10:41:47 -030062#include <asm/div64.h>
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030063
64#include "dvb_frontend.h"
65#include "drx39xxj.h"
66
Devin Heitmueller38b2df92012-08-13 21:18:02 -030067#include "drxj.h"
68#include "drxj_map.h"
69
Devin Heitmueller38b2df92012-08-13 21:18:02 -030070/*============================================================================*/
71/*=== DEFINES ================================================================*/
72/*============================================================================*/
73
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030074#define DRX39XX_MAIN_FIRMWARE "dvb-fe-drxj-mc-1.0.8.fw"
75
Devin Heitmueller38b2df92012-08-13 21:18:02 -030076/**
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -030077* \brief Maximum u32 value.
Devin Heitmueller38b2df92012-08-13 21:18:02 -030078*/
79#ifndef MAX_U32
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -030080#define MAX_U32 ((u32) (0xFFFFFFFFL))
Devin Heitmueller38b2df92012-08-13 21:18:02 -030081#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
103/**** START DJCOMBO patches to DRXJ registermap constants *********************/
104/**** registermap 200706071303 from drxj **************************************/
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
191/**** END DJCOMBO patches to DRXJ registermap *********************************/
192
193#include "drx_driver_version.h"
194
Mauro Carvalho Chehab7ef66752014-01-16 11:08:15 -0300195/* #define DRX_DEBUG */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300196#ifdef DRX_DEBUG
197#include <stdio.h>
198#endif
199
200/*-----------------------------------------------------------------------------
201ENUMS
202----------------------------------------------------------------------------*/
203
204/*-----------------------------------------------------------------------------
205DEFINES
206----------------------------------------------------------------------------*/
207#ifndef DRXJ_WAKE_UP_KEY
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300208#define DRXJ_WAKE_UP_KEY (demod->my_i2c_dev_addr->i2c_addr)
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300209#endif
210
211/**
212* \def DRXJ_DEF_I2C_ADDR
213* \brief Default I2C addres of a demodulator instance.
214*/
215#define DRXJ_DEF_I2C_ADDR (0x52)
216
217/**
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
223/**
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
229/**
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300230* \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
237/**
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
245/**
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
251/**
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
263/**
264* \brief Min supported symbolrates.
265*/
266#ifndef DRXJ_QAM_SYMBOLRATE_MIN
267#define DRXJ_QAM_SYMBOLRATE_MIN (520000)
268#endif
269
270/**
271* \brief Max supported symbolrates.
272*/
273#ifndef DRXJ_QAM_SYMBOLRATE_MAX
274#define DRXJ_QAM_SYMBOLRATE_MAX (7233000)
275#endif
276
277/**
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
293/**
294* \def SCU status and results
295* \brief SCU
296*/
297#define DRX_SCU_READY 0
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300298#define DRXJ_MAX_WAITTIME 100 /* ms */
299#define FEC_RS_MEASUREMENT_PERIOD 12894 /* 1 sec */
300#define FEC_RS_MEASUREMENT_PRESCALE 1 /* n sec */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300301
302/**
303* \def DRX_AUD_MAX_DEVIATION
304* \brief Needed for calculation of prescale feature in AUD
305*/
306#ifndef DRXJ_AUD_MAX_FM_DEVIATION
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300307#define DRXJ_AUD_MAX_FM_DEVIATION 100 /* kHz */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300308#endif
309
310/**
311* \brief Needed for calculation of NICAM prescale feature in AUD
312*/
313#ifndef DRXJ_AUD_MAX_NICAM_PRESCALE
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300314#define DRXJ_AUD_MAX_NICAM_PRESCALE (9) /* dB */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300315#endif
316
317/**
318* \brief Needed for calculation of NICAM prescale feature in AUD
319*/
320#ifndef DRXJ_AUD_MAX_WAITTIME
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300321#define DRXJ_AUD_MAX_WAITTIME 250 /* ms */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300322#endif
323
324/* ATV config changed flags */
Mauro Carvalho Chehab7ef66752014-01-16 11:08:15 -0300325#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)
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300330
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
Mauro Carvalho Chehabb240eac2014-01-24 06:25:07 -0300335/*
336 * MICROCODE RELATED DEFINES
337 */
338
339/* Magic word for checking correct Endianess of microcode data */
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
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300369/* Pin safe mode macro */
370#define DRXJ_PIN_SAFE_MODE 0x0000
371/*============================================================================*/
372/*=== GLOBAL VARIABLEs =======================================================*/
373/*============================================================================*/
374/**
375*/
376
377/**
378* \brief Temporary register definitions.
379* (register definitions that are not yet available in register master)
380*/
381
382/******************************************************************************/
383/* Audio block 0x103 is write only. To avoid shadowing in driver accessing */
384/* RAM adresses directly. This must be READ ONLY to avoid problems. */
385/* Writing to the interface adresses is more than only writing the RAM */
386/* locations */
387/******************************************************************************/
388/**
389* \brief RAM location of MODUS registers
390*/
391#define AUD_DEM_RAM_MODUS_HI__A 0x10204A3
392#define AUD_DEM_RAM_MODUS_HI__M 0xF000
393
394#define AUD_DEM_RAM_MODUS_LO__A 0x10204A4
395#define AUD_DEM_RAM_MODUS_LO__M 0x0FFF
396
397/**
398* \brief RAM location of I2S config registers
399*/
400#define AUD_DEM_RAM_I2S_CONFIG1__A 0x10204B1
401#define AUD_DEM_RAM_I2S_CONFIG2__A 0x10204B2
402
403/**
404* \brief RAM location of DCO config registers
405*/
406#define AUD_DEM_RAM_DCO_B_HI__A 0x1020461
407#define AUD_DEM_RAM_DCO_B_LO__A 0x1020462
408#define AUD_DEM_RAM_DCO_A_HI__A 0x1020463
409#define AUD_DEM_RAM_DCO_A_LO__A 0x1020464
410
411/**
412* \brief RAM location of Threshold registers
413*/
414#define AUD_DEM_RAM_NICAM_THRSHLD__A 0x102045A
415#define AUD_DEM_RAM_A2_THRSHLD__A 0x10204BB
416#define AUD_DEM_RAM_BTSC_THRSHLD__A 0x10204A6
417
418/**
419* \brief RAM location of Carrier Threshold registers
420*/
421#define AUD_DEM_RAM_CM_A_THRSHLD__A 0x10204AF
422#define AUD_DEM_RAM_CM_B_THRSHLD__A 0x10204B0
423
424/**
425* \brief FM Matrix register fix
426*/
Mauro Carvalho Chehab7ef66752014-01-16 11:08:15 -0300427#ifdef AUD_DEM_WR_FM_MATRIX__A
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300428#undef AUD_DEM_WR_FM_MATRIX__A
429#endif
430#define AUD_DEM_WR_FM_MATRIX__A 0x105006F
431
432/*============================================================================*/
433/**
434* \brief Defines required for audio
435*/
436#define AUD_VOLUME_ZERO_DB 115
437#define AUD_VOLUME_DB_MIN -60
438#define AUD_VOLUME_DB_MAX 12
439#define AUD_CARRIER_STRENGTH_QP_0DB 0x4000
440#define AUD_CARRIER_STRENGTH_QP_0DB_LOG10T100 421
441#define AUD_MAX_AVC_REF_LEVEL 15
442#define AUD_I2S_FREQUENCY_MAX 48000UL
443#define AUD_I2S_FREQUENCY_MIN 12000UL
444#define AUD_RDS_ARRAY_SIZE 18
445
446/**
447* \brief Needed for calculation of prescale feature in AUD
448*/
449#ifndef DRX_AUD_MAX_FM_DEVIATION
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300450#define DRX_AUD_MAX_FM_DEVIATION (100) /* kHz */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300451#endif
452
453/**
454* \brief Needed for calculation of NICAM prescale feature in AUD
455*/
456#ifndef DRX_AUD_MAX_NICAM_PRESCALE
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300457#define DRX_AUD_MAX_NICAM_PRESCALE (9) /* dB */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300458#endif
459
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300460/*============================================================================*/
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
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300481/**
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*/
Mauro Carvalho Chehab7ef66752014-01-16 11:08:15 -0300487#define DRXJ_16TO8(x) ((u8) (((u16)x) & 0xFF)), \
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -0300488 ((u8)((((u16)x)>>8)&0xFF))
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300489/**
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*/
Mauro Carvalho Chehab7ef66752014-01-16 11:08:15 -0300494#define DRXJ_8TO16(x) ((u16) (x[0] | (x[1] << 8)))
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300495
496/*============================================================================*/
497/*=== MISC DEFINES ===========================================================*/
498/*============================================================================*/
499
500/*============================================================================*/
501/*=== HI COMMAND RELATED DEFINES =============================================*/
502/*============================================================================*/
503
504/**
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
Mauro Carvalho Chehabadc0e252014-01-16 15:56:51 -0300513#define DRXJ_ISATVSTD(std) ((std == DRX_STANDARD_PAL_SECAM_BG) || \
Mauro Carvalho Chehab7ef66752014-01-16 11:08:15 -0300514 (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) || \
Mauro Carvalho Chehab22892262014-01-16 11:28:52 -0300519 (std == DRX_STANDARD_FM))
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300520
Mauro Carvalho Chehabadc0e252014-01-16 15:56:51 -0300521#define DRXJ_ISQAMSTD(std) ((std == DRX_STANDARD_ITU_A) || \
Mauro Carvalho Chehab7ef66752014-01-16 11:08:15 -0300522 (std == DRX_STANDARD_ITU_B) || \
523 (std == DRX_STANDARD_ITU_C) || \
524 (std == DRX_STANDARD_ITU_D))
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300525
526/*-----------------------------------------------------------------------------
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300527GLOBAL VARIABLES
528----------------------------------------------------------------------------*/
529/*
530 * DRXJ DAP structures
531 */
532
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -0300533static int drxdap_fasi_read_block(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -0300534 u32 addr,
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -0300535 u16 datasize,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -0300536 u8 *data, u32 flags);
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300537
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300538
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300539static int drxj_dap_read_modify_write_reg16(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -0300540 u32 waddr,
541 u32 raddr,
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -0300542 u16 wdata, u16 *rdata);
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300543
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300544static int drxj_dap_read_reg16(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -0300545 u32 addr,
546 u16 *data, u32 flags);
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300547
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -0300548static int drxdap_fasi_read_reg32(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -0300549 u32 addr,
550 u32 *data, u32 flags);
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300551
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -0300552static int drxdap_fasi_write_block(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -0300553 u32 addr,
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -0300554 u16 datasize,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -0300555 u8 *data, u32 flags);
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300556
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300557static int drxj_dap_write_reg16(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -0300558 u32 addr,
559 u16 data, u32 flags);
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300560
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -0300561static int drxdap_fasi_write_reg32(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -0300562 u32 addr,
563 u32 data, u32 flags);
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300564
Mauro Carvalho Chehab01473142014-03-09 10:33:19 -0300565static struct drxj_data drxj_data_g = {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300566 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 */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300574 0, /* mfx A1/A2/A... */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300575
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300576 /* tuner settings */
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -0300577 false, /* tuner mirrors RF signal */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300578 /* standard/channel settings */
579 DRX_STANDARD_UNKNOWN, /* current standard */
580 DRX_CONSTELLATION_AUTO, /* constellation */
581 0, /* frequency in KHz */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300582 DRX_BANDWIDTH_UNKNOWN, /* curr_bandwidth */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300583 DRX_MIRROR_NO, /* mirror */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300584
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300585 /* signal quality information: */
586 /* default values taken from the QAM Programming guide */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300587 /* fec_bits_desired should not be less than 4000000 */
588 4000000, /* fec_bits_desired */
589 5, /* fec_vd_plen */
590 4, /* qam_vd_prescale */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300591 0xFFFF, /* qamVDPeriod */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300592 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 */
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -0300596 0, /* pkt_err_acc_start */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300597
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300598 /* HI configuration */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300599 0, /* hi_cfg_timing_div */
600 0, /* hi_cfg_bridge_delay */
601 0, /* hi_cfg_wake_up_key */
602 0, /* hi_cfg_ctrl */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300603 0, /* HICfgTimeout */
604 /* UIO configuartion */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300605 DRX_UIO_MODE_DISABLE, /* uio_sma_rx_mode */
606 DRX_UIO_MODE_DISABLE, /* uio_sma_tx_mode */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300607 DRX_UIO_MODE_DISABLE, /* uioASELMode */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300608 DRX_UIO_MODE_DISABLE, /* uio_irqn_mode */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300609 /* FS setting */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300610 0UL, /* iqm_fs_rate_ofs */
611 false, /* pos_image */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300612 /* RC setting */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300613 0UL, /* iqm_rc_rate_ofs */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300614 /* AUD information */
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -0300615/* false, * flagSetAUDdone */
616/* false, * detectedRDS */
617/* true, * flagASDRequest */
618/* false, * flagHDevClear */
619/* false, * flagHDevSet */
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -0300620/* (u16) 0xFFF, * rdsLastCount */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300621
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300622 /* ATV configuartion */
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},
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -0300656 false, /* flag: true=bypass */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300657 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 */
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -0300659 true, /* flag CVBS ouput enable */
660 false, /* flag SIF ouput enable */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300661 DRXJ_SIF_ATTENUATION_0DB, /* current SIF att setting */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300662 { /* qam_rf_agc_cfg */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300663 DRX_STANDARD_ITU_B, /* standard */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300664 DRX_AGC_CTRL_AUTO, /* ctrl_mode */
665 0, /* output_level */
666 0, /* min_output_level */
667 0xFFFF, /* max_output_level */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300668 0x0000, /* speed */
669 0x0000, /* top */
670 0x0000 /* c.o.c. */
671 },
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300672 { /* qam_if_agc_cfg */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300673 DRX_STANDARD_ITU_B, /* standard */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300674 DRX_AGC_CTRL_AUTO, /* ctrl_mode */
675 0, /* output_level */
676 0, /* min_output_level */
677 0xFFFF, /* max_output_level */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300678 0x0000, /* speed */
679 0x0000, /* top (don't care) */
680 0x0000 /* c.o.c. (don't care) */
681 },
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300682 { /* vsb_rf_agc_cfg */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300683 DRX_STANDARD_8VSB, /* standard */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300684 DRX_AGC_CTRL_AUTO, /* ctrl_mode */
685 0, /* output_level */
686 0, /* min_output_level */
687 0xFFFF, /* max_output_level */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300688 0x0000, /* speed */
689 0x0000, /* top (don't care) */
690 0x0000 /* c.o.c. (don't care) */
691 },
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300692 { /* vsb_if_agc_cfg */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300693 DRX_STANDARD_8VSB, /* standard */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300694 DRX_AGC_CTRL_AUTO, /* ctrl_mode */
695 0, /* output_level */
696 0, /* min_output_level */
697 0xFFFF, /* max_output_level */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300698 0x0000, /* speed */
699 0x0000, /* top (don't care) */
700 0x0000 /* c.o.c. (don't care) */
701 },
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300702 0, /* qam_pga_cfg */
703 0, /* vsb_pga_cfg */
704 { /* qam_pre_saw_cfg */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300705 DRX_STANDARD_ITU_B, /* standard */
706 0, /* reference */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300707 false /* use_pre_saw */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300708 },
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300709 { /* vsb_pre_saw_cfg */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300710 DRX_STANDARD_8VSB, /* standard */
711 0, /* reference */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300712 false /* use_pre_saw */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300713 },
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300714
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300715 /* Version information */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300716#ifndef _CH_
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300717 {
718 "01234567890", /* human readable version microcode */
719 "01234567890" /* human readable version device specific code */
720 },
721 {
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -0300722 { /* struct drx_version for microcode */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300723 DRX_MODULE_UNKNOWN,
724 (char *)(NULL),
725 0,
726 0,
727 0,
728 (char *)(NULL)
729 },
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -0300730 { /* struct drx_version for device specific code */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300731 DRX_MODULE_UNKNOWN,
732 (char *)(NULL),
733 0,
734 0,
735 0,
736 (char *)(NULL)
737 }
738 },
739 {
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -0300740 { /* struct drx_version_list for microcode */
741 (struct drx_version *) (NULL),
742 (struct drx_version_list *) (NULL)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300743 },
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -0300744 { /* struct drx_version_list for device specific code */
745 (struct drx_version *) (NULL),
746 (struct drx_version_list *) (NULL)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300747 }
748 },
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300749#endif
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300750 false, /* smart_ant_inverted */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300751 /* Tracking filter setting for OOB */
752 {
753 12000,
754 9300,
755 6600,
756 5280,
757 3700,
758 3000,
759 2000,
760 0},
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300761 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 */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300767
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300768 /* Pre SAW & Agc configuration for ATV */
769 {
770 DRX_STANDARD_NTSC, /* standard */
771 7, /* reference */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300772 true /* use_pre_saw */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300773 },
774 { /* ATV RF-AGC */
775 DRX_STANDARD_NTSC, /* standard */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300776 DRX_AGC_CTRL_AUTO, /* ctrl_mode */
777 0, /* output_level */
778 0, /* min_output_level (d.c.) */
779 0, /* max_output_level (d.c.) */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300780 3, /* speed */
781 9500, /* top */
782 4000 /* cut-off current */
783 },
784 { /* ATV IF-AGC */
785 DRX_STANDARD_NTSC, /* standard */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300786 DRX_AGC_CTRL_AUTO, /* ctrl_mode */
787 0, /* output_level */
788 0, /* min_output_level (d.c.) */
789 0, /* max_output_level (d.c.) */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300790 3, /* speed */
791 2400, /* top */
792 0 /* c.o.c. (d.c.) */
793 },
794 140, /* ATV PGA config */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300795 0, /* curr_symbol_rate */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300796
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300797 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 */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300802
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300803 4, /* oob_pre_saw */
804 DRXJ_OOB_LO_POW_MINUS10DB, /* oob_lo_pow */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300805 {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300806 false /* aud_data, only first member */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300807 },
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300808};
809
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300810/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300811* \var drxj_default_addr_g
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300812* \brief Default I2C address and device identifier.
813*/
Mauro Carvalho Chehab01473142014-03-09 10:33:19 -0300814static struct i2c_device_addr drxj_default_addr_g = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300815 DRXJ_DEF_I2C_ADDR, /* i2c address */
816 DRXJ_DEF_DEMOD_DEV_ID /* device id */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300817};
818
819/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300820* \var drxj_default_comm_attr_g
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300821* \brief Default common attributes of a drxj demodulator instance.
822*/
Mauro Carvalho Chehab01473142014-03-09 10:33:19 -0300823static struct drx_common_attr drxj_default_comm_attr_g = {
Mauro Carvalho Chehabb48293d2014-01-18 11:13:02 -0300824 NULL, /* ucode file */
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -0300825 true, /* ucode verify switch */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300826 {0}, /* version record */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300827
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300828 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 */
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -0300832 false, /* If true mirror frequency spectrum */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300833 {
834 /* MPEG output configuration */
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -0300835 true, /* If true, enable MPEG ouput */
836 false, /* If true, insert RS byte */
Mauro Carvalho Chehaba5e7a672014-03-03 06:13:17 -0300837 false, /* If true, parallel out otherwise serial */
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -0300838 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
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300844 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 },
850 /* Initilisations below can be ommited, they require no user input and
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -0300851 are initialy 0, NULL or false. The compiler will initialize them to these
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300852 values when ommited. */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300853 false, /* is_opened */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300854
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300855 /* SCAN */
856 NULL, /* no scan params yet */
857 0, /* current scan index */
858 0, /* next scan frequency */
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -0300859 false, /* scan ready flag */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300860 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 */
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -0300866 false,
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300867
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300868 /* Power management */
869 DRX_POWER_UP,
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300870
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300871 /* 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 */
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -0300875 false, /* Rf Agc Polarity */
876 false, /* If Agc Polarity */
877 false, /* tuner slow mode */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300878
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300879 { /* current channel (all 0) */
880 0UL /* channel.frequency */
881 },
882 DRX_STANDARD_UNKNOWN, /* current standard */
883 DRX_STANDARD_UNKNOWN, /* previous standard */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300884 DRX_STANDARD_UNKNOWN, /* di_cache_standard */
885 false, /* use_bootloader */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300886 0UL, /* capabilities */
887 0 /* mfx */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300888};
889
890/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300891* \var drxj_default_demod_g
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300892* \brief Default drxj demodulator instance.
893*/
Mauro Carvalho Chehab01473142014-03-09 10:33:19 -0300894static struct drx_demod_instance drxj_default_demod_g = {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300895 &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 */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300898};
899
900/**
901* \brief Default audio data structure for DRK demodulator instance.
902*
903* This structure is DRXK specific.
904*
905*/
Fengguang Wuc4cfb292014-03-09 09:08:30 -0300906static struct drx_aud_data drxj_default_aud_data_g = {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300907 false, /* audio_is_active */
908 DRX_AUD_STANDARD_AUTO, /* audio_standard */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300909
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300910 /* i2sdata */
911 {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300912 false, /* output_enable */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300913 48000, /* frequency */
914 DRX_I2S_MODE_MASTER, /* mode */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300915 DRX_I2S_WORDLENGTH_32, /* word_length */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300916 DRX_I2S_POLARITY_RIGHT, /* polarity */
917 DRX_I2S_FORMAT_WS_WITH_DATA /* format */
918 },
919 /* volume */
920 {
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -0300921 true, /* mute; */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300922 0, /* volume */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300923 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 */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300929 },
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300930 DRX_AUD_AUTO_SOUND_SELECT_ON_CHANGE_ON, /* auto_sound */
931 /* ass_thresholds */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300932 {
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 },
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300953
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300954 },
955 /* mixer */
956 {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300957 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 */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300960 },
961 DRX_AUD_DEVIATION_NORMAL, /* deviation */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300962 DRX_AUD_AVSYNC_OFF, /* av_sync */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300963
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300964 /* prescale */
965 {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300966 DRX_AUD_MAX_FM_DEVIATION, /* fm_deviation */
967 DRX_AUD_MAX_NICAM_PRESCALE /* nicam_gain */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -0300968 },
969 DRX_AUD_FM_DEEMPH_75US, /* deemph */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300970 DRX_BTSC_STEREO, /* btsc_detect */
971 0, /* rds_data_counter */
972 false /* rds_data_present */
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300973};
974
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300975/*-----------------------------------------------------------------------------
976STRUCTURES
977----------------------------------------------------------------------------*/
Mauro Carvalho Chehab60d36032014-01-17 07:00:31 -0300978struct drxjeq_stat {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -0300979 u16 eq_mse;
980 u8 eq_mode;
981 u8 eq_ctrl;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -0300982 u8 eq_stat;
983};
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300984
985/* HI command */
Mauro Carvalho Chehab60d36032014-01-17 07:00:31 -0300986struct drxj_hi_cmd {
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -0300987 u16 cmd;
988 u16 param1;
989 u16 param2;
990 u16 param3;
991 u16 param4;
992 u16 param5;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -0300993 u16 param6;
994};
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300995
Devin Heitmueller38b2df92012-08-13 21:18:02 -0300996/*============================================================================*/
997/*=== MICROCODE RELATED STRUCTURES ===========================================*/
998/*============================================================================*/
999
Mauro Carvalho Chehabb240eac2014-01-24 06:25:07 -03001000/**
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 */
Mauro Carvalho Chehab60d36032014-01-17 07:00:31 -03001009struct drxu_code_block_hdr {
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03001010 u32 addr;
1011 u16 size;
Mauro Carvalho Chehabb240eac2014-01-24 06:25:07 -03001012 u16 flags;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03001013 u16 CRC;
1014};
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001015
1016/*-----------------------------------------------------------------------------
1017FUNCTIONS
1018----------------------------------------------------------------------------*/
1019/* Some prototypes */
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03001020static int
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001021hi_command(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab60d36032014-01-17 07:00:31 -03001022 const struct drxj_hi_cmd *cmd, u16 *result);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001023
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03001024static int
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03001025ctrl_lock_status(struct drx_demod_instance *demod, enum drx_lock_status *lock_stat);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001026
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03001027static int
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03001028ctrl_power_mode(struct drx_demod_instance *demod, enum drx_power_mode *mode);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001029
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03001030static int power_down_aud(struct drx_demod_instance *demod);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001031
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03001032static int
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03001033ctrl_set_cfg_pre_saw(struct drx_demod_instance *demod, struct drxj_cfg_pre_saw *pre_saw);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001034
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03001035static int
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03001036ctrl_set_cfg_afe_gain(struct drx_demod_instance *demod, struct drxj_cfg_afe_gain *afe_gain);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001037
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001038/*============================================================================*/
1039/*============================================================================*/
1040/*== HELPER FUNCTIONS ==*/
1041/*============================================================================*/
1042/*============================================================================*/
1043
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001044
1045/*============================================================================*/
1046
1047/*
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001048* \fn u32 frac28(u32 N, u32 D)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001049* \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
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001056* frac28 performs an unsigned 28/28 bits division to 32-bit fixed point
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001057* 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*/
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001067static u32 frac28(u32 N, u32 D)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001068{
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001069 int i = 0;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03001070 u32 Q1 = 0;
1071 u32 R0 = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001072
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001073 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 */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001076
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001077 /* 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++;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001085
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001086 return Q1;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001087}
1088
1089/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001090* \fn u32 log1_times100( u32 x)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001091* \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
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001105static u32 log1_times100(u32 x)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001106{
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03001107 static const u8 scale = 15;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001108 static const u8 index_width = 5;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001109 /*
1110 log2lut[n] = (1<<scale) * 200 * log2( 1.0 + ( (1.0/(1<<INDEXWIDTH)) * n ))
1111 0 <= n < ((1<<INDEXWIDTH)+1)
1112 */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001113
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03001114 static const u32 log2lut[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001115 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 };
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001149
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03001150 u8 i = 0;
1151 u32 y = 0;
1152 u32 d = 0;
1153 u32 k = 0;
1154 u32 r = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001155
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001156 if (x == 0)
Mauro Carvalho Chehab64e49cb2014-01-17 06:28:28 -03001157 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001158
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001159 /* Scale x (normalize) */
1160 /* computing y in log(x/y) = log(x) - log(y) */
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03001161 if ((x & (((u32) (-1)) << (scale + 1))) == 0) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001162 for (k = scale; k > 0; k--) {
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03001163 if (x & (((u32) 1) << scale))
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001164 break;
1165 x <<= 1;
1166 }
1167 } else {
1168 for (k = scale; k < 31; k++) {
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03001169 if ((x & (((u32) (-1)) << (scale + 1))) == 0)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001170 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 */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001177
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001178 /* correction for divison: log(x) = log(x/y)+log(y) */
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03001179 y = k * ((((u32) 1) << scale) * 200);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001180
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001181 /* remove integer part */
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03001182 x &= ((((u32) 1) << scale) - 1);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001183 /* get index */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001184 i = (u8) (x >> (scale - index_width));
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001185 /* compute delta (x-a) */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001186 d = x & ((((u32) 1) << (scale - index_width)) - 1);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001187 /* compute log, multiplication ( d* (.. )) must be within range ! */
1188 y += log2lut[i] +
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001189 ((d * (log2lut[i + 1] - log2lut[i])) >> (scale - index_width));
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001190 /* Conver to log10() */
1191 y /= 108853; /* (log2(10) << scale) */
1192 r = (y >> 1);
1193 /* rounding */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03001194 if (y & ((u32)1))
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001195 r++;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001196
Mauro Carvalho Chehab64e49cb2014-01-17 06:28:28 -03001197 return r;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001198
1199}
1200
1201/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001202* \fn u32 frac_times1e6( u16 N, u32 D)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001203* \brief Compute: (N/D) * 1000000.
1204* \param N nominator 16-bits.
1205* \param D denominator 32-bits.
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03001206* \return u32
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001207* \retval ((N/D) * 1000000), 32 bits
1208*
1209* No check on D=0!
1210*/
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001211static u32 frac_times1e6(u32 N, u32 D)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001212{
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03001213 u32 remainder = 0;
1214 u32 frac = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001215
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001216 /*
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 */
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03001223 frac = (((u32) N) * (1000000 >> 4)) / D;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001224 frac <<= 4;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03001225 remainder = (((u32) N) * (1000000 >> 4)) % D;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001226 remainder <<= 4;
1227 frac += remainder / D;
1228 remainder = remainder % D;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03001229 if ((remainder * 2) > D)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001230 frac++;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001231
Mauro Carvalho Chehab64e49cb2014-01-17 06:28:28 -03001232 return frac;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001233}
1234
1235/*============================================================================*/
1236
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001237
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001238/**
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*/
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03001243static const u16 nicam_presc_table_val[43] = {
1244 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4,
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001245 5, 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16,
1246 18, 20, 23, 25, 28, 32, 36, 40, 45,
1247 51, 57, 64, 71, 80, 90, 101, 113, 127
1248};
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001249
1250/*============================================================================*/
1251/*== END HELPER FUNCTIONS ==*/
1252/*============================================================================*/
1253
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001254/*============================================================================*/
1255/*============================================================================*/
1256/*== DRXJ DAP FUNCTIONS ==*/
1257/*============================================================================*/
1258/*============================================================================*/
1259
1260/*
1261 This layer takes care of some device specific register access protocols:
1262 -conversion to short address format
1263 -access to audio block
1264 This layer is placed between the drx_dap_fasi and the rest of the drxj
1265 specific implementation. This layer can use address map knowledge whereas
1266 dap_fasi may not use memory map knowledge.
1267
1268 * For audio currently only 16 bits read and write register access is
1269 supported. More is not needed. RMW and 32 or 8 bit access on audio
1270 registers will have undefined behaviour. Flags (RMW, CRC reset, broadcast
1271 single/multi master) will be ignored.
1272
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001273 TODO: check ignoring single/multimaster is ok for AUD access ?
1274*/
1275
Mauro Carvalho Chehab22892262014-01-16 11:28:52 -03001276#define DRXJ_ISAUDWRITE(addr) (((((addr)>>16)&1) == 1) ? true : false)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001277#define DRXJ_DAP_AUDTRIF_TIMEOUT 80 /* millisec */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001278/*============================================================================*/
1279
1280/**
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03001281* \fn bool is_handled_by_aud_tr_if( u32 addr )
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001282* \brief Check if this address is handled by the audio token ring interface.
1283* \param addr
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -03001284* \return bool
1285* \retval true Yes, handled by audio token ring interface
1286* \retval false No, not handled by audio token ring interface
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001287*
1288*/
1289static
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03001290bool is_handled_by_aud_tr_if(u32 addr)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001291{
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -03001292 bool retval = false;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001293
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001294 if ((DRXDAP_FASI_ADDR2BLOCK(addr) == 4) &&
1295 (DRXDAP_FASI_ADDR2BANK(addr) > 1) &&
1296 (DRXDAP_FASI_ADDR2BANK(addr) < 6)) {
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -03001297 retval = true;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001298 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001299
Mauro Carvalho Chehab64e49cb2014-01-17 06:28:28 -03001300 return retval;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001301}
1302
1303/*============================================================================*/
1304
Mauro Carvalho Chehab73b3fc32014-01-27 02:14:14 -03001305int drxbsp_i2c_write_read(struct i2c_device_addr *w_dev_addr,
1306 u16 w_count,
1307 u8 *wData,
1308 struct i2c_device_addr *r_dev_addr,
1309 u16 r_count, u8 *r_data)
1310{
1311 struct drx39xxj_state *state;
1312 struct i2c_msg msg[2];
1313 unsigned int num_msgs;
1314
1315 if (w_dev_addr == NULL) {
1316 /* Read only */
1317 state = r_dev_addr->user_data;
1318 msg[0].addr = r_dev_addr->i2c_addr >> 1;
1319 msg[0].flags = I2C_M_RD;
1320 msg[0].buf = r_data;
1321 msg[0].len = r_count;
1322 num_msgs = 1;
1323 } else if (r_dev_addr == NULL) {
1324 /* Write only */
1325 state = w_dev_addr->user_data;
1326 msg[0].addr = w_dev_addr->i2c_addr >> 1;
1327 msg[0].flags = 0;
1328 msg[0].buf = wData;
1329 msg[0].len = w_count;
1330 num_msgs = 1;
1331 } else {
1332 /* Both write and read */
1333 state = w_dev_addr->user_data;
1334 msg[0].addr = w_dev_addr->i2c_addr >> 1;
1335 msg[0].flags = 0;
1336 msg[0].buf = wData;
1337 msg[0].len = w_count;
1338 msg[1].addr = r_dev_addr->i2c_addr >> 1;
1339 msg[1].flags = I2C_M_RD;
1340 msg[1].buf = r_data;
1341 msg[1].len = r_count;
1342 num_msgs = 2;
1343 }
1344
1345 if (state->i2c == NULL) {
1346 pr_err("i2c was zero, aborting\n");
1347 return 0;
1348 }
1349 if (i2c_transfer(state->i2c, msg, num_msgs) != num_msgs) {
1350 pr_warn("drx3933: I2C write/read failed\n");
1351 return -EREMOTEIO;
1352 }
1353
Mauro Carvalho Chehab73b3fc32014-01-27 02:14:14 -03001354#ifdef DJH_DEBUG
Shuah Khan1ad77b52014-02-28 18:23:02 -03001355 if (w_dev_addr == NULL || r_dev_addr == NULL)
1356 return 0;
Mauro Carvalho Chehab73b3fc32014-01-27 02:14:14 -03001357
Shuah Khan1ad77b52014-02-28 18:23:02 -03001358 state = w_dev_addr->user_data;
1359
1360 if (state->i2c == NULL)
1361 return 0;
1362
1363 msg[0].addr = w_dev_addr->i2c_addr;
1364 msg[0].flags = 0;
1365 msg[0].buf = wData;
1366 msg[0].len = w_count;
1367 msg[1].addr = r_dev_addr->i2c_addr;
1368 msg[1].flags = I2C_M_RD;
1369 msg[1].buf = r_data;
1370 msg[1].len = r_count;
1371 num_msgs = 2;
Mauro Carvalho Chehab73b3fc32014-01-27 02:14:14 -03001372
Shuah Khan6c955b82014-02-28 18:23:00 -03001373 pr_debug("drx3933 i2c operation addr=%x i2c=%p, wc=%x rc=%x\n",
Mauro Carvalho Chehab73b3fc32014-01-27 02:14:14 -03001374 w_dev_addr->i2c_addr, state->i2c, w_count, r_count);
1375
1376 if (i2c_transfer(state->i2c, msg, 2) != 2) {
1377 pr_warn("drx3933: I2C write/read failed\n");
1378 return -EREMOTEIO;
1379 }
1380#endif
1381 return 0;
1382}
1383
1384/*============================================================================*/
1385
1386/******************************
1387*
1388* int drxdap_fasi_read_block (
1389* struct i2c_device_addr *dev_addr, -- address of I2C device
1390* u32 addr, -- address of chip register/memory
1391* u16 datasize, -- number of bytes to read
1392* u8 *data, -- data to receive
1393* u32 flags) -- special device flags
1394*
1395* Read block data from chip address. Because the chip is word oriented,
1396* the number of bytes to read must be even.
1397*
1398* Make sure that the buffer to receive the data is large enough.
1399*
1400* Although this function expects an even number of bytes, it is still byte
1401* oriented, and the data read back is NOT translated to the endianness of
1402* the target platform.
1403*
1404* Output:
1405* - 0 if reading was successful
1406* in that case: data read is in *data.
1407* - -EIO if anything went wrong
1408*
1409******************************/
1410
1411static int drxdap_fasi_read_block(struct i2c_device_addr *dev_addr,
1412 u32 addr,
1413 u16 datasize,
1414 u8 *data, u32 flags)
1415{
1416 u8 buf[4];
1417 u16 bufx;
1418 int rc;
1419 u16 overhead_size = 0;
1420
1421 /* Check parameters ******************************************************* */
1422 if (dev_addr == NULL)
1423 return -EINVAL;
1424
1425 overhead_size = (IS_I2C_10BIT(dev_addr->i2c_addr) ? 2 : 1) +
1426 (DRXDAP_FASI_LONG_FORMAT(addr) ? 4 : 2);
1427
1428 if ((DRXDAP_FASI_OFFSET_TOO_LARGE(addr)) ||
1429 ((!(DRXDAPFASI_LONG_ADDR_ALLOWED)) &&
1430 DRXDAP_FASI_LONG_FORMAT(addr)) ||
1431 (overhead_size > (DRXDAP_MAX_WCHUNKSIZE)) ||
1432 ((datasize != 0) && (data == NULL)) || ((datasize & 1) == 1)) {
1433 return -EINVAL;
1434 }
1435
1436 /* ReadModifyWrite & mode flag bits are not allowed */
1437 flags &= (~DRXDAP_FASI_RMW & ~DRXDAP_FASI_MODEFLAGS);
1438#if DRXDAP_SINGLE_MASTER
1439 flags |= DRXDAP_FASI_SINGLE_MASTER;
1440#endif
1441
1442 /* Read block from I2C **************************************************** */
1443 do {
1444 u16 todo = (datasize < DRXDAP_MAX_RCHUNKSIZE ?
1445 datasize : DRXDAP_MAX_RCHUNKSIZE);
1446
1447 bufx = 0;
1448
1449 addr &= ~DRXDAP_FASI_FLAGS;
1450 addr |= flags;
1451
1452#if ((DRXDAPFASI_LONG_ADDR_ALLOWED == 1) && (DRXDAPFASI_SHORT_ADDR_ALLOWED == 1))
1453 /* short format address preferred but long format otherwise */
1454 if (DRXDAP_FASI_LONG_FORMAT(addr)) {
1455#endif
1456#if (DRXDAPFASI_LONG_ADDR_ALLOWED == 1)
1457 buf[bufx++] = (u8) (((addr << 1) & 0xFF) | 0x01);
1458 buf[bufx++] = (u8) ((addr >> 16) & 0xFF);
1459 buf[bufx++] = (u8) ((addr >> 24) & 0xFF);
1460 buf[bufx++] = (u8) ((addr >> 7) & 0xFF);
1461#endif
1462#if ((DRXDAPFASI_LONG_ADDR_ALLOWED == 1) && (DRXDAPFASI_SHORT_ADDR_ALLOWED == 1))
1463 } else {
1464#endif
1465#if (DRXDAPFASI_SHORT_ADDR_ALLOWED == 1)
1466 buf[bufx++] = (u8) ((addr << 1) & 0xFF);
1467 buf[bufx++] =
1468 (u8) (((addr >> 16) & 0x0F) |
1469 ((addr >> 18) & 0xF0));
1470#endif
1471#if ((DRXDAPFASI_LONG_ADDR_ALLOWED == 1) && (DRXDAPFASI_SHORT_ADDR_ALLOWED == 1))
1472 }
1473#endif
1474
1475#if DRXDAP_SINGLE_MASTER
1476 /*
1477 * In single master mode, split the read and write actions.
1478 * No special action is needed for write chunks here.
1479 */
Mauro Carvalho Chehabdb5657c2014-03-09 09:32:58 -03001480 rc = drxbsp_i2c_write_read(dev_addr, bufx, buf,
1481 NULL, 0, NULL);
Mauro Carvalho Chehab73b3fc32014-01-27 02:14:14 -03001482 if (rc == 0)
Mauro Carvalho Chehabdb5657c2014-03-09 09:32:58 -03001483 rc = drxbsp_i2c_write_read(NULL, 0, NULL, dev_addr, todo, data);
Mauro Carvalho Chehab73b3fc32014-01-27 02:14:14 -03001484#else
1485 /* In multi master mode, do everything in one RW action */
1486 rc = drxbsp_i2c_write_read(dev_addr, bufx, buf, dev_addr, todo,
1487 data);
1488#endif
1489 data += todo;
1490 addr += (todo >> 1);
1491 datasize -= todo;
1492 } while (datasize && rc == 0);
1493
1494 return rc;
1495}
1496
1497
1498/******************************
1499*
1500* int drxdap_fasi_read_reg16 (
1501* struct i2c_device_addr *dev_addr, -- address of I2C device
1502* u32 addr, -- address of chip register/memory
1503* u16 *data, -- data to receive
1504* u32 flags) -- special device flags
1505*
1506* Read one 16-bit register or memory location. The data received back is
1507* converted back to the target platform's endianness.
1508*
1509* Output:
1510* - 0 if reading was successful
1511* in that case: read data is at *data
1512* - -EIO if anything went wrong
1513*
1514******************************/
1515
1516static int drxdap_fasi_read_reg16(struct i2c_device_addr *dev_addr,
1517 u32 addr,
1518 u16 *data, u32 flags)
1519{
1520 u8 buf[sizeof(*data)];
1521 int rc;
1522
1523 if (!data)
1524 return -EINVAL;
1525
1526 rc = drxdap_fasi_read_block(dev_addr, addr, sizeof(*data), buf, flags);
1527 *data = buf[0] + (((u16) buf[1]) << 8);
1528 return rc;
1529}
1530
1531/******************************
1532*
1533* int drxdap_fasi_read_reg32 (
1534* struct i2c_device_addr *dev_addr, -- address of I2C device
1535* u32 addr, -- address of chip register/memory
1536* u32 *data, -- data to receive
1537* u32 flags) -- special device flags
1538*
1539* Read one 32-bit register or memory location. The data received back is
1540* converted back to the target platform's endianness.
1541*
1542* Output:
1543* - 0 if reading was successful
1544* in that case: read data is at *data
1545* - -EIO if anything went wrong
1546*
1547******************************/
1548
1549static int drxdap_fasi_read_reg32(struct i2c_device_addr *dev_addr,
1550 u32 addr,
1551 u32 *data, u32 flags)
1552{
1553 u8 buf[sizeof(*data)];
1554 int rc;
1555
1556 if (!data)
1557 return -EINVAL;
1558
1559 rc = drxdap_fasi_read_block(dev_addr, addr, sizeof(*data), buf, flags);
1560 *data = (((u32) buf[0]) << 0) +
1561 (((u32) buf[1]) << 8) +
1562 (((u32) buf[2]) << 16) + (((u32) buf[3]) << 24);
1563 return rc;
1564}
1565
1566/******************************
1567*
1568* int drxdap_fasi_write_block (
1569* struct i2c_device_addr *dev_addr, -- address of I2C device
1570* u32 addr, -- address of chip register/memory
1571* u16 datasize, -- number of bytes to read
1572* u8 *data, -- data to receive
1573* u32 flags) -- special device flags
1574*
1575* Write block data to chip address. Because the chip is word oriented,
1576* the number of bytes to write must be even.
1577*
1578* Although this function expects an even number of bytes, it is still byte
1579* oriented, and the data being written is NOT translated from the endianness of
1580* the target platform.
1581*
1582* Output:
1583* - 0 if writing was successful
1584* - -EIO if anything went wrong
1585*
1586******************************/
1587
1588static int drxdap_fasi_write_block(struct i2c_device_addr *dev_addr,
1589 u32 addr,
1590 u16 datasize,
1591 u8 *data, u32 flags)
1592{
1593 u8 buf[DRXDAP_MAX_WCHUNKSIZE];
1594 int st = -EIO;
1595 int first_err = 0;
1596 u16 overhead_size = 0;
1597 u16 block_size = 0;
1598
1599 /* Check parameters ******************************************************* */
1600 if (dev_addr == NULL)
1601 return -EINVAL;
1602
1603 overhead_size = (IS_I2C_10BIT(dev_addr->i2c_addr) ? 2 : 1) +
1604 (DRXDAP_FASI_LONG_FORMAT(addr) ? 4 : 2);
1605
1606 if ((DRXDAP_FASI_OFFSET_TOO_LARGE(addr)) ||
1607 ((!(DRXDAPFASI_LONG_ADDR_ALLOWED)) &&
1608 DRXDAP_FASI_LONG_FORMAT(addr)) ||
1609 (overhead_size > (DRXDAP_MAX_WCHUNKSIZE)) ||
1610 ((datasize != 0) && (data == NULL)) || ((datasize & 1) == 1))
1611 return -EINVAL;
1612
1613 flags &= DRXDAP_FASI_FLAGS;
1614 flags &= ~DRXDAP_FASI_MODEFLAGS;
1615#if DRXDAP_SINGLE_MASTER
1616 flags |= DRXDAP_FASI_SINGLE_MASTER;
1617#endif
1618
1619 /* Write block to I2C ***************************************************** */
1620 block_size = ((DRXDAP_MAX_WCHUNKSIZE) - overhead_size) & ~1;
1621 do {
1622 u16 todo = 0;
1623 u16 bufx = 0;
1624
1625 /* Buffer device address */
1626 addr &= ~DRXDAP_FASI_FLAGS;
1627 addr |= flags;
1628#if (((DRXDAPFASI_LONG_ADDR_ALLOWED) == 1) && ((DRXDAPFASI_SHORT_ADDR_ALLOWED) == 1))
1629 /* short format address preferred but long format otherwise */
1630 if (DRXDAP_FASI_LONG_FORMAT(addr)) {
1631#endif
1632#if ((DRXDAPFASI_LONG_ADDR_ALLOWED) == 1)
1633 buf[bufx++] = (u8) (((addr << 1) & 0xFF) | 0x01);
1634 buf[bufx++] = (u8) ((addr >> 16) & 0xFF);
1635 buf[bufx++] = (u8) ((addr >> 24) & 0xFF);
1636 buf[bufx++] = (u8) ((addr >> 7) & 0xFF);
1637#endif
1638#if (((DRXDAPFASI_LONG_ADDR_ALLOWED) == 1) && ((DRXDAPFASI_SHORT_ADDR_ALLOWED) == 1))
1639 } else {
1640#endif
1641#if ((DRXDAPFASI_SHORT_ADDR_ALLOWED) == 1)
1642 buf[bufx++] = (u8) ((addr << 1) & 0xFF);
1643 buf[bufx++] =
1644 (u8) (((addr >> 16) & 0x0F) |
1645 ((addr >> 18) & 0xF0));
1646#endif
1647#if (((DRXDAPFASI_LONG_ADDR_ALLOWED) == 1) && ((DRXDAPFASI_SHORT_ADDR_ALLOWED) == 1))
1648 }
1649#endif
1650
1651 /*
1652 In single master mode block_size can be 0. In such a case this I2C
1653 sequense will be visible: (1) write address {i2c addr,
1654 4 bytes chip address} (2) write data {i2c addr, 4 bytes data }
1655 (3) write address (4) write data etc...
1656 Addres must be rewriten because HI is reset after data transport and
1657 expects an address.
1658 */
1659 todo = (block_size < datasize ? block_size : datasize);
1660 if (todo == 0) {
1661 u16 overhead_size_i2c_addr = 0;
1662 u16 data_block_size = 0;
1663
1664 overhead_size_i2c_addr =
1665 (IS_I2C_10BIT(dev_addr->i2c_addr) ? 2 : 1);
1666 data_block_size =
1667 (DRXDAP_MAX_WCHUNKSIZE - overhead_size_i2c_addr) & ~1;
1668
1669 /* write device address */
1670 st = drxbsp_i2c_write_read(dev_addr,
1671 (u16) (bufx),
1672 buf,
1673 (struct i2c_device_addr *)(NULL),
1674 0, (u8 *)(NULL));
1675
1676 if ((st != 0) && (first_err == 0)) {
1677 /* at the end, return the first error encountered */
1678 first_err = st;
1679 }
1680 bufx = 0;
1681 todo =
1682 (data_block_size <
1683 datasize ? data_block_size : datasize);
1684 }
1685 memcpy(&buf[bufx], data, todo);
1686 /* write (address if can do and) data */
1687 st = drxbsp_i2c_write_read(dev_addr,
1688 (u16) (bufx + todo),
1689 buf,
1690 (struct i2c_device_addr *)(NULL),
1691 0, (u8 *)(NULL));
1692
1693 if ((st != 0) && (first_err == 0)) {
1694 /* at the end, return the first error encountered */
1695 first_err = st;
1696 }
1697 datasize -= todo;
1698 data += todo;
1699 addr += (todo >> 1);
1700 } while (datasize);
1701
1702 return first_err;
1703}
1704
1705/******************************
1706*
1707* int drxdap_fasi_write_reg16 (
1708* struct i2c_device_addr *dev_addr, -- address of I2C device
1709* u32 addr, -- address of chip register/memory
1710* u16 data, -- data to send
1711* u32 flags) -- special device flags
1712*
1713* Write one 16-bit register or memory location. The data being written is
1714* converted from the target platform's endianness to little endian.
1715*
1716* Output:
1717* - 0 if writing was successful
1718* - -EIO if anything went wrong
1719*
1720******************************/
1721
1722static int drxdap_fasi_write_reg16(struct i2c_device_addr *dev_addr,
1723 u32 addr,
1724 u16 data, u32 flags)
1725{
1726 u8 buf[sizeof(data)];
1727
1728 buf[0] = (u8) ((data >> 0) & 0xFF);
1729 buf[1] = (u8) ((data >> 8) & 0xFF);
1730
1731 return drxdap_fasi_write_block(dev_addr, addr, sizeof(data), buf, flags);
1732}
1733
1734/******************************
1735*
1736* int drxdap_fasi_read_modify_write_reg16 (
1737* struct i2c_device_addr *dev_addr, -- address of I2C device
1738* u32 waddr, -- address of chip register/memory
1739* u32 raddr, -- chip address to read back from
1740* u16 wdata, -- data to send
1741* u16 *rdata) -- data to receive back
1742*
1743* Write 16-bit data, then read back the original contents of that location.
1744* Requires long addressing format to be allowed.
1745*
1746* Before sending data, the data is converted to little endian. The
1747* data received back is converted back to the target platform's endianness.
1748*
1749* WARNING: This function is only guaranteed to work if there is one
1750* master on the I2C bus.
1751*
1752* Output:
1753* - 0 if reading was successful
1754* in that case: read back data is at *rdata
1755* - -EIO if anything went wrong
1756*
1757******************************/
1758
1759static int drxdap_fasi_read_modify_write_reg16(struct i2c_device_addr *dev_addr,
1760 u32 waddr,
1761 u32 raddr,
1762 u16 wdata, u16 *rdata)
1763{
1764 int rc = -EIO;
1765
1766#if (DRXDAPFASI_LONG_ADDR_ALLOWED == 1)
1767 if (rdata == NULL)
1768 return -EINVAL;
1769
1770 rc = drxdap_fasi_write_reg16(dev_addr, waddr, wdata, DRXDAP_FASI_RMW);
1771 if (rc == 0)
1772 rc = drxdap_fasi_read_reg16(dev_addr, raddr, rdata, 0);
1773#endif
1774
1775 return rc;
1776}
1777
1778/******************************
1779*
1780* int drxdap_fasi_write_reg32 (
1781* struct i2c_device_addr *dev_addr, -- address of I2C device
1782* u32 addr, -- address of chip register/memory
1783* u32 data, -- data to send
1784* u32 flags) -- special device flags
1785*
1786* Write one 32-bit register or memory location. The data being written is
1787* converted from the target platform's endianness to little endian.
1788*
1789* Output:
1790* - 0 if writing was successful
1791* - -EIO if anything went wrong
1792*
1793******************************/
1794
1795static int drxdap_fasi_write_reg32(struct i2c_device_addr *dev_addr,
1796 u32 addr,
1797 u32 data, u32 flags)
1798{
1799 u8 buf[sizeof(data)];
1800
1801 buf[0] = (u8) ((data >> 0) & 0xFF);
1802 buf[1] = (u8) ((data >> 8) & 0xFF);
1803 buf[2] = (u8) ((data >> 16) & 0xFF);
1804 buf[3] = (u8) ((data >> 24) & 0xFF);
1805
1806 return drxdap_fasi_write_block(dev_addr, addr, sizeof(data), buf, flags);
1807}
1808
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001809/*============================================================================*/
1810
1811/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001812* \fn int drxj_dap_rm_write_reg16short
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001813* \brief Read modify write 16 bits audio register using short format only.
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001814* \param dev_addr
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001815* \param waddr Address to write to
1816* \param raddr Address to read from (usually SIO_HI_RA_RAM_S0_RMWBUF__A)
1817* \param wdata Data to write
1818* \param rdata Buffer for data to read
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03001819* \return int
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03001820* \retval 0 Succes
1821* \retval -EIO Timeout, I2C error, illegal bank
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001822*
1823* 16 bits register read modify write access using short addressing format only.
1824* Requires knowledge of the registermap, thus device dependent.
1825* Using DAP FASI directly to avoid endless recursion of RMWs to audio registers.
1826*
1827*/
1828
1829/* TODO correct define should be #if ( DRXDAPFASI_SHORT_ADDR_ALLOWED==1 )
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001830 See comments drxj_dap_read_modify_write_reg16 */
Mauro Carvalho Chehab7ef66752014-01-16 11:08:15 -03001831#if (DRXDAPFASI_LONG_ADDR_ALLOWED == 0)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001832static int drxj_dap_rm_write_reg16short(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03001833 u32 waddr,
1834 u32 raddr,
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03001835 u16 wdata, u16 *rdata)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001836{
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03001837 int rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001838
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03001839 if (rdata == NULL)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03001840 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001841
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001842 /* Set RMW flag */
Mauro Carvalho Chehab80bff4b2014-01-27 02:24:25 -03001843 rc = drxdap_fasi_write_reg16(dev_addr,
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001844 SIO_HI_RA_RAM_S0_FLG_ACC__A,
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001845 SIO_HI_RA_RAM_S0_FLG_ACC_S0_RWM__M,
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001846 0x0000);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03001847 if (rc == 0) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001848 /* Write new data: triggers RMW */
Mauro Carvalho Chehab80bff4b2014-01-27 02:24:25 -03001849 rc = drxdap_fasi_write_reg16(dev_addr, waddr, wdata,
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001850 0x0000);
1851 }
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03001852 if (rc == 0) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001853 /* Read old data */
Mauro Carvalho Chehab80bff4b2014-01-27 02:24:25 -03001854 rc = drxdap_fasi_read_reg16(dev_addr, raddr, rdata,
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001855 0x0000);
1856 }
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03001857 if (rc == 0) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001858 /* Reset RMW flag */
Mauro Carvalho Chehab80bff4b2014-01-27 02:24:25 -03001859 rc = drxdap_fasi_write_reg16(dev_addr,
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001860 SIO_HI_RA_RAM_S0_FLG_ACC__A,
1861 0, 0x0000);
1862 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001863
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001864 return rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001865}
1866#endif
1867
1868/*============================================================================*/
1869
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001870static int drxj_dap_read_modify_write_reg16(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03001871 u32 waddr,
1872 u32 raddr,
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03001873 u16 wdata, u16 *rdata)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001874{
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001875 /* TODO: correct short/long addressing format decision,
1876 now long format has higher prio then short because short also
1877 needs virt bnks (not impl yet) for certain audio registers */
Mauro Carvalho Chehab7ef66752014-01-16 11:08:15 -03001878#if (DRXDAPFASI_LONG_ADDR_ALLOWED == 1)
Mauro Carvalho Chehab80bff4b2014-01-27 02:24:25 -03001879 return drxdap_fasi_read_modify_write_reg16(dev_addr,
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001880 waddr,
1881 raddr, wdata, rdata);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001882#else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001883 return drxj_dap_rm_write_reg16short(dev_addr, waddr, raddr, wdata, rdata);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001884#endif
1885}
1886
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001887
1888/*============================================================================*/
1889
1890/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001891* \fn int drxj_dap_read_aud_reg16
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001892* \brief Read 16 bits audio register
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001893* \param dev_addr
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001894* \param addr
1895* \param data
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03001896* \return int
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03001897* \retval 0 Succes
1898* \retval -EIO Timeout, I2C error, illegal bank
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001899*
1900* 16 bits register read access via audio token ring interface.
1901*
1902*/
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001903static int drxj_dap_read_aud_reg16(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03001904 u32 addr, u16 *data)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001905{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001906 u32 start_timer = 0;
1907 u32 current_timer = 0;
1908 u32 delta_timer = 0;
1909 u16 tr_status = 0;
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03001910 int stat = -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001911
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001912 /* No read possible for bank 3, return with error */
1913 if (DRXDAP_FASI_ADDR2BANK(addr) == 3) {
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03001914 stat = -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001915 } else {
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03001916 const u32 write_bit = ((dr_xaddr_t) 1) << 16;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001917
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001918 /* Force reset write bit */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001919 addr &= (~write_bit);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001920
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001921 /* Set up read */
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03001922 start_timer = jiffies_to_msecs(jiffies);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001923 do {
1924 /* RMW to aud TR IF until request is granted or timeout */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001925 stat = drxj_dap_read_modify_write_reg16(dev_addr,
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001926 addr,
1927 SIO_HI_RA_RAM_S0_RMWBUF__A,
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001928 0x0000, &tr_status);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001929
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03001930 if (stat != 0)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001931 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001932
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03001933 current_timer = jiffies_to_msecs(jiffies);
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001934 delta_timer = current_timer - start_timer;
1935 if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) {
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03001936 stat = -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001937 break;
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03001938 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001939
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001940 } while (((tr_status & AUD_TOP_TR_CTR_FIFO_LOCK__M) ==
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001941 AUD_TOP_TR_CTR_FIFO_LOCK_LOCKED) ||
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001942 ((tr_status & AUD_TOP_TR_CTR_FIFO_FULL__M) ==
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001943 AUD_TOP_TR_CTR_FIFO_FULL_FULL));
1944 } /* if ( DRXDAP_FASI_ADDR2BANK(addr)!=3 ) */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001945
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001946 /* Wait for read ready status or timeout */
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03001947 if (stat == 0) {
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03001948 start_timer = jiffies_to_msecs(jiffies);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001949
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001950 while ((tr_status & AUD_TOP_TR_CTR_FIFO_RD_RDY__M) !=
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001951 AUD_TOP_TR_CTR_FIFO_RD_RDY_READY) {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001952 stat = drxj_dap_read_reg16(dev_addr,
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001953 AUD_TOP_TR_CTR__A,
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001954 &tr_status, 0x0000);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03001955 if (stat != 0)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001956 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001957
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03001958 current_timer = jiffies_to_msecs(jiffies);
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001959 delta_timer = current_timer - start_timer;
1960 if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) {
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03001961 stat = -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001962 break;
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03001963 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001964 } /* while ( ... ) */
1965 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001966
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001967 /* Read value */
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03001968 if (stat == 0)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001969 stat = drxj_dap_read_modify_write_reg16(dev_addr,
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001970 AUD_TOP_TR_RD_REG__A,
1971 SIO_HI_RA_RAM_S0_RMWBUF__A,
1972 0x0000, data);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001973 return stat;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001974}
1975
1976/*============================================================================*/
1977
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001978static int drxj_dap_read_reg16(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03001979 u32 addr,
1980 u16 *data, u32 flags)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001981{
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03001982 int stat = -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001983
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001984 /* Check param */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03001985 if ((dev_addr == NULL) || (data == NULL))
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03001986 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001987
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03001988 if (is_handled_by_aud_tr_if(addr))
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001989 stat = drxj_dap_read_aud_reg16(dev_addr, addr, data);
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03001990 else
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03001991 stat = drxdap_fasi_read_reg16(dev_addr, addr, data, flags);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001992
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03001993 return stat;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001994}
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001995/*============================================================================*/
1996
1997/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03001998* \fn int drxj_dap_write_aud_reg16
Devin Heitmueller38b2df92012-08-13 21:18:02 -03001999* \brief Write 16 bits audio register
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002000* \param dev_addr
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002001* \param addr
2002* \param data
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03002003* \return int
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002004* \retval 0 Succes
2005* \retval -EIO Timeout, I2C error, illegal bank
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002006*
2007* 16 bits register write access via audio token ring interface.
2008*
2009*/
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002010static int drxj_dap_write_aud_reg16(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002011 u32 addr, u16 data)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002012{
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002013 int stat = -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002014
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002015 /* No write possible for bank 2, return with error */
2016 if (DRXDAP_FASI_ADDR2BANK(addr) == 2) {
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002017 stat = -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002018 } else {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002019 u32 start_timer = 0;
2020 u32 current_timer = 0;
2021 u32 delta_timer = 0;
2022 u16 tr_status = 0;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002023 const u32 write_bit = ((dr_xaddr_t) 1) << 16;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002024
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002025 /* Force write bit */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002026 addr |= write_bit;
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03002027 start_timer = jiffies_to_msecs(jiffies);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002028 do {
2029 /* RMW to aud TR IF until request is granted or timeout */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002030 stat = drxj_dap_read_modify_write_reg16(dev_addr,
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002031 addr,
2032 SIO_HI_RA_RAM_S0_RMWBUF__A,
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002033 data, &tr_status);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002034 if (stat != 0)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002035 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002036
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03002037 current_timer = jiffies_to_msecs(jiffies);
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002038 delta_timer = current_timer - start_timer;
2039 if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) {
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002040 stat = -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002041 break;
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03002042 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002043
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002044 } while (((tr_status & AUD_TOP_TR_CTR_FIFO_LOCK__M) ==
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002045 AUD_TOP_TR_CTR_FIFO_LOCK_LOCKED) ||
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002046 ((tr_status & AUD_TOP_TR_CTR_FIFO_FULL__M) ==
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002047 AUD_TOP_TR_CTR_FIFO_FULL_FULL));
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002048
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002049 } /* if ( DRXDAP_FASI_ADDR2BANK(addr)!=2 ) */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002050
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002051 return stat;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002052}
2053
2054/*============================================================================*/
2055
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002056static int drxj_dap_write_reg16(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002057 u32 addr,
2058 u16 data, u32 flags)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002059{
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002060 int stat = -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002061
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002062 /* Check param */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002063 if (dev_addr == NULL)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002064 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002065
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002066 if (is_handled_by_aud_tr_if(addr))
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002067 stat = drxj_dap_write_aud_reg16(dev_addr, addr, data);
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002068 else
Mauro Carvalho Chehab80bff4b2014-01-27 02:24:25 -03002069 stat = drxdap_fasi_write_reg16(dev_addr,
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002070 addr, data, flags);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002071
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002072 return stat;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002073}
2074
2075/*============================================================================*/
2076
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002077/* Free data ram in SIO HI */
2078#define SIO_HI_RA_RAM_USR_BEGIN__A 0x420040
2079#define SIO_HI_RA_RAM_USR_END__A 0x420060
2080
2081#define DRXJ_HI_ATOMIC_BUF_START (SIO_HI_RA_RAM_USR_BEGIN__A)
2082#define DRXJ_HI_ATOMIC_BUF_END (SIO_HI_RA_RAM_USR_BEGIN__A + 7)
2083#define DRXJ_HI_ATOMIC_READ SIO_HI_RA_RAM_PAR_3_ACP_RW_READ
2084#define DRXJ_HI_ATOMIC_WRITE SIO_HI_RA_RAM_PAR_3_ACP_RW_WRITE
2085
2086/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002087* \fn int drxj_dap_atomic_read_write_block()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002088* \brief Basic access routine for atomic read or write access
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002089* \param dev_addr pointer to i2c dev address
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002090* \param addr destination/source address
2091* \param datasize size of data buffer in bytes
2092* \param data pointer to data buffer
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03002093* \return int
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002094* \retval 0 Succes
2095* \retval -EIO Timeout, I2C error, illegal bank
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002096*
2097*/
2098static
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002099int drxj_dap_atomic_read_write_block(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002100 u32 addr,
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03002101 u16 datasize,
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002102 u8 *data, bool read_flag)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002103{
Mauro Carvalho Chehab60d36032014-01-17 07:00:31 -03002104 struct drxj_hi_cmd hi_cmd;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002105 int rc;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03002106 u16 word;
2107 u16 dummy = 0;
2108 u16 i = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002109
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002110 /* Parameter check */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002111 if (!data || !dev_addr || ((datasize % 2)) || ((datasize / 2) > 8))
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002112 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002113
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002114 /* Set up HI parameters to read or write n bytes */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002115 hi_cmd.cmd = SIO_HI_RA_RAM_CMD_ATOMIC_COPY;
2116 hi_cmd.param1 =
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03002117 (u16) ((DRXDAP_FASI_ADDR2BLOCK(DRXJ_HI_ATOMIC_BUF_START) << 6) +
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002118 DRXDAP_FASI_ADDR2BANK(DRXJ_HI_ATOMIC_BUF_START));
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002119 hi_cmd.param2 =
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03002120 (u16) DRXDAP_FASI_ADDR2OFFSET(DRXJ_HI_ATOMIC_BUF_START);
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002121 hi_cmd.param3 = (u16) ((datasize / 2) - 1);
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002122 if (!read_flag)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002123 hi_cmd.param3 |= DRXJ_HI_ATOMIC_WRITE;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002124 else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002125 hi_cmd.param3 |= DRXJ_HI_ATOMIC_READ;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002126 hi_cmd.param4 = (u16) ((DRXDAP_FASI_ADDR2BLOCK(addr) << 6) +
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002127 DRXDAP_FASI_ADDR2BANK(addr));
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002128 hi_cmd.param5 = (u16) DRXDAP_FASI_ADDR2OFFSET(addr);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002129
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03002130 if (!read_flag) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002131 /* write data to buffer */
2132 for (i = 0; i < (datasize / 2); i++) {
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002133
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03002134 word = ((u16) data[2 * i]);
2135 word += (((u16) data[(2 * i) + 1]) << 8);
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002136 drxj_dap_write_reg16(dev_addr,
Mauro Carvalho Chehab22892262014-01-16 11:28:52 -03002137 (DRXJ_HI_ATOMIC_BUF_START + i),
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002138 word, 0);
2139 }
2140 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002141
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002142 rc = hi_command(dev_addr, &hi_cmd, &dummy);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002143 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002144 pr_err("error %d\n", rc);
2145 goto rw_error;
2146 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002147
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03002148 if (read_flag) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002149 /* read data from buffer */
2150 for (i = 0; i < (datasize / 2); i++) {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002151 drxj_dap_read_reg16(dev_addr,
Mauro Carvalho Chehab22892262014-01-16 11:28:52 -03002152 (DRXJ_HI_ATOMIC_BUF_START + i),
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002153 &word, 0);
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03002154 data[2 * i] = (u8) (word & 0xFF);
2155 data[(2 * i) + 1] = (u8) (word >> 8);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002156 }
2157 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002158
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002159 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002160
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002161rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002162 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002163
2164}
2165
2166/*============================================================================*/
2167
2168/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002169* \fn int drxj_dap_atomic_read_reg32()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002170* \brief Atomic read of 32 bits words
2171*/
2172static
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002173int drxj_dap_atomic_read_reg32(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002174 u32 addr,
2175 u32 *data, u32 flags)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002176{
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03002177 u8 buf[sizeof(*data)];
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002178 int rc = -EIO;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03002179 u32 word = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002180
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002181 if (!data)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002182 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002183
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002184 rc = drxj_dap_atomic_read_write_block(dev_addr, addr,
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002185 sizeof(*data), buf, true);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002186
Mauro Carvalho Chehabb1d0a592014-01-16 16:34:03 -03002187 if (rc < 0)
2188 return 0;
2189
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03002190 word = (u32) buf[3];
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002191 word <<= 8;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03002192 word |= (u32) buf[2];
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002193 word <<= 8;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03002194 word |= (u32) buf[1];
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002195 word <<= 8;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03002196 word |= (u32) buf[0];
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002197
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002198 *data = word;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002199
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002200 return rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002201}
2202
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002203/*============================================================================*/
2204
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002205/*============================================================================*/
2206/*== END DRXJ DAP FUNCTIONS ==*/
2207/*============================================================================*/
2208
2209/*============================================================================*/
2210/*============================================================================*/
2211/*== HOST INTERFACE FUNCTIONS ==*/
2212/*============================================================================*/
2213/*============================================================================*/
2214
2215/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002216* \fn int hi_cfg_command()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002217* \brief Configure HI with settings stored in the demod structure.
2218* \param demod Demodulator.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03002219* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002220*
2221* This routine was created because to much orthogonal settings have
2222* been put into one HI API function (configure). Especially the I2C bridge
2223* enable/disable should not need re-configuration of the HI.
2224*
2225*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002226static int hi_cfg_command(const struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002227{
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03002228 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
Mauro Carvalho Chehab60d36032014-01-17 07:00:31 -03002229 struct drxj_hi_cmd hi_cmd;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03002230 u16 result = 0;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002231 int rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002232
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03002233 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002234
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002235 hi_cmd.cmd = SIO_HI_RA_RAM_CMD_CONFIG;
2236 hi_cmd.param1 = SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY;
2237 hi_cmd.param2 = ext_attr->hi_cfg_timing_div;
2238 hi_cmd.param3 = ext_attr->hi_cfg_bridge_delay;
2239 hi_cmd.param4 = ext_attr->hi_cfg_wake_up_key;
2240 hi_cmd.param5 = ext_attr->hi_cfg_ctrl;
2241 hi_cmd.param6 = ext_attr->hi_cfg_transmit;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002242
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002243 rc = hi_command(demod->my_i2c_dev_addr, &hi_cmd, &result);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002244 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002245 pr_err("error %d\n", rc);
2246 goto rw_error;
2247 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002248
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002249 /* Reset power down flag (set one call only) */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002250 ext_attr->hi_cfg_ctrl &= (~(SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ));
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002251
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002252 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002253
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002254rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002255 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002256}
2257
2258/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002259* \fn int hi_command()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002260* \brief Configure HI with settings stored in the demod structure.
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002261* \param dev_addr I2C address.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002262* \param cmd HI command.
2263* \param result HI command result.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03002264* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002265*
2266* Sends command to HI
2267*
2268*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03002269static int
Mauro Carvalho Chehab60d36032014-01-17 07:00:31 -03002270hi_command(struct i2c_device_addr *dev_addr, const struct drxj_hi_cmd *cmd, u16 *result)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002271{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002272 u16 wait_cmd = 0;
2273 u16 nr_retries = 0;
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -03002274 bool powerdown_cmd = false;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002275 int rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002276
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002277 /* Write parameters */
2278 switch (cmd->cmd) {
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002279
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002280 case SIO_HI_RA_RAM_CMD_CONFIG:
2281 case SIO_HI_RA_RAM_CMD_ATOMIC_COPY:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002282 rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_6__A, cmd->param6, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002283 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002284 pr_err("error %d\n", rc);
2285 goto rw_error;
2286 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002287 rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_5__A, cmd->param5, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002288 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002289 pr_err("error %d\n", rc);
2290 goto rw_error;
2291 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002292 rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_4__A, cmd->param4, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002293 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002294 pr_err("error %d\n", rc);
2295 goto rw_error;
2296 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002297 rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_3__A, cmd->param3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002298 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002299 pr_err("error %d\n", rc);
2300 goto rw_error;
2301 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002302 /* fallthrough */
2303 case SIO_HI_RA_RAM_CMD_BRDCTRL:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002304 rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_2__A, cmd->param2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002305 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002306 pr_err("error %d\n", rc);
2307 goto rw_error;
2308 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002309 rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_1__A, cmd->param1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002310 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002311 pr_err("error %d\n", rc);
2312 goto rw_error;
2313 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002314 /* fallthrough */
2315 case SIO_HI_RA_RAM_CMD_NULL:
2316 /* No parameters */
2317 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002318
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002319 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002320 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002321 break;
2322 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002323
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002324 /* Write command */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002325 rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_CMD__A, cmd->cmd, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002326 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002327 pr_err("error %d\n", rc);
2328 goto rw_error;
2329 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002330
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002331 if ((cmd->cmd) == SIO_HI_RA_RAM_CMD_RESET)
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03002332 msleep(1);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002333
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002334 /* Detect power down to ommit reading result */
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -03002335 powerdown_cmd = (bool) ((cmd->cmd == SIO_HI_RA_RAM_CMD_CONFIG) &&
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002336 (((cmd->
2337 param5) & SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M)
2338 == SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ));
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03002339 if (!powerdown_cmd) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002340 /* Wait until command rdy */
2341 do {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002342 nr_retries++;
2343 if (nr_retries > DRXJ_MAX_RETRIES) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002344 pr_err("timeout\n");
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002345 goto rw_error;
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03002346 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002347
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002348 rc = drxj_dap_read_reg16(dev_addr, SIO_HI_RA_RAM_CMD__A, &wait_cmd, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002349 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002350 pr_err("error %d\n", rc);
2351 goto rw_error;
2352 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002353 } while (wait_cmd != 0);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002354
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002355 /* Read result */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002356 rc = drxj_dap_read_reg16(dev_addr, SIO_HI_RA_RAM_RES__A, result, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002357 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002358 pr_err("error %d\n", rc);
2359 goto rw_error;
2360 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002361
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002362 }
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -03002363 /* if ( powerdown_cmd == true ) */
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002364 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002365rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002366 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002367}
2368
2369/**
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002370* \fn int init_hi( const struct drx_demod_instance *demod )
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002371* \brief Initialise and configurate HI.
2372* \param demod pointer to demod data.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03002373* \return int Return status.
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002374* \retval 0 Success.
2375* \retval -EIO Failure.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002376*
2377* Needs to know Psys (System Clock period) and Posc (Osc Clock period)
2378* Need to store configuration in driver because of the way I2C
2379* bridging is controlled.
2380*
2381*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002382static int init_hi(const struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002383{
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03002384 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002385 struct drx_common_attr *common_attr = (struct drx_common_attr *) (NULL);
Mauro Carvalho Chehab22892262014-01-16 11:28:52 -03002386 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002387 int rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002388
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03002389 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002390 common_attr = (struct drx_common_attr *) demod->my_common_attr;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002391 dev_addr = demod->my_i2c_dev_addr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002392
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002393 /* PATCH for bug 5003, HI ucode v3.1.0 */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002394 rc = drxj_dap_write_reg16(dev_addr, 0x4301D7, 0x801, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002395 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002396 pr_err("error %d\n", rc);
2397 goto rw_error;
2398 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002399
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002400 /* Timing div, 250ns/Psys */
2401 /* Timing div, = ( delay (nano seconds) * sysclk (kHz) )/ 1000 */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002402 ext_attr->hi_cfg_timing_div =
2403 (u16) ((common_attr->sys_clock_freq / 1000) * HI_I2C_DELAY) / 1000;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002404 /* Clipping */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002405 if ((ext_attr->hi_cfg_timing_div) > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002406 ext_attr->hi_cfg_timing_div = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002407 /* Bridge delay, uses oscilator clock */
2408 /* Delay = ( delay (nano seconds) * oscclk (kHz) )/ 1000 */
2409 /* SDA brdige delay */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002410 ext_attr->hi_cfg_bridge_delay =
2411 (u16) ((common_attr->osc_clock_freq / 1000) * HI_I2C_BRIDGE_DELAY) /
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002412 1000;
2413 /* Clipping */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002414 if ((ext_attr->hi_cfg_bridge_delay) > SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002415 ext_attr->hi_cfg_bridge_delay = SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002416 /* SCL bridge delay, same as SDA for now */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002417 ext_attr->hi_cfg_bridge_delay += ((ext_attr->hi_cfg_bridge_delay) <<
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002418 SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B);
2419 /* Wakeup key, setting the read flag (as suggest in the documentation) does
2420 not always result into a working solution (barebones worked VI2C failed).
2421 Not setting the bit works in all cases . */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002422 ext_attr->hi_cfg_wake_up_key = DRXJ_WAKE_UP_KEY;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002423 /* port/bridge/power down ctrl */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002424 ext_attr->hi_cfg_ctrl = (SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002425 /* transit mode time out delay and watch dog divider */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002426 ext_attr->hi_cfg_transmit = SIO_HI_RA_RAM_PAR_6__PRE;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002427
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002428 rc = hi_cfg_command(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002429 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002430 pr_err("error %d\n", rc);
2431 goto rw_error;
2432 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002433
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002434 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002435
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002436rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002437 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002438}
2439
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002440/*============================================================================*/
2441/*== END HOST INTERFACE FUNCTIONS ==*/
2442/*============================================================================*/
2443
2444/*============================================================================*/
2445/*============================================================================*/
2446/*== AUXILIARY FUNCTIONS ==*/
2447/*============================================================================*/
2448/*============================================================================*/
2449
2450/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002451* \fn int get_device_capabilities()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002452* \brief Get and store device capabilities.
2453* \param demod Pointer to demodulator instance.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03002454* \return int.
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002455* \return 0 Success
2456* \retval -EIO Failure
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002457*
2458* Depending on pulldowns on MDx pins the following internals are set:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002459* * common_attr->osc_clock_freq
2460* * ext_attr->has_lna
2461* * ext_attr->has_ntsc
2462* * ext_attr->has_btsc
2463* * ext_attr->has_oob
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002464*
2465*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002466static int get_device_capabilities(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002467{
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002468 struct drx_common_attr *common_attr = (struct drx_common_attr *) (NULL);
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03002469 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
Mauro Carvalho Chehab22892262014-01-16 11:28:52 -03002470 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002471 u16 sio_pdr_ohw_cfg = 0;
2472 u32 sio_top_jtagid_lo = 0;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03002473 u16 bid = 0;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002474 int rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002475
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002476 common_attr = (struct drx_common_attr *) demod->my_common_attr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03002477 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002478 dev_addr = demod->my_i2c_dev_addr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002479
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002480 rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002481 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002482 pr_err("error %d\n", rc);
2483 goto rw_error;
2484 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002485 rc = drxj_dap_read_reg16(dev_addr, SIO_PDR_OHW_CFG__A, &sio_pdr_ohw_cfg, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002486 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002487 pr_err("error %d\n", rc);
2488 goto rw_error;
2489 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002490 rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY__PRE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002491 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002492 pr_err("error %d\n", rc);
2493 goto rw_error;
2494 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002495
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002496 switch ((sio_pdr_ohw_cfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002497 case 0:
2498 /* ignore (bypass ?) */
2499 break;
2500 case 1:
2501 /* 27 MHz */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002502 common_attr->osc_clock_freq = 27000;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002503 break;
2504 case 2:
2505 /* 20.25 MHz */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002506 common_attr->osc_clock_freq = 20250;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002507 break;
2508 case 3:
2509 /* 4 MHz */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002510 common_attr->osc_clock_freq = 4000;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002511 break;
2512 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002513 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002514 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002515
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002516 /*
2517 Determine device capabilities
2518 Based on pinning v47
2519 */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002520 rc = drxdap_fasi_read_reg32(dev_addr, SIO_TOP_JTAGID_LO__A, &sio_top_jtagid_lo, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002521 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002522 pr_err("error %d\n", rc);
2523 goto rw_error;
2524 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002525 ext_attr->mfx = (u8) ((sio_top_jtagid_lo >> 29) & 0xF);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002526
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002527 switch ((sio_top_jtagid_lo >> 12) & 0xFF) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002528 case 0x31:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002529 rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002530 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002531 pr_err("error %d\n", rc);
2532 goto rw_error;
2533 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002534 rc = drxj_dap_read_reg16(dev_addr, SIO_PDR_UIO_IN_HI__A, &bid, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002535 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002536 pr_err("error %d\n", rc);
2537 goto rw_error;
2538 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002539 bid = (bid >> 10) & 0xf;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002540 rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY__PRE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002541 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002542 pr_err("error %d\n", rc);
2543 goto rw_error;
2544 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002545
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002546 ext_attr->has_lna = true;
2547 ext_attr->has_ntsc = false;
2548 ext_attr->has_btsc = false;
2549 ext_attr->has_oob = false;
2550 ext_attr->has_smatx = true;
2551 ext_attr->has_smarx = false;
2552 ext_attr->has_gpio = false;
2553 ext_attr->has_irqn = false;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002554 break;
2555 case 0x33:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002556 ext_attr->has_lna = false;
2557 ext_attr->has_ntsc = false;
2558 ext_attr->has_btsc = false;
2559 ext_attr->has_oob = false;
2560 ext_attr->has_smatx = true;
2561 ext_attr->has_smarx = false;
2562 ext_attr->has_gpio = false;
2563 ext_attr->has_irqn = false;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002564 break;
2565 case 0x45:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002566 ext_attr->has_lna = true;
2567 ext_attr->has_ntsc = true;
2568 ext_attr->has_btsc = false;
2569 ext_attr->has_oob = false;
2570 ext_attr->has_smatx = true;
2571 ext_attr->has_smarx = true;
2572 ext_attr->has_gpio = true;
2573 ext_attr->has_irqn = false;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002574 break;
2575 case 0x46:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002576 ext_attr->has_lna = false;
2577 ext_attr->has_ntsc = true;
2578 ext_attr->has_btsc = false;
2579 ext_attr->has_oob = false;
2580 ext_attr->has_smatx = true;
2581 ext_attr->has_smarx = true;
2582 ext_attr->has_gpio = true;
2583 ext_attr->has_irqn = false;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002584 break;
2585 case 0x41:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002586 ext_attr->has_lna = true;
2587 ext_attr->has_ntsc = true;
2588 ext_attr->has_btsc = true;
2589 ext_attr->has_oob = false;
2590 ext_attr->has_smatx = true;
2591 ext_attr->has_smarx = true;
2592 ext_attr->has_gpio = true;
2593 ext_attr->has_irqn = false;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002594 break;
2595 case 0x43:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002596 ext_attr->has_lna = false;
2597 ext_attr->has_ntsc = true;
2598 ext_attr->has_btsc = true;
2599 ext_attr->has_oob = false;
2600 ext_attr->has_smatx = true;
2601 ext_attr->has_smarx = true;
2602 ext_attr->has_gpio = true;
2603 ext_attr->has_irqn = false;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002604 break;
2605 case 0x32:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002606 ext_attr->has_lna = true;
2607 ext_attr->has_ntsc = false;
2608 ext_attr->has_btsc = false;
2609 ext_attr->has_oob = true;
2610 ext_attr->has_smatx = true;
2611 ext_attr->has_smarx = true;
2612 ext_attr->has_gpio = true;
2613 ext_attr->has_irqn = true;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002614 break;
2615 case 0x34:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002616 ext_attr->has_lna = false;
2617 ext_attr->has_ntsc = true;
2618 ext_attr->has_btsc = true;
2619 ext_attr->has_oob = true;
2620 ext_attr->has_smatx = true;
2621 ext_attr->has_smarx = true;
2622 ext_attr->has_gpio = true;
2623 ext_attr->has_irqn = true;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002624 break;
2625 case 0x42:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002626 ext_attr->has_lna = true;
2627 ext_attr->has_ntsc = true;
2628 ext_attr->has_btsc = true;
2629 ext_attr->has_oob = true;
2630 ext_attr->has_smatx = true;
2631 ext_attr->has_smarx = true;
2632 ext_attr->has_gpio = true;
2633 ext_attr->has_irqn = true;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002634 break;
2635 case 0x44:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002636 ext_attr->has_lna = false;
2637 ext_attr->has_ntsc = true;
2638 ext_attr->has_btsc = true;
2639 ext_attr->has_oob = true;
2640 ext_attr->has_smatx = true;
2641 ext_attr->has_smarx = true;
2642 ext_attr->has_gpio = true;
2643 ext_attr->has_irqn = true;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002644 break;
2645 default:
2646 /* Unknown device variant */
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002647 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002648 break;
2649 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002650
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002651 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002652rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002653 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002654}
2655
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002656/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002657* \fn int power_up_device()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002658* \brief Power up device.
2659* \param demod Pointer to demodulator instance.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03002660* \return int.
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002661* \return 0 Success
2662* \retval -EIO Failure, I2C or max retries reached
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002663*
2664*/
2665
2666#ifndef DRXJ_MAX_RETRIES_POWERUP
2667#define DRXJ_MAX_RETRIES_POWERUP 10
2668#endif
2669
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002670static int power_up_device(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002671{
Mauro Carvalho Chehab22892262014-01-16 11:28:52 -03002672 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03002673 u8 data = 0;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002674 u16 retry_count = 0;
2675 struct i2c_device_addr wake_up_addr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002676
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002677 dev_addr = demod->my_i2c_dev_addr;
2678 wake_up_addr.i2c_addr = DRXJ_WAKE_UP_KEY;
2679 wake_up_addr.i2c_dev_id = dev_addr->i2c_dev_id;
2680 wake_up_addr.user_data = dev_addr->user_data;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002681 /*
2682 * I2C access may fail in this case: no ack
2683 * dummy write must be used to wake uop device, dummy read must be used to
2684 * reset HI state machine (avoiding actual writes)
2685 */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002686 do {
2687 data = 0;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002688 drxbsp_i2c_write_read(&wake_up_addr, 1, &data,
Mauro Carvalho Chehab22892262014-01-16 11:28:52 -03002689 (struct i2c_device_addr *)(NULL), 0,
2690 (u8 *)(NULL));
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03002691 msleep(10);
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002692 retry_count++;
2693 } while ((drxbsp_i2c_write_read
Mauro Carvalho Chehab22892262014-01-16 11:28:52 -03002694 ((struct i2c_device_addr *) (NULL), 0, (u8 *)(NULL), dev_addr, 1,
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002695 &data)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002696 != 0) && (retry_count < DRXJ_MAX_RETRIES_POWERUP));
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002697
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002698 /* Need some recovery time .... */
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03002699 msleep(10);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002700
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002701 if (retry_count == DRXJ_MAX_RETRIES_POWERUP)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002702 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002703
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002704 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002705}
2706
2707/*----------------------------------------------------------------------------*/
2708/* MPEG Output Configuration Functions - begin */
2709/*----------------------------------------------------------------------------*/
2710/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002711* \fn int ctrl_set_cfg_mpeg_output()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002712* \brief Set MPEG output configuration of the device.
2713* \param devmod Pointer to demodulator instance.
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002714* \param cfg_data Pointer to mpeg output configuaration.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03002715* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002716*
2717* Configure MPEG output parameters.
2718*
2719*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03002720static int
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002721ctrl_set_cfg_mpeg_output(struct drx_demod_instance *demod, struct drx_cfg_mpeg_output *cfg_data)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002722{
Mauro Carvalho Chehab22892262014-01-16 11:28:52 -03002723 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03002724 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002725 struct drx_common_attr *common_attr = (struct drx_common_attr *) (NULL);
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002726 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002727 u16 fec_oc_reg_mode = 0;
2728 u16 fec_oc_reg_ipr_mode = 0;
2729 u16 fec_oc_reg_ipr_invert = 0;
2730 u32 max_bit_rate = 0;
2731 u32 rcn_rate = 0;
2732 u32 nr_bits = 0;
2733 u16 sio_pdr_md_cfg = 0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002734 /* data mask for the output data byte */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002735 u16 invert_data_mask =
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002736 FEC_OC_IPR_INVERT_MD7__M | FEC_OC_IPR_INVERT_MD6__M |
2737 FEC_OC_IPR_INVERT_MD5__M | FEC_OC_IPR_INVERT_MD4__M |
2738 FEC_OC_IPR_INVERT_MD3__M | FEC_OC_IPR_INVERT_MD2__M |
2739 FEC_OC_IPR_INVERT_MD1__M | FEC_OC_IPR_INVERT_MD0__M;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002740
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002741 /* check arguments */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002742 if ((demod == NULL) || (cfg_data == NULL))
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002743 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002744
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002745 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03002746 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03002747 common_attr = (struct drx_common_attr *) demod->my_common_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002748
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002749 if (cfg_data->enable_mpeg_output == true) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002750 /* quick and dirty patch to set MPEG incase current std is not
2751 producing MPEG */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002752 switch (ext_attr->standard) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002753 case DRX_STANDARD_8VSB:
2754 case DRX_STANDARD_ITU_A:
2755 case DRX_STANDARD_ITU_B:
2756 case DRX_STANDARD_ITU_C:
2757 break;
2758 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002759 return 0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002760 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002761
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002762 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_OCR_INVERT__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002763 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002764 pr_err("error %d\n", rc);
2765 goto rw_error;
2766 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002767 switch (ext_attr->standard) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002768 case DRX_STANDARD_8VSB:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002769 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_FCT_USAGE__A, 7, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002770 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002771 pr_err("error %d\n", rc);
2772 goto rw_error;
2773 } /* 2048 bytes fifo ram */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002774 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_TMD_CTL_UPD_RATE__A, 10, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002775 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002776 pr_err("error %d\n", rc);
2777 goto rw_error;
2778 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002779 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_TMD_INT_UPD_RATE__A, 10, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002780 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002781 pr_err("error %d\n", rc);
2782 goto rw_error;
2783 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002784 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_AVR_PARM_A__A, 5, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002785 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002786 pr_err("error %d\n", rc);
2787 goto rw_error;
2788 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002789 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_AVR_PARM_B__A, 7, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002790 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002791 pr_err("error %d\n", rc);
2792 goto rw_error;
2793 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002794 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_RCN_GAIN__A, 10, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002795 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002796 pr_err("error %d\n", rc);
2797 goto rw_error;
2798 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002799 /* Low Water Mark for synchronization */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002800 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_LWM__A, 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002801 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002802 pr_err("error %d\n", rc);
2803 goto rw_error;
2804 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002805 /* High Water Mark for synchronization */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002806 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_HWM__A, 5, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002807 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002808 pr_err("error %d\n", rc);
2809 goto rw_error;
2810 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002811 break;
2812 case DRX_STANDARD_ITU_A:
2813 case DRX_STANDARD_ITU_C:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002814 switch (ext_attr->constellation) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002815 case DRX_CONSTELLATION_QAM256:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002816 nr_bits = 8;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002817 break;
2818 case DRX_CONSTELLATION_QAM128:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002819 nr_bits = 7;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002820 break;
2821 case DRX_CONSTELLATION_QAM64:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002822 nr_bits = 6;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002823 break;
2824 case DRX_CONSTELLATION_QAM32:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002825 nr_bits = 5;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002826 break;
2827 case DRX_CONSTELLATION_QAM16:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002828 nr_bits = 4;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002829 break;
2830 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002831 return -EIO;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002832 } /* ext_attr->constellation */
2833 /* max_bit_rate = symbol_rate * nr_bits * coef */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002834 /* coef = 188/204 */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002835 max_bit_rate =
2836 (ext_attr->curr_symbol_rate / 8) * nr_bits * 188;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002837 /* pass through b/c Annex A/c need following settings */
2838 case DRX_STANDARD_ITU_B:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002839 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_FCT_USAGE__A, FEC_OC_FCT_USAGE__PRE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002840 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002841 pr_err("error %d\n", rc);
2842 goto rw_error;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002843 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002844 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_TMD_CTL_UPD_RATE__A, FEC_OC_TMD_CTL_UPD_RATE__PRE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002845 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002846 pr_err("error %d\n", rc);
2847 goto rw_error;
2848 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002849 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_TMD_INT_UPD_RATE__A, 5, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002850 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002851 pr_err("error %d\n", rc);
2852 goto rw_error;
2853 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002854 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_AVR_PARM_A__A, FEC_OC_AVR_PARM_A__PRE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002855 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002856 pr_err("error %d\n", rc);
2857 goto rw_error;
2858 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002859 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_AVR_PARM_B__A, FEC_OC_AVR_PARM_B__PRE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002860 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002861 pr_err("error %d\n", rc);
2862 goto rw_error;
2863 }
2864 if (cfg_data->static_clk == true) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002865 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_RCN_GAIN__A, 0xD, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002866 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002867 pr_err("error %d\n", rc);
2868 goto rw_error;
2869 }
2870 } else {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002871 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_RCN_GAIN__A, FEC_OC_RCN_GAIN__PRE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002872 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002873 pr_err("error %d\n", rc);
2874 goto rw_error;
2875 }
2876 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002877 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_LWM__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002878 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002879 pr_err("error %d\n", rc);
2880 goto rw_error;
2881 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002882 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_HWM__A, 12, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002883 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002884 pr_err("error %d\n", rc);
2885 goto rw_error;
2886 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002887 break;
2888 default:
2889 break;
2890 } /* swtich (standard) */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002891
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002892 /* Check insertion of the Reed-Solomon parity bytes */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002893 rc = drxj_dap_read_reg16(dev_addr, FEC_OC_MODE__A, &fec_oc_reg_mode, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002894 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002895 pr_err("error %d\n", rc);
2896 goto rw_error;
2897 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03002898 rc = drxj_dap_read_reg16(dev_addr, FEC_OC_IPR_MODE__A, &fec_oc_reg_ipr_mode, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002899 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03002900 pr_err("error %d\n", rc);
2901 goto rw_error;
2902 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002903 if (cfg_data->insert_rs_byte == true) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002904 /* enable parity symbol forward */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002905 fec_oc_reg_mode |= FEC_OC_MODE_PARITY__M;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002906 /* MVAL disable during parity bytes */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002907 fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M;
2908 switch (ext_attr->standard) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002909 case DRX_STANDARD_8VSB:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002910 rcn_rate = 0x004854D3;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002911 break;
2912 case DRX_STANDARD_ITU_B:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002913 fec_oc_reg_mode |= FEC_OC_MODE_TRANSPARENT__M;
2914 switch (ext_attr->constellation) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002915 case DRX_CONSTELLATION_QAM256:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002916 rcn_rate = 0x008945E7;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002917 break;
2918 case DRX_CONSTELLATION_QAM64:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002919 rcn_rate = 0x005F64D4;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002920 break;
2921 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002922 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002923 }
2924 break;
2925 case DRX_STANDARD_ITU_A:
2926 case DRX_STANDARD_ITU_C:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002927 /* insert_rs_byte = true -> coef = 188/188 -> 1, RS bits are in MPEG output */
2928 rcn_rate =
2929 (frac28
2930 (max_bit_rate,
2931 (u32) (common_attr->sys_clock_freq / 8))) /
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002932 188;
2933 break;
2934 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002935 return -EIO;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002936 } /* ext_attr->standard */
2937 } else { /* insert_rs_byte == false */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002938
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002939 /* disable parity symbol forward */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002940 fec_oc_reg_mode &= (~FEC_OC_MODE_PARITY__M);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002941 /* MVAL enable during parity bytes */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002942 fec_oc_reg_ipr_mode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M);
2943 switch (ext_attr->standard) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002944 case DRX_STANDARD_8VSB:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002945 rcn_rate = 0x0041605C;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002946 break;
2947 case DRX_STANDARD_ITU_B:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002948 fec_oc_reg_mode &= (~FEC_OC_MODE_TRANSPARENT__M);
2949 switch (ext_attr->constellation) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002950 case DRX_CONSTELLATION_QAM256:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002951 rcn_rate = 0x0082D6A0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002952 break;
2953 case DRX_CONSTELLATION_QAM64:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002954 rcn_rate = 0x005AEC1A;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002955 break;
2956 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002957 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002958 }
2959 break;
2960 case DRX_STANDARD_ITU_A:
2961 case DRX_STANDARD_ITU_C:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002962 /* insert_rs_byte = false -> coef = 188/204, RS bits not in MPEG output */
2963 rcn_rate =
2964 (frac28
2965 (max_bit_rate,
2966 (u32) (common_attr->sys_clock_freq / 8))) /
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002967 204;
2968 break;
2969 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03002970 return -EIO;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002971 } /* ext_attr->standard */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002972 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002973
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002974 if (cfg_data->enable_parallel == true) { /* MPEG data output is paralel -> clear ipr_mode[0] */
2975 fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M));
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002976 } else { /* MPEG data output is serial -> set ipr_mode[0] */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002977 fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002978 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002979
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03002980 /* Control slective inversion of output bits */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002981 if (cfg_data->invert_data == true)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002982 fec_oc_reg_ipr_invert |= invert_data_mask;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002983 else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002984 fec_oc_reg_ipr_invert &= (~(invert_data_mask));
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002985
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002986 if (cfg_data->invert_err == true)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002987 fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MERR__M;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002988 else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002989 fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MERR__M));
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002990
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002991 if (cfg_data->invert_str == true)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002992 fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MSTRT__M;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002993 else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002994 fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MSTRT__M));
Devin Heitmueller38b2df92012-08-13 21:18:02 -03002995
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002996 if (cfg_data->invert_val == true)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002997 fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MVAL__M;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03002998 else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03002999 fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MVAL__M));
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003000
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003001 if (cfg_data->invert_clk == true)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003002 fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MCLK__M;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003003 else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003004 fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MCLK__M));
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003005
Mauro Carvalho Chehab41b5cc02014-03-02 11:01:11 -03003006
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003007 if (cfg_data->static_clk == true) { /* Static mode */
3008 u32 dto_rate = 0;
3009 u32 bit_rate = 0;
3010 u16 fec_oc_dto_burst_len = 0;
3011 u16 fec_oc_dto_period = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003012
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003013 fec_oc_dto_burst_len = FEC_OC_DTO_BURST_LEN__PRE;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003014
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003015 switch (ext_attr->standard) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003016 case DRX_STANDARD_8VSB:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003017 fec_oc_dto_period = 4;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003018 if (cfg_data->insert_rs_byte == true)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003019 fec_oc_dto_burst_len = 208;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003020 break;
3021 case DRX_STANDARD_ITU_A:
3022 {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003023 u32 symbol_rate_th = 6400000;
3024 if (cfg_data->insert_rs_byte == true) {
3025 fec_oc_dto_burst_len = 204;
3026 symbol_rate_th = 5900000;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003027 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003028 if (ext_attr->curr_symbol_rate >=
3029 symbol_rate_th) {
3030 fec_oc_dto_period = 0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003031 } else {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003032 fec_oc_dto_period = 1;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003033 }
3034 }
3035 break;
3036 case DRX_STANDARD_ITU_B:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003037 fec_oc_dto_period = 1;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003038 if (cfg_data->insert_rs_byte == true)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003039 fec_oc_dto_burst_len = 128;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003040 break;
3041 case DRX_STANDARD_ITU_C:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003042 fec_oc_dto_period = 1;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003043 if (cfg_data->insert_rs_byte == true)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003044 fec_oc_dto_burst_len = 204;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003045 break;
3046 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003047 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003048 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003049 bit_rate =
3050 common_attr->sys_clock_freq * 1000 / (fec_oc_dto_period +
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003051 2);
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003052 dto_rate =
3053 frac28(bit_rate, common_attr->sys_clock_freq * 1000);
3054 dto_rate >>= 3;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003055 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DTO_RATE_HI__A, (u16)((dto_rate >> 16) & FEC_OC_DTO_RATE_HI__M), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003056 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003057 pr_err("error %d\n", rc);
3058 goto rw_error;
3059 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003060 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003061 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003062 pr_err("error %d\n", rc);
3063 goto rw_error;
3064 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003065 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003066 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003067 pr_err("error %d\n", rc);
3068 goto rw_error;
3069 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003070 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003071 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003072 pr_err("error %d\n", rc);
3073 goto rw_error;
3074 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003075 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DTO_BURST_LEN__A, fec_oc_dto_burst_len, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003076 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003077 pr_err("error %d\n", rc);
3078 goto rw_error;
3079 }
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003080 if (ext_attr->mpeg_output_clock_rate != DRXJ_MPEGOUTPUT_CLOCK_RATE_AUTO)
3081 fec_oc_dto_period = ext_attr->mpeg_output_clock_rate - 1;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003082 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DTO_PERIOD__A, fec_oc_dto_period, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003083 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003084 pr_err("error %d\n", rc);
3085 goto rw_error;
3086 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003087 } else { /* Dynamic mode */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003088
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003089 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DTO_MODE__A, FEC_OC_DTO_MODE_DYNAMIC__M, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003090 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003091 pr_err("error %d\n", rc);
3092 goto rw_error;
3093 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003094 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_FCT_MODE__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003095 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003096 pr_err("error %d\n", rc);
3097 goto rw_error;
3098 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003099 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003100
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003101 rc = drxdap_fasi_write_reg32(dev_addr, FEC_OC_RCN_CTL_RATE_LO__A, rcn_rate, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003102 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003103 pr_err("error %d\n", rc);
3104 goto rw_error;
3105 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003106
3107 /* Write appropriate registers with requested configuration */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003108 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_MODE__A, fec_oc_reg_mode, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003109 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003110 pr_err("error %d\n", rc);
3111 goto rw_error;
3112 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003113 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_IPR_MODE__A, fec_oc_reg_ipr_mode, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003114 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003115 pr_err("error %d\n", rc);
3116 goto rw_error;
3117 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003118 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_IPR_INVERT__A, fec_oc_reg_ipr_invert, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003119 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003120 pr_err("error %d\n", rc);
3121 goto rw_error;
3122 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003123
3124 /* enabling for both parallel and serial now */
3125 /* Write magic word to enable pdr reg write */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003126 rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003127 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003128 pr_err("error %d\n", rc);
3129 goto rw_error;
3130 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003131 /* Set MPEG TS pads to outputmode */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003132 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MSTRT_CFG__A, 0x0013, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003133 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003134 pr_err("error %d\n", rc);
3135 goto rw_error;
3136 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003137 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MERR_CFG__A, 0x0013, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003138 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003139 pr_err("error %d\n", rc);
3140 goto rw_error;
3141 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003142 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003143 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003144 pr_err("error %d\n", rc);
3145 goto rw_error;
3146 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003147 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MVAL_CFG__A, 0x0013, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003148 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003149 pr_err("error %d\n", rc);
3150 goto rw_error;
3151 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003152 sio_pdr_md_cfg =
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003153 MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH <<
3154 SIO_PDR_MD0_CFG_DRIVE__B | 0x03 << SIO_PDR_MD0_CFG_MODE__B;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003155 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD0_CFG__A, sio_pdr_md_cfg, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003156 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003157 pr_err("error %d\n", rc);
3158 goto rw_error;
3159 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003160 if (cfg_data->enable_parallel == true) { /* MPEG data output is paralel -> set MD1 to MD7 to output mode */
3161 sio_pdr_md_cfg =
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003162 MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH <<
3163 SIO_PDR_MD0_CFG_DRIVE__B | 0x03 <<
3164 SIO_PDR_MD0_CFG_MODE__B;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003165 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD0_CFG__A, sio_pdr_md_cfg, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003166 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003167 pr_err("error %d\n", rc);
3168 goto rw_error;
3169 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003170 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD1_CFG__A, sio_pdr_md_cfg, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003171 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003172 pr_err("error %d\n", rc);
3173 goto rw_error;
3174 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003175 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD2_CFG__A, sio_pdr_md_cfg, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003176 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003177 pr_err("error %d\n", rc);
3178 goto rw_error;
3179 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003180 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD3_CFG__A, sio_pdr_md_cfg, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003181 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003182 pr_err("error %d\n", rc);
3183 goto rw_error;
3184 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003185 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD4_CFG__A, sio_pdr_md_cfg, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003186 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003187 pr_err("error %d\n", rc);
3188 goto rw_error;
3189 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003190 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD5_CFG__A, sio_pdr_md_cfg, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003191 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003192 pr_err("error %d\n", rc);
3193 goto rw_error;
3194 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003195 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD6_CFG__A, sio_pdr_md_cfg, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003196 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003197 pr_err("error %d\n", rc);
3198 goto rw_error;
3199 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003200 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD7_CFG__A, sio_pdr_md_cfg, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003201 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003202 pr_err("error %d\n", rc);
3203 goto rw_error;
3204 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003205 } else { /* MPEG data output is serial -> set MD1 to MD7 to tri-state */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003206 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD1_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003207 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003208 pr_err("error %d\n", rc);
3209 goto rw_error;
3210 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003211 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD2_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003212 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003213 pr_err("error %d\n", rc);
3214 goto rw_error;
3215 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003216 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD3_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003217 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003218 pr_err("error %d\n", rc);
3219 goto rw_error;
3220 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003221 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD4_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003222 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003223 pr_err("error %d\n", rc);
3224 goto rw_error;
3225 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003226 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD5_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003227 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003228 pr_err("error %d\n", rc);
3229 goto rw_error;
3230 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003231 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD6_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003232 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003233 pr_err("error %d\n", rc);
3234 goto rw_error;
3235 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003236 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD7_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003237 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003238 pr_err("error %d\n", rc);
3239 goto rw_error;
3240 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003241 }
3242 /* Enable Monitor Bus output over MPEG pads and ctl input */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003243 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MON_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003244 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003245 pr_err("error %d\n", rc);
3246 goto rw_error;
3247 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003248 /* Write nomagic word to enable pdr reg write */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003249 rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003250 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003251 pr_err("error %d\n", rc);
3252 goto rw_error;
3253 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003254 } else {
3255 /* Write magic word to enable pdr reg write */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003256 rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003257 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003258 pr_err("error %d\n", rc);
3259 goto rw_error;
3260 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003261 /* Set MPEG TS pads to inputmode */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003262 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MSTRT_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003263 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003264 pr_err("error %d\n", rc);
3265 goto rw_error;
3266 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003267 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MERR_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003268 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003269 pr_err("error %d\n", rc);
3270 goto rw_error;
3271 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003272 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MCLK_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003273 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003274 pr_err("error %d\n", rc);
3275 goto rw_error;
3276 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003277 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MVAL_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003278 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003279 pr_err("error %d\n", rc);
3280 goto rw_error;
3281 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003282 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD0_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003283 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003284 pr_err("error %d\n", rc);
3285 goto rw_error;
3286 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003287 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD1_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003288 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003289 pr_err("error %d\n", rc);
3290 goto rw_error;
3291 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003292 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD2_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003293 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003294 pr_err("error %d\n", rc);
3295 goto rw_error;
3296 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003297 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD3_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003298 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003299 pr_err("error %d\n", rc);
3300 goto rw_error;
3301 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003302 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD4_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003303 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003304 pr_err("error %d\n", rc);
3305 goto rw_error;
3306 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003307 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD5_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003308 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003309 pr_err("error %d\n", rc);
3310 goto rw_error;
3311 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003312 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD6_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003313 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003314 pr_err("error %d\n", rc);
3315 goto rw_error;
3316 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003317 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MD7_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003318 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003319 pr_err("error %d\n", rc);
3320 goto rw_error;
3321 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003322 /* Enable Monitor Bus output over MPEG pads and ctl input */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003323 rc = drxj_dap_write_reg16(dev_addr, SIO_PDR_MON_CFG__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003324 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003325 pr_err("error %d\n", rc);
3326 goto rw_error;
3327 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003328 /* Write nomagic word to enable pdr reg write */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003329 rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003330 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003331 pr_err("error %d\n", rc);
3332 goto rw_error;
3333 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003334 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003335
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003336 /* save values for restore after re-acquire */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003337 common_attr->mpeg_cfg.enable_mpeg_output = cfg_data->enable_mpeg_output;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003338
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003339 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003340rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003341 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003342}
3343
3344/*----------------------------------------------------------------------------*/
3345
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003346
3347/*----------------------------------------------------------------------------*/
3348/* MPEG Output Configuration Functions - end */
3349/*----------------------------------------------------------------------------*/
3350
3351/*----------------------------------------------------------------------------*/
3352/* miscellaneous configuartions - begin */
3353/*----------------------------------------------------------------------------*/
3354
3355/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003356* \fn int set_mpegtei_handling()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003357* \brief Activate MPEG TEI handling settings.
3358* \param devmod Pointer to demodulator instance.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03003359* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003360*
3361* This routine should be called during a set channel of QAM/VSB
3362*
3363*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03003364static int set_mpegtei_handling(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003365{
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03003366 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
Mauro Carvalho Chehab22892262014-01-16 11:28:52 -03003367 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003368 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003369 u16 fec_oc_dpr_mode = 0;
3370 u16 fec_oc_snc_mode = 0;
3371 u16 fec_oc_ems_mode = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003372
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003373 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03003374 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003375
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003376 rc = drxj_dap_read_reg16(dev_addr, FEC_OC_DPR_MODE__A, &fec_oc_dpr_mode, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003377 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003378 pr_err("error %d\n", rc);
3379 goto rw_error;
3380 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003381 rc = drxj_dap_read_reg16(dev_addr, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003382 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003383 pr_err("error %d\n", rc);
3384 goto rw_error;
3385 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003386 rc = drxj_dap_read_reg16(dev_addr, FEC_OC_EMS_MODE__A, &fec_oc_ems_mode, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003387 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003388 pr_err("error %d\n", rc);
3389 goto rw_error;
3390 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003391
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003392 /* reset to default, allow TEI bit to be changed */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003393 fec_oc_dpr_mode &= (~FEC_OC_DPR_MODE_ERR_DISABLE__M);
3394 fec_oc_snc_mode &= (~(FEC_OC_SNC_MODE_ERROR_CTL__M |
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003395 FEC_OC_SNC_MODE_CORR_DISABLE__M));
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003396 fec_oc_ems_mode &= (~FEC_OC_EMS_MODE_MODE__M);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003397
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03003398 if (ext_attr->disable_te_ihandling) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003399 /* do not change TEI bit */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003400 fec_oc_dpr_mode |= FEC_OC_DPR_MODE_ERR_DISABLE__M;
3401 fec_oc_snc_mode |= FEC_OC_SNC_MODE_CORR_DISABLE__M |
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003402 ((0x2) << (FEC_OC_SNC_MODE_ERROR_CTL__B));
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003403 fec_oc_ems_mode |= ((0x01) << (FEC_OC_EMS_MODE_MODE__B));
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003404 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003405
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003406 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_DPR_MODE__A, fec_oc_dpr_mode, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003407 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003408 pr_err("error %d\n", rc);
3409 goto rw_error;
3410 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003411 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_MODE__A, fec_oc_snc_mode, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003412 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003413 pr_err("error %d\n", rc);
3414 goto rw_error;
3415 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003416 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_EMS_MODE__A, fec_oc_ems_mode, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003417 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003418 pr_err("error %d\n", rc);
3419 goto rw_error;
3420 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003421
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003422 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003423rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003424 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003425}
3426
3427/*----------------------------------------------------------------------------*/
3428/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003429* \fn int bit_reverse_mpeg_output()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003430* \brief Set MPEG output bit-endian settings.
3431* \param devmod Pointer to demodulator instance.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03003432* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003433*
3434* This routine should be called during a set channel of QAM/VSB
3435*
3436*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03003437static int bit_reverse_mpeg_output(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003438{
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03003439 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
Mauro Carvalho Chehab22892262014-01-16 11:28:52 -03003440 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003441 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003442 u16 fec_oc_ipr_mode = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003443
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003444 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03003445 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003446
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003447 rc = drxj_dap_read_reg16(dev_addr, FEC_OC_IPR_MODE__A, &fec_oc_ipr_mode, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003448 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003449 pr_err("error %d\n", rc);
3450 goto rw_error;
3451 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003452
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003453 /* reset to default (normal bit order) */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003454 fec_oc_ipr_mode &= (~FEC_OC_IPR_MODE_REVERSE_ORDER__M);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003455
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003456 if (ext_attr->bit_reverse_mpeg_outout)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003457 fec_oc_ipr_mode |= FEC_OC_IPR_MODE_REVERSE_ORDER__M;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003458
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003459 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_IPR_MODE__A, fec_oc_ipr_mode, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003460 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003461 pr_err("error %d\n", rc);
3462 goto rw_error;
3463 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003464
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003465 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003466rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003467 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003468}
3469
3470/*----------------------------------------------------------------------------*/
3471/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003472* \fn int set_mpeg_start_width()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003473* \brief Set MPEG start width.
3474* \param devmod Pointer to demodulator instance.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03003475* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003476*
3477* This routine should be called during a set channel of QAM/VSB
3478*
3479*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03003480static int set_mpeg_start_width(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003481{
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03003482 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
Mauro Carvalho Chehab22892262014-01-16 11:28:52 -03003483 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03003484 struct drx_common_attr *common_attr = (struct drx_common_attr *) NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003485 int rc;
3486 u16 fec_oc_comm_mb = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003487
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003488 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03003489 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003490 common_attr = demod->my_common_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003491
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003492 if ((common_attr->mpeg_cfg.static_clk == true)
3493 && (common_attr->mpeg_cfg.enable_parallel == false)) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003494 rc = drxj_dap_read_reg16(dev_addr, FEC_OC_COMM_MB__A, &fec_oc_comm_mb, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003495 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003496 pr_err("error %d\n", rc);
3497 goto rw_error;
3498 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003499 fec_oc_comm_mb &= ~FEC_OC_COMM_MB_CTL_ON;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003500 if (ext_attr->mpeg_start_width == DRXJ_MPEG_START_WIDTH_8CLKCYC)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003501 fec_oc_comm_mb |= FEC_OC_COMM_MB_CTL_ON;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003502 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_COMM_MB__A, fec_oc_comm_mb, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003503 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003504 pr_err("error %d\n", rc);
3505 goto rw_error;
3506 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003507 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003508
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003509 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003510rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003511 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003512}
3513
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003514/*----------------------------------------------------------------------------*/
3515/* miscellaneous configuartions - end */
3516/*----------------------------------------------------------------------------*/
3517
3518/*----------------------------------------------------------------------------*/
3519/* UIO Configuration Functions - begin */
3520/*----------------------------------------------------------------------------*/
3521/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003522* \fn int ctrl_set_uio_cfg()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003523* \brief Configure modus oprandi UIO.
3524* \param demod Pointer to demodulator instance.
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003525* \param uio_cfg Pointer to a configuration setting for a certain UIO.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03003526* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003527*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03003528static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg *uio_cfg)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003529{
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03003530 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003531 int rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003532
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003533 if ((uio_cfg == NULL) || (demod == NULL))
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003534 return -EINVAL;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003535
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03003536 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003537
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003538 /* Write magic word to enable pdr reg write */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003539 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003540 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003541 pr_err("error %d\n", rc);
3542 goto rw_error;
3543 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003544 switch (uio_cfg->uio) {
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003545 /*====================================================================*/
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003546 case DRX_UIO1:
3547 /* DRX_UIO1: SMA_TX UIO-1 */
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03003548 if (!ext_attr->has_smatx)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003549 return -EIO;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003550 switch (uio_cfg->mode) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003551 case DRX_UIO_MODE_FIRMWARE_SMA: /* falltrough */
3552 case DRX_UIO_MODE_FIRMWARE_SAW: /* falltrough */
3553 case DRX_UIO_MODE_READWRITE:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003554 ext_attr->uio_sma_tx_mode = uio_cfg->mode;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003555 break;
3556 case DRX_UIO_MODE_DISABLE:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003557 ext_attr->uio_sma_tx_mode = uio_cfg->mode;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003558 /* pad configuration register is set 0 - input mode */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003559 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003560 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003561 pr_err("error %d\n", rc);
3562 goto rw_error;
3563 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003564 break;
3565 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003566 return -EINVAL;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003567 } /* switch ( uio_cfg->mode ) */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003568 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003569 /*====================================================================*/
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003570 case DRX_UIO2:
3571 /* DRX_UIO2: SMA_RX UIO-2 */
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03003572 if (!ext_attr->has_smarx)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003573 return -EIO;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003574 switch (uio_cfg->mode) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003575 case DRX_UIO_MODE_FIRMWARE0: /* falltrough */
3576 case DRX_UIO_MODE_READWRITE:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003577 ext_attr->uio_sma_rx_mode = uio_cfg->mode;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003578 break;
3579 case DRX_UIO_MODE_DISABLE:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003580 ext_attr->uio_sma_rx_mode = uio_cfg->mode;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003581 /* pad configuration register is set 0 - input mode */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003582 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_RX_CFG__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003583 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003584 pr_err("error %d\n", rc);
3585 goto rw_error;
3586 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003587 break;
3588 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003589 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003590 break;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003591 } /* switch ( uio_cfg->mode ) */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003592 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003593 /*====================================================================*/
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003594 case DRX_UIO3:
3595 /* DRX_UIO3: GPIO UIO-3 */
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03003596 if (!ext_attr->has_gpio)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003597 return -EIO;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003598 switch (uio_cfg->mode) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003599 case DRX_UIO_MODE_FIRMWARE0: /* falltrough */
3600 case DRX_UIO_MODE_READWRITE:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003601 ext_attr->uio_gpio_mode = uio_cfg->mode;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003602 break;
3603 case DRX_UIO_MODE_DISABLE:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003604 ext_attr->uio_gpio_mode = uio_cfg->mode;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003605 /* pad configuration register is set 0 - input mode */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003606 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_GPIO_CFG__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003607 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003608 pr_err("error %d\n", rc);
3609 goto rw_error;
3610 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003611 break;
3612 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003613 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003614 break;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003615 } /* switch ( uio_cfg->mode ) */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003616 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003617 /*====================================================================*/
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003618 case DRX_UIO4:
3619 /* DRX_UIO4: IRQN UIO-4 */
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03003620 if (!ext_attr->has_irqn)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003621 return -EIO;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003622 switch (uio_cfg->mode) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003623 case DRX_UIO_MODE_READWRITE:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003624 ext_attr->uio_irqn_mode = uio_cfg->mode;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003625 break;
3626 case DRX_UIO_MODE_DISABLE:
3627 /* pad configuration register is set 0 - input mode */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003628 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_IRQN_CFG__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003629 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003630 pr_err("error %d\n", rc);
3631 goto rw_error;
3632 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003633 ext_attr->uio_irqn_mode = uio_cfg->mode;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003634 break;
3635 case DRX_UIO_MODE_FIRMWARE0: /* falltrough */
3636 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003637 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003638 break;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003639 } /* switch ( uio_cfg->mode ) */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003640 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003641 /*====================================================================*/
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003642 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003643 return -EINVAL;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003644 } /* switch ( uio_cfg->uio ) */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003645
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003646 /* Write magic word to disable pdr reg write */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003647 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003648 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003649 pr_err("error %d\n", rc);
3650 goto rw_error;
3651 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003652
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003653 return 0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003654rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003655 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003656}
3657
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003658/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003659* \fn int ctrl_uio_write()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003660* \brief Write to a UIO.
3661* \param demod Pointer to demodulator instance.
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003662* \param uio_data Pointer to data container for a certain UIO.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03003663* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003664*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03003665static int
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03003666ctrl_uio_write(struct drx_demod_instance *demod, struct drxuio_data *uio_data)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003667{
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03003668 struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003669 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003670 u16 pin_cfg_value = 0;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03003671 u16 value = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003672
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003673 if ((uio_data == NULL) || (demod == NULL))
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003674 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003675
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03003676 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003677
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003678 /* Write magic word to enable pdr reg write */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003679 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003680 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003681 pr_err("error %d\n", rc);
3682 goto rw_error;
3683 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003684 switch (uio_data->uio) {
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003685 /*====================================================================*/
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003686 case DRX_UIO1:
3687 /* DRX_UIO1: SMA_TX UIO-1 */
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03003688 if (!ext_attr->has_smatx)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003689 return -EIO;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003690 if ((ext_attr->uio_sma_tx_mode != DRX_UIO_MODE_READWRITE)
3691 && (ext_attr->uio_sma_tx_mode != DRX_UIO_MODE_FIRMWARE_SAW)) {
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003692 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003693 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003694 pin_cfg_value = 0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003695 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003696 pin_cfg_value |= 0x0113;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003697 /* io_pad_cfg_mode output mode is drive always */
3698 /* io_pad_cfg_drive is set to power 2 (23 mA) */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003699
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003700 /* write to io pad configuration register - output mode */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003701 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, pin_cfg_value, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003702 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003703 pr_err("error %d\n", rc);
3704 goto rw_error;
3705 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003706
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003707 /* use corresponding bit in io data output registar */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003708 rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, &value, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003709 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003710 pr_err("error %d\n", rc);
3711 goto rw_error;
3712 }
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003713 if (!uio_data->value)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003714 value &= 0x7FFF; /* write zero to 15th bit - 1st UIO */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003715 else
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003716 value |= 0x8000; /* write one to 15th bit - 1st UIO */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003717
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003718 /* write back to io data output register */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003719 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003720 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003721 pr_err("error %d\n", rc);
3722 goto rw_error;
3723 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003724 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003725 /*======================================================================*/
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003726 case DRX_UIO2:
3727 /* DRX_UIO2: SMA_RX UIO-2 */
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03003728 if (!ext_attr->has_smarx)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003729 return -EIO;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003730 if (ext_attr->uio_sma_rx_mode != DRX_UIO_MODE_READWRITE)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003731 return -EIO;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003732
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003733 pin_cfg_value = 0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003734 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003735 pin_cfg_value |= 0x0113;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003736 /* io_pad_cfg_mode output mode is drive always */
3737 /* io_pad_cfg_drive is set to power 2 (23 mA) */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003738
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003739 /* write to io pad configuration register - output mode */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003740 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_RX_CFG__A, pin_cfg_value, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003741 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003742 pr_err("error %d\n", rc);
3743 goto rw_error;
3744 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003745
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003746 /* use corresponding bit in io data output registar */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003747 rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, &value, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003748 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003749 pr_err("error %d\n", rc);
3750 goto rw_error;
3751 }
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003752 if (!uio_data->value)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003753 value &= 0xBFFF; /* write zero to 14th bit - 2nd UIO */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003754 else
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003755 value |= 0x4000; /* write one to 14th bit - 2nd UIO */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003756
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003757 /* write back to io data output register */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003758 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003759 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003760 pr_err("error %d\n", rc);
3761 goto rw_error;
3762 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003763 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003764 /*====================================================================*/
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003765 case DRX_UIO3:
3766 /* DRX_UIO3: ASEL UIO-3 */
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03003767 if (!ext_attr->has_gpio)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003768 return -EIO;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003769 if (ext_attr->uio_gpio_mode != DRX_UIO_MODE_READWRITE)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003770 return -EIO;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003771
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003772 pin_cfg_value = 0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003773 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003774 pin_cfg_value |= 0x0113;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003775 /* io_pad_cfg_mode output mode is drive always */
3776 /* io_pad_cfg_drive is set to power 2 (23 mA) */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003777
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003778 /* write to io pad configuration register - output mode */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003779 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_GPIO_CFG__A, pin_cfg_value, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003780 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003781 pr_err("error %d\n", rc);
3782 goto rw_error;
3783 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003784
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003785 /* use corresponding bit in io data output registar */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003786 rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_HI__A, &value, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003787 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003788 pr_err("error %d\n", rc);
3789 goto rw_error;
3790 }
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003791 if (!uio_data->value)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003792 value &= 0xFFFB; /* write zero to 2nd bit - 3rd UIO */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003793 else
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003794 value |= 0x0004; /* write one to 2nd bit - 3rd UIO */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003795
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003796 /* write back to io data output register */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003797 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_HI__A, value, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003798 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003799 pr_err("error %d\n", rc);
3800 goto rw_error;
3801 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003802 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003803 /*=====================================================================*/
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003804 case DRX_UIO4:
3805 /* DRX_UIO4: IRQN UIO-4 */
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03003806 if (!ext_attr->has_irqn)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003807 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003808
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003809 if (ext_attr->uio_irqn_mode != DRX_UIO_MODE_READWRITE)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003810 return -EIO;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003811
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003812 pin_cfg_value = 0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003813 /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003814 pin_cfg_value |= 0x0113;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003815 /* io_pad_cfg_mode output mode is drive always */
3816 /* io_pad_cfg_drive is set to power 2 (23 mA) */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003817
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003818 /* write to io pad configuration register - output mode */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003819 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_IRQN_CFG__A, pin_cfg_value, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003820 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003821 pr_err("error %d\n", rc);
3822 goto rw_error;
3823 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003824
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003825 /* use corresponding bit in io data output registar */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003826 rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, &value, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003827 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003828 pr_err("error %d\n", rc);
3829 goto rw_error;
3830 }
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003831 if (uio_data->value == false)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003832 value &= 0xEFFF; /* write zero to 12th bit - 4th UIO */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003833 else
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003834 value |= 0x1000; /* write one to 12th bit - 4th UIO */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003835
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003836 /* write back to io data output register */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003837 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_UIO_OUT_LO__A, value, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003838 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003839 pr_err("error %d\n", rc);
3840 goto rw_error;
3841 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003842 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003843 /*=====================================================================*/
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003844 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003845 return -EINVAL;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003846 } /* switch ( uio_data->uio ) */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003847
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003848 /* Write magic word to disable pdr reg write */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003849 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003850 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003851 pr_err("error %d\n", rc);
3852 goto rw_error;
3853 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003854
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003855 return 0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003856rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003857 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003858}
3859
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003860/*---------------------------------------------------------------------------*/
3861/* UIO Configuration Functions - end */
3862/*---------------------------------------------------------------------------*/
3863
3864/*----------------------------------------------------------------------------*/
3865/* I2C Bridge Functions - begin */
3866/*----------------------------------------------------------------------------*/
3867/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003868* \fn int ctrl_i2c_bridge()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003869* \brief Open or close the I2C switch to tuner.
3870* \param demod Pointer to demodulator instance.
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003871* \param bridge_closed Pointer to bool indication if bridge is closed not.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03003872* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003873
3874*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03003875static int
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03003876ctrl_i2c_bridge(struct drx_demod_instance *demod, bool *bridge_closed)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003877{
Mauro Carvalho Chehab60d36032014-01-17 07:00:31 -03003878 struct drxj_hi_cmd hi_cmd;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03003879 u16 result = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003880
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003881 /* check arguments */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003882 if (bridge_closed == NULL)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003883 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003884
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003885 hi_cmd.cmd = SIO_HI_RA_RAM_CMD_BRDCTRL;
3886 hi_cmd.param1 = SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003887 if (*bridge_closed)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003888 hi_cmd.param2 = SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003889 else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003890 hi_cmd.param2 = SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003891
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003892 return hi_command(demod->my_i2c_dev_addr, &hi_cmd, &result);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003893}
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003894
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003895/*----------------------------------------------------------------------------*/
3896/* I2C Bridge Functions - end */
3897/*----------------------------------------------------------------------------*/
3898
3899/*----------------------------------------------------------------------------*/
3900/* Smart antenna Functions - begin */
3901/*----------------------------------------------------------------------------*/
3902/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003903* \fn int smart_ant_init()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003904* \brief Initialize Smart Antenna.
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03003905* \param pointer to struct drx_demod_instance.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03003906* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003907*
3908*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03003909static int smart_ant_init(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003910{
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03003911 struct drxj_data *ext_attr = NULL;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003912 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03003913 struct drxuio_cfg uio_cfg = { DRX_UIO1, DRX_UIO_MODE_FIRMWARE_SMA };
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003914 int rc;
3915 u16 data = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003916
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003917 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03003918 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003919
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003920 /* Write magic word to enable pdr reg write */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003921 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003922 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003923 pr_err("error %d\n", rc);
3924 goto rw_error;
3925 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003926 /* init smart antenna */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003927 rc = drxj_dap_read_reg16(dev_addr, SIO_SA_TX_COMMAND__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003928 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003929 pr_err("error %d\n", rc);
3930 goto rw_error;
3931 }
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003932 if (ext_attr->smart_ant_inverted) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003933 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003934 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003935 pr_err("error %d\n", rc);
3936 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003937 }
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003938 } else {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003939 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003940 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003941 pr_err("error %d\n", rc);
3942 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003943 }
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003944 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003945
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003946 /* config SMA_TX pin to smart antenna mode */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003947 rc = ctrl_set_uio_cfg(demod, &uio_cfg);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003948 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003949 pr_err("error %d\n", rc);
3950 goto rw_error;
3951 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003952 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_CFG__A, 0x13, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003953 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003954 pr_err("error %d\n", rc);
3955 goto rw_error;
3956 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003957 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_PDR_SMA_TX_GPIO_FNC__A, 0x03, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003958 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003959 pr_err("error %d\n", rc);
3960 goto rw_error;
3961 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003962
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003963 /* Write magic word to disable pdr reg write */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003964 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003965 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003966 pr_err("error %d\n", rc);
3967 goto rw_error;
3968 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003969
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003970 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003971rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003972 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003973}
3974
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03003975static int scu_command(struct i2c_device_addr *dev_addr, struct drxjscu_cmd *cmd)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003976{
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003977 int rc;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003978 u16 cur_cmd = 0;
Mauro Carvalho Chehabceea5e22014-01-26 15:55:57 -03003979 unsigned long timeout;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003980
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003981 /* Check param */
3982 if (cmd == NULL)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003983 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003984
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003985 /* Wait until SCU command interface is ready to receive command */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003986 rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_COMMAND__A, &cur_cmd, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003987 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003988 pr_err("error %d\n", rc);
3989 goto rw_error;
3990 }
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03003991 if (cur_cmd != DRX_SCU_READY)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003992 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03003993
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03003994 switch (cmd->parameter_len) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03003995 case 5:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03003996 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_4__A, *(cmd->parameter + 4), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03003997 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03003998 pr_err("error %d\n", rc);
3999 goto rw_error;
4000 } /* fallthrough */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004001 case 4:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004002 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_3__A, *(cmd->parameter + 3), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004003 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004004 pr_err("error %d\n", rc);
4005 goto rw_error;
4006 } /* fallthrough */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004007 case 3:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004008 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_2__A, *(cmd->parameter + 2), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004009 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004010 pr_err("error %d\n", rc);
4011 goto rw_error;
4012 } /* fallthrough */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004013 case 2:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004014 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_1__A, *(cmd->parameter + 1), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004015 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004016 pr_err("error %d\n", rc);
4017 goto rw_error;
4018 } /* fallthrough */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004019 case 1:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004020 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_0__A, *(cmd->parameter + 0), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004021 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004022 pr_err("error %d\n", rc);
4023 goto rw_error;
4024 } /* fallthrough */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004025 case 0:
4026 /* do nothing */
4027 break;
4028 default:
4029 /* this number of parameters is not supported */
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004030 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004031 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004032 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_COMMAND__A, cmd->command, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004033 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004034 pr_err("error %d\n", rc);
4035 goto rw_error;
4036 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004037
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004038 /* Wait until SCU has processed command */
Mauro Carvalho Chehabceea5e22014-01-26 15:55:57 -03004039 timeout = jiffies + msecs_to_jiffies(DRXJ_MAX_WAITTIME);
4040 while (time_is_after_jiffies(timeout)) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004041 rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_COMMAND__A, &cur_cmd, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004042 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004043 pr_err("error %d\n", rc);
4044 goto rw_error;
4045 }
Mauro Carvalho Chehabceea5e22014-01-26 15:55:57 -03004046 if (cur_cmd == DRX_SCU_READY)
4047 break;
4048 usleep_range(1000, 2000);
4049 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004050
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004051 if (cur_cmd != DRX_SCU_READY)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004052 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004053
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004054 /* read results */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004055 if ((cmd->result_len > 0) && (cmd->result != NULL)) {
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03004056 s16 err;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004057
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004058 switch (cmd->result_len) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004059 case 4:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004060 rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_PARAM_3__A, cmd->result + 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004061 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004062 pr_err("error %d\n", rc);
4063 goto rw_error;
4064 } /* fallthrough */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004065 case 3:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004066 rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_PARAM_2__A, cmd->result + 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004067 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004068 pr_err("error %d\n", rc);
4069 goto rw_error;
4070 } /* fallthrough */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004071 case 2:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004072 rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_PARAM_1__A, cmd->result + 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004073 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004074 pr_err("error %d\n", rc);
4075 goto rw_error;
4076 } /* fallthrough */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004077 case 1:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004078 rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_PARAM_0__A, cmd->result + 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004079 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004080 pr_err("error %d\n", rc);
4081 goto rw_error;
4082 } /* fallthrough */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004083 case 0:
4084 /* do nothing */
4085 break;
4086 default:
4087 /* this number of parameters is not supported */
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004088 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004089 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004090
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004091 /* Check if an error was reported by SCU */
4092 err = cmd->result[0];
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004093
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004094 /* check a few fixed error codes */
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03004095 if ((err == (s16) SCU_RAM_PARAM_0_RESULT_UNKSTD)
4096 || (err == (s16) SCU_RAM_PARAM_0_RESULT_UNKCMD)
4097 || (err == (s16) SCU_RAM_PARAM_0_RESULT_INVPAR)
4098 || (err == (s16) SCU_RAM_PARAM_0_RESULT_SIZE)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004099 ) {
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004100 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004101 }
4102 /* here it is assumed that negative means error, and positive no error */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004103 else if (err < 0)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004104 return -EIO;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004105 else
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004106 return 0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004107 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004108
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004109 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004110
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004111rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004112 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004113}
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004114
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004115/**
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03004116* \fn int DRXJ_DAP_SCUAtomicReadWriteBlock()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004117* \brief Basic access routine for SCU atomic read or write access
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004118* \param dev_addr pointer to i2c dev address
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004119* \param addr destination/source address
4120* \param datasize size of data buffer in bytes
4121* \param data pointer to data buffer
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03004122* \return int
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004123* \retval 0 Succes
4124* \retval -EIO Timeout, I2C error, illegal bank
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004125*
4126*/
4127#define ADDR_AT_SCU_SPACE(x) ((x - 0x82E000) * 2)
4128static
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03004129int 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 */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004130 u8 *data, bool read_flag)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004131{
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03004132 struct drxjscu_cmd scu_cmd;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004133 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004134 u16 set_param_parameters[15];
4135 u16 cmd_result[15];
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004136
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004137 /* Parameter check */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004138 if (!data || !dev_addr || (datasize % 2) || ((datasize / 2) > 16))
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004139 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004140
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004141 set_param_parameters[1] = (u16) ADDR_AT_SCU_SPACE(addr);
4142 if (read_flag) { /* read */
4143 set_param_parameters[0] = ((~(0x0080)) & datasize);
4144 scu_cmd.parameter_len = 2;
4145 scu_cmd.result_len = datasize / 2 + 2;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004146 } else {
4147 int i = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004148
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004149 set_param_parameters[0] = 0x0080 | datasize;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004150 for (i = 0; i < (datasize / 2); i++) {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004151 set_param_parameters[i + 2] =
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004152 (data[2 * i] | (data[(2 * i) + 1] << 8));
4153 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004154 scu_cmd.parameter_len = datasize / 2 + 2;
4155 scu_cmd.result_len = 1;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004156 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004157
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004158 scu_cmd.command =
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004159 SCU_RAM_COMMAND_STANDARD_TOP |
4160 SCU_RAM_COMMAND_CMD_AUX_SCU_ATOMIC_ACCESS;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004161 scu_cmd.result = cmd_result;
4162 scu_cmd.parameter = set_param_parameters;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004163 rc = scu_command(dev_addr, &scu_cmd);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004164 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004165 pr_err("error %d\n", rc);
4166 goto rw_error;
4167 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004168
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03004169 if (read_flag) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004170 int i = 0;
4171 /* read data from buffer */
4172 for (i = 0; i < (datasize / 2); i++) {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004173 data[2 * i] = (u8) (scu_cmd.result[i + 2] & 0xFF);
4174 data[(2 * i) + 1] = (u8) (scu_cmd.result[i + 2] >> 8);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004175 }
4176 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004177
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004178 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004179
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004180rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004181 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004182
4183}
4184
4185/*============================================================================*/
4186
4187/**
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03004188* \fn int DRXJ_DAP_AtomicReadReg16()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004189* \brief Atomic read of 16 bits words
4190*/
4191static
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004192int drxj_dap_scu_atomic_read_reg16(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03004193 u32 addr,
4194 u16 *data, u32 flags)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004195{
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03004196 u8 buf[2];
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004197 int rc = -EIO;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03004198 u16 word = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004199
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004200 if (!data)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004201 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004202
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004203 rc = drxj_dap_scu_atomic_read_write_block(dev_addr, addr, 2, buf, true);
Mauro Carvalho Chehabb1d0a592014-01-16 16:34:03 -03004204 if (rc < 0)
4205 return rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004206
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03004207 word = (u16) (buf[0] + (buf[1] << 8));
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004208
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004209 *data = word;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004210
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004211 return rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004212}
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004213
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004214/*============================================================================*/
4215/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004216* \fn int drxj_dap_scu_atomic_write_reg16()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004217* \brief Atomic read of 16 bits words
4218*/
4219static
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004220int drxj_dap_scu_atomic_write_reg16(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03004221 u32 addr,
4222 u16 data, u32 flags)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004223{
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03004224 u8 buf[2];
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004225 int rc = -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004226
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03004227 buf[0] = (u8) (data & 0xff);
4228 buf[1] = (u8) ((data >> 8) & 0xff);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004229
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004230 rc = drxj_dap_scu_atomic_read_write_block(dev_addr, addr, 2, buf, false);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004231
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004232 return rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004233}
4234
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004235/* -------------------------------------------------------------------------- */
4236/**
4237* \brief Measure result of ADC synchronisation
4238* \param demod demod instance
4239* \param count (returned) count
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03004240* \return int.
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004241* \retval 0 Success
4242* \retval -EIO Failure: I2C error
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004243*
4244*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03004245static int adc_sync_measurement(struct drx_demod_instance *demod, u16 *count)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004246{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004247 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004248 int rc;
4249 u16 data = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004250
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004251 dev_addr = demod->my_i2c_dev_addr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004252
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004253 /* Start measurement */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004254 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_COMM_EXEC__A, IQM_AF_COMM_EXEC_ACTIVE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004255 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004256 pr_err("error %d\n", rc);
4257 goto rw_error;
4258 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004259 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_START_LOCK__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004260 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004261 pr_err("error %d\n", rc);
4262 goto rw_error;
4263 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004264
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004265 /* Wait at least 3*128*(1/sysclk) <<< 1 millisec */
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03004266 msleep(1);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004267
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004268 *count = 0;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004269 rc = drxj_dap_read_reg16(dev_addr, IQM_AF_PHASE0__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004270 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004271 pr_err("error %d\n", rc);
4272 goto rw_error;
4273 }
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004274 if (data == 127)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004275 *count = *count + 1;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004276 rc = drxj_dap_read_reg16(dev_addr, IQM_AF_PHASE1__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004277 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004278 pr_err("error %d\n", rc);
4279 goto rw_error;
4280 }
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004281 if (data == 127)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004282 *count = *count + 1;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004283 rc = drxj_dap_read_reg16(dev_addr, IQM_AF_PHASE2__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004284 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004285 pr_err("error %d\n", rc);
4286 goto rw_error;
4287 }
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004288 if (data == 127)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004289 *count = *count + 1;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004290
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004291 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004292rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004293 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004294}
4295
4296/**
4297* \brief Synchronize analog and digital clock domains
4298* \param demod demod instance
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03004299* \return int.
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004300* \retval 0 Success
4301* \retval -EIO Failure: I2C error or failure to synchronize
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004302*
4303* An IQM reset will also reset the results of this synchronization.
4304* After an IQM reset this routine needs to be called again.
4305*
4306*/
4307
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03004308static int adc_synchronization(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004309{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004310 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004311 int rc;
4312 u16 count = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004313
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004314 dev_addr = demod->my_i2c_dev_addr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004315
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004316 rc = adc_sync_measurement(demod, &count);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004317 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004318 pr_err("error %d\n", rc);
4319 goto rw_error;
4320 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004321
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004322 if (count == 1) {
4323 /* Try sampling on a diffrent edge */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004324 u16 clk_neg = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004325
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004326 rc = drxj_dap_read_reg16(dev_addr, IQM_AF_CLKNEG__A, &clk_neg, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004327 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004328 pr_err("error %d\n", rc);
4329 goto rw_error;
4330 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004331
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004332 clk_neg ^= IQM_AF_CLKNEG_CLKNEGDATA__M;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004333 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_CLKNEG__A, clk_neg, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004334 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004335 pr_err("error %d\n", rc);
4336 goto rw_error;
4337 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004338
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004339 rc = adc_sync_measurement(demod, &count);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004340 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004341 pr_err("error %d\n", rc);
4342 goto rw_error;
4343 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004344 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004345
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004346 /* TODO: implement fallback scenarios */
4347 if (count < 2)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004348 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004349
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004350 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004351rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004352 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004353}
4354
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004355/*============================================================================*/
4356/*== END AUXILIARY FUNCTIONS ==*/
4357/*============================================================================*/
4358
4359/*============================================================================*/
4360/*============================================================================*/
4361/*== 8VSB & QAM COMMON DATAPATH FUNCTIONS ==*/
4362/*============================================================================*/
4363/*============================================================================*/
4364/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004365* \fn int init_agc ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004366* \brief Initialize AGC for all standards.
4367* \param demod instance of demodulator.
4368* \param channel pointer to channel data.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03004369* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004370*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03004371static int init_agc(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004372{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004373 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03004374 struct drx_common_attr *common_attr = NULL;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03004375 struct drxj_data *ext_attr = NULL;
4376 struct drxj_cfg_agc *p_agc_rf_settings = NULL;
4377 struct drxj_cfg_agc *p_agc_if_settings = NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004378 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004379 u16 ingain_tgt_max = 0;
4380 u16 clp_dir_to = 0;
4381 u16 sns_sum_max = 0;
4382 u16 clp_sum_max = 0;
4383 u16 sns_dir_to = 0;
4384 u16 ki_innergain_min = 0;
4385 u16 agc_ki = 0;
4386 u16 ki_max = 0;
4387 u16 if_iaccu_hi_tgt_min = 0;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03004388 u16 data = 0;
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -03004389 u16 agc_ki_dgain = 0;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004390 u16 ki_min = 0;
4391 u16 clp_ctrl_mode = 0;
4392 u16 agc_rf = 0;
4393 u16 agc_if = 0;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004394
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004395 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03004396 common_attr = (struct drx_common_attr *) demod->my_common_attr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03004397 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004398
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004399 switch (ext_attr->standard) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004400 case DRX_STANDARD_8VSB:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004401 clp_sum_max = 1023;
4402 clp_dir_to = (u16) (-9);
4403 sns_sum_max = 1023;
4404 sns_dir_to = (u16) (-9);
4405 ki_innergain_min = (u16) (-32768);
4406 ki_max = 0x032C;
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -03004407 agc_ki_dgain = 0xC;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004408 if_iaccu_hi_tgt_min = 2047;
4409 ki_min = 0x0117;
4410 ingain_tgt_max = 16383;
4411 clp_ctrl_mode = 0;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004412 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004413 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004414 pr_err("error %d\n", rc);
4415 goto rw_error;
4416 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004417 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004418 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004419 pr_err("error %d\n", rc);
4420 goto rw_error;
4421 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004422 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_SUM__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004423 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004424 pr_err("error %d\n", rc);
4425 goto rw_error;
4426 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004427 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_CYCCNT__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004428 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004429 pr_err("error %d\n", rc);
4430 goto rw_error;
4431 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004432 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_DIR_WD__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004433 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004434 pr_err("error %d\n", rc);
4435 goto rw_error;
4436 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004437 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_DIR_STP__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004438 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004439 pr_err("error %d\n", rc);
4440 goto rw_error;
4441 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004442 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_SUM__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004443 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004444 pr_err("error %d\n", rc);
4445 goto rw_error;
4446 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004447 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_CYCCNT__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004448 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004449 pr_err("error %d\n", rc);
4450 goto rw_error;
4451 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004452 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_DIR_WD__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004453 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004454 pr_err("error %d\n", rc);
4455 goto rw_error;
4456 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004457 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_DIR_STP__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004458 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004459 pr_err("error %d\n", rc);
4460 goto rw_error;
4461 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004462 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN__A, 1024, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004463 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004464 pr_err("error %d\n", rc);
4465 goto rw_error;
4466 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004467 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_VSB_AGC_POW_TGT__A, 22600, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004468 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004469 pr_err("error %d\n", rc);
4470 goto rw_error;
4471 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004472 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, 13200, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004473 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004474 pr_err("error %d\n", rc);
4475 goto rw_error;
4476 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004477 p_agc_if_settings = &(ext_attr->vsb_if_agc_cfg);
4478 p_agc_rf_settings = &(ext_attr->vsb_rf_agc_cfg);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004479 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004480#ifndef DRXJ_VSB_ONLY
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004481 case DRX_STANDARD_ITU_A:
4482 case DRX_STANDARD_ITU_C:
4483 case DRX_STANDARD_ITU_B:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004484 ingain_tgt_max = 5119;
4485 clp_sum_max = 1023;
4486 clp_dir_to = (u16) (-5);
4487 sns_sum_max = 127;
4488 sns_dir_to = (u16) (-3);
4489 ki_innergain_min = 0;
4490 ki_max = 0x0657;
4491 if_iaccu_hi_tgt_min = 2047;
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -03004492 agc_ki_dgain = 0x7;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004493 ki_min = 0x0117;
4494 clp_ctrl_mode = 0;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004495 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004496 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004497 pr_err("error %d\n", rc);
4498 goto rw_error;
4499 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004500 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004501 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004502 pr_err("error %d\n", rc);
4503 goto rw_error;
4504 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004505 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_SUM__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004506 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004507 pr_err("error %d\n", rc);
4508 goto rw_error;
4509 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004510 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_CYCCNT__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004511 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004512 pr_err("error %d\n", rc);
4513 goto rw_error;
4514 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004515 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_DIR_WD__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004516 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004517 pr_err("error %d\n", rc);
4518 goto rw_error;
4519 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004520 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_DIR_STP__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004521 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004522 pr_err("error %d\n", rc);
4523 goto rw_error;
4524 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004525 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_SUM__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004526 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004527 pr_err("error %d\n", rc);
4528 goto rw_error;
4529 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004530 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_CYCCNT__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004531 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004532 pr_err("error %d\n", rc);
4533 goto rw_error;
4534 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004535 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_DIR_WD__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004536 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004537 pr_err("error %d\n", rc);
4538 goto rw_error;
4539 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004540 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_DIR_STP__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004541 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004542 pr_err("error %d\n", rc);
4543 goto rw_error;
4544 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004545 p_agc_if_settings = &(ext_attr->qam_if_agc_cfg);
4546 p_agc_rf_settings = &(ext_attr->qam_rf_agc_cfg);
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004547 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN_TGT__A, p_agc_if_settings->top, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004548 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004549 pr_err("error %d\n", rc);
4550 goto rw_error;
4551 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004552
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004553 rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_AGC_KI__A, &agc_ki, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004554 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004555 pr_err("error %d\n", rc);
4556 goto rw_error;
4557 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004558 agc_ki &= 0xf000;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004559 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI__A, agc_ki, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004560 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004561 pr_err("error %d\n", rc);
4562 goto rw_error;
4563 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004564 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004565#endif
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004566 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004567 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004568 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004569
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004570 /* for new AGC interface */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004571 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN_TGT_MIN__A, p_agc_if_settings->top, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004572 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004573 pr_err("error %d\n", rc);
4574 goto rw_error;
4575 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004576 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN__A, p_agc_if_settings->top, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004577 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004578 pr_err("error %d\n", rc);
4579 goto rw_error;
4580 } /* Gain fed from inner to outer AGC */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004581 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingain_tgt_max, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004582 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004583 pr_err("error %d\n", rc);
4584 goto rw_error;
4585 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004586 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, if_iaccu_hi_tgt_min, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004587 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004588 pr_err("error %d\n", rc);
4589 goto rw_error;
4590 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004591 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_IF_IACCU_HI__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004592 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004593 pr_err("error %d\n", rc);
4594 goto rw_error;
4595 } /* set to p_agc_settings->top before */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004596 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_IF_IACCU_LO__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004597 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004598 pr_err("error %d\n", rc);
4599 goto rw_error;
4600 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004601 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_RF_IACCU_HI__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004602 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004603 pr_err("error %d\n", rc);
4604 goto rw_error;
4605 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004606 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_RF_IACCU_LO__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004607 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004608 pr_err("error %d\n", rc);
4609 goto rw_error;
4610 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004611 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_RF_MAX__A, 32767, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004612 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004613 pr_err("error %d\n", rc);
4614 goto rw_error;
4615 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004616 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_SUM_MAX__A, clp_sum_max, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004617 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004618 pr_err("error %d\n", rc);
4619 goto rw_error;
4620 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004621 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_SUM_MAX__A, sns_sum_max, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004622 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004623 pr_err("error %d\n", rc);
4624 goto rw_error;
4625 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004626 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, ki_innergain_min, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004627 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004628 pr_err("error %d\n", rc);
4629 goto rw_error;
4630 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004631 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_FAST_SNS_CTRL_DELAY__A, 50, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004632 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004633 pr_err("error %d\n", rc);
4634 goto rw_error;
4635 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004636 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_CYCLEN__A, 500, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004637 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004638 pr_err("error %d\n", rc);
4639 goto rw_error;
4640 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004641 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_CYCLEN__A, 500, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004642 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004643 pr_err("error %d\n", rc);
4644 goto rw_error;
4645 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004646 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MAXMINGAIN_TH__A, 20, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004647 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004648 pr_err("error %d\n", rc);
4649 goto rw_error;
4650 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004651 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MIN__A, ki_min, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004652 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004653 pr_err("error %d\n", rc);
4654 goto rw_error;
4655 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004656 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_MAX__A, ki_max, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004657 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004658 pr_err("error %d\n", rc);
4659 goto rw_error;
4660 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004661 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI_RED__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004662 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004663 pr_err("error %d\n", rc);
4664 goto rw_error;
4665 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004666 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_SUM_MIN__A, 8, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004667 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004668 pr_err("error %d\n", rc);
4669 goto rw_error;
4670 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004671 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_CYCLEN__A, 500, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004672 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004673 pr_err("error %d\n", rc);
4674 goto rw_error;
4675 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004676 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_DIR_TO__A, clp_dir_to, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004677 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004678 pr_err("error %d\n", rc);
4679 goto rw_error;
4680 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004681 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_SUM_MIN__A, 8, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004682 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004683 pr_err("error %d\n", rc);
4684 goto rw_error;
4685 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004686 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_SNS_DIR_TO__A, sns_dir_to, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004687 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004688 pr_err("error %d\n", rc);
4689 goto rw_error;
4690 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004691 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, 50, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004692 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004693 pr_err("error %d\n", rc);
4694 goto rw_error;
4695 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004696 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_CLP_CTRL_MODE__A, clp_ctrl_mode, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004697 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004698 pr_err("error %d\n", rc);
4699 goto rw_error;
4700 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004701
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004702 agc_rf = 0x800 + p_agc_rf_settings->cut_off_current;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004703 if (common_attr->tuner_rf_agc_pol == true)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004704 agc_rf = 0x87ff - agc_rf;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004705
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004706 agc_if = 0x800;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004707 if (common_attr->tuner_if_agc_pol == true)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004708 agc_rf = 0x87ff - agc_rf;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004709
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004710 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_AGC_RF__A, agc_rf, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004711 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004712 pr_err("error %d\n", rc);
4713 goto rw_error;
4714 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004715 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_AGC_IF__A, agc_if, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004716 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004717 pr_err("error %d\n", rc);
4718 goto rw_error;
4719 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004720
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004721 /* Set/restore Ki DGAIN factor */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004722 rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004723 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004724 pr_err("error %d\n", rc);
4725 goto rw_error;
4726 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004727 data &= ~SCU_RAM_AGC_KI_DGAIN__M;
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -03004728 data |= (agc_ki_dgain << SCU_RAM_AGC_KI_DGAIN__B);
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004729 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004730 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004731 pr_err("error %d\n", rc);
4732 goto rw_error;
4733 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004734
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004735 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004736rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004737 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004738}
4739
4740/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004741* \fn int set_frequency ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004742* \brief Set frequency shift.
4743* \param demod instance of demodulator.
4744* \param channel pointer to channel data.
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004745* \param tuner_freq_offset residual frequency from tuner.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03004746* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004747*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03004748static int
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03004749set_frequency(struct drx_demod_instance *demod,
4750 struct drx_channel *channel, s32 tuner_freq_offset)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004751{
Mauro Carvalho Chehab4d7bb0e2014-01-16 11:49:13 -03004752 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03004753 struct drxj_data *ext_attr = demod->my_ext_attr;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004754 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004755 s32 sampling_frequency = 0;
4756 s32 frequency_shift = 0;
4757 s32 if_freq_actual = 0;
Mauro Carvalho Chehab4d7bb0e2014-01-16 11:49:13 -03004758 s32 rf_freq_residual = -1 * tuner_freq_offset;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004759 s32 adc_freq = 0;
4760 s32 intermediate_freq = 0;
4761 u32 iqm_fs_rate_ofs = 0;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004762 bool adc_flip = true;
4763 bool select_pos_image = false;
Mauro Carvalho Chehab4d7bb0e2014-01-16 11:49:13 -03004764 bool rf_mirror;
4765 bool tuner_mirror;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004766 bool image_to_select = true;
4767 s32 fm_frequency_shift = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004768
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004769 rf_mirror = (ext_attr->mirror == DRX_MIRROR_YES) ? true : false;
4770 tuner_mirror = demod->my_common_attr->mirror_freq_spect ? false : true;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004771 /*
4772 Program frequency shifter
4773 No need to account for mirroring on RF
4774 */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004775 switch (ext_attr->standard) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004776 case DRX_STANDARD_ITU_A: /* fallthrough */
4777 case DRX_STANDARD_ITU_C: /* fallthrough */
4778 case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
4779 case DRX_STANDARD_8VSB:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004780 select_pos_image = true;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004781 break;
4782 case DRX_STANDARD_FM:
4783 /* After IQM FS sound carrier must appear at 4 Mhz in spect.
4784 Sound carrier is already 3Mhz above centre frequency due
4785 to tuner setting so now add an extra shift of 1MHz... */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004786 fm_frequency_shift = 1000;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004787 case DRX_STANDARD_ITU_B: /* fallthrough */
4788 case DRX_STANDARD_NTSC: /* fallthrough */
4789 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
4790 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
4791 case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
4792 case DRX_STANDARD_PAL_SECAM_L:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004793 select_pos_image = false;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004794 break;
4795 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004796 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004797 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004798 intermediate_freq = demod->my_common_attr->intermediate_freq;
4799 sampling_frequency = demod->my_common_attr->sys_clock_freq / 3;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004800 if (tuner_mirror)
4801 if_freq_actual = intermediate_freq + rf_freq_residual + fm_frequency_shift;
4802 else
4803 if_freq_actual = intermediate_freq - rf_freq_residual - fm_frequency_shift;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004804 if (if_freq_actual > sampling_frequency / 2) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004805 /* adc mirrors */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004806 adc_freq = sampling_frequency - if_freq_actual;
4807 adc_flip = true;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004808 } else {
4809 /* adc doesn't mirror */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004810 adc_freq = if_freq_actual;
4811 adc_flip = false;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004812 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004813
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004814 frequency_shift = adc_freq;
4815 image_to_select =
4816 (bool) (rf_mirror ^ tuner_mirror ^ adc_flip ^ select_pos_image);
4817 iqm_fs_rate_ofs = frac28(frequency_shift, sampling_frequency);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004818
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004819 if (image_to_select)
4820 iqm_fs_rate_ofs = ~iqm_fs_rate_ofs + 1;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004821
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004822 /* Program frequency shifter with tuner offset compensation */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004823 /* frequency_shift += tuner_freq_offset; TODO */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004824 rc = drxdap_fasi_write_reg32(dev_addr, IQM_FS_RATE_OFS_LO__A, iqm_fs_rate_ofs, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004825 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004826 pr_err("error %d\n", rc);
4827 goto rw_error;
4828 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004829 ext_attr->iqm_fs_rate_ofs = iqm_fs_rate_ofs;
4830 ext_attr->pos_image = (bool) (rf_mirror ^ tuner_mirror ^ select_pos_image);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004831
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004832 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004833rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004834 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004835}
4836
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004837/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004838* \fn int get_acc_pkt_err()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004839* \brief Retrieve signal strength for VSB and QAM.
4840* \param demod Pointer to demod instance
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004841* \param packet_err Pointer to packet error
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03004842* \return int.
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004843* \retval 0 sig_strength contains valid data.
4844* \retval -EINVAL sig_strength is NULL.
4845* \retval -EIO Erroneous data, sig_strength contains invalid data.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004846*/
4847#ifdef DRXJ_SIGNAL_ACCUM_ERR
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03004848static int get_acc_pkt_err(struct drx_demod_instance *demod, u16 *packet_err)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004849{
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004850 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004851 static u16 pkt_err;
4852 static u16 last_pkt_err;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03004853 u16 data = 0;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03004854 struct drxj_data *ext_attr = NULL;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004855 struct i2c_device_addr *dev_addr = NULL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004856
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03004857 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004858 dev_addr = demod->my_i2c_dev_addr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004859
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004860 rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004861 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004862 pr_err("error %d\n", rc);
4863 goto rw_error;
4864 }
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03004865 if (ext_attr->reset_pkt_err_acc) {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004866 last_pkt_err = data;
4867 pkt_err = 0;
4868 ext_attr->reset_pkt_err_acc = false;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004869 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004870
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004871 if (data < last_pkt_err) {
4872 pkt_err += 0xffff - last_pkt_err;
4873 pkt_err += data;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004874 } else {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004875 pkt_err += (data - last_pkt_err);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004876 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004877 *packet_err = pkt_err;
4878 last_pkt_err = data;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004879
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004880 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004881rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004882 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004883}
4884#endif
4885
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004886
4887/*============================================================================*/
4888
4889/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004890* \fn int set_agc_rf ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004891* \brief Configure RF AGC
4892* \param demod instance of demodulator.
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004893* \param agc_settings AGC configuration structure
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03004894* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004895*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03004896static int
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03004897set_agc_rf(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings, bool atomic)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004898{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004899 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03004900 struct drxj_data *ext_attr = NULL;
4901 struct drxj_cfg_agc *p_agc_settings = NULL;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03004902 struct drx_common_attr *common_attr = NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004903 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004904 drx_write_reg16func_t scu_wr16 = NULL;
4905 drx_read_reg16func_t scu_rr16 = NULL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004906
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03004907 common_attr = (struct drx_common_attr *) demod->my_common_attr;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004908 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03004909 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004910
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004911 if (atomic) {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004912 scu_rr16 = drxj_dap_scu_atomic_read_reg16;
4913 scu_wr16 = drxj_dap_scu_atomic_write_reg16;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004914 } else {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004915 scu_rr16 = drxj_dap_read_reg16;
4916 scu_wr16 = drxj_dap_write_reg16;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004917 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004918
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004919 /* Configure AGC only if standard is currently active */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004920 if ((ext_attr->standard == agc_settings->standard) ||
4921 (DRXJ_ISQAMSTD(ext_attr->standard) &&
4922 DRXJ_ISQAMSTD(agc_settings->standard)) ||
4923 (DRXJ_ISATVSTD(ext_attr->standard) &&
4924 DRXJ_ISATVSTD(agc_settings->standard))) {
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03004925 u16 data = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004926
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004927 switch (agc_settings->ctrl_mode) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004928 case DRX_AGC_CTRL_AUTO:
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004929
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004930 /* Enable RF AGC DAC */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004931 rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004932 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004933 pr_err("error %d\n", rc);
4934 goto rw_error;
4935 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004936 data |= IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03004937 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004938 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004939 pr_err("error %d\n", rc);
4940 goto rw_error;
4941 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004942
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004943 /* Enable SCU RF AGC loop */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004944 rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004945 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004946 pr_err("error %d\n", rc);
4947 goto rw_error;
4948 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004949 data &= ~SCU_RAM_AGC_KI_RF__M;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004950 if (ext_attr->standard == DRX_STANDARD_8VSB)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004951 data |= (2 << SCU_RAM_AGC_KI_RF__B);
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004952 else if (DRXJ_ISQAMSTD(ext_attr->standard))
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004953 data |= (5 << SCU_RAM_AGC_KI_RF__B);
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004954 else
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004955 data |= (4 << SCU_RAM_AGC_KI_RF__B);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004956
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004957 if (common_attr->tuner_rf_agc_pol)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004958 data |= SCU_RAM_AGC_KI_INV_RF_POL__M;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004959 else
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004960 data &= ~SCU_RAM_AGC_KI_INV_RF_POL__M;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004961 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004962 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004963 pr_err("error %d\n", rc);
4964 goto rw_error;
4965 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004966
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004967 /* Set speed ( using complementary reduction value ) */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004968 rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI_RED__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004969 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004970 pr_err("error %d\n", rc);
4971 goto rw_error;
4972 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004973 data &= ~SCU_RAM_AGC_KI_RED_RAGC_RED__M;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03004974 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004975 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004976 pr_err("error %d\n", rc);
4977 goto rw_error;
4978 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004979
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004980 if (agc_settings->standard == DRX_STANDARD_8VSB)
4981 p_agc_settings = &(ext_attr->vsb_if_agc_cfg);
4982 else if (DRXJ_ISQAMSTD(agc_settings->standard))
4983 p_agc_settings = &(ext_attr->qam_if_agc_cfg);
4984 else if (DRXJ_ISATVSTD(agc_settings->standard))
4985 p_agc_settings = &(ext_attr->atv_if_agc_cfg);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004986 else
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004987 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03004988
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03004989 /* Set TOP, only if IF-AGC is in AUTO mode */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03004990 if (p_agc_settings->ctrl_mode == DRX_AGC_CTRL_AUTO) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004991 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, agc_settings->top, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004992 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004993 pr_err("error %d\n", rc);
4994 goto rw_error;
4995 }
4996 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, agc_settings->top, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03004997 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03004998 pr_err("error %d\n", rc);
4999 goto rw_error;
5000 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005001 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005002
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005003 /* Cut-Off current */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005004 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_RF_IACCU_HI_CO__A, agc_settings->cut_off_current, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005005 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005006 pr_err("error %d\n", rc);
5007 goto rw_error;
5008 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005009 break;
5010 case DRX_AGC_CTRL_USER:
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005011
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005012 /* Enable RF AGC DAC */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005013 rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005014 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005015 pr_err("error %d\n", rc);
5016 goto rw_error;
5017 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005018 data |= IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005019 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005020 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005021 pr_err("error %d\n", rc);
5022 goto rw_error;
5023 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005024
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005025 /* Disable SCU RF AGC loop */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005026 rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005027 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005028 pr_err("error %d\n", rc);
5029 goto rw_error;
5030 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005031 data &= ~SCU_RAM_AGC_KI_RF__M;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03005032 if (common_attr->tuner_rf_agc_pol)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005033 data |= SCU_RAM_AGC_KI_INV_RF_POL__M;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03005034 else
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005035 data &= ~SCU_RAM_AGC_KI_INV_RF_POL__M;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005036 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005037 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005038 pr_err("error %d\n", rc);
5039 goto rw_error;
5040 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005041
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005042 /* Write value to output pin */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005043 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_RF_IACCU_HI__A, agc_settings->output_level, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005044 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005045 pr_err("error %d\n", rc);
5046 goto rw_error;
5047 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005048 break;
5049 case DRX_AGC_CTRL_OFF:
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005050
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005051 /* Disable RF AGC DAC */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005052 rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005053 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005054 pr_err("error %d\n", rc);
5055 goto rw_error;
5056 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005057 data &= (~IQM_AF_STDBY_STDBY_TAGC_RF_A2_ACTIVE);
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005058 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005059 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005060 pr_err("error %d\n", rc);
5061 goto rw_error;
5062 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005063
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005064 /* Disable SCU RF AGC loop */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005065 rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005066 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005067 pr_err("error %d\n", rc);
5068 goto rw_error;
5069 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005070 data &= ~SCU_RAM_AGC_KI_RF__M;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005071 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005072 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005073 pr_err("error %d\n", rc);
5074 goto rw_error;
5075 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005076 break;
5077 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005078 return -EINVAL;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005079 } /* switch ( agcsettings->ctrl_mode ) */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005080 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005081
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005082 /* Store rf agc settings */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005083 switch (agc_settings->standard) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005084 case DRX_STANDARD_8VSB:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005085 ext_attr->vsb_rf_agc_cfg = *agc_settings;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005086 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005087#ifndef DRXJ_VSB_ONLY
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005088 case DRX_STANDARD_ITU_A:
5089 case DRX_STANDARD_ITU_B:
5090 case DRX_STANDARD_ITU_C:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005091 ext_attr->qam_rf_agc_cfg = *agc_settings;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005092 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005093#endif
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005094 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005095 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005096 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005097
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005098 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005099rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005100 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005101}
5102
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005103/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005104* \fn int set_agc_if ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005105* \brief Configure If AGC
5106* \param demod instance of demodulator.
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005107* \param agc_settings AGC configuration structure
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03005108* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005109*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03005110static int
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03005111set_agc_if(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings, bool atomic)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005112{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005113 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03005114 struct drxj_data *ext_attr = NULL;
5115 struct drxj_cfg_agc *p_agc_settings = NULL;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03005116 struct drx_common_attr *common_attr = NULL;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005117 drx_write_reg16func_t scu_wr16 = NULL;
5118 drx_read_reg16func_t scu_rr16 = NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005119 int rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005120
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03005121 common_attr = (struct drx_common_attr *) demod->my_common_attr;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005122 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03005123 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005124
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005125 if (atomic) {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005126 scu_rr16 = drxj_dap_scu_atomic_read_reg16;
5127 scu_wr16 = drxj_dap_scu_atomic_write_reg16;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005128 } else {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005129 scu_rr16 = drxj_dap_read_reg16;
5130 scu_wr16 = drxj_dap_write_reg16;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005131 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005132
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005133 /* Configure AGC only if standard is currently active */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005134 if ((ext_attr->standard == agc_settings->standard) ||
5135 (DRXJ_ISQAMSTD(ext_attr->standard) &&
5136 DRXJ_ISQAMSTD(agc_settings->standard)) ||
5137 (DRXJ_ISATVSTD(ext_attr->standard) &&
5138 DRXJ_ISATVSTD(agc_settings->standard))) {
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03005139 u16 data = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005140
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005141 switch (agc_settings->ctrl_mode) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005142 case DRX_AGC_CTRL_AUTO:
5143 /* Enable IF AGC DAC */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005144 rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005145 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005146 pr_err("error %d\n", rc);
5147 goto rw_error;
5148 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005149 data |= IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005150 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005151 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005152 pr_err("error %d\n", rc);
5153 goto rw_error;
5154 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005155
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005156 /* Enable SCU IF AGC loop */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005157 rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005158 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005159 pr_err("error %d\n", rc);
5160 goto rw_error;
5161 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005162 data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
5163 data &= ~SCU_RAM_AGC_KI_IF__M;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03005164 if (ext_attr->standard == DRX_STANDARD_8VSB)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005165 data |= (3 << SCU_RAM_AGC_KI_IF__B);
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03005166 else if (DRXJ_ISQAMSTD(ext_attr->standard))
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005167 data |= (6 << SCU_RAM_AGC_KI_IF__B);
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03005168 else
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005169 data |= (5 << SCU_RAM_AGC_KI_IF__B);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005170
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03005171 if (common_attr->tuner_if_agc_pol)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005172 data |= SCU_RAM_AGC_KI_INV_IF_POL__M;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03005173 else
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005174 data &= ~SCU_RAM_AGC_KI_INV_IF_POL__M;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005175 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005176 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005177 pr_err("error %d\n", rc);
5178 goto rw_error;
5179 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005180
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005181 /* Set speed (using complementary reduction value) */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005182 rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI_RED__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005183 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005184 pr_err("error %d\n", rc);
5185 goto rw_error;
5186 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005187 data &= ~SCU_RAM_AGC_KI_RED_IAGC_RED__M;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005188 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005189 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005190 pr_err("error %d\n", rc);
5191 goto rw_error;
5192 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005193
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005194 if (agc_settings->standard == DRX_STANDARD_8VSB)
5195 p_agc_settings = &(ext_attr->vsb_rf_agc_cfg);
5196 else if (DRXJ_ISQAMSTD(agc_settings->standard))
5197 p_agc_settings = &(ext_attr->qam_rf_agc_cfg);
5198 else if (DRXJ_ISATVSTD(agc_settings->standard))
5199 p_agc_settings = &(ext_attr->atv_rf_agc_cfg);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005200 else
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005201 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005202
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005203 /* Restore TOP */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005204 if (p_agc_settings->ctrl_mode == DRX_AGC_CTRL_AUTO) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005205 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, p_agc_settings->top, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005206 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005207 pr_err("error %d\n", rc);
5208 goto rw_error;
5209 }
5210 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, p_agc_settings->top, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005211 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005212 pr_err("error %d\n", rc);
5213 goto rw_error;
5214 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005215 } else {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005216 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005217 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005218 pr_err("error %d\n", rc);
5219 goto rw_error;
5220 }
5221 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005222 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005223 pr_err("error %d\n", rc);
5224 goto rw_error;
5225 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005226 }
5227 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005228
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005229 case DRX_AGC_CTRL_USER:
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005230
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005231 /* Enable IF AGC DAC */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005232 rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005233 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005234 pr_err("error %d\n", rc);
5235 goto rw_error;
5236 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005237 data |= IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005238 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005239 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005240 pr_err("error %d\n", rc);
5241 goto rw_error;
5242 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005243
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005244 /* Disable SCU IF AGC loop */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005245 rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005246 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005247 pr_err("error %d\n", rc);
5248 goto rw_error;
5249 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005250 data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
5251 data |= SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03005252 if (common_attr->tuner_if_agc_pol)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005253 data |= SCU_RAM_AGC_KI_INV_IF_POL__M;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03005254 else
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005255 data &= ~SCU_RAM_AGC_KI_INV_IF_POL__M;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005256 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005257 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005258 pr_err("error %d\n", rc);
5259 goto rw_error;
5260 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005261
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005262 /* Write value to output pin */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005263 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, agc_settings->output_level, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005264 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005265 pr_err("error %d\n", rc);
5266 goto rw_error;
5267 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005268 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005269
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005270 case DRX_AGC_CTRL_OFF:
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005271
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005272 /* Disable If AGC DAC */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005273 rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005274 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005275 pr_err("error %d\n", rc);
5276 goto rw_error;
5277 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005278 data &= (~IQM_AF_STDBY_STDBY_TAGC_IF_A2_ACTIVE);
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005279 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005280 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005281 pr_err("error %d\n", rc);
5282 goto rw_error;
5283 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005284
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005285 /* Disable SCU IF AGC loop */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005286 rc = (*scu_rr16)(dev_addr, SCU_RAM_AGC_KI__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005287 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005288 pr_err("error %d\n", rc);
5289 goto rw_error;
5290 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005291 data &= ~SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
5292 data |= SCU_RAM_AGC_KI_IF_AGC_DISABLE__M;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005293 rc = (*scu_wr16)(dev_addr, SCU_RAM_AGC_KI__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005294 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005295 pr_err("error %d\n", rc);
5296 goto rw_error;
5297 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005298 break;
5299 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005300 return -EINVAL;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005301 } /* switch ( agcsettings->ctrl_mode ) */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005302
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005303 /* always set the top to support configurations without if-loop */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005304 rc = (*scu_wr16) (dev_addr, SCU_RAM_AGC_INGAIN_TGT_MIN__A, agc_settings->top, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005305 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005306 pr_err("error %d\n", rc);
5307 goto rw_error;
5308 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005309 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005310
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005311 /* Store if agc settings */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005312 switch (agc_settings->standard) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005313 case DRX_STANDARD_8VSB:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005314 ext_attr->vsb_if_agc_cfg = *agc_settings;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005315 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005316#ifndef DRXJ_VSB_ONLY
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005317 case DRX_STANDARD_ITU_A:
5318 case DRX_STANDARD_ITU_B:
5319 case DRX_STANDARD_ITU_C:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005320 ext_attr->qam_if_agc_cfg = *agc_settings;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005321 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005322#endif
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005323 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005324 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005325 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005326
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005327 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005328rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005329 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005330}
5331
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005332/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005333* \fn int set_iqm_af ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005334* \brief Configure IQM AF registers
5335* \param demod instance of demodulator.
5336* \param active
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03005337* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005338*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03005339static int set_iqm_af(struct drx_demod_instance *demod, bool active)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005340{
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03005341 u16 data = 0;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005342 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005343 int rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005344
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005345 dev_addr = demod->my_i2c_dev_addr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005346
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005347 /* Configure IQM */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005348 rc = drxj_dap_read_reg16(dev_addr, IQM_AF_STDBY__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005349 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005350 pr_err("error %d\n", rc);
5351 goto rw_error;
5352 }
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03005353 if (!active)
5354 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));
5355 else
5356 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);
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005357 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005358 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005359 pr_err("error %d\n", rc);
5360 goto rw_error;
5361 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005362
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005363 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005364rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005365 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005366}
5367
5368/*============================================================================*/
5369/*== END 8VSB & QAM COMMON DATAPATH FUNCTIONS ==*/
5370/*============================================================================*/
5371
5372/*============================================================================*/
5373/*============================================================================*/
5374/*== 8VSB DATAPATH FUNCTIONS ==*/
5375/*============================================================================*/
5376/*============================================================================*/
5377
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005378/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005379* \fn int power_down_vsb ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005380* \brief Powr down QAM related blocks.
5381* \param demod instance of demodulator.
5382* \param channel pointer to channel data.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03005383* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005384*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03005385static int power_down_vsb(struct drx_demod_instance *demod, bool primary)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005386{
Mauro Carvalho Chehab4d7bb0e2014-01-16 11:49:13 -03005387 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03005388 struct drxjscu_cmd cmd_scu = { /* command */ 0,
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005389 /* parameter_len */ 0,
5390 /* result_len */ 0,
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005391 /* *parameter */ NULL,
5392 /* *result */ NULL
5393 };
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03005394 struct drx_cfg_mpeg_output cfg_mpeg_output;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005395 int rc;
5396 u16 cmd_result = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005397
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005398 /*
5399 STOP demodulator
5400 reset of FEC and VSB HW
5401 */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005402 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB |
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005403 SCU_RAM_COMMAND_CMD_DEMOD_STOP;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005404 cmd_scu.parameter_len = 0;
5405 cmd_scu.result_len = 1;
5406 cmd_scu.parameter = NULL;
5407 cmd_scu.result = &cmd_result;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005408 rc = scu_command(dev_addr, &cmd_scu);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005409 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005410 pr_err("error %d\n", rc);
5411 goto rw_error;
5412 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005413
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005414 /* stop all comm_exec */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005415 rc = drxj_dap_write_reg16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005416 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005417 pr_err("error %d\n", rc);
5418 goto rw_error;
5419 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005420 rc = drxj_dap_write_reg16(dev_addr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005421 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005422 pr_err("error %d\n", rc);
5423 goto rw_error;
5424 }
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03005425 if (primary) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005426 rc = drxj_dap_write_reg16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005427 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005428 pr_err("error %d\n", rc);
5429 goto rw_error;
5430 }
5431 rc = set_iqm_af(demod, false);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005432 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005433 pr_err("error %d\n", rc);
5434 goto rw_error;
5435 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005436 } else {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005437 rc = drxj_dap_write_reg16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005438 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005439 pr_err("error %d\n", rc);
5440 goto rw_error;
5441 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005442 rc = drxj_dap_write_reg16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005443 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005444 pr_err("error %d\n", rc);
5445 goto rw_error;
5446 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005447 rc = drxj_dap_write_reg16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005448 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005449 pr_err("error %d\n", rc);
5450 goto rw_error;
5451 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005452 rc = drxj_dap_write_reg16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005453 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005454 pr_err("error %d\n", rc);
5455 goto rw_error;
5456 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005457 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005458 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005459 pr_err("error %d\n", rc);
5460 goto rw_error;
5461 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005462 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005463
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005464 cfg_mpeg_output.enable_mpeg_output = false;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005465 rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005466 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005467 pr_err("error %d\n", rc);
5468 goto rw_error;
5469 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005470
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005471 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005472rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005473 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005474}
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005475
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005476/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005477* \fn int set_vsb_leak_n_gain ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005478* \brief Set ATSC demod.
5479* \param demod instance of demodulator.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03005480* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005481*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03005482static int set_vsb_leak_n_gain(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005483{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005484 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005485 int rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005486
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03005487 const u8 vsb_ffe_leak_gain_ram0[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005488 DRXJ_16TO8(0x8), /* FFETRAINLKRATIO1 */
5489 DRXJ_16TO8(0x8), /* FFETRAINLKRATIO2 */
5490 DRXJ_16TO8(0x8), /* FFETRAINLKRATIO3 */
5491 DRXJ_16TO8(0xf), /* FFETRAINLKRATIO4 */
5492 DRXJ_16TO8(0xf), /* FFETRAINLKRATIO5 */
5493 DRXJ_16TO8(0xf), /* FFETRAINLKRATIO6 */
5494 DRXJ_16TO8(0xf), /* FFETRAINLKRATIO7 */
5495 DRXJ_16TO8(0xf), /* FFETRAINLKRATIO8 */
5496 DRXJ_16TO8(0xf), /* FFETRAINLKRATIO9 */
5497 DRXJ_16TO8(0x8), /* FFETRAINLKRATIO10 */
5498 DRXJ_16TO8(0x8), /* FFETRAINLKRATIO11 */
5499 DRXJ_16TO8(0x8), /* FFETRAINLKRATIO12 */
5500 DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO1 */
5501 DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO2 */
5502 DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO3 */
5503 DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO4 */
5504 DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO5 */
5505 DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO6 */
5506 DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO7 */
5507 DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO8 */
5508 DRXJ_16TO8(0x20), /* FFERCA1TRAINLKRATIO9 */
5509 DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO10 */
5510 DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO11 */
5511 DRXJ_16TO8(0x10), /* FFERCA1TRAINLKRATIO12 */
5512 DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO1 */
5513 DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO2 */
5514 DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO3 */
5515 DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO4 */
5516 DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO5 */
5517 DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO6 */
5518 DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO7 */
5519 DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO8 */
5520 DRXJ_16TO8(0x20), /* FFERCA1DATALKRATIO9 */
5521 DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO10 */
5522 DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO11 */
5523 DRXJ_16TO8(0x10), /* FFERCA1DATALKRATIO12 */
5524 DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO1 */
5525 DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO2 */
5526 DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO3 */
5527 DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO4 */
5528 DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO5 */
5529 DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO6 */
5530 DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO7 */
5531 DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO8 */
5532 DRXJ_16TO8(0x20), /* FFERCA2TRAINLKRATIO9 */
5533 DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO10 */
5534 DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO11 */
5535 DRXJ_16TO8(0x10), /* FFERCA2TRAINLKRATIO12 */
5536 DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO1 */
5537 DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO2 */
5538 DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO3 */
5539 DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO4 */
5540 DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO5 */
5541 DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO6 */
5542 DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO7 */
5543 DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO8 */
5544 DRXJ_16TO8(0x20), /* FFERCA2DATALKRATIO9 */
5545 DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO10 */
5546 DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO11 */
5547 DRXJ_16TO8(0x10), /* FFERCA2DATALKRATIO12 */
5548 DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO1 */
5549 DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO2 */
5550 DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO3 */
5551 DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO4 */
5552 DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO5 */
5553 DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO6 */
5554 DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO7 */
5555 DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO8 */
5556 DRXJ_16TO8(0x0e), /* FFEDDM1TRAINLKRATIO9 */
5557 DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO10 */
5558 DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO11 */
5559 DRXJ_16TO8(0x07), /* FFEDDM1TRAINLKRATIO12 */
5560 DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO1 */
5561 DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO2 */
5562 DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO3 */
5563 DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO4 */
5564 DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO5 */
5565 DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO6 */
5566 DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO7 */
5567 DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO8 */
5568 DRXJ_16TO8(0x0e), /* FFEDDM1DATALKRATIO9 */
5569 DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO10 */
5570 DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO11 */
5571 DRXJ_16TO8(0x07), /* FFEDDM1DATALKRATIO12 */
5572 DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO1 */
5573 DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO2 */
5574 DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO3 */
5575 DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO4 */
5576 DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO5 */
5577 DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO6 */
5578 DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO7 */
5579 DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO8 */
5580 DRXJ_16TO8(0x0c), /* FFEDDM2TRAINLKRATIO9 */
5581 DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO10 */
5582 DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO11 */
5583 DRXJ_16TO8(0x06), /* FFEDDM2TRAINLKRATIO12 */
5584 DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO1 */
5585 DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO2 */
5586 DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO3 */
5587 DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO4 */
5588 DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO5 */
5589 DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO6 */
5590 DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO7 */
5591 DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO8 */
5592 DRXJ_16TO8(0x0c), /* FFEDDM2DATALKRATIO9 */
5593 DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO10 */
5594 DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO11 */
5595 DRXJ_16TO8(0x06), /* FFEDDM2DATALKRATIO12 */
5596 DRXJ_16TO8(0x2020), /* FIRTRAINGAIN1 */
5597 DRXJ_16TO8(0x2020), /* FIRTRAINGAIN2 */
5598 DRXJ_16TO8(0x2020), /* FIRTRAINGAIN3 */
5599 DRXJ_16TO8(0x4040), /* FIRTRAINGAIN4 */
5600 DRXJ_16TO8(0x4040), /* FIRTRAINGAIN5 */
5601 DRXJ_16TO8(0x4040), /* FIRTRAINGAIN6 */
5602 DRXJ_16TO8(0x4040), /* FIRTRAINGAIN7 */
5603 DRXJ_16TO8(0x4040), /* FIRTRAINGAIN8 */
5604 DRXJ_16TO8(0x4040), /* FIRTRAINGAIN9 */
5605 DRXJ_16TO8(0x2020), /* FIRTRAINGAIN10 */
5606 DRXJ_16TO8(0x2020), /* FIRTRAINGAIN11 */
5607 DRXJ_16TO8(0x2020), /* FIRTRAINGAIN12 */
5608 DRXJ_16TO8(0x0808), /* FIRRCA1GAIN1 */
5609 DRXJ_16TO8(0x0808), /* FIRRCA1GAIN2 */
5610 DRXJ_16TO8(0x0808), /* FIRRCA1GAIN3 */
5611 DRXJ_16TO8(0x1010), /* FIRRCA1GAIN4 */
5612 DRXJ_16TO8(0x1010), /* FIRRCA1GAIN5 */
5613 DRXJ_16TO8(0x1010), /* FIRRCA1GAIN6 */
5614 DRXJ_16TO8(0x1010), /* FIRRCA1GAIN7 */
5615 DRXJ_16TO8(0x1010) /* FIRRCA1GAIN8 */
5616 };
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005617
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03005618 const u8 vsb_ffe_leak_gain_ram1[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005619 DRXJ_16TO8(0x1010), /* FIRRCA1GAIN9 */
5620 DRXJ_16TO8(0x0808), /* FIRRCA1GAIN10 */
5621 DRXJ_16TO8(0x0808), /* FIRRCA1GAIN11 */
5622 DRXJ_16TO8(0x0808), /* FIRRCA1GAIN12 */
5623 DRXJ_16TO8(0x0808), /* FIRRCA2GAIN1 */
5624 DRXJ_16TO8(0x0808), /* FIRRCA2GAIN2 */
5625 DRXJ_16TO8(0x0808), /* FIRRCA2GAIN3 */
5626 DRXJ_16TO8(0x1010), /* FIRRCA2GAIN4 */
5627 DRXJ_16TO8(0x1010), /* FIRRCA2GAIN5 */
5628 DRXJ_16TO8(0x1010), /* FIRRCA2GAIN6 */
5629 DRXJ_16TO8(0x1010), /* FIRRCA2GAIN7 */
5630 DRXJ_16TO8(0x1010), /* FIRRCA2GAIN8 */
5631 DRXJ_16TO8(0x1010), /* FIRRCA2GAIN9 */
5632 DRXJ_16TO8(0x0808), /* FIRRCA2GAIN10 */
5633 DRXJ_16TO8(0x0808), /* FIRRCA2GAIN11 */
5634 DRXJ_16TO8(0x0808), /* FIRRCA2GAIN12 */
5635 DRXJ_16TO8(0x0303), /* FIRDDM1GAIN1 */
5636 DRXJ_16TO8(0x0303), /* FIRDDM1GAIN2 */
5637 DRXJ_16TO8(0x0303), /* FIRDDM1GAIN3 */
5638 DRXJ_16TO8(0x0606), /* FIRDDM1GAIN4 */
5639 DRXJ_16TO8(0x0606), /* FIRDDM1GAIN5 */
5640 DRXJ_16TO8(0x0606), /* FIRDDM1GAIN6 */
5641 DRXJ_16TO8(0x0606), /* FIRDDM1GAIN7 */
5642 DRXJ_16TO8(0x0606), /* FIRDDM1GAIN8 */
5643 DRXJ_16TO8(0x0606), /* FIRDDM1GAIN9 */
5644 DRXJ_16TO8(0x0303), /* FIRDDM1GAIN10 */
5645 DRXJ_16TO8(0x0303), /* FIRDDM1GAIN11 */
5646 DRXJ_16TO8(0x0303), /* FIRDDM1GAIN12 */
5647 DRXJ_16TO8(0x0303), /* FIRDDM2GAIN1 */
5648 DRXJ_16TO8(0x0303), /* FIRDDM2GAIN2 */
5649 DRXJ_16TO8(0x0303), /* FIRDDM2GAIN3 */
5650 DRXJ_16TO8(0x0505), /* FIRDDM2GAIN4 */
5651 DRXJ_16TO8(0x0505), /* FIRDDM2GAIN5 */
5652 DRXJ_16TO8(0x0505), /* FIRDDM2GAIN6 */
5653 DRXJ_16TO8(0x0505), /* FIRDDM2GAIN7 */
5654 DRXJ_16TO8(0x0505), /* FIRDDM2GAIN8 */
5655 DRXJ_16TO8(0x0505), /* FIRDDM2GAIN9 */
5656 DRXJ_16TO8(0x0303), /* FIRDDM2GAIN10 */
5657 DRXJ_16TO8(0x0303), /* FIRDDM2GAIN11 */
5658 DRXJ_16TO8(0x0303), /* FIRDDM2GAIN12 */
5659 DRXJ_16TO8(0x001f), /* DFETRAINLKRATIO */
5660 DRXJ_16TO8(0x01ff), /* DFERCA1TRAINLKRATIO */
5661 DRXJ_16TO8(0x01ff), /* DFERCA1DATALKRATIO */
5662 DRXJ_16TO8(0x004f), /* DFERCA2TRAINLKRATIO */
5663 DRXJ_16TO8(0x004f), /* DFERCA2DATALKRATIO */
5664 DRXJ_16TO8(0x01ff), /* DFEDDM1TRAINLKRATIO */
5665 DRXJ_16TO8(0x01ff), /* DFEDDM1DATALKRATIO */
5666 DRXJ_16TO8(0x0352), /* DFEDDM2TRAINLKRATIO */
5667 DRXJ_16TO8(0x0352), /* DFEDDM2DATALKRATIO */
5668 DRXJ_16TO8(0x0000), /* DFETRAINGAIN */
5669 DRXJ_16TO8(0x2020), /* DFERCA1GAIN */
5670 DRXJ_16TO8(0x1010), /* DFERCA2GAIN */
5671 DRXJ_16TO8(0x1818), /* DFEDDM1GAIN */
5672 DRXJ_16TO8(0x1212) /* DFEDDM2GAIN */
5673 };
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005674
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005675 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005676 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005677 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005678 pr_err("error %d\n", rc);
5679 goto rw_error;
5680 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005681 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005682 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005683 pr_err("error %d\n", rc);
5684 goto rw_error;
5685 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005686
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005687 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005688rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005689 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005690}
5691
5692/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005693* \fn int set_vsb()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005694* \brief Set 8VSB demod.
5695* \param demod instance of demodulator.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03005696* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005697*
5698*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03005699static int set_vsb(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005700{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005701 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005702 int rc;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03005703 struct drx_common_attr *common_attr = NULL;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03005704 struct drxjscu_cmd cmd_scu;
5705 struct drxj_data *ext_attr = NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005706 u16 cmd_result = 0;
5707 u16 cmd_param = 0;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03005708 const u8 vsb_taps_re[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005709 DRXJ_16TO8(-2), /* re0 */
5710 DRXJ_16TO8(4), /* re1 */
5711 DRXJ_16TO8(1), /* re2 */
5712 DRXJ_16TO8(-4), /* re3 */
5713 DRXJ_16TO8(1), /* re4 */
5714 DRXJ_16TO8(4), /* re5 */
5715 DRXJ_16TO8(-3), /* re6 */
5716 DRXJ_16TO8(-3), /* re7 */
5717 DRXJ_16TO8(6), /* re8 */
5718 DRXJ_16TO8(1), /* re9 */
5719 DRXJ_16TO8(-9), /* re10 */
5720 DRXJ_16TO8(3), /* re11 */
5721 DRXJ_16TO8(12), /* re12 */
5722 DRXJ_16TO8(-9), /* re13 */
5723 DRXJ_16TO8(-15), /* re14 */
5724 DRXJ_16TO8(17), /* re15 */
5725 DRXJ_16TO8(19), /* re16 */
5726 DRXJ_16TO8(-29), /* re17 */
5727 DRXJ_16TO8(-22), /* re18 */
5728 DRXJ_16TO8(45), /* re19 */
5729 DRXJ_16TO8(25), /* re20 */
5730 DRXJ_16TO8(-70), /* re21 */
5731 DRXJ_16TO8(-28), /* re22 */
5732 DRXJ_16TO8(111), /* re23 */
5733 DRXJ_16TO8(30), /* re24 */
5734 DRXJ_16TO8(-201), /* re25 */
5735 DRXJ_16TO8(-31), /* re26 */
5736 DRXJ_16TO8(629) /* re27 */
5737 };
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005738
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005739 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03005740 common_attr = (struct drx_common_attr *) demod->my_common_attr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03005741 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005742
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005743 /* stop all comm_exec */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005744 rc = drxj_dap_write_reg16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005745 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005746 pr_err("error %d\n", rc);
5747 goto rw_error;
5748 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005749 rc = drxj_dap_write_reg16(dev_addr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005750 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005751 pr_err("error %d\n", rc);
5752 goto rw_error;
5753 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005754 rc = drxj_dap_write_reg16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005755 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005756 pr_err("error %d\n", rc);
5757 goto rw_error;
5758 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005759 rc = drxj_dap_write_reg16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005760 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005761 pr_err("error %d\n", rc);
5762 goto rw_error;
5763 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005764 rc = drxj_dap_write_reg16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005765 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005766 pr_err("error %d\n", rc);
5767 goto rw_error;
5768 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005769 rc = drxj_dap_write_reg16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005770 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005771 pr_err("error %d\n", rc);
5772 goto rw_error;
5773 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005774 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005775 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005776 pr_err("error %d\n", rc);
5777 goto rw_error;
5778 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005779
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005780 /* reset demodulator */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005781 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005782 | SCU_RAM_COMMAND_CMD_DEMOD_RESET;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005783 cmd_scu.parameter_len = 0;
5784 cmd_scu.result_len = 1;
5785 cmd_scu.parameter = NULL;
5786 cmd_scu.result = &cmd_result;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005787 rc = scu_command(dev_addr, &cmd_scu);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005788 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005789 pr_err("error %d\n", rc);
5790 goto rw_error;
5791 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005792
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005793 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_DCF_BYPASS__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005794 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005795 pr_err("error %d\n", rc);
5796 goto rw_error;
5797 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005798 rc = drxj_dap_write_reg16(dev_addr, IQM_FS_ADJ_SEL__A, IQM_FS_ADJ_SEL_B_VSB, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005799 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005800 pr_err("error %d\n", rc);
5801 goto rw_error;
5802 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005803 rc = drxj_dap_write_reg16(dev_addr, IQM_RC_ADJ_SEL__A, IQM_RC_ADJ_SEL_B_VSB, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005804 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005805 pr_err("error %d\n", rc);
5806 goto rw_error;
5807 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005808 ext_attr->iqm_rc_rate_ofs = 0x00AD0D79;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005809 rc = drxdap_fasi_write_reg32(dev_addr, IQM_RC_RATE_OFS_LO__A, ext_attr->iqm_rc_rate_ofs, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005810 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005811 pr_err("error %d\n", rc);
5812 goto rw_error;
5813 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005814 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CFAGC_GAINSHIFT__A, 4, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005815 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005816 pr_err("error %d\n", rc);
5817 goto rw_error;
5818 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005819 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CYGN1TRK__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005820 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005821 pr_err("error %d\n", rc);
5822 goto rw_error;
5823 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005824
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005825 rc = drxj_dap_write_reg16(dev_addr, IQM_RC_CROUT_ENA__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005826 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005827 pr_err("error %d\n", rc);
5828 goto rw_error;
5829 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005830 rc = drxj_dap_write_reg16(dev_addr, IQM_RC_STRETCH__A, 28, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005831 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005832 pr_err("error %d\n", rc);
5833 goto rw_error;
5834 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005835 rc = drxj_dap_write_reg16(dev_addr, IQM_RT_ACTIVE__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005836 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005837 pr_err("error %d\n", rc);
5838 goto rw_error;
5839 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005840 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_SYMMETRIC__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005841 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005842 pr_err("error %d\n", rc);
5843 goto rw_error;
5844 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005845 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_MIDTAP__A, 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005846 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005847 pr_err("error %d\n", rc);
5848 goto rw_error;
5849 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005850 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_OUT_ENA__A, IQM_CF_OUT_ENA_VSB__M, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005851 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005852 pr_err("error %d\n", rc);
5853 goto rw_error;
5854 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005855 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_SCALE__A, 1393, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005856 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005857 pr_err("error %d\n", rc);
5858 goto rw_error;
5859 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005860 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_SCALE_SH__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005861 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005862 pr_err("error %d\n", rc);
5863 goto rw_error;
5864 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005865 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_POW_MEAS_LEN__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005866 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005867 pr_err("error %d\n", rc);
5868 goto rw_error;
5869 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005870
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005871 rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_RE0__A, sizeof(vsb_taps_re), ((u8 *)vsb_taps_re), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005872 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005873 pr_err("error %d\n", rc);
5874 goto rw_error;
5875 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005876 rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_IM0__A, sizeof(vsb_taps_re), ((u8 *)vsb_taps_re), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005877 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005878 pr_err("error %d\n", rc);
5879 goto rw_error;
5880 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005881
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005882 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_BNTHRESH__A, 330, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005883 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005884 pr_err("error %d\n", rc);
5885 goto rw_error;
5886 } /* set higher threshold */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005887 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CLPLASTNUM__A, 90, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005888 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005889 pr_err("error %d\n", rc);
5890 goto rw_error;
5891 } /* burst detection on */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005892 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_SNRTH_RCA1__A, 0x0042, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005893 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005894 pr_err("error %d\n", rc);
5895 goto rw_error;
5896 } /* drop thresholds by 1 dB */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005897 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_SNRTH_RCA2__A, 0x0053, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005898 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005899 pr_err("error %d\n", rc);
5900 goto rw_error;
5901 } /* drop thresholds by 2 dB */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005902 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_EQCTRL__A, 0x1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005903 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005904 pr_err("error %d\n", rc);
5905 goto rw_error;
5906 } /* cma on */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005907 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_GPIO__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005908 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005909 pr_err("error %d\n", rc);
5910 goto rw_error;
5911 } /* GPIO */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005912
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005913 /* Initialize the FEC Subsystem */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005914 rc = drxj_dap_write_reg16(dev_addr, FEC_TOP_ANNEX__A, FEC_TOP_ANNEX_D, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005915 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005916 pr_err("error %d\n", rc);
5917 goto rw_error;
5918 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005919 {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005920 u16 fec_oc_snc_mode = 0;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005921 rc = drxj_dap_read_reg16(dev_addr, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005922 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005923 pr_err("error %d\n", rc);
5924 goto rw_error;
5925 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005926 /* output data even when not locked */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005927 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_MODE__A, fec_oc_snc_mode | FEC_OC_SNC_MODE_UNLOCK_ENABLE__M, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005928 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005929 pr_err("error %d\n", rc);
5930 goto rw_error;
5931 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005932 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005933
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005934 /* set clip */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005935 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_CLP_LEN__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005936 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005937 pr_err("error %d\n", rc);
5938 goto rw_error;
5939 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005940 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_CLP_TH__A, 470, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005941 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005942 pr_err("error %d\n", rc);
5943 goto rw_error;
5944 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005945 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_SNS_LEN__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005946 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005947 pr_err("error %d\n", rc);
5948 goto rw_error;
5949 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005950 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_SNRTH_PT__A, 0xD4, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005951 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005952 pr_err("error %d\n", rc);
5953 goto rw_error;
5954 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005955 /* no transparent, no A&C framing; parity is set in mpegoutput */
5956 {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03005957 u16 fec_oc_reg_mode = 0;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005958 rc = drxj_dap_read_reg16(dev_addr, FEC_OC_MODE__A, &fec_oc_reg_mode, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005959 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005960 pr_err("error %d\n", rc);
5961 goto rw_error;
5962 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005963 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005964 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005965 pr_err("error %d\n", rc);
5966 goto rw_error;
5967 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005968 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005969
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005970 rc = drxj_dap_write_reg16(dev_addr, FEC_DI_TIMEOUT_LO__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005971 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005972 pr_err("error %d\n", rc);
5973 goto rw_error;
5974 } /* timeout counter for restarting */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005975 rc = drxj_dap_write_reg16(dev_addr, FEC_DI_TIMEOUT_HI__A, 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005976 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005977 pr_err("error %d\n", rc);
5978 goto rw_error;
5979 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005980 rc = drxj_dap_write_reg16(dev_addr, FEC_RS_MODE__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005981 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005982 pr_err("error %d\n", rc);
5983 goto rw_error;
5984 } /* bypass disabled */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005985 /* initialize RS packet error measurement parameters */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005986 rc = drxj_dap_write_reg16(dev_addr, FEC_RS_MEASUREMENT_PERIOD__A, FEC_RS_MEASUREMENT_PERIOD, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005987 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005988 pr_err("error %d\n", rc);
5989 goto rw_error;
5990 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005991 rc = drxj_dap_write_reg16(dev_addr, FEC_RS_MEASUREMENT_PRESCALE__A, FEC_RS_MEASUREMENT_PRESCALE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005992 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03005993 pr_err("error %d\n", rc);
5994 goto rw_error;
5995 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03005996
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03005997 /* init measurement period of MER/SER */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03005998 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_MEASUREMENT_PERIOD__A, VSB_TOP_MEASUREMENT_PERIOD, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03005999 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006000 pr_err("error %d\n", rc);
6001 goto rw_error;
6002 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006003 rc = drxdap_fasi_write_reg32(dev_addr, SCU_RAM_FEC_ACCUM_CW_CORRECTED_LO__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006004 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006005 pr_err("error %d\n", rc);
6006 goto rw_error;
6007 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006008 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_FEC_MEAS_COUNT__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006009 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006010 pr_err("error %d\n", rc);
6011 goto rw_error;
6012 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006013 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006014 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006015 pr_err("error %d\n", rc);
6016 goto rw_error;
6017 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006018
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006019 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CKGN1TRK__A, 128, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006020 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006021 pr_err("error %d\n", rc);
6022 goto rw_error;
6023 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006024 /* B-Input to ADC, PGA+filter in standby */
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03006025 if (!ext_attr->has_lna) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006026 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_AMUX__A, 0x02, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006027 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006028 pr_err("error %d\n", rc);
6029 goto rw_error;
6030 }
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03006031 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006032
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006033 /* turn on IQMAF. It has to be in front of setAgc**() */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006034 rc = set_iqm_af(demod, true);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006035 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006036 pr_err("error %d\n", rc);
6037 goto rw_error;
6038 }
6039 rc = adc_synchronization(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006040 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006041 pr_err("error %d\n", rc);
6042 goto rw_error;
6043 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006044
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006045 rc = init_agc(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006046 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006047 pr_err("error %d\n", rc);
6048 goto rw_error;
6049 }
6050 rc = set_agc_if(demod, &(ext_attr->vsb_if_agc_cfg), false);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006051 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006052 pr_err("error %d\n", rc);
6053 goto rw_error;
6054 }
6055 rc = set_agc_rf(demod, &(ext_attr->vsb_rf_agc_cfg), false);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006056 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006057 pr_err("error %d\n", rc);
6058 goto rw_error;
6059 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006060 {
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03006061 /* TODO fix this, store a struct drxj_cfg_afe_gain structure in struct drxj_data instead
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006062 of only the gain */
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03006063 struct drxj_cfg_afe_gain vsb_pga_cfg = { DRX_STANDARD_8VSB, 0 };
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006064
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006065 vsb_pga_cfg.gain = ext_attr->vsb_pga_cfg;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006066 rc = ctrl_set_cfg_afe_gain(demod, &vsb_pga_cfg);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006067 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006068 pr_err("error %d\n", rc);
6069 goto rw_error;
6070 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006071 }
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006072 rc = ctrl_set_cfg_pre_saw(demod, &(ext_attr->vsb_pre_saw_cfg));
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006073 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006074 pr_err("error %d\n", rc);
6075 goto rw_error;
6076 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006077
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006078 /* Mpeg output has to be in front of FEC active */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006079 rc = set_mpegtei_handling(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006080 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006081 pr_err("error %d\n", rc);
6082 goto rw_error;
6083 }
6084 rc = bit_reverse_mpeg_output(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006085 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006086 pr_err("error %d\n", rc);
6087 goto rw_error;
6088 }
6089 rc = set_mpeg_start_width(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006090 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006091 pr_err("error %d\n", rc);
6092 goto rw_error;
6093 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006094 {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006095 /* TODO: move to set_standard after hardware reset value problem is solved */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006096 /* Configure initial MPEG output */
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03006097 struct drx_cfg_mpeg_output cfg_mpeg_output;
Mauro Carvalho Chehab41b5cc02014-03-02 11:01:11 -03006098
6099 memcpy(&cfg_mpeg_output, &common_attr->mpeg_cfg, sizeof(cfg_mpeg_output));
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006100 cfg_mpeg_output.enable_mpeg_output = true;
Mauro Carvalho Chehab41b5cc02014-03-02 11:01:11 -03006101
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006102 rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006103 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006104 pr_err("error %d\n", rc);
6105 goto rw_error;
6106 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006107 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006108
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006109 /* TBD: what parameters should be set */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006110 cmd_param = 0x00; /* Default mode AGC on, etc */
6111 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006112 | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006113 cmd_scu.parameter_len = 1;
6114 cmd_scu.result_len = 1;
6115 cmd_scu.parameter = &cmd_param;
6116 cmd_scu.result = &cmd_result;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006117 rc = scu_command(dev_addr, &cmd_scu);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006118 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006119 pr_err("error %d\n", rc);
6120 goto rw_error;
6121 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006122
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006123 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_BEAGC_GAINSHIFT__A, 0x0004, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006124 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006125 pr_err("error %d\n", rc);
6126 goto rw_error;
6127 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006128 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_SNRTH_PT__A, 0x00D2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006129 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006130 pr_err("error %d\n", rc);
6131 goto rw_error;
6132 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006133 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_SYSSMTRNCTRL__A, VSB_TOP_SYSSMTRNCTRL__PRE | VSB_TOP_SYSSMTRNCTRL_NCOTIMEOUTCNTEN__M, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006134 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006135 pr_err("error %d\n", rc);
6136 goto rw_error;
6137 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006138 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_BEDETCTRL__A, 0x142, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006139 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006140 pr_err("error %d\n", rc);
6141 goto rw_error;
6142 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006143 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_LBAGCREFLVL__A, 640, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006144 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006145 pr_err("error %d\n", rc);
6146 goto rw_error;
6147 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006148 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CYGN1ACQ__A, 4, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006149 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006150 pr_err("error %d\n", rc);
6151 goto rw_error;
6152 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006153 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CYGN1TRK__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006154 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006155 pr_err("error %d\n", rc);
6156 goto rw_error;
6157 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006158 rc = drxj_dap_write_reg16(dev_addr, VSB_TOP_CYGN2TRK__A, 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006159 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006160 pr_err("error %d\n", rc);
6161 goto rw_error;
6162 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006163
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006164 /* start demodulator */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006165 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006166 | SCU_RAM_COMMAND_CMD_DEMOD_START;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006167 cmd_scu.parameter_len = 0;
6168 cmd_scu.result_len = 1;
6169 cmd_scu.parameter = NULL;
6170 cmd_scu.result = &cmd_result;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006171 rc = scu_command(dev_addr, &cmd_scu);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006172 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006173 pr_err("error %d\n", rc);
6174 goto rw_error;
6175 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006176
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006177 rc = drxj_dap_write_reg16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_ACTIVE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006178 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006179 pr_err("error %d\n", rc);
6180 goto rw_error;
6181 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006182 rc = drxj_dap_write_reg16(dev_addr, VSB_COMM_EXEC__A, VSB_COMM_EXEC_ACTIVE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006183 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006184 pr_err("error %d\n", rc);
6185 goto rw_error;
6186 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006187 rc = drxj_dap_write_reg16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006188 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006189 pr_err("error %d\n", rc);
6190 goto rw_error;
6191 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006192
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006193 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006194rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006195 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006196}
6197
6198/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006199* \fn static short get_vsb_post_rs_pck_err(struct i2c_device_addr *dev_addr, u16 *PckErrs)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006200* \brief Get the values of packet error in 8VSB mode
6201* \return Error code
6202*/
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03006203static int get_vsb_post_rs_pck_err(struct i2c_device_addr *dev_addr,
Mauro Carvalho Chehabd5915902014-03-10 08:22:34 -03006204 u32 *pck_errs, u32 *pck_count)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006205{
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006206 int rc;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03006207 u16 data = 0;
6208 u16 period = 0;
6209 u16 prescale = 0;
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -03006210 u16 packet_errors_mant = 0;
6211 u16 packet_errors_exp = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006212
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006213 rc = drxj_dap_read_reg16(dev_addr, FEC_RS_NR_FAILURES__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006214 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006215 pr_err("error %d\n", rc);
6216 goto rw_error;
6217 }
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -03006218 packet_errors_mant = data & FEC_RS_NR_FAILURES_FIXED_MANT__M;
6219 packet_errors_exp = (data & FEC_RS_NR_FAILURES_EXP__M)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006220 >> FEC_RS_NR_FAILURES_EXP__B;
6221 period = FEC_RS_MEASUREMENT_PERIOD;
6222 prescale = FEC_RS_MEASUREMENT_PRESCALE;
6223 /* packet error rate = (error packet number) per second */
6224 /* 77.3 us is time for per packet */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006225 if (period * prescale == 0) {
6226 pr_err("error: period and/or prescale is zero!\n");
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006227 return -EIO;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006228 }
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03006229 *pck_errs = packet_errors_mant * (1 << packet_errors_exp);
6230 *pck_count = period * prescale * 77;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006231
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006232 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006233rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006234 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006235}
6236
6237/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006238* \fn static short GetVSBBer(struct i2c_device_addr *dev_addr, u32 *ber)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006239* \brief Get the values of ber in VSB mode
6240* \return Error code
6241*/
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03006242static int get_vs_bpost_viterbi_ber(struct i2c_device_addr *dev_addr,
6243 u32 *ber, u32 *cnt)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006244{
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006245 int rc;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03006246 u16 data = 0;
6247 u16 period = 0;
6248 u16 prescale = 0;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006249 u16 bit_errors_mant = 0;
6250 u16 bit_errors_exp = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006251
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006252 rc = drxj_dap_read_reg16(dev_addr, FEC_RS_NR_BIT_ERRORS__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006253 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006254 pr_err("error %d\n", rc);
6255 goto rw_error;
6256 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006257 period = FEC_RS_MEASUREMENT_PERIOD;
6258 prescale = FEC_RS_MEASUREMENT_PRESCALE;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006259
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006260 bit_errors_mant = data & FEC_RS_NR_BIT_ERRORS_FIXED_MANT__M;
6261 bit_errors_exp = (data & FEC_RS_NR_BIT_ERRORS_EXP__M)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006262 >> FEC_RS_NR_BIT_ERRORS_EXP__B;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006263
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03006264 *cnt = period * prescale * 207 * ((bit_errors_exp > 2) ? 1 : 8);
6265
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006266 if (((bit_errors_mant << bit_errors_exp) >> 3) > 68700)
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03006267 *ber = (*cnt) * 26570;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006268 else {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006269 if (period * prescale == 0) {
6270 pr_err("error: period and/or prescale is zero!\n");
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006271 return -EIO;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006272 }
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03006273 *ber = bit_errors_mant << ((bit_errors_exp > 2) ?
6274 (bit_errors_exp - 3) : bit_errors_exp);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006275 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006276
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006277 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006278rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006279 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006280}
6281
6282/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006283* \fn static short get_vs_bpre_viterbi_ber(struct i2c_device_addr *dev_addr, u32 *ber)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006284* \brief Get the values of ber in VSB mode
6285* \return Error code
6286*/
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03006287static int get_vs_bpre_viterbi_ber(struct i2c_device_addr *dev_addr,
6288 u32 *ber, u32 *cnt)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006289{
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03006290 u16 data = 0;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006291 int rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006292
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006293 rc = drxj_dap_read_reg16(dev_addr, VSB_TOP_NR_SYM_ERRS__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006294 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006295 pr_err("error %d\n", rc);
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03006296 return -EIO;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006297 }
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03006298 *ber = data;
6299 *cnt = VSB_TOP_MEASUREMENT_PERIOD * SYMBOLS_PER_SEGMENT;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006300
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006301 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006302}
6303
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006304/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006305* \fn static int get_vsbmer(struct i2c_device_addr *dev_addr, u16 *mer)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006306* \brief Get the values of MER
6307* \return Error code
6308*/
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006309static int get_vsbmer(struct i2c_device_addr *dev_addr, u16 *mer)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006310{
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006311 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006312 u16 data_hi = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006313
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006314 rc = drxj_dap_read_reg16(dev_addr, VSB_TOP_ERR_ENERGY_H__A, &data_hi, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006315 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006316 pr_err("error %d\n", rc);
6317 goto rw_error;
6318 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006319 *mer =
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006320 (u16) (log1_times100(21504) - log1_times100((data_hi << 6) / 52));
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006321
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006322 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006323rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006324 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006325}
6326
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006327
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006328/*============================================================================*/
6329/*== END 8VSB DATAPATH FUNCTIONS ==*/
6330/*============================================================================*/
6331
6332/*============================================================================*/
6333/*============================================================================*/
6334/*== QAM DATAPATH FUNCTIONS ==*/
6335/*============================================================================*/
6336/*============================================================================*/
6337
6338/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006339* \fn int power_down_qam ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006340* \brief Powr down QAM related blocks.
6341* \param demod instance of demodulator.
6342* \param channel pointer to channel data.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03006343* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006344*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03006345static int power_down_qam(struct drx_demod_instance *demod, bool primary)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006346{
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03006347 struct drxjscu_cmd cmd_scu = { /* command */ 0,
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006348 /* parameter_len */ 0,
6349 /* result_len */ 0,
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006350 /* *parameter */ NULL,
6351 /* *result */ NULL
6352 };
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006353 int rc;
Mauro Carvalho Chehab4d7bb0e2014-01-16 11:49:13 -03006354 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03006355 struct drx_cfg_mpeg_output cfg_mpeg_output;
Mauro Carvalho Chehab41b5cc02014-03-02 11:01:11 -03006356 struct drx_common_attr *common_attr = demod->my_common_attr;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006357 u16 cmd_result = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006358
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006359 /*
6360 STOP demodulator
6361 resets IQM, QAM and FEC HW blocks
6362 */
6363 /* stop all comm_exec */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006364 rc = drxj_dap_write_reg16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006365 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006366 pr_err("error %d\n", rc);
6367 goto rw_error;
6368 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006369 rc = drxj_dap_write_reg16(dev_addr, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006370 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006371 pr_err("error %d\n", rc);
6372 goto rw_error;
6373 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006374
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006375 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006376 SCU_RAM_COMMAND_CMD_DEMOD_STOP;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006377 cmd_scu.parameter_len = 0;
6378 cmd_scu.result_len = 1;
6379 cmd_scu.parameter = NULL;
6380 cmd_scu.result = &cmd_result;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006381 rc = scu_command(dev_addr, &cmd_scu);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006382 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006383 pr_err("error %d\n", rc);
6384 goto rw_error;
6385 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006386
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03006387 if (primary) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006388 rc = drxj_dap_write_reg16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006389 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006390 pr_err("error %d\n", rc);
6391 goto rw_error;
6392 }
6393 rc = set_iqm_af(demod, false);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006394 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006395 pr_err("error %d\n", rc);
6396 goto rw_error;
6397 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006398 } else {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006399 rc = drxj_dap_write_reg16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006400 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006401 pr_err("error %d\n", rc);
6402 goto rw_error;
6403 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006404 rc = drxj_dap_write_reg16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006405 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006406 pr_err("error %d\n", rc);
6407 goto rw_error;
6408 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006409 rc = drxj_dap_write_reg16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006410 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006411 pr_err("error %d\n", rc);
6412 goto rw_error;
6413 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006414 rc = drxj_dap_write_reg16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006415 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006416 pr_err("error %d\n", rc);
6417 goto rw_error;
6418 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006419 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006420 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006421 pr_err("error %d\n", rc);
6422 goto rw_error;
6423 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006424 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006425
Mauro Carvalho Chehab41b5cc02014-03-02 11:01:11 -03006426 memcpy(&cfg_mpeg_output, &common_attr->mpeg_cfg, sizeof(cfg_mpeg_output));
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006427 cfg_mpeg_output.enable_mpeg_output = false;
Mauro Carvalho Chehab41b5cc02014-03-02 11:01:11 -03006428
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006429 rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006430 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006431 pr_err("error %d\n", rc);
6432 goto rw_error;
6433 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006434
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006435 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006436rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006437 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006438}
6439
6440/*============================================================================*/
6441
6442/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006443* \fn int set_qam_measurement ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006444* \brief Setup of the QAM Measuremnt intervals for signal quality
6445* \param demod instance of demod.
6446* \param constellation current constellation.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03006447* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006448*
6449* NOTE:
6450* Take into account that for certain settings the errorcounters can overflow.
6451* The implementation does not check this.
6452*
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006453* TODO: overriding the ext_attr->fec_bits_desired by constellation dependent
6454* constants to get a measurement period of approx. 1 sec. Remove fec_bits_desired
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006455* field ?
6456*
6457*/
6458#ifndef DRXJ_VSB_ONLY
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03006459static int
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03006460set_qam_measurement(struct drx_demod_instance *demod,
Mauro Carvalho Chehab22892262014-01-16 11:28:52 -03006461 enum drx_modulation constellation, u32 symbol_rate)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006462{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006463 struct i2c_device_addr *dev_addr = NULL; /* device address for I2C writes */
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03006464 struct drxj_data *ext_attr = NULL; /* Global data container for DRXJ specif data */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006465 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006466 u32 fec_bits_desired = 0; /* BER accounting period */
6467 u16 fec_rs_plen = 0; /* defines RS BER measurement period */
6468 u16 fec_rs_prescale = 0; /* ReedSolomon Measurement Prescale */
6469 u32 fec_rs_period = 0; /* Value for corresponding I2C register */
6470 u32 fec_rs_bit_cnt = 0; /* Actual precise amount of bits */
6471 u32 fec_oc_snc_fail_period = 0; /* Value for corresponding I2C register */
6472 u32 qam_vd_period = 0; /* Value for corresponding I2C register */
6473 u32 qam_vd_bit_cnt = 0; /* Actual precise amount of bits */
6474 u16 fec_vd_plen = 0; /* no of trellis symbols: VD SER measur period */
6475 u16 qam_vd_prescale = 0; /* Viterbi Measurement Prescale */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006476
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006477 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03006478 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006479
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006480 fec_bits_desired = ext_attr->fec_bits_desired;
6481 fec_rs_prescale = ext_attr->fec_rs_prescale;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006482
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006483 switch (constellation) {
6484 case DRX_CONSTELLATION_QAM16:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006485 fec_bits_desired = 4 * symbol_rate;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006486 break;
6487 case DRX_CONSTELLATION_QAM32:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006488 fec_bits_desired = 5 * symbol_rate;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006489 break;
6490 case DRX_CONSTELLATION_QAM64:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006491 fec_bits_desired = 6 * symbol_rate;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006492 break;
6493 case DRX_CONSTELLATION_QAM128:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006494 fec_bits_desired = 7 * symbol_rate;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006495 break;
6496 case DRX_CONSTELLATION_QAM256:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006497 fec_bits_desired = 8 * symbol_rate;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006498 break;
6499 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006500 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006501 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006502
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006503 /* Parameters for Reed-Solomon Decoder */
6504 /* fecrs_period = (int)ceil(FEC_BITS_DESIRED/(fecrs_prescale*plen)) */
6505 /* rs_bit_cnt = fecrs_period*fecrs_prescale*plen */
6506 /* result is within 32 bit arithmetic -> */
6507 /* no need for mult or frac functions */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006508
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006509 /* TODO: use constant instead of calculation and remove the fec_rs_plen in ext_attr */
6510 switch (ext_attr->standard) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006511 case DRX_STANDARD_ITU_A:
6512 case DRX_STANDARD_ITU_C:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006513 fec_rs_plen = 204 * 8;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006514 break;
6515 case DRX_STANDARD_ITU_B:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006516 fec_rs_plen = 128 * 7;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006517 break;
6518 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006519 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006520 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006521
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006522 ext_attr->fec_rs_plen = fec_rs_plen; /* for getSigQual */
6523 fec_rs_bit_cnt = fec_rs_prescale * fec_rs_plen; /* temp storage */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006524 if (fec_rs_bit_cnt == 0) {
6525 pr_err("error: fec_rs_bit_cnt is zero!\n");
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006526 return -EIO;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006527 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006528 fec_rs_period = fec_bits_desired / fec_rs_bit_cnt + 1; /* ceil */
6529 if (ext_attr->standard != DRX_STANDARD_ITU_B)
6530 fec_oc_snc_fail_period = fec_rs_period;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006531
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006532 /* limit to max 16 bit value (I2C register width) if needed */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006533 if (fec_rs_period > 0xFFFF)
6534 fec_rs_period = 0xFFFF;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006535
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006536 /* write corresponding registers */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006537 switch (ext_attr->standard) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006538 case DRX_STANDARD_ITU_A:
6539 case DRX_STANDARD_ITU_C:
6540 break;
6541 case DRX_STANDARD_ITU_B:
6542 switch (constellation) {
6543 case DRX_CONSTELLATION_QAM64:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006544 fec_rs_period = 31581;
6545 fec_oc_snc_fail_period = 17932;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006546 break;
6547 case DRX_CONSTELLATION_QAM256:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006548 fec_rs_period = 45446;
6549 fec_oc_snc_fail_period = 25805;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006550 break;
6551 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006552 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006553 }
6554 break;
6555 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006556 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006557 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006558
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006559 rc = drxj_dap_write_reg16(dev_addr, FEC_OC_SNC_FAIL_PERIOD__A, (u16)fec_oc_snc_fail_period, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006560 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006561 pr_err("error %d\n", rc);
6562 goto rw_error;
6563 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006564 rc = drxj_dap_write_reg16(dev_addr, FEC_RS_MEASUREMENT_PERIOD__A, (u16)fec_rs_period, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006565 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006566 pr_err("error %d\n", rc);
6567 goto rw_error;
6568 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006569 rc = drxj_dap_write_reg16(dev_addr, FEC_RS_MEASUREMENT_PRESCALE__A, fec_rs_prescale, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006570 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006571 pr_err("error %d\n", rc);
6572 goto rw_error;
6573 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006574 ext_attr->fec_rs_period = (u16) fec_rs_period;
6575 ext_attr->fec_rs_prescale = fec_rs_prescale;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006576 rc = drxdap_fasi_write_reg32(dev_addr, SCU_RAM_FEC_ACCUM_CW_CORRECTED_LO__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006577 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006578 pr_err("error %d\n", rc);
6579 goto rw_error;
6580 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006581 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_FEC_MEAS_COUNT__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006582 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006583 pr_err("error %d\n", rc);
6584 goto rw_error;
6585 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006586 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006587 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006588 pr_err("error %d\n", rc);
6589 goto rw_error;
6590 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006591
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006592 if (ext_attr->standard == DRX_STANDARD_ITU_B) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006593 /* Parameters for Viterbi Decoder */
6594 /* qamvd_period = (int)ceil(FEC_BITS_DESIRED/ */
6595 /* (qamvd_prescale*plen*(qam_constellation+1))) */
6596 /* vd_bit_cnt = qamvd_period*qamvd_prescale*plen */
6597 /* result is within 32 bit arithmetic -> */
6598 /* no need for mult or frac functions */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006599
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006600 /* a(8 bit) * b(8 bit) = 16 bit result => mult32 not needed */
6601 fec_vd_plen = ext_attr->fec_vd_plen;
6602 qam_vd_prescale = ext_attr->qam_vd_prescale;
6603 qam_vd_bit_cnt = qam_vd_prescale * fec_vd_plen; /* temp storage */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006604
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006605 switch (constellation) {
6606 case DRX_CONSTELLATION_QAM64:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006607 /* a(16 bit) * b(4 bit) = 20 bit result => mult32 not needed */
6608 qam_vd_period =
6609 qam_vd_bit_cnt * (QAM_TOP_CONSTELLATION_QAM64 + 1)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006610 * (QAM_TOP_CONSTELLATION_QAM64 + 1);
6611 break;
6612 case DRX_CONSTELLATION_QAM256:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006613 /* a(16 bit) * b(5 bit) = 21 bit result => mult32 not needed */
6614 qam_vd_period =
6615 qam_vd_bit_cnt * (QAM_TOP_CONSTELLATION_QAM256 + 1)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006616 * (QAM_TOP_CONSTELLATION_QAM256 + 1);
6617 break;
6618 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006619 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006620 }
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006621 if (qam_vd_period == 0) {
6622 pr_err("error: qam_vd_period is zero!\n");
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006623 return -EIO;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006624 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006625 qam_vd_period = fec_bits_desired / qam_vd_period;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006626 /* limit to max 16 bit value (I2C register width) if needed */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006627 if (qam_vd_period > 0xFFFF)
6628 qam_vd_period = 0xFFFF;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006629
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006630 /* a(16 bit) * b(16 bit) = 32 bit result => mult32 not needed */
6631 qam_vd_bit_cnt *= qam_vd_period;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006632
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006633 rc = drxj_dap_write_reg16(dev_addr, QAM_VD_MEASUREMENT_PERIOD__A, (u16)qam_vd_period, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006634 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006635 pr_err("error %d\n", rc);
6636 goto rw_error;
6637 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006638 rc = drxj_dap_write_reg16(dev_addr, QAM_VD_MEASUREMENT_PRESCALE__A, qam_vd_prescale, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006639 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006640 pr_err("error %d\n", rc);
6641 goto rw_error;
6642 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006643 ext_attr->qam_vd_period = (u16) qam_vd_period;
6644 ext_attr->qam_vd_prescale = qam_vd_prescale;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006645 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006646
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006647 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006648rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006649 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006650}
6651
6652/*============================================================================*/
6653
6654/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006655* \fn int set_qam16 ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006656* \brief QAM16 specific setup
6657* \param demod instance of demod.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03006658* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006659*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03006660static int set_qam16(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006661{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006662 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006663 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006664 const u8 qam_dq_qual_fun[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006665 DRXJ_16TO8(2), /* fun0 */
6666 DRXJ_16TO8(2), /* fun1 */
6667 DRXJ_16TO8(2), /* fun2 */
6668 DRXJ_16TO8(2), /* fun3 */
6669 DRXJ_16TO8(3), /* fun4 */
6670 DRXJ_16TO8(3), /* fun5 */
6671 };
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006672 const u8 qam_eq_cma_rad[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006673 DRXJ_16TO8(13517), /* RAD0 */
6674 DRXJ_16TO8(13517), /* RAD1 */
6675 DRXJ_16TO8(13517), /* RAD2 */
6676 DRXJ_16TO8(13517), /* RAD3 */
6677 DRXJ_16TO8(13517), /* RAD4 */
6678 DRXJ_16TO8(13517), /* RAD5 */
6679 };
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006680
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006681 rc = drxdap_fasi_write_block(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun), ((u8 *)qam_dq_qual_fun), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006682 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006683 pr_err("error %d\n", rc);
6684 goto rw_error;
6685 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006686 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006687 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006688 pr_err("error %d\n", rc);
6689 goto rw_error;
6690 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006691
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006692 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 140, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006693 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006694 pr_err("error %d\n", rc);
6695 goto rw_error;
6696 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006697 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 50, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006698 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006699 pr_err("error %d\n", rc);
6700 goto rw_error;
6701 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006702 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 120, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006703 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006704 pr_err("error %d\n", rc);
6705 goto rw_error;
6706 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006707 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 230, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006708 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006709 pr_err("error %d\n", rc);
6710 goto rw_error;
6711 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006712 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 95, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006713 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006714 pr_err("error %d\n", rc);
6715 goto rw_error;
6716 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006717 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 105, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006718 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006719 pr_err("error %d\n", rc);
6720 goto rw_error;
6721 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006722
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006723 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006724 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006725 pr_err("error %d\n", rc);
6726 goto rw_error;
6727 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006728 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 56, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006729 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006730 pr_err("error %d\n", rc);
6731 goto rw_error;
6732 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006733 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006734 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006735 pr_err("error %d\n", rc);
6736 goto rw_error;
6737 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006738
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006739 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006740 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006741 pr_err("error %d\n", rc);
6742 goto rw_error;
6743 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006744 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 220, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006745 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006746 pr_err("error %d\n", rc);
6747 goto rw_error;
6748 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006749 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 25, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006750 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006751 pr_err("error %d\n", rc);
6752 goto rw_error;
6753 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006754 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 6, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006755 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006756 pr_err("error %d\n", rc);
6757 goto rw_error;
6758 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006759 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16)(-24), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006760 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006761 pr_err("error %d\n", rc);
6762 goto rw_error;
6763 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006764 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16)(-65), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006765 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006766 pr_err("error %d\n", rc);
6767 goto rw_error;
6768 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006769 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16)(-127), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006770 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006771 pr_err("error %d\n", rc);
6772 goto rw_error;
6773 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006774
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006775 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006776 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006777 pr_err("error %d\n", rc);
6778 goto rw_error;
6779 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006780 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006781 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006782 pr_err("error %d\n", rc);
6783 goto rw_error;
6784 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006785 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006786 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006787 pr_err("error %d\n", rc);
6788 goto rw_error;
6789 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006790 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006791 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006792 pr_err("error %d\n", rc);
6793 goto rw_error;
6794 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006795 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006796 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006797 pr_err("error %d\n", rc);
6798 goto rw_error;
6799 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006800 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006801 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006802 pr_err("error %d\n", rc);
6803 goto rw_error;
6804 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006805 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 10, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006806 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006807 pr_err("error %d\n", rc);
6808 goto rw_error;
6809 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006810 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 50, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006811 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006812 pr_err("error %d\n", rc);
6813 goto rw_error;
6814 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006815 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006816 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006817 pr_err("error %d\n", rc);
6818 goto rw_error;
6819 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006820 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006821 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006822 pr_err("error %d\n", rc);
6823 goto rw_error;
6824 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006825 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006826 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006827 pr_err("error %d\n", rc);
6828 goto rw_error;
6829 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006830 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006831 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006832 pr_err("error %d\n", rc);
6833 goto rw_error;
6834 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006835 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006836 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006837 pr_err("error %d\n", rc);
6838 goto rw_error;
6839 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006840 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006841 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006842 pr_err("error %d\n", rc);
6843 goto rw_error;
6844 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006845 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006846 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006847 pr_err("error %d\n", rc);
6848 goto rw_error;
6849 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006850 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 32, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006851 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006852 pr_err("error %d\n", rc);
6853 goto rw_error;
6854 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006855 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 240, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006856 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006857 pr_err("error %d\n", rc);
6858 goto rw_error;
6859 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006860 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006861 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006862 pr_err("error %d\n", rc);
6863 goto rw_error;
6864 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006865 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006866 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006867 pr_err("error %d\n", rc);
6868 goto rw_error;
6869 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006870 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 32, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006871 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006872 pr_err("error %d\n", rc);
6873 goto rw_error;
6874 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006875
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006876 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 40960, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006877 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006878 pr_err("error %d\n", rc);
6879 goto rw_error;
6880 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006881
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006882 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006883rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006884 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006885}
6886
6887/*============================================================================*/
6888
6889/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006890* \fn int set_qam32 ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006891* \brief QAM32 specific setup
6892* \param demod instance of demod.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03006893* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006894*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03006895static int set_qam32(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006896{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006897 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006898 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006899 const u8 qam_dq_qual_fun[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006900 DRXJ_16TO8(3), /* fun0 */
6901 DRXJ_16TO8(3), /* fun1 */
6902 DRXJ_16TO8(3), /* fun2 */
6903 DRXJ_16TO8(3), /* fun3 */
6904 DRXJ_16TO8(4), /* fun4 */
6905 DRXJ_16TO8(4), /* fun5 */
6906 };
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03006907 const u8 qam_eq_cma_rad[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03006908 DRXJ_16TO8(6707), /* RAD0 */
6909 DRXJ_16TO8(6707), /* RAD1 */
6910 DRXJ_16TO8(6707), /* RAD2 */
6911 DRXJ_16TO8(6707), /* RAD3 */
6912 DRXJ_16TO8(6707), /* RAD4 */
6913 DRXJ_16TO8(6707), /* RAD5 */
6914 };
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006915
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006916 rc = drxdap_fasi_write_block(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun), ((u8 *)qam_dq_qual_fun), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006917 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006918 pr_err("error %d\n", rc);
6919 goto rw_error;
6920 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006921 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006922 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006923 pr_err("error %d\n", rc);
6924 goto rw_error;
6925 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006926
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006927 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 90, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006928 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006929 pr_err("error %d\n", rc);
6930 goto rw_error;
6931 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006932 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 50, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006933 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006934 pr_err("error %d\n", rc);
6935 goto rw_error;
6936 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006937 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 100, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006938 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006939 pr_err("error %d\n", rc);
6940 goto rw_error;
6941 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006942 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 170, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006943 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006944 pr_err("error %d\n", rc);
6945 goto rw_error;
6946 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006947 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 80, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006948 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006949 pr_err("error %d\n", rc);
6950 goto rw_error;
6951 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006952 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 100, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006953 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006954 pr_err("error %d\n", rc);
6955 goto rw_error;
6956 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006957
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006958 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006959 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006960 pr_err("error %d\n", rc);
6961 goto rw_error;
6962 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006963 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 56, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006964 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006965 pr_err("error %d\n", rc);
6966 goto rw_error;
6967 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006968 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006969 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006970 pr_err("error %d\n", rc);
6971 goto rw_error;
6972 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03006973
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006974 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 12, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006975 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006976 pr_err("error %d\n", rc);
6977 goto rw_error;
6978 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006979 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 140, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006980 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006981 pr_err("error %d\n", rc);
6982 goto rw_error;
6983 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006984 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16)(-8), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006985 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006986 pr_err("error %d\n", rc);
6987 goto rw_error;
6988 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006989 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16)(-16), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006990 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006991 pr_err("error %d\n", rc);
6992 goto rw_error;
6993 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006994 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16)(-26), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03006995 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03006996 pr_err("error %d\n", rc);
6997 goto rw_error;
6998 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03006999 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16)(-56), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007000 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007001 pr_err("error %d\n", rc);
7002 goto rw_error;
7003 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007004 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16)(-86), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007005 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007006 pr_err("error %d\n", rc);
7007 goto rw_error;
7008 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007009
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007010 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007011 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007012 pr_err("error %d\n", rc);
7013 goto rw_error;
7014 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007015 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007016 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007017 pr_err("error %d\n", rc);
7018 goto rw_error;
7019 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007020 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007021 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007022 pr_err("error %d\n", rc);
7023 goto rw_error;
7024 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007025 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007026 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007027 pr_err("error %d\n", rc);
7028 goto rw_error;
7029 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007030 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007031 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007032 pr_err("error %d\n", rc);
7033 goto rw_error;
7034 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007035 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007036 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007037 pr_err("error %d\n", rc);
7038 goto rw_error;
7039 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007040 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 10, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007041 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007042 pr_err("error %d\n", rc);
7043 goto rw_error;
7044 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007045 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 50, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007046 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007047 pr_err("error %d\n", rc);
7048 goto rw_error;
7049 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007050 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007051 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007052 pr_err("error %d\n", rc);
7053 goto rw_error;
7054 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007055 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007056 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007057 pr_err("error %d\n", rc);
7058 goto rw_error;
7059 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007060 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007061 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007062 pr_err("error %d\n", rc);
7063 goto rw_error;
7064 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007065 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007066 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007067 pr_err("error %d\n", rc);
7068 goto rw_error;
7069 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007070 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007071 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007072 pr_err("error %d\n", rc);
7073 goto rw_error;
7074 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007075 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007076 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007077 pr_err("error %d\n", rc);
7078 goto rw_error;
7079 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007080 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007081 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007082 pr_err("error %d\n", rc);
7083 goto rw_error;
7084 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007085 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 32, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007086 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007087 pr_err("error %d\n", rc);
7088 goto rw_error;
7089 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007090 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 176, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007091 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007092 pr_err("error %d\n", rc);
7093 goto rw_error;
7094 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007095 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007096 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007097 pr_err("error %d\n", rc);
7098 goto rw_error;
7099 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007100 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007101 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007102 pr_err("error %d\n", rc);
7103 goto rw_error;
7104 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007105 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 8, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007106 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007107 pr_err("error %d\n", rc);
7108 goto rw_error;
7109 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007110
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007111 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 20480, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007112 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007113 pr_err("error %d\n", rc);
7114 goto rw_error;
7115 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007116
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007117 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007118rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007119 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007120}
7121
7122/*============================================================================*/
7123
7124/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007125* \fn int set_qam64 ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007126* \brief QAM64 specific setup
7127* \param demod instance of demod.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03007128* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007129*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03007130static int set_qam64(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007131{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007132 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007133 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007134 const u8 qam_dq_qual_fun[] = { /* this is hw reset value. no necessary to re-write */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03007135 DRXJ_16TO8(4), /* fun0 */
7136 DRXJ_16TO8(4), /* fun1 */
7137 DRXJ_16TO8(4), /* fun2 */
7138 DRXJ_16TO8(4), /* fun3 */
7139 DRXJ_16TO8(6), /* fun4 */
7140 DRXJ_16TO8(6), /* fun5 */
7141 };
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007142 const u8 qam_eq_cma_rad[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03007143 DRXJ_16TO8(13336), /* RAD0 */
7144 DRXJ_16TO8(12618), /* RAD1 */
7145 DRXJ_16TO8(11988), /* RAD2 */
7146 DRXJ_16TO8(13809), /* RAD3 */
7147 DRXJ_16TO8(13809), /* RAD4 */
7148 DRXJ_16TO8(15609), /* RAD5 */
7149 };
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007150
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007151 rc = drxdap_fasi_write_block(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun), ((u8 *)qam_dq_qual_fun), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007152 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007153 pr_err("error %d\n", rc);
7154 goto rw_error;
7155 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007156 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007157 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007158 pr_err("error %d\n", rc);
7159 goto rw_error;
7160 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007161
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007162 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 105, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007163 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007164 pr_err("error %d\n", rc);
7165 goto rw_error;
7166 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007167 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 60, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007168 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007169 pr_err("error %d\n", rc);
7170 goto rw_error;
7171 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007172 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 100, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007173 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007174 pr_err("error %d\n", rc);
7175 goto rw_error;
7176 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007177 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 195, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007178 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007179 pr_err("error %d\n", rc);
7180 goto rw_error;
7181 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007182 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 80, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007183 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007184 pr_err("error %d\n", rc);
7185 goto rw_error;
7186 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007187 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 84, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007188 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007189 pr_err("error %d\n", rc);
7190 goto rw_error;
7191 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007192
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007193 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007194 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007195 pr_err("error %d\n", rc);
7196 goto rw_error;
7197 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007198 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 32, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007199 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007200 pr_err("error %d\n", rc);
7201 goto rw_error;
7202 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007203 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007204 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007205 pr_err("error %d\n", rc);
7206 goto rw_error;
7207 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007208
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007209 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 12, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007210 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007211 pr_err("error %d\n", rc);
7212 goto rw_error;
7213 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007214 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 141, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007215 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007216 pr_err("error %d\n", rc);
7217 goto rw_error;
7218 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007219 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 7, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007220 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007221 pr_err("error %d\n", rc);
7222 goto rw_error;
7223 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007224 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007225 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007226 pr_err("error %d\n", rc);
7227 goto rw_error;
7228 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007229 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16)(-15), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007230 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007231 pr_err("error %d\n", rc);
7232 goto rw_error;
7233 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007234 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16)(-45), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007235 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007236 pr_err("error %d\n", rc);
7237 goto rw_error;
7238 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007239 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16)(-80), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007240 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007241 pr_err("error %d\n", rc);
7242 goto rw_error;
7243 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007244
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007245 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007246 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007247 pr_err("error %d\n", rc);
7248 goto rw_error;
7249 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007250 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007251 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007252 pr_err("error %d\n", rc);
7253 goto rw_error;
7254 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007255 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007256 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007257 pr_err("error %d\n", rc);
7258 goto rw_error;
7259 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007260 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 30, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007261 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007262 pr_err("error %d\n", rc);
7263 goto rw_error;
7264 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007265 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007266 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007267 pr_err("error %d\n", rc);
7268 goto rw_error;
7269 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007270 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007271 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007272 pr_err("error %d\n", rc);
7273 goto rw_error;
7274 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007275 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 15, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007276 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007277 pr_err("error %d\n", rc);
7278 goto rw_error;
7279 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007280 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 80, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007281 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007282 pr_err("error %d\n", rc);
7283 goto rw_error;
7284 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007285 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007286 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007287 pr_err("error %d\n", rc);
7288 goto rw_error;
7289 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007290 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007291 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007292 pr_err("error %d\n", rc);
7293 goto rw_error;
7294 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007295 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007296 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007297 pr_err("error %d\n", rc);
7298 goto rw_error;
7299 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007300 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007301 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007302 pr_err("error %d\n", rc);
7303 goto rw_error;
7304 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007305 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007306 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007307 pr_err("error %d\n", rc);
7308 goto rw_error;
7309 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007310 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007311 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007312 pr_err("error %d\n", rc);
7313 goto rw_error;
7314 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007315 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007316 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007317 pr_err("error %d\n", rc);
7318 goto rw_error;
7319 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007320 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 48, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007321 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007322 pr_err("error %d\n", rc);
7323 goto rw_error;
7324 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007325 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 160, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007326 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007327 pr_err("error %d\n", rc);
7328 goto rw_error;
7329 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007330 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007331 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007332 pr_err("error %d\n", rc);
7333 goto rw_error;
7334 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007335 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007336 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007337 pr_err("error %d\n", rc);
7338 goto rw_error;
7339 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007340 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 32, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007341 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007342 pr_err("error %d\n", rc);
7343 goto rw_error;
7344 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007345
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007346 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 43008, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007347 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007348 pr_err("error %d\n", rc);
7349 goto rw_error;
7350 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007351
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007352 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007353rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007354 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007355}
7356
7357/*============================================================================*/
7358
7359/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007360* \fn int set_qam128 ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007361* \brief QAM128 specific setup
7362* \param demod: instance of demod.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03007363* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007364*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03007365static int set_qam128(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007366{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007367 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007368 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007369 const u8 qam_dq_qual_fun[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03007370 DRXJ_16TO8(6), /* fun0 */
7371 DRXJ_16TO8(6), /* fun1 */
7372 DRXJ_16TO8(6), /* fun2 */
7373 DRXJ_16TO8(6), /* fun3 */
7374 DRXJ_16TO8(9), /* fun4 */
7375 DRXJ_16TO8(9), /* fun5 */
7376 };
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007377 const u8 qam_eq_cma_rad[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03007378 DRXJ_16TO8(6164), /* RAD0 */
7379 DRXJ_16TO8(6598), /* RAD1 */
7380 DRXJ_16TO8(6394), /* RAD2 */
7381 DRXJ_16TO8(6409), /* RAD3 */
7382 DRXJ_16TO8(6656), /* RAD4 */
7383 DRXJ_16TO8(7238), /* RAD5 */
7384 };
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007385
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007386 rc = drxdap_fasi_write_block(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun), ((u8 *)qam_dq_qual_fun), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007387 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007388 pr_err("error %d\n", rc);
7389 goto rw_error;
7390 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007391 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007392 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007393 pr_err("error %d\n", rc);
7394 goto rw_error;
7395 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007396
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007397 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 50, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007398 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007399 pr_err("error %d\n", rc);
7400 goto rw_error;
7401 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007402 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 60, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007403 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007404 pr_err("error %d\n", rc);
7405 goto rw_error;
7406 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007407 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 100, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007408 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007409 pr_err("error %d\n", rc);
7410 goto rw_error;
7411 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007412 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 140, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007413 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007414 pr_err("error %d\n", rc);
7415 goto rw_error;
7416 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007417 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 80, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007418 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007419 pr_err("error %d\n", rc);
7420 goto rw_error;
7421 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007422 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 100, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007423 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007424 pr_err("error %d\n", rc);
7425 goto rw_error;
7426 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007427
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007428 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007429 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007430 pr_err("error %d\n", rc);
7431 goto rw_error;
7432 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007433 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 32, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007434 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007435 pr_err("error %d\n", rc);
7436 goto rw_error;
7437 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007438 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007439 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007440 pr_err("error %d\n", rc);
7441 goto rw_error;
7442 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007443
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007444 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 8, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007445 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007446 pr_err("error %d\n", rc);
7447 goto rw_error;
7448 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007449 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 65, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007450 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007451 pr_err("error %d\n", rc);
7452 goto rw_error;
7453 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007454 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 5, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007455 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007456 pr_err("error %d\n", rc);
7457 goto rw_error;
7458 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007459 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007460 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007461 pr_err("error %d\n", rc);
7462 goto rw_error;
7463 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007464 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16)(-1), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007465 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007466 pr_err("error %d\n", rc);
7467 goto rw_error;
7468 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007469 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, 12, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007470 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007471 pr_err("error %d\n", rc);
7472 goto rw_error;
7473 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007474 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16)(-23), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007475 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007476 pr_err("error %d\n", rc);
7477 goto rw_error;
7478 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007479
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007480 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007481 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007482 pr_err("error %d\n", rc);
7483 goto rw_error;
7484 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007485 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007486 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007487 pr_err("error %d\n", rc);
7488 goto rw_error;
7489 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007490 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007491 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007492 pr_err("error %d\n", rc);
7493 goto rw_error;
7494 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007495 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 40, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007496 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007497 pr_err("error %d\n", rc);
7498 goto rw_error;
7499 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007500 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007501 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007502 pr_err("error %d\n", rc);
7503 goto rw_error;
7504 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007505 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007506 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007507 pr_err("error %d\n", rc);
7508 goto rw_error;
7509 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007510 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 20, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007511 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007512 pr_err("error %d\n", rc);
7513 goto rw_error;
7514 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007515 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 80, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007516 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007517 pr_err("error %d\n", rc);
7518 goto rw_error;
7519 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007520 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007521 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007522 pr_err("error %d\n", rc);
7523 goto rw_error;
7524 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007525 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007526 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007527 pr_err("error %d\n", rc);
7528 goto rw_error;
7529 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007530 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007531 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007532 pr_err("error %d\n", rc);
7533 goto rw_error;
7534 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007535 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007536 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007537 pr_err("error %d\n", rc);
7538 goto rw_error;
7539 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007540 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007541 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007542 pr_err("error %d\n", rc);
7543 goto rw_error;
7544 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007545 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007546 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007547 pr_err("error %d\n", rc);
7548 goto rw_error;
7549 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007550 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007551 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007552 pr_err("error %d\n", rc);
7553 goto rw_error;
7554 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007555 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 32, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007556 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007557 pr_err("error %d\n", rc);
7558 goto rw_error;
7559 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007560 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 144, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007561 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007562 pr_err("error %d\n", rc);
7563 goto rw_error;
7564 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007565 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007566 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007567 pr_err("error %d\n", rc);
7568 goto rw_error;
7569 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007570 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007571 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007572 pr_err("error %d\n", rc);
7573 goto rw_error;
7574 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007575 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007576 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007577 pr_err("error %d\n", rc);
7578 goto rw_error;
7579 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007580
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007581 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 20992, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007582 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007583 pr_err("error %d\n", rc);
7584 goto rw_error;
7585 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007586
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007587 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007588rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007589 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007590}
7591
7592/*============================================================================*/
7593
7594/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007595* \fn int set_qam256 ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007596* \brief QAM256 specific setup
7597* \param demod: instance of demod.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03007598* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007599*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03007600static int set_qam256(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007601{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007602 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007603 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007604 const u8 qam_dq_qual_fun[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03007605 DRXJ_16TO8(8), /* fun0 */
7606 DRXJ_16TO8(8), /* fun1 */
7607 DRXJ_16TO8(8), /* fun2 */
7608 DRXJ_16TO8(8), /* fun3 */
7609 DRXJ_16TO8(12), /* fun4 */
7610 DRXJ_16TO8(12), /* fun5 */
7611 };
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007612 const u8 qam_eq_cma_rad[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03007613 DRXJ_16TO8(12345), /* RAD0 */
7614 DRXJ_16TO8(12345), /* RAD1 */
7615 DRXJ_16TO8(13626), /* RAD2 */
7616 DRXJ_16TO8(12931), /* RAD3 */
7617 DRXJ_16TO8(14719), /* RAD4 */
7618 DRXJ_16TO8(15356), /* RAD5 */
7619 };
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007620
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007621 rc = drxdap_fasi_write_block(dev_addr, QAM_DQ_QUAL_FUN0__A, sizeof(qam_dq_qual_fun), ((u8 *)qam_dq_qual_fun), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007622 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007623 pr_err("error %d\n", rc);
7624 goto rw_error;
7625 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007626 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007627 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007628 pr_err("error %d\n", rc);
7629 goto rw_error;
7630 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007631
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007632 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RTH__A, 50, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007633 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007634 pr_err("error %d\n", rc);
7635 goto rw_error;
7636 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007637 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FTH__A, 60, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007638 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007639 pr_err("error %d\n", rc);
7640 goto rw_error;
7641 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007642 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_PTH__A, 100, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007643 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007644 pr_err("error %d\n", rc);
7645 goto rw_error;
7646 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007647 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_QTH__A, 150, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007648 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007649 pr_err("error %d\n", rc);
7650 goto rw_error;
7651 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007652 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_CTH__A, 80, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007653 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007654 pr_err("error %d\n", rc);
7655 goto rw_error;
7656 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007657 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MTH__A, 110, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007658 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007659 pr_err("error %d\n", rc);
7660 goto rw_error;
7661 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007662
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007663 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RATE_LIM__A, 40, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007664 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007665 pr_err("error %d\n", rc);
7666 goto rw_error;
7667 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007668 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_FREQ_LIM__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007669 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007670 pr_err("error %d\n", rc);
7671 goto rw_error;
7672 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007673 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_COUNT_LIM__A, 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007674 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007675 pr_err("error %d\n", rc);
7676 goto rw_error;
7677 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007678
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007679 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, 8, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007680 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007681 pr_err("error %d\n", rc);
7682 goto rw_error;
7683 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007684 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, 74, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007685 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007686 pr_err("error %d\n", rc);
7687 goto rw_error;
7688 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007689 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, 18, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007690 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007691 pr_err("error %d\n", rc);
7692 goto rw_error;
7693 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007694 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, 13, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007695 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007696 pr_err("error %d\n", rc);
7697 goto rw_error;
7698 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007699 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, 7, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007700 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007701 pr_err("error %d\n", rc);
7702 goto rw_error;
7703 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007704 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007705 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007706 pr_err("error %d\n", rc);
7707 goto rw_error;
7708 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007709 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16)(-8), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007710 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007711 pr_err("error %d\n", rc);
7712 goto rw_error;
7713 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007714
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007715 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_FINE__A, 15, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007716 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007717 pr_err("error %d\n", rc);
7718 goto rw_error;
7719 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007720 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CA_COARSE__A, 40, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007721 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007722 pr_err("error %d\n", rc);
7723 goto rw_error;
7724 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007725 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_FINE__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007726 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007727 pr_err("error %d\n", rc);
7728 goto rw_error;
7729 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007730 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_MEDIUM__A, 50, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007731 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007732 pr_err("error %d\n", rc);
7733 goto rw_error;
7734 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007735 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CP_COARSE__A, 255, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007736 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007737 pr_err("error %d\n", rc);
7738 goto rw_error;
7739 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007740 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_FINE__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007741 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007742 pr_err("error %d\n", rc);
7743 goto rw_error;
7744 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007745 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_MEDIUM__A, 25, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007746 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007747 pr_err("error %d\n", rc);
7748 goto rw_error;
7749 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007750 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CI_COARSE__A, 80, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007751 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007752 pr_err("error %d\n", rc);
7753 goto rw_error;
7754 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007755 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_FINE__A, 12, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007756 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007757 pr_err("error %d\n", rc);
7758 goto rw_error;
7759 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007760 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007761 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007762 pr_err("error %d\n", rc);
7763 goto rw_error;
7764 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007765 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EP_COARSE__A, 24, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007766 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007767 pr_err("error %d\n", rc);
7768 goto rw_error;
7769 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007770 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_FINE__A, 12, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007771 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007772 pr_err("error %d\n", rc);
7773 goto rw_error;
7774 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007775 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007776 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007777 pr_err("error %d\n", rc);
7778 goto rw_error;
7779 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007780 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_EI_COARSE__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007781 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007782 pr_err("error %d\n", rc);
7783 goto rw_error;
7784 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007785 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_FINE__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007786 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007787 pr_err("error %d\n", rc);
7788 goto rw_error;
7789 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007790 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_MEDIUM__A, 48, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007791 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007792 pr_err("error %d\n", rc);
7793 goto rw_error;
7794 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007795 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF_COARSE__A, 80, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007796 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007797 pr_err("error %d\n", rc);
7798 goto rw_error;
7799 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007800 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_FINE__A, 5, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007801 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007802 pr_err("error %d\n", rc);
7803 goto rw_error;
7804 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007805 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 15, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007806 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007807 pr_err("error %d\n", rc);
7808 goto rw_error;
7809 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007810 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_LC_CF1_COARSE__A, 16, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007811 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007812 pr_err("error %d\n", rc);
7813 goto rw_error;
7814 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007815
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03007816 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_SL_SIG_POWER__A, 43520, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007817 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007818 pr_err("error %d\n", rc);
7819 goto rw_error;
7820 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007821
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007822 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007823rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03007824 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007825}
7826
7827/*============================================================================*/
7828#define QAM_SET_OP_ALL 0x1
7829#define QAM_SET_OP_CONSTELLATION 0x2
7830#define QAM_SET_OP_SPECTRUM 0X4
7831
7832/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007833* \fn int set_qam ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007834* \brief Set QAM demod.
7835* \param demod: instance of demod.
7836* \param channel: pointer to channel data.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03007837* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007838*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03007839static int
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03007840set_qam(struct drx_demod_instance *demod,
7841 struct drx_channel *channel, s32 tuner_freq_offset, u32 op)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007842{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007843 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03007844 struct drxj_data *ext_attr = NULL;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03007845 struct drx_common_attr *common_attr = NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007846 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007847 u32 adc_frequency = 0;
7848 u32 iqm_rc_rate = 0;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03007849 u16 cmd_result = 0;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007850 u16 lc_symbol_freq = 0;
7851 u16 iqm_rc_stretch = 0;
7852 u16 set_env_parameters = 0;
7853 u16 set_param_parameters[2] = { 0 };
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03007854 struct drxjscu_cmd cmd_scu = { /* command */ 0,
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007855 /* parameter_len */ 0,
7856 /* result_len */ 0,
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03007857 /* parameter */ NULL,
7858 /* result */ NULL
7859 };
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007860 const u8 qam_a_taps[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03007861 DRXJ_16TO8(-1), /* re0 */
7862 DRXJ_16TO8(1), /* re1 */
7863 DRXJ_16TO8(1), /* re2 */
7864 DRXJ_16TO8(-1), /* re3 */
7865 DRXJ_16TO8(-1), /* re4 */
7866 DRXJ_16TO8(2), /* re5 */
7867 DRXJ_16TO8(1), /* re6 */
7868 DRXJ_16TO8(-2), /* re7 */
7869 DRXJ_16TO8(0), /* re8 */
7870 DRXJ_16TO8(3), /* re9 */
7871 DRXJ_16TO8(-1), /* re10 */
7872 DRXJ_16TO8(-3), /* re11 */
7873 DRXJ_16TO8(4), /* re12 */
7874 DRXJ_16TO8(1), /* re13 */
7875 DRXJ_16TO8(-8), /* re14 */
7876 DRXJ_16TO8(4), /* re15 */
7877 DRXJ_16TO8(13), /* re16 */
7878 DRXJ_16TO8(-13), /* re17 */
7879 DRXJ_16TO8(-19), /* re18 */
7880 DRXJ_16TO8(28), /* re19 */
7881 DRXJ_16TO8(25), /* re20 */
7882 DRXJ_16TO8(-53), /* re21 */
7883 DRXJ_16TO8(-31), /* re22 */
7884 DRXJ_16TO8(96), /* re23 */
7885 DRXJ_16TO8(37), /* re24 */
7886 DRXJ_16TO8(-190), /* re25 */
7887 DRXJ_16TO8(-40), /* re26 */
7888 DRXJ_16TO8(619) /* re27 */
7889 };
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007890 const u8 qam_b64_taps[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03007891 DRXJ_16TO8(0), /* re0 */
7892 DRXJ_16TO8(-2), /* re1 */
7893 DRXJ_16TO8(1), /* re2 */
7894 DRXJ_16TO8(2), /* re3 */
7895 DRXJ_16TO8(-2), /* re4 */
7896 DRXJ_16TO8(0), /* re5 */
7897 DRXJ_16TO8(4), /* re6 */
7898 DRXJ_16TO8(-2), /* re7 */
7899 DRXJ_16TO8(-4), /* re8 */
7900 DRXJ_16TO8(4), /* re9 */
7901 DRXJ_16TO8(3), /* re10 */
7902 DRXJ_16TO8(-6), /* re11 */
7903 DRXJ_16TO8(0), /* re12 */
7904 DRXJ_16TO8(6), /* re13 */
7905 DRXJ_16TO8(-5), /* re14 */
7906 DRXJ_16TO8(-3), /* re15 */
7907 DRXJ_16TO8(11), /* re16 */
7908 DRXJ_16TO8(-4), /* re17 */
7909 DRXJ_16TO8(-19), /* re18 */
7910 DRXJ_16TO8(19), /* re19 */
7911 DRXJ_16TO8(28), /* re20 */
7912 DRXJ_16TO8(-45), /* re21 */
7913 DRXJ_16TO8(-36), /* re22 */
7914 DRXJ_16TO8(90), /* re23 */
7915 DRXJ_16TO8(42), /* re24 */
7916 DRXJ_16TO8(-185), /* re25 */
7917 DRXJ_16TO8(-46), /* re26 */
7918 DRXJ_16TO8(614) /* re27 */
7919 };
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007920 const u8 qam_b256_taps[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03007921 DRXJ_16TO8(-2), /* re0 */
7922 DRXJ_16TO8(4), /* re1 */
7923 DRXJ_16TO8(1), /* re2 */
7924 DRXJ_16TO8(-4), /* re3 */
7925 DRXJ_16TO8(0), /* re4 */
7926 DRXJ_16TO8(4), /* re5 */
7927 DRXJ_16TO8(-2), /* re6 */
7928 DRXJ_16TO8(-4), /* re7 */
7929 DRXJ_16TO8(5), /* re8 */
7930 DRXJ_16TO8(2), /* re9 */
7931 DRXJ_16TO8(-8), /* re10 */
7932 DRXJ_16TO8(2), /* re11 */
7933 DRXJ_16TO8(11), /* re12 */
7934 DRXJ_16TO8(-8), /* re13 */
7935 DRXJ_16TO8(-15), /* re14 */
7936 DRXJ_16TO8(16), /* re15 */
7937 DRXJ_16TO8(19), /* re16 */
7938 DRXJ_16TO8(-27), /* re17 */
7939 DRXJ_16TO8(-22), /* re18 */
7940 DRXJ_16TO8(44), /* re19 */
7941 DRXJ_16TO8(26), /* re20 */
7942 DRXJ_16TO8(-69), /* re21 */
7943 DRXJ_16TO8(-28), /* re22 */
7944 DRXJ_16TO8(110), /* re23 */
7945 DRXJ_16TO8(31), /* re24 */
7946 DRXJ_16TO8(-201), /* re25 */
7947 DRXJ_16TO8(-32), /* re26 */
7948 DRXJ_16TO8(628) /* re27 */
7949 };
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007950 const u8 qam_c_taps[] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03007951 DRXJ_16TO8(-3), /* re0 */
7952 DRXJ_16TO8(3), /* re1 */
7953 DRXJ_16TO8(2), /* re2 */
7954 DRXJ_16TO8(-4), /* re3 */
7955 DRXJ_16TO8(0), /* re4 */
7956 DRXJ_16TO8(4), /* re5 */
7957 DRXJ_16TO8(-1), /* re6 */
7958 DRXJ_16TO8(-4), /* re7 */
7959 DRXJ_16TO8(3), /* re8 */
7960 DRXJ_16TO8(3), /* re9 */
7961 DRXJ_16TO8(-5), /* re10 */
7962 DRXJ_16TO8(0), /* re11 */
7963 DRXJ_16TO8(9), /* re12 */
7964 DRXJ_16TO8(-4), /* re13 */
7965 DRXJ_16TO8(-12), /* re14 */
7966 DRXJ_16TO8(10), /* re15 */
7967 DRXJ_16TO8(16), /* re16 */
7968 DRXJ_16TO8(-21), /* re17 */
7969 DRXJ_16TO8(-20), /* re18 */
7970 DRXJ_16TO8(37), /* re19 */
7971 DRXJ_16TO8(25), /* re20 */
7972 DRXJ_16TO8(-62), /* re21 */
7973 DRXJ_16TO8(-28), /* re22 */
7974 DRXJ_16TO8(105), /* re23 */
7975 DRXJ_16TO8(31), /* re24 */
7976 DRXJ_16TO8(-197), /* re25 */
7977 DRXJ_16TO8(-33), /* re26 */
7978 DRXJ_16TO8(626) /* re27 */
7979 };
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007980
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007981 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03007982 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03007983 common_attr = (struct drx_common_attr *) demod->my_common_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03007984
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03007985 if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007986 if (ext_attr->standard == DRX_STANDARD_ITU_B) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03007987 switch (channel->constellation) {
7988 case DRX_CONSTELLATION_QAM256:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007989 iqm_rc_rate = 0x00AE3562;
7990 lc_symbol_freq =
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03007991 QAM_LC_SYMBOL_FREQ_FREQ_QAM_B_256;
7992 channel->symbolrate = 5360537;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007993 iqm_rc_stretch = IQM_RC_STRETCH_QAM_B_256;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03007994 break;
7995 case DRX_CONSTELLATION_QAM64:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007996 iqm_rc_rate = 0x00C05A0E;
7997 lc_symbol_freq = 409;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03007998 channel->symbolrate = 5056941;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03007999 iqm_rc_stretch = IQM_RC_STRETCH_QAM_B_64;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008000 break;
8001 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008002 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008003 }
8004 } else {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008005 adc_frequency = (common_attr->sys_clock_freq * 1000) / 3;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008006 if (channel->symbolrate == 0) {
8007 pr_err("error: channel symbolrate is zero!\n");
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008008 return -EIO;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008009 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008010 iqm_rc_rate =
8011 (adc_frequency / channel->symbolrate) * (1 << 21) +
8012 (frac28
8013 ((adc_frequency % channel->symbolrate),
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008014 channel->symbolrate) >> 7) - (1 << 23);
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008015 lc_symbol_freq =
8016 (u16) (frac28
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008017 (channel->symbolrate +
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008018 (adc_frequency >> 13),
8019 adc_frequency) >> 16);
8020 if (lc_symbol_freq > 511)
8021 lc_symbol_freq = 511;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008022
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008023 iqm_rc_stretch = 21;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008024 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008025
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008026 if (ext_attr->standard == DRX_STANDARD_ITU_A) {
8027 set_env_parameters = QAM_TOP_ANNEX_A; /* annex */
8028 set_param_parameters[0] = channel->constellation; /* constellation */
8029 set_param_parameters[1] = DRX_INTERLEAVEMODE_I12_J17; /* interleave mode */
8030 } else if (ext_attr->standard == DRX_STANDARD_ITU_B) {
8031 set_env_parameters = QAM_TOP_ANNEX_B; /* annex */
8032 set_param_parameters[0] = channel->constellation; /* constellation */
8033 set_param_parameters[1] = channel->interleavemode; /* interleave mode */
8034 } else if (ext_attr->standard == DRX_STANDARD_ITU_C) {
8035 set_env_parameters = QAM_TOP_ANNEX_C; /* annex */
8036 set_param_parameters[0] = channel->constellation; /* constellation */
8037 set_param_parameters[1] = DRX_INTERLEAVEMODE_I12_J17; /* interleave mode */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008038 } else {
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008039 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008040 }
8041 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008042
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008043 if (op & QAM_SET_OP_ALL) {
8044 /*
8045 STEP 1: reset demodulator
8046 resets IQM, QAM and FEC HW blocks
8047 resets SCU variables
8048 */
8049 /* stop all comm_exec */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008050 rc = drxj_dap_write_reg16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008051 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008052 pr_err("error %d\n", rc);
8053 goto rw_error;
8054 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008055 rc = drxj_dap_write_reg16(dev_addr, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008056 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008057 pr_err("error %d\n", rc);
8058 goto rw_error;
8059 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008060 rc = drxj_dap_write_reg16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008061 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008062 pr_err("error %d\n", rc);
8063 goto rw_error;
8064 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008065 rc = drxj_dap_write_reg16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008066 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008067 pr_err("error %d\n", rc);
8068 goto rw_error;
8069 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008070 rc = drxj_dap_write_reg16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008071 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008072 pr_err("error %d\n", rc);
8073 goto rw_error;
8074 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008075 rc = drxj_dap_write_reg16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008076 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008077 pr_err("error %d\n", rc);
8078 goto rw_error;
8079 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008080 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008081 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008082 pr_err("error %d\n", rc);
8083 goto rw_error;
8084 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008085
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008086 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008087 SCU_RAM_COMMAND_CMD_DEMOD_RESET;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008088 cmd_scu.parameter_len = 0;
8089 cmd_scu.result_len = 1;
8090 cmd_scu.parameter = NULL;
8091 cmd_scu.result = &cmd_result;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008092 rc = scu_command(dev_addr, &cmd_scu);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008093 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008094 pr_err("error %d\n", rc);
8095 goto rw_error;
8096 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008097 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008098
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008099 if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
8100 /*
8101 STEP 2: configure demodulator
8102 -set env
8103 -set params (resets IQM,QAM,FEC HW; initializes some SCU variables )
8104 */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008105 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008106 SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008107 cmd_scu.parameter_len = 1;
8108 cmd_scu.result_len = 1;
8109 cmd_scu.parameter = &set_env_parameters;
8110 cmd_scu.result = &cmd_result;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008111 rc = scu_command(dev_addr, &cmd_scu);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008112 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008113 pr_err("error %d\n", rc);
8114 goto rw_error;
8115 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008116
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008117 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008118 SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008119 cmd_scu.parameter_len = 2;
8120 cmd_scu.result_len = 1;
8121 cmd_scu.parameter = set_param_parameters;
8122 cmd_scu.result = &cmd_result;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008123 rc = scu_command(dev_addr, &cmd_scu);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008124 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008125 pr_err("error %d\n", rc);
8126 goto rw_error;
8127 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008128 /* set symbol rate */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008129 rc = drxdap_fasi_write_reg32(dev_addr, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008130 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008131 pr_err("error %d\n", rc);
8132 goto rw_error;
8133 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008134 ext_attr->iqm_rc_rate_ofs = iqm_rc_rate;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008135 rc = set_qam_measurement(demod, channel->constellation, channel->symbolrate);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008136 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008137 pr_err("error %d\n", rc);
8138 goto rw_error;
8139 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008140 }
8141 /* STEP 3: enable the system in a mode where the ADC provides valid signal
8142 setup constellation independent registers */
8143 /* from qam_cmd.py script (qam_driver_b) */
8144 /* TODO: remove re-writes of HW reset values */
8145 if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_SPECTRUM)) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008146 rc = set_frequency(demod, channel, tuner_freq_offset);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008147 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008148 pr_err("error %d\n", rc);
8149 goto rw_error;
8150 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008151 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008152
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008153 if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008154
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008155 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_SYMBOL_FREQ__A, lc_symbol_freq, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008156 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008157 pr_err("error %d\n", rc);
8158 goto rw_error;
8159 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008160 rc = drxj_dap_write_reg16(dev_addr, IQM_RC_STRETCH__A, iqm_rc_stretch, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008161 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008162 pr_err("error %d\n", rc);
8163 goto rw_error;
8164 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008165 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008166
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008167 if (op & QAM_SET_OP_ALL) {
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03008168 if (!ext_attr->has_lna) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008169 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_AMUX__A, 0x02, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008170 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008171 pr_err("error %d\n", rc);
8172 goto rw_error;
8173 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008174 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008175 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_SYMMETRIC__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008176 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008177 pr_err("error %d\n", rc);
8178 goto rw_error;
8179 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008180 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_MIDTAP__A, 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008181 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008182 pr_err("error %d\n", rc);
8183 goto rw_error;
8184 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008185 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_OUT_ENA__A, IQM_CF_OUT_ENA_QAM__M, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008186 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008187 pr_err("error %d\n", rc);
8188 goto rw_error;
8189 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008190
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008191 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_WR_RSV_0__A, 0x5f, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008192 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008193 pr_err("error %d\n", rc);
8194 goto rw_error;
8195 } /* scu temporary shut down agc */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008196
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008197 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_SYNC_SEL__A, 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008198 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008199 pr_err("error %d\n", rc);
8200 goto rw_error;
8201 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008202 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_CLP_LEN__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008203 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008204 pr_err("error %d\n", rc);
8205 goto rw_error;
8206 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008207 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_CLP_TH__A, 448, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008208 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008209 pr_err("error %d\n", rc);
8210 goto rw_error;
8211 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008212 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_SNS_LEN__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008213 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008214 pr_err("error %d\n", rc);
8215 goto rw_error;
8216 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008217 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_PDREF__A, 4, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008218 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008219 pr_err("error %d\n", rc);
8220 goto rw_error;
8221 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008222 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_STDBY__A, 0x10, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008223 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008224 pr_err("error %d\n", rc);
8225 goto rw_error;
8226 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008227 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_PGA_GAIN__A, 11, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008228 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008229 pr_err("error %d\n", rc);
8230 goto rw_error;
8231 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008232
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008233 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_POW_MEAS_LEN__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008234 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008235 pr_err("error %d\n", rc);
8236 goto rw_error;
8237 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008238 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_SCALE_SH__A, IQM_CF_SCALE_SH__PRE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008239 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008240 pr_err("error %d\n", rc);
8241 goto rw_error;
8242 } /*! reset default val ! */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008243
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008244 rc = drxj_dap_write_reg16(dev_addr, QAM_SY_TIMEOUT__A, QAM_SY_TIMEOUT__PRE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008245 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008246 pr_err("error %d\n", rc);
8247 goto rw_error;
8248 } /*! reset default val ! */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008249 if (ext_attr->standard == DRX_STANDARD_ITU_B) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008250 rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_LWM__A, QAM_SY_SYNC_LWM__PRE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008251 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008252 pr_err("error %d\n", rc);
8253 goto rw_error;
8254 } /*! reset default val ! */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008255 rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_AWM__A, QAM_SY_SYNC_AWM__PRE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008256 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008257 pr_err("error %d\n", rc);
8258 goto rw_error;
8259 } /*! reset default val ! */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008260 rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_HWM__A, QAM_SY_SYNC_HWM__PRE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008261 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008262 pr_err("error %d\n", rc);
8263 goto rw_error;
8264 } /*! reset default val ! */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008265 } else {
8266 switch (channel->constellation) {
8267 case DRX_CONSTELLATION_QAM16:
8268 case DRX_CONSTELLATION_QAM64:
8269 case DRX_CONSTELLATION_QAM256:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008270 rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_LWM__A, 0x03, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008271 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008272 pr_err("error %d\n", rc);
8273 goto rw_error;
8274 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008275 rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_AWM__A, 0x04, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008276 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008277 pr_err("error %d\n", rc);
8278 goto rw_error;
8279 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008280 rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_HWM__A, QAM_SY_SYNC_HWM__PRE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008281 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008282 pr_err("error %d\n", rc);
8283 goto rw_error;
8284 } /*! reset default val ! */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008285 break;
8286 case DRX_CONSTELLATION_QAM32:
8287 case DRX_CONSTELLATION_QAM128:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008288 rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_LWM__A, 0x03, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008289 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008290 pr_err("error %d\n", rc);
8291 goto rw_error;
8292 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008293 rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_AWM__A, 0x05, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008294 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008295 pr_err("error %d\n", rc);
8296 goto rw_error;
8297 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008298 rc = drxj_dap_write_reg16(dev_addr, QAM_SY_SYNC_HWM__A, 0x06, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008299 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008300 pr_err("error %d\n", rc);
8301 goto rw_error;
8302 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008303 break;
8304 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008305 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008306 } /* switch */
8307 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008308
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008309 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_MODE__A, QAM_LC_MODE__PRE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008310 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008311 pr_err("error %d\n", rc);
8312 goto rw_error;
8313 } /*! reset default val ! */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008314 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_RATE_LIMIT__A, 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008315 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008316 pr_err("error %d\n", rc);
8317 goto rw_error;
8318 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008319 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_LPF_FACTORP__A, 4, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008320 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008321 pr_err("error %d\n", rc);
8322 goto rw_error;
8323 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008324 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_LPF_FACTORI__A, 4, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008325 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008326 pr_err("error %d\n", rc);
8327 goto rw_error;
8328 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008329 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_MODE__A, 7, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008330 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008331 pr_err("error %d\n", rc);
8332 goto rw_error;
8333 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008334 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB0__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008335 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008336 pr_err("error %d\n", rc);
8337 goto rw_error;
8338 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008339 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB1__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008340 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008341 pr_err("error %d\n", rc);
8342 goto rw_error;
8343 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008344 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB2__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008345 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008346 pr_err("error %d\n", rc);
8347 goto rw_error;
8348 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008349 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB3__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008350 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008351 pr_err("error %d\n", rc);
8352 goto rw_error;
8353 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008354 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB4__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008355 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008356 pr_err("error %d\n", rc);
8357 goto rw_error;
8358 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008359 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB5__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008360 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008361 pr_err("error %d\n", rc);
8362 goto rw_error;
8363 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008364 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB6__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008365 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008366 pr_err("error %d\n", rc);
8367 goto rw_error;
8368 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008369 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB8__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008370 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008371 pr_err("error %d\n", rc);
8372 goto rw_error;
8373 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008374 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB9__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008375 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008376 pr_err("error %d\n", rc);
8377 goto rw_error;
8378 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008379 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB10__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008380 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008381 pr_err("error %d\n", rc);
8382 goto rw_error;
8383 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008384 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB12__A, 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008385 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008386 pr_err("error %d\n", rc);
8387 goto rw_error;
8388 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008389 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB15__A, 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008390 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008391 pr_err("error %d\n", rc);
8392 goto rw_error;
8393 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008394 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB16__A, 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008395 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008396 pr_err("error %d\n", rc);
8397 goto rw_error;
8398 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008399 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB20__A, 4, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008400 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008401 pr_err("error %d\n", rc);
8402 goto rw_error;
8403 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008404 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_QUAL_TAB25__A, 4, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008405 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008406 pr_err("error %d\n", rc);
8407 goto rw_error;
8408 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008409
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008410 rc = drxj_dap_write_reg16(dev_addr, IQM_FS_ADJ_SEL__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008411 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008412 pr_err("error %d\n", rc);
8413 goto rw_error;
8414 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008415 rc = drxj_dap_write_reg16(dev_addr, IQM_RC_ADJ_SEL__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008416 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008417 pr_err("error %d\n", rc);
8418 goto rw_error;
8419 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008420 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_ADJ_SEL__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008421 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008422 pr_err("error %d\n", rc);
8423 goto rw_error;
8424 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008425 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_POW_MEAS_LEN__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008426 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008427 pr_err("error %d\n", rc);
8428 goto rw_error;
8429 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008430 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_GPIO__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008431 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008432 pr_err("error %d\n", rc);
8433 goto rw_error;
8434 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008435
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008436 /* No more resets of the IQM, current standard correctly set =>
8437 now AGCs can be configured. */
8438 /* turn on IQMAF. It has to be in front of setAgc**() */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008439 rc = set_iqm_af(demod, true);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008440 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008441 pr_err("error %d\n", rc);
8442 goto rw_error;
8443 }
8444 rc = adc_synchronization(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008445 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008446 pr_err("error %d\n", rc);
8447 goto rw_error;
8448 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008449
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008450 rc = init_agc(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008451 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008452 pr_err("error %d\n", rc);
8453 goto rw_error;
8454 }
8455 rc = set_agc_if(demod, &(ext_attr->qam_if_agc_cfg), false);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008456 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008457 pr_err("error %d\n", rc);
8458 goto rw_error;
8459 }
8460 rc = set_agc_rf(demod, &(ext_attr->qam_rf_agc_cfg), false);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008461 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008462 pr_err("error %d\n", rc);
8463 goto rw_error;
8464 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008465 {
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03008466 /* TODO fix this, store a struct drxj_cfg_afe_gain structure in struct drxj_data instead
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008467 of only the gain */
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03008468 struct drxj_cfg_afe_gain qam_pga_cfg = { DRX_STANDARD_ITU_B, 0 };
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008469
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008470 qam_pga_cfg.gain = ext_attr->qam_pga_cfg;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008471 rc = ctrl_set_cfg_afe_gain(demod, &qam_pga_cfg);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008472 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008473 pr_err("error %d\n", rc);
8474 goto rw_error;
8475 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008476 }
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008477 rc = ctrl_set_cfg_pre_saw(demod, &(ext_attr->qam_pre_saw_cfg));
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008478 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008479 pr_err("error %d\n", rc);
8480 goto rw_error;
8481 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008482 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008483
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008484 if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008485 if (ext_attr->standard == DRX_STANDARD_ITU_A) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008486 rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_RE0__A, sizeof(qam_a_taps), ((u8 *)qam_a_taps), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008487 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008488 pr_err("error %d\n", rc);
8489 goto rw_error;
8490 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008491 rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_IM0__A, sizeof(qam_a_taps), ((u8 *)qam_a_taps), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008492 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008493 pr_err("error %d\n", rc);
8494 goto rw_error;
8495 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008496 } else if (ext_attr->standard == DRX_STANDARD_ITU_B) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008497 switch (channel->constellation) {
8498 case DRX_CONSTELLATION_QAM64:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008499 rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_RE0__A, sizeof(qam_b64_taps), ((u8 *)qam_b64_taps), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008500 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008501 pr_err("error %d\n", rc);
8502 goto rw_error;
8503 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008504 rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_IM0__A, sizeof(qam_b64_taps), ((u8 *)qam_b64_taps), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008505 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008506 pr_err("error %d\n", rc);
8507 goto rw_error;
8508 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008509 break;
8510 case DRX_CONSTELLATION_QAM256:
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008511 rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_RE0__A, sizeof(qam_b256_taps), ((u8 *)qam_b256_taps), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008512 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008513 pr_err("error %d\n", rc);
8514 goto rw_error;
8515 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008516 rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_IM0__A, sizeof(qam_b256_taps), ((u8 *)qam_b256_taps), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008517 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008518 pr_err("error %d\n", rc);
8519 goto rw_error;
8520 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008521 break;
8522 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008523 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008524 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008525 } else if (ext_attr->standard == DRX_STANDARD_ITU_C) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008526 rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_RE0__A, sizeof(qam_c_taps), ((u8 *)qam_c_taps), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008527 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008528 pr_err("error %d\n", rc);
8529 goto rw_error;
8530 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008531 rc = drxdap_fasi_write_block(dev_addr, IQM_CF_TAP_IM0__A, sizeof(qam_c_taps), ((u8 *)qam_c_taps), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008532 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008533 pr_err("error %d\n", rc);
8534 goto rw_error;
8535 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008536 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008537
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008538 /* SETP 4: constellation specific setup */
8539 switch (channel->constellation) {
8540 case DRX_CONSTELLATION_QAM16:
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008541 rc = set_qam16(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008542 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008543 pr_err("error %d\n", rc);
8544 goto rw_error;
8545 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008546 break;
8547 case DRX_CONSTELLATION_QAM32:
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008548 rc = set_qam32(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008549 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008550 pr_err("error %d\n", rc);
8551 goto rw_error;
8552 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008553 break;
8554 case DRX_CONSTELLATION_QAM64:
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008555 rc = set_qam64(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008556 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008557 pr_err("error %d\n", rc);
8558 goto rw_error;
8559 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008560 break;
8561 case DRX_CONSTELLATION_QAM128:
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008562 rc = set_qam128(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008563 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008564 pr_err("error %d\n", rc);
8565 goto rw_error;
8566 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008567 break;
8568 case DRX_CONSTELLATION_QAM256:
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008569 rc = set_qam256(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008570 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008571 pr_err("error %d\n", rc);
8572 goto rw_error;
8573 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008574 break;
8575 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008576 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008577 } /* switch */
8578 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008579
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008580 if ((op & QAM_SET_OP_ALL)) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008581 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_SCALE_SH__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008582 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008583 pr_err("error %d\n", rc);
8584 goto rw_error;
8585 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008586
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008587 /* Mpeg output has to be in front of FEC active */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008588 rc = set_mpegtei_handling(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008589 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008590 pr_err("error %d\n", rc);
8591 goto rw_error;
8592 }
8593 rc = bit_reverse_mpeg_output(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008594 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008595 pr_err("error %d\n", rc);
8596 goto rw_error;
8597 }
8598 rc = set_mpeg_start_width(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008599 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008600 pr_err("error %d\n", rc);
8601 goto rw_error;
8602 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008603 {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008604 /* TODO: move to set_standard after hardware reset value problem is solved */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008605 /* Configure initial MPEG output */
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03008606 struct drx_cfg_mpeg_output cfg_mpeg_output;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008607
Mauro Carvalho Chehab41b5cc02014-03-02 11:01:11 -03008608 memcpy(&cfg_mpeg_output, &common_attr->mpeg_cfg, sizeof(cfg_mpeg_output));
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008609 cfg_mpeg_output.enable_mpeg_output = true;
Mauro Carvalho Chehab41b5cc02014-03-02 11:01:11 -03008610
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008611 rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008612 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008613 pr_err("error %d\n", rc);
8614 goto rw_error;
8615 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008616 }
8617 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008618
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008619 if ((op & QAM_SET_OP_ALL) || (op & QAM_SET_OP_CONSTELLATION)) {
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008620
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008621 /* STEP 5: start QAM demodulator (starts FEC, QAM and IQM HW) */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008622 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008623 SCU_RAM_COMMAND_CMD_DEMOD_START;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008624 cmd_scu.parameter_len = 0;
8625 cmd_scu.result_len = 1;
8626 cmd_scu.parameter = NULL;
8627 cmd_scu.result = &cmd_result;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008628 rc = scu_command(dev_addr, &cmd_scu);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008629 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008630 pr_err("error %d\n", rc);
8631 goto rw_error;
8632 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008633 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008634
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008635 rc = drxj_dap_write_reg16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_ACTIVE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008636 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008637 pr_err("error %d\n", rc);
8638 goto rw_error;
8639 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008640 rc = drxj_dap_write_reg16(dev_addr, QAM_COMM_EXEC__A, QAM_COMM_EXEC_ACTIVE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008641 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008642 pr_err("error %d\n", rc);
8643 goto rw_error;
8644 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008645 rc = drxj_dap_write_reg16(dev_addr, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008646 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008647 pr_err("error %d\n", rc);
8648 goto rw_error;
8649 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008650
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008651 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008652rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008653 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008654}
8655
8656/*============================================================================*/
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03008657static int ctrl_get_qam_sig_quality(struct drx_demod_instance *demod);
8658
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03008659static int qam_flip_spec(struct drx_demod_instance *demod, struct drx_channel *channel)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008660{
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03008661 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
8662 struct drxj_data *ext_attr = demod->my_ext_attr;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008663 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008664 u32 iqm_fs_rate_ofs = 0;
8665 u32 iqm_fs_rate_lo = 0;
8666 u16 qam_ctl_ena = 0;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03008667 u16 data = 0;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008668 u16 equ_mode = 0;
8669 u16 fsm_state = 0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008670 int i = 0;
8671 int ofsofs = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008672
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008673 /* Silence the controlling of lc, equ, and the acquisition state machine */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008674 rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_QAM_CTL_ENA__A, &qam_ctl_ena, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008675 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008676 pr_err("error %d\n", rc);
8677 goto rw_error;
8678 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008679 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008680 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008681 pr_err("error %d\n", rc);
8682 goto rw_error;
8683 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008684
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008685 /* freeze the frequency control loop */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008686 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_CF__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008687 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008688 pr_err("error %d\n", rc);
8689 goto rw_error;
8690 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008691 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_CF1__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008692 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008693 pr_err("error %d\n", rc);
8694 goto rw_error;
8695 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008696
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008697 rc = drxj_dap_atomic_read_reg32(dev_addr, IQM_FS_RATE_OFS_LO__A, &iqm_fs_rate_ofs, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008698 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008699 pr_err("error %d\n", rc);
8700 goto rw_error;
8701 }
8702 rc = drxj_dap_atomic_read_reg32(dev_addr, IQM_FS_RATE_LO__A, &iqm_fs_rate_lo, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008703 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008704 pr_err("error %d\n", rc);
8705 goto rw_error;
8706 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008707 ofsofs = iqm_fs_rate_lo - iqm_fs_rate_ofs;
8708 iqm_fs_rate_ofs = ~iqm_fs_rate_ofs + 1;
8709 iqm_fs_rate_ofs -= 2 * ofsofs;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008710
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008711 /* freeze dq/fq updating */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008712 rc = drxj_dap_read_reg16(dev_addr, QAM_DQ_MODE__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008713 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008714 pr_err("error %d\n", rc);
8715 goto rw_error;
8716 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008717 data = (data & 0xfff9);
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008718 rc = drxj_dap_write_reg16(dev_addr, QAM_DQ_MODE__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008719 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008720 pr_err("error %d\n", rc);
8721 goto rw_error;
8722 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008723 rc = drxj_dap_write_reg16(dev_addr, QAM_FQ_MODE__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008724 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008725 pr_err("error %d\n", rc);
8726 goto rw_error;
8727 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008728
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008729 /* lc_cp / _ci / _ca */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008730 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_CI__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008731 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008732 pr_err("error %d\n", rc);
8733 goto rw_error;
8734 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008735 rc = drxj_dap_write_reg16(dev_addr, QAM_LC_EP__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008736 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008737 pr_err("error %d\n", rc);
8738 goto rw_error;
8739 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008740 rc = drxj_dap_write_reg16(dev_addr, QAM_FQ_LA_FACTOR__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008741 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008742 pr_err("error %d\n", rc);
8743 goto rw_error;
8744 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008745
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008746 /* flip the spec */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008747 rc = drxdap_fasi_write_reg32(dev_addr, IQM_FS_RATE_OFS_LO__A, iqm_fs_rate_ofs, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008748 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008749 pr_err("error %d\n", rc);
8750 goto rw_error;
8751 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008752 ext_attr->iqm_fs_rate_ofs = iqm_fs_rate_ofs;
8753 ext_attr->pos_image = (ext_attr->pos_image) ? false : true;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008754
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008755 /* freeze dq/fq updating */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008756 rc = drxj_dap_read_reg16(dev_addr, QAM_DQ_MODE__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008757 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008758 pr_err("error %d\n", rc);
8759 goto rw_error;
8760 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008761 equ_mode = data;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008762 data = (data & 0xfff9);
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008763 rc = drxj_dap_write_reg16(dev_addr, QAM_DQ_MODE__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008764 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008765 pr_err("error %d\n", rc);
8766 goto rw_error;
8767 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008768 rc = drxj_dap_write_reg16(dev_addr, QAM_FQ_MODE__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008769 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008770 pr_err("error %d\n", rc);
8771 goto rw_error;
8772 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008773
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008774 for (i = 0; i < 28; i++) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008775 rc = drxj_dap_read_reg16(dev_addr, QAM_DQ_TAP_IM_EL0__A + (2 * i), &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008776 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008777 pr_err("error %d\n", rc);
8778 goto rw_error;
8779 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008780 rc = drxj_dap_write_reg16(dev_addr, QAM_DQ_TAP_IM_EL0__A + (2 * i), -data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008781 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008782 pr_err("error %d\n", rc);
8783 goto rw_error;
8784 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008785 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008786
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008787 for (i = 0; i < 24; i++) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008788 rc = drxj_dap_read_reg16(dev_addr, QAM_FQ_TAP_IM_EL0__A + (2 * i), &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008789 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008790 pr_err("error %d\n", rc);
8791 goto rw_error;
8792 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008793 rc = drxj_dap_write_reg16(dev_addr, QAM_FQ_TAP_IM_EL0__A + (2 * i), -data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008794 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008795 pr_err("error %d\n", rc);
8796 goto rw_error;
8797 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008798 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008799
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008800 data = equ_mode;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008801 rc = drxj_dap_write_reg16(dev_addr, QAM_DQ_MODE__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008802 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008803 pr_err("error %d\n", rc);
8804 goto rw_error;
8805 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008806 rc = drxj_dap_write_reg16(dev_addr, QAM_FQ_MODE__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008807 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008808 pr_err("error %d\n", rc);
8809 goto rw_error;
8810 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008811
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008812 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_FSM_STATE_TGT__A, 4, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008813 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008814 pr_err("error %d\n", rc);
8815 goto rw_error;
8816 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008817
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008818 i = 0;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008819 while ((fsm_state != 4) && (i++ < 100)) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008820 rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_QAM_FSM_STATE__A, &fsm_state, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008821 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008822 pr_err("error %d\n", rc);
8823 goto rw_error;
8824 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008825 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008826 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_QAM_CTL_ENA__A, (qam_ctl_ena | 0x0016), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008827 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008828 pr_err("error %d\n", rc);
8829 goto rw_error;
8830 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008831
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008832 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008833rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008834 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008835
8836}
8837
8838#define NO_LOCK 0x0
8839#define DEMOD_LOCKED 0x1
8840#define SYNC_FLIPPED 0x2
8841#define SPEC_MIRRORED 0x4
8842/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008843* \fn int qam64auto ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008844* \brief auto do sync pattern switching and mirroring.
8845* \param demod: instance of demod.
8846* \param channel: pointer to channel data.
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008847* \param tuner_freq_offset: tuner frequency offset.
8848* \param lock_status: pointer to lock status.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03008849* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008850*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03008851static int
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03008852qam64auto(struct drx_demod_instance *demod,
8853 struct drx_channel *channel,
8854 s32 tuner_freq_offset, enum drx_lock_status *lock_status)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008855{
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03008856 struct drxj_data *ext_attr = demod->my_ext_attr;
8857 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
8858 struct drx39xxj_state *state = dev_addr->user_data;
8859 struct dtv_frontend_properties *p = &state->frontend.dtv_property_cache;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008860 int rc;
Mauro Carvalho Chehab6f64c522014-03-09 17:30:48 -03008861 u32 lck_state = NO_LOCK;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008862 u32 start_time = 0;
8863 u32 d_locked_time = 0;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008864 u32 timeout_ofs = 0;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008865 u16 data = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008866
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008867 /* external attributes for storing aquired channel constellation */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008868 *lock_status = DRX_NOT_LOCKED;
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03008869 start_time = jiffies_to_msecs(jiffies);
Mauro Carvalho Chehab6f64c522014-03-09 17:30:48 -03008870 lck_state = NO_LOCK;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008871 do {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008872 rc = ctrl_lock_status(demod, lock_status);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008873 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008874 pr_err("error %d\n", rc);
8875 goto rw_error;
8876 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008877
Mauro Carvalho Chehab6f64c522014-03-09 17:30:48 -03008878 switch (lck_state) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008879 case NO_LOCK:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008880 if (*lock_status == DRXJ_DEMOD_LOCK) {
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03008881 rc = ctrl_get_qam_sig_quality(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008882 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008883 pr_err("error %d\n", rc);
8884 goto rw_error;
8885 }
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03008886 if (p->cnr.stat[0].svalue > 20800) {
Mauro Carvalho Chehab6f64c522014-03-09 17:30:48 -03008887 lck_state = DEMOD_LOCKED;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008888 /* some delay to see if fec_lock possible TODO find the right value */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008889 timeout_ofs += DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME; /* see something, waiting longer */
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03008890 d_locked_time = jiffies_to_msecs(jiffies);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008891 }
8892 }
8893 break;
8894 case DEMOD_LOCKED:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008895 if ((*lock_status == DRXJ_DEMOD_LOCK) && /* still demod_lock in 150ms */
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03008896 ((jiffies_to_msecs(jiffies) - d_locked_time) >
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008897 DRXJ_QAM_FEC_LOCK_WAITTIME)) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008898 rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008899 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008900 pr_err("error %d\n", rc);
8901 goto rw_error;
8902 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008903 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, data | 0x1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008904 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008905 pr_err("error %d\n", rc);
8906 goto rw_error;
8907 }
Mauro Carvalho Chehab6f64c522014-03-09 17:30:48 -03008908 lck_state = SYNC_FLIPPED;
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03008909 msleep(10);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008910 }
8911 break;
8912 case SYNC_FLIPPED:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008913 if (*lock_status == DRXJ_DEMOD_LOCK) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008914 if (channel->mirror == DRX_MIRROR_AUTO) {
8915 /* flip sync pattern back */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008916 rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008917 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008918 pr_err("error %d\n", rc);
8919 goto rw_error;
8920 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008921 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, data & 0xFFFE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008922 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008923 pr_err("error %d\n", rc);
8924 goto rw_error;
8925 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008926 /* flip spectrum */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008927 ext_attr->mirror = DRX_MIRROR_YES;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008928 rc = qam_flip_spec(demod, channel);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008929 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008930 pr_err("error %d\n", rc);
8931 goto rw_error;
8932 }
Mauro Carvalho Chehab6f64c522014-03-09 17:30:48 -03008933 lck_state = SPEC_MIRRORED;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008934 /* reset timer TODO: still need 500ms? */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008935 start_time = d_locked_time =
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03008936 jiffies_to_msecs(jiffies);
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008937 timeout_ofs = 0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008938 } else { /* no need to wait lock */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008939
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008940 start_time =
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03008941 jiffies_to_msecs(jiffies) -
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008942 DRXJ_QAM_MAX_WAITTIME - timeout_ofs;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008943 }
8944 }
8945 break;
8946 case SPEC_MIRRORED:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008947 if ((*lock_status == DRXJ_DEMOD_LOCK) && /* still demod_lock in 150ms */
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03008948 ((jiffies_to_msecs(jiffies) - d_locked_time) >
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008949 DRXJ_QAM_FEC_LOCK_WAITTIME)) {
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03008950 rc = ctrl_get_qam_sig_quality(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008951 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008952 pr_err("error %d\n", rc);
8953 goto rw_error;
8954 }
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03008955 if (p->cnr.stat[0].svalue > 20800) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008956 rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008957 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008958 pr_err("error %d\n", rc);
8959 goto rw_error;
8960 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03008961 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, data | 0x1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008962 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03008963 pr_err("error %d\n", rc);
8964 goto rw_error;
8965 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008966 /* no need to wait lock */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008967 start_time =
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03008968 jiffies_to_msecs(jiffies) -
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008969 DRXJ_QAM_MAX_WAITTIME - timeout_ofs;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008970 }
8971 }
8972 break;
8973 default:
8974 break;
8975 }
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03008976 msleep(10);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008977 } while
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008978 ((*lock_status != DRX_LOCKED) &&
8979 (*lock_status != DRX_NEVER_LOCK) &&
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03008980 ((jiffies_to_msecs(jiffies) - start_time) <
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008981 (DRXJ_QAM_MAX_WAITTIME + timeout_ofs))
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03008982 );
8983 /* Returning control to apllication ... */
8984
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008985 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008986rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03008987 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008988}
8989
8990/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008991* \fn int qam256auto ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008992* \brief auto do sync pattern switching and mirroring.
8993* \param demod: instance of demod.
8994* \param channel: pointer to channel data.
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03008995* \param tuner_freq_offset: tuner frequency offset.
8996* \param lock_status: pointer to lock status.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03008997* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03008998*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03008999static int
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03009000qam256auto(struct drx_demod_instance *demod,
9001 struct drx_channel *channel,
9002 s32 tuner_freq_offset, enum drx_lock_status *lock_status)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009003{
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03009004 struct drxj_data *ext_attr = demod->my_ext_attr;
9005 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
9006 struct drx39xxj_state *state = dev_addr->user_data;
9007 struct dtv_frontend_properties *p = &state->frontend.dtv_property_cache;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009008 int rc;
Mauro Carvalho Chehab6f64c522014-03-09 17:30:48 -03009009 u32 lck_state = NO_LOCK;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009010 u32 start_time = 0;
9011 u32 d_locked_time = 0;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009012 u32 timeout_ofs = DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009013
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009014 /* external attributes for storing aquired channel constellation */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009015 *lock_status = DRX_NOT_LOCKED;
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03009016 start_time = jiffies_to_msecs(jiffies);
Mauro Carvalho Chehab6f64c522014-03-09 17:30:48 -03009017 lck_state = NO_LOCK;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009018 do {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009019 rc = ctrl_lock_status(demod, lock_status);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009020 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009021 pr_err("error %d\n", rc);
9022 goto rw_error;
9023 }
Mauro Carvalho Chehab6f64c522014-03-09 17:30:48 -03009024 switch (lck_state) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009025 case NO_LOCK:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009026 if (*lock_status == DRXJ_DEMOD_LOCK) {
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03009027 rc = ctrl_get_qam_sig_quality(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009028 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009029 pr_err("error %d\n", rc);
9030 goto rw_error;
9031 }
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03009032 if (p->cnr.stat[0].svalue > 26800) {
Mauro Carvalho Chehab6f64c522014-03-09 17:30:48 -03009033 lck_state = DEMOD_LOCKED;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009034 timeout_ofs += DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME; /* see something, wait longer */
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03009035 d_locked_time = jiffies_to_msecs(jiffies);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009036 }
9037 }
9038 break;
9039 case DEMOD_LOCKED:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009040 if (*lock_status == DRXJ_DEMOD_LOCK) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009041 if ((channel->mirror == DRX_MIRROR_AUTO) &&
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03009042 ((jiffies_to_msecs(jiffies) - d_locked_time) >
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009043 DRXJ_QAM_FEC_LOCK_WAITTIME)) {
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009044 ext_attr->mirror = DRX_MIRROR_YES;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009045 rc = qam_flip_spec(demod, channel);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009046 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009047 pr_err("error %d\n", rc);
9048 goto rw_error;
9049 }
Mauro Carvalho Chehab6f64c522014-03-09 17:30:48 -03009050 lck_state = SPEC_MIRRORED;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009051 /* reset timer TODO: still need 300ms? */
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03009052 start_time = jiffies_to_msecs(jiffies);
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009053 timeout_ofs = -DRXJ_QAM_MAX_WAITTIME / 2;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009054 }
9055 }
9056 break;
9057 case SPEC_MIRRORED:
9058 break;
9059 default:
9060 break;
9061 }
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03009062 msleep(10);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009063 } while
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009064 ((*lock_status < DRX_LOCKED) &&
9065 (*lock_status != DRX_NEVER_LOCK) &&
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -03009066 ((jiffies_to_msecs(jiffies) - start_time) <
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009067 (DRXJ_QAM_MAX_WAITTIME + timeout_ofs)));
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009068
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009069 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009070rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009071 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009072}
9073
9074/**
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -03009075* \fn int set_qam_channel ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009076* \brief Set QAM channel according to the requested constellation.
9077* \param demod: instance of demod.
9078* \param channel: pointer to channel data.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03009079* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009080*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03009081static int
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -03009082set_qam_channel(struct drx_demod_instance *demod,
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03009083 struct drx_channel *channel, s32 tuner_freq_offset)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009084{
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03009085 struct drxj_data *ext_attr = NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009086 int rc;
9087 enum drx_lock_status lock_status = DRX_NOT_LOCKED;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009088 bool auto_flag = false;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009089
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009090 /* external attributes for storing aquired channel constellation */
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03009091 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009092
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009093 /* set QAM channel constellation */
9094 switch (channel->constellation) {
9095 case DRX_CONSTELLATION_QAM16:
9096 case DRX_CONSTELLATION_QAM32:
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009097 case DRX_CONSTELLATION_QAM128:
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009098 return -EINVAL;
9099 case DRX_CONSTELLATION_QAM64:
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009100 case DRX_CONSTELLATION_QAM256:
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009101 if (ext_attr->standard != DRX_STANDARD_ITU_B)
9102 return -EINVAL;
9103
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009104 ext_attr->constellation = channel->constellation;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03009105 if (channel->mirror == DRX_MIRROR_AUTO)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009106 ext_attr->mirror = DRX_MIRROR_NO;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03009107 else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009108 ext_attr->mirror = channel->mirror;
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009109
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009110 rc = set_qam(demod, channel, tuner_freq_offset, QAM_SET_OP_ALL);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009111 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009112 pr_err("error %d\n", rc);
9113 goto rw_error;
9114 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009115
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009116 if (channel->constellation == DRX_CONSTELLATION_QAM64)
9117 rc = qam64auto(demod, channel, tuner_freq_offset,
9118 &lock_status);
9119 else
9120 rc = qam256auto(demod, channel, tuner_freq_offset,
9121 &lock_status);
9122 if (rc != 0) {
9123 pr_err("error %d\n", rc);
9124 goto rw_error;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009125 }
9126 break;
9127 case DRX_CONSTELLATION_AUTO: /* for channel scan */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009128 if (ext_attr->standard == DRX_STANDARD_ITU_B) {
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009129 u16 qam_ctl_ena = 0;
9130
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009131 auto_flag = true;
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009132
9133 /* try to lock default QAM constellation: QAM256 */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009134 channel->constellation = DRX_CONSTELLATION_QAM256;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009135 ext_attr->constellation = DRX_CONSTELLATION_QAM256;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03009136 if (channel->mirror == DRX_MIRROR_AUTO)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009137 ext_attr->mirror = DRX_MIRROR_NO;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03009138 else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009139 ext_attr->mirror = channel->mirror;
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009140 rc = set_qam(demod, channel, tuner_freq_offset,
9141 QAM_SET_OP_ALL);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009142 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009143 pr_err("error %d\n", rc);
9144 goto rw_error;
9145 }
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009146 rc = qam256auto(demod, channel, tuner_freq_offset,
9147 &lock_status);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009148 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009149 pr_err("error %d\n", rc);
9150 goto rw_error;
9151 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009152
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009153 if (lock_status >= DRX_LOCKED) {
9154 channel->constellation = DRX_CONSTELLATION_AUTO;
9155 break;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009156 }
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009157
9158 /* QAM254 not locked. Try QAM64 constellation */
9159 channel->constellation = DRX_CONSTELLATION_QAM64;
9160 ext_attr->constellation = DRX_CONSTELLATION_QAM64;
9161 if (channel->mirror == DRX_MIRROR_AUTO)
9162 ext_attr->mirror = DRX_MIRROR_NO;
9163 else
9164 ext_attr->mirror = channel->mirror;
9165
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009166 rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr,
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009167 SCU_RAM_QAM_CTL_ENA__A,
9168 &qam_ctl_ena, 0);
9169 if (rc != 0) {
9170 pr_err("error %d\n", rc);
9171 goto rw_error;
9172 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009173 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr,
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009174 SCU_RAM_QAM_CTL_ENA__A,
9175 qam_ctl_ena & ~SCU_RAM_QAM_CTL_ENA_ACQ__M, 0);
9176 if (rc != 0) {
9177 pr_err("error %d\n", rc);
9178 goto rw_error;
9179 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009180 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr,
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009181 SCU_RAM_QAM_FSM_STATE_TGT__A,
9182 0x2, 0);
9183 if (rc != 0) {
9184 pr_err("error %d\n", rc);
9185 goto rw_error;
9186 } /* force to rate hunting */
9187
9188 rc = set_qam(demod, channel, tuner_freq_offset,
9189 QAM_SET_OP_CONSTELLATION);
9190 if (rc != 0) {
9191 pr_err("error %d\n", rc);
9192 goto rw_error;
9193 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009194 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr,
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009195 SCU_RAM_QAM_CTL_ENA__A,
9196 qam_ctl_ena, 0);
9197 if (rc != 0) {
9198 pr_err("error %d\n", rc);
9199 goto rw_error;
9200 }
9201
9202 rc = qam64auto(demod, channel, tuner_freq_offset,
9203 &lock_status);
9204 if (rc != 0) {
9205 pr_err("error %d\n", rc);
9206 goto rw_error;
9207 }
9208
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009209 channel->constellation = DRX_CONSTELLATION_AUTO;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009210 } else if (ext_attr->standard == DRX_STANDARD_ITU_C) {
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009211 u16 qam_ctl_ena = 0;
9212
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009213 channel->constellation = DRX_CONSTELLATION_QAM64;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009214 ext_attr->constellation = DRX_CONSTELLATION_QAM64;
9215 auto_flag = true;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009216
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03009217 if (channel->mirror == DRX_MIRROR_AUTO)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009218 ext_attr->mirror = DRX_MIRROR_NO;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03009219 else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009220 ext_attr->mirror = channel->mirror;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009221 rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr,
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009222 SCU_RAM_QAM_CTL_ENA__A,
9223 &qam_ctl_ena, 0);
9224 if (rc != 0) {
9225 pr_err("error %d\n", rc);
9226 goto rw_error;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009227 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009228 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr,
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009229 SCU_RAM_QAM_CTL_ENA__A,
9230 qam_ctl_ena & ~SCU_RAM_QAM_CTL_ENA_ACQ__M, 0);
9231 if (rc != 0) {
9232 pr_err("error %d\n", rc);
9233 goto rw_error;
9234 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009235 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr,
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009236 SCU_RAM_QAM_FSM_STATE_TGT__A,
9237 0x2, 0);
9238 if (rc != 0) {
9239 pr_err("error %d\n", rc);
9240 goto rw_error;
9241 } /* force to rate hunting */
9242
9243 rc = set_qam(demod, channel, tuner_freq_offset,
9244 QAM_SET_OP_CONSTELLATION);
9245 if (rc != 0) {
9246 pr_err("error %d\n", rc);
9247 goto rw_error;
9248 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009249 rc = drxj_dap_write_reg16(demod->my_i2c_dev_addr,
Mauro Carvalho Chehab938f11f2014-01-26 16:41:51 -03009250 SCU_RAM_QAM_CTL_ENA__A,
9251 qam_ctl_ena, 0);
9252 if (rc != 0) {
9253 pr_err("error %d\n", rc);
9254 goto rw_error;
9255 }
9256 rc = qam64auto(demod, channel, tuner_freq_offset,
9257 &lock_status);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009258 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009259 pr_err("error %d\n", rc);
9260 goto rw_error;
9261 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009262 channel->constellation = DRX_CONSTELLATION_AUTO;
9263 } else {
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009264 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009265 }
9266 break;
9267 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009268 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009269 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009270
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009271 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009272rw_error:
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009273 /* restore starting value */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009274 if (auto_flag)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009275 channel->constellation = DRX_CONSTELLATION_AUTO;
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009276 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009277}
9278
9279/*============================================================================*/
9280
9281/**
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -03009282* \fn static short get_qamrs_err_count(struct i2c_device_addr *dev_addr)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009283* \brief Get RS error count in QAM mode (used for post RS BER calculation)
9284* \return Error code
9285*
9286* precondition: measurement period & measurement prescale must be set
9287*
9288*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03009289static int
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03009290get_qamrs_err_count(struct i2c_device_addr *dev_addr,
9291 struct drxjrs_errors *rs_errors)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009292{
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009293 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009294 u16 nr_bit_errors = 0,
9295 nr_symbol_errors = 0,
9296 nr_packet_errors = 0, nr_failures = 0, nr_snc_par_fail_count = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009297
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009298 /* check arguments */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03009299 if (dev_addr == NULL)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009300 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009301
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009302 /* all reported errors are received in the */
9303 /* most recently finished measurment period */
9304 /* no of pre RS bit errors */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009305 rc = drxj_dap_read_reg16(dev_addr, FEC_RS_NR_BIT_ERRORS__A, &nr_bit_errors, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009306 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009307 pr_err("error %d\n", rc);
9308 goto rw_error;
9309 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009310 /* no of symbol errors */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009311 rc = drxj_dap_read_reg16(dev_addr, FEC_RS_NR_SYMBOL_ERRORS__A, &nr_symbol_errors, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009312 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009313 pr_err("error %d\n", rc);
9314 goto rw_error;
9315 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009316 /* no of packet errors */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009317 rc = drxj_dap_read_reg16(dev_addr, FEC_RS_NR_PACKET_ERRORS__A, &nr_packet_errors, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009318 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009319 pr_err("error %d\n", rc);
9320 goto rw_error;
9321 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009322 /* no of failures to decode */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009323 rc = drxj_dap_read_reg16(dev_addr, FEC_RS_NR_FAILURES__A, &nr_failures, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009324 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009325 pr_err("error %d\n", rc);
9326 goto rw_error;
9327 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009328 /* no of post RS bit erros */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009329 rc = drxj_dap_read_reg16(dev_addr, FEC_OC_SNC_FAIL_COUNT__A, &nr_snc_par_fail_count, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009330 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009331 pr_err("error %d\n", rc);
9332 goto rw_error;
9333 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009334 /* TODO: NOTE */
9335 /* These register values are fetched in non-atomic fashion */
9336 /* It is possible that the read values contain unrelated information */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009337
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009338 rs_errors->nr_bit_errors = nr_bit_errors & FEC_RS_NR_BIT_ERRORS__M;
9339 rs_errors->nr_symbol_errors = nr_symbol_errors & FEC_RS_NR_SYMBOL_ERRORS__M;
9340 rs_errors->nr_packet_errors = nr_packet_errors & FEC_RS_NR_PACKET_ERRORS__M;
9341 rs_errors->nr_failures = nr_failures & FEC_RS_NR_FAILURES__M;
9342 rs_errors->nr_snc_par_fail_count =
9343 nr_snc_par_fail_count & FEC_OC_SNC_FAIL_COUNT__M;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009344
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009345 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009346rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009347 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009348}
9349
9350/*============================================================================*/
9351
9352/**
Mauro Carvalho Chehab80e5ed12014-03-09 17:37:27 -03009353 * \fn int get_sig_strength()
9354 * \brief Retrieve signal strength for VSB and QAM.
9355 * \param demod Pointer to demod instance
9356 * \param u16-t Pointer to signal strength data; range 0, .. , 100.
9357 * \return int.
9358 * \retval 0 sig_strength contains valid data.
9359 * \retval -EINVAL sig_strength is NULL.
9360 * \retval -EIO Erroneous data, sig_strength contains invalid data.
9361 */
9362#define DRXJ_AGC_TOP 0x2800
9363#define DRXJ_AGC_SNS 0x1600
9364#define DRXJ_RFAGC_MAX 0x3fff
9365#define DRXJ_RFAGC_MIN 0x800
9366
9367static int get_sig_strength(struct drx_demod_instance *demod, u16 *sig_strength)
9368{
9369 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
9370 int rc;
9371 u16 rf_gain = 0;
9372 u16 if_gain = 0;
9373 u16 if_agc_sns = 0;
9374 u16 if_agc_top = 0;
9375 u16 rf_agc_max = 0;
9376 u16 rf_agc_min = 0;
9377
9378 rc = drxj_dap_read_reg16(dev_addr, IQM_AF_AGC_IF__A, &if_gain, 0);
9379 if (rc != 0) {
9380 pr_err("error %d\n", rc);
9381 goto rw_error;
9382 }
9383 if_gain &= IQM_AF_AGC_IF__M;
9384 rc = drxj_dap_read_reg16(dev_addr, IQM_AF_AGC_RF__A, &rf_gain, 0);
9385 if (rc != 0) {
9386 pr_err("error %d\n", rc);
9387 goto rw_error;
9388 }
9389 rf_gain &= IQM_AF_AGC_RF__M;
9390
9391 if_agc_sns = DRXJ_AGC_SNS;
9392 if_agc_top = DRXJ_AGC_TOP;
9393 rf_agc_max = DRXJ_RFAGC_MAX;
9394 rf_agc_min = DRXJ_RFAGC_MIN;
9395
9396 if (if_gain > if_agc_top) {
9397 if (rf_gain > rf_agc_max)
9398 *sig_strength = 100;
9399 else if (rf_gain > rf_agc_min) {
9400 if (rf_agc_max == rf_agc_min) {
9401 pr_err("error: rf_agc_max == rf_agc_min\n");
9402 return -EIO;
9403 }
9404 *sig_strength =
9405 75 + 25 * (rf_gain - rf_agc_min) / (rf_agc_max -
9406 rf_agc_min);
9407 } else
9408 *sig_strength = 75;
9409 } else if (if_gain > if_agc_sns) {
9410 if (if_agc_top == if_agc_sns) {
9411 pr_err("error: if_agc_top == if_agc_sns\n");
9412 return -EIO;
9413 }
9414 *sig_strength =
9415 20 + 55 * (if_gain - if_agc_sns) / (if_agc_top - if_agc_sns);
9416 } else {
9417 if (!if_agc_sns) {
9418 pr_err("error: if_agc_sns is zero!\n");
9419 return -EIO;
9420 }
9421 *sig_strength = (20 * if_gain / if_agc_sns);
9422 }
9423
Mauro Carvalho Chehab80846a52014-03-10 08:18:31 -03009424 if (*sig_strength <= 7)
9425 *sig_strength = 0;
9426
Mauro Carvalho Chehab80e5ed12014-03-09 17:37:27 -03009427 return 0;
9428 rw_error:
9429 return -EIO;
9430}
9431
9432/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009433* \fn int ctrl_get_qam_sig_quality()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009434* \brief Retreive QAM signal quality from device.
9435* \param devmod Pointer to demodulator instance.
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009436* \param sig_quality Pointer to signal quality data.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03009437* \return int.
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009438* \retval 0 sig_quality contains valid data.
9439* \retval -EINVAL sig_quality is NULL.
9440* \retval -EIO Erroneous data, sig_quality contains invalid data.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009441
9442* Pre-condition: Device must be started and in lock.
9443*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03009444static int
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03009445ctrl_get_qam_sig_quality(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009446{
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03009447 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
9448 struct drxj_data *ext_attr = demod->my_ext_attr;
9449 struct drx39xxj_state *state = dev_addr->user_data;
9450 struct dtv_frontend_properties *p = &state->frontend.dtv_property_cache;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03009451 struct drxjrs_errors measuredrs_errors = { 0, 0, 0, 0, 0 };
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03009452 enum drx_modulation constellation = ext_attr->constellation;
9453 int rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009454
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009455 u32 pre_bit_err_rs = 0; /* pre RedSolomon Bit Error Rate */
9456 u32 post_bit_err_rs = 0; /* post RedSolomon Bit Error Rate */
9457 u32 pkt_errs = 0; /* no of packet errors in RS */
9458 u16 qam_sl_err_power = 0; /* accumulated error between raw and sliced symbols */
9459 u16 qsym_err_vd = 0; /* quadrature symbol errors in QAM_VD */
9460 u16 fec_oc_period = 0; /* SNC sync failure measurement period */
9461 u16 fec_rs_prescale = 0; /* ReedSolomon Measurement Prescale */
9462 u16 fec_rs_period = 0; /* Value for corresponding I2C register */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009463 /* calculation constants */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009464 u32 rs_bit_cnt = 0; /* RedSolomon Bit Count */
9465 u32 qam_sl_sig_power = 0; /* used for MER, depends of QAM constellation */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009466 /* intermediate results */
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03009467 u32 e = 0; /* exponent value used for QAM BER/SER */
9468 u32 m = 0; /* mantisa value used for QAM BER/SER */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009469 u32 ber_cnt = 0; /* BER count */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009470 /* signal quality info */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009471 u32 qam_sl_mer = 0; /* QAM MER */
9472 u32 qam_pre_rs_ber = 0; /* Pre RedSolomon BER */
9473 u32 qam_post_rs_ber = 0; /* Post RedSolomon BER */
9474 u32 qam_vd_ser = 0; /* ViterbiDecoder SER */
9475 u16 qam_vd_prescale = 0; /* Viterbi Measurement Prescale */
9476 u16 qam_vd_period = 0; /* Viterbi Measurement period */
9477 u32 vd_bit_cnt = 0; /* ViterbiDecoder Bit Count */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009478
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03009479 p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
9480
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009481 /* read the physical registers */
9482 /* Get the RS error data */
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -03009483 rc = get_qamrs_err_count(dev_addr, &measuredrs_errors);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009484 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009485 pr_err("error %d\n", rc);
9486 goto rw_error;
9487 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009488 /* get the register value needed for MER */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009489 rc = drxj_dap_read_reg16(dev_addr, QAM_SL_ERR_POWER__A, &qam_sl_err_power, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009490 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009491 pr_err("error %d\n", rc);
9492 goto rw_error;
9493 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009494 /* get the register value needed for post RS BER */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009495 rc = drxj_dap_read_reg16(dev_addr, FEC_OC_SNC_FAIL_PERIOD__A, &fec_oc_period, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009496 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009497 pr_err("error %d\n", rc);
9498 goto rw_error;
9499 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009500
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009501 /* get constants needed for signal quality calculation */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009502 fec_rs_period = ext_attr->fec_rs_period;
9503 fec_rs_prescale = ext_attr->fec_rs_prescale;
9504 rs_bit_cnt = fec_rs_period * fec_rs_prescale * ext_attr->fec_rs_plen;
9505 qam_vd_period = ext_attr->qam_vd_period;
9506 qam_vd_prescale = ext_attr->qam_vd_prescale;
9507 vd_bit_cnt = qam_vd_period * qam_vd_prescale * ext_attr->fec_vd_plen;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009508
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009509 /* DRXJ_QAM_SL_SIG_POWER_QAMxxx * 4 */
9510 switch (constellation) {
9511 case DRX_CONSTELLATION_QAM16:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009512 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM16 << 2;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009513 break;
9514 case DRX_CONSTELLATION_QAM32:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009515 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM32 << 2;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009516 break;
9517 case DRX_CONSTELLATION_QAM64:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009518 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM64 << 2;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009519 break;
9520 case DRX_CONSTELLATION_QAM128:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009521 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM128 << 2;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009522 break;
9523 case DRX_CONSTELLATION_QAM256:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009524 qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM256 << 2;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009525 break;
9526 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009527 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009528 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009529
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009530 /* ------------------------------ */
9531 /* MER Calculation */
9532 /* ------------------------------ */
9533 /* MER is good if it is above 27.5 for QAM256 or 21.5 for QAM64 */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009534
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009535 /* 10.0*log10(qam_sl_sig_power * 4.0 / qam_sl_err_power); */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009536 if (qam_sl_err_power == 0)
9537 qam_sl_mer = 0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009538 else
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03009539 qam_sl_mer = log1_times100(qam_sl_sig_power) - log1_times100((u32)qam_sl_err_power);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009540
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009541 /* ----------------------------------------- */
9542 /* Pre Viterbi Symbol Error Rate Calculation */
9543 /* ----------------------------------------- */
9544 /* pre viterbi SER is good if it is bellow 0.025 */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009545
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009546 /* get the register value */
9547 /* no of quadrature symbol errors */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009548 rc = drxj_dap_read_reg16(dev_addr, QAM_VD_NR_QSYM_ERRORS__A, &qsym_err_vd, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009549 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009550 pr_err("error %d\n", rc);
9551 goto rw_error;
9552 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009553 /* Extract the Exponent and the Mantisa */
9554 /* of number of quadrature symbol errors */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009555 e = (qsym_err_vd & QAM_VD_NR_QSYM_ERRORS_EXP__M) >>
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009556 QAM_VD_NR_QSYM_ERRORS_EXP__B;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009557 m = (qsym_err_vd & QAM_VD_NR_SYMBOL_ERRORS_FIXED_MANT__M) >>
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009558 QAM_VD_NR_SYMBOL_ERRORS_FIXED_MANT__B;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009559
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03009560 if ((m << e) >> 3 > 549752)
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03009561 qam_vd_ser = 500000 * vd_bit_cnt * ((e > 2) ? 1 : 8) / 8;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03009562 else
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03009563 qam_vd_ser = m << ((e > 2) ? (e - 3) : e);
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009564
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009565 /* --------------------------------------- */
9566 /* pre and post RedSolomon BER Calculation */
9567 /* --------------------------------------- */
9568 /* pre RS BER is good if it is below 3.5e-4 */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009569
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009570 /* get the register values */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009571 pre_bit_err_rs = (u32) measuredrs_errors.nr_bit_errors;
9572 pkt_errs = post_bit_err_rs = (u32) measuredrs_errors.nr_snc_par_fail_count;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009573
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009574 /* Extract the Exponent and the Mantisa of the */
9575 /* pre Reed-Solomon bit error count */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009576 e = (pre_bit_err_rs & FEC_RS_NR_BIT_ERRORS_EXP__M) >>
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009577 FEC_RS_NR_BIT_ERRORS_EXP__B;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009578 m = (pre_bit_err_rs & FEC_RS_NR_BIT_ERRORS_FIXED_MANT__M) >>
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009579 FEC_RS_NR_BIT_ERRORS_FIXED_MANT__B;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009580
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009581 ber_cnt = m << e;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009582
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009583 /*qam_pre_rs_ber = frac_times1e6( ber_cnt, rs_bit_cnt ); */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03009584 if (m > (rs_bit_cnt >> (e + 1)) || (rs_bit_cnt >> e) == 0)
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03009585 qam_pre_rs_ber = 500000 * rs_bit_cnt >> e;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03009586 else
Mauro Carvalho Chehabee0f4a12014-03-11 07:34:44 -03009587 qam_pre_rs_ber = ber_cnt;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009588
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009589 /* post RS BER = 1000000* (11.17 * FEC_OC_SNC_FAIL_COUNT__A) / */
9590 /* (1504.0 * FEC_OC_SNC_FAIL_PERIOD__A) */
9591 /*
9592 => c = (1000000*100*11.17)/1504 =
9593 post RS BER = (( c* FEC_OC_SNC_FAIL_COUNT__A) /
9594 (100 * FEC_OC_SNC_FAIL_PERIOD__A)
9595 *100 and /100 is for more precision.
9596 => (20 bits * 12 bits) /(16 bits * 7 bits) => safe in 32 bits computation
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009597
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009598 Precision errors still possible.
9599 */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009600 e = post_bit_err_rs * 742686;
9601 m = fec_oc_period * 100;
9602 if (fec_oc_period == 0)
9603 qam_post_rs_ber = 0xFFFFFFFF;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009604 else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009605 qam_post_rs_ber = e / m;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009606
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009607 /* fill signal quality data structure */
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03009608 p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
9609 p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
9610 p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
9611 p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
9612 p->block_error.stat[0].scale = FE_SCALE_COUNTER;
9613 p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
9614
9615 p->cnr.stat[0].svalue = ((u16) qam_sl_mer) * 100;
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03009616 if (ext_attr->standard == DRX_STANDARD_ITU_B) {
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03009617 p->pre_bit_error.stat[0].uvalue += qam_vd_ser;
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03009618 p->pre_bit_count.stat[0].uvalue += vd_bit_cnt * ((e > 2) ? 1 : 8) / 8;
9619 } else {
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03009620 p->pre_bit_error.stat[0].uvalue += qam_pre_rs_ber;
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -03009621 p->pre_bit_count.stat[0].uvalue += rs_bit_cnt >> e;
9622 }
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03009623
Mauro Carvalho Chehab0d49e772014-03-11 07:43:54 -03009624 p->post_bit_error.stat[0].uvalue += qam_post_rs_ber;
9625 p->post_bit_count.stat[0].uvalue += rs_bit_cnt >> e;
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03009626
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03009627 p->block_error.stat[0].uvalue += pkt_errs;
9628
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009629#ifdef DRXJ_SIGNAL_ACCUM_ERR
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009630 rc = get_acc_pkt_err(demod, &sig_quality->packet_error);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009631 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009632 pr_err("error %d\n", rc);
9633 goto rw_error;
9634 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009635#endif
9636
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009637 return 0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009638rw_error:
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -03009639 p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
9640 p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
9641 p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
9642 p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
9643 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
9644 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
9645
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009646 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009647}
9648
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009649#endif /* #ifndef DRXJ_VSB_ONLY */
9650
9651/*============================================================================*/
9652/*== END QAM DATAPATH FUNCTIONS ==*/
9653/*============================================================================*/
9654
9655/*============================================================================*/
9656/*============================================================================*/
9657/*== ATV DATAPATH FUNCTIONS ==*/
9658/*============================================================================*/
9659/*============================================================================*/
9660
9661/*
9662 Implementation notes.
9663
9664 NTSC/FM AGCs
9665
9666 Four AGCs are used for NTSC:
9667 (1) RF (used to attenuate the input signal in case of to much power)
9668 (2) IF (used to attenuate the input signal in case of to much power)
9669 (3) Video AGC (used to amplify the output signal in case input to low)
9670 (4) SIF AGC (used to amplify the output signal in case input to low)
9671
9672 Video AGC is coupled to RF and IF. SIF AGC is not coupled. It is assumed
9673 that the coupling between Video AGC and the RF and IF AGCs also works in
9674 favor of the SIF AGC.
9675
9676 Three AGCs are used for FM:
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) SIF AGC (used to amplify the output signal in case input to low)
9680
9681 The SIF AGC is now coupled to the RF/IF AGCs.
9682 The SIF AGC is needed for both SIF ouput and the internal SIF signal to
9683 the AUD block.
9684
9685 RF and IF AGCs DACs are part of AFE, Video and SIF AGC DACs are part of
9686 the ATV block. The AGC control algorithms are all implemented in
9687 microcode.
9688
9689 ATV SETTINGS
9690
9691 (Shadow settings will not be used for now, they will be implemented
9692 later on because of the schedule)
9693
9694 Several HW/SCU "settings" can be used for ATV. The standard selection
9695 will reset most of these settings. To avoid that the end user apllication
9696 has to perform these settings each time the ATV or FM standards is
9697 selected the driver will shadow these settings. This enables the end user
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009698 to perform the settings only once after a drx_open(). The driver must
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009699 write the shadow settings to HW/SCU incase:
9700 ( setstandard FM/ATV) ||
9701 ( settings have changed && FM/ATV standard is active)
9702 The shadow settings will be stored in the device specific data container.
9703 A set of flags will be defined to flag changes in shadow settings.
9704 A routine will be implemented to write all changed shadow settings to
9705 HW/SCU.
9706
9707 The "settings" will consist of: AGC settings, filter settings etc.
9708
9709 Disadvantage of use of shadow settings:
9710 Direct changes in HW/SCU registers will not be reflected in the
9711 shadow settings and these changes will be overwritten during a next
9712 update. This can happen during evaluation. This will not be a problem
9713 for normal customer usage.
9714*/
9715/* -------------------------------------------------------------------------- */
9716
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009717/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009718* \fn int power_down_atv ()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009719* \brief Power down ATV.
9720* \param demod instance of demodulator
9721* \param standard either NTSC or FM (sub strandard for ATV )
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03009722* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009723*
9724* Stops and thus resets ATV and IQM block
9725* SIF and CVBS ADC are powered down
9726* Calls audio power down
9727*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03009728static int
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03009729power_down_atv(struct drx_demod_instance *demod, enum drx_standard standard, bool primary)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009730{
Mauro Carvalho Chehab4d7bb0e2014-01-16 11:49:13 -03009731 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03009732 struct drxjscu_cmd cmd_scu = { /* command */ 0,
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009733 /* parameter_len */ 0,
9734 /* result_len */ 0,
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009735 /* *parameter */ NULL,
9736 /* *result */ NULL
9737 };
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009738 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009739 u16 cmd_result = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009740
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009741 /* ATV NTSC */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009742
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009743 /* Stop ATV SCU (will reset ATV and IQM hardware */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009744 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_ATV |
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009745 SCU_RAM_COMMAND_CMD_DEMOD_STOP;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009746 cmd_scu.parameter_len = 0;
9747 cmd_scu.result_len = 1;
9748 cmd_scu.parameter = NULL;
9749 cmd_scu.result = &cmd_result;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009750 rc = scu_command(dev_addr, &cmd_scu);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009751 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009752 pr_err("error %d\n", rc);
9753 goto rw_error;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009754 }
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009755 /* Disable ATV outputs (ATV reset enables CVBS, undo this) */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009756 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009757 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009758 pr_err("error %d\n", rc);
9759 goto rw_error;
9760 }
9761
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009762 rc = drxj_dap_write_reg16(dev_addr, ATV_COMM_EXEC__A, ATV_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009763 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009764 pr_err("error %d\n", rc);
9765 goto rw_error;
9766 }
Mauro Carvalho Chehab259f3802014-01-17 06:40:47 -03009767 if (primary) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009768 rc = drxj_dap_write_reg16(dev_addr, IQM_COMM_EXEC__A, IQM_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009769 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009770 pr_err("error %d\n", rc);
9771 goto rw_error;
9772 }
9773 rc = set_iqm_af(demod, false);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009774 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009775 pr_err("error %d\n", rc);
9776 goto rw_error;
9777 }
9778 } else {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009779 rc = drxj_dap_write_reg16(dev_addr, IQM_FS_COMM_EXEC__A, IQM_FS_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009780 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009781 pr_err("error %d\n", rc);
9782 goto rw_error;
9783 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009784 rc = drxj_dap_write_reg16(dev_addr, IQM_FD_COMM_EXEC__A, IQM_FD_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009785 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009786 pr_err("error %d\n", rc);
9787 goto rw_error;
9788 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009789 rc = drxj_dap_write_reg16(dev_addr, IQM_RC_COMM_EXEC__A, IQM_RC_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009790 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009791 pr_err("error %d\n", rc);
9792 goto rw_error;
9793 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009794 rc = drxj_dap_write_reg16(dev_addr, IQM_RT_COMM_EXEC__A, IQM_RT_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009795 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009796 pr_err("error %d\n", rc);
9797 goto rw_error;
9798 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009799 rc = drxj_dap_write_reg16(dev_addr, IQM_CF_COMM_EXEC__A, IQM_CF_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009800 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009801 pr_err("error %d\n", rc);
9802 goto rw_error;
9803 }
9804 }
9805 rc = power_down_aud(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009806 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009807 pr_err("error %d\n", rc);
9808 goto rw_error;
9809 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009810
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009811 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009812rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009813 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009814}
9815
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009816/*============================================================================*/
9817
9818/**
9819* \brief Power up AUD.
9820* \param demod instance of demodulator
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03009821* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009822*
9823*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03009824static int power_down_aud(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009825{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009826 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03009827 struct drxj_data *ext_attr = NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009828 int rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009829
Mauro Carvalho Chehab22892262014-01-16 11:28:52 -03009830 dev_addr = (struct i2c_device_addr *)demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03009831 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009832
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009833 rc = drxj_dap_write_reg16(dev_addr, AUD_COMM_EXEC__A, AUD_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009834 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009835 pr_err("error %d\n", rc);
9836 goto rw_error;
9837 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009838
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009839 ext_attr->aud_data.audio_is_active = false;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009840
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009841 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009842rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009843 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009844}
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009845
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009846/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009847* \fn int set_orx_nsu_aox()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009848* \brief Configure OrxNsuAox for OOB
9849* \param demod instance of demodulator.
9850* \param active
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03009851* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009852*/
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03009853static int set_orx_nsu_aox(struct drx_demod_instance *demod, bool active)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009854{
Mauro Carvalho Chehab4d7bb0e2014-01-16 11:49:13 -03009855 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009856 int rc;
9857 u16 data = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009858
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009859 /* Configure NSU_AOX */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009860 rc = drxj_dap_read_reg16(dev_addr, ORX_NSU_AOX_STDBY_W__A, &data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009861 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009862 pr_err("error %d\n", rc);
9863 goto rw_error;
9864 }
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03009865 if (!active)
9866 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));
9867 else
9868 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);
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009869 rc = drxj_dap_write_reg16(dev_addr, ORX_NSU_AOX_STDBY_W__A, data, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009870 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009871 pr_err("error %d\n", rc);
9872 goto rw_error;
9873 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009874
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009875 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009876rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009877 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009878}
9879
9880/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009881* \fn int ctrl_set_oob()
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009882* \brief Set OOB channel to be used.
9883* \param demod instance of demodulator
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009884* \param oob_param OOB parameters for channel setting.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009885* \frequency should be in KHz
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -03009886* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009887*
9888* Accepts only. Returns error otherwise.
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009889* Demapper value is written after scu_command START
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009890* because START command causes COMM_EXEC transition
9891* from 0 to 1 which causes all registers to be
9892* overwritten with initial value
9893*
9894*/
9895
9896/* Nyquist filter impulse response */
Mauro Carvalho Chehab7ef66752014-01-16 11:08:15 -03009897#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 */
9898#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 */
9899#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) */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009900
9901/* Coefficients for the nyquist fitler (total: 27 taps) */
9902#define NYQFILTERLEN 27
9903
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -03009904static int ctrl_set_oob(struct drx_demod_instance *demod, struct drxoob *oob_param)
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009905{
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009906 int rc;
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -03009907 s32 freq = 0; /* KHz */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009908 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03009909 struct drxj_data *ext_attr = NULL;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03009910 u16 i = 0;
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -03009911 bool mirror_freq_spect_oob = false;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009912 u16 trk_filter_value = 0;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03009913 struct drxjscu_cmd scu_cmd;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009914 u16 set_param_parameters[3];
9915 u16 cmd_result[2] = { 0, 0 };
9916 s16 nyquist_coeffs[4][(NYQFILTERLEN + 1) / 2] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009917 IMPULSE_COSINE_ALPHA_0_3, /* Target Mode 0 */
9918 IMPULSE_COSINE_ALPHA_0_3, /* Target Mode 1 */
9919 IMPULSE_COSINE_ALPHA_0_5, /* Target Mode 2 */
9920 IMPULSE_COSINE_ALPHA_RO_0_5 /* Target Mode 3 */
9921 };
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03009922 u8 mode_val[4] = { 2, 2, 0, 1 };
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009923 u8 pfi_coeffs[4][6] = {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009924 {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) */
9925 {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) */
9926 {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) */
9927 {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) */
9928 };
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03009929 u16 mode_index;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009930
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009931 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -03009932 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -03009933 mirror_freq_spect_oob = ext_attr->mirror_freq_spect_oob;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009934
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009935 /* Check parameters */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009936 if (oob_param == NULL) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009937 /* power off oob module */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009938 scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009939 | SCU_RAM_COMMAND_CMD_DEMOD_STOP;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009940 scu_cmd.parameter_len = 0;
9941 scu_cmd.result_len = 1;
9942 scu_cmd.result = cmd_result;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009943 rc = scu_command(dev_addr, &scu_cmd);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009944 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009945 pr_err("error %d\n", rc);
9946 goto rw_error;
9947 }
9948 rc = set_orx_nsu_aox(demod, false);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009949 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009950 pr_err("error %d\n", rc);
9951 goto rw_error;
9952 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009953 rc = drxj_dap_write_reg16(dev_addr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009954 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03009955 pr_err("error %d\n", rc);
9956 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009957 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009958
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009959 ext_attr->oob_power_on = false;
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009960 return 0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009961 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009962
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009963 freq = oob_param->frequency;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009964 if ((freq < 70000) || (freq > 130000))
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009965 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009966 freq = (freq - 50000) / 50;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009967
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009968 {
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03009969 u16 index = 0;
9970 u16 remainder = 0;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009971 u16 *trk_filtercfg = ext_attr->oob_trk_filter_cfg;
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009972
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -03009973 index = (u16) ((freq - 400) / 200);
9974 remainder = (u16) ((freq - 400) % 200);
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009975 trk_filter_value =
9976 trk_filtercfg[index] - (trk_filtercfg[index] -
9977 trk_filtercfg[index +
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009978 1]) / 10 * remainder /
9979 20;
9980 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009981
9982 /*********/
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009983 /* Stop */
Devin Heitmueller38b2df92012-08-13 21:18:02 -03009984 /*********/
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -03009985 rc = drxj_dap_write_reg16(dev_addr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009986 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -03009987 pr_err("error %d\n", rc);
9988 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009989 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009990 scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -03009991 | SCU_RAM_COMMAND_CMD_DEMOD_STOP;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -03009992 scu_cmd.parameter_len = 0;
9993 scu_cmd.result_len = 1;
9994 scu_cmd.result = cmd_result;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009995 rc = scu_command(dev_addr, &scu_cmd);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -03009996 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -03009997 pr_err("error %d\n", rc);
9998 goto rw_error;
9999 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010000 /*********/
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010001 /* Reset */
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010002 /*********/
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010003 scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010004 | SCU_RAM_COMMAND_CMD_DEMOD_RESET;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010005 scu_cmd.parameter_len = 0;
10006 scu_cmd.result_len = 1;
10007 scu_cmd.result = cmd_result;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010008 rc = scu_command(dev_addr, &scu_cmd);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010009 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010010 pr_err("error %d\n", rc);
10011 goto rw_error;
10012 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010013 /***********/
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010014 /* SET_ENV */
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010015 /***********/
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010016 /* set frequency, spectrum inversion and data rate */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010017 scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010018 | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010019 scu_cmd.parameter_len = 3;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010020 /* 1-data rate;2-frequency */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010021 switch (oob_param->standard) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010022 case DRX_OOB_MODE_A:
10023 if (
10024 /* signal is transmitted inverted */
Mauro Carvalho Chehab87bf0e52014-03-09 09:36:59 -030010025 ((oob_param->spectrum_inverted == true) &&
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010026 /* and tuner is not mirroring the signal */
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -030010027 (!mirror_freq_spect_oob)) |
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010028 /* or */
10029 /* signal is transmitted noninverted */
Mauro Carvalho Chehab87bf0e52014-03-09 09:36:59 -030010030 ((oob_param->spectrum_inverted == false) &&
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010031 /* and tuner is mirroring the signal */
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -030010032 (mirror_freq_spect_oob))
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010033 )
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010034 set_param_parameters[0] =
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010035 SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_INVSPEC;
10036 else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010037 set_param_parameters[0] =
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010038 SCU_RAM_ORX_RF_RX_DATA_RATE_2048KBPS_REGSPEC;
10039 break;
10040 case DRX_OOB_MODE_B_GRADE_A:
10041 if (
10042 /* signal is transmitted inverted */
Mauro Carvalho Chehab87bf0e52014-03-09 09:36:59 -030010043 ((oob_param->spectrum_inverted == true) &&
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010044 /* and tuner is not mirroring the signal */
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -030010045 (!mirror_freq_spect_oob)) |
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010046 /* or */
10047 /* signal is transmitted noninverted */
Mauro Carvalho Chehab87bf0e52014-03-09 09:36:59 -030010048 ((oob_param->spectrum_inverted == false) &&
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010049 /* and tuner is mirroring the signal */
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -030010050 (mirror_freq_spect_oob))
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010051 )
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010052 set_param_parameters[0] =
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010053 SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_INVSPEC;
10054 else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010055 set_param_parameters[0] =
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010056 SCU_RAM_ORX_RF_RX_DATA_RATE_1544KBPS_REGSPEC;
10057 break;
10058 case DRX_OOB_MODE_B_GRADE_B:
10059 default:
10060 if (
10061 /* signal is transmitted inverted */
Mauro Carvalho Chehab87bf0e52014-03-09 09:36:59 -030010062 ((oob_param->spectrum_inverted == true) &&
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010063 /* and tuner is not mirroring the signal */
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -030010064 (!mirror_freq_spect_oob)) |
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010065 /* or */
10066 /* signal is transmitted noninverted */
Mauro Carvalho Chehab87bf0e52014-03-09 09:36:59 -030010067 ((oob_param->spectrum_inverted == false) &&
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010068 /* and tuner is mirroring the signal */
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -030010069 (mirror_freq_spect_oob))
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010070 )
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010071 set_param_parameters[0] =
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010072 SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_INVSPEC;
10073 else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010074 set_param_parameters[0] =
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010075 SCU_RAM_ORX_RF_RX_DATA_RATE_3088KBPS_REGSPEC;
10076 break;
10077 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010078 set_param_parameters[1] = (u16) (freq & 0xFFFF);
10079 set_param_parameters[2] = trk_filter_value;
10080 scu_cmd.parameter = set_param_parameters;
10081 scu_cmd.result_len = 1;
10082 scu_cmd.result = cmd_result;
10083 mode_index = mode_val[(set_param_parameters[0] & 0xC0) >> 6];
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010084 rc = scu_command(dev_addr, &scu_cmd);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010085 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010086 pr_err("error %d\n", rc);
10087 goto rw_error;
10088 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010089
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010090 rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010091 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010092 pr_err("error %d\n", rc);
10093 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010094 } /* Write magic word to enable pdr reg write */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010095 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010096 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010097 pr_err("error %d\n", rc);
10098 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010099 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010100 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010101 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010102 pr_err("error %d\n", rc);
10103 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010104 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010105 rc = drxj_dap_write_reg16(dev_addr, SIO_TOP_COMM_KEY__A, 0x0000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010106 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010107 pr_err("error %d\n", rc);
10108 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010109 } /* Write magic word to disable pdr reg write */
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010110
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010111 rc = drxj_dap_write_reg16(dev_addr, ORX_TOP_COMM_KEY__A, 0, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010112 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010113 pr_err("error %d\n", rc);
10114 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010115 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010116 rc = drxj_dap_write_reg16(dev_addr, ORX_FWP_AAG_LEN_W__A, 16000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010117 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010118 pr_err("error %d\n", rc);
10119 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010120 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010121 rc = drxj_dap_write_reg16(dev_addr, ORX_FWP_AAG_THR_W__A, 40, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010122 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010123 pr_err("error %d\n", rc);
10124 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010125 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010126
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010127 /* ddc */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010128 rc = drxj_dap_write_reg16(dev_addr, ORX_DDC_OFO_SET_W__A, ORX_DDC_OFO_SET_W__PRE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010129 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010130 pr_err("error %d\n", rc);
10131 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010132 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010133
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010134 /* nsu */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010135 rc = drxj_dap_write_reg16(dev_addr, ORX_NSU_AOX_LOPOW_W__A, ext_attr->oob_lo_pow, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010136 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010137 pr_err("error %d\n", rc);
10138 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010139 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010140
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010141 /* initialization for target mode */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010142 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_TARGET_MODE__A, SCU_RAM_ORX_TARGET_MODE_2048KBPS_SQRT, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010143 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010144 pr_err("error %d\n", rc);
10145 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010146 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010147 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_FREQ_GAIN_CORR__A, SCU_RAM_ORX_FREQ_GAIN_CORR_2048KBPS, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010148 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010149 pr_err("error %d\n", rc);
10150 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010151 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010152
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010153 /* Reset bits for timing and freq. recovery */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010154 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_RST_CPH__A, 0x0001, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010155 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010156 pr_err("error %d\n", rc);
10157 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010158 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010159 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_RST_CTI__A, 0x0002, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010160 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010161 pr_err("error %d\n", rc);
10162 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010163 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010164 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_RST_KRN__A, 0x0004, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010165 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010166 pr_err("error %d\n", rc);
10167 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010168 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010169 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_RST_KRP__A, 0x0008, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010170 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010171 pr_err("error %d\n", rc);
10172 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010173 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010174
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010175 /* AGN_LOCK = {2048>>3, -2048, 8, -8, 0, 1}; */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010176 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_AGN_LOCK_TH__A, 2048 >> 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010177 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010178 pr_err("error %d\n", rc);
10179 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010180 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010181 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_AGN_LOCK_TOTH__A, (u16)(-2048), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010182 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010183 pr_err("error %d\n", rc);
10184 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010185 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010186 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_AGN_ONLOCK_TTH__A, 8, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010187 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010188 pr_err("error %d\n", rc);
10189 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010190 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010191 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_AGN_UNLOCK_TTH__A, (u16)(-8), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010192 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010193 pr_err("error %d\n", rc);
10194 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010195 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010196 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_AGN_LOCK_MASK__A, 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010197 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010198 pr_err("error %d\n", rc);
10199 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010200 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010201
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010202 /* DGN_LOCK = {10, -2048, 8, -8, 0, 1<<1}; */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010203 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_DGN_LOCK_TH__A, 10, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010204 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010205 pr_err("error %d\n", rc);
10206 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010207 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010208 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_DGN_LOCK_TOTH__A, (u16)(-2048), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010209 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010210 pr_err("error %d\n", rc);
10211 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010212 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010213 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_DGN_ONLOCK_TTH__A, 8, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010214 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010215 pr_err("error %d\n", rc);
10216 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010217 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010218 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_DGN_UNLOCK_TTH__A, (u16)(-8), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010219 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010220 pr_err("error %d\n", rc);
10221 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010222 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010223 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_DGN_LOCK_MASK__A, 1 << 1, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010224 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010225 pr_err("error %d\n", rc);
10226 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010227 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010228
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010229 /* FRQ_LOCK = {15,-2048, 8, -8, 0, 1<<2}; */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010230 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_FRQ_LOCK_TH__A, 17, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010231 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010232 pr_err("error %d\n", rc);
10233 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010234 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010235 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_FRQ_LOCK_TOTH__A, (u16)(-2048), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010236 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010237 pr_err("error %d\n", rc);
10238 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010239 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010240 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_FRQ_ONLOCK_TTH__A, 8, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010241 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010242 pr_err("error %d\n", rc);
10243 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010244 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010245 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_FRQ_UNLOCK_TTH__A, (u16)(-8), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010246 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010247 pr_err("error %d\n", rc);
10248 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010249 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010250 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_FRQ_LOCK_MASK__A, 1 << 2, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010251 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010252 pr_err("error %d\n", rc);
10253 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010254 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010255
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010256 /* PHA_LOCK = {5000, -2048, 8, -8, 0, 1<<3}; */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010257 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_PHA_LOCK_TH__A, 3000, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010258 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010259 pr_err("error %d\n", rc);
10260 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010261 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010262 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_PHA_LOCK_TOTH__A, (u16)(-2048), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010263 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010264 pr_err("error %d\n", rc);
10265 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010266 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010267 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_PHA_ONLOCK_TTH__A, 8, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010268 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010269 pr_err("error %d\n", rc);
10270 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010271 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010272 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_PHA_UNLOCK_TTH__A, (u16)(-8), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010273 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010274 pr_err("error %d\n", rc);
10275 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010276 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010277 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_PHA_LOCK_MASK__A, 1 << 3, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010278 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010279 pr_err("error %d\n", rc);
10280 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010281 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010282
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010283 /* TIM_LOCK = {300, -2048, 8, -8, 0, 1<<4}; */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010284 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_TIM_LOCK_TH__A, 400, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010285 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010286 pr_err("error %d\n", rc);
10287 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010288 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010289 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_TIM_LOCK_TOTH__A, (u16)(-2048), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010290 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010291 pr_err("error %d\n", rc);
10292 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010293 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010294 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_TIM_ONLOCK_TTH__A, 8, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010295 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010296 pr_err("error %d\n", rc);
10297 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010298 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010299 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_TIM_UNLOCK_TTH__A, (u16)(-8), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010300 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010301 pr_err("error %d\n", rc);
10302 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010303 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010304 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_TIM_LOCK_MASK__A, 1 << 4, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010305 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010306 pr_err("error %d\n", rc);
10307 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010308 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010309
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010310 /* EQU_LOCK = {20, -2048, 8, -8, 0, 1<<5}; */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010311 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_EQU_LOCK_TH__A, 20, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010312 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010313 pr_err("error %d\n", rc);
10314 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010315 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010316 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_EQU_LOCK_TOTH__A, (u16)(-2048), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010317 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010318 pr_err("error %d\n", rc);
10319 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010320 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010321 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_EQU_ONLOCK_TTH__A, 4, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010322 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010323 pr_err("error %d\n", rc);
10324 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010325 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010326 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_EQU_UNLOCK_TTH__A, (u16)(-4), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010327 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010328 pr_err("error %d\n", rc);
10329 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010330 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010331 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_ORX_EQU_LOCK_MASK__A, 1 << 5, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010332 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010333 pr_err("error %d\n", rc);
10334 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010335 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010336
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010337 /* PRE-Filter coefficients (PFI) */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010338 rc = drxdap_fasi_write_block(dev_addr, ORX_FWP_PFI_A_W__A, sizeof(pfi_coeffs[mode_index]), ((u8 *)pfi_coeffs[mode_index]), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010339 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010340 pr_err("error %d\n", rc);
10341 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010342 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010343 rc = drxj_dap_write_reg16(dev_addr, ORX_TOP_MDE_W__A, mode_index, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010344 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010345 pr_err("error %d\n", rc);
10346 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010347 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010348
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010349 /* NYQUIST-Filter coefficients (NYQ) */
10350 for (i = 0; i < (NYQFILTERLEN + 1) / 2; i++) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010351 rc = drxj_dap_write_reg16(dev_addr, ORX_FWP_NYQ_ADR_W__A, i, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010352 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010353 pr_err("error %d\n", rc);
10354 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010355 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010356 rc = drxj_dap_write_reg16(dev_addr, ORX_FWP_NYQ_COF_RW__A, nyquist_coeffs[mode_index][i], 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010357 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010358 pr_err("error %d\n", rc);
10359 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010360 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010361 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010362 rc = drxj_dap_write_reg16(dev_addr, ORX_FWP_NYQ_ADR_W__A, 31, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010363 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010364 pr_err("error %d\n", rc);
10365 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010366 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010367 rc = drxj_dap_write_reg16(dev_addr, ORX_COMM_EXEC__A, ORX_COMM_EXEC_ACTIVE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010368 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010369 pr_err("error %d\n", rc);
10370 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010371 }
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010372 /*********/
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010373 /* Start */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010374 /*********/
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010375 scu_cmd.command = SCU_RAM_COMMAND_STANDARD_OOB
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010376 | SCU_RAM_COMMAND_CMD_DEMOD_START;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010377 scu_cmd.parameter_len = 0;
10378 scu_cmd.result_len = 1;
10379 scu_cmd.result = cmd_result;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010380 rc = scu_command(dev_addr, &scu_cmd);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010381 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010382 pr_err("error %d\n", rc);
10383 goto rw_error;
10384 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010385
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010386 rc = set_orx_nsu_aox(demod, true);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010387 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010388 pr_err("error %d\n", rc);
10389 goto rw_error;
10390 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010391 rc = drxj_dap_write_reg16(dev_addr, ORX_NSU_AOX_STHR_W__A, ext_attr->oob_pre_saw, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010392 if (rc != 0) {
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010393 pr_err("error %d\n", rc);
10394 goto rw_error;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010395 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010396
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010397 ext_attr->oob_power_on = true;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010398
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010399 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010400rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010401 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010402}
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010403
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010404/*============================================================================*/
10405/*== END OOB DATAPATH FUNCTIONS ==*/
10406/*============================================================================*/
10407
10408/*=============================================================================
10409 ===== MC command related functions ==========================================
10410 ===========================================================================*/
10411
10412/*=============================================================================
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010413 ===== ctrl_set_channel() ==========================================================
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010414 ===========================================================================*/
10415/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010416* \fn int ctrl_set_channel()
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010417* \brief Select a new transmission channel.
10418* \param demod instance of demod.
10419* \param channel Pointer to channel data.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -030010420* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010421*
10422* In case the tuner module is not used and in case of NTSC/FM the pogrammer
10423* must tune the tuner to the centre frequency of the NTSC/FM channel.
10424*
10425*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -030010426static int
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -030010427ctrl_set_channel(struct drx_demod_instance *demod, struct drx_channel *channel)
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010428{
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010429 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010430 s32 tuner_freq_offset = 0;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030010431 struct drxj_data *ext_attr = NULL;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010432 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -030010433 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010434#ifndef DRXJ_VSB_ONLY
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010435 u32 min_symbol_rate = 0;
10436 u32 max_symbol_rate = 0;
10437 int bandwidth_temp = 0;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010438 int bandwidth = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010439#endif
10440 /*== check arguments ======================================================*/
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010441 if ((demod == NULL) || (channel == NULL))
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010442 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010443
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010444 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030010445 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010446 standard = ext_attr->standard;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010447
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010448 /* check valid standards */
10449 switch (standard) {
10450 case DRX_STANDARD_8VSB:
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010451#ifndef DRXJ_VSB_ONLY
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010452 case DRX_STANDARD_ITU_A:
10453 case DRX_STANDARD_ITU_B:
10454 case DRX_STANDARD_ITU_C:
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010455#endif /* DRXJ_VSB_ONLY */
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010456 break;
10457 case DRX_STANDARD_UNKNOWN:
10458 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010459 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010460 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010461
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010462 /* check bandwidth QAM annex B, NTSC and 8VSB */
10463 if ((standard == DRX_STANDARD_ITU_B) ||
10464 (standard == DRX_STANDARD_8VSB) ||
10465 (standard == DRX_STANDARD_NTSC)) {
10466 switch (channel->bandwidth) {
10467 case DRX_BANDWIDTH_6MHZ:
10468 case DRX_BANDWIDTH_UNKNOWN: /* fall through */
10469 channel->bandwidth = DRX_BANDWIDTH_6MHZ;
10470 break;
10471 case DRX_BANDWIDTH_8MHZ: /* fall through */
10472 case DRX_BANDWIDTH_7MHZ: /* fall through */
10473 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010474 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010475 }
10476 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010477
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010478 /* For QAM annex A and annex C:
10479 -check symbolrate and constellation
10480 -derive bandwidth from symbolrate (input bandwidth is ignored)
10481 */
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010482#ifndef DRXJ_VSB_ONLY
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010483 if ((standard == DRX_STANDARD_ITU_A) ||
10484 (standard == DRX_STANDARD_ITU_C)) {
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -030010485 struct drxuio_cfg uio_cfg = { DRX_UIO1, DRX_UIO_MODE_FIRMWARE_SAW };
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010486 int bw_rolloff_factor = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010487
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010488 bw_rolloff_factor = (standard == DRX_STANDARD_ITU_A) ? 115 : 113;
10489 min_symbol_rate = DRXJ_QAM_SYMBOLRATE_MIN;
10490 max_symbol_rate = DRXJ_QAM_SYMBOLRATE_MAX;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010491 /* config SMA_TX pin to SAW switch mode */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010492 rc = ctrl_set_uio_cfg(demod, &uio_cfg);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010493 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010494 pr_err("error %d\n", rc);
10495 goto rw_error;
10496 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010497
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010498 if (channel->symbolrate < min_symbol_rate ||
10499 channel->symbolrate > max_symbol_rate) {
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010500 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010501 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010502
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010503 switch (channel->constellation) {
10504 case DRX_CONSTELLATION_QAM16: /* fall through */
10505 case DRX_CONSTELLATION_QAM32: /* fall through */
10506 case DRX_CONSTELLATION_QAM64: /* fall through */
10507 case DRX_CONSTELLATION_QAM128: /* fall through */
10508 case DRX_CONSTELLATION_QAM256:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010509 bandwidth_temp = channel->symbolrate * bw_rolloff_factor;
10510 bandwidth = bandwidth_temp / 100;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010511
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010512 if ((bandwidth_temp % 100) >= 50)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010513 bandwidth++;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010514
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010515 if (bandwidth <= 6100000) {
10516 channel->bandwidth = DRX_BANDWIDTH_6MHZ;
10517 } else if ((bandwidth > 6100000)
10518 && (bandwidth <= 7100000)) {
10519 channel->bandwidth = DRX_BANDWIDTH_7MHZ;
10520 } else if (bandwidth > 7100000) {
10521 channel->bandwidth = DRX_BANDWIDTH_8MHZ;
10522 }
10523 break;
10524 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010525 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010526 }
10527 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010528
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010529 /* For QAM annex B:
10530 -check constellation
10531 */
10532 if (standard == DRX_STANDARD_ITU_B) {
10533 switch (channel->constellation) {
10534 case DRX_CONSTELLATION_AUTO:
10535 case DRX_CONSTELLATION_QAM256:
10536 case DRX_CONSTELLATION_QAM64:
10537 break;
10538 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010539 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010540 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010541
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010542 switch (channel->interleavemode) {
10543 case DRX_INTERLEAVEMODE_I128_J1:
10544 case DRX_INTERLEAVEMODE_I128_J1_V2:
10545 case DRX_INTERLEAVEMODE_I128_J2:
10546 case DRX_INTERLEAVEMODE_I64_J2:
10547 case DRX_INTERLEAVEMODE_I128_J3:
10548 case DRX_INTERLEAVEMODE_I32_J4:
10549 case DRX_INTERLEAVEMODE_I128_J4:
10550 case DRX_INTERLEAVEMODE_I16_J8:
10551 case DRX_INTERLEAVEMODE_I128_J5:
10552 case DRX_INTERLEAVEMODE_I8_J16:
10553 case DRX_INTERLEAVEMODE_I128_J6:
10554 case DRX_INTERLEAVEMODE_I128_J7:
10555 case DRX_INTERLEAVEMODE_I128_J8:
10556 case DRX_INTERLEAVEMODE_I12_J17:
10557 case DRX_INTERLEAVEMODE_I5_J4:
10558 case DRX_INTERLEAVEMODE_B52_M240:
10559 case DRX_INTERLEAVEMODE_B52_M720:
10560 case DRX_INTERLEAVEMODE_UNKNOWN:
10561 case DRX_INTERLEAVEMODE_AUTO:
10562 break;
10563 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010564 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010565 }
10566 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010567
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010568 if ((ext_attr->uio_sma_tx_mode) == DRX_UIO_MODE_FIRMWARE_SAW) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010569 /* SAW SW, user UIO is used for switchable SAW */
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -030010570 struct drxuio_data uio1 = { DRX_UIO1, false };
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010571
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010572 switch (channel->bandwidth) {
10573 case DRX_BANDWIDTH_8MHZ:
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -030010574 uio1.value = true;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010575 break;
10576 case DRX_BANDWIDTH_7MHZ:
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -030010577 uio1.value = false;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010578 break;
10579 case DRX_BANDWIDTH_6MHZ:
Mauro Carvalho Chehab73f70652012-03-20 00:59:03 -030010580 uio1.value = false;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010581 break;
10582 case DRX_BANDWIDTH_UNKNOWN:
10583 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010584 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010585 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010586
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010587 rc = ctrl_uio_write(demod, &uio1);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010588 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010589 pr_err("error %d\n", rc);
10590 goto rw_error;
10591 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010592 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010593#endif /* DRXJ_VSB_ONLY */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010594 rc = drxj_dap_write_reg16(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010595 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010596 pr_err("error %d\n", rc);
10597 goto rw_error;
10598 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010599
Mauro Carvalho Chehaba6530ce52014-01-26 14:54:08 -030010600 tuner_freq_offset = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010601
10602 /*== Setup demod for specific standard ====================================*/
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010603 switch (standard) {
10604 case DRX_STANDARD_8VSB:
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010605 if (channel->mirror == DRX_MIRROR_AUTO)
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010606 ext_attr->mirror = DRX_MIRROR_NO;
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010607 else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010608 ext_attr->mirror = channel->mirror;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010609 rc = set_vsb(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010610 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010611 pr_err("error %d\n", rc);
10612 goto rw_error;
10613 }
10614 rc = set_frequency(demod, channel, tuner_freq_offset);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010615 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010616 pr_err("error %d\n", rc);
10617 goto rw_error;
10618 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010619 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010620#ifndef DRXJ_VSB_ONLY
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010621 case DRX_STANDARD_ITU_A: /* fallthrough */
10622 case DRX_STANDARD_ITU_B: /* fallthrough */
10623 case DRX_STANDARD_ITU_C:
Mauro Carvalho Chehabe33f21932014-01-17 06:47:04 -030010624 rc = set_qam_channel(demod, channel, tuner_freq_offset);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010625 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010626 pr_err("error %d\n", rc);
10627 goto rw_error;
10628 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010629 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010630#endif
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010631 case DRX_STANDARD_UNKNOWN:
10632 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010633 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010634 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010635
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010636 /* flag the packet error counter reset */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010637 ext_attr->reset_pkt_err_acc = true;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010638
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010639 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010640rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010641 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010642}
10643
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010644/*=============================================================================
10645 ===== SigQuality() ==========================================================
10646 ===========================================================================*/
10647
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010648/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010649* \fn int ctrl_sig_quality()
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010650* \brief Retreive signal quality form device.
10651* \param devmod Pointer to demodulator instance.
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010652* \param sig_quality Pointer to signal quality data.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -030010653* \return int.
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010654* \retval 0 sig_quality contains valid data.
10655* \retval -EINVAL sig_quality is NULL.
10656* \retval -EIO Erroneous data, sig_quality contains invalid data.
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010657
10658*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -030010659static int
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010660ctrl_sig_quality(struct drx_demod_instance *demod,
10661 enum drx_lock_status lock_status)
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010662{
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010663 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
10664 struct drxj_data *ext_attr = demod->my_ext_attr;
10665 struct drx39xxj_state *state = dev_addr->user_data;
10666 struct dtv_frontend_properties *p = &state->frontend.dtv_property_cache;
10667 enum drx_standard standard = ext_attr->standard;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010668 int rc;
Mauro Carvalho Chehabd5915902014-03-10 08:22:34 -030010669 u32 ber, cnt, err, pkt;
10670 u16 mer, strength;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010671
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010672 rc = get_sig_strength(demod, &strength);
10673 if (rc < 0) {
10674 pr_err("error getting signal strength %d\n", rc);
10675 p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
10676 } else {
10677 p->strength.stat[0].scale = FE_SCALE_RELATIVE;
10678 p->strength.stat[0].uvalue = 65535UL * strength/ 100;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010679 }
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010680
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010681 switch (standard) {
10682 case DRX_STANDARD_8VSB:
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010683#ifdef DRXJ_SIGNAL_ACCUM_ERR
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010684 rc = get_acc_pkt_err(demod, &pkt);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010685 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010686 pr_err("error %d\n", rc);
10687 goto rw_error;
10688 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010689#endif
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010690 if (lock_status != DRXJ_DEMOD_LOCK && lock_status != DRX_LOCKED) {
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010691 p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010692 p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -030010693 p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010694 p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -030010695 p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010696 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
10697 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010698 } else {
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -030010699 rc = get_vsb_post_rs_pck_err(dev_addr, &err, &pkt);
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010700 if (rc != 0) {
10701 pr_err("error %d getting UCB\n", rc);
10702 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
10703 } else {
10704 p->block_error.stat[0].scale = FE_SCALE_COUNTER;
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -030010705 p->block_error.stat[0].uvalue += err;
10706 p->block_count.stat[0].scale = FE_SCALE_COUNTER;
10707 p->block_count.stat[0].uvalue += pkt;
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010708 }
10709
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010710 /* PostViterbi is compute in steps of 10^(-6) */
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -030010711 rc = get_vs_bpre_viterbi_ber(dev_addr, &ber, &cnt);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010712 if (rc != 0) {
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010713 pr_err("error %d getting pre-ber\n", rc);
10714 p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
10715 } else {
10716 p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
10717 p->pre_bit_error.stat[0].uvalue += ber;
10718 p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -030010719 p->pre_bit_count.stat[0].uvalue += cnt;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010720 }
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010721
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -030010722 rc = get_vs_bpost_viterbi_ber(dev_addr, &ber, &cnt);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010723 if (rc != 0) {
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010724 pr_err("error %d getting post-ber\n", rc);
10725 p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
10726 } else {
10727 p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
10728 p->post_bit_error.stat[0].uvalue += ber;
10729 p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -030010730 p->post_bit_count.stat[0].uvalue += cnt;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010731 }
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010732 rc = get_vsbmer(dev_addr, &mer);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010733 if (rc != 0) {
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010734 pr_err("error %d getting MER\n", rc);
10735 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
10736 } else {
10737 p->cnr.stat[0].svalue = mer * 100;
10738 p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010739 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010740 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010741 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010742#ifndef DRXJ_VSB_ONLY
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010743 case DRX_STANDARD_ITU_A:
10744 case DRX_STANDARD_ITU_B:
10745 case DRX_STANDARD_ITU_C:
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030010746 rc = ctrl_get_qam_sig_quality(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010747 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010748 pr_err("error %d\n", rc);
10749 goto rw_error;
10750 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010751 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010752#endif
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010753 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010754 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010755 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010756
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010757 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010758rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010759 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010760}
10761
10762/*============================================================================*/
10763
10764/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010765* \fn int ctrl_lock_status()
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010766* \brief Retreive lock status .
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010767* \param dev_addr Pointer to demodulator device address.
10768* \param lock_stat Pointer to lock status structure.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -030010769* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010770*
10771*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -030010772static int
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -030010773ctrl_lock_status(struct drx_demod_instance *demod, enum drx_lock_status *lock_stat)
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010774{
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -030010775 enum drx_standard standard = DRX_STANDARD_UNKNOWN;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030010776 struct drxj_data *ext_attr = NULL;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010777 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030010778 struct drxjscu_cmd cmd_scu = { /* command */ 0,
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010779 /* parameter_len */ 0,
10780 /* result_len */ 0,
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010781 /* *parameter */ NULL,
10782 /* *result */ NULL
10783 };
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010784 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010785 u16 cmd_result[2] = { 0, 0 };
10786 u16 demod_lock = SCU_RAM_PARAM_1_RES_DEMOD_GET_LOCK_DEMOD_LOCKED;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010787
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010788 /* check arguments */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010789 if ((demod == NULL) || (lock_stat == NULL))
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010790 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010791
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010792 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030010793 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010794 standard = ext_attr->standard;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010795
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010796 *lock_stat = DRX_NOT_LOCKED;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010797
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010798 /* define the SCU command code */
10799 switch (standard) {
10800 case DRX_STANDARD_8VSB:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010801 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_VSB |
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010802 SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010803 demod_lock |= 0x6;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010804 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010805#ifndef DRXJ_VSB_ONLY
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010806 case DRX_STANDARD_ITU_A:
10807 case DRX_STANDARD_ITU_B:
10808 case DRX_STANDARD_ITU_C:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010809 cmd_scu.command = SCU_RAM_COMMAND_STANDARD_QAM |
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010810 SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK;
10811 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010812#endif
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010813 case DRX_STANDARD_UNKNOWN: /* fallthrough */
10814 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010815 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010816 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010817
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010818 /* define the SCU command paramters and execute the command */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010819 cmd_scu.parameter_len = 0;
10820 cmd_scu.result_len = 2;
10821 cmd_scu.parameter = NULL;
10822 cmd_scu.result = cmd_result;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010823 rc = scu_command(dev_addr, &cmd_scu);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010824 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010825 pr_err("error %d\n", rc);
10826 goto rw_error;
10827 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010828
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010829 /* set the lock status */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010830 if (cmd_scu.result[1] < demod_lock) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010831 /* 0x0000 NOT LOCKED */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010832 *lock_stat = DRX_NOT_LOCKED;
10833 } else if (cmd_scu.result[1] < SCU_RAM_PARAM_1_RES_DEMOD_GET_LOCK_LOCKED) {
10834 *lock_stat = DRXJ_DEMOD_LOCK;
10835 } else if (cmd_scu.result[1] <
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010836 SCU_RAM_PARAM_1_RES_DEMOD_GET_LOCK_NEVER_LOCK) {
10837 /* 0x8000 DEMOD + FEC LOCKED (system lock) */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010838 *lock_stat = DRX_LOCKED;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010839 } else {
10840 /* 0xC000 NEVER LOCKED */
10841 /* (system will never be able to lock to the signal) */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010842 *lock_stat = DRX_NEVER_LOCK;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010843 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010844
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010845 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010846rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010847 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010848}
10849
10850/*============================================================================*/
10851
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010852/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010853* \fn int ctrl_set_standard()
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010854* \brief Set modulation standard to be used.
10855* \param standard Modulation standard.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -030010856* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010857*
10858* Setup stuff for the desired demodulation standard.
10859* Disable and power down the previous selected demodulation standard
10860*
10861*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -030010862static int
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -030010863ctrl_set_standard(struct drx_demod_instance *demod, enum drx_standard *standard)
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010864{
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030010865 struct drxj_data *ext_attr = NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010866 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010867 enum drx_standard prev_standard;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010868
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010869 /* check arguments */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010870 if ((standard == NULL) || (demod == NULL))
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010871 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010872
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030010873 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010874 prev_standard = ext_attr->standard;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010875
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010876 /*
10877 Stop and power down previous standard
10878 */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010879 switch (prev_standard) {
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010880#ifndef DRXJ_VSB_ONLY
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010881 case DRX_STANDARD_ITU_A: /* fallthrough */
10882 case DRX_STANDARD_ITU_B: /* fallthrough */
10883 case DRX_STANDARD_ITU_C:
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010884 rc = power_down_qam(demod, false);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010885 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010886 pr_err("error %d\n", rc);
10887 goto rw_error;
10888 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010889 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010890#endif
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010891 case DRX_STANDARD_8VSB:
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010892 rc = power_down_vsb(demod, false);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010893 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010894 pr_err("error %d\n", rc);
10895 goto rw_error;
10896 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010897 break;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010898 case DRX_STANDARD_UNKNOWN:
10899 /* Do nothing */
10900 break;
10901 case DRX_STANDARD_AUTO: /* fallthrough */
10902 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010903 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010904 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010905
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010906 /*
10907 Initialize channel independent registers
10908 Power up new standard
10909 */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010910 ext_attr->standard = *standard;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010911
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010912 switch (*standard) {
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010913#ifndef DRXJ_VSB_ONLY
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010914 case DRX_STANDARD_ITU_A: /* fallthrough */
10915 case DRX_STANDARD_ITU_B: /* fallthrough */
10916 case DRX_STANDARD_ITU_C:
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010917 do {
10918 u16 dummy;
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030010919 rc = drxj_dap_read_reg16(demod->my_i2c_dev_addr, SCU_RAM_VERSION_HI__A, &dummy, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010920 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010921 pr_err("error %d\n", rc);
10922 goto rw_error;
10923 }
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030010924 } while (0);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010925 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010926#endif
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010927 case DRX_STANDARD_8VSB:
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010928 rc = set_vsb_leak_n_gain(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010929 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030010930 pr_err("error %d\n", rc);
10931 goto rw_error;
10932 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010933 break;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010934 default:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010935 ext_attr->standard = DRX_STANDARD_UNKNOWN;
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010936 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010937 break;
10938 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010939
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010940 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010941rw_error:
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030010942 /* Don't know what the standard is now ... try again */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030010943 ext_attr->standard = DRX_STANDARD_UNKNOWN;
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030010944 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010945}
10946
Devin Heitmueller38b2df92012-08-13 21:18:02 -030010947/*============================================================================*/
10948
Mauro Carvalho Chehabaafdbaa2014-01-19 10:31:47 -030010949static void drxj_reset_mode(struct drxj_data *ext_attr)
10950{
10951 /* Initialize default AFE configuartion for QAM */
10952 if (ext_attr->has_lna) {
10953 /* IF AGC off, PGA active */
10954#ifndef DRXJ_VSB_ONLY
10955 ext_attr->qam_if_agc_cfg.standard = DRX_STANDARD_ITU_B;
10956 ext_attr->qam_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_OFF;
10957 ext_attr->qam_pga_cfg = 140 + (11 * 13);
10958#endif
10959 ext_attr->vsb_if_agc_cfg.standard = DRX_STANDARD_8VSB;
10960 ext_attr->vsb_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_OFF;
10961 ext_attr->vsb_pga_cfg = 140 + (11 * 13);
10962 } else {
10963 /* IF AGC on, PGA not 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_AUTO;
10967 ext_attr->qam_if_agc_cfg.min_output_level = 0;
10968 ext_attr->qam_if_agc_cfg.max_output_level = 0x7FFF;
10969 ext_attr->qam_if_agc_cfg.speed = 3;
10970 ext_attr->qam_if_agc_cfg.top = 1297;
10971 ext_attr->qam_pga_cfg = 140;
10972#endif
10973 ext_attr->vsb_if_agc_cfg.standard = DRX_STANDARD_8VSB;
10974 ext_attr->vsb_if_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
10975 ext_attr->vsb_if_agc_cfg.min_output_level = 0;
10976 ext_attr->vsb_if_agc_cfg.max_output_level = 0x7FFF;
10977 ext_attr->vsb_if_agc_cfg.speed = 3;
10978 ext_attr->vsb_if_agc_cfg.top = 1024;
10979 ext_attr->vsb_pga_cfg = 140;
10980 }
10981 /* TODO: remove min_output_level and max_output_level for both QAM and VSB after */
10982 /* mc has not used them */
10983#ifndef DRXJ_VSB_ONLY
10984 ext_attr->qam_rf_agc_cfg.standard = DRX_STANDARD_ITU_B;
10985 ext_attr->qam_rf_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
10986 ext_attr->qam_rf_agc_cfg.min_output_level = 0;
10987 ext_attr->qam_rf_agc_cfg.max_output_level = 0x7FFF;
10988 ext_attr->qam_rf_agc_cfg.speed = 3;
10989 ext_attr->qam_rf_agc_cfg.top = 9500;
10990 ext_attr->qam_rf_agc_cfg.cut_off_current = 4000;
10991 ext_attr->qam_pre_saw_cfg.standard = DRX_STANDARD_ITU_B;
10992 ext_attr->qam_pre_saw_cfg.reference = 0x07;
10993 ext_attr->qam_pre_saw_cfg.use_pre_saw = true;
10994#endif
10995 /* Initialize default AFE configuartion for VSB */
10996 ext_attr->vsb_rf_agc_cfg.standard = DRX_STANDARD_8VSB;
10997 ext_attr->vsb_rf_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
10998 ext_attr->vsb_rf_agc_cfg.min_output_level = 0;
10999 ext_attr->vsb_rf_agc_cfg.max_output_level = 0x7FFF;
11000 ext_attr->vsb_rf_agc_cfg.speed = 3;
11001 ext_attr->vsb_rf_agc_cfg.top = 9500;
11002 ext_attr->vsb_rf_agc_cfg.cut_off_current = 4000;
11003 ext_attr->vsb_pre_saw_cfg.standard = DRX_STANDARD_8VSB;
11004 ext_attr->vsb_pre_saw_cfg.reference = 0x07;
11005 ext_attr->vsb_pre_saw_cfg.use_pre_saw = true;
Mauro Carvalho Chehabaafdbaa2014-01-19 10:31:47 -030011006}
11007
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011008/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011009* \fn int ctrl_power_mode()
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011010* \brief Set the power mode of the device to the specified power mode
11011* \param demod Pointer to demodulator instance.
11012* \param mode Pointer to new power mode.
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -030011013* \return int.
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011014* \retval 0 Success
11015* \retval -EIO I2C error or other failure
11016* \retval -EINVAL Invalid mode argument.
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011017*
11018*
11019*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -030011020static int
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -030011021ctrl_power_mode(struct drx_demod_instance *demod, enum drx_power_mode *mode)
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011022{
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -030011023 struct drx_common_attr *common_attr = (struct drx_common_attr *) NULL;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030011024 struct drxj_data *ext_attr = (struct drxj_data *) NULL;
Mauro Carvalho Chehab22892262014-01-16 11:28:52 -030011025 struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011026 int rc;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011027 u16 sio_cc_pwd_mode = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011028
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -030011029 common_attr = (struct drx_common_attr *) demod->my_common_attr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030011030 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011031 dev_addr = demod->my_i2c_dev_addr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011032
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011033 /* Check arguments */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030011034 if (mode == NULL)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011035 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011036
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011037 /* If already in requested power mode, do nothing */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030011038 if (common_attr->current_power_mode == *mode)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011039 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011040
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011041 switch (*mode) {
11042 case DRX_POWER_UP:
11043 case DRXJ_POWER_DOWN_MAIN_PATH:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011044 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_NONE;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011045 break;
11046 case DRXJ_POWER_DOWN_CORE:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011047 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_CLOCK;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011048 break;
11049 case DRXJ_POWER_DOWN_PLL:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011050 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_PLL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011051 break;
11052 case DRX_POWER_DOWN:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011053 sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011054 break;
11055 default:
11056 /* Unknow sleep mode */
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011057 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011058 break;
11059 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011060
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011061 /* Check if device needs to be powered up */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011062 if ((common_attr->current_power_mode != DRX_POWER_UP)) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011063 rc = power_up_device(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011064 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011065 pr_err("error %d\n", rc);
11066 goto rw_error;
11067 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011068 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011069
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011070 if ((*mode == DRX_POWER_UP)) {
11071 /* Restore analog & pin configuartion */
Mauro Carvalho Chehabaafdbaa2014-01-19 10:31:47 -030011072
11073 /* Initialize default AFE configuartion for VSB */
11074 drxj_reset_mode(ext_attr);
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011075 } else {
11076 /* Power down to requested mode */
11077 /* Backup some register settings */
11078 /* Set pins with possible pull-ups connected to them in input mode */
11079 /* Analog power down */
11080 /* ADC power down */
11081 /* Power down device */
11082 /* stop all comm_exec */
11083 /*
11084 Stop and power down previous standard
11085 */
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011086
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011087 switch (ext_attr->standard) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011088 case DRX_STANDARD_ITU_A:
11089 case DRX_STANDARD_ITU_B:
11090 case DRX_STANDARD_ITU_C:
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011091 rc = power_down_qam(demod, true);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011092 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011093 pr_err("error %d\n", rc);
11094 goto rw_error;
11095 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011096 break;
11097 case DRX_STANDARD_8VSB:
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011098 rc = power_down_vsb(demod, true);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011099 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011100 pr_err("error %d\n", rc);
11101 goto rw_error;
11102 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011103 break;
11104 case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
11105 case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
11106 case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
11107 case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */
11108 case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
11109 case DRX_STANDARD_NTSC: /* fallthrough */
11110 case DRX_STANDARD_FM:
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011111 rc = power_down_atv(demod, ext_attr->standard, true);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011112 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011113 pr_err("error %d\n", rc);
11114 goto rw_error;
11115 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011116 break;
11117 case DRX_STANDARD_UNKNOWN:
11118 /* Do nothing */
11119 break;
11120 case DRX_STANDARD_AUTO: /* fallthrough */
11121 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011122 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011123 }
Mauro Carvalho Chehabd7a54782014-02-27 05:35:13 -030011124 ext_attr->standard = DRX_STANDARD_UNKNOWN;
11125 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011126
Mauro Carvalho Chehabd7a54782014-02-27 05:35:13 -030011127 if (*mode != DRXJ_POWER_DOWN_MAIN_PATH) {
11128 rc = drxj_dap_write_reg16(dev_addr, SIO_CC_PWD_MODE__A, sio_cc_pwd_mode, 0);
11129 if (rc != 0) {
11130 pr_err("error %d\n", rc);
11131 goto rw_error;
11132 }
11133 rc = drxj_dap_write_reg16(dev_addr, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY, 0);
11134 if (rc != 0) {
11135 pr_err("error %d\n", rc);
11136 goto rw_error;
11137 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011138
Mauro Carvalho Chehabd7a54782014-02-27 05:35:13 -030011139 if ((*mode != DRX_POWER_UP)) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011140 /* Initialize HI, wakeup key especially before put IC to sleep */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011141 rc = init_hi(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011142 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011143 pr_err("error %d\n", rc);
11144 goto rw_error;
11145 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011146
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011147 ext_attr->hi_cfg_ctrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011148 rc = hi_cfg_command(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011149 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011150 pr_err("error %d\n", rc);
11151 goto rw_error;
11152 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011153 }
11154 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011155
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011156 common_attr->current_power_mode = *mode;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011157
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011158 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011159rw_error:
Mauro Carvalho Chehabd7a54782014-02-27 05:35:13 -030011160 return rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011161}
11162
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011163/*============================================================================*/
11164/*== CTRL Set/Get Config related functions ===================================*/
11165/*============================================================================*/
11166
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011167/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011168* \fn int ctrl_set_cfg_pre_saw()
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011169* \brief Set Pre-saw reference.
11170* \param demod demod instance
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -030011171* \param u16 *
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -030011172* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011173*
11174* Check arguments
11175* Dispatch handling to standard specific function.
11176*
11177*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -030011178static int
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030011179ctrl_set_cfg_pre_saw(struct drx_demod_instance *demod, struct drxj_cfg_pre_saw *pre_saw)
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011180{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011181 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030011182 struct drxj_data *ext_attr = NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011183 int rc;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011184
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011185 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030011186 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011187
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011188 /* check arguments */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011189 if ((pre_saw == NULL) || (pre_saw->reference > IQM_AF_PDREF__M)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011190 ) {
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011191 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011192 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011193
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011194 /* Only if standard is currently active */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011195 if ((ext_attr->standard == pre_saw->standard) ||
11196 (DRXJ_ISQAMSTD(ext_attr->standard) &&
11197 DRXJ_ISQAMSTD(pre_saw->standard)) ||
11198 (DRXJ_ISATVSTD(ext_attr->standard) &&
11199 DRXJ_ISATVSTD(pre_saw->standard))) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030011200 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_PDREF__A, pre_saw->reference, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011201 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011202 pr_err("error %d\n", rc);
11203 goto rw_error;
11204 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011205 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011206
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011207 /* Store pre-saw settings */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011208 switch (pre_saw->standard) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011209 case DRX_STANDARD_8VSB:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011210 ext_attr->vsb_pre_saw_cfg = *pre_saw;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011211 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011212#ifndef DRXJ_VSB_ONLY
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011213 case DRX_STANDARD_ITU_A: /* fallthrough */
11214 case DRX_STANDARD_ITU_B: /* fallthrough */
11215 case DRX_STANDARD_ITU_C:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011216 ext_attr->qam_pre_saw_cfg = *pre_saw;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011217 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011218#endif
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011219 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011220 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011221 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011222
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011223 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011224rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011225 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011226}
11227
11228/*============================================================================*/
11229
11230/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011231* \fn int ctrl_set_cfg_afe_gain()
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011232* \brief Set AFE Gain.
11233* \param demod demod instance
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -030011234* \param u16 *
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -030011235* \return int.
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011236*
11237* Check arguments
11238* Dispatch handling to standard specific function.
11239*
11240*/
Mauro Carvalho Chehab61263c72012-03-20 01:18:02 -030011241static int
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030011242ctrl_set_cfg_afe_gain(struct drx_demod_instance *demod, struct drxj_cfg_afe_gain *afe_gain)
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011243{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011244 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030011245 struct drxj_data *ext_attr = NULL;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011246 int rc;
Mauro Carvalho Chehab43a431e2012-03-20 00:49:45 -030011247 u8 gain = 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011248
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011249 /* check arguments */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030011250 if (afe_gain == NULL)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011251 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011252
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011253 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030011254 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011255
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011256 switch (afe_gain->standard) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011257 case DRX_STANDARD_8VSB: /* fallthrough */
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011258#ifndef DRXJ_VSB_ONLY
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011259 case DRX_STANDARD_ITU_A: /* fallthrough */
11260 case DRX_STANDARD_ITU_B: /* fallthrough */
11261 case DRX_STANDARD_ITU_C:
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011262#endif
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011263 /* Do nothing */
11264 break;
11265 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011266 return -EINVAL;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011267 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011268
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011269 /* TODO PGA gain is also written by microcode (at least by QAM and VSB)
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011270 So I (PJ) think interface requires choice between auto, user mode */
11271
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011272 if (afe_gain->gain >= 329)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011273 gain = 15;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011274 else if (afe_gain->gain <= 147)
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011275 gain = 0;
11276 else
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011277 gain = (afe_gain->gain - 140 + 6) / 13;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011278
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011279 /* Only if standard is currently active */
Mauro Carvalho Chehab63713512014-01-17 07:12:28 -030011280 if (ext_attr->standard == afe_gain->standard) {
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030011281 rc = drxj_dap_write_reg16(dev_addr, IQM_AF_PGA_GAIN__A, gain, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011282 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011283 pr_err("error %d\n", rc);
11284 goto rw_error;
11285 }
11286 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011287
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011288 /* Store AFE Gain settings */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011289 switch (afe_gain->standard) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011290 case DRX_STANDARD_8VSB:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011291 ext_attr->vsb_pga_cfg = gain * 13 + 140;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011292 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011293#ifndef DRXJ_VSB_ONLY
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011294 case DRX_STANDARD_ITU_A: /* fallthrough */
11295 case DRX_STANDARD_ITU_B: /* fallthrough */
11296 case DRX_STANDARD_ITU_C:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011297 ext_attr->qam_pga_cfg = gain * 13 + 140;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011298 break;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011299#endif
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011300 default:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011301 return -EIO;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011302 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011303
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011304 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011305rw_error:
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011306 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011307}
11308
11309/*============================================================================*/
11310
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011311
11312/*=============================================================================
11313===== EXPORTED FUNCTIONS ====================================================*/
Mauro Carvalho Chehabaafdbaa2014-01-19 10:31:47 -030011314
Mauro Carvalho Chehabdc5a91d2014-01-24 11:14:17 -030011315static int drx_ctrl_u_code(struct drx_demod_instance *demod,
11316 struct drxu_code_info *mc_info,
11317 enum drxu_code_action action);
11318
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011319/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011320* \fn drxj_open()
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011321* \brief Open the demod instance, configure device, configure drxdriver
11322* \return Status_t Return status.
11323*
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011324* drxj_open() can be called with a NULL ucode image => no ucode upload.
11325* This means that drxj_open() must NOT contain SCU commands or, in general,
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011326* rely on SCU or AUD ucode to be present.
11327*
11328*/
Mauro Carvalho Chehabdc5a91d2014-01-24 11:14:17 -030011329
Mauro Carvalho Chehab01473142014-03-09 10:33:19 -030011330static int drxj_open(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011331{
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011332 struct i2c_device_addr *dev_addr = NULL;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030011333 struct drxj_data *ext_attr = NULL;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -030011334 struct drx_common_attr *common_attr = NULL;
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011335 u32 driver_version = 0;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -030011336 struct drxu_code_info ucode_info;
11337 struct drx_cfg_mpeg_output cfg_mpeg_output;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011338 int rc;
Mauro Carvalho Chehabd7a54782014-02-27 05:35:13 -030011339 enum drx_power_mode power_mode = DRX_POWER_UP;
Mauro Carvalho Chehabb78359a2014-01-24 12:21:17 -030011340
11341 if ((demod == NULL) ||
11342 (demod->my_common_attr == NULL) ||
11343 (demod->my_ext_attr == NULL) ||
11344 (demod->my_i2c_dev_addr == NULL) ||
11345 (demod->my_common_attr->is_opened)) {
11346 return -EINVAL;
11347 }
11348
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011349 /* Check arguments */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011350 if (demod->my_ext_attr == NULL)
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011351 return -EINVAL;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011352
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011353 dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehabb3ce3a82014-01-16 15:33:14 -030011354 ext_attr = (struct drxj_data *) demod->my_ext_attr;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -030011355 common_attr = (struct drx_common_attr *) demod->my_common_attr;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011356
Mauro Carvalho Chehabd7a54782014-02-27 05:35:13 -030011357 rc = ctrl_power_mode(demod, &power_mode);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011358 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011359 pr_err("error %d\n", rc);
11360 goto rw_error;
11361 }
Mauro Carvalho Chehabd7a54782014-02-27 05:35:13 -030011362 if (power_mode != DRX_POWER_UP) {
11363 rc = -EINVAL;
11364 pr_err("failed to powerup device\n");
11365 goto rw_error;
11366 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011367
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011368 /* has to be in front of setIqmAf and setOrxNsuAox */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011369 rc = get_device_capabilities(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011370 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011371 pr_err("error %d\n", rc);
11372 goto rw_error;
11373 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011374
Mauro Carvalho Chehab8afff9a2014-02-27 08:48:44 -030011375 /*
11376 * Soft reset of sys- and osc-clockdomain
11377 *
11378 * HACK: On windows, it writes a 0x07 here, instead of just 0x03.
11379 * As we didn't load the firmware here yet, we should do the same.
11380 * Btw, this is coherent with DRX-K, where we send reset codes
11381 * for modulation (OFTM, in DRX-k), SYS and OSC clock domains.
11382 */
11383 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011384 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011385 pr_err("error %d\n", rc);
11386 goto rw_error;
11387 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030011388 rc = drxj_dap_write_reg16(dev_addr, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011389 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011390 pr_err("error %d\n", rc);
11391 goto rw_error;
11392 }
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -030011393 msleep(1);
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011394
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011395 /* TODO first make sure that everything keeps working before enabling this */
11396 /* PowerDownAnalogBlocks() */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030011397 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);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011398 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011399 pr_err("error %d\n", rc);
11400 goto rw_error;
11401 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011402
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011403 rc = set_iqm_af(demod, false);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011404 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011405 pr_err("error %d\n", rc);
11406 goto rw_error;
11407 }
11408 rc = set_orx_nsu_aox(demod, false);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011409 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011410 pr_err("error %d\n", rc);
11411 goto rw_error;
11412 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011413
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011414 rc = init_hi(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011415 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011416 pr_err("error %d\n", rc);
11417 goto rw_error;
11418 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011419
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011420 /* disable mpegoutput pins */
Mauro Carvalho Chehab41b5cc02014-03-02 11:01:11 -030011421 memcpy(&cfg_mpeg_output, &common_attr->mpeg_cfg, sizeof(cfg_mpeg_output));
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011422 cfg_mpeg_output.enable_mpeg_output = false;
Mauro Carvalho Chehab41b5cc02014-03-02 11:01:11 -030011423
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011424 rc = ctrl_set_cfg_mpeg_output(demod, &cfg_mpeg_output);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011425 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011426 pr_err("error %d\n", rc);
11427 goto rw_error;
11428 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011429 /* Stop AUD Inform SetAudio it will need to do all setting */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011430 rc = power_down_aud(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011431 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011432 pr_err("error %d\n", rc);
11433 goto rw_error;
11434 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011435 /* Stop SCU */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030011436 rc = drxj_dap_write_reg16(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_STOP, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011437 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011438 pr_err("error %d\n", rc);
11439 goto rw_error;
11440 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011441
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011442 /* Upload microcode */
Mauro Carvalho Chehabb48293d2014-01-18 11:13:02 -030011443 if (common_attr->microcode_file != NULL) {
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011444 /* Dirty trick to use common ucode upload & verify,
11445 pretend device is already open */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011446 common_attr->is_opened = true;
Mauro Carvalho Chehabb48293d2014-01-18 11:13:02 -030011447 ucode_info.mc_file = common_attr->microcode_file;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011448
Mauro Carvalho Chehabdc5a91d2014-01-24 11:14:17 -030011449 if (DRX_ISPOWERDOWNMODE(demod->my_common_attr->current_power_mode)) {
11450 pr_err("Should powerup before loading the firmware.");
11451 return -EINVAL;
11452 }
11453
11454 rc = drx_ctrl_u_code(demod, &ucode_info, UCODE_UPLOAD);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011455 if (rc != 0) {
Mauro Carvalho Chehabdc5a91d2014-01-24 11:14:17 -030011456 pr_err("error %d while uploading the firmware\n", rc);
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011457 goto rw_error;
11458 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011459 if (common_attr->verify_microcode == true) {
Mauro Carvalho Chehabdc5a91d2014-01-24 11:14:17 -030011460 rc = drx_ctrl_u_code(demod, &ucode_info, UCODE_VERIFY);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011461 if (rc != 0) {
Mauro Carvalho Chehabdc5a91d2014-01-24 11:14:17 -030011462 pr_err("error %d while verifying the firmware\n",
11463 rc);
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011464 goto rw_error;
11465 }
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011466 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011467 common_attr->is_opened = false;
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011468 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011469
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011470 /* Run SCU for a little while to initialize microcode version numbers */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030011471 rc = drxj_dap_write_reg16(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011472 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011473 pr_err("error %d\n", rc);
11474 goto rw_error;
11475 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011476
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011477 /* Initialize scan timeout */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011478 common_attr->scan_demod_lock_timeout = DRXJ_SCAN_TIMEOUT;
11479 common_attr->scan_desired_lock = DRX_LOCKED;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011480
Mauro Carvalho Chehabaafdbaa2014-01-19 10:31:47 -030011481 drxj_reset_mode(ext_attr);
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011482 ext_attr->standard = DRX_STANDARD_UNKNOWN;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011483
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011484 rc = smart_ant_init(demod);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011485 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011486 pr_err("error %d\n", rc);
11487 goto rw_error;
11488 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011489
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011490 /* Stamp driver version number in SCU data RAM in BCD code
11491 Done to enable field application engineers to retreive drxdriver version
11492 via I2C from SCU RAM
11493 */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011494 driver_version = (VERSION_MAJOR / 100) % 10;
11495 driver_version <<= 4;
11496 driver_version += (VERSION_MAJOR / 10) % 10;
11497 driver_version <<= 4;
11498 driver_version += (VERSION_MAJOR % 10);
11499 driver_version <<= 4;
11500 driver_version += (VERSION_MINOR % 10);
11501 driver_version <<= 4;
11502 driver_version += (VERSION_PATCH / 1000) % 10;
11503 driver_version <<= 4;
11504 driver_version += (VERSION_PATCH / 100) % 10;
11505 driver_version <<= 4;
11506 driver_version += (VERSION_PATCH / 10) % 10;
11507 driver_version <<= 4;
11508 driver_version += (VERSION_PATCH % 10);
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030011509 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_DRIVER_VER_HI__A, (u16)(driver_version >> 16), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011510 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011511 pr_err("error %d\n", rc);
11512 goto rw_error;
11513 }
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030011514 rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_DRIVER_VER_LO__A, (u16)(driver_version & 0xFFFF), 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011515 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011516 pr_err("error %d\n", rc);
11517 goto rw_error;
11518 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011519
Mauro Carvalho Chehabbf9b94a2014-03-02 09:52:34 -030011520 rc = ctrl_set_oob(demod, NULL);
11521 if (rc != 0) {
11522 pr_err("error %d\n", rc);
11523 goto rw_error;
11524 }
11525
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011526 /* refresh the audio data structure with default */
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011527 ext_attr->aud_data = drxj_default_aud_data_g;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011528
Mauro Carvalho Chehabb78359a2014-01-24 12:21:17 -030011529 demod->my_common_attr->is_opened = true;
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011530 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011531rw_error:
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011532 common_attr->is_opened = false;
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011533 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011534}
11535
11536/*============================================================================*/
11537/**
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011538* \fn drxj_close()
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011539* \brief Close the demod instance, power down the device
11540* \return Status_t Return status.
11541*
11542*/
Mauro Carvalho Chehab01473142014-03-09 10:33:19 -030011543static int drxj_close(struct drx_demod_instance *demod)
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011544{
Mauro Carvalho Chehab4d7bb0e2014-01-16 11:49:13 -030011545 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011546 int rc;
Mauro Carvalho Chehab1bfc9e12014-01-16 12:51:36 -030011547 enum drx_power_mode power_mode = DRX_POWER_UP;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011548
Mauro Carvalho Chehab1e5ec312014-03-09 10:33:54 -030011549 if ((demod->my_common_attr == NULL) ||
Mauro Carvalho Chehabb78359a2014-01-24 12:21:17 -030011550 (demod->my_ext_attr == NULL) ||
11551 (demod->my_i2c_dev_addr == NULL) ||
11552 (!demod->my_common_attr->is_opened)) {
11553 return -EINVAL;
11554 }
11555
Mauro Carvalho Chehab443f18d2012-03-20 00:00:42 -030011556 /* power up */
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011557 rc = ctrl_power_mode(demod, &power_mode);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011558 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011559 pr_err("error %d\n", rc);
11560 goto rw_error;
11561 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011562
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030011563 rc = drxj_dap_write_reg16(dev_addr, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE, 0);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011564 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011565 pr_err("error %d\n", rc);
11566 goto rw_error;
11567 }
Mauro Carvalho Chehab57afe2f2014-01-16 11:24:57 -030011568 power_mode = DRX_POWER_DOWN;
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011569 rc = ctrl_power_mode(demod, &power_mode);
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011570 if (rc != 0) {
Mauro Carvalho Chehab068e94e2014-01-16 19:41:13 -030011571 pr_err("error %d\n", rc);
11572 goto rw_error;
11573 }
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011574
Mauro Carvalho Chehabb78359a2014-01-24 12:21:17 -030011575 DRX_ATTR_ISOPENED(demod) = false;
11576
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011577 return 0;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011578rw_error:
Mauro Carvalho Chehabb78359a2014-01-24 12:21:17 -030011579 DRX_ATTR_ISOPENED(demod) = false;
11580
Mauro Carvalho Chehab94823542014-01-17 10:18:16 -030011581 return -EIO;
Devin Heitmueller38b2df92012-08-13 21:18:02 -030011582}
11583
Mauro Carvalho Chehabb240eac2014-01-24 06:25:07 -030011584/*
11585 * Microcode related functions
11586 */
11587
11588/**
11589 * drx_u_code_compute_crc - Compute CRC of block of microcode data.
11590 * @block_data: Pointer to microcode data.
11591 * @nr_words: Size of microcode block (number of 16 bits words).
11592 *
11593 * returns The computed CRC residue.
11594 */
11595static u16 drx_u_code_compute_crc(u8 *block_data, u16 nr_words)
11596{
11597 u16 i = 0;
11598 u16 j = 0;
11599 u32 crc_word = 0;
11600 u32 carry = 0;
11601
11602 while (i < nr_words) {
11603 crc_word |= (u32)be16_to_cpu(*(u32 *)(block_data));
11604 for (j = 0; j < 16; j++) {
11605 crc_word <<= 1;
11606 if (carry != 0)
11607 crc_word ^= 0x80050000UL;
11608 carry = crc_word & 0x80000000UL;
11609 }
11610 i++;
11611 block_data += (sizeof(u16));
11612 }
11613 return (u16)(crc_word >> 16);
11614}
11615
11616/**
11617 * drx_check_firmware - checks if the loaded firmware is valid
11618 *
11619 * @demod: demod structure
11620 * @mc_data: pointer to the start of the firmware
11621 * @size: firmware size
11622 */
11623static int drx_check_firmware(struct drx_demod_instance *demod, u8 *mc_data,
11624 unsigned size)
11625{
11626 struct drxu_code_block_hdr block_hdr;
11627 int i;
11628 unsigned count = 2 * sizeof(u16);
11629 u32 mc_dev_type, mc_version, mc_base_version;
11630 u16 mc_nr_of_blks = be16_to_cpu(*(u32 *)(mc_data + sizeof(u16)));
11631
11632 /*
11633 * Scan microcode blocks first for version info
11634 * and firmware check
11635 */
11636
11637 /* Clear version block */
11638 DRX_ATTR_MCRECORD(demod).aux_type = 0;
11639 DRX_ATTR_MCRECORD(demod).mc_dev_type = 0;
11640 DRX_ATTR_MCRECORD(demod).mc_version = 0;
11641 DRX_ATTR_MCRECORD(demod).mc_base_version = 0;
11642
11643 for (i = 0; i < mc_nr_of_blks; i++) {
11644 if (count + 3 * sizeof(u16) + sizeof(u32) > size)
11645 goto eof;
11646
11647 /* Process block header */
11648 block_hdr.addr = be32_to_cpu(*(u32 *)(mc_data + count));
11649 count += sizeof(u32);
11650 block_hdr.size = be16_to_cpu(*(u32 *)(mc_data + count));
11651 count += sizeof(u16);
11652 block_hdr.flags = be16_to_cpu(*(u32 *)(mc_data + count));
11653 count += sizeof(u16);
11654 block_hdr.CRC = be16_to_cpu(*(u32 *)(mc_data + count));
11655 count += sizeof(u16);
11656
11657 pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n",
11658 count, block_hdr.addr, block_hdr.size, block_hdr.flags,
11659 block_hdr.CRC);
11660
11661 if (block_hdr.flags & 0x8) {
11662 u8 *auxblk = ((void *)mc_data) + block_hdr.addr;
11663 u16 auxtype;
11664
11665 if (block_hdr.addr + sizeof(u16) > size)
11666 goto eof;
11667
11668 auxtype = be16_to_cpu(*(u32 *)(auxblk));
11669
11670 /* Aux block. Check type */
11671 if (DRX_ISMCVERTYPE(auxtype)) {
11672 if (block_hdr.addr + 2 * sizeof(u16) + 2 * sizeof (u32) > size)
11673 goto eof;
11674
11675 auxblk += sizeof(u16);
11676 mc_dev_type = be32_to_cpu(*(u32 *)(auxblk));
11677 auxblk += sizeof(u32);
11678 mc_version = be32_to_cpu(*(u32 *)(auxblk));
11679 auxblk += sizeof(u32);
11680 mc_base_version = be32_to_cpu(*(u32 *)(auxblk));
11681
11682 DRX_ATTR_MCRECORD(demod).aux_type = auxtype;
11683 DRX_ATTR_MCRECORD(demod).mc_dev_type = mc_dev_type;
11684 DRX_ATTR_MCRECORD(demod).mc_version = mc_version;
11685 DRX_ATTR_MCRECORD(demod).mc_base_version = mc_base_version;
11686
11687 pr_info("Firmware dev %x, ver %x, base ver %x\n",
11688 mc_dev_type, mc_version, mc_base_version);
11689
11690 }
11691 } else if (count + block_hdr.size * sizeof(u16) > size)
11692 goto eof;
11693
11694 count += block_hdr.size * sizeof(u16);
11695 }
11696 return 0;
11697eof:
11698 pr_err("Firmware is truncated at pos %u/%u\n", count, size);
11699 return -EINVAL;
11700}
11701
11702/**
11703 * drx_ctrl_u_code - Handle microcode upload or verify.
11704 * @dev_addr: Address of device.
11705 * @mc_info: Pointer to information about microcode data.
11706 * @action: Either UCODE_UPLOAD or UCODE_VERIFY
11707 *
11708 * This function returns:
11709 * 0:
11710 * - In case of UCODE_UPLOAD: code is successfully uploaded.
11711 * - In case of UCODE_VERIFY: image on device is equal to
11712 * image provided to this control function.
11713 * -EIO:
11714 * - In case of UCODE_UPLOAD: I2C error.
11715 * - In case of UCODE_VERIFY: I2C error or image on device
11716 * is not equal to image provided to this control function.
11717 * -EINVAL:
11718 * - Invalid arguments.
11719 * - Provided image is corrupt
11720 */
11721static int drx_ctrl_u_code(struct drx_demod_instance *demod,
11722 struct drxu_code_info *mc_info,
11723 enum drxu_code_action action)
11724{
11725 struct i2c_device_addr *dev_addr = demod->my_i2c_dev_addr;
11726 int rc;
11727 u16 i = 0;
11728 u16 mc_nr_of_blks = 0;
11729 u16 mc_magic_word = 0;
11730 const u8 *mc_data_init = NULL;
11731 u8 *mc_data = NULL;
11732 unsigned size;
Mauro Carvalho Chehab1d001c32014-03-09 10:10:19 -030011733 char *mc_file;
Mauro Carvalho Chehabb240eac2014-01-24 06:25:07 -030011734
11735 /* Check arguments */
Mauro Carvalho Chehab1d001c32014-03-09 10:10:19 -030011736 if (!mc_info || !mc_info->mc_file)
Mauro Carvalho Chehabb240eac2014-01-24 06:25:07 -030011737 return -EINVAL;
11738
Mauro Carvalho Chehab1d001c32014-03-09 10:10:19 -030011739 mc_file = mc_info->mc_file;
11740
Mauro Carvalho Chehabb240eac2014-01-24 06:25:07 -030011741 if (!demod->firmware) {
11742 const struct firmware *fw = NULL;
11743
11744 rc = request_firmware(&fw, mc_file, demod->i2c->dev.parent);
11745 if (rc < 0) {
11746 pr_err("Couldn't read firmware %s\n", mc_file);
Mauro Carvalho Chehab691cbbe2014-03-09 10:36:24 -030011747 return rc;
Mauro Carvalho Chehabb240eac2014-01-24 06:25:07 -030011748 }
11749 demod->firmware = fw;
11750
11751 if (demod->firmware->size < 2 * sizeof(u16)) {
11752 rc = -EINVAL;
11753 pr_err("Firmware is too short!\n");
11754 goto release;
11755 }
11756
11757 pr_info("Firmware %s, size %zu\n",
11758 mc_file, demod->firmware->size);
11759 }
11760
11761 mc_data_init = demod->firmware->data;
11762 size = demod->firmware->size;
11763
11764 mc_data = (void *)mc_data_init;
11765 /* Check data */
11766 mc_magic_word = be16_to_cpu(*(u32 *)(mc_data));
11767 mc_data += sizeof(u16);
11768 mc_nr_of_blks = be16_to_cpu(*(u32 *)(mc_data));
11769 mc_data += sizeof(u16);
11770
11771 if ((mc_magic_word != DRX_UCODE_MAGIC_WORD) || (mc_nr_of_blks == 0)) {
11772 rc = -EINVAL;
11773 pr_err("Firmware magic word doesn't match\n");
11774 goto release;
11775 }
11776
11777 if (action == UCODE_UPLOAD) {
11778 rc = drx_check_firmware(demod, (u8 *)mc_data_init, size);
11779 if (rc)
11780 goto release;
Mauro Carvalho Chehabb240eac2014-01-24 06:25:07 -030011781 pr_info("Uploading firmware %s\n", mc_file);
Mauro Carvalho Chehabdc5a91d2014-01-24 11:14:17 -030011782 } else {
Mauro Carvalho Chehabb240eac2014-01-24 06:25:07 -030011783 pr_info("Verifying if firmware upload was ok.\n");
11784 }
11785
11786 /* Process microcode blocks */
11787 for (i = 0; i < mc_nr_of_blks; i++) {
11788 struct drxu_code_block_hdr block_hdr;
11789 u16 mc_block_nr_bytes = 0;
11790
11791 /* Process block header */
11792 block_hdr.addr = be32_to_cpu(*(u32 *)(mc_data));
11793 mc_data += sizeof(u32);
11794 block_hdr.size = be16_to_cpu(*(u32 *)(mc_data));
11795 mc_data += sizeof(u16);
11796 block_hdr.flags = be16_to_cpu(*(u32 *)(mc_data));
11797 mc_data += sizeof(u16);
11798 block_hdr.CRC = be16_to_cpu(*(u32 *)(mc_data));
11799 mc_data += sizeof(u16);
11800
11801 pr_debug("%u: addr %u, size %u, flags 0x%04x, CRC 0x%04x\n",
11802 (unsigned)(mc_data - mc_data_init), block_hdr.addr,
11803 block_hdr.size, block_hdr.flags, block_hdr.CRC);
11804
11805 /* Check block header on:
11806 - data larger than 64Kb
11807 - if CRC enabled check CRC
11808 */
11809 if ((block_hdr.size > 0x7FFF) ||
11810 (((block_hdr.flags & DRX_UCODE_CRC_FLAG) != 0) &&
11811 (block_hdr.CRC != drx_u_code_compute_crc(mc_data, block_hdr.size)))
11812 ) {
11813 /* Wrong data ! */
11814 rc = -EINVAL;
11815 pr_err("firmware CRC is wrong\n");
11816 goto release;
11817 }
11818
11819 if (!block_hdr.size)
11820 continue;
11821
11822 mc_block_nr_bytes = block_hdr.size * ((u16) sizeof(u16));
11823
11824 /* Perform the desired action */
11825 switch (action) {
11826 case UCODE_UPLOAD: /* Upload microcode */
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030011827 if (drxdap_fasi_write_block(dev_addr,
Mauro Carvalho Chehabb240eac2014-01-24 06:25:07 -030011828 block_hdr.addr,
11829 mc_block_nr_bytes,
11830 mc_data, 0x0000)) {
11831 rc = -EIO;
11832 pr_err("error writing firmware at pos %u\n",
11833 (unsigned)(mc_data - mc_data_init));
11834 goto release;
11835 }
11836 break;
11837 case UCODE_VERIFY: { /* Verify uploaded microcode */
11838 int result = 0;
11839 u8 mc_data_buffer[DRX_UCODE_MAX_BUF_SIZE];
11840 u32 bytes_to_comp = 0;
11841 u32 bytes_left = mc_block_nr_bytes;
11842 u32 curr_addr = block_hdr.addr;
11843 u8 *curr_ptr = mc_data;
11844
11845 while (bytes_left != 0) {
11846 if (bytes_left > DRX_UCODE_MAX_BUF_SIZE)
11847 bytes_to_comp = DRX_UCODE_MAX_BUF_SIZE;
11848 else
11849 bytes_to_comp = bytes_left;
11850
Mauro Carvalho Chehab244c0e02014-01-27 02:33:18 -030011851 if (drxdap_fasi_read_block(dev_addr,
Mauro Carvalho Chehabb240eac2014-01-24 06:25:07 -030011852 curr_addr,
11853 (u16)bytes_to_comp,
11854 (u8 *)mc_data_buffer,
11855 0x0000)) {
11856 pr_err("error reading firmware at pos %u\n",
11857 (unsigned)(mc_data - mc_data_init));
11858 return -EIO;
11859 }
11860
Mauro Carvalho Chehabd7b06312014-01-26 14:23:24 -030011861 result = memcmp(curr_ptr, mc_data_buffer,
11862 bytes_to_comp);
Mauro Carvalho Chehabb240eac2014-01-24 06:25:07 -030011863
11864 if (result) {
11865 pr_err("error verifying firmware at pos %u\n",
11866 (unsigned)(mc_data - mc_data_init));
11867 return -EIO;
11868 }
11869
11870 curr_addr += ((dr_xaddr_t)(bytes_to_comp / 2));
11871 curr_ptr =&(curr_ptr[bytes_to_comp]);
11872 bytes_left -=((u32) bytes_to_comp);
11873 }
11874 break;
11875 }
11876 default:
11877 return -EINVAL;
11878 break;
11879
11880 }
11881 mc_data += mc_block_nr_bytes;
11882 }
11883
11884 return 0;
11885
11886release:
11887 release_firmware(demod->firmware);
11888 demod->firmware = NULL;
11889
11890 return rc;
11891}
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030011892
11893/*
11894 * The Linux DVB Driver for Micronas DRX39xx family (drx3933j)
11895 *
11896 * Written by Devin Heitmueller <devin.heitmueller@kernellabs.com>
11897 */
11898
11899static int drx39xxj_set_powerstate(struct dvb_frontend *fe, int enable)
11900{
11901 struct drx39xxj_state *state = fe->demodulator_priv;
11902 struct drx_demod_instance *demod = state->demod;
11903 int result;
11904 enum drx_power_mode power_mode;
11905
11906 if (enable)
11907 power_mode = DRX_POWER_UP;
11908 else
11909 power_mode = DRX_POWER_DOWN;
11910
Mauro Carvalho Chehabb0baeb42014-01-24 13:00:08 -030011911 result = ctrl_power_mode(demod, &power_mode);
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030011912 if (result != 0) {
11913 pr_err("Power state change failed\n");
11914 return 0;
11915 }
11916
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030011917 return 0;
11918}
11919
11920static int drx39xxj_read_status(struct dvb_frontend *fe, fe_status_t *status)
11921{
11922 struct drx39xxj_state *state = fe->demodulator_priv;
11923 struct drx_demod_instance *demod = state->demod;
11924 int result;
11925 enum drx_lock_status lock_status;
11926
11927 *status = 0;
11928
Mauro Carvalho Chehabb0baeb42014-01-24 13:00:08 -030011929 result = ctrl_lock_status(demod, &lock_status);
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030011930 if (result != 0) {
11931 pr_err("drx39xxj: could not get lock status!\n");
11932 *status = 0;
11933 }
11934
11935 switch (lock_status) {
11936 case DRX_NEVER_LOCK:
11937 *status = 0;
11938 pr_err("drx says NEVER_LOCK\n");
11939 break;
11940 case DRX_NOT_LOCKED:
11941 *status = 0;
11942 break;
11943 case DRX_LOCK_STATE_1:
11944 case DRX_LOCK_STATE_2:
11945 case DRX_LOCK_STATE_3:
11946 case DRX_LOCK_STATE_4:
11947 case DRX_LOCK_STATE_5:
11948 case DRX_LOCK_STATE_6:
11949 case DRX_LOCK_STATE_7:
11950 case DRX_LOCK_STATE_8:
11951 case DRX_LOCK_STATE_9:
11952 *status = FE_HAS_SIGNAL
11953 | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC;
11954 break;
11955 case DRX_LOCKED:
11956 *status = FE_HAS_SIGNAL
11957 | FE_HAS_CARRIER
11958 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
11959 break;
11960 default:
11961 pr_err("Lock state unknown %d\n", lock_status);
11962 }
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030011963 ctrl_sig_quality(demod, lock_status);
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030011964
11965 return 0;
11966}
11967
11968static int drx39xxj_read_ber(struct dvb_frontend *fe, u32 *ber)
11969{
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030011970 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030011971
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030011972 if (p->pre_bit_error.stat[0].scale == FE_SCALE_NOT_AVAILABLE) {
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030011973 *ber = 0;
11974 return 0;
11975 }
11976
Mauro Carvalho Chehab69832572014-03-10 08:08:53 -030011977 if (!p->pre_bit_count.stat[0].uvalue) {
11978 if (!p->pre_bit_error.stat[0].uvalue)
11979 *ber = 0;
11980 else
11981 *ber = 1000000;
11982 } else {
11983 *ber = frac_times1e6(p->pre_bit_error.stat[0].uvalue,
11984 p->pre_bit_count.stat[0].uvalue);
11985 }
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030011986 return 0;
11987}
11988
11989static int drx39xxj_read_signal_strength(struct dvb_frontend *fe,
11990 u16 *strength)
11991{
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030011992 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030011993
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030011994 if (p->strength.stat[0].scale == FE_SCALE_NOT_AVAILABLE) {
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030011995 *strength = 0;
11996 return 0;
11997 }
11998
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030011999 *strength = p->strength.stat[0].uvalue;
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012000 return 0;
12001}
12002
12003static int drx39xxj_read_snr(struct dvb_frontend *fe, u16 *snr)
12004{
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030012005 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Gianluca Gennari90d9c3e2014-03-11 10:41:47 -030012006 u64 tmp64;
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012007
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030012008 if (p->cnr.stat[0].scale == FE_SCALE_NOT_AVAILABLE) {
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012009 *snr = 0;
12010 return 0;
12011 }
12012
Gianluca Gennari90d9c3e2014-03-11 10:41:47 -030012013 tmp64 = p->cnr.stat[0].svalue;
12014 do_div(tmp64, 10);
12015 *snr = tmp64;
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012016 return 0;
12017}
12018
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030012019static int drx39xxj_read_ucblocks(struct dvb_frontend *fe, u32 *ucb)
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012020{
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030012021 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012022
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030012023 if (p->block_error.stat[0].scale == FE_SCALE_NOT_AVAILABLE) {
12024 *ucb = 0;
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012025 return 0;
12026 }
12027
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030012028 *ucb = p->block_error.stat[0].uvalue;
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012029 return 0;
12030}
12031
12032static int drx39xxj_set_frontend(struct dvb_frontend *fe)
12033{
12034#ifdef DJH_DEBUG
12035 int i;
12036#endif
12037 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
12038 struct drx39xxj_state *state = fe->demodulator_priv;
12039 struct drx_demod_instance *demod = state->demod;
12040 enum drx_standard standard = DRX_STANDARD_8VSB;
12041 struct drx_channel channel;
12042 int result;
12043 struct drxuio_data uio_data;
12044 static const struct drx_channel def_channel = {
12045 /* frequency */ 0,
12046 /* bandwidth */ DRX_BANDWIDTH_6MHZ,
12047 /* mirror */ DRX_MIRROR_NO,
12048 /* constellation */ DRX_CONSTELLATION_AUTO,
12049 /* hierarchy */ DRX_HIERARCHY_UNKNOWN,
12050 /* priority */ DRX_PRIORITY_UNKNOWN,
12051 /* coderate */ DRX_CODERATE_UNKNOWN,
12052 /* guard */ DRX_GUARD_UNKNOWN,
12053 /* fftmode */ DRX_FFTMODE_UNKNOWN,
12054 /* classification */ DRX_CLASSIFICATION_AUTO,
12055 /* symbolrate */ 5057000,
12056 /* interleavemode */ DRX_INTERLEAVEMODE_UNKNOWN,
12057 /* ldpc */ DRX_LDPC_UNKNOWN,
12058 /* carrier */ DRX_CARRIER_UNKNOWN,
12059 /* frame mode */ DRX_FRAMEMODE_UNKNOWN
12060 };
12061 u32 constellation = DRX_CONSTELLATION_AUTO;
12062
12063 /* Bring the demod out of sleep */
12064 drx39xxj_set_powerstate(fe, 1);
12065
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012066 if (fe->ops.tuner_ops.set_params) {
Mauro Carvalho Chehab7abc7a52014-01-26 15:02:25 -030012067 u32 int_freq;
12068
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012069 if (fe->ops.i2c_gate_ctrl)
12070 fe->ops.i2c_gate_ctrl(fe, 1);
Mauro Carvalho Chehab7abc7a52014-01-26 15:02:25 -030012071
12072 /* Set tuner to desired frequency and standard */
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012073 fe->ops.tuner_ops.set_params(fe);
Mauro Carvalho Chehab7abc7a52014-01-26 15:02:25 -030012074
12075 /* Use the tuner's IF */
12076 if (fe->ops.tuner_ops.get_if_frequency) {
12077 fe->ops.tuner_ops.get_if_frequency(fe, &int_freq);
12078 demod->my_common_attr->intermediate_freq = int_freq / 1000;
12079 }
12080
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012081 if (fe->ops.i2c_gate_ctrl)
12082 fe->ops.i2c_gate_ctrl(fe, 0);
12083 }
12084
12085 switch (p->delivery_system) {
12086 case SYS_ATSC:
12087 standard = DRX_STANDARD_8VSB;
12088 break;
12089 case SYS_DVBC_ANNEX_B:
12090 standard = DRX_STANDARD_ITU_B;
12091
12092 switch (p->modulation) {
12093 case QAM_64:
12094 constellation = DRX_CONSTELLATION_QAM64;
12095 break;
12096 case QAM_256:
12097 constellation = DRX_CONSTELLATION_QAM256;
12098 break;
12099 default:
12100 constellation = DRX_CONSTELLATION_AUTO;
12101 break;
12102 }
12103 break;
12104 default:
12105 return -EINVAL;
12106 }
Mauro Carvalho Chehabc4dc6f92014-01-26 15:39:06 -030012107 /* Set the standard (will be powered up if necessary */
12108 result = ctrl_set_standard(demod, &standard);
12109 if (result != 0) {
12110 pr_err("Failed to set standard! result=%02x\n",
12111 result);
12112 return -EINVAL;
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012113 }
12114
12115 /* set channel parameters */
12116 channel = def_channel;
12117 channel.frequency = p->frequency / 1000;
12118 channel.bandwidth = DRX_BANDWIDTH_6MHZ;
12119 channel.constellation = constellation;
12120
12121 /* program channel */
Mauro Carvalho Chehabb0baeb42014-01-24 13:00:08 -030012122 result = ctrl_set_channel(demod, &channel);
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012123 if (result != 0) {
12124 pr_err("Failed to set channel!\n");
12125 return -EINVAL;
12126 }
12127 /* Just for giggles, let's shut off the LNA again.... */
12128 uio_data.uio = DRX_UIO1;
12129 uio_data.value = false;
Mauro Carvalho Chehabb0baeb42014-01-24 13:00:08 -030012130 result = ctrl_uio_write(demod, &uio_data);
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012131 if (result != 0) {
12132 pr_err("Failed to disable LNA!\n");
12133 return 0;
12134 }
Mauro Carvalho Chehab03fdfbf2014-03-09 17:46:01 -030012135
12136 /* After set_frontend, except for strength, stats aren't available */
12137 p->strength.stat[0].scale = FE_SCALE_RELATIVE;
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012138
12139 return 0;
12140}
12141
12142static int drx39xxj_sleep(struct dvb_frontend *fe)
12143{
12144 /* power-down the demodulator */
12145 return drx39xxj_set_powerstate(fe, 0);
12146}
12147
12148static int drx39xxj_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
12149{
12150 struct drx39xxj_state *state = fe->demodulator_priv;
12151 struct drx_demod_instance *demod = state->demod;
12152 bool i2c_gate_state;
12153 int result;
12154
12155#ifdef DJH_DEBUG
Shuah Khan6c955b82014-02-28 18:23:00 -030012156 pr_debug("i2c gate call: enable=%d state=%d\n", enable,
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012157 state->i2c_gate_open);
12158#endif
12159
12160 if (enable)
12161 i2c_gate_state = true;
12162 else
12163 i2c_gate_state = false;
12164
12165 if (state->i2c_gate_open == enable) {
12166 /* We're already in the desired state */
12167 return 0;
12168 }
12169
Mauro Carvalho Chehabb0baeb42014-01-24 13:00:08 -030012170 result = ctrl_i2c_bridge(demod, &i2c_gate_state);
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012171 if (result != 0) {
12172 pr_err("drx39xxj: could not open i2c gate [%d]\n",
12173 result);
12174 dump_stack();
12175 } else {
12176 state->i2c_gate_open = enable;
12177 }
12178 return 0;
12179}
12180
12181static int drx39xxj_init(struct dvb_frontend *fe)
12182{
12183 /* Bring the demod out of sleep */
12184 drx39xxj_set_powerstate(fe, 1);
12185
12186 return 0;
12187}
12188
Mauro Carvalho Chehabea8f3c22014-02-16 00:38:44 -030012189static int drx39xxj_set_lna(struct dvb_frontend *fe)
12190{
12191 int result;
12192 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
12193 struct drx39xxj_state *state = fe->demodulator_priv;
12194 struct drx_demod_instance *demod = state->demod;
12195 struct drxj_data *ext_attr = demod->my_ext_attr;
12196 struct drxuio_cfg uio_cfg;
12197 struct drxuio_data uio_data;
12198
12199 if (c->lna) {
12200 if (!ext_attr->has_lna) {
12201 pr_err("LNA is not supported on this device!\n");
12202 return -EINVAL;
12203
12204 }
12205 }
12206
12207 /* Turn off the LNA */
12208 uio_cfg.uio = DRX_UIO1;
12209 uio_cfg.mode = DRX_UIO_MODE_READWRITE;
12210 /* Configure user-I/O #3: enable read/write */
12211 result = ctrl_set_uio_cfg(demod, &uio_cfg);
12212 if (result) {
12213 pr_err("Failed to setup LNA GPIO!\n");
12214 return result;
12215 }
12216
12217 uio_data.uio = DRX_UIO1;
12218 uio_data.value = c->lna;
12219 result = ctrl_uio_write(demod, &uio_data);
12220 if (result != 0) {
12221 pr_err("Failed to %sable LNA!\n",
12222 c->lna ? "en" : "dis");
12223 return result;
12224 }
12225
12226 return 0;
12227}
12228
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012229static int drx39xxj_get_tune_settings(struct dvb_frontend *fe,
12230 struct dvb_frontend_tune_settings *tune)
12231{
12232 tune->min_delay_ms = 1000;
12233 return 0;
12234}
12235
12236static void drx39xxj_release(struct dvb_frontend *fe)
12237{
12238 struct drx39xxj_state *state = fe->demodulator_priv;
12239 struct drx_demod_instance *demod = state->demod;
12240
Mauro Carvalho Chehab1e5ec312014-03-09 10:33:54 -030012241 drxj_close(demod);
12242
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012243 kfree(demod->my_ext_attr);
12244 kfree(demod->my_common_attr);
12245 kfree(demod->my_i2c_dev_addr);
12246 if (demod->firmware)
12247 release_firmware(demod->firmware);
12248 kfree(demod);
12249 kfree(state);
12250}
12251
12252static struct dvb_frontend_ops drx39xxj_ops;
12253
12254struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c)
12255{
12256 struct drx39xxj_state *state = NULL;
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012257 struct i2c_device_addr *demod_addr = NULL;
12258 struct drx_common_attr *demod_comm_attr = NULL;
12259 struct drxj_data *demod_ext_attr = NULL;
12260 struct drx_demod_instance *demod = NULL;
Mauro Carvalho Chehabd5915902014-03-10 08:22:34 -030012261 struct dtv_frontend_properties *p;
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012262 struct drxuio_cfg uio_cfg;
12263 struct drxuio_data uio_data;
12264 int result;
12265
12266 /* allocate memory for the internal state */
12267 state = kzalloc(sizeof(struct drx39xxj_state), GFP_KERNEL);
12268 if (state == NULL)
12269 goto error;
12270
12271 demod = kmalloc(sizeof(struct drx_demod_instance), GFP_KERNEL);
12272 if (demod == NULL)
12273 goto error;
12274
12275 demod_addr = kmalloc(sizeof(struct i2c_device_addr), GFP_KERNEL);
12276 if (demod_addr == NULL)
12277 goto error;
12278 memcpy(demod_addr, &drxj_default_addr_g,
12279 sizeof(struct i2c_device_addr));
12280
12281 demod_comm_attr = kmalloc(sizeof(struct drx_common_attr), GFP_KERNEL);
12282 if (demod_comm_attr == NULL)
12283 goto error;
12284 memcpy(demod_comm_attr, &drxj_default_comm_attr_g,
12285 sizeof(struct drx_common_attr));
12286
12287 demod_ext_attr = kmalloc(sizeof(struct drxj_data), GFP_KERNEL);
12288 if (demod_ext_attr == NULL)
12289 goto error;
12290 memcpy(demod_ext_attr, &drxj_data_g, sizeof(struct drxj_data));
12291
12292 /* setup the state */
12293 state->i2c = i2c;
12294 state->demod = demod;
12295
12296 /* setup the demod data */
12297 memcpy(demod, &drxj_default_demod_g, sizeof(struct drx_demod_instance));
12298
12299 demod->my_i2c_dev_addr = demod_addr;
12300 demod->my_common_attr = demod_comm_attr;
12301 demod->my_i2c_dev_addr->user_data = state;
12302 demod->my_common_attr->microcode_file = DRX39XX_MAIN_FIRMWARE;
12303 demod->my_common_attr->verify_microcode = true;
12304 demod->my_common_attr->intermediate_freq = 5000;
Mauro Carvalho Chehabd7a54782014-02-27 05:35:13 -030012305 demod->my_common_attr->current_power_mode = DRX_POWER_DOWN;
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012306 demod->my_ext_attr = demod_ext_attr;
12307 ((struct drxj_data *)demod_ext_attr)->uio_sma_tx_mode = DRX_UIO_MODE_READWRITE;
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012308 demod->i2c = i2c;
12309
12310 result = drxj_open(demod);
12311 if (result != 0) {
12312 pr_err("DRX open failed! Aborting\n");
12313 goto error;
12314 }
12315
12316 /* Turn off the LNA */
12317 uio_cfg.uio = DRX_UIO1;
12318 uio_cfg.mode = DRX_UIO_MODE_READWRITE;
12319 /* Configure user-I/O #3: enable read/write */
Mauro Carvalho Chehabb0baeb42014-01-24 13:00:08 -030012320 result = ctrl_set_uio_cfg(demod, &uio_cfg);
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012321 if (result) {
12322 pr_err("Failed to setup LNA GPIO!\n");
12323 goto error;
12324 }
12325
12326 uio_data.uio = DRX_UIO1;
12327 uio_data.value = false;
Mauro Carvalho Chehabb0baeb42014-01-24 13:00:08 -030012328 result = ctrl_uio_write(demod, &uio_data);
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012329 if (result != 0) {
12330 pr_err("Failed to disable LNA!\n");
12331 goto error;
12332 }
12333
12334 /* create dvb_frontend */
12335 memcpy(&state->frontend.ops, &drx39xxj_ops,
12336 sizeof(struct dvb_frontend_ops));
12337
12338 state->frontend.demodulator_priv = state;
Mauro Carvalho Chehabd5915902014-03-10 08:22:34 -030012339
12340 /* Initialize stats - needed for DVBv5 stats to work */
12341 p = &state->frontend.dtv_property_cache;
12342 p->strength.len = 1;
12343 p->pre_bit_count.len = 1;
12344 p->pre_bit_error.len = 1;
12345 p->post_bit_count.len = 1;
12346 p->post_bit_error.len = 1;
12347 p->block_count.len = 1;
12348 p->block_error.len = 1;
12349 p->cnr.len = 1;
12350
12351 p->strength.stat[0].scale = FE_SCALE_RELATIVE;
12352 p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
12353 p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
12354 p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
12355 p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
12356 p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
12357 p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
12358 p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
12359
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012360 return &state->frontend;
12361
12362error:
12363 kfree(demod_ext_attr);
12364 kfree(demod_comm_attr);
12365 kfree(demod_addr);
12366 kfree(demod);
12367 kfree(state);
12368
12369 return NULL;
12370}
12371EXPORT_SYMBOL(drx39xxj_attach);
12372
12373static struct dvb_frontend_ops drx39xxj_ops = {
12374 .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
12375 .info = {
12376 .name = "Micronas DRX39xxj family Frontend",
12377 .frequency_stepsize = 62500,
12378 .frequency_min = 51000000,
12379 .frequency_max = 858000000,
12380 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
12381 },
12382
12383 .init = drx39xxj_init,
12384 .i2c_gate_ctrl = drx39xxj_i2c_gate_ctrl,
12385 .sleep = drx39xxj_sleep,
12386 .set_frontend = drx39xxj_set_frontend,
12387 .get_tune_settings = drx39xxj_get_tune_settings,
12388 .read_status = drx39xxj_read_status,
12389 .read_ber = drx39xxj_read_ber,
12390 .read_signal_strength = drx39xxj_read_signal_strength,
12391 .read_snr = drx39xxj_read_snr,
12392 .read_ucblocks = drx39xxj_read_ucblocks,
12393 .release = drx39xxj_release,
Mauro Carvalho Chehabea8f3c22014-02-16 00:38:44 -030012394 .set_lna = drx39xxj_set_lna,
Mauro Carvalho Chehab19013742014-01-24 12:25:04 -030012395};
12396
12397MODULE_DESCRIPTION("Micronas DRX39xxj Frontend");
12398MODULE_AUTHOR("Devin Heitmueller");
12399MODULE_LICENSE("GPL");
12400MODULE_FIRMWARE(DRX39XX_MAIN_FIRMWARE);