1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * helene.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Sony HELENE DVB-S/S2 DVB-T/T2 DVB-C/C2 ISDB-T/S tuner driver (CXD2858ER)
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright 2012 Sony Corporation
8*4882a593Smuzhiyun * Copyright (C) 2014 NetUP Inc.
9*4882a593Smuzhiyun * Copyright (C) 2014 Abylay Ospan <aospan@netup.ru>
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/slab.h>
13*4882a593Smuzhiyun #include <linux/module.h>
14*4882a593Smuzhiyun #include <linux/dvb/frontend.h>
15*4882a593Smuzhiyun #include <linux/types.h>
16*4882a593Smuzhiyun #include "helene.h"
17*4882a593Smuzhiyun #include <media/dvb_frontend.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #define MAX_WRITE_REGSIZE 20
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun enum helene_state {
22*4882a593Smuzhiyun STATE_UNKNOWN,
23*4882a593Smuzhiyun STATE_SLEEP,
24*4882a593Smuzhiyun STATE_ACTIVE
25*4882a593Smuzhiyun };
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun struct helene_priv {
28*4882a593Smuzhiyun u32 frequency;
29*4882a593Smuzhiyun u8 i2c_address;
30*4882a593Smuzhiyun struct i2c_adapter *i2c;
31*4882a593Smuzhiyun enum helene_state state;
32*4882a593Smuzhiyun void *set_tuner_data;
33*4882a593Smuzhiyun int (*set_tuner)(void *, int);
34*4882a593Smuzhiyun enum helene_xtal xtal;
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #define TERR_INTERNAL_LOOPFILTER_AVAILABLE(tv_system) \
38*4882a593Smuzhiyun (((tv_system) != SONY_HELENE_DTV_DVBC_6) && \
39*4882a593Smuzhiyun ((tv_system) != SONY_HELENE_DTV_DVBC_8)\
40*4882a593Smuzhiyun && ((tv_system) != SONY_HELENE_DTV_DVBC2_6) && \
41*4882a593Smuzhiyun ((tv_system) != SONY_HELENE_DTV_DVBC2_8))
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun #define HELENE_AUTO 0xff
44*4882a593Smuzhiyun #define HELENE_OFFSET(ofs) ((u8)(ofs) & 0x1F)
45*4882a593Smuzhiyun #define HELENE_BW_6 0x00
46*4882a593Smuzhiyun #define HELENE_BW_7 0x01
47*4882a593Smuzhiyun #define HELENE_BW_8 0x02
48*4882a593Smuzhiyun #define HELENE_BW_1_7 0x03
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun enum helene_tv_system_t {
51*4882a593Smuzhiyun SONY_HELENE_TV_SYSTEM_UNKNOWN,
52*4882a593Smuzhiyun /* Terrestrial Analog */
53*4882a593Smuzhiyun SONY_HELENE_ATV_MN_EIAJ,
54*4882a593Smuzhiyun /**< System-M (Japan) (IF: Fp=5.75MHz in default) */
55*4882a593Smuzhiyun SONY_HELENE_ATV_MN_SAP,
56*4882a593Smuzhiyun /**< System-M (US) (IF: Fp=5.75MHz in default) */
57*4882a593Smuzhiyun SONY_HELENE_ATV_MN_A2,
58*4882a593Smuzhiyun /**< System-M (Korea) (IF: Fp=5.9MHz in default) */
59*4882a593Smuzhiyun SONY_HELENE_ATV_BG,
60*4882a593Smuzhiyun /**< System-B/G (IF: Fp=7.3MHz in default) */
61*4882a593Smuzhiyun SONY_HELENE_ATV_I,
62*4882a593Smuzhiyun /**< System-I (IF: Fp=7.85MHz in default) */
63*4882a593Smuzhiyun SONY_HELENE_ATV_DK,
64*4882a593Smuzhiyun /**< System-D/K (IF: Fp=7.85MHz in default) */
65*4882a593Smuzhiyun SONY_HELENE_ATV_L,
66*4882a593Smuzhiyun /**< System-L (IF: Fp=7.85MHz in default) */
67*4882a593Smuzhiyun SONY_HELENE_ATV_L_DASH,
68*4882a593Smuzhiyun /**< System-L DASH (IF: Fp=2.2MHz in default) */
69*4882a593Smuzhiyun /* Terrestrial/Cable Digital */
70*4882a593Smuzhiyun SONY_HELENE_DTV_8VSB,
71*4882a593Smuzhiyun /**< ATSC 8VSB (IF: Fc=3.7MHz in default) */
72*4882a593Smuzhiyun SONY_HELENE_DTV_QAM,
73*4882a593Smuzhiyun /**< US QAM (IF: Fc=3.7MHz in default) */
74*4882a593Smuzhiyun SONY_HELENE_DTV_ISDBT_6,
75*4882a593Smuzhiyun /**< ISDB-T 6MHzBW (IF: Fc=3.55MHz in default) */
76*4882a593Smuzhiyun SONY_HELENE_DTV_ISDBT_7,
77*4882a593Smuzhiyun /**< ISDB-T 7MHzBW (IF: Fc=4.15MHz in default) */
78*4882a593Smuzhiyun SONY_HELENE_DTV_ISDBT_8,
79*4882a593Smuzhiyun /**< ISDB-T 8MHzBW (IF: Fc=4.75MHz in default) */
80*4882a593Smuzhiyun SONY_HELENE_DTV_DVBT_5,
81*4882a593Smuzhiyun /**< DVB-T 5MHzBW (IF: Fc=3.6MHz in default) */
82*4882a593Smuzhiyun SONY_HELENE_DTV_DVBT_6,
83*4882a593Smuzhiyun /**< DVB-T 6MHzBW (IF: Fc=3.6MHz in default) */
84*4882a593Smuzhiyun SONY_HELENE_DTV_DVBT_7,
85*4882a593Smuzhiyun /**< DVB-T 7MHzBW (IF: Fc=4.2MHz in default) */
86*4882a593Smuzhiyun SONY_HELENE_DTV_DVBT_8,
87*4882a593Smuzhiyun /**< DVB-T 8MHzBW (IF: Fc=4.8MHz in default) */
88*4882a593Smuzhiyun SONY_HELENE_DTV_DVBT2_1_7,
89*4882a593Smuzhiyun /**< DVB-T2 1.7MHzBW (IF: Fc=3.5MHz in default) */
90*4882a593Smuzhiyun SONY_HELENE_DTV_DVBT2_5,
91*4882a593Smuzhiyun /**< DVB-T2 5MHzBW (IF: Fc=3.6MHz in default) */
92*4882a593Smuzhiyun SONY_HELENE_DTV_DVBT2_6,
93*4882a593Smuzhiyun /**< DVB-T2 6MHzBW (IF: Fc=3.6MHz in default) */
94*4882a593Smuzhiyun SONY_HELENE_DTV_DVBT2_7,
95*4882a593Smuzhiyun /**< DVB-T2 7MHzBW (IF: Fc=4.2MHz in default) */
96*4882a593Smuzhiyun SONY_HELENE_DTV_DVBT2_8,
97*4882a593Smuzhiyun /**< DVB-T2 8MHzBW (IF: Fc=4.8MHz in default) */
98*4882a593Smuzhiyun SONY_HELENE_DTV_DVBC_6,
99*4882a593Smuzhiyun /**< DVB-C 6MHzBW (IF: Fc=3.7MHz in default) */
100*4882a593Smuzhiyun SONY_HELENE_DTV_DVBC_8,
101*4882a593Smuzhiyun /**< DVB-C 8MHzBW (IF: Fc=4.9MHz in default) */
102*4882a593Smuzhiyun SONY_HELENE_DTV_DVBC2_6,
103*4882a593Smuzhiyun /**< DVB-C2 6MHzBW (IF: Fc=3.7MHz in default) */
104*4882a593Smuzhiyun SONY_HELENE_DTV_DVBC2_8,
105*4882a593Smuzhiyun /**< DVB-C2 8MHzBW (IF: Fc=4.9MHz in default) */
106*4882a593Smuzhiyun SONY_HELENE_DTV_DTMB,
107*4882a593Smuzhiyun /**< DTMB (IF: Fc=5.1MHz in default) */
108*4882a593Smuzhiyun /* Satellite */
109*4882a593Smuzhiyun SONY_HELENE_STV_ISDBS,
110*4882a593Smuzhiyun /**< ISDB-S */
111*4882a593Smuzhiyun SONY_HELENE_STV_DVBS,
112*4882a593Smuzhiyun /**< DVB-S */
113*4882a593Smuzhiyun SONY_HELENE_STV_DVBS2,
114*4882a593Smuzhiyun /**< DVB-S2 */
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun SONY_HELENE_ATV_MIN = SONY_HELENE_ATV_MN_EIAJ,
117*4882a593Smuzhiyun /**< Minimum analog terrestrial system */
118*4882a593Smuzhiyun SONY_HELENE_ATV_MAX = SONY_HELENE_ATV_L_DASH,
119*4882a593Smuzhiyun /**< Maximum analog terrestrial system */
120*4882a593Smuzhiyun SONY_HELENE_DTV_MIN = SONY_HELENE_DTV_8VSB,
121*4882a593Smuzhiyun /**< Minimum digital terrestrial system */
122*4882a593Smuzhiyun SONY_HELENE_DTV_MAX = SONY_HELENE_DTV_DTMB,
123*4882a593Smuzhiyun /**< Maximum digital terrestrial system */
124*4882a593Smuzhiyun SONY_HELENE_TERR_TV_SYSTEM_NUM,
125*4882a593Smuzhiyun /**< Number of supported terrestrial broadcasting system */
126*4882a593Smuzhiyun SONY_HELENE_STV_MIN = SONY_HELENE_STV_ISDBS,
127*4882a593Smuzhiyun /**< Minimum satellite system */
128*4882a593Smuzhiyun SONY_HELENE_STV_MAX = SONY_HELENE_STV_DVBS2
129*4882a593Smuzhiyun /**< Maximum satellite system */
130*4882a593Smuzhiyun };
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun struct helene_terr_adjust_param_t {
133*4882a593Smuzhiyun /* < Addr:0x69 Bit[6:4] : RFVGA gain.
134*4882a593Smuzhiyun * 0xFF means Auto. (RF_GAIN_SEL = 1)
135*4882a593Smuzhiyun */
136*4882a593Smuzhiyun uint8_t RF_GAIN;
137*4882a593Smuzhiyun /* < Addr:0x69 Bit[3:0] : IF_BPF gain.
138*4882a593Smuzhiyun */
139*4882a593Smuzhiyun uint8_t IF_BPF_GC;
140*4882a593Smuzhiyun /* < Addr:0x6B Bit[3:0] : RF overload
141*4882a593Smuzhiyun * RF input detect level. (FRF <= 172MHz)
142*4882a593Smuzhiyun */
143*4882a593Smuzhiyun uint8_t RFOVLD_DET_LV1_VL;
144*4882a593Smuzhiyun /* < Addr:0x6B Bit[3:0] : RF overload
145*4882a593Smuzhiyun * RF input detect level. (172MHz < FRF <= 464MHz)
146*4882a593Smuzhiyun */
147*4882a593Smuzhiyun uint8_t RFOVLD_DET_LV1_VH;
148*4882a593Smuzhiyun /* < Addr:0x6B Bit[3:0] : RF overload
149*4882a593Smuzhiyun * RF input detect level. (FRF > 464MHz)
150*4882a593Smuzhiyun */
151*4882a593Smuzhiyun uint8_t RFOVLD_DET_LV1_U;
152*4882a593Smuzhiyun /* < Addr:0x6C Bit[2:0] :
153*4882a593Smuzhiyun * Internal RFAGC detect level. (FRF <= 172MHz)
154*4882a593Smuzhiyun */
155*4882a593Smuzhiyun uint8_t IFOVLD_DET_LV_VL;
156*4882a593Smuzhiyun /* < Addr:0x6C Bit[2:0] :
157*4882a593Smuzhiyun * Internal RFAGC detect level. (172MHz < FRF <= 464MHz)
158*4882a593Smuzhiyun */
159*4882a593Smuzhiyun uint8_t IFOVLD_DET_LV_VH;
160*4882a593Smuzhiyun /* < Addr:0x6C Bit[2:0] :
161*4882a593Smuzhiyun * Internal RFAGC detect level. (FRF > 464MHz)
162*4882a593Smuzhiyun */
163*4882a593Smuzhiyun uint8_t IFOVLD_DET_LV_U;
164*4882a593Smuzhiyun /* < Addr:0x6D Bit[5:4] :
165*4882a593Smuzhiyun * IF filter center offset.
166*4882a593Smuzhiyun */
167*4882a593Smuzhiyun uint8_t IF_BPF_F0;
168*4882a593Smuzhiyun /* < Addr:0x6D Bit[1:0] :
169*4882a593Smuzhiyun * 6MHzBW(0x00) or 7MHzBW(0x01)
170*4882a593Smuzhiyun * or 8MHzBW(0x02) or 1.7MHzBW(0x03)
171*4882a593Smuzhiyun */
172*4882a593Smuzhiyun uint8_t BW;
173*4882a593Smuzhiyun /* < Addr:0x6E Bit[4:0] :
174*4882a593Smuzhiyun * 5bit signed. IF offset (kHz) = FIF_OFFSET x 50
175*4882a593Smuzhiyun */
176*4882a593Smuzhiyun uint8_t FIF_OFFSET;
177*4882a593Smuzhiyun /* < Addr:0x6F Bit[4:0] :
178*4882a593Smuzhiyun * 5bit signed. BW offset (kHz) =
179*4882a593Smuzhiyun * BW_OFFSET x 50 (BW_OFFSET x 10 in 1.7MHzBW)
180*4882a593Smuzhiyun */
181*4882a593Smuzhiyun uint8_t BW_OFFSET;
182*4882a593Smuzhiyun /* < Addr:0x9C Bit[0] :
183*4882a593Smuzhiyun * Local polarity. (0: Upper Local, 1: Lower Local)
184*4882a593Smuzhiyun */
185*4882a593Smuzhiyun uint8_t IS_LOWERLOCAL;
186*4882a593Smuzhiyun };
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun static const struct helene_terr_adjust_param_t
189*4882a593Smuzhiyun terr_params[SONY_HELENE_TERR_TV_SYSTEM_NUM] = {
190*4882a593Smuzhiyun /*< SONY_HELENE_TV_SYSTEM_UNKNOWN */
191*4882a593Smuzhiyun {HELENE_AUTO, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192*4882a593Smuzhiyun HELENE_BW_6, HELENE_OFFSET(0), HELENE_OFFSET(0), 0x00},
193*4882a593Smuzhiyun /* Analog */
194*4882a593Smuzhiyun /**< SONY_HELENE_ATV_MN_EIAJ (System-M (Japan)) */
195*4882a593Smuzhiyun {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00,
196*4882a593Smuzhiyun HELENE_BW_6, HELENE_OFFSET(0), HELENE_OFFSET(1), 0x00},
197*4882a593Smuzhiyun /**< SONY_HELENE_ATV_MN_SAP (System-M (US)) */
198*4882a593Smuzhiyun {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00,
199*4882a593Smuzhiyun HELENE_BW_6, HELENE_OFFSET(0), HELENE_OFFSET(1), 0x00},
200*4882a593Smuzhiyun {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00,
201*4882a593Smuzhiyun HELENE_BW_6, HELENE_OFFSET(3), HELENE_OFFSET(1), 0x00},
202*4882a593Smuzhiyun /**< SONY_HELENE_ATV_MN_A2 (System-M (Korea)) */
203*4882a593Smuzhiyun {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00,
204*4882a593Smuzhiyun HELENE_BW_7, HELENE_OFFSET(11), HELENE_OFFSET(5), 0x00},
205*4882a593Smuzhiyun /**< SONY_HELENE_ATV_BG (System-B/G) */
206*4882a593Smuzhiyun {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00,
207*4882a593Smuzhiyun HELENE_BW_8, HELENE_OFFSET(2), HELENE_OFFSET(-3), 0x00},
208*4882a593Smuzhiyun /**< SONY_HELENE_ATV_I (System-I) */
209*4882a593Smuzhiyun {HELENE_AUTO, 0x05, 0x03, 0x06, 0x03, 0x01, 0x01, 0x01, 0x00,
210*4882a593Smuzhiyun HELENE_BW_8, HELENE_OFFSET(2), HELENE_OFFSET(-3), 0x00},
211*4882a593Smuzhiyun /**< SONY_HELENE_ATV_DK (System-D/K) */
212*4882a593Smuzhiyun {HELENE_AUTO, 0x03, 0x04, 0x0A, 0x04, 0x04, 0x04, 0x04, 0x00,
213*4882a593Smuzhiyun HELENE_BW_8, HELENE_OFFSET(2), HELENE_OFFSET(-3), 0x00},
214*4882a593Smuzhiyun /**< SONY_HELENE_ATV_L (System-L) */
215*4882a593Smuzhiyun {HELENE_AUTO, 0x03, 0x04, 0x0A, 0x04, 0x04, 0x04, 0x04, 0x00,
216*4882a593Smuzhiyun HELENE_BW_8, HELENE_OFFSET(-1), HELENE_OFFSET(4), 0x00},
217*4882a593Smuzhiyun /**< SONY_HELENE_ATV_L_DASH (System-L DASH) */
218*4882a593Smuzhiyun /* Digital */
219*4882a593Smuzhiyun {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x03, 0x03, 0x03, 0x00,
220*4882a593Smuzhiyun HELENE_BW_6, HELENE_OFFSET(-6), HELENE_OFFSET(-3), 0x00},
221*4882a593Smuzhiyun /**< SONY_HELENE_DTV_8VSB (ATSC 8VSB) */
222*4882a593Smuzhiyun {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00,
223*4882a593Smuzhiyun HELENE_BW_6, HELENE_OFFSET(-6), HELENE_OFFSET(-3), 0x00},
224*4882a593Smuzhiyun /**< SONY_HELENE_DTV_QAM (US QAM) */
225*4882a593Smuzhiyun {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00,
226*4882a593Smuzhiyun HELENE_BW_6, HELENE_OFFSET(-9), HELENE_OFFSET(-5), 0x00},
227*4882a593Smuzhiyun /**< SONY_HELENE_DTV_ISDBT_6 (ISDB-T 6MHzBW) */
228*4882a593Smuzhiyun {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00,
229*4882a593Smuzhiyun HELENE_BW_7, HELENE_OFFSET(-7), HELENE_OFFSET(-6), 0x00},
230*4882a593Smuzhiyun /**< SONY_HELENE_DTV_ISDBT_7 (ISDB-T 7MHzBW) */
231*4882a593Smuzhiyun {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00,
232*4882a593Smuzhiyun HELENE_BW_8, HELENE_OFFSET(-5), HELENE_OFFSET(-7), 0x00},
233*4882a593Smuzhiyun /**< SONY_HELENE_DTV_ISDBT_8 (ISDB-T 8MHzBW) */
234*4882a593Smuzhiyun {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00,
235*4882a593Smuzhiyun HELENE_BW_6, HELENE_OFFSET(-8), HELENE_OFFSET(-3), 0x00},
236*4882a593Smuzhiyun /**< SONY_HELENE_DTV_DVBT_5 (DVB-T 5MHzBW) */
237*4882a593Smuzhiyun {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00,
238*4882a593Smuzhiyun HELENE_BW_6, HELENE_OFFSET(-8), HELENE_OFFSET(-3), 0x00},
239*4882a593Smuzhiyun /**< SONY_HELENE_DTV_DVBT_6 (DVB-T 6MHzBW) */
240*4882a593Smuzhiyun {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00,
241*4882a593Smuzhiyun HELENE_BW_7, HELENE_OFFSET(-6), HELENE_OFFSET(-5), 0x00},
242*4882a593Smuzhiyun /**< SONY_HELENE_DTV_DVBT_7 (DVB-T 7MHzBW) */
243*4882a593Smuzhiyun {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00,
244*4882a593Smuzhiyun HELENE_BW_8, HELENE_OFFSET(-4), HELENE_OFFSET(-6), 0x00},
245*4882a593Smuzhiyun /**< SONY_HELENE_DTV_DVBT_8 (DVB-T 8MHzBW) */
246*4882a593Smuzhiyun {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00,
247*4882a593Smuzhiyun HELENE_BW_1_7, HELENE_OFFSET(-10), HELENE_OFFSET(-10), 0x00},
248*4882a593Smuzhiyun /**< SONY_HELENE_DTV_DVBT2_1_7 (DVB-T2 1.7MHzBW) */
249*4882a593Smuzhiyun {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00,
250*4882a593Smuzhiyun HELENE_BW_6, HELENE_OFFSET(-8), HELENE_OFFSET(-3), 0x00},
251*4882a593Smuzhiyun /**< SONY_HELENE_DTV_DVBT2_5 (DVB-T2 5MHzBW) */
252*4882a593Smuzhiyun {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00,
253*4882a593Smuzhiyun HELENE_BW_6, HELENE_OFFSET(-8), HELENE_OFFSET(-3), 0x00},
254*4882a593Smuzhiyun /**< SONY_HELENE_DTV_DVBT2_6 (DVB-T2 6MHzBW) */
255*4882a593Smuzhiyun {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00,
256*4882a593Smuzhiyun HELENE_BW_7, HELENE_OFFSET(-6), HELENE_OFFSET(-5), 0x00},
257*4882a593Smuzhiyun /**< SONY_HELENE_DTV_DVBT2_7 (DVB-T2 7MHzBW) */
258*4882a593Smuzhiyun {HELENE_AUTO, 0x09, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00,
259*4882a593Smuzhiyun HELENE_BW_8, HELENE_OFFSET(-4), HELENE_OFFSET(-6), 0x00},
260*4882a593Smuzhiyun /**< SONY_HELENE_DTV_DVBT2_8 (DVB-T2 8MHzBW) */
261*4882a593Smuzhiyun {HELENE_AUTO, 0x05, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00,
262*4882a593Smuzhiyun HELENE_BW_6, HELENE_OFFSET(-6), HELENE_OFFSET(-4), 0x00},
263*4882a593Smuzhiyun /**< SONY_HELENE_DTV_DVBC_6 (DVB-C 6MHzBW) */
264*4882a593Smuzhiyun {HELENE_AUTO, 0x05, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00,
265*4882a593Smuzhiyun HELENE_BW_8, HELENE_OFFSET(-2), HELENE_OFFSET(-3), 0x00},
266*4882a593Smuzhiyun /**< SONY_HELENE_DTV_DVBC_8 (DVB-C 8MHzBW) */
267*4882a593Smuzhiyun {HELENE_AUTO, 0x03, 0x09, 0x09, 0x09, 0x02, 0x02, 0x02, 0x00,
268*4882a593Smuzhiyun HELENE_BW_6, HELENE_OFFSET(-6), HELENE_OFFSET(-2), 0x00},
269*4882a593Smuzhiyun /**< SONY_HELENE_DTV_DVBC2_6 (DVB-C2 6MHzBW) */
270*4882a593Smuzhiyun {HELENE_AUTO, 0x03, 0x09, 0x09, 0x09, 0x02, 0x02, 0x02, 0x00,
271*4882a593Smuzhiyun HELENE_BW_8, HELENE_OFFSET(-2), HELENE_OFFSET(0), 0x00},
272*4882a593Smuzhiyun /**< SONY_HELENE_DTV_DVBC2_8 (DVB-C2 8MHzBW) */
273*4882a593Smuzhiyun {HELENE_AUTO, 0x04, 0x0B, 0x0B, 0x0B, 0x02, 0x02, 0x02, 0x00,
274*4882a593Smuzhiyun HELENE_BW_8, HELENE_OFFSET(2), HELENE_OFFSET(1), 0x00}
275*4882a593Smuzhiyun /**< SONY_HELENE_DTV_DTMB (DTMB) */
276*4882a593Smuzhiyun };
277*4882a593Smuzhiyun
helene_i2c_debug(struct helene_priv * priv,u8 reg,u8 write,const u8 * data,u32 len)278*4882a593Smuzhiyun static void helene_i2c_debug(struct helene_priv *priv,
279*4882a593Smuzhiyun u8 reg, u8 write, const u8 *data, u32 len)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun dev_dbg(&priv->i2c->dev, "helene: I2C %s reg 0x%02x size %d\n",
282*4882a593Smuzhiyun (write == 0 ? "read" : "write"), reg, len);
283*4882a593Smuzhiyun print_hex_dump_bytes("helene: I2C data: ",
284*4882a593Smuzhiyun DUMP_PREFIX_OFFSET, data, len);
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun
helene_write_regs(struct helene_priv * priv,u8 reg,const u8 * data,u32 len)287*4882a593Smuzhiyun static int helene_write_regs(struct helene_priv *priv,
288*4882a593Smuzhiyun u8 reg, const u8 *data, u32 len)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun int ret;
291*4882a593Smuzhiyun u8 buf[MAX_WRITE_REGSIZE + 1];
292*4882a593Smuzhiyun struct i2c_msg msg[1] = {
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun .addr = priv->i2c_address,
295*4882a593Smuzhiyun .flags = 0,
296*4882a593Smuzhiyun .len = len + 1,
297*4882a593Smuzhiyun .buf = buf,
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun };
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun if (len + 1 > sizeof(buf)) {
302*4882a593Smuzhiyun dev_warn(&priv->i2c->dev,
303*4882a593Smuzhiyun "wr reg=%04x: len=%d vs %zu is too big!\n",
304*4882a593Smuzhiyun reg, len + 1, sizeof(buf));
305*4882a593Smuzhiyun return -E2BIG;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun helene_i2c_debug(priv, reg, 1, data, len);
309*4882a593Smuzhiyun buf[0] = reg;
310*4882a593Smuzhiyun memcpy(&buf[1], data, len);
311*4882a593Smuzhiyun ret = i2c_transfer(priv->i2c, msg, 1);
312*4882a593Smuzhiyun if (ret >= 0 && ret != 1)
313*4882a593Smuzhiyun ret = -EREMOTEIO;
314*4882a593Smuzhiyun if (ret < 0) {
315*4882a593Smuzhiyun dev_warn(&priv->i2c->dev,
316*4882a593Smuzhiyun "%s: i2c wr failed=%d reg=%02x len=%d\n",
317*4882a593Smuzhiyun KBUILD_MODNAME, ret, reg, len);
318*4882a593Smuzhiyun return ret;
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun return 0;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun
helene_write_reg(struct helene_priv * priv,u8 reg,u8 val)323*4882a593Smuzhiyun static int helene_write_reg(struct helene_priv *priv, u8 reg, u8 val)
324*4882a593Smuzhiyun {
325*4882a593Smuzhiyun u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun return helene_write_regs(priv, reg, &tmp, 1);
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun
helene_read_regs(struct helene_priv * priv,u8 reg,u8 * val,u32 len)330*4882a593Smuzhiyun static int helene_read_regs(struct helene_priv *priv,
331*4882a593Smuzhiyun u8 reg, u8 *val, u32 len)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun int ret;
334*4882a593Smuzhiyun struct i2c_msg msg[2] = {
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun .addr = priv->i2c_address,
337*4882a593Smuzhiyun .flags = 0,
338*4882a593Smuzhiyun .len = 1,
339*4882a593Smuzhiyun .buf = ®,
340*4882a593Smuzhiyun }, {
341*4882a593Smuzhiyun .addr = priv->i2c_address,
342*4882a593Smuzhiyun .flags = I2C_M_RD,
343*4882a593Smuzhiyun .len = len,
344*4882a593Smuzhiyun .buf = val,
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun };
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun ret = i2c_transfer(priv->i2c, &msg[0], 1);
349*4882a593Smuzhiyun if (ret >= 0 && ret != 1)
350*4882a593Smuzhiyun ret = -EREMOTEIO;
351*4882a593Smuzhiyun if (ret < 0) {
352*4882a593Smuzhiyun dev_warn(&priv->i2c->dev,
353*4882a593Smuzhiyun "%s: I2C rw failed=%d addr=%02x reg=%02x\n",
354*4882a593Smuzhiyun KBUILD_MODNAME, ret, priv->i2c_address, reg);
355*4882a593Smuzhiyun return ret;
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun ret = i2c_transfer(priv->i2c, &msg[1], 1);
358*4882a593Smuzhiyun if (ret >= 0 && ret != 1)
359*4882a593Smuzhiyun ret = -EREMOTEIO;
360*4882a593Smuzhiyun if (ret < 0) {
361*4882a593Smuzhiyun dev_warn(&priv->i2c->dev,
362*4882a593Smuzhiyun "%s: i2c rd failed=%d addr=%02x reg=%02x\n",
363*4882a593Smuzhiyun KBUILD_MODNAME, ret, priv->i2c_address, reg);
364*4882a593Smuzhiyun return ret;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun helene_i2c_debug(priv, reg, 0, val, len);
367*4882a593Smuzhiyun return 0;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun
helene_read_reg(struct helene_priv * priv,u8 reg,u8 * val)370*4882a593Smuzhiyun static int helene_read_reg(struct helene_priv *priv, u8 reg, u8 *val)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun return helene_read_regs(priv, reg, val, 1);
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun
helene_set_reg_bits(struct helene_priv * priv,u8 reg,u8 data,u8 mask)375*4882a593Smuzhiyun static int helene_set_reg_bits(struct helene_priv *priv,
376*4882a593Smuzhiyun u8 reg, u8 data, u8 mask)
377*4882a593Smuzhiyun {
378*4882a593Smuzhiyun int res;
379*4882a593Smuzhiyun u8 rdata;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun if (mask != 0xff) {
382*4882a593Smuzhiyun res = helene_read_reg(priv, reg, &rdata);
383*4882a593Smuzhiyun if (res != 0)
384*4882a593Smuzhiyun return res;
385*4882a593Smuzhiyun data = ((data & mask) | (rdata & (mask ^ 0xFF)));
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun return helene_write_reg(priv, reg, data);
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun
helene_enter_power_save(struct helene_priv * priv)390*4882a593Smuzhiyun static int helene_enter_power_save(struct helene_priv *priv)
391*4882a593Smuzhiyun {
392*4882a593Smuzhiyun dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
393*4882a593Smuzhiyun if (priv->state == STATE_SLEEP)
394*4882a593Smuzhiyun return 0;
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun /* Standby setting for CPU */
397*4882a593Smuzhiyun helene_write_reg(priv, 0x88, 0x0);
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun /* Standby setting for internal logic block */
400*4882a593Smuzhiyun helene_write_reg(priv, 0x87, 0xC0);
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun priv->state = STATE_SLEEP;
403*4882a593Smuzhiyun return 0;
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun
helene_leave_power_save(struct helene_priv * priv)406*4882a593Smuzhiyun static int helene_leave_power_save(struct helene_priv *priv)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
409*4882a593Smuzhiyun if (priv->state == STATE_ACTIVE)
410*4882a593Smuzhiyun return 0;
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun /* Standby setting for internal logic block */
413*4882a593Smuzhiyun helene_write_reg(priv, 0x87, 0xC4);
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun /* Standby setting for CPU */
416*4882a593Smuzhiyun helene_write_reg(priv, 0x88, 0x40);
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun priv->state = STATE_ACTIVE;
419*4882a593Smuzhiyun return 0;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun
helene_init(struct dvb_frontend * fe)422*4882a593Smuzhiyun static int helene_init(struct dvb_frontend *fe)
423*4882a593Smuzhiyun {
424*4882a593Smuzhiyun struct helene_priv *priv = fe->tuner_priv;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
427*4882a593Smuzhiyun return helene_leave_power_save(priv);
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun
helene_release(struct dvb_frontend * fe)430*4882a593Smuzhiyun static void helene_release(struct dvb_frontend *fe)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun struct helene_priv *priv = fe->tuner_priv;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
435*4882a593Smuzhiyun kfree(fe->tuner_priv);
436*4882a593Smuzhiyun fe->tuner_priv = NULL;
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun
helene_sleep(struct dvb_frontend * fe)439*4882a593Smuzhiyun static int helene_sleep(struct dvb_frontend *fe)
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun struct helene_priv *priv = fe->tuner_priv;
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
444*4882a593Smuzhiyun helene_enter_power_save(priv);
445*4882a593Smuzhiyun return 0;
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun
helene_get_tv_system(struct dvb_frontend * fe)448*4882a593Smuzhiyun static enum helene_tv_system_t helene_get_tv_system(struct dvb_frontend *fe)
449*4882a593Smuzhiyun {
450*4882a593Smuzhiyun enum helene_tv_system_t system = SONY_HELENE_TV_SYSTEM_UNKNOWN;
451*4882a593Smuzhiyun struct dtv_frontend_properties *p = &fe->dtv_property_cache;
452*4882a593Smuzhiyun struct helene_priv *priv = fe->tuner_priv;
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun if (p->delivery_system == SYS_DVBT) {
455*4882a593Smuzhiyun if (p->bandwidth_hz <= 5000000)
456*4882a593Smuzhiyun system = SONY_HELENE_DTV_DVBT_5;
457*4882a593Smuzhiyun else if (p->bandwidth_hz <= 6000000)
458*4882a593Smuzhiyun system = SONY_HELENE_DTV_DVBT_6;
459*4882a593Smuzhiyun else if (p->bandwidth_hz <= 7000000)
460*4882a593Smuzhiyun system = SONY_HELENE_DTV_DVBT_7;
461*4882a593Smuzhiyun else if (p->bandwidth_hz <= 8000000)
462*4882a593Smuzhiyun system = SONY_HELENE_DTV_DVBT_8;
463*4882a593Smuzhiyun else {
464*4882a593Smuzhiyun system = SONY_HELENE_DTV_DVBT_8;
465*4882a593Smuzhiyun p->bandwidth_hz = 8000000;
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun } else if (p->delivery_system == SYS_DVBT2) {
468*4882a593Smuzhiyun if (p->bandwidth_hz <= 5000000)
469*4882a593Smuzhiyun system = SONY_HELENE_DTV_DVBT2_5;
470*4882a593Smuzhiyun else if (p->bandwidth_hz <= 6000000)
471*4882a593Smuzhiyun system = SONY_HELENE_DTV_DVBT2_6;
472*4882a593Smuzhiyun else if (p->bandwidth_hz <= 7000000)
473*4882a593Smuzhiyun system = SONY_HELENE_DTV_DVBT2_7;
474*4882a593Smuzhiyun else if (p->bandwidth_hz <= 8000000)
475*4882a593Smuzhiyun system = SONY_HELENE_DTV_DVBT2_8;
476*4882a593Smuzhiyun else {
477*4882a593Smuzhiyun system = SONY_HELENE_DTV_DVBT2_8;
478*4882a593Smuzhiyun p->bandwidth_hz = 8000000;
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun } else if (p->delivery_system == SYS_DVBS) {
481*4882a593Smuzhiyun system = SONY_HELENE_STV_DVBS;
482*4882a593Smuzhiyun } else if (p->delivery_system == SYS_DVBS2) {
483*4882a593Smuzhiyun system = SONY_HELENE_STV_DVBS2;
484*4882a593Smuzhiyun } else if (p->delivery_system == SYS_ISDBS) {
485*4882a593Smuzhiyun system = SONY_HELENE_STV_ISDBS;
486*4882a593Smuzhiyun } else if (p->delivery_system == SYS_ISDBT) {
487*4882a593Smuzhiyun if (p->bandwidth_hz <= 6000000)
488*4882a593Smuzhiyun system = SONY_HELENE_DTV_ISDBT_6;
489*4882a593Smuzhiyun else if (p->bandwidth_hz <= 7000000)
490*4882a593Smuzhiyun system = SONY_HELENE_DTV_ISDBT_7;
491*4882a593Smuzhiyun else if (p->bandwidth_hz <= 8000000)
492*4882a593Smuzhiyun system = SONY_HELENE_DTV_ISDBT_8;
493*4882a593Smuzhiyun else {
494*4882a593Smuzhiyun system = SONY_HELENE_DTV_ISDBT_8;
495*4882a593Smuzhiyun p->bandwidth_hz = 8000000;
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun } else if (p->delivery_system == SYS_DVBC_ANNEX_A) {
498*4882a593Smuzhiyun if (p->bandwidth_hz <= 6000000)
499*4882a593Smuzhiyun system = SONY_HELENE_DTV_DVBC_6;
500*4882a593Smuzhiyun else if (p->bandwidth_hz <= 8000000)
501*4882a593Smuzhiyun system = SONY_HELENE_DTV_DVBC_8;
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun dev_dbg(&priv->i2c->dev,
504*4882a593Smuzhiyun "%s(): HELENE DTV system %d (delsys %d, bandwidth %d)\n",
505*4882a593Smuzhiyun __func__, (int)system, p->delivery_system,
506*4882a593Smuzhiyun p->bandwidth_hz);
507*4882a593Smuzhiyun return system;
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun
helene_set_params_s(struct dvb_frontend * fe)510*4882a593Smuzhiyun static int helene_set_params_s(struct dvb_frontend *fe)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun u8 data[MAX_WRITE_REGSIZE];
513*4882a593Smuzhiyun u32 frequency;
514*4882a593Smuzhiyun enum helene_tv_system_t tv_system;
515*4882a593Smuzhiyun struct dtv_frontend_properties *p = &fe->dtv_property_cache;
516*4882a593Smuzhiyun struct helene_priv *priv = fe->tuner_priv;
517*4882a593Smuzhiyun int frequencykHz = p->frequency;
518*4882a593Smuzhiyun uint32_t frequency4kHz = 0;
519*4882a593Smuzhiyun u32 symbol_rate = p->symbol_rate/1000;
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun dev_dbg(&priv->i2c->dev, "%s(): tune frequency %dkHz sr=%uKsps\n",
522*4882a593Smuzhiyun __func__, frequencykHz, symbol_rate);
523*4882a593Smuzhiyun tv_system = helene_get_tv_system(fe);
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun if (tv_system == SONY_HELENE_TV_SYSTEM_UNKNOWN) {
526*4882a593Smuzhiyun dev_err(&priv->i2c->dev, "%s(): unknown DTV system\n",
527*4882a593Smuzhiyun __func__);
528*4882a593Smuzhiyun return -EINVAL;
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun /* RF switch turn to satellite */
531*4882a593Smuzhiyun if (priv->set_tuner)
532*4882a593Smuzhiyun priv->set_tuner(priv->set_tuner_data, 0);
533*4882a593Smuzhiyun frequency = roundup(p->frequency / 1000, 1);
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun /* Disable IF signal output */
536*4882a593Smuzhiyun helene_write_reg(priv, 0x15, 0x02);
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun /* RFIN matching in power save (Sat) reset */
539*4882a593Smuzhiyun helene_write_reg(priv, 0x43, 0x06);
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun /* Analog block setting (0x6A, 0x6B) */
542*4882a593Smuzhiyun data[0] = 0x00;
543*4882a593Smuzhiyun data[1] = 0x00;
544*4882a593Smuzhiyun helene_write_regs(priv, 0x6A, data, 2);
545*4882a593Smuzhiyun helene_write_reg(priv, 0x75, 0x99);
546*4882a593Smuzhiyun helene_write_reg(priv, 0x9D, 0x00);
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun /* Tuning setting for CPU (0x61) */
549*4882a593Smuzhiyun helene_write_reg(priv, 0x61, 0x07);
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun /* Satellite mode select (0x01) */
552*4882a593Smuzhiyun helene_write_reg(priv, 0x01, 0x01);
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun /* Clock enable for internal logic block, CPU wake-up (0x04, 0x05) */
555*4882a593Smuzhiyun data[0] = 0xC4;
556*4882a593Smuzhiyun data[1] = 0x40;
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun switch (priv->xtal) {
559*4882a593Smuzhiyun case SONY_HELENE_XTAL_16000:
560*4882a593Smuzhiyun data[2] = 0x02;
561*4882a593Smuzhiyun break;
562*4882a593Smuzhiyun case SONY_HELENE_XTAL_20500:
563*4882a593Smuzhiyun data[2] = 0x02;
564*4882a593Smuzhiyun break;
565*4882a593Smuzhiyun case SONY_HELENE_XTAL_24000:
566*4882a593Smuzhiyun data[2] = 0x03;
567*4882a593Smuzhiyun break;
568*4882a593Smuzhiyun case SONY_HELENE_XTAL_41000:
569*4882a593Smuzhiyun data[2] = 0x05;
570*4882a593Smuzhiyun break;
571*4882a593Smuzhiyun default:
572*4882a593Smuzhiyun dev_err(&priv->i2c->dev, "%s(): unknown xtal %d\n",
573*4882a593Smuzhiyun __func__, priv->xtal);
574*4882a593Smuzhiyun return -EINVAL;
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun /* Setting for analog block (0x07). LOOPFILTER INTERNAL */
578*4882a593Smuzhiyun data[3] = 0x80;
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun /* Tuning setting for analog block
581*4882a593Smuzhiyun * (0x08, 0x09, 0x0A, 0x0B). LOOPFILTER INTERNAL
582*4882a593Smuzhiyun */
583*4882a593Smuzhiyun if (priv->xtal == SONY_HELENE_XTAL_20500)
584*4882a593Smuzhiyun data[4] = 0x58;
585*4882a593Smuzhiyun else
586*4882a593Smuzhiyun data[4] = 0x70;
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun data[5] = 0x1E;
589*4882a593Smuzhiyun data[6] = 0x02;
590*4882a593Smuzhiyun data[7] = 0x24;
591*4882a593Smuzhiyun
592*4882a593Smuzhiyun /* Enable for analog block (0x0C, 0x0D, 0x0E). SAT LNA ON */
593*4882a593Smuzhiyun data[8] = 0x0F;
594*4882a593Smuzhiyun data[8] |= 0xE0; /* POWERSAVE_TERR_RF_ACTIVE */
595*4882a593Smuzhiyun data[9] = 0x02;
596*4882a593Smuzhiyun data[10] = 0x1E;
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun /* Setting for LPF cutoff frequency (0x0F) */
599*4882a593Smuzhiyun switch (tv_system) {
600*4882a593Smuzhiyun case SONY_HELENE_STV_ISDBS:
601*4882a593Smuzhiyun data[11] = 0x22; /* 22MHz */
602*4882a593Smuzhiyun break;
603*4882a593Smuzhiyun case SONY_HELENE_STV_DVBS:
604*4882a593Smuzhiyun if (symbol_rate <= 4000)
605*4882a593Smuzhiyun data[11] = 0x05;
606*4882a593Smuzhiyun else if (symbol_rate <= 10000)
607*4882a593Smuzhiyun data[11] = (uint8_t)((symbol_rate * 47
608*4882a593Smuzhiyun + (40000-1)) / 40000);
609*4882a593Smuzhiyun else
610*4882a593Smuzhiyun data[11] = (uint8_t)((symbol_rate * 27
611*4882a593Smuzhiyun + (40000-1)) / 40000 + 5);
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun if (data[11] > 36)
614*4882a593Smuzhiyun data[11] = 36; /* 5 <= lpf_cutoff <= 36 is valid */
615*4882a593Smuzhiyun break;
616*4882a593Smuzhiyun case SONY_HELENE_STV_DVBS2:
617*4882a593Smuzhiyun if (symbol_rate <= 4000)
618*4882a593Smuzhiyun data[11] = 0x05;
619*4882a593Smuzhiyun else if (symbol_rate <= 10000)
620*4882a593Smuzhiyun data[11] = (uint8_t)((symbol_rate * 11
621*4882a593Smuzhiyun + (10000-1)) / 10000);
622*4882a593Smuzhiyun else
623*4882a593Smuzhiyun data[11] = (uint8_t)((symbol_rate * 3
624*4882a593Smuzhiyun + (5000-1)) / 5000 + 5);
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun if (data[11] > 36)
627*4882a593Smuzhiyun data[11] = 36; /* 5 <= lpf_cutoff <= 36 is valid */
628*4882a593Smuzhiyun break;
629*4882a593Smuzhiyun default:
630*4882a593Smuzhiyun dev_err(&priv->i2c->dev, "%s(): unknown standard %d\n",
631*4882a593Smuzhiyun __func__, tv_system);
632*4882a593Smuzhiyun return -EINVAL;
633*4882a593Smuzhiyun }
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun /* RF tuning frequency setting (0x10, 0x11, 0x12) */
636*4882a593Smuzhiyun frequency4kHz = (frequencykHz + 2) / 4;
637*4882a593Smuzhiyun data[12] = (uint8_t)(frequency4kHz & 0xFF); /* FRF_L */
638*4882a593Smuzhiyun data[13] = (uint8_t)((frequency4kHz >> 8) & 0xFF); /* FRF_M */
639*4882a593Smuzhiyun /* FRF_H (bit[3:0]) */
640*4882a593Smuzhiyun data[14] = (uint8_t)((frequency4kHz >> 16) & 0x0F);
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun /* Tuning command (0x13) */
643*4882a593Smuzhiyun data[15] = 0xFF;
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun /* Setting for IQOUT_LIMIT (0x14) 0.75Vpp */
646*4882a593Smuzhiyun data[16] = 0x00;
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun /* Enable IQ output (0x15) */
649*4882a593Smuzhiyun data[17] = 0x01;
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun helene_write_regs(priv, 0x04, data, 18);
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun dev_dbg(&priv->i2c->dev, "%s(): tune done\n",
654*4882a593Smuzhiyun __func__);
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun priv->frequency = frequency;
657*4882a593Smuzhiyun return 0;
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun
helene_set_params_t(struct dvb_frontend * fe)660*4882a593Smuzhiyun static int helene_set_params_t(struct dvb_frontend *fe)
661*4882a593Smuzhiyun {
662*4882a593Smuzhiyun u8 data[MAX_WRITE_REGSIZE];
663*4882a593Smuzhiyun u32 frequency;
664*4882a593Smuzhiyun enum helene_tv_system_t tv_system;
665*4882a593Smuzhiyun struct dtv_frontend_properties *p = &fe->dtv_property_cache;
666*4882a593Smuzhiyun struct helene_priv *priv = fe->tuner_priv;
667*4882a593Smuzhiyun int frequencykHz = p->frequency / 1000;
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun dev_dbg(&priv->i2c->dev, "%s(): tune frequency %dkHz\n",
670*4882a593Smuzhiyun __func__, frequencykHz);
671*4882a593Smuzhiyun tv_system = helene_get_tv_system(fe);
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun if (tv_system == SONY_HELENE_TV_SYSTEM_UNKNOWN) {
674*4882a593Smuzhiyun dev_dbg(&priv->i2c->dev, "%s(): unknown DTV system\n",
675*4882a593Smuzhiyun __func__);
676*4882a593Smuzhiyun return -EINVAL;
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun if (priv->set_tuner)
679*4882a593Smuzhiyun priv->set_tuner(priv->set_tuner_data, 1);
680*4882a593Smuzhiyun frequency = roundup(p->frequency / 1000, 25);
681*4882a593Smuzhiyun
682*4882a593Smuzhiyun /* mode select */
683*4882a593Smuzhiyun helene_write_reg(priv, 0x01, 0x00);
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun /* Disable IF signal output */
686*4882a593Smuzhiyun helene_write_reg(priv, 0x74, 0x02);
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun if (priv->state == STATE_SLEEP)
689*4882a593Smuzhiyun helene_leave_power_save(priv);
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun /* Initial setting for internal analog block (0x91, 0x92) */
692*4882a593Smuzhiyun if ((tv_system == SONY_HELENE_DTV_DVBC_6) ||
693*4882a593Smuzhiyun (tv_system == SONY_HELENE_DTV_DVBC_8)) {
694*4882a593Smuzhiyun data[0] = 0x16;
695*4882a593Smuzhiyun data[1] = 0x26;
696*4882a593Smuzhiyun } else {
697*4882a593Smuzhiyun data[0] = 0x10;
698*4882a593Smuzhiyun data[1] = 0x20;
699*4882a593Smuzhiyun }
700*4882a593Smuzhiyun helene_write_regs(priv, 0x91, data, 2);
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun /* Setting for analog block */
703*4882a593Smuzhiyun if (TERR_INTERNAL_LOOPFILTER_AVAILABLE(tv_system))
704*4882a593Smuzhiyun data[0] = 0x90;
705*4882a593Smuzhiyun else
706*4882a593Smuzhiyun data[0] = 0x00;
707*4882a593Smuzhiyun
708*4882a593Smuzhiyun /* Setting for local polarity (0x9D) */
709*4882a593Smuzhiyun data[1] = (uint8_t)(terr_params[tv_system].IS_LOWERLOCAL & 0x01);
710*4882a593Smuzhiyun helene_write_regs(priv, 0x9C, data, 2);
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun /* Enable for analog block */
713*4882a593Smuzhiyun data[0] = 0xEE;
714*4882a593Smuzhiyun data[1] = 0x02;
715*4882a593Smuzhiyun data[2] = 0x1E;
716*4882a593Smuzhiyun data[3] = 0x67; /* Tuning setting for CPU */
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun /* Setting for PLL reference divider for xtal=24MHz */
719*4882a593Smuzhiyun if ((tv_system == SONY_HELENE_DTV_DVBC_6) ||
720*4882a593Smuzhiyun (tv_system == SONY_HELENE_DTV_DVBC_8))
721*4882a593Smuzhiyun data[4] = 0x18;
722*4882a593Smuzhiyun else
723*4882a593Smuzhiyun data[4] = 0x03;
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun /* Tuning setting for analog block */
726*4882a593Smuzhiyun if (TERR_INTERNAL_LOOPFILTER_AVAILABLE(tv_system)) {
727*4882a593Smuzhiyun data[5] = 0x38;
728*4882a593Smuzhiyun data[6] = 0x1E;
729*4882a593Smuzhiyun data[7] = 0x02;
730*4882a593Smuzhiyun data[8] = 0x24;
731*4882a593Smuzhiyun } else if ((tv_system == SONY_HELENE_DTV_DVBC_6) ||
732*4882a593Smuzhiyun (tv_system == SONY_HELENE_DTV_DVBC_8)) {
733*4882a593Smuzhiyun data[5] = 0x1C;
734*4882a593Smuzhiyun data[6] = 0x78;
735*4882a593Smuzhiyun data[7] = 0x08;
736*4882a593Smuzhiyun data[8] = 0x1C;
737*4882a593Smuzhiyun } else {
738*4882a593Smuzhiyun data[5] = 0xB4;
739*4882a593Smuzhiyun data[6] = 0x78;
740*4882a593Smuzhiyun data[7] = 0x08;
741*4882a593Smuzhiyun data[8] = 0x30;
742*4882a593Smuzhiyun }
743*4882a593Smuzhiyun helene_write_regs(priv, 0x5E, data, 9);
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun /* LT_AMP_EN should be 0 */
746*4882a593Smuzhiyun helene_set_reg_bits(priv, 0x67, 0x0, 0x02);
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun /* Setting for IFOUT_LIMIT */
749*4882a593Smuzhiyun data[0] = 0x00; /* 1.5Vpp */
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun /* RF_GAIN setting */
752*4882a593Smuzhiyun if (terr_params[tv_system].RF_GAIN == HELENE_AUTO)
753*4882a593Smuzhiyun data[1] = 0x80; /* RF_GAIN_SEL = 1 */
754*4882a593Smuzhiyun else
755*4882a593Smuzhiyun data[1] = (uint8_t)((terr_params[tv_system].RF_GAIN
756*4882a593Smuzhiyun << 4) & 0x70);
757*4882a593Smuzhiyun
758*4882a593Smuzhiyun /* IF_BPF_GC setting */
759*4882a593Smuzhiyun data[1] |= (uint8_t)(terr_params[tv_system].IF_BPF_GC & 0x0F);
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun /* Setting for internal RFAGC (0x6A, 0x6B, 0x6C) */
762*4882a593Smuzhiyun data[2] = 0x00;
763*4882a593Smuzhiyun if (frequencykHz <= 172000) {
764*4882a593Smuzhiyun data[3] = (uint8_t)(terr_params[tv_system].RFOVLD_DET_LV1_VL
765*4882a593Smuzhiyun & 0x0F);
766*4882a593Smuzhiyun data[4] = (uint8_t)(terr_params[tv_system].IFOVLD_DET_LV_VL
767*4882a593Smuzhiyun & 0x07);
768*4882a593Smuzhiyun } else if (frequencykHz <= 464000) {
769*4882a593Smuzhiyun data[3] = (uint8_t)(terr_params[tv_system].RFOVLD_DET_LV1_VH
770*4882a593Smuzhiyun & 0x0F);
771*4882a593Smuzhiyun data[4] = (uint8_t)(terr_params[tv_system].IFOVLD_DET_LV_VH
772*4882a593Smuzhiyun & 0x07);
773*4882a593Smuzhiyun } else {
774*4882a593Smuzhiyun data[3] = (uint8_t)(terr_params[tv_system].RFOVLD_DET_LV1_U
775*4882a593Smuzhiyun & 0x0F);
776*4882a593Smuzhiyun data[4] = (uint8_t)(terr_params[tv_system].IFOVLD_DET_LV_U
777*4882a593Smuzhiyun & 0x07);
778*4882a593Smuzhiyun }
779*4882a593Smuzhiyun data[4] |= 0x20;
780*4882a593Smuzhiyun
781*4882a593Smuzhiyun /* Setting for IF frequency and bandwidth */
782*4882a593Smuzhiyun
783*4882a593Smuzhiyun /* IF filter center frequency offset (IF_BPF_F0) (0x6D) */
784*4882a593Smuzhiyun data[5] = (uint8_t)((terr_params[tv_system].IF_BPF_F0 << 4) & 0x30);
785*4882a593Smuzhiyun
786*4882a593Smuzhiyun /* IF filter band width (BW) (0x6D) */
787*4882a593Smuzhiyun data[5] |= (uint8_t)(terr_params[tv_system].BW & 0x03);
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun /* IF frequency offset value (FIF_OFFSET) (0x6E) */
790*4882a593Smuzhiyun data[6] = (uint8_t)(terr_params[tv_system].FIF_OFFSET & 0x1F);
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun /* IF band width offset value (BW_OFFSET) (0x6F) */
793*4882a593Smuzhiyun data[7] = (uint8_t)(terr_params[tv_system].BW_OFFSET & 0x1F);
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun /* RF tuning frequency setting (0x70, 0x71, 0x72) */
796*4882a593Smuzhiyun data[8] = (uint8_t)(frequencykHz & 0xFF); /* FRF_L */
797*4882a593Smuzhiyun data[9] = (uint8_t)((frequencykHz >> 8) & 0xFF); /* FRF_M */
798*4882a593Smuzhiyun data[10] = (uint8_t)((frequencykHz >> 16)
799*4882a593Smuzhiyun & 0x0F); /* FRF_H (bit[3:0]) */
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun /* Tuning command */
802*4882a593Smuzhiyun data[11] = 0xFF;
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun /* Enable IF output, AGC and IFOUT pin selection (0x74) */
805*4882a593Smuzhiyun data[12] = 0x01;
806*4882a593Smuzhiyun
807*4882a593Smuzhiyun if ((tv_system == SONY_HELENE_DTV_DVBC_6) ||
808*4882a593Smuzhiyun (tv_system == SONY_HELENE_DTV_DVBC_8)) {
809*4882a593Smuzhiyun data[13] = 0xD9;
810*4882a593Smuzhiyun data[14] = 0x0F;
811*4882a593Smuzhiyun data[15] = 0x24;
812*4882a593Smuzhiyun data[16] = 0x87;
813*4882a593Smuzhiyun } else {
814*4882a593Smuzhiyun data[13] = 0x99;
815*4882a593Smuzhiyun data[14] = 0x00;
816*4882a593Smuzhiyun data[15] = 0x24;
817*4882a593Smuzhiyun data[16] = 0x87;
818*4882a593Smuzhiyun }
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun helene_write_regs(priv, 0x68, data, 17);
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun dev_dbg(&priv->i2c->dev, "%s(): tune done\n",
823*4882a593Smuzhiyun __func__);
824*4882a593Smuzhiyun
825*4882a593Smuzhiyun priv->frequency = frequency;
826*4882a593Smuzhiyun return 0;
827*4882a593Smuzhiyun }
828*4882a593Smuzhiyun
helene_set_params(struct dvb_frontend * fe)829*4882a593Smuzhiyun static int helene_set_params(struct dvb_frontend *fe)
830*4882a593Smuzhiyun {
831*4882a593Smuzhiyun struct dtv_frontend_properties *p = &fe->dtv_property_cache;
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun if (p->delivery_system == SYS_DVBT ||
834*4882a593Smuzhiyun p->delivery_system == SYS_DVBT2 ||
835*4882a593Smuzhiyun p->delivery_system == SYS_ISDBT ||
836*4882a593Smuzhiyun p->delivery_system == SYS_DVBC_ANNEX_A)
837*4882a593Smuzhiyun return helene_set_params_t(fe);
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun return helene_set_params_s(fe);
840*4882a593Smuzhiyun }
841*4882a593Smuzhiyun
helene_get_frequency(struct dvb_frontend * fe,u32 * frequency)842*4882a593Smuzhiyun static int helene_get_frequency(struct dvb_frontend *fe, u32 *frequency)
843*4882a593Smuzhiyun {
844*4882a593Smuzhiyun struct helene_priv *priv = fe->tuner_priv;
845*4882a593Smuzhiyun
846*4882a593Smuzhiyun *frequency = priv->frequency * 1000;
847*4882a593Smuzhiyun return 0;
848*4882a593Smuzhiyun }
849*4882a593Smuzhiyun
850*4882a593Smuzhiyun static const struct dvb_tuner_ops helene_tuner_ops_t = {
851*4882a593Smuzhiyun .info = {
852*4882a593Smuzhiyun .name = "Sony HELENE Ter tuner",
853*4882a593Smuzhiyun .frequency_min_hz = 1 * MHz,
854*4882a593Smuzhiyun .frequency_max_hz = 1200 * MHz,
855*4882a593Smuzhiyun .frequency_step_hz = 25 * kHz,
856*4882a593Smuzhiyun },
857*4882a593Smuzhiyun .init = helene_init,
858*4882a593Smuzhiyun .release = helene_release,
859*4882a593Smuzhiyun .sleep = helene_sleep,
860*4882a593Smuzhiyun .set_params = helene_set_params_t,
861*4882a593Smuzhiyun .get_frequency = helene_get_frequency,
862*4882a593Smuzhiyun };
863*4882a593Smuzhiyun
864*4882a593Smuzhiyun static const struct dvb_tuner_ops helene_tuner_ops_s = {
865*4882a593Smuzhiyun .info = {
866*4882a593Smuzhiyun .name = "Sony HELENE Sat tuner",
867*4882a593Smuzhiyun .frequency_min_hz = 500 * MHz,
868*4882a593Smuzhiyun .frequency_max_hz = 2500 * MHz,
869*4882a593Smuzhiyun .frequency_step_hz = 1 * MHz,
870*4882a593Smuzhiyun },
871*4882a593Smuzhiyun .init = helene_init,
872*4882a593Smuzhiyun .release = helene_release,
873*4882a593Smuzhiyun .sleep = helene_sleep,
874*4882a593Smuzhiyun .set_params = helene_set_params_s,
875*4882a593Smuzhiyun .get_frequency = helene_get_frequency,
876*4882a593Smuzhiyun };
877*4882a593Smuzhiyun
878*4882a593Smuzhiyun static const struct dvb_tuner_ops helene_tuner_ops = {
879*4882a593Smuzhiyun .info = {
880*4882a593Smuzhiyun .name = "Sony HELENE Sat/Ter tuner",
881*4882a593Smuzhiyun .frequency_min_hz = 1 * MHz,
882*4882a593Smuzhiyun .frequency_max_hz = 2500 * MHz,
883*4882a593Smuzhiyun .frequency_step_hz = 25 * kHz,
884*4882a593Smuzhiyun },
885*4882a593Smuzhiyun .init = helene_init,
886*4882a593Smuzhiyun .release = helene_release,
887*4882a593Smuzhiyun .sleep = helene_sleep,
888*4882a593Smuzhiyun .set_params = helene_set_params,
889*4882a593Smuzhiyun .get_frequency = helene_get_frequency,
890*4882a593Smuzhiyun };
891*4882a593Smuzhiyun
892*4882a593Smuzhiyun /* power-on tuner
893*4882a593Smuzhiyun * call once after reset
894*4882a593Smuzhiyun */
helene_x_pon(struct helene_priv * priv)895*4882a593Smuzhiyun static int helene_x_pon(struct helene_priv *priv)
896*4882a593Smuzhiyun {
897*4882a593Smuzhiyun /* RFIN matching in power save (terrestrial) = ACTIVE */
898*4882a593Smuzhiyun /* RFIN matching in power save (satellite) = ACTIVE */
899*4882a593Smuzhiyun u8 dataT[] = { 0x06, 0x00, 0x02, 0x00 };
900*4882a593Smuzhiyun /* SAT_RF_ACTIVE = true, lnaOff = false, terrRfActive = true */
901*4882a593Smuzhiyun u8 dataS[] = { 0x05, 0x06 };
902*4882a593Smuzhiyun u8 cdata[] = {0x7A, 0x01};
903*4882a593Smuzhiyun u8 data[20];
904*4882a593Smuzhiyun u8 rdata[2];
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun /* mode select */
907*4882a593Smuzhiyun helene_write_reg(priv, 0x01, 0x00);
908*4882a593Smuzhiyun
909*4882a593Smuzhiyun helene_write_reg(priv, 0x67, dataT[3]);
910*4882a593Smuzhiyun helene_write_reg(priv, 0x43, dataS[1]);
911*4882a593Smuzhiyun helene_write_regs(priv, 0x5E, dataT, 3);
912*4882a593Smuzhiyun helene_write_reg(priv, 0x0C, dataS[0]);
913*4882a593Smuzhiyun
914*4882a593Smuzhiyun /* Initial setting for internal logic block */
915*4882a593Smuzhiyun helene_write_regs(priv, 0x99, cdata, sizeof(cdata));
916*4882a593Smuzhiyun
917*4882a593Smuzhiyun /* 0x81 - 0x94 */
918*4882a593Smuzhiyun if (priv->xtal == SONY_HELENE_XTAL_16000)
919*4882a593Smuzhiyun data[0] = 0x10; /* xtal 16 MHz */
920*4882a593Smuzhiyun else
921*4882a593Smuzhiyun data[0] = 0x18; /* xtal 24 MHz */
922*4882a593Smuzhiyun data[1] = (uint8_t)(0x80 | (0x04 & 0x1F)); /* 4 x 25 = 100uA */
923*4882a593Smuzhiyun data[2] = (uint8_t)(0x80 | (0x26 & 0x7F)); /* 38 x 0.25 = 9.5pF */
924*4882a593Smuzhiyun data[3] = 0x80; /* REFOUT signal output 500mVpp */
925*4882a593Smuzhiyun data[4] = 0x00; /* GPIO settings */
926*4882a593Smuzhiyun data[5] = 0x00; /* GPIO settings */
927*4882a593Smuzhiyun data[6] = 0xC4; /* Clock enable for internal logic block */
928*4882a593Smuzhiyun data[7] = 0x40; /* Start CPU boot-up */
929*4882a593Smuzhiyun data[8] = 0x10; /* For burst-write */
930*4882a593Smuzhiyun
931*4882a593Smuzhiyun /* Setting for internal RFAGC */
932*4882a593Smuzhiyun data[9] = 0x00;
933*4882a593Smuzhiyun data[10] = 0x45;
934*4882a593Smuzhiyun data[11] = 0x75;
935*4882a593Smuzhiyun
936*4882a593Smuzhiyun data[12] = 0x07; /* Setting for analog block */
937*4882a593Smuzhiyun
938*4882a593Smuzhiyun /* Initial setting for internal analog block */
939*4882a593Smuzhiyun data[13] = 0x1C;
940*4882a593Smuzhiyun data[14] = 0x3F;
941*4882a593Smuzhiyun data[15] = 0x02;
942*4882a593Smuzhiyun data[16] = 0x10;
943*4882a593Smuzhiyun data[17] = 0x20;
944*4882a593Smuzhiyun data[18] = 0x0A;
945*4882a593Smuzhiyun data[19] = 0x00;
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun helene_write_regs(priv, 0x81, data, sizeof(data));
948*4882a593Smuzhiyun
949*4882a593Smuzhiyun /* Setting for internal RFAGC */
950*4882a593Smuzhiyun helene_write_reg(priv, 0x9B, 0x00);
951*4882a593Smuzhiyun
952*4882a593Smuzhiyun msleep(20);
953*4882a593Smuzhiyun
954*4882a593Smuzhiyun /* Check CPU_STT/CPU_ERR */
955*4882a593Smuzhiyun helene_read_regs(priv, 0x1A, rdata, sizeof(rdata));
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun if (rdata[0] != 0x00) {
958*4882a593Smuzhiyun dev_err(&priv->i2c->dev,
959*4882a593Smuzhiyun "HELENE tuner CPU error 0x%x\n", rdata[0]);
960*4882a593Smuzhiyun return -EIO;
961*4882a593Smuzhiyun }
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun /* VCO current setting */
964*4882a593Smuzhiyun cdata[0] = 0x90;
965*4882a593Smuzhiyun cdata[1] = 0x06;
966*4882a593Smuzhiyun helene_write_regs(priv, 0x17, cdata, sizeof(cdata));
967*4882a593Smuzhiyun msleep(20);
968*4882a593Smuzhiyun helene_read_reg(priv, 0x19, data);
969*4882a593Smuzhiyun helene_write_reg(priv, 0x95, (uint8_t)((data[0] >> 4) & 0x0F));
970*4882a593Smuzhiyun
971*4882a593Smuzhiyun /* Disable IF signal output */
972*4882a593Smuzhiyun helene_write_reg(priv, 0x74, 0x02);
973*4882a593Smuzhiyun
974*4882a593Smuzhiyun /* Standby setting for CPU */
975*4882a593Smuzhiyun helene_write_reg(priv, 0x88, 0x00);
976*4882a593Smuzhiyun
977*4882a593Smuzhiyun /* Standby setting for internal logic block */
978*4882a593Smuzhiyun helene_write_reg(priv, 0x87, 0xC0);
979*4882a593Smuzhiyun
980*4882a593Smuzhiyun /* Load capacitance control setting for crystal oscillator */
981*4882a593Smuzhiyun helene_write_reg(priv, 0x80, 0x01);
982*4882a593Smuzhiyun
983*4882a593Smuzhiyun /* Satellite initial setting */
984*4882a593Smuzhiyun cdata[0] = 0x07;
985*4882a593Smuzhiyun cdata[1] = 0x00;
986*4882a593Smuzhiyun helene_write_regs(priv, 0x41, cdata, sizeof(cdata));
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun dev_info(&priv->i2c->dev,
989*4882a593Smuzhiyun "HELENE tuner x_pon done\n");
990*4882a593Smuzhiyun
991*4882a593Smuzhiyun return 0;
992*4882a593Smuzhiyun }
993*4882a593Smuzhiyun
helene_attach_s(struct dvb_frontend * fe,const struct helene_config * config,struct i2c_adapter * i2c)994*4882a593Smuzhiyun struct dvb_frontend *helene_attach_s(struct dvb_frontend *fe,
995*4882a593Smuzhiyun const struct helene_config *config,
996*4882a593Smuzhiyun struct i2c_adapter *i2c)
997*4882a593Smuzhiyun {
998*4882a593Smuzhiyun struct helene_priv *priv = NULL;
999*4882a593Smuzhiyun
1000*4882a593Smuzhiyun priv = kzalloc(sizeof(struct helene_priv), GFP_KERNEL);
1001*4882a593Smuzhiyun if (priv == NULL)
1002*4882a593Smuzhiyun return NULL;
1003*4882a593Smuzhiyun priv->i2c_address = (config->i2c_address >> 1);
1004*4882a593Smuzhiyun priv->i2c = i2c;
1005*4882a593Smuzhiyun priv->set_tuner_data = config->set_tuner_priv;
1006*4882a593Smuzhiyun priv->set_tuner = config->set_tuner_callback;
1007*4882a593Smuzhiyun priv->xtal = config->xtal;
1008*4882a593Smuzhiyun
1009*4882a593Smuzhiyun if (fe->ops.i2c_gate_ctrl)
1010*4882a593Smuzhiyun fe->ops.i2c_gate_ctrl(fe, 1);
1011*4882a593Smuzhiyun
1012*4882a593Smuzhiyun if (helene_x_pon(priv) != 0) {
1013*4882a593Smuzhiyun kfree(priv);
1014*4882a593Smuzhiyun return NULL;
1015*4882a593Smuzhiyun }
1016*4882a593Smuzhiyun
1017*4882a593Smuzhiyun if (fe->ops.i2c_gate_ctrl)
1018*4882a593Smuzhiyun fe->ops.i2c_gate_ctrl(fe, 0);
1019*4882a593Smuzhiyun
1020*4882a593Smuzhiyun memcpy(&fe->ops.tuner_ops, &helene_tuner_ops_s,
1021*4882a593Smuzhiyun sizeof(struct dvb_tuner_ops));
1022*4882a593Smuzhiyun fe->tuner_priv = priv;
1023*4882a593Smuzhiyun dev_info(&priv->i2c->dev,
1024*4882a593Smuzhiyun "Sony HELENE Sat attached on addr=%x at I2C adapter %p\n",
1025*4882a593Smuzhiyun priv->i2c_address, priv->i2c);
1026*4882a593Smuzhiyun return fe;
1027*4882a593Smuzhiyun }
1028*4882a593Smuzhiyun EXPORT_SYMBOL(helene_attach_s);
1029*4882a593Smuzhiyun
helene_attach(struct dvb_frontend * fe,const struct helene_config * config,struct i2c_adapter * i2c)1030*4882a593Smuzhiyun struct dvb_frontend *helene_attach(struct dvb_frontend *fe,
1031*4882a593Smuzhiyun const struct helene_config *config,
1032*4882a593Smuzhiyun struct i2c_adapter *i2c)
1033*4882a593Smuzhiyun {
1034*4882a593Smuzhiyun struct helene_priv *priv = NULL;
1035*4882a593Smuzhiyun
1036*4882a593Smuzhiyun priv = kzalloc(sizeof(struct helene_priv), GFP_KERNEL);
1037*4882a593Smuzhiyun if (priv == NULL)
1038*4882a593Smuzhiyun return NULL;
1039*4882a593Smuzhiyun priv->i2c_address = (config->i2c_address >> 1);
1040*4882a593Smuzhiyun priv->i2c = i2c;
1041*4882a593Smuzhiyun priv->set_tuner_data = config->set_tuner_priv;
1042*4882a593Smuzhiyun priv->set_tuner = config->set_tuner_callback;
1043*4882a593Smuzhiyun priv->xtal = config->xtal;
1044*4882a593Smuzhiyun
1045*4882a593Smuzhiyun if (fe->ops.i2c_gate_ctrl)
1046*4882a593Smuzhiyun fe->ops.i2c_gate_ctrl(fe, 1);
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun if (helene_x_pon(priv) != 0) {
1049*4882a593Smuzhiyun kfree(priv);
1050*4882a593Smuzhiyun return NULL;
1051*4882a593Smuzhiyun }
1052*4882a593Smuzhiyun
1053*4882a593Smuzhiyun if (fe->ops.i2c_gate_ctrl)
1054*4882a593Smuzhiyun fe->ops.i2c_gate_ctrl(fe, 0);
1055*4882a593Smuzhiyun
1056*4882a593Smuzhiyun memcpy(&fe->ops.tuner_ops, &helene_tuner_ops_t,
1057*4882a593Smuzhiyun sizeof(struct dvb_tuner_ops));
1058*4882a593Smuzhiyun fe->tuner_priv = priv;
1059*4882a593Smuzhiyun dev_info(&priv->i2c->dev,
1060*4882a593Smuzhiyun "Sony HELENE Ter attached on addr=%x at I2C adapter %p\n",
1061*4882a593Smuzhiyun priv->i2c_address, priv->i2c);
1062*4882a593Smuzhiyun return fe;
1063*4882a593Smuzhiyun }
1064*4882a593Smuzhiyun EXPORT_SYMBOL(helene_attach);
1065*4882a593Smuzhiyun
helene_probe(struct i2c_client * client,const struct i2c_device_id * id)1066*4882a593Smuzhiyun static int helene_probe(struct i2c_client *client,
1067*4882a593Smuzhiyun const struct i2c_device_id *id)
1068*4882a593Smuzhiyun {
1069*4882a593Smuzhiyun struct helene_config *config = client->dev.platform_data;
1070*4882a593Smuzhiyun struct dvb_frontend *fe = config->fe;
1071*4882a593Smuzhiyun struct device *dev = &client->dev;
1072*4882a593Smuzhiyun struct helene_priv *priv;
1073*4882a593Smuzhiyun
1074*4882a593Smuzhiyun priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1075*4882a593Smuzhiyun if (!priv)
1076*4882a593Smuzhiyun return -ENOMEM;
1077*4882a593Smuzhiyun
1078*4882a593Smuzhiyun priv->i2c_address = client->addr;
1079*4882a593Smuzhiyun priv->i2c = client->adapter;
1080*4882a593Smuzhiyun priv->set_tuner_data = config->set_tuner_priv;
1081*4882a593Smuzhiyun priv->set_tuner = config->set_tuner_callback;
1082*4882a593Smuzhiyun priv->xtal = config->xtal;
1083*4882a593Smuzhiyun
1084*4882a593Smuzhiyun if (fe->ops.i2c_gate_ctrl)
1085*4882a593Smuzhiyun fe->ops.i2c_gate_ctrl(fe, 1);
1086*4882a593Smuzhiyun
1087*4882a593Smuzhiyun if (helene_x_pon(priv) != 0)
1088*4882a593Smuzhiyun return -EINVAL;
1089*4882a593Smuzhiyun
1090*4882a593Smuzhiyun if (fe->ops.i2c_gate_ctrl)
1091*4882a593Smuzhiyun fe->ops.i2c_gate_ctrl(fe, 0);
1092*4882a593Smuzhiyun
1093*4882a593Smuzhiyun memcpy(&fe->ops.tuner_ops, &helene_tuner_ops,
1094*4882a593Smuzhiyun sizeof(struct dvb_tuner_ops));
1095*4882a593Smuzhiyun fe->tuner_priv = priv;
1096*4882a593Smuzhiyun i2c_set_clientdata(client, priv);
1097*4882a593Smuzhiyun
1098*4882a593Smuzhiyun dev_info(dev, "Sony HELENE attached on addr=%x at I2C adapter %p\n",
1099*4882a593Smuzhiyun priv->i2c_address, priv->i2c);
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun return 0;
1102*4882a593Smuzhiyun }
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun static const struct i2c_device_id helene_id[] = {
1105*4882a593Smuzhiyun { "helene", },
1106*4882a593Smuzhiyun {}
1107*4882a593Smuzhiyun };
1108*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, helene_id);
1109*4882a593Smuzhiyun
1110*4882a593Smuzhiyun static struct i2c_driver helene_driver = {
1111*4882a593Smuzhiyun .driver = {
1112*4882a593Smuzhiyun .name = "helene",
1113*4882a593Smuzhiyun },
1114*4882a593Smuzhiyun .probe = helene_probe,
1115*4882a593Smuzhiyun .id_table = helene_id,
1116*4882a593Smuzhiyun };
1117*4882a593Smuzhiyun module_i2c_driver(helene_driver);
1118*4882a593Smuzhiyun
1119*4882a593Smuzhiyun MODULE_DESCRIPTION("Sony HELENE Sat/Ter tuner driver");
1120*4882a593Smuzhiyun MODULE_AUTHOR("Abylay Ospan <aospan@netup.ru>");
1121*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1122