1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Montage Technology M88DS3103/M88RS6000 demodulator driver |
4 | * |
5 | * Copyright (C) 2013 Antti Palosaari <crope@iki.fi> |
6 | */ |
7 | |
8 | #include "m88ds3103_priv.h" |
9 | |
10 | static const struct dvb_frontend_ops m88ds3103_ops; |
11 | |
12 | /* write single register with mask */ |
13 | static int m88ds3103_update_bits(struct m88ds3103_dev *dev, |
14 | u8 reg, u8 mask, u8 val) |
15 | { |
16 | int ret; |
17 | u8 tmp; |
18 | |
19 | /* no need for read if whole reg is written */ |
20 | if (mask != 0xff) { |
21 | ret = regmap_bulk_read(map: dev->regmap, reg, val: &tmp, val_count: 1); |
22 | if (ret) |
23 | return ret; |
24 | |
25 | val &= mask; |
26 | tmp &= ~mask; |
27 | val |= tmp; |
28 | } |
29 | |
30 | return regmap_bulk_write(map: dev->regmap, reg, val: &val, val_count: 1); |
31 | } |
32 | |
33 | /* write reg val table using reg addr auto increment */ |
34 | static int m88ds3103_wr_reg_val_tab(struct m88ds3103_dev *dev, |
35 | const struct m88ds3103_reg_val *tab, int tab_len) |
36 | { |
37 | struct i2c_client *client = dev->client; |
38 | int ret, i, j; |
39 | u8 buf[83]; |
40 | |
41 | dev_dbg(&client->dev, "tab_len=%d\n" , tab_len); |
42 | |
43 | if (tab_len > 86) { |
44 | ret = -EINVAL; |
45 | goto err; |
46 | } |
47 | |
48 | for (i = 0, j = 0; i < tab_len; i++, j++) { |
49 | buf[j] = tab[i].val; |
50 | |
51 | if (i == tab_len - 1 || tab[i].reg != tab[i + 1].reg - 1 || |
52 | !((j + 1) % (dev->cfg->i2c_wr_max - 1))) { |
53 | ret = regmap_bulk_write(map: dev->regmap, reg: tab[i].reg - j, val: buf, val_count: j + 1); |
54 | if (ret) |
55 | goto err; |
56 | |
57 | j = -1; |
58 | } |
59 | } |
60 | |
61 | return 0; |
62 | err: |
63 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
64 | return ret; |
65 | } |
66 | |
67 | /* |
68 | * m88ds3103b demod has an internal device related to clocking. First the i2c |
69 | * gate must be opened, for one transaction, then writes will be allowed. |
70 | */ |
71 | static int m88ds3103b_dt_write(struct m88ds3103_dev *dev, int reg, int data) |
72 | { |
73 | struct i2c_client *client = dev->client; |
74 | u8 buf[] = {reg, data}; |
75 | u8 val; |
76 | int ret; |
77 | struct i2c_msg msg = { |
78 | .addr = dev->dt_addr, .flags = 0, .buf = buf, .len = 2 |
79 | }; |
80 | |
81 | m88ds3103_update_bits(dev, reg: 0x11, mask: 0x01, val: 0x00); |
82 | |
83 | val = 0x11; |
84 | ret = regmap_write(map: dev->regmap, reg: 0x03, val); |
85 | if (ret) |
86 | dev_dbg(&client->dev, "fail=%d\n" , ret); |
87 | |
88 | ret = i2c_transfer(adap: dev->dt_client->adapter, msgs: &msg, num: 1); |
89 | if (ret != 1) { |
90 | dev_err(&client->dev, "0x%02x (ret=%i, reg=0x%02x, value=0x%02x)\n" , |
91 | dev->dt_addr, ret, reg, data); |
92 | |
93 | m88ds3103_update_bits(dev, reg: 0x11, mask: 0x01, val: 0x01); |
94 | return -EREMOTEIO; |
95 | } |
96 | m88ds3103_update_bits(dev, reg: 0x11, mask: 0x01, val: 0x01); |
97 | |
98 | dev_dbg(&client->dev, "0x%02x reg 0x%02x, value 0x%02x\n" , |
99 | dev->dt_addr, reg, data); |
100 | |
101 | return 0; |
102 | } |
103 | |
104 | /* |
105 | * m88ds3103b demod has an internal device related to clocking. First the i2c |
106 | * gate must be opened, for two transactions, then reads will be allowed. |
107 | */ |
108 | static int m88ds3103b_dt_read(struct m88ds3103_dev *dev, u8 reg) |
109 | { |
110 | struct i2c_client *client = dev->client; |
111 | int ret; |
112 | u8 val; |
113 | u8 b0[] = { reg }; |
114 | u8 b1[] = { 0 }; |
115 | struct i2c_msg msg[] = { |
116 | { |
117 | .addr = dev->dt_addr, |
118 | .flags = 0, |
119 | .buf = b0, |
120 | .len = 1 |
121 | }, |
122 | { |
123 | .addr = dev->dt_addr, |
124 | .flags = I2C_M_RD, |
125 | .buf = b1, |
126 | .len = 1 |
127 | } |
128 | }; |
129 | |
130 | m88ds3103_update_bits(dev, reg: 0x11, mask: 0x01, val: 0x00); |
131 | |
132 | val = 0x12; |
133 | ret = regmap_write(map: dev->regmap, reg: 0x03, val); |
134 | if (ret) |
135 | dev_dbg(&client->dev, "fail=%d\n" , ret); |
136 | |
137 | ret = i2c_transfer(adap: dev->dt_client->adapter, msgs: msg, num: 2); |
138 | if (ret != 2) { |
139 | dev_err(&client->dev, "0x%02x (ret=%d, reg=0x%02x)\n" , |
140 | dev->dt_addr, ret, reg); |
141 | |
142 | m88ds3103_update_bits(dev, reg: 0x11, mask: 0x01, val: 0x01); |
143 | return -EREMOTEIO; |
144 | } |
145 | m88ds3103_update_bits(dev, reg: 0x11, mask: 0x01, val: 0x01); |
146 | |
147 | dev_dbg(&client->dev, "0x%02x reg 0x%02x, value 0x%02x\n" , |
148 | dev->dt_addr, reg, b1[0]); |
149 | |
150 | return b1[0]; |
151 | } |
152 | |
153 | /* |
154 | * Get the demodulator AGC PWM voltage setting supplied to the tuner. |
155 | */ |
156 | int m88ds3103_get_agc_pwm(struct dvb_frontend *fe, u8 *_agc_pwm) |
157 | { |
158 | struct m88ds3103_dev *dev = fe->demodulator_priv; |
159 | unsigned tmp; |
160 | int ret; |
161 | |
162 | ret = regmap_read(map: dev->regmap, reg: 0x3f, val: &tmp); |
163 | if (ret == 0) |
164 | *_agc_pwm = tmp; |
165 | return ret; |
166 | } |
167 | EXPORT_SYMBOL(m88ds3103_get_agc_pwm); |
168 | |
169 | static int m88ds3103_read_status(struct dvb_frontend *fe, |
170 | enum fe_status *status) |
171 | { |
172 | struct m88ds3103_dev *dev = fe->demodulator_priv; |
173 | struct i2c_client *client = dev->client; |
174 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
175 | int ret, i, itmp; |
176 | unsigned int utmp; |
177 | u8 buf[3]; |
178 | |
179 | *status = 0; |
180 | |
181 | if (!dev->warm) { |
182 | ret = -EAGAIN; |
183 | goto err; |
184 | } |
185 | |
186 | switch (c->delivery_system) { |
187 | case SYS_DVBS: |
188 | ret = regmap_read(map: dev->regmap, reg: 0xd1, val: &utmp); |
189 | if (ret) |
190 | goto err; |
191 | |
192 | if ((utmp & 0x07) == 0x07) |
193 | *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | |
194 | FE_HAS_VITERBI | FE_HAS_SYNC | |
195 | FE_HAS_LOCK; |
196 | break; |
197 | case SYS_DVBS2: |
198 | ret = regmap_read(map: dev->regmap, reg: 0x0d, val: &utmp); |
199 | if (ret) |
200 | goto err; |
201 | |
202 | if ((utmp & 0x8f) == 0x8f) |
203 | *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | |
204 | FE_HAS_VITERBI | FE_HAS_SYNC | |
205 | FE_HAS_LOCK; |
206 | break; |
207 | default: |
208 | dev_dbg(&client->dev, "invalid delivery_system\n" ); |
209 | ret = -EINVAL; |
210 | goto err; |
211 | } |
212 | |
213 | dev->fe_status = *status; |
214 | dev_dbg(&client->dev, "lock=%02x status=%02x\n" , utmp, *status); |
215 | |
216 | /* CNR */ |
217 | if (dev->fe_status & FE_HAS_VITERBI) { |
218 | unsigned int cnr, noise, signal, noise_tot, signal_tot; |
219 | |
220 | cnr = 0; |
221 | /* more iterations for more accurate estimation */ |
222 | #define M88DS3103_SNR_ITERATIONS 3 |
223 | |
224 | switch (c->delivery_system) { |
225 | case SYS_DVBS: |
226 | itmp = 0; |
227 | |
228 | for (i = 0; i < M88DS3103_SNR_ITERATIONS; i++) { |
229 | ret = regmap_read(map: dev->regmap, reg: 0xff, val: &utmp); |
230 | if (ret) |
231 | goto err; |
232 | |
233 | itmp += utmp; |
234 | } |
235 | |
236 | /* use of single register limits max value to 15 dB */ |
237 | /* SNR(X) dB = 10 * ln(X) / ln(10) dB */ |
238 | itmp = DIV_ROUND_CLOSEST(itmp, 8 * M88DS3103_SNR_ITERATIONS); |
239 | if (itmp) |
240 | cnr = div_u64(dividend: (u64) 10000 * intlog2(value: itmp), divisor: intlog2(value: 10)); |
241 | break; |
242 | case SYS_DVBS2: |
243 | noise_tot = 0; |
244 | signal_tot = 0; |
245 | |
246 | for (i = 0; i < M88DS3103_SNR_ITERATIONS; i++) { |
247 | ret = regmap_bulk_read(map: dev->regmap, reg: 0x8c, val: buf, val_count: 3); |
248 | if (ret) |
249 | goto err; |
250 | |
251 | noise = buf[1] << 6; /* [13:6] */ |
252 | noise |= buf[0] & 0x3f; /* [5:0] */ |
253 | noise >>= 2; |
254 | signal = buf[2] * buf[2]; |
255 | signal >>= 1; |
256 | |
257 | noise_tot += noise; |
258 | signal_tot += signal; |
259 | } |
260 | |
261 | noise = noise_tot / M88DS3103_SNR_ITERATIONS; |
262 | signal = signal_tot / M88DS3103_SNR_ITERATIONS; |
263 | |
264 | /* SNR(X) dB = 10 * log10(X) dB */ |
265 | if (signal > noise) { |
266 | itmp = signal / noise; |
267 | cnr = div_u64(dividend: (u64) 10000 * intlog10(value: itmp), divisor: (1 << 24)); |
268 | } |
269 | break; |
270 | default: |
271 | dev_dbg(&client->dev, "invalid delivery_system\n" ); |
272 | ret = -EINVAL; |
273 | goto err; |
274 | } |
275 | |
276 | if (cnr) { |
277 | c->cnr.stat[0].scale = FE_SCALE_DECIBEL; |
278 | c->cnr.stat[0].svalue = cnr; |
279 | } else { |
280 | c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
281 | } |
282 | } else { |
283 | c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
284 | } |
285 | |
286 | /* BER */ |
287 | if (dev->fe_status & FE_HAS_LOCK) { |
288 | unsigned int utmp, post_bit_error, post_bit_count; |
289 | |
290 | switch (c->delivery_system) { |
291 | case SYS_DVBS: |
292 | ret = regmap_write(map: dev->regmap, reg: 0xf9, val: 0x04); |
293 | if (ret) |
294 | goto err; |
295 | |
296 | ret = regmap_read(map: dev->regmap, reg: 0xf8, val: &utmp); |
297 | if (ret) |
298 | goto err; |
299 | |
300 | /* measurement ready? */ |
301 | if (!(utmp & 0x10)) { |
302 | ret = regmap_bulk_read(map: dev->regmap, reg: 0xf6, val: buf, val_count: 2); |
303 | if (ret) |
304 | goto err; |
305 | |
306 | post_bit_error = buf[1] << 8 | buf[0] << 0; |
307 | post_bit_count = 0x800000; |
308 | dev->post_bit_error += post_bit_error; |
309 | dev->post_bit_count += post_bit_count; |
310 | dev->dvbv3_ber = post_bit_error; |
311 | |
312 | /* restart measurement */ |
313 | utmp |= 0x10; |
314 | ret = regmap_write(map: dev->regmap, reg: 0xf8, val: utmp); |
315 | if (ret) |
316 | goto err; |
317 | } |
318 | break; |
319 | case SYS_DVBS2: |
320 | ret = regmap_bulk_read(map: dev->regmap, reg: 0xd5, val: buf, val_count: 3); |
321 | if (ret) |
322 | goto err; |
323 | |
324 | utmp = buf[2] << 16 | buf[1] << 8 | buf[0] << 0; |
325 | |
326 | /* enough data? */ |
327 | if (utmp > 4000) { |
328 | ret = regmap_bulk_read(map: dev->regmap, reg: 0xf7, val: buf, val_count: 2); |
329 | if (ret) |
330 | goto err; |
331 | |
332 | post_bit_error = buf[1] << 8 | buf[0] << 0; |
333 | post_bit_count = 32 * utmp; /* TODO: FEC */ |
334 | dev->post_bit_error += post_bit_error; |
335 | dev->post_bit_count += post_bit_count; |
336 | dev->dvbv3_ber = post_bit_error; |
337 | |
338 | /* restart measurement */ |
339 | ret = regmap_write(map: dev->regmap, reg: 0xd1, val: 0x01); |
340 | if (ret) |
341 | goto err; |
342 | |
343 | ret = regmap_write(map: dev->regmap, reg: 0xf9, val: 0x01); |
344 | if (ret) |
345 | goto err; |
346 | |
347 | ret = regmap_write(map: dev->regmap, reg: 0xf9, val: 0x00); |
348 | if (ret) |
349 | goto err; |
350 | |
351 | ret = regmap_write(map: dev->regmap, reg: 0xd1, val: 0x00); |
352 | if (ret) |
353 | goto err; |
354 | } |
355 | break; |
356 | default: |
357 | dev_dbg(&client->dev, "invalid delivery_system\n" ); |
358 | ret = -EINVAL; |
359 | goto err; |
360 | } |
361 | |
362 | c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; |
363 | c->post_bit_error.stat[0].uvalue = dev->post_bit_error; |
364 | c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; |
365 | c->post_bit_count.stat[0].uvalue = dev->post_bit_count; |
366 | } else { |
367 | c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
368 | c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
369 | } |
370 | |
371 | return 0; |
372 | err: |
373 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
374 | return ret; |
375 | } |
376 | |
377 | static int m88ds3103b_select_mclk(struct m88ds3103_dev *dev) |
378 | { |
379 | struct i2c_client *client = dev->client; |
380 | struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; |
381 | u32 adc_Freq_MHz[3] = {96, 93, 99}; |
382 | u8 reg16_list[3] = {96, 92, 100}, reg16, reg15; |
383 | u32 offset_MHz[3]; |
384 | u32 max_offset = 0; |
385 | u32 old_setting = dev->mclk; |
386 | u32 tuner_freq_MHz = c->frequency / 1000; |
387 | u8 i; |
388 | char big_symbol = 0; |
389 | |
390 | big_symbol = (c->symbol_rate > 45010000) ? 1 : 0; |
391 | |
392 | if (big_symbol) { |
393 | reg16 = 115; |
394 | } else { |
395 | reg16 = 96; |
396 | |
397 | /* TODO: IS THIS NECESSARY ? */ |
398 | for (i = 0; i < 3; i++) { |
399 | offset_MHz[i] = tuner_freq_MHz % adc_Freq_MHz[i]; |
400 | |
401 | if (offset_MHz[i] > (adc_Freq_MHz[i] / 2)) |
402 | offset_MHz[i] = adc_Freq_MHz[i] - offset_MHz[i]; |
403 | |
404 | if (offset_MHz[i] > max_offset) { |
405 | max_offset = offset_MHz[i]; |
406 | reg16 = reg16_list[i]; |
407 | dev->mclk = adc_Freq_MHz[i] * 1000 * 1000; |
408 | |
409 | if (big_symbol) |
410 | dev->mclk /= 2; |
411 | |
412 | dev_dbg(&client->dev, "modifying mclk %u -> %u\n" , |
413 | old_setting, dev->mclk); |
414 | } |
415 | } |
416 | } |
417 | |
418 | if (dev->mclk == 93000000) |
419 | regmap_write(map: dev->regmap, reg: 0xA0, val: 0x42); |
420 | else if (dev->mclk == 96000000) |
421 | regmap_write(map: dev->regmap, reg: 0xA0, val: 0x44); |
422 | else if (dev->mclk == 99000000) |
423 | regmap_write(map: dev->regmap, reg: 0xA0, val: 0x46); |
424 | else if (dev->mclk == 110250000) |
425 | regmap_write(map: dev->regmap, reg: 0xA0, val: 0x4E); |
426 | else |
427 | regmap_write(map: dev->regmap, reg: 0xA0, val: 0x44); |
428 | |
429 | reg15 = m88ds3103b_dt_read(dev, reg: 0x15); |
430 | |
431 | m88ds3103b_dt_write(dev, reg: 0x05, data: 0x40); |
432 | m88ds3103b_dt_write(dev, reg: 0x11, data: 0x08); |
433 | |
434 | if (big_symbol) |
435 | reg15 |= 0x02; |
436 | else |
437 | reg15 &= ~0x02; |
438 | |
439 | m88ds3103b_dt_write(dev, reg: 0x15, data: reg15); |
440 | m88ds3103b_dt_write(dev, reg: 0x16, data: reg16); |
441 | |
442 | usleep_range(min: 5000, max: 5500); |
443 | |
444 | m88ds3103b_dt_write(dev, reg: 0x05, data: 0x00); |
445 | m88ds3103b_dt_write(dev, reg: 0x11, data: (u8)(big_symbol ? 0x0E : 0x0A)); |
446 | |
447 | usleep_range(min: 5000, max: 5500); |
448 | |
449 | return 0; |
450 | } |
451 | |
452 | static int m88ds3103b_set_mclk(struct m88ds3103_dev *dev, u32 mclk_khz) |
453 | { |
454 | u8 reg15, reg16, reg1D, reg1E, reg1F, tmp; |
455 | u8 sm, f0 = 0, f1 = 0, f2 = 0, f3 = 0; |
456 | u16 pll_div_fb, N; |
457 | u32 div; |
458 | |
459 | reg15 = m88ds3103b_dt_read(dev, reg: 0x15); |
460 | reg16 = m88ds3103b_dt_read(dev, reg: 0x16); |
461 | reg1D = m88ds3103b_dt_read(dev, reg: 0x1D); |
462 | |
463 | if (dev->cfg->ts_mode != M88DS3103_TS_SERIAL) { |
464 | if (reg16 == 92) |
465 | tmp = 93; |
466 | else if (reg16 == 100) |
467 | tmp = 99; |
468 | else |
469 | tmp = 96; |
470 | |
471 | mclk_khz *= tmp; |
472 | mclk_khz /= 96; |
473 | } |
474 | |
475 | pll_div_fb = (reg15 & 0x01) << 8; |
476 | pll_div_fb += reg16; |
477 | pll_div_fb += 32; |
478 | |
479 | div = 9000 * pll_div_fb * 4; |
480 | div /= mclk_khz; |
481 | |
482 | if (dev->cfg->ts_mode == M88DS3103_TS_SERIAL) { |
483 | if (div <= 32) { |
484 | N = 2; |
485 | |
486 | f0 = 0; |
487 | f1 = div / N; |
488 | f2 = div - f1; |
489 | f3 = 0; |
490 | } else if (div <= 34) { |
491 | N = 3; |
492 | |
493 | f0 = div / N; |
494 | f1 = (div - f0) / (N - 1); |
495 | f2 = div - f0 - f1; |
496 | f3 = 0; |
497 | } else if (div <= 64) { |
498 | N = 4; |
499 | |
500 | f0 = div / N; |
501 | f1 = (div - f0) / (N - 1); |
502 | f2 = (div - f0 - f1) / (N - 2); |
503 | f3 = div - f0 - f1 - f2; |
504 | } else { |
505 | N = 4; |
506 | |
507 | f0 = 16; |
508 | f1 = 16; |
509 | f2 = 16; |
510 | f3 = 16; |
511 | } |
512 | |
513 | if (f0 == 16) |
514 | f0 = 0; |
515 | else if ((f0 < 8) && (f0 != 0)) |
516 | f0 = 8; |
517 | |
518 | if (f1 == 16) |
519 | f1 = 0; |
520 | else if ((f1 < 8) && (f1 != 0)) |
521 | f1 = 8; |
522 | |
523 | if (f2 == 16) |
524 | f2 = 0; |
525 | else if ((f2 < 8) && (f2 != 0)) |
526 | f2 = 8; |
527 | |
528 | if (f3 == 16) |
529 | f3 = 0; |
530 | else if ((f3 < 8) && (f3 != 0)) |
531 | f3 = 8; |
532 | } else { |
533 | if (div <= 32) { |
534 | N = 2; |
535 | |
536 | f0 = 0; |
537 | f1 = div / N; |
538 | f2 = div - f1; |
539 | f3 = 0; |
540 | } else if (div <= 48) { |
541 | N = 3; |
542 | |
543 | f0 = div / N; |
544 | f1 = (div - f0) / (N - 1); |
545 | f2 = div - f0 - f1; |
546 | f3 = 0; |
547 | } else if (div <= 64) { |
548 | N = 4; |
549 | |
550 | f0 = div / N; |
551 | f1 = (div - f0) / (N - 1); |
552 | f2 = (div - f0 - f1) / (N - 2); |
553 | f3 = div - f0 - f1 - f2; |
554 | } else { |
555 | N = 4; |
556 | |
557 | f0 = 16; |
558 | f1 = 16; |
559 | f2 = 16; |
560 | f3 = 16; |
561 | } |
562 | |
563 | if (f0 == 16) |
564 | f0 = 0; |
565 | else if ((f0 < 9) && (f0 != 0)) |
566 | f0 = 9; |
567 | |
568 | if (f1 == 16) |
569 | f1 = 0; |
570 | else if ((f1 < 9) && (f1 != 0)) |
571 | f1 = 9; |
572 | |
573 | if (f2 == 16) |
574 | f2 = 0; |
575 | else if ((f2 < 9) && (f2 != 0)) |
576 | f2 = 9; |
577 | |
578 | if (f3 == 16) |
579 | f3 = 0; |
580 | else if ((f3 < 9) && (f3 != 0)) |
581 | f3 = 9; |
582 | } |
583 | |
584 | sm = N - 1; |
585 | |
586 | /* Write to registers */ |
587 | //reg15 &= 0x01; |
588 | //reg15 |= (pll_div_fb >> 8) & 0x01; |
589 | |
590 | //reg16 = pll_div_fb & 0xFF; |
591 | |
592 | reg1D &= ~0x03; |
593 | reg1D |= sm; |
594 | reg1D |= 0x80; |
595 | |
596 | reg1E = ((f3 << 4) + f2) & 0xFF; |
597 | reg1F = ((f1 << 4) + f0) & 0xFF; |
598 | |
599 | m88ds3103b_dt_write(dev, reg: 0x05, data: 0x40); |
600 | m88ds3103b_dt_write(dev, reg: 0x11, data: 0x08); |
601 | m88ds3103b_dt_write(dev, reg: 0x1D, data: reg1D); |
602 | m88ds3103b_dt_write(dev, reg: 0x1E, data: reg1E); |
603 | m88ds3103b_dt_write(dev, reg: 0x1F, data: reg1F); |
604 | |
605 | m88ds3103b_dt_write(dev, reg: 0x17, data: 0xc1); |
606 | m88ds3103b_dt_write(dev, reg: 0x17, data: 0x81); |
607 | |
608 | usleep_range(min: 5000, max: 5500); |
609 | |
610 | m88ds3103b_dt_write(dev, reg: 0x05, data: 0x00); |
611 | m88ds3103b_dt_write(dev, reg: 0x11, data: 0x0A); |
612 | |
613 | usleep_range(min: 5000, max: 5500); |
614 | |
615 | return 0; |
616 | } |
617 | |
618 | static int m88ds3103_set_frontend(struct dvb_frontend *fe) |
619 | { |
620 | struct m88ds3103_dev *dev = fe->demodulator_priv; |
621 | struct i2c_client *client = dev->client; |
622 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
623 | int ret, len; |
624 | const struct m88ds3103_reg_val *init; |
625 | u8 u8tmp, u8tmp1 = 0, u8tmp2 = 0; /* silence compiler warning */ |
626 | u8 buf[3]; |
627 | u16 u16tmp; |
628 | u32 tuner_frequency_khz, target_mclk, u32tmp; |
629 | s32 s32tmp; |
630 | static const struct reg_sequence reset_buf[] = { |
631 | {0x07, 0x80}, {0x07, 0x00} |
632 | }; |
633 | |
634 | dev_dbg(&client->dev, |
635 | "delivery_system=%d modulation=%d frequency=%u symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n" , |
636 | c->delivery_system, c->modulation, c->frequency, c->symbol_rate, |
637 | c->inversion, c->pilot, c->rolloff); |
638 | |
639 | if (!dev->warm) { |
640 | ret = -EAGAIN; |
641 | goto err; |
642 | } |
643 | |
644 | /* reset */ |
645 | ret = regmap_multi_reg_write(map: dev->regmap, regs: reset_buf, num_regs: 2); |
646 | if (ret) |
647 | goto err; |
648 | |
649 | /* Disable demod clock path */ |
650 | if (dev->chip_id == M88RS6000_CHIP_ID) { |
651 | if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { |
652 | ret = regmap_read(map: dev->regmap, reg: 0xb2, val: &u32tmp); |
653 | if (ret) |
654 | goto err; |
655 | if (u32tmp == 0x01) { |
656 | ret = regmap_write(map: dev->regmap, reg: 0x00, val: 0x00); |
657 | if (ret) |
658 | goto err; |
659 | ret = regmap_write(map: dev->regmap, reg: 0xb2, val: 0x00); |
660 | if (ret) |
661 | goto err; |
662 | } |
663 | } |
664 | |
665 | ret = regmap_write(map: dev->regmap, reg: 0x06, val: 0xe0); |
666 | if (ret) |
667 | goto err; |
668 | } |
669 | |
670 | /* program tuner */ |
671 | if (fe->ops.tuner_ops.set_params) { |
672 | ret = fe->ops.tuner_ops.set_params(fe); |
673 | if (ret) |
674 | goto err; |
675 | } |
676 | |
677 | if (fe->ops.tuner_ops.get_frequency) { |
678 | ret = fe->ops.tuner_ops.get_frequency(fe, &tuner_frequency_khz); |
679 | if (ret) |
680 | goto err; |
681 | } else { |
682 | /* |
683 | * Use nominal target frequency as tuner driver does not provide |
684 | * actual frequency used. Carrier offset calculation is not |
685 | * valid. |
686 | */ |
687 | tuner_frequency_khz = c->frequency; |
688 | } |
689 | |
690 | /* set M88RS6000/DS3103B demod main mclk and ts mclk from tuner die */ |
691 | if (dev->chip_id == M88RS6000_CHIP_ID) { |
692 | if (c->symbol_rate > 45010000) |
693 | dev->mclk = 110250000; |
694 | else |
695 | dev->mclk = 96000000; |
696 | |
697 | if (c->delivery_system == SYS_DVBS) |
698 | target_mclk = 96000000; |
699 | else |
700 | target_mclk = 144000000; |
701 | |
702 | if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { |
703 | m88ds3103b_select_mclk(dev); |
704 | m88ds3103b_set_mclk(dev, mclk_khz: target_mclk / 1000); |
705 | } |
706 | |
707 | /* Enable demod clock path */ |
708 | ret = regmap_write(map: dev->regmap, reg: 0x06, val: 0x00); |
709 | if (ret) |
710 | goto err; |
711 | usleep_range(min: 10000, max: 20000); |
712 | } else { |
713 | /* set M88DS3103 mclk and ts mclk. */ |
714 | dev->mclk = 96000000; |
715 | |
716 | switch (dev->cfg->ts_mode) { |
717 | case M88DS3103_TS_SERIAL: |
718 | case M88DS3103_TS_SERIAL_D7: |
719 | target_mclk = dev->cfg->ts_clk; |
720 | break; |
721 | case M88DS3103_TS_PARALLEL: |
722 | case M88DS3103_TS_CI: |
723 | if (c->delivery_system == SYS_DVBS) |
724 | target_mclk = 96000000; |
725 | else { |
726 | if (c->symbol_rate < 18000000) |
727 | target_mclk = 96000000; |
728 | else if (c->symbol_rate < 28000000) |
729 | target_mclk = 144000000; |
730 | else |
731 | target_mclk = 192000000; |
732 | } |
733 | break; |
734 | default: |
735 | dev_dbg(&client->dev, "invalid ts_mode\n" ); |
736 | ret = -EINVAL; |
737 | goto err; |
738 | } |
739 | |
740 | switch (target_mclk) { |
741 | case 96000000: |
742 | u8tmp1 = 0x02; /* 0b10 */ |
743 | u8tmp2 = 0x01; /* 0b01 */ |
744 | break; |
745 | case 144000000: |
746 | u8tmp1 = 0x00; /* 0b00 */ |
747 | u8tmp2 = 0x01; /* 0b01 */ |
748 | break; |
749 | case 192000000: |
750 | u8tmp1 = 0x03; /* 0b11 */ |
751 | u8tmp2 = 0x00; /* 0b00 */ |
752 | break; |
753 | } |
754 | ret = m88ds3103_update_bits(dev, reg: 0x22, mask: 0xc0, val: u8tmp1 << 6); |
755 | if (ret) |
756 | goto err; |
757 | ret = m88ds3103_update_bits(dev, reg: 0x24, mask: 0xc0, val: u8tmp2 << 6); |
758 | if (ret) |
759 | goto err; |
760 | } |
761 | |
762 | ret = regmap_write(map: dev->regmap, reg: 0xb2, val: 0x01); |
763 | if (ret) |
764 | goto err; |
765 | |
766 | ret = regmap_write(map: dev->regmap, reg: 0x00, val: 0x01); |
767 | if (ret) |
768 | goto err; |
769 | |
770 | switch (c->delivery_system) { |
771 | case SYS_DVBS: |
772 | if (dev->chip_id == M88RS6000_CHIP_ID) { |
773 | len = ARRAY_SIZE(m88rs6000_dvbs_init_reg_vals); |
774 | init = m88rs6000_dvbs_init_reg_vals; |
775 | } else { |
776 | len = ARRAY_SIZE(m88ds3103_dvbs_init_reg_vals); |
777 | init = m88ds3103_dvbs_init_reg_vals; |
778 | } |
779 | break; |
780 | case SYS_DVBS2: |
781 | if (dev->chip_id == M88RS6000_CHIP_ID) { |
782 | len = ARRAY_SIZE(m88rs6000_dvbs2_init_reg_vals); |
783 | init = m88rs6000_dvbs2_init_reg_vals; |
784 | } else { |
785 | len = ARRAY_SIZE(m88ds3103_dvbs2_init_reg_vals); |
786 | init = m88ds3103_dvbs2_init_reg_vals; |
787 | } |
788 | break; |
789 | default: |
790 | dev_dbg(&client->dev, "invalid delivery_system\n" ); |
791 | ret = -EINVAL; |
792 | goto err; |
793 | } |
794 | |
795 | /* program init table */ |
796 | if (c->delivery_system != dev->delivery_system) { |
797 | ret = m88ds3103_wr_reg_val_tab(dev, tab: init, tab_len: len); |
798 | if (ret) |
799 | goto err; |
800 | } |
801 | |
802 | if (dev->chip_id == M88RS6000_CHIP_ID) { |
803 | if (c->delivery_system == SYS_DVBS2 && |
804 | c->symbol_rate <= 5000000) { |
805 | ret = regmap_write(map: dev->regmap, reg: 0xc0, val: 0x04); |
806 | if (ret) |
807 | goto err; |
808 | buf[0] = 0x09; |
809 | buf[1] = 0x22; |
810 | buf[2] = 0x88; |
811 | ret = regmap_bulk_write(map: dev->regmap, reg: 0x8a, val: buf, val_count: 3); |
812 | if (ret) |
813 | goto err; |
814 | } |
815 | ret = m88ds3103_update_bits(dev, reg: 0x9d, mask: 0x08, val: 0x08); |
816 | if (ret) |
817 | goto err; |
818 | |
819 | if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { |
820 | buf[0] = m88ds3103b_dt_read(dev, reg: 0x15); |
821 | buf[1] = m88ds3103b_dt_read(dev, reg: 0x16); |
822 | |
823 | if (c->symbol_rate > 45010000) { |
824 | buf[0] &= ~0x03; |
825 | buf[0] |= 0x02; |
826 | buf[0] |= ((147 - 32) >> 8) & 0x01; |
827 | buf[1] = (147 - 32) & 0xFF; |
828 | |
829 | dev->mclk = 110250 * 1000; |
830 | } else { |
831 | buf[0] &= ~0x03; |
832 | buf[0] |= ((128 - 32) >> 8) & 0x01; |
833 | buf[1] = (128 - 32) & 0xFF; |
834 | |
835 | dev->mclk = 96000 * 1000; |
836 | } |
837 | m88ds3103b_dt_write(dev, reg: 0x15, data: buf[0]); |
838 | m88ds3103b_dt_write(dev, reg: 0x16, data: buf[1]); |
839 | |
840 | regmap_read(map: dev->regmap, reg: 0x30, val: &u32tmp); |
841 | u32tmp &= ~0x80; |
842 | regmap_write(map: dev->regmap, reg: 0x30, val: u32tmp & 0xff); |
843 | } |
844 | |
845 | ret = regmap_write(map: dev->regmap, reg: 0xf1, val: 0x01); |
846 | if (ret) |
847 | goto err; |
848 | |
849 | if (dev->chiptype != M88DS3103_CHIPTYPE_3103B) { |
850 | ret = m88ds3103_update_bits(dev, reg: 0x30, mask: 0x80, val: 0x80); |
851 | if (ret) |
852 | goto err; |
853 | } |
854 | } |
855 | |
856 | switch (dev->cfg->ts_mode) { |
857 | case M88DS3103_TS_SERIAL: |
858 | u8tmp1 = 0x00; |
859 | u8tmp = 0x06; |
860 | break; |
861 | case M88DS3103_TS_SERIAL_D7: |
862 | u8tmp1 = 0x20; |
863 | u8tmp = 0x06; |
864 | break; |
865 | case M88DS3103_TS_PARALLEL: |
866 | u8tmp = 0x02; |
867 | if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { |
868 | u8tmp = 0x01; |
869 | u8tmp1 = 0x01; |
870 | } |
871 | break; |
872 | case M88DS3103_TS_CI: |
873 | u8tmp = 0x03; |
874 | break; |
875 | default: |
876 | dev_dbg(&client->dev, "invalid ts_mode\n" ); |
877 | ret = -EINVAL; |
878 | goto err; |
879 | } |
880 | |
881 | if (dev->cfg->ts_clk_pol) |
882 | u8tmp |= 0x40; |
883 | |
884 | /* TS mode */ |
885 | ret = regmap_write(map: dev->regmap, reg: 0xfd, val: u8tmp); |
886 | if (ret) |
887 | goto err; |
888 | |
889 | switch (dev->cfg->ts_mode) { |
890 | case M88DS3103_TS_SERIAL: |
891 | case M88DS3103_TS_SERIAL_D7: |
892 | ret = m88ds3103_update_bits(dev, reg: 0x29, mask: 0x20, val: u8tmp1); |
893 | if (ret) |
894 | goto err; |
895 | u16tmp = 0; |
896 | u8tmp1 = 0x3f; |
897 | u8tmp2 = 0x3f; |
898 | break; |
899 | case M88DS3103_TS_PARALLEL: |
900 | if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { |
901 | ret = m88ds3103_update_bits(dev, reg: 0x29, mask: 0x01, val: u8tmp1); |
902 | if (ret) |
903 | goto err; |
904 | } |
905 | fallthrough; |
906 | default: |
907 | u16tmp = DIV_ROUND_UP(target_mclk, dev->cfg->ts_clk); |
908 | u8tmp1 = u16tmp / 2 - 1; |
909 | u8tmp2 = DIV_ROUND_UP(u16tmp, 2) - 1; |
910 | } |
911 | |
912 | dev_dbg(&client->dev, "target_mclk=%u ts_clk=%u ts_clk_divide_ratio=%u\n" , |
913 | target_mclk, dev->cfg->ts_clk, u16tmp); |
914 | |
915 | /* u8tmp1[5:2] => fe[3:0], u8tmp1[1:0] => ea[7:6] */ |
916 | /* u8tmp2[5:0] => ea[5:0] */ |
917 | u8tmp = (u8tmp1 >> 2) & 0x0f; |
918 | ret = regmap_update_bits(map: dev->regmap, reg: 0xfe, mask: 0x0f, val: u8tmp); |
919 | if (ret) |
920 | goto err; |
921 | u8tmp = ((u8tmp1 & 0x03) << 6) | u8tmp2 >> 0; |
922 | ret = regmap_write(map: dev->regmap, reg: 0xea, val: u8tmp); |
923 | if (ret) |
924 | goto err; |
925 | |
926 | if (c->symbol_rate <= 3000000) |
927 | u8tmp = 0x20; |
928 | else if (c->symbol_rate <= 10000000) |
929 | u8tmp = 0x10; |
930 | else |
931 | u8tmp = 0x06; |
932 | |
933 | if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) |
934 | m88ds3103b_set_mclk(dev, mclk_khz: target_mclk / 1000); |
935 | |
936 | ret = regmap_write(map: dev->regmap, reg: 0xc3, val: 0x08); |
937 | if (ret) |
938 | goto err; |
939 | |
940 | ret = regmap_write(map: dev->regmap, reg: 0xc8, val: u8tmp); |
941 | if (ret) |
942 | goto err; |
943 | |
944 | ret = regmap_write(map: dev->regmap, reg: 0xc4, val: 0x08); |
945 | if (ret) |
946 | goto err; |
947 | |
948 | ret = regmap_write(map: dev->regmap, reg: 0xc7, val: 0x00); |
949 | if (ret) |
950 | goto err; |
951 | |
952 | u16tmp = DIV_ROUND_CLOSEST_ULL((u64)c->symbol_rate * 0x10000, dev->mclk); |
953 | buf[0] = (u16tmp >> 0) & 0xff; |
954 | buf[1] = (u16tmp >> 8) & 0xff; |
955 | ret = regmap_bulk_write(map: dev->regmap, reg: 0x61, val: buf, val_count: 2); |
956 | if (ret) |
957 | goto err; |
958 | |
959 | ret = m88ds3103_update_bits(dev, reg: 0x4d, mask: 0x02, val: dev->cfg->spec_inv << 1); |
960 | if (ret) |
961 | goto err; |
962 | |
963 | ret = m88ds3103_update_bits(dev, reg: 0x30, mask: 0x10, val: dev->cfg->agc_inv << 4); |
964 | if (ret) |
965 | goto err; |
966 | |
967 | ret = regmap_write(map: dev->regmap, reg: 0x33, val: dev->cfg->agc); |
968 | if (ret) |
969 | goto err; |
970 | |
971 | if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { |
972 | /* enable/disable 192M LDPC clock */ |
973 | ret = m88ds3103_update_bits(dev, reg: 0x29, mask: 0x10, |
974 | val: (c->delivery_system == SYS_DVBS) ? 0x10 : 0x0); |
975 | if (ret) |
976 | goto err; |
977 | |
978 | ret = m88ds3103_update_bits(dev, reg: 0xc9, mask: 0x08, val: 0x08); |
979 | if (ret) |
980 | goto err; |
981 | } |
982 | |
983 | dev_dbg(&client->dev, "carrier offset=%d\n" , |
984 | (tuner_frequency_khz - c->frequency)); |
985 | |
986 | /* Use 32-bit calc as there is no s64 version of DIV_ROUND_CLOSEST() */ |
987 | s32tmp = 0x10000 * (tuner_frequency_khz - c->frequency); |
988 | s32tmp = DIV_ROUND_CLOSEST(s32tmp, dev->mclk / 1000); |
989 | buf[0] = (s32tmp >> 0) & 0xff; |
990 | buf[1] = (s32tmp >> 8) & 0xff; |
991 | ret = regmap_bulk_write(map: dev->regmap, reg: 0x5e, val: buf, val_count: 2); |
992 | if (ret) |
993 | goto err; |
994 | |
995 | ret = regmap_write(map: dev->regmap, reg: 0x00, val: 0x00); |
996 | if (ret) |
997 | goto err; |
998 | |
999 | ret = regmap_write(map: dev->regmap, reg: 0xb2, val: 0x00); |
1000 | if (ret) |
1001 | goto err; |
1002 | |
1003 | dev->delivery_system = c->delivery_system; |
1004 | |
1005 | return 0; |
1006 | err: |
1007 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
1008 | return ret; |
1009 | } |
1010 | |
1011 | static int m88ds3103_init(struct dvb_frontend *fe) |
1012 | { |
1013 | struct m88ds3103_dev *dev = fe->demodulator_priv; |
1014 | struct i2c_client *client = dev->client; |
1015 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
1016 | int ret, len, rem; |
1017 | unsigned int utmp; |
1018 | const struct firmware *firmware; |
1019 | const char *name; |
1020 | |
1021 | dev_dbg(&client->dev, "\n" ); |
1022 | |
1023 | /* set cold state by default */ |
1024 | dev->warm = false; |
1025 | |
1026 | /* wake up device from sleep */ |
1027 | ret = m88ds3103_update_bits(dev, reg: 0x08, mask: 0x01, val: 0x01); |
1028 | if (ret) |
1029 | goto err; |
1030 | ret = m88ds3103_update_bits(dev, reg: 0x04, mask: 0x01, val: 0x00); |
1031 | if (ret) |
1032 | goto err; |
1033 | ret = m88ds3103_update_bits(dev, reg: 0x23, mask: 0x10, val: 0x00); |
1034 | if (ret) |
1035 | goto err; |
1036 | |
1037 | /* firmware status */ |
1038 | ret = regmap_read(map: dev->regmap, reg: 0xb9, val: &utmp); |
1039 | if (ret) |
1040 | goto err; |
1041 | |
1042 | dev_dbg(&client->dev, "firmware=%02x\n" , utmp); |
1043 | |
1044 | if (utmp) |
1045 | goto warm; |
1046 | |
1047 | /* global reset, global diseqc reset, global fec reset */ |
1048 | ret = regmap_write(map: dev->regmap, reg: 0x07, val: 0xe0); |
1049 | if (ret) |
1050 | goto err; |
1051 | ret = regmap_write(map: dev->regmap, reg: 0x07, val: 0x00); |
1052 | if (ret) |
1053 | goto err; |
1054 | |
1055 | /* cold state - try to download firmware */ |
1056 | dev_info(&client->dev, "found a '%s' in cold state\n" , |
1057 | dev->fe.ops.info.name); |
1058 | |
1059 | if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) |
1060 | name = M88DS3103B_FIRMWARE; |
1061 | else if (dev->chip_id == M88RS6000_CHIP_ID) |
1062 | name = M88RS6000_FIRMWARE; |
1063 | else |
1064 | name = M88DS3103_FIRMWARE; |
1065 | |
1066 | /* request the firmware, this will block and timeout */ |
1067 | ret = request_firmware(fw: &firmware, name, device: &client->dev); |
1068 | if (ret) { |
1069 | dev_err(&client->dev, "firmware file '%s' not found\n" , name); |
1070 | goto err; |
1071 | } |
1072 | |
1073 | dev_info(&client->dev, "downloading firmware from file '%s'\n" , name); |
1074 | |
1075 | ret = regmap_write(map: dev->regmap, reg: 0xb2, val: 0x01); |
1076 | if (ret) |
1077 | goto err_release_firmware; |
1078 | |
1079 | for (rem = firmware->size; rem > 0; rem -= (dev->cfg->i2c_wr_max - 1)) { |
1080 | len = min(dev->cfg->i2c_wr_max - 1, rem); |
1081 | ret = regmap_bulk_write(map: dev->regmap, reg: 0xb0, |
1082 | val: &firmware->data[firmware->size - rem], |
1083 | val_count: len); |
1084 | if (ret) { |
1085 | dev_err(&client->dev, "firmware download failed %d\n" , |
1086 | ret); |
1087 | goto err_release_firmware; |
1088 | } |
1089 | } |
1090 | |
1091 | ret = regmap_write(map: dev->regmap, reg: 0xb2, val: 0x00); |
1092 | if (ret) |
1093 | goto err_release_firmware; |
1094 | |
1095 | release_firmware(fw: firmware); |
1096 | |
1097 | ret = regmap_read(map: dev->regmap, reg: 0xb9, val: &utmp); |
1098 | if (ret) |
1099 | goto err; |
1100 | |
1101 | if (!utmp) { |
1102 | ret = -EINVAL; |
1103 | dev_info(&client->dev, "firmware did not run\n" ); |
1104 | goto err; |
1105 | } |
1106 | |
1107 | dev_info(&client->dev, "found a '%s' in warm state\n" , |
1108 | dev->fe.ops.info.name); |
1109 | dev_info(&client->dev, "firmware version: %X.%X\n" , |
1110 | (utmp >> 4) & 0xf, (utmp >> 0 & 0xf)); |
1111 | |
1112 | if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { |
1113 | m88ds3103b_dt_write(dev, reg: 0x21, data: 0x92); |
1114 | m88ds3103b_dt_write(dev, reg: 0x15, data: 0x6C); |
1115 | m88ds3103b_dt_write(dev, reg: 0x17, data: 0xC1); |
1116 | m88ds3103b_dt_write(dev, reg: 0x17, data: 0x81); |
1117 | } |
1118 | warm: |
1119 | /* warm state */ |
1120 | dev->warm = true; |
1121 | |
1122 | /* init stats here in order signal app which stats are supported */ |
1123 | c->cnr.len = 1; |
1124 | c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
1125 | c->post_bit_error.len = 1; |
1126 | c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
1127 | c->post_bit_count.len = 1; |
1128 | c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
1129 | |
1130 | return 0; |
1131 | err_release_firmware: |
1132 | release_firmware(fw: firmware); |
1133 | err: |
1134 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
1135 | return ret; |
1136 | } |
1137 | |
1138 | static int m88ds3103_sleep(struct dvb_frontend *fe) |
1139 | { |
1140 | struct m88ds3103_dev *dev = fe->demodulator_priv; |
1141 | struct i2c_client *client = dev->client; |
1142 | int ret; |
1143 | unsigned int utmp; |
1144 | |
1145 | dev_dbg(&client->dev, "\n" ); |
1146 | |
1147 | dev->fe_status = 0; |
1148 | dev->delivery_system = SYS_UNDEFINED; |
1149 | |
1150 | /* TS Hi-Z */ |
1151 | if (dev->chip_id == M88RS6000_CHIP_ID) |
1152 | utmp = 0x29; |
1153 | else |
1154 | utmp = 0x27; |
1155 | ret = m88ds3103_update_bits(dev, reg: utmp, mask: 0x01, val: 0x00); |
1156 | if (ret) |
1157 | goto err; |
1158 | |
1159 | /* sleep */ |
1160 | ret = m88ds3103_update_bits(dev, reg: 0x08, mask: 0x01, val: 0x00); |
1161 | if (ret) |
1162 | goto err; |
1163 | ret = m88ds3103_update_bits(dev, reg: 0x04, mask: 0x01, val: 0x01); |
1164 | if (ret) |
1165 | goto err; |
1166 | ret = m88ds3103_update_bits(dev, reg: 0x23, mask: 0x10, val: 0x10); |
1167 | if (ret) |
1168 | goto err; |
1169 | |
1170 | return 0; |
1171 | err: |
1172 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
1173 | return ret; |
1174 | } |
1175 | |
1176 | static int m88ds3103_get_frontend(struct dvb_frontend *fe, |
1177 | struct dtv_frontend_properties *c) |
1178 | { |
1179 | struct m88ds3103_dev *dev = fe->demodulator_priv; |
1180 | struct i2c_client *client = dev->client; |
1181 | int ret; |
1182 | u8 buf[3]; |
1183 | |
1184 | dev_dbg(&client->dev, "\n" ); |
1185 | |
1186 | if (!dev->warm || !(dev->fe_status & FE_HAS_LOCK)) { |
1187 | ret = 0; |
1188 | goto err; |
1189 | } |
1190 | |
1191 | switch (c->delivery_system) { |
1192 | case SYS_DVBS: |
1193 | ret = regmap_bulk_read(map: dev->regmap, reg: 0xe0, val: &buf[0], val_count: 1); |
1194 | if (ret) |
1195 | goto err; |
1196 | |
1197 | ret = regmap_bulk_read(map: dev->regmap, reg: 0xe6, val: &buf[1], val_count: 1); |
1198 | if (ret) |
1199 | goto err; |
1200 | |
1201 | switch ((buf[0] >> 2) & 0x01) { |
1202 | case 0: |
1203 | c->inversion = INVERSION_OFF; |
1204 | break; |
1205 | case 1: |
1206 | c->inversion = INVERSION_ON; |
1207 | break; |
1208 | } |
1209 | |
1210 | switch ((buf[1] >> 5) & 0x07) { |
1211 | case 0: |
1212 | c->fec_inner = FEC_7_8; |
1213 | break; |
1214 | case 1: |
1215 | c->fec_inner = FEC_5_6; |
1216 | break; |
1217 | case 2: |
1218 | c->fec_inner = FEC_3_4; |
1219 | break; |
1220 | case 3: |
1221 | c->fec_inner = FEC_2_3; |
1222 | break; |
1223 | case 4: |
1224 | c->fec_inner = FEC_1_2; |
1225 | break; |
1226 | default: |
1227 | dev_dbg(&client->dev, "invalid fec_inner\n" ); |
1228 | } |
1229 | |
1230 | c->modulation = QPSK; |
1231 | |
1232 | break; |
1233 | case SYS_DVBS2: |
1234 | ret = regmap_bulk_read(map: dev->regmap, reg: 0x7e, val: &buf[0], val_count: 1); |
1235 | if (ret) |
1236 | goto err; |
1237 | |
1238 | ret = regmap_bulk_read(map: dev->regmap, reg: 0x89, val: &buf[1], val_count: 1); |
1239 | if (ret) |
1240 | goto err; |
1241 | |
1242 | ret = regmap_bulk_read(map: dev->regmap, reg: 0xf2, val: &buf[2], val_count: 1); |
1243 | if (ret) |
1244 | goto err; |
1245 | |
1246 | switch ((buf[0] >> 0) & 0x0f) { |
1247 | case 2: |
1248 | c->fec_inner = FEC_2_5; |
1249 | break; |
1250 | case 3: |
1251 | c->fec_inner = FEC_1_2; |
1252 | break; |
1253 | case 4: |
1254 | c->fec_inner = FEC_3_5; |
1255 | break; |
1256 | case 5: |
1257 | c->fec_inner = FEC_2_3; |
1258 | break; |
1259 | case 6: |
1260 | c->fec_inner = FEC_3_4; |
1261 | break; |
1262 | case 7: |
1263 | c->fec_inner = FEC_4_5; |
1264 | break; |
1265 | case 8: |
1266 | c->fec_inner = FEC_5_6; |
1267 | break; |
1268 | case 9: |
1269 | c->fec_inner = FEC_8_9; |
1270 | break; |
1271 | case 10: |
1272 | c->fec_inner = FEC_9_10; |
1273 | break; |
1274 | default: |
1275 | dev_dbg(&client->dev, "invalid fec_inner\n" ); |
1276 | } |
1277 | |
1278 | switch ((buf[0] >> 5) & 0x01) { |
1279 | case 0: |
1280 | c->pilot = PILOT_OFF; |
1281 | break; |
1282 | case 1: |
1283 | c->pilot = PILOT_ON; |
1284 | break; |
1285 | } |
1286 | |
1287 | switch ((buf[0] >> 6) & 0x07) { |
1288 | case 0: |
1289 | c->modulation = QPSK; |
1290 | break; |
1291 | case 1: |
1292 | c->modulation = PSK_8; |
1293 | break; |
1294 | case 2: |
1295 | c->modulation = APSK_16; |
1296 | break; |
1297 | case 3: |
1298 | c->modulation = APSK_32; |
1299 | break; |
1300 | default: |
1301 | dev_dbg(&client->dev, "invalid modulation\n" ); |
1302 | } |
1303 | |
1304 | switch ((buf[1] >> 7) & 0x01) { |
1305 | case 0: |
1306 | c->inversion = INVERSION_OFF; |
1307 | break; |
1308 | case 1: |
1309 | c->inversion = INVERSION_ON; |
1310 | break; |
1311 | } |
1312 | |
1313 | switch ((buf[2] >> 0) & 0x03) { |
1314 | case 0: |
1315 | c->rolloff = ROLLOFF_35; |
1316 | break; |
1317 | case 1: |
1318 | c->rolloff = ROLLOFF_25; |
1319 | break; |
1320 | case 2: |
1321 | c->rolloff = ROLLOFF_20; |
1322 | break; |
1323 | default: |
1324 | dev_dbg(&client->dev, "invalid rolloff\n" ); |
1325 | } |
1326 | break; |
1327 | default: |
1328 | dev_dbg(&client->dev, "invalid delivery_system\n" ); |
1329 | ret = -EINVAL; |
1330 | goto err; |
1331 | } |
1332 | |
1333 | ret = regmap_bulk_read(map: dev->regmap, reg: 0x6d, val: buf, val_count: 2); |
1334 | if (ret) |
1335 | goto err; |
1336 | |
1337 | c->symbol_rate = DIV_ROUND_CLOSEST_ULL((u64)(buf[1] << 8 | buf[0] << 0) * dev->mclk, 0x10000); |
1338 | |
1339 | return 0; |
1340 | err: |
1341 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
1342 | return ret; |
1343 | } |
1344 | |
1345 | static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *snr) |
1346 | { |
1347 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
1348 | |
1349 | if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL) |
1350 | *snr = div_s64(dividend: c->cnr.stat[0].svalue, divisor: 100); |
1351 | else |
1352 | *snr = 0; |
1353 | |
1354 | return 0; |
1355 | } |
1356 | |
1357 | static int m88ds3103_read_ber(struct dvb_frontend *fe, u32 *ber) |
1358 | { |
1359 | struct m88ds3103_dev *dev = fe->demodulator_priv; |
1360 | |
1361 | *ber = dev->dvbv3_ber; |
1362 | |
1363 | return 0; |
1364 | } |
1365 | |
1366 | static int m88ds3103_set_tone(struct dvb_frontend *fe, |
1367 | enum fe_sec_tone_mode fe_sec_tone_mode) |
1368 | { |
1369 | struct m88ds3103_dev *dev = fe->demodulator_priv; |
1370 | struct i2c_client *client = dev->client; |
1371 | int ret; |
1372 | unsigned int utmp, tone, reg_a1_mask; |
1373 | |
1374 | dev_dbg(&client->dev, "fe_sec_tone_mode=%d\n" , fe_sec_tone_mode); |
1375 | |
1376 | if (!dev->warm) { |
1377 | ret = -EAGAIN; |
1378 | goto err; |
1379 | } |
1380 | |
1381 | switch (fe_sec_tone_mode) { |
1382 | case SEC_TONE_ON: |
1383 | tone = 0; |
1384 | reg_a1_mask = 0x47; |
1385 | break; |
1386 | case SEC_TONE_OFF: |
1387 | tone = 1; |
1388 | reg_a1_mask = 0x00; |
1389 | break; |
1390 | default: |
1391 | dev_dbg(&client->dev, "invalid fe_sec_tone_mode\n" ); |
1392 | ret = -EINVAL; |
1393 | goto err; |
1394 | } |
1395 | |
1396 | utmp = tone << 7 | dev->cfg->envelope_mode << 5; |
1397 | ret = m88ds3103_update_bits(dev, reg: 0xa2, mask: 0xe0, val: utmp); |
1398 | if (ret) |
1399 | goto err; |
1400 | |
1401 | utmp = 1 << 2; |
1402 | ret = m88ds3103_update_bits(dev, reg: 0xa1, mask: reg_a1_mask, val: utmp); |
1403 | if (ret) |
1404 | goto err; |
1405 | |
1406 | return 0; |
1407 | err: |
1408 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
1409 | return ret; |
1410 | } |
1411 | |
1412 | static int m88ds3103_set_voltage(struct dvb_frontend *fe, |
1413 | enum fe_sec_voltage fe_sec_voltage) |
1414 | { |
1415 | struct m88ds3103_dev *dev = fe->demodulator_priv; |
1416 | struct i2c_client *client = dev->client; |
1417 | int ret; |
1418 | unsigned int utmp; |
1419 | bool voltage_sel, voltage_dis; |
1420 | |
1421 | dev_dbg(&client->dev, "fe_sec_voltage=%d\n" , fe_sec_voltage); |
1422 | |
1423 | if (!dev->warm) { |
1424 | ret = -EAGAIN; |
1425 | goto err; |
1426 | } |
1427 | |
1428 | switch (fe_sec_voltage) { |
1429 | case SEC_VOLTAGE_18: |
1430 | voltage_sel = true; |
1431 | voltage_dis = false; |
1432 | break; |
1433 | case SEC_VOLTAGE_13: |
1434 | voltage_sel = false; |
1435 | voltage_dis = false; |
1436 | break; |
1437 | case SEC_VOLTAGE_OFF: |
1438 | voltage_sel = false; |
1439 | voltage_dis = true; |
1440 | break; |
1441 | default: |
1442 | dev_dbg(&client->dev, "invalid fe_sec_voltage\n" ); |
1443 | ret = -EINVAL; |
1444 | goto err; |
1445 | } |
1446 | |
1447 | /* output pin polarity */ |
1448 | voltage_sel ^= dev->cfg->lnb_hv_pol; |
1449 | voltage_dis ^= dev->cfg->lnb_en_pol; |
1450 | |
1451 | utmp = voltage_dis << 1 | voltage_sel << 0; |
1452 | ret = m88ds3103_update_bits(dev, reg: 0xa2, mask: 0x03, val: utmp); |
1453 | if (ret) |
1454 | goto err; |
1455 | |
1456 | return 0; |
1457 | err: |
1458 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
1459 | return ret; |
1460 | } |
1461 | |
1462 | static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe, |
1463 | struct dvb_diseqc_master_cmd *diseqc_cmd) |
1464 | { |
1465 | struct m88ds3103_dev *dev = fe->demodulator_priv; |
1466 | struct i2c_client *client = dev->client; |
1467 | int ret; |
1468 | unsigned int utmp; |
1469 | unsigned long timeout; |
1470 | |
1471 | dev_dbg(&client->dev, "msg=%*ph\n" , |
1472 | diseqc_cmd->msg_len, diseqc_cmd->msg); |
1473 | |
1474 | if (!dev->warm) { |
1475 | ret = -EAGAIN; |
1476 | goto err; |
1477 | } |
1478 | |
1479 | if (diseqc_cmd->msg_len < 3 || diseqc_cmd->msg_len > 6) { |
1480 | ret = -EINVAL; |
1481 | goto err; |
1482 | } |
1483 | |
1484 | utmp = dev->cfg->envelope_mode << 5; |
1485 | ret = m88ds3103_update_bits(dev, reg: 0xa2, mask: 0xe0, val: utmp); |
1486 | if (ret) |
1487 | goto err; |
1488 | |
1489 | ret = regmap_bulk_write(map: dev->regmap, reg: 0xa3, val: diseqc_cmd->msg, |
1490 | val_count: diseqc_cmd->msg_len); |
1491 | if (ret) |
1492 | goto err; |
1493 | |
1494 | ret = regmap_write(map: dev->regmap, reg: 0xa1, |
1495 | val: (diseqc_cmd->msg_len - 1) << 3 | 0x07); |
1496 | if (ret) |
1497 | goto err; |
1498 | |
1499 | /* wait DiSEqC TX ready */ |
1500 | #define SEND_MASTER_CMD_TIMEOUT 120 |
1501 | timeout = jiffies + msecs_to_jiffies(SEND_MASTER_CMD_TIMEOUT); |
1502 | |
1503 | /* DiSEqC message period is 13.5 ms per byte */ |
1504 | utmp = diseqc_cmd->msg_len * 13500; |
1505 | usleep_range(min: utmp - 4000, max: utmp); |
1506 | |
1507 | for (utmp = 1; !time_after(jiffies, timeout) && utmp;) { |
1508 | ret = regmap_read(map: dev->regmap, reg: 0xa1, val: &utmp); |
1509 | if (ret) |
1510 | goto err; |
1511 | utmp = (utmp >> 6) & 0x1; |
1512 | } |
1513 | |
1514 | if (utmp == 0) { |
1515 | dev_dbg(&client->dev, "diseqc tx took %u ms\n" , |
1516 | jiffies_to_msecs(jiffies) - |
1517 | (jiffies_to_msecs(timeout) - SEND_MASTER_CMD_TIMEOUT)); |
1518 | } else { |
1519 | dev_dbg(&client->dev, "diseqc tx timeout\n" ); |
1520 | |
1521 | ret = m88ds3103_update_bits(dev, reg: 0xa1, mask: 0xc0, val: 0x40); |
1522 | if (ret) |
1523 | goto err; |
1524 | } |
1525 | |
1526 | ret = m88ds3103_update_bits(dev, reg: 0xa2, mask: 0xc0, val: 0x80); |
1527 | if (ret) |
1528 | goto err; |
1529 | |
1530 | if (utmp == 1) { |
1531 | ret = -ETIMEDOUT; |
1532 | goto err; |
1533 | } |
1534 | |
1535 | return 0; |
1536 | err: |
1537 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
1538 | return ret; |
1539 | } |
1540 | |
1541 | static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe, |
1542 | enum fe_sec_mini_cmd fe_sec_mini_cmd) |
1543 | { |
1544 | struct m88ds3103_dev *dev = fe->demodulator_priv; |
1545 | struct i2c_client *client = dev->client; |
1546 | int ret; |
1547 | unsigned int utmp, burst; |
1548 | unsigned long timeout; |
1549 | |
1550 | dev_dbg(&client->dev, "fe_sec_mini_cmd=%d\n" , fe_sec_mini_cmd); |
1551 | |
1552 | if (!dev->warm) { |
1553 | ret = -EAGAIN; |
1554 | goto err; |
1555 | } |
1556 | |
1557 | utmp = dev->cfg->envelope_mode << 5; |
1558 | ret = m88ds3103_update_bits(dev, reg: 0xa2, mask: 0xe0, val: utmp); |
1559 | if (ret) |
1560 | goto err; |
1561 | |
1562 | switch (fe_sec_mini_cmd) { |
1563 | case SEC_MINI_A: |
1564 | burst = 0x02; |
1565 | break; |
1566 | case SEC_MINI_B: |
1567 | burst = 0x01; |
1568 | break; |
1569 | default: |
1570 | dev_dbg(&client->dev, "invalid fe_sec_mini_cmd\n" ); |
1571 | ret = -EINVAL; |
1572 | goto err; |
1573 | } |
1574 | |
1575 | ret = regmap_write(map: dev->regmap, reg: 0xa1, val: burst); |
1576 | if (ret) |
1577 | goto err; |
1578 | |
1579 | /* wait DiSEqC TX ready */ |
1580 | #define SEND_BURST_TIMEOUT 40 |
1581 | timeout = jiffies + msecs_to_jiffies(SEND_BURST_TIMEOUT); |
1582 | |
1583 | /* DiSEqC ToneBurst period is 12.5 ms */ |
1584 | usleep_range(min: 8500, max: 12500); |
1585 | |
1586 | for (utmp = 1; !time_after(jiffies, timeout) && utmp;) { |
1587 | ret = regmap_read(map: dev->regmap, reg: 0xa1, val: &utmp); |
1588 | if (ret) |
1589 | goto err; |
1590 | utmp = (utmp >> 6) & 0x1; |
1591 | } |
1592 | |
1593 | if (utmp == 0) { |
1594 | dev_dbg(&client->dev, "diseqc tx took %u ms\n" , |
1595 | jiffies_to_msecs(jiffies) - |
1596 | (jiffies_to_msecs(timeout) - SEND_BURST_TIMEOUT)); |
1597 | } else { |
1598 | dev_dbg(&client->dev, "diseqc tx timeout\n" ); |
1599 | |
1600 | ret = m88ds3103_update_bits(dev, reg: 0xa1, mask: 0xc0, val: 0x40); |
1601 | if (ret) |
1602 | goto err; |
1603 | } |
1604 | |
1605 | ret = m88ds3103_update_bits(dev, reg: 0xa2, mask: 0xc0, val: 0x80); |
1606 | if (ret) |
1607 | goto err; |
1608 | |
1609 | if (utmp == 1) { |
1610 | ret = -ETIMEDOUT; |
1611 | goto err; |
1612 | } |
1613 | |
1614 | return 0; |
1615 | err: |
1616 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
1617 | return ret; |
1618 | } |
1619 | |
1620 | static int m88ds3103_get_tune_settings(struct dvb_frontend *fe, |
1621 | struct dvb_frontend_tune_settings *s) |
1622 | { |
1623 | s->min_delay_ms = 3000; |
1624 | |
1625 | return 0; |
1626 | } |
1627 | |
1628 | static void m88ds3103_release(struct dvb_frontend *fe) |
1629 | { |
1630 | struct m88ds3103_dev *dev = fe->demodulator_priv; |
1631 | struct i2c_client *client = dev->client; |
1632 | |
1633 | i2c_unregister_device(client); |
1634 | } |
1635 | |
1636 | static int m88ds3103_select(struct i2c_mux_core *muxc, u32 chan) |
1637 | { |
1638 | struct m88ds3103_dev *dev = i2c_mux_priv(muxc); |
1639 | struct i2c_client *client = dev->client; |
1640 | int ret; |
1641 | struct i2c_msg msg = { |
1642 | .addr = client->addr, |
1643 | .flags = 0, |
1644 | .len = 2, |
1645 | .buf = "\x03\x11" , |
1646 | }; |
1647 | |
1648 | /* Open tuner I2C repeater for 1 xfer, closes automatically */ |
1649 | ret = __i2c_transfer(adap: client->adapter, msgs: &msg, num: 1); |
1650 | if (ret != 1) { |
1651 | dev_warn(&client->dev, "i2c wr failed=%d\n" , ret); |
1652 | if (ret >= 0) |
1653 | ret = -EREMOTEIO; |
1654 | return ret; |
1655 | } |
1656 | |
1657 | return 0; |
1658 | } |
1659 | |
1660 | /* |
1661 | * XXX: That is wrapper to m88ds3103_probe() via driver core in order to provide |
1662 | * proper I2C client for legacy media attach binding. |
1663 | * New users must use I2C client binding directly! |
1664 | */ |
1665 | struct dvb_frontend *m88ds3103_attach(const struct m88ds3103_config *cfg, |
1666 | struct i2c_adapter *i2c, |
1667 | struct i2c_adapter **tuner_i2c_adapter) |
1668 | { |
1669 | struct i2c_client *client; |
1670 | struct i2c_board_info board_info; |
1671 | struct m88ds3103_platform_data pdata = {}; |
1672 | |
1673 | pdata.clk = cfg->clock; |
1674 | pdata.i2c_wr_max = cfg->i2c_wr_max; |
1675 | pdata.ts_mode = cfg->ts_mode; |
1676 | pdata.ts_clk = cfg->ts_clk; |
1677 | pdata.ts_clk_pol = cfg->ts_clk_pol; |
1678 | pdata.spec_inv = cfg->spec_inv; |
1679 | pdata.agc = cfg->agc; |
1680 | pdata.agc_inv = cfg->agc_inv; |
1681 | pdata.clk_out = cfg->clock_out; |
1682 | pdata.envelope_mode = cfg->envelope_mode; |
1683 | pdata.lnb_hv_pol = cfg->lnb_hv_pol; |
1684 | pdata.lnb_en_pol = cfg->lnb_en_pol; |
1685 | pdata.attach_in_use = true; |
1686 | |
1687 | memset(&board_info, 0, sizeof(board_info)); |
1688 | strscpy(p: board_info.type, q: "m88ds3103" , I2C_NAME_SIZE); |
1689 | board_info.addr = cfg->i2c_addr; |
1690 | board_info.platform_data = &pdata; |
1691 | client = i2c_new_client_device(adap: i2c, info: &board_info); |
1692 | if (!i2c_client_has_driver(client)) |
1693 | return NULL; |
1694 | |
1695 | *tuner_i2c_adapter = pdata.get_i2c_adapter(client); |
1696 | return pdata.get_dvb_frontend(client); |
1697 | } |
1698 | EXPORT_SYMBOL_GPL(m88ds3103_attach); |
1699 | |
1700 | static const struct dvb_frontend_ops m88ds3103_ops = { |
1701 | .delsys = {SYS_DVBS, SYS_DVBS2}, |
1702 | .info = { |
1703 | .name = "Montage Technology M88DS3103" , |
1704 | .frequency_min_hz = 950 * MHz, |
1705 | .frequency_max_hz = 2150 * MHz, |
1706 | .frequency_tolerance_hz = 5 * MHz, |
1707 | .symbol_rate_min = 1000000, |
1708 | .symbol_rate_max = 45000000, |
1709 | .caps = FE_CAN_INVERSION_AUTO | |
1710 | FE_CAN_FEC_1_2 | |
1711 | FE_CAN_FEC_2_3 | |
1712 | FE_CAN_FEC_3_4 | |
1713 | FE_CAN_FEC_4_5 | |
1714 | FE_CAN_FEC_5_6 | |
1715 | FE_CAN_FEC_6_7 | |
1716 | FE_CAN_FEC_7_8 | |
1717 | FE_CAN_FEC_8_9 | |
1718 | FE_CAN_FEC_AUTO | |
1719 | FE_CAN_QPSK | |
1720 | FE_CAN_RECOVER | |
1721 | FE_CAN_2G_MODULATION |
1722 | }, |
1723 | |
1724 | .release = m88ds3103_release, |
1725 | |
1726 | .get_tune_settings = m88ds3103_get_tune_settings, |
1727 | |
1728 | .init = m88ds3103_init, |
1729 | .sleep = m88ds3103_sleep, |
1730 | |
1731 | .set_frontend = m88ds3103_set_frontend, |
1732 | .get_frontend = m88ds3103_get_frontend, |
1733 | |
1734 | .read_status = m88ds3103_read_status, |
1735 | .read_snr = m88ds3103_read_snr, |
1736 | .read_ber = m88ds3103_read_ber, |
1737 | |
1738 | .diseqc_send_master_cmd = m88ds3103_diseqc_send_master_cmd, |
1739 | .diseqc_send_burst = m88ds3103_diseqc_send_burst, |
1740 | |
1741 | .set_tone = m88ds3103_set_tone, |
1742 | .set_voltage = m88ds3103_set_voltage, |
1743 | }; |
1744 | |
1745 | static struct dvb_frontend *m88ds3103_get_dvb_frontend(struct i2c_client *client) |
1746 | { |
1747 | struct m88ds3103_dev *dev = i2c_get_clientdata(client); |
1748 | |
1749 | dev_dbg(&client->dev, "\n" ); |
1750 | |
1751 | return &dev->fe; |
1752 | } |
1753 | |
1754 | static struct i2c_adapter *m88ds3103_get_i2c_adapter(struct i2c_client *client) |
1755 | { |
1756 | struct m88ds3103_dev *dev = i2c_get_clientdata(client); |
1757 | |
1758 | dev_dbg(&client->dev, "\n" ); |
1759 | |
1760 | return dev->muxc->adapter[0]; |
1761 | } |
1762 | |
1763 | static int m88ds3103_probe(struct i2c_client *client) |
1764 | { |
1765 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
1766 | struct m88ds3103_dev *dev; |
1767 | struct m88ds3103_platform_data *pdata = client->dev.platform_data; |
1768 | int ret; |
1769 | unsigned int utmp; |
1770 | |
1771 | dev = kzalloc(size: sizeof(*dev), GFP_KERNEL); |
1772 | if (!dev) { |
1773 | ret = -ENOMEM; |
1774 | goto err; |
1775 | } |
1776 | |
1777 | dev->client = client; |
1778 | dev->config.clock = pdata->clk; |
1779 | dev->config.i2c_wr_max = pdata->i2c_wr_max; |
1780 | dev->config.ts_mode = pdata->ts_mode; |
1781 | dev->config.ts_clk = pdata->ts_clk * 1000; |
1782 | dev->config.ts_clk_pol = pdata->ts_clk_pol; |
1783 | dev->config.spec_inv = pdata->spec_inv; |
1784 | dev->config.agc_inv = pdata->agc_inv; |
1785 | dev->config.clock_out = pdata->clk_out; |
1786 | dev->config.envelope_mode = pdata->envelope_mode; |
1787 | dev->config.agc = pdata->agc; |
1788 | dev->config.lnb_hv_pol = pdata->lnb_hv_pol; |
1789 | dev->config.lnb_en_pol = pdata->lnb_en_pol; |
1790 | dev->cfg = &dev->config; |
1791 | /* create regmap */ |
1792 | dev->regmap_config.reg_bits = 8; |
1793 | dev->regmap_config.val_bits = 8; |
1794 | dev->regmap_config.lock_arg = dev; |
1795 | dev->regmap = devm_regmap_init_i2c(client, &dev->regmap_config); |
1796 | if (IS_ERR(ptr: dev->regmap)) { |
1797 | ret = PTR_ERR(ptr: dev->regmap); |
1798 | goto err_kfree; |
1799 | } |
1800 | |
1801 | /* 0x00: chip id[6:0], 0x01: chip ver[7:0], 0x02: chip ver[15:8] */ |
1802 | ret = regmap_read(map: dev->regmap, reg: 0x00, val: &utmp); |
1803 | if (ret) |
1804 | goto err_kfree; |
1805 | |
1806 | dev->chip_id = utmp >> 1; |
1807 | dev->chiptype = (u8)id->driver_data; |
1808 | |
1809 | dev_dbg(&client->dev, "chip_id=%02x\n" , dev->chip_id); |
1810 | |
1811 | switch (dev->chip_id) { |
1812 | case M88RS6000_CHIP_ID: |
1813 | case M88DS3103_CHIP_ID: |
1814 | break; |
1815 | default: |
1816 | ret = -ENODEV; |
1817 | dev_err(&client->dev, "Unknown device. Chip_id=%02x\n" , dev->chip_id); |
1818 | goto err_kfree; |
1819 | } |
1820 | |
1821 | switch (dev->cfg->clock_out) { |
1822 | case M88DS3103_CLOCK_OUT_DISABLED: |
1823 | utmp = 0x80; |
1824 | break; |
1825 | case M88DS3103_CLOCK_OUT_ENABLED: |
1826 | utmp = 0x00; |
1827 | break; |
1828 | case M88DS3103_CLOCK_OUT_ENABLED_DIV2: |
1829 | utmp = 0x10; |
1830 | break; |
1831 | default: |
1832 | ret = -EINVAL; |
1833 | goto err_kfree; |
1834 | } |
1835 | |
1836 | if (!pdata->ts_clk) { |
1837 | ret = -EINVAL; |
1838 | goto err_kfree; |
1839 | } |
1840 | |
1841 | /* 0x29 register is defined differently for m88rs6000. */ |
1842 | /* set internal tuner address to 0x21 */ |
1843 | if (dev->chip_id == M88RS6000_CHIP_ID) |
1844 | utmp = 0x00; |
1845 | |
1846 | ret = regmap_write(map: dev->regmap, reg: 0x29, val: utmp); |
1847 | if (ret) |
1848 | goto err_kfree; |
1849 | |
1850 | /* sleep */ |
1851 | ret = m88ds3103_update_bits(dev, reg: 0x08, mask: 0x01, val: 0x00); |
1852 | if (ret) |
1853 | goto err_kfree; |
1854 | ret = m88ds3103_update_bits(dev, reg: 0x04, mask: 0x01, val: 0x01); |
1855 | if (ret) |
1856 | goto err_kfree; |
1857 | ret = m88ds3103_update_bits(dev, reg: 0x23, mask: 0x10, val: 0x10); |
1858 | if (ret) |
1859 | goto err_kfree; |
1860 | |
1861 | /* create mux i2c adapter for tuner */ |
1862 | dev->muxc = i2c_mux_alloc(parent: client->adapter, dev: &client->dev, max_adapters: 1, sizeof_priv: 0, flags: 0, |
1863 | select: m88ds3103_select, NULL); |
1864 | if (!dev->muxc) { |
1865 | ret = -ENOMEM; |
1866 | goto err_kfree; |
1867 | } |
1868 | dev->muxc->priv = dev; |
1869 | ret = i2c_mux_add_adapter(muxc: dev->muxc, force_nr: 0, chan_id: 0, class: 0); |
1870 | if (ret) |
1871 | goto err_kfree; |
1872 | |
1873 | /* create dvb_frontend */ |
1874 | memcpy(&dev->fe.ops, &m88ds3103_ops, sizeof(struct dvb_frontend_ops)); |
1875 | if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) |
1876 | strscpy(p: dev->fe.ops.info.name, q: "Montage Technology M88DS3103B" , |
1877 | size: sizeof(dev->fe.ops.info.name)); |
1878 | else if (dev->chip_id == M88RS6000_CHIP_ID) |
1879 | strscpy(p: dev->fe.ops.info.name, q: "Montage Technology M88RS6000" , |
1880 | size: sizeof(dev->fe.ops.info.name)); |
1881 | if (!pdata->attach_in_use) |
1882 | dev->fe.ops.release = NULL; |
1883 | dev->fe.demodulator_priv = dev; |
1884 | i2c_set_clientdata(client, data: dev); |
1885 | |
1886 | /* setup callbacks */ |
1887 | pdata->get_dvb_frontend = m88ds3103_get_dvb_frontend; |
1888 | pdata->get_i2c_adapter = m88ds3103_get_i2c_adapter; |
1889 | |
1890 | if (dev->chiptype == M88DS3103_CHIPTYPE_3103B) { |
1891 | /* enable i2c repeater for tuner */ |
1892 | m88ds3103_update_bits(dev, reg: 0x11, mask: 0x01, val: 0x01); |
1893 | |
1894 | /* get frontend address */ |
1895 | ret = regmap_read(map: dev->regmap, reg: 0x29, val: &utmp); |
1896 | if (ret) |
1897 | goto err_kfree; |
1898 | dev->dt_addr = ((utmp & 0x80) == 0) ? 0x42 >> 1 : 0x40 >> 1; |
1899 | dev_dbg(&client->dev, "dt addr is 0x%02x\n" , dev->dt_addr); |
1900 | |
1901 | dev->dt_client = i2c_new_dummy_device(adapter: client->adapter, |
1902 | address: dev->dt_addr); |
1903 | if (IS_ERR(ptr: dev->dt_client)) { |
1904 | ret = PTR_ERR(ptr: dev->dt_client); |
1905 | goto err_kfree; |
1906 | } |
1907 | } |
1908 | |
1909 | return 0; |
1910 | err_kfree: |
1911 | kfree(objp: dev); |
1912 | err: |
1913 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
1914 | return ret; |
1915 | } |
1916 | |
1917 | static void m88ds3103_remove(struct i2c_client *client) |
1918 | { |
1919 | struct m88ds3103_dev *dev = i2c_get_clientdata(client); |
1920 | |
1921 | dev_dbg(&client->dev, "\n" ); |
1922 | |
1923 | i2c_unregister_device(client: dev->dt_client); |
1924 | |
1925 | i2c_mux_del_adapters(muxc: dev->muxc); |
1926 | |
1927 | kfree(objp: dev); |
1928 | } |
1929 | |
1930 | static const struct i2c_device_id m88ds3103_id_table[] = { |
1931 | {"m88ds3103" , M88DS3103_CHIPTYPE_3103}, |
1932 | {"m88rs6000" , M88DS3103_CHIPTYPE_RS6000}, |
1933 | {"m88ds3103b" , M88DS3103_CHIPTYPE_3103B}, |
1934 | {} |
1935 | }; |
1936 | MODULE_DEVICE_TABLE(i2c, m88ds3103_id_table); |
1937 | |
1938 | static struct i2c_driver m88ds3103_driver = { |
1939 | .driver = { |
1940 | .name = "m88ds3103" , |
1941 | .suppress_bind_attrs = true, |
1942 | }, |
1943 | .probe = m88ds3103_probe, |
1944 | .remove = m88ds3103_remove, |
1945 | .id_table = m88ds3103_id_table, |
1946 | }; |
1947 | |
1948 | module_i2c_driver(m88ds3103_driver); |
1949 | |
1950 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>" ); |
1951 | MODULE_DESCRIPTION("Montage Technology M88DS3103 DVB-S/S2 demodulator driver" ); |
1952 | MODULE_LICENSE("GPL" ); |
1953 | MODULE_FIRMWARE(M88DS3103_FIRMWARE); |
1954 | MODULE_FIRMWARE(M88RS6000_FIRMWARE); |
1955 | MODULE_FIRMWARE(M88DS3103B_FIRMWARE); |
1956 | |