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