1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Realtek RTL2830 DVB-T demodulator driver |
4 | * |
5 | * Copyright (C) 2011 Antti Palosaari <crope@iki.fi> |
6 | */ |
7 | |
8 | #include "rtl2830_priv.h" |
9 | |
10 | /* Our regmap is bypassing I2C adapter lock, thus we do it! */ |
11 | static int rtl2830_bulk_write(struct i2c_client *client, unsigned int reg, |
12 | const void *val, size_t val_count) |
13 | { |
14 | struct rtl2830_dev *dev = i2c_get_clientdata(client); |
15 | int ret; |
16 | |
17 | i2c_lock_bus(adapter: client->adapter, I2C_LOCK_SEGMENT); |
18 | ret = regmap_bulk_write(map: dev->regmap, reg, val, val_count); |
19 | i2c_unlock_bus(adapter: client->adapter, I2C_LOCK_SEGMENT); |
20 | return ret; |
21 | } |
22 | |
23 | static int rtl2830_update_bits(struct i2c_client *client, unsigned int reg, |
24 | unsigned int mask, unsigned int val) |
25 | { |
26 | struct rtl2830_dev *dev = i2c_get_clientdata(client); |
27 | int ret; |
28 | |
29 | i2c_lock_bus(adapter: client->adapter, I2C_LOCK_SEGMENT); |
30 | ret = regmap_update_bits(map: dev->regmap, reg, mask, val); |
31 | i2c_unlock_bus(adapter: client->adapter, I2C_LOCK_SEGMENT); |
32 | return ret; |
33 | } |
34 | |
35 | static int rtl2830_bulk_read(struct i2c_client *client, unsigned int reg, |
36 | void *val, size_t val_count) |
37 | { |
38 | struct rtl2830_dev *dev = i2c_get_clientdata(client); |
39 | int ret; |
40 | |
41 | i2c_lock_bus(adapter: client->adapter, I2C_LOCK_SEGMENT); |
42 | ret = regmap_bulk_read(map: dev->regmap, reg, val, val_count); |
43 | i2c_unlock_bus(adapter: client->adapter, I2C_LOCK_SEGMENT); |
44 | return ret; |
45 | } |
46 | |
47 | static int rtl2830_init(struct dvb_frontend *fe) |
48 | { |
49 | struct i2c_client *client = fe->demodulator_priv; |
50 | struct rtl2830_dev *dev = i2c_get_clientdata(client); |
51 | struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; |
52 | int ret, i; |
53 | struct rtl2830_reg_val_mask tab[] = { |
54 | {.reg: 0x00d, .val: 0x01, .mask: 0x03}, |
55 | {0x00d, 0x10, 0x10}, |
56 | {0x104, 0x00, 0x1e}, |
57 | {0x105, 0x80, 0x80}, |
58 | {0x110, 0x02, 0x03}, |
59 | {0x110, 0x08, 0x0c}, |
60 | {0x17b, 0x00, 0x40}, |
61 | {0x17d, 0x05, 0x0f}, |
62 | {0x17d, 0x50, 0xf0}, |
63 | {0x18c, 0x08, 0x0f}, |
64 | {0x18d, 0x00, 0xc0}, |
65 | {0x188, 0x05, 0x0f}, |
66 | {0x189, 0x00, 0xfc}, |
67 | {0x2d5, 0x02, 0x02}, |
68 | {0x2f1, 0x02, 0x06}, |
69 | {0x2f1, 0x20, 0xf8}, |
70 | {0x16d, 0x00, 0x01}, |
71 | {0x1a6, 0x00, 0x80}, |
72 | {0x106, dev->pdata->vtop, 0x3f}, |
73 | {0x107, dev->pdata->krf, 0x3f}, |
74 | {0x112, 0x28, 0xff}, |
75 | {0x103, dev->pdata->agc_targ_val, 0xff}, |
76 | {0x00a, 0x02, 0x07}, |
77 | {0x140, 0x0c, 0x3c}, |
78 | {0x140, 0x40, 0xc0}, |
79 | {0x15b, 0x05, 0x07}, |
80 | {0x15b, 0x28, 0x38}, |
81 | {0x15c, 0x05, 0x07}, |
82 | {0x15c, 0x28, 0x38}, |
83 | {0x115, dev->pdata->spec_inv, 0x01}, |
84 | {0x16f, 0x01, 0x07}, |
85 | {0x170, 0x18, 0x38}, |
86 | {0x172, 0x0f, 0x0f}, |
87 | {0x173, 0x08, 0x38}, |
88 | {0x175, 0x01, 0x07}, |
89 | {0x176, 0x00, 0xc0}, |
90 | }; |
91 | |
92 | for (i = 0; i < ARRAY_SIZE(tab); i++) { |
93 | ret = rtl2830_update_bits(client, reg: tab[i].reg, mask: tab[i].mask, |
94 | val: tab[i].val); |
95 | if (ret) |
96 | goto err; |
97 | } |
98 | |
99 | ret = rtl2830_bulk_write(client, reg: 0x18f, val: "\x28\x00" , val_count: 2); |
100 | if (ret) |
101 | goto err; |
102 | |
103 | ret = rtl2830_bulk_write(client, reg: 0x195, |
104 | val: "\x04\x06\x0a\x12\x0a\x12\x1e\x28" , val_count: 8); |
105 | if (ret) |
106 | goto err; |
107 | |
108 | /* TODO: spec init */ |
109 | |
110 | /* soft reset */ |
111 | ret = rtl2830_update_bits(client, reg: 0x101, mask: 0x04, val: 0x04); |
112 | if (ret) |
113 | goto err; |
114 | |
115 | ret = rtl2830_update_bits(client, reg: 0x101, mask: 0x04, val: 0x00); |
116 | if (ret) |
117 | goto err; |
118 | |
119 | /* init stats here in order signal app which stats are supported */ |
120 | c->strength.len = 1; |
121 | c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
122 | c->cnr.len = 1; |
123 | c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
124 | c->post_bit_error.len = 1; |
125 | c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
126 | c->post_bit_count.len = 1; |
127 | c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
128 | |
129 | dev->sleeping = false; |
130 | |
131 | return ret; |
132 | err: |
133 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
134 | return ret; |
135 | } |
136 | |
137 | static int rtl2830_sleep(struct dvb_frontend *fe) |
138 | { |
139 | struct i2c_client *client = fe->demodulator_priv; |
140 | struct rtl2830_dev *dev = i2c_get_clientdata(client); |
141 | |
142 | dev->sleeping = true; |
143 | dev->fe_status = 0; |
144 | |
145 | return 0; |
146 | } |
147 | |
148 | static int rtl2830_get_tune_settings(struct dvb_frontend *fe, |
149 | struct dvb_frontend_tune_settings *s) |
150 | { |
151 | s->min_delay_ms = 500; |
152 | s->step_size = fe->ops.info.frequency_stepsize_hz * 2; |
153 | s->max_drift = (fe->ops.info.frequency_stepsize_hz * 2) + 1; |
154 | |
155 | return 0; |
156 | } |
157 | |
158 | static int rtl2830_set_frontend(struct dvb_frontend *fe) |
159 | { |
160 | struct i2c_client *client = fe->demodulator_priv; |
161 | struct rtl2830_dev *dev = i2c_get_clientdata(client); |
162 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
163 | int ret, i; |
164 | u64 num; |
165 | u8 buf[3], u8tmp; |
166 | u32 if_ctl, if_frequency; |
167 | static const u8 bw_params1[3][34] = { |
168 | { |
169 | 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41, |
170 | 0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a, |
171 | 0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82, |
172 | 0x03, 0x73, 0x03, 0xcf, /* 6 MHz */ |
173 | }, { |
174 | 0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca, |
175 | 0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca, |
176 | 0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e, |
177 | 0x03, 0xd0, 0x04, 0x53, /* 7 MHz */ |
178 | }, { |
179 | 0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0, |
180 | 0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a, |
181 | 0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f, |
182 | 0x04, 0x24, 0x04, 0xdb, /* 8 MHz */ |
183 | }, |
184 | }; |
185 | static const u8 bw_params2[3][6] = { |
186 | {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30}, /* 6 MHz */ |
187 | {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98}, /* 7 MHz */ |
188 | {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64}, /* 8 MHz */ |
189 | }; |
190 | |
191 | dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u inversion=%u\n" , |
192 | c->frequency, c->bandwidth_hz, c->inversion); |
193 | |
194 | /* program tuner */ |
195 | if (fe->ops.tuner_ops.set_params) |
196 | fe->ops.tuner_ops.set_params(fe); |
197 | |
198 | switch (c->bandwidth_hz) { |
199 | case 6000000: |
200 | i = 0; |
201 | break; |
202 | case 7000000: |
203 | i = 1; |
204 | break; |
205 | case 8000000: |
206 | i = 2; |
207 | break; |
208 | default: |
209 | dev_err(&client->dev, "invalid bandwidth_hz %u\n" , |
210 | c->bandwidth_hz); |
211 | return -EINVAL; |
212 | } |
213 | |
214 | ret = rtl2830_update_bits(client, reg: 0x008, mask: 0x06, val: i << 1); |
215 | if (ret) |
216 | goto err; |
217 | |
218 | /* program if frequency */ |
219 | if (fe->ops.tuner_ops.get_if_frequency) |
220 | ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency); |
221 | else |
222 | ret = -EINVAL; |
223 | if (ret) |
224 | goto err; |
225 | |
226 | num = if_frequency % dev->pdata->clk; |
227 | num *= 0x400000; |
228 | num = div_u64(dividend: num, divisor: dev->pdata->clk); |
229 | num = -num; |
230 | if_ctl = num & 0x3fffff; |
231 | dev_dbg(&client->dev, "if_frequency=%d if_ctl=%08x\n" , |
232 | if_frequency, if_ctl); |
233 | |
234 | buf[0] = (if_ctl >> 16) & 0x3f; |
235 | buf[1] = (if_ctl >> 8) & 0xff; |
236 | buf[2] = (if_ctl >> 0) & 0xff; |
237 | |
238 | ret = rtl2830_bulk_read(client, reg: 0x119, val: &u8tmp, val_count: 1); |
239 | if (ret) |
240 | goto err; |
241 | |
242 | buf[0] |= u8tmp & 0xc0; /* [7:6] */ |
243 | |
244 | ret = rtl2830_bulk_write(client, reg: 0x119, val: buf, val_count: 3); |
245 | if (ret) |
246 | goto err; |
247 | |
248 | /* 1/2 split I2C write */ |
249 | ret = rtl2830_bulk_write(client, reg: 0x11c, val: &bw_params1[i][0], val_count: 17); |
250 | if (ret) |
251 | goto err; |
252 | |
253 | /* 2/2 split I2C write */ |
254 | ret = rtl2830_bulk_write(client, reg: 0x12d, val: &bw_params1[i][17], val_count: 17); |
255 | if (ret) |
256 | goto err; |
257 | |
258 | ret = rtl2830_bulk_write(client, reg: 0x19d, val: bw_params2[i], val_count: 6); |
259 | if (ret) |
260 | goto err; |
261 | |
262 | return ret; |
263 | err: |
264 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
265 | return ret; |
266 | } |
267 | |
268 | static int rtl2830_get_frontend(struct dvb_frontend *fe, |
269 | struct dtv_frontend_properties *c) |
270 | { |
271 | struct i2c_client *client = fe->demodulator_priv; |
272 | struct rtl2830_dev *dev = i2c_get_clientdata(client); |
273 | int ret; |
274 | u8 buf[3]; |
275 | |
276 | if (dev->sleeping) |
277 | return 0; |
278 | |
279 | ret = rtl2830_bulk_read(client, reg: 0x33c, val: buf, val_count: 2); |
280 | if (ret) |
281 | goto err; |
282 | |
283 | ret = rtl2830_bulk_read(client, reg: 0x351, val: &buf[2], val_count: 1); |
284 | if (ret) |
285 | goto err; |
286 | |
287 | dev_dbg(&client->dev, "TPS=%*ph\n" , 3, buf); |
288 | |
289 | switch ((buf[0] >> 2) & 3) { |
290 | case 0: |
291 | c->modulation = QPSK; |
292 | break; |
293 | case 1: |
294 | c->modulation = QAM_16; |
295 | break; |
296 | case 2: |
297 | c->modulation = QAM_64; |
298 | break; |
299 | } |
300 | |
301 | switch ((buf[2] >> 2) & 1) { |
302 | case 0: |
303 | c->transmission_mode = TRANSMISSION_MODE_2K; |
304 | break; |
305 | case 1: |
306 | c->transmission_mode = TRANSMISSION_MODE_8K; |
307 | } |
308 | |
309 | switch ((buf[2] >> 0) & 3) { |
310 | case 0: |
311 | c->guard_interval = GUARD_INTERVAL_1_32; |
312 | break; |
313 | case 1: |
314 | c->guard_interval = GUARD_INTERVAL_1_16; |
315 | break; |
316 | case 2: |
317 | c->guard_interval = GUARD_INTERVAL_1_8; |
318 | break; |
319 | case 3: |
320 | c->guard_interval = GUARD_INTERVAL_1_4; |
321 | break; |
322 | } |
323 | |
324 | switch ((buf[0] >> 4) & 7) { |
325 | case 0: |
326 | c->hierarchy = HIERARCHY_NONE; |
327 | break; |
328 | case 1: |
329 | c->hierarchy = HIERARCHY_1; |
330 | break; |
331 | case 2: |
332 | c->hierarchy = HIERARCHY_2; |
333 | break; |
334 | case 3: |
335 | c->hierarchy = HIERARCHY_4; |
336 | break; |
337 | } |
338 | |
339 | switch ((buf[1] >> 3) & 7) { |
340 | case 0: |
341 | c->code_rate_HP = FEC_1_2; |
342 | break; |
343 | case 1: |
344 | c->code_rate_HP = FEC_2_3; |
345 | break; |
346 | case 2: |
347 | c->code_rate_HP = FEC_3_4; |
348 | break; |
349 | case 3: |
350 | c->code_rate_HP = FEC_5_6; |
351 | break; |
352 | case 4: |
353 | c->code_rate_HP = FEC_7_8; |
354 | break; |
355 | } |
356 | |
357 | switch ((buf[1] >> 0) & 7) { |
358 | case 0: |
359 | c->code_rate_LP = FEC_1_2; |
360 | break; |
361 | case 1: |
362 | c->code_rate_LP = FEC_2_3; |
363 | break; |
364 | case 2: |
365 | c->code_rate_LP = FEC_3_4; |
366 | break; |
367 | case 3: |
368 | c->code_rate_LP = FEC_5_6; |
369 | break; |
370 | case 4: |
371 | c->code_rate_LP = FEC_7_8; |
372 | break; |
373 | } |
374 | |
375 | return 0; |
376 | err: |
377 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
378 | return ret; |
379 | } |
380 | |
381 | static int rtl2830_read_status(struct dvb_frontend *fe, enum fe_status *status) |
382 | { |
383 | struct i2c_client *client = fe->demodulator_priv; |
384 | struct rtl2830_dev *dev = i2c_get_clientdata(client); |
385 | struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache; |
386 | int ret, stmp; |
387 | unsigned int utmp; |
388 | u8 u8tmp, buf[2]; |
389 | |
390 | *status = 0; |
391 | |
392 | if (dev->sleeping) |
393 | return 0; |
394 | |
395 | ret = rtl2830_bulk_read(client, reg: 0x351, val: &u8tmp, val_count: 1); |
396 | if (ret) |
397 | goto err; |
398 | |
399 | u8tmp = (u8tmp >> 3) & 0x0f; /* [6:3] */ |
400 | if (u8tmp == 11) { |
401 | *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | |
402 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; |
403 | } else if (u8tmp == 10) { |
404 | *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | |
405 | FE_HAS_VITERBI; |
406 | } |
407 | |
408 | dev->fe_status = *status; |
409 | |
410 | /* Signal strength */ |
411 | if (dev->fe_status & FE_HAS_SIGNAL) { |
412 | /* Read IF AGC */ |
413 | ret = rtl2830_bulk_read(client, reg: 0x359, val: buf, val_count: 2); |
414 | if (ret) |
415 | goto err; |
416 | |
417 | stmp = buf[0] << 8 | buf[1] << 0; |
418 | stmp = sign_extend32(value: stmp, index: 13); |
419 | utmp = clamp_val(-4 * stmp + 32767, 0x0000, 0xffff); |
420 | |
421 | dev_dbg(&client->dev, "IF AGC=%d\n" , stmp); |
422 | |
423 | c->strength.stat[0].scale = FE_SCALE_RELATIVE; |
424 | c->strength.stat[0].uvalue = utmp; |
425 | } else { |
426 | c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
427 | } |
428 | |
429 | /* CNR */ |
430 | if (dev->fe_status & FE_HAS_VITERBI) { |
431 | unsigned int hierarchy, constellation; |
432 | #define CONSTELLATION_NUM 3 |
433 | #define HIERARCHY_NUM 4 |
434 | static const u32 constant[CONSTELLATION_NUM][HIERARCHY_NUM] = { |
435 | {70705899, 70705899, 70705899, 70705899}, |
436 | {82433173, 82433173, 87483115, 94445660}, |
437 | {92888734, 92888734, 95487525, 99770748}, |
438 | }; |
439 | |
440 | ret = rtl2830_bulk_read(client, reg: 0x33c, val: &u8tmp, val_count: 1); |
441 | if (ret) |
442 | goto err; |
443 | |
444 | constellation = (u8tmp >> 2) & 0x03; /* [3:2] */ |
445 | if (constellation > CONSTELLATION_NUM - 1) |
446 | goto err; |
447 | |
448 | hierarchy = (u8tmp >> 4) & 0x07; /* [6:4] */ |
449 | if (hierarchy > HIERARCHY_NUM - 1) |
450 | goto err; |
451 | |
452 | ret = rtl2830_bulk_read(client, reg: 0x40c, val: buf, val_count: 2); |
453 | if (ret) |
454 | goto err; |
455 | |
456 | utmp = buf[0] << 8 | buf[1] << 0; |
457 | if (utmp) |
458 | stmp = (constant[constellation][hierarchy] - |
459 | intlog10(value: utmp)) / ((1 << 24) / 10000); |
460 | else |
461 | stmp = 0; |
462 | |
463 | dev_dbg(&client->dev, "CNR raw=%u\n" , utmp); |
464 | |
465 | c->cnr.stat[0].scale = FE_SCALE_DECIBEL; |
466 | c->cnr.stat[0].svalue = stmp; |
467 | } else { |
468 | c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
469 | } |
470 | |
471 | /* BER */ |
472 | if (dev->fe_status & FE_HAS_LOCK) { |
473 | ret = rtl2830_bulk_read(client, reg: 0x34e, val: buf, val_count: 2); |
474 | if (ret) |
475 | goto err; |
476 | |
477 | utmp = buf[0] << 8 | buf[1] << 0; |
478 | dev->post_bit_error += utmp; |
479 | dev->post_bit_count += 1000000; |
480 | |
481 | dev_dbg(&client->dev, "BER errors=%u total=1000000\n" , utmp); |
482 | |
483 | c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; |
484 | c->post_bit_error.stat[0].uvalue = dev->post_bit_error; |
485 | c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; |
486 | c->post_bit_count.stat[0].uvalue = dev->post_bit_count; |
487 | } else { |
488 | c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
489 | c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
490 | } |
491 | |
492 | |
493 | return ret; |
494 | err: |
495 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
496 | return ret; |
497 | } |
498 | |
499 | static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) |
500 | { |
501 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
502 | |
503 | if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL) |
504 | *snr = div_s64(dividend: c->cnr.stat[0].svalue, divisor: 100); |
505 | else |
506 | *snr = 0; |
507 | |
508 | return 0; |
509 | } |
510 | |
511 | static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber) |
512 | { |
513 | struct i2c_client *client = fe->demodulator_priv; |
514 | struct rtl2830_dev *dev = i2c_get_clientdata(client); |
515 | |
516 | *ber = (dev->post_bit_error - dev->post_bit_error_prev); |
517 | dev->post_bit_error_prev = dev->post_bit_error; |
518 | |
519 | return 0; |
520 | } |
521 | |
522 | static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) |
523 | { |
524 | *ucblocks = 0; |
525 | |
526 | return 0; |
527 | } |
528 | |
529 | static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength) |
530 | { |
531 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
532 | |
533 | if (c->strength.stat[0].scale == FE_SCALE_RELATIVE) |
534 | *strength = c->strength.stat[0].uvalue; |
535 | else |
536 | *strength = 0; |
537 | |
538 | return 0; |
539 | } |
540 | |
541 | static const struct dvb_frontend_ops rtl2830_ops = { |
542 | .delsys = {SYS_DVBT}, |
543 | .info = { |
544 | .name = "Realtek RTL2830 (DVB-T)" , |
545 | .caps = FE_CAN_FEC_1_2 | |
546 | FE_CAN_FEC_2_3 | |
547 | FE_CAN_FEC_3_4 | |
548 | FE_CAN_FEC_5_6 | |
549 | FE_CAN_FEC_7_8 | |
550 | FE_CAN_FEC_AUTO | |
551 | FE_CAN_QPSK | |
552 | FE_CAN_QAM_16 | |
553 | FE_CAN_QAM_64 | |
554 | FE_CAN_QAM_AUTO | |
555 | FE_CAN_TRANSMISSION_MODE_AUTO | |
556 | FE_CAN_GUARD_INTERVAL_AUTO | |
557 | FE_CAN_HIERARCHY_AUTO | |
558 | FE_CAN_RECOVER | |
559 | FE_CAN_MUTE_TS |
560 | }, |
561 | |
562 | .init = rtl2830_init, |
563 | .sleep = rtl2830_sleep, |
564 | |
565 | .get_tune_settings = rtl2830_get_tune_settings, |
566 | |
567 | .set_frontend = rtl2830_set_frontend, |
568 | .get_frontend = rtl2830_get_frontend, |
569 | |
570 | .read_status = rtl2830_read_status, |
571 | .read_snr = rtl2830_read_snr, |
572 | .read_ber = rtl2830_read_ber, |
573 | .read_ucblocks = rtl2830_read_ucblocks, |
574 | .read_signal_strength = rtl2830_read_signal_strength, |
575 | }; |
576 | |
577 | static int rtl2830_pid_filter_ctrl(struct dvb_frontend *fe, int onoff) |
578 | { |
579 | struct i2c_client *client = fe->demodulator_priv; |
580 | int ret; |
581 | u8 u8tmp; |
582 | |
583 | dev_dbg(&client->dev, "onoff=%d\n" , onoff); |
584 | |
585 | /* enable / disable PID filter */ |
586 | if (onoff) |
587 | u8tmp = 0x80; |
588 | else |
589 | u8tmp = 0x00; |
590 | |
591 | ret = rtl2830_update_bits(client, reg: 0x061, mask: 0x80, val: u8tmp); |
592 | if (ret) |
593 | goto err; |
594 | |
595 | return 0; |
596 | err: |
597 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
598 | return ret; |
599 | } |
600 | |
601 | static int rtl2830_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid, int onoff) |
602 | { |
603 | struct i2c_client *client = fe->demodulator_priv; |
604 | struct rtl2830_dev *dev = i2c_get_clientdata(client); |
605 | int ret; |
606 | u8 buf[4]; |
607 | |
608 | dev_dbg(&client->dev, "index=%d pid=%04x onoff=%d\n" , |
609 | index, pid, onoff); |
610 | |
611 | /* skip invalid PIDs (0x2000) */ |
612 | if (pid > 0x1fff || index > 32) |
613 | return 0; |
614 | |
615 | if (onoff) |
616 | set_bit(nr: index, addr: &dev->filters); |
617 | else |
618 | clear_bit(nr: index, addr: &dev->filters); |
619 | |
620 | /* enable / disable PIDs */ |
621 | buf[0] = (dev->filters >> 0) & 0xff; |
622 | buf[1] = (dev->filters >> 8) & 0xff; |
623 | buf[2] = (dev->filters >> 16) & 0xff; |
624 | buf[3] = (dev->filters >> 24) & 0xff; |
625 | ret = rtl2830_bulk_write(client, reg: 0x062, val: buf, val_count: 4); |
626 | if (ret) |
627 | goto err; |
628 | |
629 | /* add PID */ |
630 | buf[0] = (pid >> 8) & 0xff; |
631 | buf[1] = (pid >> 0) & 0xff; |
632 | ret = rtl2830_bulk_write(client, reg: 0x066 + 2 * index, val: buf, val_count: 2); |
633 | if (ret) |
634 | goto err; |
635 | |
636 | return 0; |
637 | err: |
638 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
639 | return ret; |
640 | } |
641 | |
642 | /* |
643 | * I2C gate/mux/repeater logic |
644 | * We must use unlocked __i2c_transfer() here (through regmap) because of I2C |
645 | * adapter lock is already taken by tuner driver. |
646 | * Gate is closed automatically after single I2C transfer. |
647 | */ |
648 | static int rtl2830_select(struct i2c_mux_core *muxc, u32 chan_id) |
649 | { |
650 | struct i2c_client *client = i2c_mux_priv(muxc); |
651 | struct rtl2830_dev *dev = i2c_get_clientdata(client); |
652 | int ret; |
653 | |
654 | dev_dbg(&client->dev, "\n" ); |
655 | |
656 | /* open I2C repeater for 1 transfer, closes automatically */ |
657 | /* XXX: regmap_update_bits() does not lock I2C adapter */ |
658 | ret = regmap_update_bits(map: dev->regmap, reg: 0x101, mask: 0x08, val: 0x08); |
659 | if (ret) |
660 | goto err; |
661 | |
662 | return 0; |
663 | err: |
664 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
665 | return ret; |
666 | } |
667 | |
668 | static struct dvb_frontend *rtl2830_get_dvb_frontend(struct i2c_client *client) |
669 | { |
670 | struct rtl2830_dev *dev = i2c_get_clientdata(client); |
671 | |
672 | dev_dbg(&client->dev, "\n" ); |
673 | |
674 | return &dev->fe; |
675 | } |
676 | |
677 | static struct i2c_adapter *rtl2830_get_i2c_adapter(struct i2c_client *client) |
678 | { |
679 | struct rtl2830_dev *dev = i2c_get_clientdata(client); |
680 | |
681 | dev_dbg(&client->dev, "\n" ); |
682 | |
683 | return dev->muxc->adapter[0]; |
684 | } |
685 | |
686 | /* |
687 | * We implement own I2C access routines for regmap in order to get manual access |
688 | * to I2C adapter lock, which is needed for I2C mux adapter. |
689 | */ |
690 | static int rtl2830_regmap_read(void *context, const void *reg_buf, |
691 | size_t reg_size, void *val_buf, size_t val_size) |
692 | { |
693 | struct i2c_client *client = context; |
694 | int ret; |
695 | struct i2c_msg msg[2] = { |
696 | { |
697 | .addr = client->addr, |
698 | .flags = 0, |
699 | .len = reg_size, |
700 | .buf = (u8 *)reg_buf, |
701 | }, { |
702 | .addr = client->addr, |
703 | .flags = I2C_M_RD, |
704 | .len = val_size, |
705 | .buf = val_buf, |
706 | } |
707 | }; |
708 | |
709 | ret = __i2c_transfer(adap: client->adapter, msgs: msg, num: 2); |
710 | if (ret != 2) { |
711 | dev_warn(&client->dev, "i2c reg read failed %d\n" , ret); |
712 | if (ret >= 0) |
713 | ret = -EREMOTEIO; |
714 | return ret; |
715 | } |
716 | return 0; |
717 | } |
718 | |
719 | static int rtl2830_regmap_write(void *context, const void *data, size_t count) |
720 | { |
721 | struct i2c_client *client = context; |
722 | int ret; |
723 | struct i2c_msg msg[1] = { |
724 | { |
725 | .addr = client->addr, |
726 | .flags = 0, |
727 | .len = count, |
728 | .buf = (u8 *)data, |
729 | } |
730 | }; |
731 | |
732 | ret = __i2c_transfer(adap: client->adapter, msgs: msg, num: 1); |
733 | if (ret != 1) { |
734 | dev_warn(&client->dev, "i2c reg write failed %d\n" , ret); |
735 | if (ret >= 0) |
736 | ret = -EREMOTEIO; |
737 | return ret; |
738 | } |
739 | return 0; |
740 | } |
741 | |
742 | static int rtl2830_regmap_gather_write(void *context, const void *reg, |
743 | size_t reg_len, const void *val, |
744 | size_t val_len) |
745 | { |
746 | struct i2c_client *client = context; |
747 | int ret; |
748 | u8 buf[256]; |
749 | struct i2c_msg msg[1] = { |
750 | { |
751 | .addr = client->addr, |
752 | .flags = 0, |
753 | .len = 1 + val_len, |
754 | .buf = buf, |
755 | } |
756 | }; |
757 | |
758 | buf[0] = *(u8 const *)reg; |
759 | memcpy(&buf[1], val, val_len); |
760 | |
761 | ret = __i2c_transfer(adap: client->adapter, msgs: msg, num: 1); |
762 | if (ret != 1) { |
763 | dev_warn(&client->dev, "i2c reg write failed %d\n" , ret); |
764 | if (ret >= 0) |
765 | ret = -EREMOTEIO; |
766 | return ret; |
767 | } |
768 | return 0; |
769 | } |
770 | |
771 | static int rtl2830_probe(struct i2c_client *client) |
772 | { |
773 | struct rtl2830_platform_data *pdata = client->dev.platform_data; |
774 | struct rtl2830_dev *dev; |
775 | int ret; |
776 | u8 u8tmp; |
777 | static const struct regmap_bus regmap_bus = { |
778 | .read = rtl2830_regmap_read, |
779 | .write = rtl2830_regmap_write, |
780 | .gather_write = rtl2830_regmap_gather_write, |
781 | .val_format_endian_default = REGMAP_ENDIAN_NATIVE, |
782 | }; |
783 | static const struct regmap_range_cfg regmap_range_cfg[] = { |
784 | { |
785 | .selector_reg = 0x00, |
786 | .selector_mask = 0xff, |
787 | .selector_shift = 0, |
788 | .window_start = 0, |
789 | .window_len = 0x100, |
790 | .range_min = 0 * 0x100, |
791 | .range_max = 5 * 0x100, |
792 | }, |
793 | }; |
794 | static const struct regmap_config regmap_config = { |
795 | .reg_bits = 8, |
796 | .val_bits = 8, |
797 | .max_register = 5 * 0x100, |
798 | .ranges = regmap_range_cfg, |
799 | .num_ranges = ARRAY_SIZE(regmap_range_cfg), |
800 | }; |
801 | |
802 | dev_dbg(&client->dev, "\n" ); |
803 | |
804 | if (pdata == NULL) { |
805 | ret = -EINVAL; |
806 | goto err; |
807 | } |
808 | |
809 | /* allocate memory for the internal state */ |
810 | dev = kzalloc(size: sizeof(*dev), GFP_KERNEL); |
811 | if (dev == NULL) { |
812 | ret = -ENOMEM; |
813 | goto err; |
814 | } |
815 | |
816 | /* setup the state */ |
817 | i2c_set_clientdata(client, data: dev); |
818 | dev->client = client; |
819 | dev->pdata = client->dev.platform_data; |
820 | dev->sleeping = true; |
821 | dev->regmap = regmap_init(&client->dev, ®map_bus, client, |
822 | ®map_config); |
823 | if (IS_ERR(ptr: dev->regmap)) { |
824 | ret = PTR_ERR(ptr: dev->regmap); |
825 | goto err_kfree; |
826 | } |
827 | |
828 | /* check if the demod is there */ |
829 | ret = rtl2830_bulk_read(client, reg: 0x000, val: &u8tmp, val_count: 1); |
830 | if (ret) |
831 | goto err_regmap_exit; |
832 | |
833 | /* create muxed i2c adapter for tuner */ |
834 | dev->muxc = i2c_mux_alloc(parent: client->adapter, dev: &client->dev, max_adapters: 1, sizeof_priv: 0, flags: 0, |
835 | select: rtl2830_select, NULL); |
836 | if (!dev->muxc) { |
837 | ret = -ENOMEM; |
838 | goto err_regmap_exit; |
839 | } |
840 | dev->muxc->priv = client; |
841 | ret = i2c_mux_add_adapter(muxc: dev->muxc, force_nr: 0, chan_id: 0, class: 0); |
842 | if (ret) |
843 | goto err_regmap_exit; |
844 | |
845 | /* create dvb frontend */ |
846 | memcpy(&dev->fe.ops, &rtl2830_ops, sizeof(dev->fe.ops)); |
847 | dev->fe.demodulator_priv = client; |
848 | |
849 | /* setup callbacks */ |
850 | pdata->get_dvb_frontend = rtl2830_get_dvb_frontend; |
851 | pdata->get_i2c_adapter = rtl2830_get_i2c_adapter; |
852 | pdata->pid_filter = rtl2830_pid_filter; |
853 | pdata->pid_filter_ctrl = rtl2830_pid_filter_ctrl; |
854 | |
855 | dev_info(&client->dev, "Realtek RTL2830 successfully attached\n" ); |
856 | |
857 | return 0; |
858 | err_regmap_exit: |
859 | regmap_exit(map: dev->regmap); |
860 | err_kfree: |
861 | kfree(objp: dev); |
862 | err: |
863 | dev_dbg(&client->dev, "failed=%d\n" , ret); |
864 | return ret; |
865 | } |
866 | |
867 | static void rtl2830_remove(struct i2c_client *client) |
868 | { |
869 | struct rtl2830_dev *dev = i2c_get_clientdata(client); |
870 | |
871 | dev_dbg(&client->dev, "\n" ); |
872 | |
873 | i2c_mux_del_adapters(muxc: dev->muxc); |
874 | regmap_exit(map: dev->regmap); |
875 | kfree(objp: dev); |
876 | } |
877 | |
878 | static const struct i2c_device_id rtl2830_id_table[] = { |
879 | {"rtl2830" , 0}, |
880 | {} |
881 | }; |
882 | MODULE_DEVICE_TABLE(i2c, rtl2830_id_table); |
883 | |
884 | static struct i2c_driver rtl2830_driver = { |
885 | .driver = { |
886 | .name = "rtl2830" , |
887 | .suppress_bind_attrs = true, |
888 | }, |
889 | .probe = rtl2830_probe, |
890 | .remove = rtl2830_remove, |
891 | .id_table = rtl2830_id_table, |
892 | }; |
893 | |
894 | module_i2c_driver(rtl2830_driver); |
895 | |
896 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>" ); |
897 | MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver" ); |
898 | MODULE_LICENSE("GPL" ); |
899 | |