1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Toshiba TC90522 Demodulator |
4 | * |
5 | * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com> |
6 | */ |
7 | |
8 | /* |
9 | * NOTICE: |
10 | * This driver is incomplete and lacks init/config of the chips, |
11 | * as the necessary info is not disclosed. |
12 | * It assumes that users of this driver (such as a PCI bridge of |
13 | * DTV receiver cards) properly init and configure the chip |
14 | * via I2C *before* calling this driver's init() function. |
15 | * |
16 | * Currently, PT3 driver is the only one that uses this driver, |
17 | * and contains init/config code in its firmware. |
18 | * Thus some part of the code might be dependent on PT3 specific config. |
19 | */ |
20 | |
21 | #include <linux/kernel.h> |
22 | #include <linux/math64.h> |
23 | #include <linux/dvb/frontend.h> |
24 | #include <linux/int_log.h> |
25 | #include "tc90522.h" |
26 | |
27 | #define TC90522_I2C_THRU_REG 0xfe |
28 | |
29 | #define TC90522_MODULE_IDX(addr) (((u8)(addr) & 0x02U) >> 1) |
30 | |
31 | struct tc90522_state { |
32 | struct tc90522_config cfg; |
33 | struct dvb_frontend fe; |
34 | struct i2c_client *i2c_client; |
35 | struct i2c_adapter tuner_i2c; |
36 | |
37 | bool lna; |
38 | }; |
39 | |
40 | struct reg_val { |
41 | u8 reg; |
42 | u8 val; |
43 | }; |
44 | |
45 | static int |
46 | reg_write(struct tc90522_state *state, const struct reg_val *regs, int num) |
47 | { |
48 | int i, ret; |
49 | struct i2c_msg msg; |
50 | |
51 | ret = 0; |
52 | msg.addr = state->i2c_client->addr; |
53 | msg.flags = 0; |
54 | msg.len = 2; |
55 | for (i = 0; i < num; i++) { |
56 | msg.buf = (u8 *)®s[i]; |
57 | ret = i2c_transfer(adap: state->i2c_client->adapter, msgs: &msg, num: 1); |
58 | if (ret == 0) |
59 | ret = -EIO; |
60 | if (ret < 0) |
61 | return ret; |
62 | } |
63 | return 0; |
64 | } |
65 | |
66 | static int reg_read(struct tc90522_state *state, u8 reg, u8 *val, u8 len) |
67 | { |
68 | struct i2c_msg msgs[2] = { |
69 | { |
70 | .addr = state->i2c_client->addr, |
71 | .flags = 0, |
72 | .buf = ®, |
73 | .len = 1, |
74 | }, |
75 | { |
76 | .addr = state->i2c_client->addr, |
77 | .flags = I2C_M_RD, |
78 | .buf = val, |
79 | .len = len, |
80 | }, |
81 | }; |
82 | int ret; |
83 | |
84 | ret = i2c_transfer(adap: state->i2c_client->adapter, msgs, ARRAY_SIZE(msgs)); |
85 | if (ret == ARRAY_SIZE(msgs)) |
86 | ret = 0; |
87 | else if (ret >= 0) |
88 | ret = -EIO; |
89 | return ret; |
90 | } |
91 | |
92 | static struct tc90522_state *cfg_to_state(struct tc90522_config *c) |
93 | { |
94 | return container_of(c, struct tc90522_state, cfg); |
95 | } |
96 | |
97 | |
98 | static int tc90522s_set_tsid(struct dvb_frontend *fe) |
99 | { |
100 | struct reg_val set_tsid[] = { |
101 | { 0x8f, 00 }, |
102 | { 0x90, 00 } |
103 | }; |
104 | |
105 | set_tsid[0].val = (fe->dtv_property_cache.stream_id & 0xff00) >> 8; |
106 | set_tsid[1].val = fe->dtv_property_cache.stream_id & 0xff; |
107 | return reg_write(state: fe->demodulator_priv, regs: set_tsid, ARRAY_SIZE(set_tsid)); |
108 | } |
109 | |
110 | static int tc90522t_set_layers(struct dvb_frontend *fe) |
111 | { |
112 | struct reg_val rv; |
113 | u8 laysel; |
114 | |
115 | laysel = ~fe->dtv_property_cache.isdbt_layer_enabled & 0x07; |
116 | laysel = (laysel & 0x01) << 2 | (laysel & 0x02) | (laysel & 0x04) >> 2; |
117 | rv.reg = 0x71; |
118 | rv.val = laysel; |
119 | return reg_write(state: fe->demodulator_priv, regs: &rv, num: 1); |
120 | } |
121 | |
122 | /* frontend ops */ |
123 | |
124 | static int tc90522s_read_status(struct dvb_frontend *fe, enum fe_status *status) |
125 | { |
126 | struct tc90522_state *state; |
127 | int ret; |
128 | u8 reg; |
129 | |
130 | state = fe->demodulator_priv; |
131 | ret = reg_read(state, reg: 0xc3, val: ®, len: 1); |
132 | if (ret < 0) |
133 | return ret; |
134 | |
135 | *status = 0; |
136 | if (reg & 0x80) /* input level under min ? */ |
137 | return 0; |
138 | *status |= FE_HAS_SIGNAL; |
139 | |
140 | if (reg & 0x60) /* carrier? */ |
141 | return 0; |
142 | *status |= FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC; |
143 | |
144 | if (reg & 0x10) |
145 | return 0; |
146 | if (reg_read(state, reg: 0xc5, val: ®, len: 1) < 0 || !(reg & 0x03)) |
147 | return 0; |
148 | *status |= FE_HAS_LOCK; |
149 | return 0; |
150 | } |
151 | |
152 | static int tc90522t_read_status(struct dvb_frontend *fe, enum fe_status *status) |
153 | { |
154 | struct tc90522_state *state; |
155 | int ret; |
156 | u8 reg; |
157 | |
158 | state = fe->demodulator_priv; |
159 | ret = reg_read(state, reg: 0x96, val: ®, len: 1); |
160 | if (ret < 0) |
161 | return ret; |
162 | |
163 | *status = 0; |
164 | if (reg & 0xe0) { |
165 | *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
166 | | FE_HAS_SYNC | FE_HAS_LOCK; |
167 | return 0; |
168 | } |
169 | |
170 | ret = reg_read(state, reg: 0x80, val: ®, len: 1); |
171 | if (ret < 0) |
172 | return ret; |
173 | |
174 | if (reg & 0xf0) |
175 | return 0; |
176 | *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; |
177 | |
178 | if (reg & 0x0c) |
179 | return 0; |
180 | *status |= FE_HAS_SYNC | FE_HAS_VITERBI; |
181 | |
182 | if (reg & 0x02) |
183 | return 0; |
184 | *status |= FE_HAS_LOCK; |
185 | return 0; |
186 | } |
187 | |
188 | static const enum fe_code_rate fec_conv_sat[] = { |
189 | FEC_NONE, /* unused */ |
190 | FEC_1_2, /* for BPSK */ |
191 | FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, /* for QPSK */ |
192 | FEC_2_3, /* for 8PSK. (trellis code) */ |
193 | }; |
194 | |
195 | static int tc90522s_get_frontend(struct dvb_frontend *fe, |
196 | struct dtv_frontend_properties *c) |
197 | { |
198 | struct tc90522_state *state; |
199 | struct dtv_fe_stats *stats; |
200 | int ret, i; |
201 | int layers; |
202 | u8 val[10]; |
203 | u32 cndat; |
204 | |
205 | state = fe->demodulator_priv; |
206 | c->delivery_system = SYS_ISDBS; |
207 | c->symbol_rate = 28860000; |
208 | |
209 | layers = 0; |
210 | ret = reg_read(state, reg: 0xe6, val, len: 5); |
211 | if (ret == 0) { |
212 | u8 v; |
213 | |
214 | c->stream_id = val[0] << 8 | val[1]; |
215 | |
216 | /* high/single layer */ |
217 | v = (val[2] & 0x70) >> 4; |
218 | c->modulation = (v == 7) ? PSK_8 : QPSK; |
219 | c->fec_inner = fec_conv_sat[v]; |
220 | c->layer[0].fec = c->fec_inner; |
221 | c->layer[0].modulation = c->modulation; |
222 | c->layer[0].segment_count = val[3] & 0x3f; /* slots */ |
223 | |
224 | /* low layer */ |
225 | v = (val[2] & 0x07); |
226 | c->layer[1].fec = fec_conv_sat[v]; |
227 | if (v == 0) /* no low layer */ |
228 | c->layer[1].segment_count = 0; |
229 | else |
230 | c->layer[1].segment_count = val[4] & 0x3f; /* slots */ |
231 | /* |
232 | * actually, BPSK if v==1, but not defined in |
233 | * enum fe_modulation |
234 | */ |
235 | c->layer[1].modulation = QPSK; |
236 | layers = (v > 0) ? 2 : 1; |
237 | } |
238 | |
239 | /* statistics */ |
240 | |
241 | stats = &c->strength; |
242 | stats->len = 0; |
243 | /* let the connected tuner set RSSI property cache */ |
244 | if (fe->ops.tuner_ops.get_rf_strength) { |
245 | u16 dummy; |
246 | |
247 | fe->ops.tuner_ops.get_rf_strength(fe, &dummy); |
248 | } |
249 | |
250 | stats = &c->cnr; |
251 | stats->len = 1; |
252 | stats->stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
253 | cndat = 0; |
254 | ret = reg_read(state, reg: 0xbc, val, len: 2); |
255 | if (ret == 0) |
256 | cndat = val[0] << 8 | val[1]; |
257 | if (cndat >= 3000) { |
258 | u32 p, p4; |
259 | s64 cn; |
260 | |
261 | cndat -= 3000; /* cndat: 4.12 fixed point float */ |
262 | /* |
263 | * cnr[mdB] = -1634.6 * P^5 + 14341 * P^4 - 50259 * P^3 |
264 | * + 88977 * P^2 - 89565 * P + 58857 |
265 | * (P = sqrt(cndat) / 64) |
266 | */ |
267 | /* p := sqrt(cndat) << 8 = P << 14, 2.14 fixed point float */ |
268 | /* cn = cnr << 3 */ |
269 | p = int_sqrt(cndat << 16); |
270 | p4 = cndat * cndat; |
271 | cn = div64_s64(dividend: -16346LL * p4 * p, divisor: 10) >> 35; |
272 | cn += (14341LL * p4) >> 21; |
273 | cn -= (50259LL * cndat * p) >> 23; |
274 | cn += (88977LL * cndat) >> 9; |
275 | cn -= (89565LL * p) >> 11; |
276 | cn += 58857 << 3; |
277 | stats->stat[0].svalue = cn >> 3; |
278 | stats->stat[0].scale = FE_SCALE_DECIBEL; |
279 | } |
280 | |
281 | /* per-layer post viterbi BER (or PER? config dependent?) */ |
282 | stats = &c->post_bit_error; |
283 | memset(stats, 0, sizeof(*stats)); |
284 | stats->len = layers; |
285 | ret = reg_read(state, reg: 0xeb, val, len: 10); |
286 | if (ret < 0) |
287 | for (i = 0; i < layers; i++) |
288 | stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE; |
289 | else { |
290 | for (i = 0; i < layers; i++) { |
291 | stats->stat[i].scale = FE_SCALE_COUNTER; |
292 | stats->stat[i].uvalue = val[i * 5] << 16 |
293 | | val[i * 5 + 1] << 8 | val[i * 5 + 2]; |
294 | } |
295 | } |
296 | stats = &c->post_bit_count; |
297 | memset(stats, 0, sizeof(*stats)); |
298 | stats->len = layers; |
299 | if (ret < 0) |
300 | for (i = 0; i < layers; i++) |
301 | stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE; |
302 | else { |
303 | for (i = 0; i < layers; i++) { |
304 | stats->stat[i].scale = FE_SCALE_COUNTER; |
305 | stats->stat[i].uvalue = |
306 | val[i * 5 + 3] << 8 | val[i * 5 + 4]; |
307 | stats->stat[i].uvalue *= 204 * 8; |
308 | } |
309 | } |
310 | |
311 | return 0; |
312 | } |
313 | |
314 | |
315 | static const enum fe_transmit_mode tm_conv[] = { |
316 | TRANSMISSION_MODE_2K, |
317 | TRANSMISSION_MODE_4K, |
318 | TRANSMISSION_MODE_8K, |
319 | 0 |
320 | }; |
321 | |
322 | static const enum fe_code_rate fec_conv_ter[] = { |
323 | FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, 0, 0, 0 |
324 | }; |
325 | |
326 | static const enum fe_modulation mod_conv[] = { |
327 | DQPSK, QPSK, QAM_16, QAM_64, 0, 0, 0, 0 |
328 | }; |
329 | |
330 | static int tc90522t_get_frontend(struct dvb_frontend *fe, |
331 | struct dtv_frontend_properties *c) |
332 | { |
333 | struct tc90522_state *state; |
334 | struct dtv_fe_stats *stats; |
335 | int ret, i; |
336 | int layers; |
337 | u8 val[15], mode; |
338 | u32 cndat; |
339 | |
340 | state = fe->demodulator_priv; |
341 | c->delivery_system = SYS_ISDBT; |
342 | c->bandwidth_hz = 6000000; |
343 | mode = 1; |
344 | ret = reg_read(state, reg: 0xb0, val, len: 1); |
345 | if (ret == 0) { |
346 | mode = (val[0] & 0xc0) >> 6; |
347 | c->transmission_mode = tm_conv[mode]; |
348 | c->guard_interval = (val[0] & 0x30) >> 4; |
349 | } |
350 | |
351 | ret = reg_read(state, reg: 0xb2, val, len: 6); |
352 | layers = 0; |
353 | if (ret == 0) { |
354 | u8 v; |
355 | |
356 | c->isdbt_partial_reception = val[0] & 0x01; |
357 | c->isdbt_sb_mode = (val[0] & 0xc0) == 0x40; |
358 | |
359 | /* layer A */ |
360 | v = (val[2] & 0x78) >> 3; |
361 | if (v == 0x0f) |
362 | c->layer[0].segment_count = 0; |
363 | else { |
364 | layers++; |
365 | c->layer[0].segment_count = v; |
366 | c->layer[0].fec = fec_conv_ter[(val[1] & 0x1c) >> 2]; |
367 | c->layer[0].modulation = mod_conv[(val[1] & 0xe0) >> 5]; |
368 | v = (val[1] & 0x03) << 1 | (val[2] & 0x80) >> 7; |
369 | c->layer[0].interleaving = v; |
370 | } |
371 | |
372 | /* layer B */ |
373 | v = (val[3] & 0x03) << 2 | (val[4] & 0xc0) >> 6; |
374 | if (v == 0x0f) |
375 | c->layer[1].segment_count = 0; |
376 | else { |
377 | layers++; |
378 | c->layer[1].segment_count = v; |
379 | c->layer[1].fec = fec_conv_ter[(val[3] & 0xe0) >> 5]; |
380 | c->layer[1].modulation = mod_conv[(val[2] & 0x07)]; |
381 | c->layer[1].interleaving = (val[3] & 0x1c) >> 2; |
382 | } |
383 | |
384 | /* layer C */ |
385 | v = (val[5] & 0x1e) >> 1; |
386 | if (v == 0x0f) |
387 | c->layer[2].segment_count = 0; |
388 | else { |
389 | layers++; |
390 | c->layer[2].segment_count = v; |
391 | c->layer[2].fec = fec_conv_ter[(val[4] & 0x07)]; |
392 | c->layer[2].modulation = mod_conv[(val[4] & 0x38) >> 3]; |
393 | c->layer[2].interleaving = (val[5] & 0xe0) >> 5; |
394 | } |
395 | } |
396 | |
397 | /* statistics */ |
398 | |
399 | stats = &c->strength; |
400 | stats->len = 0; |
401 | /* let the connected tuner set RSSI property cache */ |
402 | if (fe->ops.tuner_ops.get_rf_strength) { |
403 | u16 dummy; |
404 | |
405 | fe->ops.tuner_ops.get_rf_strength(fe, &dummy); |
406 | } |
407 | |
408 | stats = &c->cnr; |
409 | stats->len = 1; |
410 | stats->stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
411 | cndat = 0; |
412 | ret = reg_read(state, reg: 0x8b, val, len: 3); |
413 | if (ret == 0) |
414 | cndat = val[0] << 16 | val[1] << 8 | val[2]; |
415 | if (cndat != 0) { |
416 | u32 p, tmp; |
417 | s64 cn; |
418 | |
419 | /* |
420 | * cnr[mdB] = 0.024 P^4 - 1.6 P^3 + 39.8 P^2 + 549.1 P + 3096.5 |
421 | * (P = 10log10(5505024/cndat)) |
422 | */ |
423 | /* cn = cnr << 3 (61.3 fixed point float */ |
424 | /* p = 10log10(5505024/cndat) << 24 (8.24 fixed point float)*/ |
425 | p = intlog10(value: 5505024) - intlog10(value: cndat); |
426 | p *= 10; |
427 | |
428 | cn = 24772; |
429 | cn += div64_s64(dividend: 43827LL * p, divisor: 10) >> 24; |
430 | tmp = p >> 8; |
431 | cn += div64_s64(dividend: 3184LL * tmp * tmp, divisor: 10) >> 32; |
432 | tmp = p >> 13; |
433 | cn -= div64_s64(dividend: 128LL * tmp * tmp * tmp, divisor: 10) >> 33; |
434 | tmp = p >> 18; |
435 | cn += div64_s64(dividend: 192LL * tmp * tmp * tmp * tmp, divisor: 1000) >> 24; |
436 | |
437 | stats->stat[0].svalue = cn >> 3; |
438 | stats->stat[0].scale = FE_SCALE_DECIBEL; |
439 | } |
440 | |
441 | /* per-layer post viterbi BER (or PER? config dependent?) */ |
442 | stats = &c->post_bit_error; |
443 | memset(stats, 0, sizeof(*stats)); |
444 | stats->len = layers; |
445 | ret = reg_read(state, reg: 0x9d, val, len: 15); |
446 | if (ret < 0) |
447 | for (i = 0; i < layers; i++) |
448 | stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE; |
449 | else { |
450 | for (i = 0; i < layers; i++) { |
451 | stats->stat[i].scale = FE_SCALE_COUNTER; |
452 | stats->stat[i].uvalue = val[i * 3] << 16 |
453 | | val[i * 3 + 1] << 8 | val[i * 3 + 2]; |
454 | } |
455 | } |
456 | stats = &c->post_bit_count; |
457 | memset(stats, 0, sizeof(*stats)); |
458 | stats->len = layers; |
459 | if (ret < 0) |
460 | for (i = 0; i < layers; i++) |
461 | stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE; |
462 | else { |
463 | for (i = 0; i < layers; i++) { |
464 | stats->stat[i].scale = FE_SCALE_COUNTER; |
465 | stats->stat[i].uvalue = |
466 | val[9 + i * 2] << 8 | val[9 + i * 2 + 1]; |
467 | stats->stat[i].uvalue *= 204 * 8; |
468 | } |
469 | } |
470 | |
471 | return 0; |
472 | } |
473 | |
474 | static const struct reg_val reset_sat = { 0x03, 0x01 }; |
475 | static const struct reg_val reset_ter = { 0x01, 0x40 }; |
476 | |
477 | static int tc90522_set_frontend(struct dvb_frontend *fe) |
478 | { |
479 | struct tc90522_state *state; |
480 | int ret; |
481 | |
482 | state = fe->demodulator_priv; |
483 | |
484 | if (fe->ops.tuner_ops.set_params) |
485 | ret = fe->ops.tuner_ops.set_params(fe); |
486 | else |
487 | ret = -ENODEV; |
488 | if (ret < 0) |
489 | goto failed; |
490 | |
491 | if (fe->ops.delsys[0] == SYS_ISDBS) { |
492 | ret = tc90522s_set_tsid(fe); |
493 | if (ret < 0) |
494 | goto failed; |
495 | ret = reg_write(state, regs: &reset_sat, num: 1); |
496 | } else { |
497 | ret = tc90522t_set_layers(fe); |
498 | if (ret < 0) |
499 | goto failed; |
500 | ret = reg_write(state, regs: &reset_ter, num: 1); |
501 | } |
502 | if (ret < 0) |
503 | goto failed; |
504 | |
505 | return 0; |
506 | |
507 | failed: |
508 | dev_warn(&state->tuner_i2c.dev, "(%s) failed. [adap%d-fe%d]\n" , |
509 | __func__, fe->dvb->num, fe->id); |
510 | return ret; |
511 | } |
512 | |
513 | static int tc90522_get_tune_settings(struct dvb_frontend *fe, |
514 | struct dvb_frontend_tune_settings *settings) |
515 | { |
516 | if (fe->ops.delsys[0] == SYS_ISDBS) { |
517 | settings->min_delay_ms = 250; |
518 | settings->step_size = 1000; |
519 | settings->max_drift = settings->step_size * 2; |
520 | } else { |
521 | settings->min_delay_ms = 400; |
522 | settings->step_size = 142857; |
523 | settings->max_drift = settings->step_size; |
524 | } |
525 | return 0; |
526 | } |
527 | |
528 | static int tc90522_set_if_agc(struct dvb_frontend *fe, bool on) |
529 | { |
530 | struct reg_val agc_sat[] = { |
531 | { 0x0a, 0x00 }, |
532 | { 0x10, 0x30 }, |
533 | { 0x11, 0x00 }, |
534 | { 0x03, 0x01 }, |
535 | }; |
536 | struct reg_val agc_ter[] = { |
537 | { 0x25, 0x00 }, |
538 | { 0x23, 0x4c }, |
539 | { 0x01, 0x40 }, |
540 | }; |
541 | struct tc90522_state *state; |
542 | struct reg_val *rv; |
543 | int num; |
544 | |
545 | state = fe->demodulator_priv; |
546 | if (fe->ops.delsys[0] == SYS_ISDBS) { |
547 | agc_sat[0].val = on ? 0xff : 0x00; |
548 | agc_sat[1].val |= 0x80; |
549 | agc_sat[1].val |= on ? 0x01 : 0x00; |
550 | agc_sat[2].val |= on ? 0x40 : 0x00; |
551 | rv = agc_sat; |
552 | num = ARRAY_SIZE(agc_sat); |
553 | } else { |
554 | agc_ter[0].val = on ? 0x40 : 0x00; |
555 | agc_ter[1].val |= on ? 0x00 : 0x01; |
556 | rv = agc_ter; |
557 | num = ARRAY_SIZE(agc_ter); |
558 | } |
559 | return reg_write(state, regs: rv, num); |
560 | } |
561 | |
562 | static const struct reg_val sleep_sat = { 0x17, 0x01 }; |
563 | static const struct reg_val sleep_ter = { 0x03, 0x90 }; |
564 | |
565 | static int tc90522_sleep(struct dvb_frontend *fe) |
566 | { |
567 | struct tc90522_state *state; |
568 | int ret; |
569 | |
570 | state = fe->demodulator_priv; |
571 | if (fe->ops.delsys[0] == SYS_ISDBS) |
572 | ret = reg_write(state, regs: &sleep_sat, num: 1); |
573 | else { |
574 | ret = reg_write(state, regs: &sleep_ter, num: 1); |
575 | if (ret == 0 && fe->ops.set_lna && |
576 | fe->dtv_property_cache.lna == LNA_AUTO) { |
577 | fe->dtv_property_cache.lna = 0; |
578 | ret = fe->ops.set_lna(fe); |
579 | fe->dtv_property_cache.lna = LNA_AUTO; |
580 | } |
581 | } |
582 | if (ret < 0) |
583 | dev_warn(&state->tuner_i2c.dev, |
584 | "(%s) failed. [adap%d-fe%d]\n" , |
585 | __func__, fe->dvb->num, fe->id); |
586 | return ret; |
587 | } |
588 | |
589 | static const struct reg_val wakeup_sat = { 0x17, 0x00 }; |
590 | static const struct reg_val wakeup_ter = { 0x03, 0x80 }; |
591 | |
592 | static int tc90522_init(struct dvb_frontend *fe) |
593 | { |
594 | struct tc90522_state *state; |
595 | int ret; |
596 | |
597 | /* |
598 | * Because the init sequence is not public, |
599 | * the parent device/driver should have init'ed the device before. |
600 | * just wake up the device here. |
601 | */ |
602 | |
603 | state = fe->demodulator_priv; |
604 | if (fe->ops.delsys[0] == SYS_ISDBS) |
605 | ret = reg_write(state, regs: &wakeup_sat, num: 1); |
606 | else { |
607 | ret = reg_write(state, regs: &wakeup_ter, num: 1); |
608 | if (ret == 0 && fe->ops.set_lna && |
609 | fe->dtv_property_cache.lna == LNA_AUTO) { |
610 | fe->dtv_property_cache.lna = 1; |
611 | ret = fe->ops.set_lna(fe); |
612 | fe->dtv_property_cache.lna = LNA_AUTO; |
613 | } |
614 | } |
615 | if (ret < 0) { |
616 | dev_warn(&state->tuner_i2c.dev, |
617 | "(%s) failed. [adap%d-fe%d]\n" , |
618 | __func__, fe->dvb->num, fe->id); |
619 | return ret; |
620 | } |
621 | |
622 | /* prefer 'all-layers' to 'none' as a default */ |
623 | if (fe->dtv_property_cache.isdbt_layer_enabled == 0) |
624 | fe->dtv_property_cache.isdbt_layer_enabled = 7; |
625 | return tc90522_set_if_agc(fe, on: true); |
626 | } |
627 | |
628 | |
629 | /* |
630 | * tuner I2C adapter functions |
631 | */ |
632 | |
633 | static int |
634 | tc90522_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) |
635 | { |
636 | struct tc90522_state *state; |
637 | struct i2c_msg *new_msgs; |
638 | int i, j; |
639 | int ret, rd_num; |
640 | u8 wbuf[256]; |
641 | u8 *p, *bufend; |
642 | |
643 | if (num <= 0) |
644 | return -EINVAL; |
645 | |
646 | rd_num = 0; |
647 | for (i = 0; i < num; i++) |
648 | if (msgs[i].flags & I2C_M_RD) |
649 | rd_num++; |
650 | new_msgs = kmalloc_array(n: num + rd_num, size: sizeof(*new_msgs), GFP_KERNEL); |
651 | if (!new_msgs) |
652 | return -ENOMEM; |
653 | |
654 | state = i2c_get_adapdata(adap); |
655 | p = wbuf; |
656 | bufend = wbuf + sizeof(wbuf); |
657 | for (i = 0, j = 0; i < num; i++, j++) { |
658 | new_msgs[j].addr = state->i2c_client->addr; |
659 | new_msgs[j].flags = msgs[i].flags; |
660 | |
661 | if (msgs[i].flags & I2C_M_RD) { |
662 | new_msgs[j].flags &= ~I2C_M_RD; |
663 | if (p + 2 > bufend) |
664 | break; |
665 | p[0] = TC90522_I2C_THRU_REG; |
666 | p[1] = msgs[i].addr << 1 | 0x01; |
667 | new_msgs[j].buf = p; |
668 | new_msgs[j].len = 2; |
669 | p += 2; |
670 | j++; |
671 | new_msgs[j].addr = state->i2c_client->addr; |
672 | new_msgs[j].flags = msgs[i].flags; |
673 | new_msgs[j].buf = msgs[i].buf; |
674 | new_msgs[j].len = msgs[i].len; |
675 | continue; |
676 | } |
677 | |
678 | if (p + msgs[i].len + 2 > bufend) |
679 | break; |
680 | p[0] = TC90522_I2C_THRU_REG; |
681 | p[1] = msgs[i].addr << 1; |
682 | memcpy(p + 2, msgs[i].buf, msgs[i].len); |
683 | new_msgs[j].buf = p; |
684 | new_msgs[j].len = msgs[i].len + 2; |
685 | p += new_msgs[j].len; |
686 | } |
687 | |
688 | if (i < num) { |
689 | ret = -ENOMEM; |
690 | } else if (!state->cfg.split_tuner_read_i2c || rd_num == 0) { |
691 | ret = i2c_transfer(adap: state->i2c_client->adapter, msgs: new_msgs, num: j); |
692 | } else { |
693 | /* |
694 | * Split transactions at each I2C_M_RD message. |
695 | * Some of the parent device require this, |
696 | * such as Friio (see. dvb-usb-gl861). |
697 | */ |
698 | int from, to; |
699 | |
700 | ret = 0; |
701 | from = 0; |
702 | do { |
703 | int r; |
704 | |
705 | to = from + 1; |
706 | while (to < j && !(new_msgs[to].flags & I2C_M_RD)) |
707 | to++; |
708 | r = i2c_transfer(adap: state->i2c_client->adapter, |
709 | msgs: &new_msgs[from], num: to - from); |
710 | ret = (r <= 0) ? r : ret + r; |
711 | from = to; |
712 | } while (from < j && ret > 0); |
713 | } |
714 | |
715 | if (ret >= 0 && ret < j) |
716 | ret = -EIO; |
717 | kfree(objp: new_msgs); |
718 | return (ret == j) ? num : ret; |
719 | } |
720 | |
721 | static u32 tc90522_functionality(struct i2c_adapter *adap) |
722 | { |
723 | return I2C_FUNC_I2C; |
724 | } |
725 | |
726 | static const struct i2c_algorithm tc90522_tuner_i2c_algo = { |
727 | .master_xfer = &tc90522_master_xfer, |
728 | .functionality = &tc90522_functionality, |
729 | }; |
730 | |
731 | |
732 | /* |
733 | * I2C driver functions |
734 | */ |
735 | |
736 | static const struct dvb_frontend_ops tc90522_ops_sat = { |
737 | .delsys = { SYS_ISDBS }, |
738 | .info = { |
739 | .name = "Toshiba TC90522 ISDB-S module" , |
740 | .frequency_min_hz = 950 * MHz, |
741 | .frequency_max_hz = 2150 * MHz, |
742 | .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO | |
743 | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | |
744 | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO, |
745 | }, |
746 | |
747 | .init = tc90522_init, |
748 | .sleep = tc90522_sleep, |
749 | .set_frontend = tc90522_set_frontend, |
750 | .get_tune_settings = tc90522_get_tune_settings, |
751 | |
752 | .get_frontend = tc90522s_get_frontend, |
753 | .read_status = tc90522s_read_status, |
754 | }; |
755 | |
756 | static const struct dvb_frontend_ops tc90522_ops_ter = { |
757 | .delsys = { SYS_ISDBT }, |
758 | .info = { |
759 | .name = "Toshiba TC90522 ISDB-T module" , |
760 | .frequency_min_hz = 470 * MHz, |
761 | .frequency_max_hz = 770 * MHz, |
762 | .frequency_stepsize_hz = 142857, |
763 | .caps = FE_CAN_INVERSION_AUTO | |
764 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | |
765 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | |
766 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | |
767 | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | |
768 | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | |
769 | FE_CAN_HIERARCHY_AUTO, |
770 | }, |
771 | |
772 | .init = tc90522_init, |
773 | .sleep = tc90522_sleep, |
774 | .set_frontend = tc90522_set_frontend, |
775 | .get_tune_settings = tc90522_get_tune_settings, |
776 | |
777 | .get_frontend = tc90522t_get_frontend, |
778 | .read_status = tc90522t_read_status, |
779 | }; |
780 | |
781 | |
782 | static int tc90522_probe(struct i2c_client *client) |
783 | { |
784 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
785 | struct tc90522_state *state; |
786 | struct tc90522_config *cfg; |
787 | const struct dvb_frontend_ops *ops; |
788 | struct i2c_adapter *adap; |
789 | int ret; |
790 | |
791 | state = kzalloc(size: sizeof(*state), GFP_KERNEL); |
792 | if (!state) |
793 | return -ENOMEM; |
794 | state->i2c_client = client; |
795 | |
796 | cfg = client->dev.platform_data; |
797 | memcpy(&state->cfg, cfg, sizeof(state->cfg)); |
798 | cfg->fe = state->cfg.fe = &state->fe; |
799 | ops = id->driver_data == 0 ? &tc90522_ops_sat : &tc90522_ops_ter; |
800 | memcpy(&state->fe.ops, ops, sizeof(*ops)); |
801 | state->fe.demodulator_priv = state; |
802 | |
803 | adap = &state->tuner_i2c; |
804 | adap->owner = THIS_MODULE; |
805 | adap->algo = &tc90522_tuner_i2c_algo; |
806 | adap->dev.parent = &client->dev; |
807 | strscpy(p: adap->name, q: "tc90522_sub" , size: sizeof(adap->name)); |
808 | i2c_set_adapdata(adap, data: state); |
809 | ret = i2c_add_adapter(adap); |
810 | if (ret < 0) |
811 | goto free_state; |
812 | cfg->tuner_i2c = state->cfg.tuner_i2c = adap; |
813 | |
814 | i2c_set_clientdata(client, data: &state->cfg); |
815 | dev_info(&client->dev, "Toshiba TC90522 attached.\n" ); |
816 | return 0; |
817 | free_state: |
818 | kfree(objp: state); |
819 | return ret; |
820 | } |
821 | |
822 | static void tc90522_remove(struct i2c_client *client) |
823 | { |
824 | struct tc90522_state *state; |
825 | |
826 | state = cfg_to_state(c: i2c_get_clientdata(client)); |
827 | i2c_del_adapter(adap: &state->tuner_i2c); |
828 | kfree(objp: state); |
829 | } |
830 | |
831 | |
832 | static const struct i2c_device_id tc90522_id[] = { |
833 | { TC90522_I2C_DEV_SAT, 0 }, |
834 | { TC90522_I2C_DEV_TER, 1 }, |
835 | {} |
836 | }; |
837 | MODULE_DEVICE_TABLE(i2c, tc90522_id); |
838 | |
839 | static struct i2c_driver tc90522_driver = { |
840 | .driver = { |
841 | .name = "tc90522" , |
842 | }, |
843 | .probe = tc90522_probe, |
844 | .remove = tc90522_remove, |
845 | .id_table = tc90522_id, |
846 | }; |
847 | |
848 | module_i2c_driver(tc90522_driver); |
849 | |
850 | MODULE_DESCRIPTION("Toshiba TC90522 frontend" ); |
851 | MODULE_AUTHOR("Akihiro TSUKADA" ); |
852 | MODULE_LICENSE("GPL" ); |
853 | |