blob: 87226056f2267c13d41bf84b0262fdab38e74834 [file] [log] [blame]
Antti Palosaaric0adca72011-07-08 23:34:09 -03001/*
2 * Realtek RTL2830 DVB-T demodulator driver
3 *
4 * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
Antti Palosaaric0adca72011-07-08 23:34:09 -030016 */
17
18#include "rtl2830_priv.h"
19
Antti Palosaari15d37f32014-12-12 01:03:51 -030020/* Our regmap is bypassing I2C adapter lock, thus we do it! */
Mauro Carvalho Chehabd858b0e2015-02-03 16:32:34 -020021static int rtl2830_bulk_write(struct i2c_client *client, unsigned int reg,
22 const void *val, size_t val_count)
Antti Palosaari0485a702011-08-04 20:27:19 -030023{
Antti Palosaari1f153c42014-12-08 22:47:21 -030024 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari0485a702011-08-04 20:27:19 -030025 int ret;
Antti Palosaari0485a702011-08-04 20:27:19 -030026
Antti Palosaari15d37f32014-12-12 01:03:51 -030027 i2c_lock_adapter(client->adapter);
28 ret = regmap_bulk_write(dev->regmap, reg, val, val_count);
29 i2c_unlock_adapter(client->adapter);
Antti Palosaarifd4cfa82014-12-09 16:14:41 -030030 return ret;
Antti Palosaari0485a702011-08-04 20:27:19 -030031}
32
Mauro Carvalho Chehabd858b0e2015-02-03 16:32:34 -020033static int rtl2830_update_bits(struct i2c_client *client, unsigned int reg,
34 unsigned int mask, unsigned int val)
Antti Palosaari0485a702011-08-04 20:27:19 -030035{
Antti Palosaari1f153c42014-12-08 22:47:21 -030036 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari0485a702011-08-04 20:27:19 -030037 int ret;
Antti Palosaari0485a702011-08-04 20:27:19 -030038
Antti Palosaari15d37f32014-12-12 01:03:51 -030039 i2c_lock_adapter(client->adapter);
40 ret = regmap_update_bits(dev->regmap, reg, mask, val);
41 i2c_unlock_adapter(client->adapter);
Antti Palosaarifd4cfa82014-12-09 16:14:41 -030042 return ret;
Antti Palosaari0485a702011-08-04 20:27:19 -030043}
44
Mauro Carvalho Chehabd858b0e2015-02-03 16:32:34 -020045static int rtl2830_bulk_read(struct i2c_client *client, unsigned int reg,
46 void *val, size_t val_count)
Antti Palosaaric0adca72011-07-08 23:34:09 -030047{
Antti Palosaari15d37f32014-12-12 01:03:51 -030048 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaaric0adca72011-07-08 23:34:09 -030049 int ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -030050
Antti Palosaari15d37f32014-12-12 01:03:51 -030051 i2c_lock_adapter(client->adapter);
52 ret = regmap_bulk_read(dev->regmap, reg, val, val_count);
53 i2c_unlock_adapter(client->adapter);
54 return ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -030055}
56
57static int rtl2830_init(struct dvb_frontend *fe)
58{
Antti Palosaari1f153c42014-12-08 22:47:21 -030059 struct i2c_client *client = fe->demodulator_priv;
60 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari47b4dbf2014-12-09 06:14:36 -030061 struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
Antti Palosaaric0adca72011-07-08 23:34:09 -030062 int ret, i;
Antti Palosaaric0adca72011-07-08 23:34:09 -030063 struct rtl2830_reg_val_mask tab[] = {
Antti Palosaari947debb2014-12-09 02:31:53 -030064 {0x00d, 0x01, 0x03},
65 {0x00d, 0x10, 0x10},
66 {0x104, 0x00, 0x1e},
67 {0x105, 0x80, 0x80},
68 {0x110, 0x02, 0x03},
69 {0x110, 0x08, 0x0c},
70 {0x17b, 0x00, 0x40},
71 {0x17d, 0x05, 0x0f},
72 {0x17d, 0x50, 0xf0},
73 {0x18c, 0x08, 0x0f},
74 {0x18d, 0x00, 0xc0},
75 {0x188, 0x05, 0x0f},
76 {0x189, 0x00, 0xfc},
77 {0x2d5, 0x02, 0x02},
78 {0x2f1, 0x02, 0x06},
79 {0x2f1, 0x20, 0xf8},
80 {0x16d, 0x00, 0x01},
81 {0x1a6, 0x00, 0x80},
82 {0x106, dev->pdata->vtop, 0x3f},
83 {0x107, dev->pdata->krf, 0x3f},
84 {0x112, 0x28, 0xff},
85 {0x103, dev->pdata->agc_targ_val, 0xff},
86 {0x00a, 0x02, 0x07},
87 {0x140, 0x0c, 0x3c},
88 {0x140, 0x40, 0xc0},
89 {0x15b, 0x05, 0x07},
90 {0x15b, 0x28, 0x38},
91 {0x15c, 0x05, 0x07},
92 {0x15c, 0x28, 0x38},
93 {0x115, dev->pdata->spec_inv, 0x01},
94 {0x16f, 0x01, 0x07},
95 {0x170, 0x18, 0x38},
96 {0x172, 0x0f, 0x0f},
97 {0x173, 0x08, 0x38},
98 {0x175, 0x01, 0x07},
99 {0x176, 0x00, 0xc0},
Antti Palosaaric0adca72011-07-08 23:34:09 -0300100 };
101
102 for (i = 0; i < ARRAY_SIZE(tab); i++) {
Antti Palosaari15d37f32014-12-12 01:03:51 -0300103 ret = rtl2830_update_bits(client, tab[i].reg, tab[i].mask,
104 tab[i].val);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300105 if (ret)
106 goto err;
107 }
108
Antti Palosaari15d37f32014-12-12 01:03:51 -0300109 ret = rtl2830_bulk_write(client, 0x18f, "\x28\x00", 2);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300110 if (ret)
111 goto err;
112
Antti Palosaari15d37f32014-12-12 01:03:51 -0300113 ret = rtl2830_bulk_write(client, 0x195,
114 "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300115 if (ret)
116 goto err;
117
Antti Palosaaric0adca72011-07-08 23:34:09 -0300118 /* TODO: spec init */
119
120 /* soft reset */
Antti Palosaari15d37f32014-12-12 01:03:51 -0300121 ret = rtl2830_update_bits(client, 0x101, 0x04, 0x04);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300122 if (ret)
123 goto err;
124
Antti Palosaari15d37f32014-12-12 01:03:51 -0300125 ret = rtl2830_update_bits(client, 0x101, 0x04, 0x00);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300126 if (ret)
127 goto err;
128
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300129 /* init stats here in order signal app which stats are supported */
Antti Palosaari871f7022014-12-09 08:49:44 -0300130 c->strength.len = 1;
131 c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300132 c->cnr.len = 1;
133 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Antti Palosaari5bb11ca2014-12-09 09:45:16 -0300134 c->post_bit_error.len = 1;
135 c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
136 c->post_bit_count.len = 1;
137 c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300138
Antti Palosaarif544f102014-12-08 22:31:28 -0300139 dev->sleeping = false;
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300140
Antti Palosaaric0adca72011-07-08 23:34:09 -0300141 return ret;
142err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300143 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300144 return ret;
145}
146
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300147static int rtl2830_sleep(struct dvb_frontend *fe)
148{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300149 struct i2c_client *client = fe->demodulator_priv;
150 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari947debb2014-12-09 02:31:53 -0300151
Antti Palosaarif544f102014-12-08 22:31:28 -0300152 dev->sleeping = true;
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300153 dev->fe_status = 0;
Antti Palosaari947debb2014-12-09 02:31:53 -0300154
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300155 return 0;
156}
157
Mauro Carvalho Chehaba17ff2e2012-10-27 11:24:08 -0300158static int rtl2830_get_tune_settings(struct dvb_frontend *fe,
Antti Palosaari947debb2014-12-09 02:31:53 -0300159 struct dvb_frontend_tune_settings *s)
Antti Palosaaric0adca72011-07-08 23:34:09 -0300160{
161 s->min_delay_ms = 500;
162 s->step_size = fe->ops.info.frequency_stepsize * 2;
163 s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
164
165 return 0;
166}
167
168static int rtl2830_set_frontend(struct dvb_frontend *fe)
169{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300170 struct i2c_client *client = fe->demodulator_priv;
171 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300172 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
173 int ret, i;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300174 u64 num;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300175 u8 buf[3], u8tmp;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300176 u32 if_ctl, if_frequency;
Antti Palosaari3a2fca22012-09-12 20:23:49 -0300177 static const u8 bw_params1[3][34] = {
Antti Palosaaric0adca72011-07-08 23:34:09 -0300178 {
179 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41,
180 0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a,
181 0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82,
182 0x03, 0x73, 0x03, 0xcf, /* 6 MHz */
183 }, {
184 0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca,
185 0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca,
186 0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e,
187 0x03, 0xd0, 0x04, 0x53, /* 7 MHz */
188 }, {
189 0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0,
190 0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a,
191 0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f,
192 0x04, 0x24, 0x04, 0xdb, /* 8 MHz */
193 },
194 };
Antti Palosaari3a2fca22012-09-12 20:23:49 -0300195 static const u8 bw_params2[3][6] = {
196 {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30}, /* 6 MHz */
197 {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98}, /* 7 MHz */
198 {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64}, /* 8 MHz */
Antti Palosaaric0adca72011-07-08 23:34:09 -0300199 };
200
Antti Palosaari7cc39322014-12-08 23:32:19 -0300201 dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u inversion=%u\n",
Antti Palosaari947debb2014-12-09 02:31:53 -0300202 c->frequency, c->bandwidth_hz, c->inversion);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300203
204 /* program tuner */
205 if (fe->ops.tuner_ops.set_params)
206 fe->ops.tuner_ops.set_params(fe);
207
208 switch (c->bandwidth_hz) {
209 case 6000000:
210 i = 0;
211 break;
212 case 7000000:
213 i = 1;
214 break;
215 case 8000000:
216 i = 2;
217 break;
218 default:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300219 dev_err(&client->dev, "invalid bandwidth_hz %u\n",
Antti Palosaari947debb2014-12-09 02:31:53 -0300220 c->bandwidth_hz);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300221 return -EINVAL;
222 }
223
Antti Palosaari15d37f32014-12-12 01:03:51 -0300224 ret = rtl2830_update_bits(client, 0x008, 0x06, i << 1);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300225 if (ret)
226 goto err;
227
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300228 /* program if frequency */
229 if (fe->ops.tuner_ops.get_if_frequency)
230 ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
231 else
232 ret = -EINVAL;
Antti Palosaari947debb2014-12-09 02:31:53 -0300233 if (ret)
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300234 goto err;
235
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300236 num = if_frequency % dev->pdata->clk;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300237 num *= 0x400000;
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300238 num = div_u64(num, dev->pdata->clk);
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300239 num = -num;
240 if_ctl = num & 0x3fffff;
Antti Palosaari7cc39322014-12-08 23:32:19 -0300241 dev_dbg(&client->dev, "if_frequency=%d if_ctl=%08x\n",
Antti Palosaari947debb2014-12-09 02:31:53 -0300242 if_frequency, if_ctl);
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300243
Antti Palosaari15d37f32014-12-12 01:03:51 -0300244 buf[0] = (if_ctl >> 16) & 0x3f;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300245 buf[1] = (if_ctl >> 8) & 0xff;
246 buf[2] = (if_ctl >> 0) & 0xff;
247
Antti Palosaari15d37f32014-12-12 01:03:51 -0300248 ret = rtl2830_bulk_read(client, 0x119, &u8tmp, 1);
249 if (ret)
250 goto err;
251
252 buf[0] |= u8tmp & 0xc0; /* [7:6] */
253
254 ret = rtl2830_bulk_write(client, 0x119, buf, 3);
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300255 if (ret)
256 goto err;
257
Antti Palosaaric0adca72011-07-08 23:34:09 -0300258 /* 1/2 split I2C write */
Antti Palosaari15d37f32014-12-12 01:03:51 -0300259 ret = rtl2830_bulk_write(client, 0x11c, &bw_params1[i][0], 17);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300260 if (ret)
261 goto err;
262
263 /* 2/2 split I2C write */
Antti Palosaari15d37f32014-12-12 01:03:51 -0300264 ret = rtl2830_bulk_write(client, 0x12d, &bw_params1[i][17], 17);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300265 if (ret)
266 goto err;
267
Antti Palosaari15d37f32014-12-12 01:03:51 -0300268 ret = rtl2830_bulk_write(client, 0x19d, bw_params2[i], 6);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300269 if (ret)
270 goto err;
271
272 return ret;
273err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300274 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300275 return ret;
276}
277
Mauro Carvalho Chehab7e3e68b2016-02-04 12:58:30 -0200278static int rtl2830_get_frontend(struct dvb_frontend *fe,
279 struct dtv_frontend_properties *c)
Antti Palosaari631a2b62012-05-18 15:58:57 -0300280{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300281 struct i2c_client *client = fe->demodulator_priv;
282 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300283 int ret;
284 u8 buf[3];
285
Antti Palosaarif544f102014-12-08 22:31:28 -0300286 if (dev->sleeping)
Antti Palosaaric1886372012-05-18 16:02:55 -0300287 return 0;
288
Antti Palosaari15d37f32014-12-12 01:03:51 -0300289 ret = rtl2830_bulk_read(client, 0x33c, buf, 2);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300290 if (ret)
291 goto err;
292
Antti Palosaari15d37f32014-12-12 01:03:51 -0300293 ret = rtl2830_bulk_read(client, 0x351, &buf[2], 1);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300294 if (ret)
295 goto err;
296
Antti Palosaari7cc39322014-12-08 23:32:19 -0300297 dev_dbg(&client->dev, "TPS=%*ph\n", 3, buf);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300298
299 switch ((buf[0] >> 2) & 3) {
300 case 0:
301 c->modulation = QPSK;
302 break;
303 case 1:
304 c->modulation = QAM_16;
305 break;
306 case 2:
307 c->modulation = QAM_64;
308 break;
309 }
310
311 switch ((buf[2] >> 2) & 1) {
312 case 0:
313 c->transmission_mode = TRANSMISSION_MODE_2K;
314 break;
315 case 1:
316 c->transmission_mode = TRANSMISSION_MODE_8K;
317 }
318
319 switch ((buf[2] >> 0) & 3) {
320 case 0:
321 c->guard_interval = GUARD_INTERVAL_1_32;
322 break;
323 case 1:
324 c->guard_interval = GUARD_INTERVAL_1_16;
325 break;
326 case 2:
327 c->guard_interval = GUARD_INTERVAL_1_8;
328 break;
329 case 3:
330 c->guard_interval = GUARD_INTERVAL_1_4;
331 break;
332 }
333
334 switch ((buf[0] >> 4) & 7) {
335 case 0:
336 c->hierarchy = HIERARCHY_NONE;
337 break;
338 case 1:
339 c->hierarchy = HIERARCHY_1;
340 break;
341 case 2:
342 c->hierarchy = HIERARCHY_2;
343 break;
344 case 3:
345 c->hierarchy = HIERARCHY_4;
346 break;
347 }
348
349 switch ((buf[1] >> 3) & 7) {
350 case 0:
351 c->code_rate_HP = FEC_1_2;
352 break;
353 case 1:
354 c->code_rate_HP = FEC_2_3;
355 break;
356 case 2:
357 c->code_rate_HP = FEC_3_4;
358 break;
359 case 3:
360 c->code_rate_HP = FEC_5_6;
361 break;
362 case 4:
363 c->code_rate_HP = FEC_7_8;
364 break;
365 }
366
367 switch ((buf[1] >> 0) & 7) {
368 case 0:
369 c->code_rate_LP = FEC_1_2;
370 break;
371 case 1:
372 c->code_rate_LP = FEC_2_3;
373 break;
374 case 2:
375 c->code_rate_LP = FEC_3_4;
376 break;
377 case 3:
378 c->code_rate_LP = FEC_5_6;
379 break;
380 case 4:
381 c->code_rate_LP = FEC_7_8;
382 break;
383 }
384
385 return 0;
386err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300387 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300388 return ret;
389}
390
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -0300391static int rtl2830_read_status(struct dvb_frontend *fe, enum fe_status *status)
Antti Palosaaric0adca72011-07-08 23:34:09 -0300392{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300393 struct i2c_client *client = fe->demodulator_priv;
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300394 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari4a7e4452016-06-29 20:40:56 -0300395 struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
396 int ret, stmp;
397 unsigned int utmp;
398 u8 u8tmp, buf[2];
Antti Palosaari947debb2014-12-09 02:31:53 -0300399
Antti Palosaaric0adca72011-07-08 23:34:09 -0300400 *status = 0;
401
Antti Palosaarif544f102014-12-08 22:31:28 -0300402 if (dev->sleeping)
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300403 return 0;
404
Antti Palosaari15d37f32014-12-12 01:03:51 -0300405 ret = rtl2830_bulk_read(client, 0x351, &u8tmp, 1);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300406 if (ret)
407 goto err;
408
Antti Palosaari15d37f32014-12-12 01:03:51 -0300409 u8tmp = (u8tmp >> 3) & 0x0f; /* [6:3] */
410 if (u8tmp == 11) {
Antti Palosaaric0adca72011-07-08 23:34:09 -0300411 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
412 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300413 } else if (u8tmp == 10) {
Antti Palosaaric0adca72011-07-08 23:34:09 -0300414 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
415 FE_HAS_VITERBI;
416 }
417
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300418 dev->fe_status = *status;
419
Antti Palosaari4a7e4452016-06-29 20:40:56 -0300420 /* Signal strength */
421 if (dev->fe_status & FE_HAS_SIGNAL) {
422 /* Read IF AGC */
423 ret = rtl2830_bulk_read(client, 0x359, buf, 2);
424 if (ret)
425 goto err;
426
427 stmp = buf[0] << 8 | buf[1] << 0;
428 stmp = sign_extend32(stmp, 13);
429 utmp = clamp_val(-4 * stmp + 32767, 0x0000, 0xffff);
430
431 dev_dbg(&client->dev, "IF AGC=%d\n", stmp);
432
433 c->strength.stat[0].scale = FE_SCALE_RELATIVE;
434 c->strength.stat[0].uvalue = utmp;
435 } else {
436 c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
437 }
438
439 /* CNR */
440 if (dev->fe_status & FE_HAS_VITERBI) {
441 unsigned int hierarchy, constellation;
442 #define CONSTELLATION_NUM 3
443 #define HIERARCHY_NUM 4
444 static const u32 constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
445 {70705899, 70705899, 70705899, 70705899},
446 {82433173, 82433173, 87483115, 94445660},
447 {92888734, 92888734, 95487525, 99770748},
448 };
449
450 ret = rtl2830_bulk_read(client, 0x33c, &u8tmp, 1);
451 if (ret)
452 goto err;
453
454 constellation = (u8tmp >> 2) & 0x03; /* [3:2] */
455 if (constellation > CONSTELLATION_NUM - 1)
456 goto err;
457
458 hierarchy = (u8tmp >> 4) & 0x07; /* [6:4] */
459 if (hierarchy > HIERARCHY_NUM - 1)
460 goto err;
461
462 ret = rtl2830_bulk_read(client, 0x40c, buf, 2);
463 if (ret)
464 goto err;
465
466 utmp = buf[0] << 8 | buf[1] << 0;
467 if (utmp)
468 stmp = (constant[constellation][hierarchy] -
469 intlog10(utmp)) / ((1 << 24) / 10000);
470 else
471 stmp = 0;
472
473 dev_dbg(&client->dev, "CNR raw=%u\n", utmp);
474
475 c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
476 c->cnr.stat[0].svalue = stmp;
477 } else {
478 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
479 }
480
481 /* BER */
482 if (dev->fe_status & FE_HAS_LOCK) {
483 ret = rtl2830_bulk_read(client, 0x34e, buf, 2);
484 if (ret)
485 goto err;
486
487 utmp = buf[0] << 8 | buf[1] << 0;
488 dev->post_bit_error += utmp;
489 dev->post_bit_count += 1000000;
490
491 dev_dbg(&client->dev, "BER errors=%u total=1000000\n", utmp);
492
493 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
494 c->post_bit_error.stat[0].uvalue = dev->post_bit_error;
495 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
496 c->post_bit_count.stat[0].uvalue = dev->post_bit_count;
497 } else {
498 c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
499 c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
500 }
501
502
Antti Palosaaric0adca72011-07-08 23:34:09 -0300503 return ret;
504err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300505 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300506 return ret;
507}
508
509static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
510{
Antti Palosaari6dcfe3c2014-12-09 10:48:10 -0300511 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Antti Palosaarieba672a2012-05-15 18:32:33 -0300512
Antti Palosaari6dcfe3c2014-12-09 10:48:10 -0300513 if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL)
514 *snr = div_s64(c->cnr.stat[0].svalue, 100);
Antti Palosaarieba672a2012-05-15 18:32:33 -0300515 else
516 *snr = 0;
517
Antti Palosaaric0adca72011-07-08 23:34:09 -0300518 return 0;
519}
520
521static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
522{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300523 struct i2c_client *client = fe->demodulator_priv;
524 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari525ffc12012-05-18 12:23:42 -0300525
Antti Palosaarif4913912014-12-09 10:27:32 -0300526 *ber = (dev->post_bit_error - dev->post_bit_error_prev);
527 dev->post_bit_error_prev = dev->post_bit_error;
Antti Palosaari525ffc12012-05-18 12:23:42 -0300528
Antti Palosaaric0adca72011-07-08 23:34:09 -0300529 return 0;
530}
531
532static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
533{
534 *ucblocks = 0;
Antti Palosaari947debb2014-12-09 02:31:53 -0300535
Antti Palosaaric0adca72011-07-08 23:34:09 -0300536 return 0;
537}
538
539static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
540{
Antti Palosaarid512e282014-12-09 10:20:01 -0300541 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Antti Palosaari78e75072012-05-18 15:17:51 -0300542
Antti Palosaarid512e282014-12-09 10:20:01 -0300543 if (c->strength.stat[0].scale == FE_SCALE_RELATIVE)
544 *strength = c->strength.stat[0].uvalue;
Antti Palosaari78e75072012-05-18 15:17:51 -0300545 else
Antti Palosaarid512e282014-12-09 10:20:01 -0300546 *strength = 0;
Antti Palosaari78e75072012-05-18 15:17:51 -0300547
Antti Palosaaric0adca72011-07-08 23:34:09 -0300548 return 0;
549}
550
Antti Palosaaric0adca72011-07-08 23:34:09 -0300551static struct dvb_frontend_ops rtl2830_ops = {
Antti Palosaari947debb2014-12-09 02:31:53 -0300552 .delsys = {SYS_DVBT},
Antti Palosaaric0adca72011-07-08 23:34:09 -0300553 .info = {
554 .name = "Realtek RTL2830 (DVB-T)",
555 .caps = FE_CAN_FEC_1_2 |
556 FE_CAN_FEC_2_3 |
557 FE_CAN_FEC_3_4 |
558 FE_CAN_FEC_5_6 |
559 FE_CAN_FEC_7_8 |
560 FE_CAN_FEC_AUTO |
561 FE_CAN_QPSK |
562 FE_CAN_QAM_16 |
563 FE_CAN_QAM_64 |
564 FE_CAN_QAM_AUTO |
565 FE_CAN_TRANSMISSION_MODE_AUTO |
566 FE_CAN_GUARD_INTERVAL_AUTO |
567 FE_CAN_HIERARCHY_AUTO |
568 FE_CAN_RECOVER |
569 FE_CAN_MUTE_TS
570 },
571
Antti Palosaaric0adca72011-07-08 23:34:09 -0300572 .init = rtl2830_init,
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300573 .sleep = rtl2830_sleep,
Antti Palosaaric0adca72011-07-08 23:34:09 -0300574
575 .get_tune_settings = rtl2830_get_tune_settings,
576
577 .set_frontend = rtl2830_set_frontend,
Antti Palosaari631a2b62012-05-18 15:58:57 -0300578 .get_frontend = rtl2830_get_frontend,
Antti Palosaaric0adca72011-07-08 23:34:09 -0300579
580 .read_status = rtl2830_read_status,
581 .read_snr = rtl2830_read_snr,
582 .read_ber = rtl2830_read_ber,
583 .read_ucblocks = rtl2830_read_ucblocks,
584 .read_signal_strength = rtl2830_read_signal_strength,
585};
586
Antti Palosaaridf70dda2014-12-09 16:08:44 -0300587static int rtl2830_pid_filter_ctrl(struct dvb_frontend *fe, int onoff)
588{
589 struct i2c_client *client = fe->demodulator_priv;
590 int ret;
591 u8 u8tmp;
592
593 dev_dbg(&client->dev, "onoff=%d\n", onoff);
594
595 /* enable / disable PID filter */
596 if (onoff)
597 u8tmp = 0x80;
598 else
599 u8tmp = 0x00;
600
Antti Palosaari15d37f32014-12-12 01:03:51 -0300601 ret = rtl2830_update_bits(client, 0x061, 0x80, u8tmp);
Antti Palosaaridf70dda2014-12-09 16:08:44 -0300602 if (ret)
603 goto err;
604
605 return 0;
606err:
607 dev_dbg(&client->dev, "failed=%d\n", ret);
608 return ret;
609}
610
611static int rtl2830_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid, int onoff)
612{
613 struct i2c_client *client = fe->demodulator_priv;
614 struct rtl2830_dev *dev = i2c_get_clientdata(client);
615 int ret;
616 u8 buf[4];
617
618 dev_dbg(&client->dev, "index=%d pid=%04x onoff=%d\n",
619 index, pid, onoff);
620
621 /* skip invalid PIDs (0x2000) */
622 if (pid > 0x1fff || index > 32)
623 return 0;
624
625 if (onoff)
626 set_bit(index, &dev->filters);
627 else
628 clear_bit(index, &dev->filters);
629
630 /* enable / disable PIDs */
631 buf[0] = (dev->filters >> 0) & 0xff;
632 buf[1] = (dev->filters >> 8) & 0xff;
633 buf[2] = (dev->filters >> 16) & 0xff;
634 buf[3] = (dev->filters >> 24) & 0xff;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300635 ret = rtl2830_bulk_write(client, 0x062, buf, 4);
Antti Palosaaridf70dda2014-12-09 16:08:44 -0300636 if (ret)
637 goto err;
638
639 /* add PID */
640 buf[0] = (pid >> 8) & 0xff;
641 buf[1] = (pid >> 0) & 0xff;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300642 ret = rtl2830_bulk_write(client, 0x066 + 2 * index, buf, 2);
Antti Palosaaridf70dda2014-12-09 16:08:44 -0300643 if (ret)
644 goto err;
645
646 return 0;
647err:
648 dev_dbg(&client->dev, "failed=%d\n", ret);
649 return ret;
650}
651
Antti Palosaari28c08792014-12-07 04:07:29 -0300652/*
Antti Palosaari15d37f32014-12-12 01:03:51 -0300653 * I2C gate/mux/repeater logic
654 * We must use unlocked __i2c_transfer() here (through regmap) because of I2C
655 * adapter lock is already taken by tuner driver.
656 * Gate is closed automatically after single I2C transfer.
Antti Palosaari28c08792014-12-07 04:07:29 -0300657 */
Peter Rosina0119152016-04-20 08:41:13 +0200658static int rtl2830_select(struct i2c_mux_core *muxc, u32 chan_id)
Antti Palosaari28c08792014-12-07 04:07:29 -0300659{
Peter Rosina0119152016-04-20 08:41:13 +0200660 struct i2c_client *client = i2c_mux_priv(muxc);
Antti Palosaarif544f102014-12-08 22:31:28 -0300661 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300662 int ret;
663
Antti Palosaarifd4cfa82014-12-09 16:14:41 -0300664 dev_dbg(&client->dev, "\n");
665
Antti Palosaari15d37f32014-12-12 01:03:51 -0300666 /* open I2C repeater for 1 transfer, closes automatically */
667 /* XXX: regmap_update_bits() does not lock I2C adapter */
668 ret = regmap_update_bits(dev->regmap, 0x101, 0x08, 0x08);
669 if (ret)
Antti Palosaari28c08792014-12-07 04:07:29 -0300670 goto err;
Antti Palosaari28c08792014-12-07 04:07:29 -0300671
672 return 0;
Antti Palosaari28c08792014-12-07 04:07:29 -0300673err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300674 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaari28c08792014-12-07 04:07:29 -0300675 return ret;
676}
677
678static struct dvb_frontend *rtl2830_get_dvb_frontend(struct i2c_client *client)
679{
Antti Palosaarif544f102014-12-08 22:31:28 -0300680 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300681
682 dev_dbg(&client->dev, "\n");
683
Antti Palosaarif544f102014-12-08 22:31:28 -0300684 return &dev->fe;
Antti Palosaari28c08792014-12-07 04:07:29 -0300685}
686
687static struct i2c_adapter *rtl2830_get_i2c_adapter(struct i2c_client *client)
688{
Antti Palosaarif544f102014-12-08 22:31:28 -0300689 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300690
691 dev_dbg(&client->dev, "\n");
692
Peter Rosina0119152016-04-20 08:41:13 +0200693 return dev->muxc->adapter[0];
Antti Palosaari28c08792014-12-07 04:07:29 -0300694}
695
Antti Palosaari15d37f32014-12-12 01:03:51 -0300696/*
697 * We implement own I2C access routines for regmap in order to get manual access
698 * to I2C adapter lock, which is needed for I2C mux adapter.
699 */
700static int rtl2830_regmap_read(void *context, const void *reg_buf,
701 size_t reg_size, void *val_buf, size_t val_size)
702{
703 struct i2c_client *client = context;
704 int ret;
705 struct i2c_msg msg[2] = {
706 {
707 .addr = client->addr,
708 .flags = 0,
709 .len = reg_size,
710 .buf = (u8 *)reg_buf,
711 }, {
712 .addr = client->addr,
713 .flags = I2C_M_RD,
714 .len = val_size,
715 .buf = val_buf,
716 }
717 };
718
719 ret = __i2c_transfer(client->adapter, msg, 2);
720 if (ret != 2) {
721 dev_warn(&client->dev, "i2c reg read failed %d\n", ret);
722 if (ret >= 0)
723 ret = -EREMOTEIO;
724 return ret;
725 }
726 return 0;
727}
728
729static int rtl2830_regmap_write(void *context, const void *data, size_t count)
730{
731 struct i2c_client *client = context;
732 int ret;
733 struct i2c_msg msg[1] = {
734 {
735 .addr = client->addr,
736 .flags = 0,
737 .len = count,
738 .buf = (u8 *)data,
739 }
740 };
741
742 ret = __i2c_transfer(client->adapter, msg, 1);
743 if (ret != 1) {
744 dev_warn(&client->dev, "i2c reg write failed %d\n", ret);
745 if (ret >= 0)
746 ret = -EREMOTEIO;
747 return ret;
748 }
749 return 0;
750}
751
752static int rtl2830_regmap_gather_write(void *context, const void *reg,
753 size_t reg_len, const void *val,
754 size_t val_len)
755{
756 struct i2c_client *client = context;
757 int ret;
758 u8 buf[256];
759 struct i2c_msg msg[1] = {
760 {
761 .addr = client->addr,
762 .flags = 0,
763 .len = 1 + val_len,
764 .buf = buf,
765 }
766 };
767
768 buf[0] = *(u8 const *)reg;
769 memcpy(&buf[1], val, val_len);
770
771 ret = __i2c_transfer(client->adapter, msg, 1);
772 if (ret != 1) {
773 dev_warn(&client->dev, "i2c reg write failed %d\n", ret);
774 if (ret >= 0)
775 ret = -EREMOTEIO;
776 return ret;
777 }
778 return 0;
779}
780
Antti Palosaari28c08792014-12-07 04:07:29 -0300781static int rtl2830_probe(struct i2c_client *client,
Antti Palosaari947debb2014-12-09 02:31:53 -0300782 const struct i2c_device_id *id)
Antti Palosaari28c08792014-12-07 04:07:29 -0300783{
784 struct rtl2830_platform_data *pdata = client->dev.platform_data;
Antti Palosaarif544f102014-12-08 22:31:28 -0300785 struct rtl2830_dev *dev;
Antti Palosaari28c08792014-12-07 04:07:29 -0300786 int ret;
787 u8 u8tmp;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300788 static const struct regmap_bus regmap_bus = {
789 .read = rtl2830_regmap_read,
790 .write = rtl2830_regmap_write,
791 .gather_write = rtl2830_regmap_gather_write,
792 .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
793 };
794 static const struct regmap_range_cfg regmap_range_cfg[] = {
795 {
796 .selector_reg = 0x00,
797 .selector_mask = 0xff,
798 .selector_shift = 0,
799 .window_start = 0,
800 .window_len = 0x100,
801 .range_min = 0 * 0x100,
802 .range_max = 5 * 0x100,
803 },
804 };
805 static const struct regmap_config regmap_config = {
806 .reg_bits = 8,
807 .val_bits = 8,
808 .max_register = 5 * 0x100,
809 .ranges = regmap_range_cfg,
810 .num_ranges = ARRAY_SIZE(regmap_range_cfg),
811 };
Antti Palosaari28c08792014-12-07 04:07:29 -0300812
813 dev_dbg(&client->dev, "\n");
814
815 if (pdata == NULL) {
816 ret = -EINVAL;
817 goto err;
818 }
819
820 /* allocate memory for the internal state */
Antti Palosaarif544f102014-12-08 22:31:28 -0300821 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
822 if (dev == NULL) {
Antti Palosaari28c08792014-12-07 04:07:29 -0300823 ret = -ENOMEM;
824 goto err;
825 }
826
827 /* setup the state */
Antti Palosaarif544f102014-12-08 22:31:28 -0300828 i2c_set_clientdata(client, dev);
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300829 dev->client = client;
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300830 dev->pdata = client->dev.platform_data;
Antti Palosaarif544f102014-12-08 22:31:28 -0300831 dev->sleeping = true;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300832 dev->regmap = regmap_init(&client->dev, &regmap_bus, client,
833 &regmap_config);
834 if (IS_ERR(dev->regmap)) {
835 ret = PTR_ERR(dev->regmap);
836 goto err_kfree;
837 }
Antti Palosaari28c08792014-12-07 04:07:29 -0300838
839 /* check if the demod is there */
Antti Palosaari15d37f32014-12-12 01:03:51 -0300840 ret = rtl2830_bulk_read(client, 0x000, &u8tmp, 1);
Antti Palosaari28c08792014-12-07 04:07:29 -0300841 if (ret)
Antti Palosaari15d37f32014-12-12 01:03:51 -0300842 goto err_regmap_exit;
Antti Palosaari28c08792014-12-07 04:07:29 -0300843
844 /* create muxed i2c adapter for tuner */
Peter Rosina0119152016-04-20 08:41:13 +0200845 dev->muxc = i2c_mux_alloc(client->adapter, &client->dev, 1, 0, 0,
846 rtl2830_select, NULL);
847 if (!dev->muxc) {
848 ret = -ENOMEM;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300849 goto err_regmap_exit;
Antti Palosaari28c08792014-12-07 04:07:29 -0300850 }
Peter Rosina0119152016-04-20 08:41:13 +0200851 dev->muxc->priv = client;
852 ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0);
853 if (ret)
854 goto err_regmap_exit;
Antti Palosaari28c08792014-12-07 04:07:29 -0300855
856 /* create dvb frontend */
Antti Palosaarif544f102014-12-08 22:31:28 -0300857 memcpy(&dev->fe.ops, &rtl2830_ops, sizeof(dev->fe.ops));
Antti Palosaari1f153c42014-12-08 22:47:21 -0300858 dev->fe.demodulator_priv = client;
Antti Palosaari28c08792014-12-07 04:07:29 -0300859
860 /* setup callbacks */
861 pdata->get_dvb_frontend = rtl2830_get_dvb_frontend;
862 pdata->get_i2c_adapter = rtl2830_get_i2c_adapter;
Antti Palosaaridf70dda2014-12-09 16:08:44 -0300863 pdata->pid_filter = rtl2830_pid_filter;
864 pdata->pid_filter_ctrl = rtl2830_pid_filter_ctrl;
Antti Palosaari28c08792014-12-07 04:07:29 -0300865
866 dev_info(&client->dev, "Realtek RTL2830 successfully attached\n");
Antti Palosaari28c08792014-12-07 04:07:29 -0300867
Antti Palosaari947debb2014-12-09 02:31:53 -0300868 return 0;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300869err_regmap_exit:
870 regmap_exit(dev->regmap);
Antti Palosaari28c08792014-12-07 04:07:29 -0300871err_kfree:
Antti Palosaarif544f102014-12-08 22:31:28 -0300872 kfree(dev);
Antti Palosaari28c08792014-12-07 04:07:29 -0300873err:
874 dev_dbg(&client->dev, "failed=%d\n", ret);
875 return ret;
876}
877
878static int rtl2830_remove(struct i2c_client *client)
879{
Antti Palosaarif544f102014-12-08 22:31:28 -0300880 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300881
882 dev_dbg(&client->dev, "\n");
883
Peter Rosina0119152016-04-20 08:41:13 +0200884 i2c_mux_del_adapters(dev->muxc);
Antti Palosaari15d37f32014-12-12 01:03:51 -0300885 regmap_exit(dev->regmap);
Antti Palosaarif544f102014-12-08 22:31:28 -0300886 kfree(dev);
Antti Palosaari947debb2014-12-09 02:31:53 -0300887
Antti Palosaari28c08792014-12-07 04:07:29 -0300888 return 0;
889}
890
891static const struct i2c_device_id rtl2830_id_table[] = {
892 {"rtl2830", 0},
893 {}
894};
895MODULE_DEVICE_TABLE(i2c, rtl2830_id_table);
896
897static struct i2c_driver rtl2830_driver = {
898 .driver = {
Antti Palosaari95e7cdb2016-06-29 20:40:55 -0300899 .name = "rtl2830",
900 .suppress_bind_attrs = true,
Antti Palosaari28c08792014-12-07 04:07:29 -0300901 },
902 .probe = rtl2830_probe,
903 .remove = rtl2830_remove,
904 .id_table = rtl2830_id_table,
905};
906
907module_i2c_driver(rtl2830_driver);
908
Antti Palosaaric0adca72011-07-08 23:34:09 -0300909MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
910MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver");
911MODULE_LICENSE("GPL");