blob: e6b8367c8cce4ec416d24a439325349798667321 [file] [log] [blame]
Thomas Gleixnerc942fdd2019-05-27 08:55:06 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Antti Palosaaric0adca72011-07-08 23:34:09 -03002/*
3 * Realtek RTL2830 DVB-T demodulator driver
4 *
5 * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
Antti Palosaaric0adca72011-07-08 23:34:09 -03006 */
7
8#include "rtl2830_priv.h"
9
Antti Palosaari15d37f32014-12-12 01:03:51 -030010/* Our regmap is bypassing I2C adapter lock, thus we do it! */
Mauro Carvalho Chehabd858b0e2015-02-03 16:32:34 -020011static int rtl2830_bulk_write(struct i2c_client *client, unsigned int reg,
12 const void *val, size_t val_count)
Antti Palosaari0485a702011-08-04 20:27:19 -030013{
Antti Palosaari1f153c42014-12-08 22:47:21 -030014 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari0485a702011-08-04 20:27:19 -030015 int ret;
Antti Palosaari0485a702011-08-04 20:27:19 -030016
Peter Rosindfecde42018-06-20 07:17:59 +020017 i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
Antti Palosaari15d37f32014-12-12 01:03:51 -030018 ret = regmap_bulk_write(dev->regmap, reg, val, val_count);
Peter Rosindfecde42018-06-20 07:17:59 +020019 i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
Antti Palosaarifd4cfa82014-12-09 16:14:41 -030020 return ret;
Antti Palosaari0485a702011-08-04 20:27:19 -030021}
22
Mauro Carvalho Chehabd858b0e2015-02-03 16:32:34 -020023static int rtl2830_update_bits(struct i2c_client *client, unsigned int reg,
24 unsigned int mask, unsigned int val)
Antti Palosaari0485a702011-08-04 20:27:19 -030025{
Antti Palosaari1f153c42014-12-08 22:47:21 -030026 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari0485a702011-08-04 20:27:19 -030027 int ret;
Antti Palosaari0485a702011-08-04 20:27:19 -030028
Peter Rosindfecde42018-06-20 07:17:59 +020029 i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
Antti Palosaari15d37f32014-12-12 01:03:51 -030030 ret = regmap_update_bits(dev->regmap, reg, mask, val);
Peter Rosindfecde42018-06-20 07:17:59 +020031 i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
Antti Palosaarifd4cfa82014-12-09 16:14:41 -030032 return ret;
Antti Palosaari0485a702011-08-04 20:27:19 -030033}
34
Mauro Carvalho Chehabd858b0e2015-02-03 16:32:34 -020035static int rtl2830_bulk_read(struct i2c_client *client, unsigned int reg,
36 void *val, size_t val_count)
Antti Palosaaric0adca72011-07-08 23:34:09 -030037{
Antti Palosaari15d37f32014-12-12 01:03:51 -030038 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaaric0adca72011-07-08 23:34:09 -030039 int ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -030040
Peter Rosindfecde42018-06-20 07:17:59 +020041 i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
Antti Palosaari15d37f32014-12-12 01:03:51 -030042 ret = regmap_bulk_read(dev->regmap, reg, val, val_count);
Peter Rosindfecde42018-06-20 07:17:59 +020043 i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
Antti Palosaari15d37f32014-12-12 01:03:51 -030044 return ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -030045}
46
47static int rtl2830_init(struct dvb_frontend *fe)
48{
Antti Palosaari1f153c42014-12-08 22:47:21 -030049 struct i2c_client *client = fe->demodulator_priv;
50 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari47b4dbf2014-12-09 06:14:36 -030051 struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
Antti Palosaaric0adca72011-07-08 23:34:09 -030052 int ret, i;
Antti Palosaaric0adca72011-07-08 23:34:09 -030053 struct rtl2830_reg_val_mask tab[] = {
Antti Palosaari947debb2014-12-09 02:31:53 -030054 {0x00d, 0x01, 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},
Antti Palosaaric0adca72011-07-08 23:34:09 -030090 };
91
92 for (i = 0; i < ARRAY_SIZE(tab); i++) {
Antti Palosaari15d37f32014-12-12 01:03:51 -030093 ret = rtl2830_update_bits(client, tab[i].reg, tab[i].mask,
94 tab[i].val);
Antti Palosaaric0adca72011-07-08 23:34:09 -030095 if (ret)
96 goto err;
97 }
98
Antti Palosaari15d37f32014-12-12 01:03:51 -030099 ret = rtl2830_bulk_write(client, 0x18f, "\x28\x00", 2);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300100 if (ret)
101 goto err;
102
Antti Palosaari15d37f32014-12-12 01:03:51 -0300103 ret = rtl2830_bulk_write(client, 0x195,
104 "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300105 if (ret)
106 goto err;
107
Antti Palosaaric0adca72011-07-08 23:34:09 -0300108 /* TODO: spec init */
109
110 /* soft reset */
Antti Palosaari15d37f32014-12-12 01:03:51 -0300111 ret = rtl2830_update_bits(client, 0x101, 0x04, 0x04);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300112 if (ret)
113 goto err;
114
Antti Palosaari15d37f32014-12-12 01:03:51 -0300115 ret = rtl2830_update_bits(client, 0x101, 0x04, 0x00);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300116 if (ret)
117 goto err;
118
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300119 /* init stats here in order signal app which stats are supported */
Antti Palosaari871f7022014-12-09 08:49:44 -0300120 c->strength.len = 1;
121 c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300122 c->cnr.len = 1;
123 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
Antti Palosaari5bb11ca2014-12-09 09:45:16 -0300124 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;
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300128
Antti Palosaarif544f102014-12-08 22:31:28 -0300129 dev->sleeping = false;
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300130
Antti Palosaaric0adca72011-07-08 23:34:09 -0300131 return ret;
132err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300133 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300134 return ret;
135}
136
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300137static int rtl2830_sleep(struct dvb_frontend *fe)
138{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300139 struct i2c_client *client = fe->demodulator_priv;
140 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari947debb2014-12-09 02:31:53 -0300141
Antti Palosaarif544f102014-12-08 22:31:28 -0300142 dev->sleeping = true;
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300143 dev->fe_status = 0;
Antti Palosaari947debb2014-12-09 02:31:53 -0300144
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300145 return 0;
146}
147
Mauro Carvalho Chehaba17ff2e2012-10-27 11:24:08 -0300148static int rtl2830_get_tune_settings(struct dvb_frontend *fe,
Antti Palosaari947debb2014-12-09 02:31:53 -0300149 struct dvb_frontend_tune_settings *s)
Antti Palosaaric0adca72011-07-08 23:34:09 -0300150{
151 s->min_delay_ms = 500;
Mauro Carvalho Chehabf1b1eab2018-07-05 18:59:36 -0400152 s->step_size = fe->ops.info.frequency_stepsize_hz * 2;
153 s->max_drift = (fe->ops.info.frequency_stepsize_hz * 2) + 1;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300154
155 return 0;
156}
157
158static int rtl2830_set_frontend(struct dvb_frontend *fe)
159{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300160 struct i2c_client *client = fe->demodulator_priv;
161 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300162 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
163 int ret, i;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300164 u64 num;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300165 u8 buf[3], u8tmp;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300166 u32 if_ctl, if_frequency;
Antti Palosaari3a2fca22012-09-12 20:23:49 -0300167 static const u8 bw_params1[3][34] = {
Antti Palosaaric0adca72011-07-08 23:34:09 -0300168 {
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 };
Antti Palosaari3a2fca22012-09-12 20:23:49 -0300185 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 */
Antti Palosaaric0adca72011-07-08 23:34:09 -0300189 };
190
Antti Palosaari7cc39322014-12-08 23:32:19 -0300191 dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u inversion=%u\n",
Antti Palosaari947debb2014-12-09 02:31:53 -0300192 c->frequency, c->bandwidth_hz, c->inversion);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300193
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:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300209 dev_err(&client->dev, "invalid bandwidth_hz %u\n",
Antti Palosaari947debb2014-12-09 02:31:53 -0300210 c->bandwidth_hz);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300211 return -EINVAL;
212 }
213
Antti Palosaari15d37f32014-12-12 01:03:51 -0300214 ret = rtl2830_update_bits(client, 0x008, 0x06, i << 1);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300215 if (ret)
216 goto err;
217
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300218 /* 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;
Antti Palosaari947debb2014-12-09 02:31:53 -0300223 if (ret)
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300224 goto err;
225
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300226 num = if_frequency % dev->pdata->clk;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300227 num *= 0x400000;
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300228 num = div_u64(num, dev->pdata->clk);
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300229 num = -num;
230 if_ctl = num & 0x3fffff;
Antti Palosaari7cc39322014-12-08 23:32:19 -0300231 dev_dbg(&client->dev, "if_frequency=%d if_ctl=%08x\n",
Antti Palosaari947debb2014-12-09 02:31:53 -0300232 if_frequency, if_ctl);
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300233
Antti Palosaari15d37f32014-12-12 01:03:51 -0300234 buf[0] = (if_ctl >> 16) & 0x3f;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300235 buf[1] = (if_ctl >> 8) & 0xff;
236 buf[2] = (if_ctl >> 0) & 0xff;
237
Antti Palosaari15d37f32014-12-12 01:03:51 -0300238 ret = rtl2830_bulk_read(client, 0x119, &u8tmp, 1);
239 if (ret)
240 goto err;
241
242 buf[0] |= u8tmp & 0xc0; /* [7:6] */
243
244 ret = rtl2830_bulk_write(client, 0x119, buf, 3);
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300245 if (ret)
246 goto err;
247
Antti Palosaaric0adca72011-07-08 23:34:09 -0300248 /* 1/2 split I2C write */
Antti Palosaari15d37f32014-12-12 01:03:51 -0300249 ret = rtl2830_bulk_write(client, 0x11c, &bw_params1[i][0], 17);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300250 if (ret)
251 goto err;
252
253 /* 2/2 split I2C write */
Antti Palosaari15d37f32014-12-12 01:03:51 -0300254 ret = rtl2830_bulk_write(client, 0x12d, &bw_params1[i][17], 17);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300255 if (ret)
256 goto err;
257
Antti Palosaari15d37f32014-12-12 01:03:51 -0300258 ret = rtl2830_bulk_write(client, 0x19d, bw_params2[i], 6);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300259 if (ret)
260 goto err;
261
262 return ret;
263err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300264 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300265 return ret;
266}
267
Mauro Carvalho Chehab7e3e68b2016-02-04 12:58:30 -0200268static int rtl2830_get_frontend(struct dvb_frontend *fe,
269 struct dtv_frontend_properties *c)
Antti Palosaari631a2b62012-05-18 15:58:57 -0300270{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300271 struct i2c_client *client = fe->demodulator_priv;
272 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300273 int ret;
274 u8 buf[3];
275
Antti Palosaarif544f102014-12-08 22:31:28 -0300276 if (dev->sleeping)
Antti Palosaaric1886372012-05-18 16:02:55 -0300277 return 0;
278
Antti Palosaari15d37f32014-12-12 01:03:51 -0300279 ret = rtl2830_bulk_read(client, 0x33c, buf, 2);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300280 if (ret)
281 goto err;
282
Antti Palosaari15d37f32014-12-12 01:03:51 -0300283 ret = rtl2830_bulk_read(client, 0x351, &buf[2], 1);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300284 if (ret)
285 goto err;
286
Antti Palosaari7cc39322014-12-08 23:32:19 -0300287 dev_dbg(&client->dev, "TPS=%*ph\n", 3, buf);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300288
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;
376err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300377 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300378 return ret;
379}
380
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -0300381static int rtl2830_read_status(struct dvb_frontend *fe, enum fe_status *status)
Antti Palosaaric0adca72011-07-08 23:34:09 -0300382{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300383 struct i2c_client *client = fe->demodulator_priv;
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300384 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari4a7e4452016-06-29 20:40:56 -0300385 struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
386 int ret, stmp;
387 unsigned int utmp;
388 u8 u8tmp, buf[2];
Antti Palosaari947debb2014-12-09 02:31:53 -0300389
Antti Palosaaric0adca72011-07-08 23:34:09 -0300390 *status = 0;
391
Antti Palosaarif544f102014-12-08 22:31:28 -0300392 if (dev->sleeping)
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300393 return 0;
394
Antti Palosaari15d37f32014-12-12 01:03:51 -0300395 ret = rtl2830_bulk_read(client, 0x351, &u8tmp, 1);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300396 if (ret)
397 goto err;
398
Antti Palosaari15d37f32014-12-12 01:03:51 -0300399 u8tmp = (u8tmp >> 3) & 0x0f; /* [6:3] */
400 if (u8tmp == 11) {
Antti Palosaaric0adca72011-07-08 23:34:09 -0300401 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
402 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300403 } else if (u8tmp == 10) {
Antti Palosaaric0adca72011-07-08 23:34:09 -0300404 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
405 FE_HAS_VITERBI;
406 }
407
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300408 dev->fe_status = *status;
409
Antti Palosaari4a7e4452016-06-29 20:40:56 -0300410 /* Signal strength */
411 if (dev->fe_status & FE_HAS_SIGNAL) {
412 /* Read IF AGC */
413 ret = rtl2830_bulk_read(client, 0x359, buf, 2);
414 if (ret)
415 goto err;
416
417 stmp = buf[0] << 8 | buf[1] << 0;
418 stmp = sign_extend32(stmp, 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, 0x33c, &u8tmp, 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, 0x40c, buf, 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(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, 0x34e, buf, 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
Antti Palosaaric0adca72011-07-08 23:34:09 -0300493 return ret;
494err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300495 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300496 return ret;
497}
498
499static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
500{
Antti Palosaari6dcfe3c2014-12-09 10:48:10 -0300501 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Antti Palosaarieba672a2012-05-15 18:32:33 -0300502
Antti Palosaari6dcfe3c2014-12-09 10:48:10 -0300503 if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL)
504 *snr = div_s64(c->cnr.stat[0].svalue, 100);
Antti Palosaarieba672a2012-05-15 18:32:33 -0300505 else
506 *snr = 0;
507
Antti Palosaaric0adca72011-07-08 23:34:09 -0300508 return 0;
509}
510
511static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
512{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300513 struct i2c_client *client = fe->demodulator_priv;
514 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari525ffc12012-05-18 12:23:42 -0300515
Antti Palosaarif4913912014-12-09 10:27:32 -0300516 *ber = (dev->post_bit_error - dev->post_bit_error_prev);
517 dev->post_bit_error_prev = dev->post_bit_error;
Antti Palosaari525ffc12012-05-18 12:23:42 -0300518
Antti Palosaaric0adca72011-07-08 23:34:09 -0300519 return 0;
520}
521
522static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
523{
524 *ucblocks = 0;
Antti Palosaari947debb2014-12-09 02:31:53 -0300525
Antti Palosaaric0adca72011-07-08 23:34:09 -0300526 return 0;
527}
528
529static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
530{
Antti Palosaarid512e2862014-12-09 10:20:01 -0300531 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Antti Palosaari78e75072012-05-18 15:17:51 -0300532
Antti Palosaarid512e2862014-12-09 10:20:01 -0300533 if (c->strength.stat[0].scale == FE_SCALE_RELATIVE)
534 *strength = c->strength.stat[0].uvalue;
Antti Palosaari78e75072012-05-18 15:17:51 -0300535 else
Antti Palosaarid512e2862014-12-09 10:20:01 -0300536 *strength = 0;
Antti Palosaari78e75072012-05-18 15:17:51 -0300537
Antti Palosaaric0adca72011-07-08 23:34:09 -0300538 return 0;
539}
540
Max Kellermannbd336e62016-08-09 18:32:21 -0300541static const struct dvb_frontend_ops rtl2830_ops = {
Antti Palosaari947debb2014-12-09 02:31:53 -0300542 .delsys = {SYS_DVBT},
Antti Palosaaric0adca72011-07-08 23:34:09 -0300543 .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
Antti Palosaaric0adca72011-07-08 23:34:09 -0300562 .init = rtl2830_init,
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300563 .sleep = rtl2830_sleep,
Antti Palosaaric0adca72011-07-08 23:34:09 -0300564
565 .get_tune_settings = rtl2830_get_tune_settings,
566
567 .set_frontend = rtl2830_set_frontend,
Antti Palosaari631a2b62012-05-18 15:58:57 -0300568 .get_frontend = rtl2830_get_frontend,
Antti Palosaaric0adca72011-07-08 23:34:09 -0300569
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
Antti Palosaaridf70dda2014-12-09 16:08:44 -0300577static 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
Antti Palosaari15d37f32014-12-12 01:03:51 -0300591 ret = rtl2830_update_bits(client, 0x061, 0x80, u8tmp);
Antti Palosaaridf70dda2014-12-09 16:08:44 -0300592 if (ret)
593 goto err;
594
595 return 0;
596err:
597 dev_dbg(&client->dev, "failed=%d\n", ret);
598 return ret;
599}
600
601static 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(index, &dev->filters);
617 else
618 clear_bit(index, &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;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300625 ret = rtl2830_bulk_write(client, 0x062, buf, 4);
Antti Palosaaridf70dda2014-12-09 16:08:44 -0300626 if (ret)
627 goto err;
628
629 /* add PID */
630 buf[0] = (pid >> 8) & 0xff;
631 buf[1] = (pid >> 0) & 0xff;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300632 ret = rtl2830_bulk_write(client, 0x066 + 2 * index, buf, 2);
Antti Palosaaridf70dda2014-12-09 16:08:44 -0300633 if (ret)
634 goto err;
635
636 return 0;
637err:
638 dev_dbg(&client->dev, "failed=%d\n", ret);
639 return ret;
640}
641
Antti Palosaari28c08792014-12-07 04:07:29 -0300642/*
Antti Palosaari15d37f32014-12-12 01:03:51 -0300643 * 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.
Antti Palosaari28c08792014-12-07 04:07:29 -0300647 */
Peter Rosina0119152016-04-20 08:41:13 +0200648static int rtl2830_select(struct i2c_mux_core *muxc, u32 chan_id)
Antti Palosaari28c08792014-12-07 04:07:29 -0300649{
Peter Rosina0119152016-04-20 08:41:13 +0200650 struct i2c_client *client = i2c_mux_priv(muxc);
Antti Palosaarif544f102014-12-08 22:31:28 -0300651 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300652 int ret;
653
Antti Palosaarifd4cfa82014-12-09 16:14:41 -0300654 dev_dbg(&client->dev, "\n");
655
Antti Palosaari15d37f32014-12-12 01:03:51 -0300656 /* open I2C repeater for 1 transfer, closes automatically */
657 /* XXX: regmap_update_bits() does not lock I2C adapter */
658 ret = regmap_update_bits(dev->regmap, 0x101, 0x08, 0x08);
659 if (ret)
Antti Palosaari28c08792014-12-07 04:07:29 -0300660 goto err;
Antti Palosaari28c08792014-12-07 04:07:29 -0300661
662 return 0;
Antti Palosaari28c08792014-12-07 04:07:29 -0300663err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300664 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaari28c08792014-12-07 04:07:29 -0300665 return ret;
666}
667
668static struct dvb_frontend *rtl2830_get_dvb_frontend(struct i2c_client *client)
669{
Antti Palosaarif544f102014-12-08 22:31:28 -0300670 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300671
672 dev_dbg(&client->dev, "\n");
673
Antti Palosaarif544f102014-12-08 22:31:28 -0300674 return &dev->fe;
Antti Palosaari28c08792014-12-07 04:07:29 -0300675}
676
677static struct i2c_adapter *rtl2830_get_i2c_adapter(struct i2c_client *client)
678{
Antti Palosaarif544f102014-12-08 22:31:28 -0300679 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300680
681 dev_dbg(&client->dev, "\n");
682
Peter Rosina0119152016-04-20 08:41:13 +0200683 return dev->muxc->adapter[0];
Antti Palosaari28c08792014-12-07 04:07:29 -0300684}
685
Antti Palosaari15d37f32014-12-12 01:03:51 -0300686/*
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 */
690static 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(client->adapter, msg, 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
719static 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(client->adapter, msg, 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
742static 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(client->adapter, msg, 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
Antti Palosaari28c08792014-12-07 04:07:29 -0300771static int rtl2830_probe(struct i2c_client *client,
Antti Palosaari947debb2014-12-09 02:31:53 -0300772 const struct i2c_device_id *id)
Antti Palosaari28c08792014-12-07 04:07:29 -0300773{
774 struct rtl2830_platform_data *pdata = client->dev.platform_data;
Antti Palosaarif544f102014-12-08 22:31:28 -0300775 struct rtl2830_dev *dev;
Antti Palosaari28c08792014-12-07 04:07:29 -0300776 int ret;
777 u8 u8tmp;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300778 static const struct regmap_bus regmap_bus = {
779 .read = rtl2830_regmap_read,
780 .write = rtl2830_regmap_write,
781 .gather_write = rtl2830_regmap_gather_write,
782 .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
783 };
784 static const struct regmap_range_cfg regmap_range_cfg[] = {
785 {
786 .selector_reg = 0x00,
787 .selector_mask = 0xff,
788 .selector_shift = 0,
789 .window_start = 0,
790 .window_len = 0x100,
791 .range_min = 0 * 0x100,
792 .range_max = 5 * 0x100,
793 },
794 };
795 static const struct regmap_config regmap_config = {
796 .reg_bits = 8,
797 .val_bits = 8,
798 .max_register = 5 * 0x100,
799 .ranges = regmap_range_cfg,
800 .num_ranges = ARRAY_SIZE(regmap_range_cfg),
801 };
Antti Palosaari28c08792014-12-07 04:07:29 -0300802
803 dev_dbg(&client->dev, "\n");
804
805 if (pdata == NULL) {
806 ret = -EINVAL;
807 goto err;
808 }
809
810 /* allocate memory for the internal state */
Antti Palosaarif544f102014-12-08 22:31:28 -0300811 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
812 if (dev == NULL) {
Antti Palosaari28c08792014-12-07 04:07:29 -0300813 ret = -ENOMEM;
814 goto err;
815 }
816
817 /* setup the state */
Antti Palosaarif544f102014-12-08 22:31:28 -0300818 i2c_set_clientdata(client, dev);
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300819 dev->client = client;
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300820 dev->pdata = client->dev.platform_data;
Antti Palosaarif544f102014-12-08 22:31:28 -0300821 dev->sleeping = true;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300822 dev->regmap = regmap_init(&client->dev, &regmap_bus, client,
823 &regmap_config);
824 if (IS_ERR(dev->regmap)) {
825 ret = PTR_ERR(dev->regmap);
826 goto err_kfree;
827 }
Antti Palosaari28c08792014-12-07 04:07:29 -0300828
829 /* check if the demod is there */
Antti Palosaari15d37f32014-12-12 01:03:51 -0300830 ret = rtl2830_bulk_read(client, 0x000, &u8tmp, 1);
Antti Palosaari28c08792014-12-07 04:07:29 -0300831 if (ret)
Antti Palosaari15d37f32014-12-12 01:03:51 -0300832 goto err_regmap_exit;
Antti Palosaari28c08792014-12-07 04:07:29 -0300833
834 /* create muxed i2c adapter for tuner */
Peter Rosina0119152016-04-20 08:41:13 +0200835 dev->muxc = i2c_mux_alloc(client->adapter, &client->dev, 1, 0, 0,
836 rtl2830_select, NULL);
837 if (!dev->muxc) {
838 ret = -ENOMEM;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300839 goto err_regmap_exit;
Antti Palosaari28c08792014-12-07 04:07:29 -0300840 }
Peter Rosina0119152016-04-20 08:41:13 +0200841 dev->muxc->priv = client;
842 ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0);
843 if (ret)
844 goto err_regmap_exit;
Antti Palosaari28c08792014-12-07 04:07:29 -0300845
846 /* create dvb frontend */
Antti Palosaarif544f102014-12-08 22:31:28 -0300847 memcpy(&dev->fe.ops, &rtl2830_ops, sizeof(dev->fe.ops));
Antti Palosaari1f153c42014-12-08 22:47:21 -0300848 dev->fe.demodulator_priv = client;
Antti Palosaari28c08792014-12-07 04:07:29 -0300849
850 /* setup callbacks */
851 pdata->get_dvb_frontend = rtl2830_get_dvb_frontend;
852 pdata->get_i2c_adapter = rtl2830_get_i2c_adapter;
Antti Palosaaridf70dda2014-12-09 16:08:44 -0300853 pdata->pid_filter = rtl2830_pid_filter;
854 pdata->pid_filter_ctrl = rtl2830_pid_filter_ctrl;
Antti Palosaari28c08792014-12-07 04:07:29 -0300855
856 dev_info(&client->dev, "Realtek RTL2830 successfully attached\n");
Antti Palosaari28c08792014-12-07 04:07:29 -0300857
Antti Palosaari947debb2014-12-09 02:31:53 -0300858 return 0;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300859err_regmap_exit:
860 regmap_exit(dev->regmap);
Antti Palosaari28c08792014-12-07 04:07:29 -0300861err_kfree:
Antti Palosaarif544f102014-12-08 22:31:28 -0300862 kfree(dev);
Antti Palosaari28c08792014-12-07 04:07:29 -0300863err:
864 dev_dbg(&client->dev, "failed=%d\n", ret);
865 return ret;
866}
867
868static int rtl2830_remove(struct i2c_client *client)
869{
Antti Palosaarif544f102014-12-08 22:31:28 -0300870 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300871
872 dev_dbg(&client->dev, "\n");
873
Peter Rosina0119152016-04-20 08:41:13 +0200874 i2c_mux_del_adapters(dev->muxc);
Antti Palosaari15d37f32014-12-12 01:03:51 -0300875 regmap_exit(dev->regmap);
Antti Palosaarif544f102014-12-08 22:31:28 -0300876 kfree(dev);
Antti Palosaari947debb2014-12-09 02:31:53 -0300877
Antti Palosaari28c08792014-12-07 04:07:29 -0300878 return 0;
879}
880
881static const struct i2c_device_id rtl2830_id_table[] = {
882 {"rtl2830", 0},
883 {}
884};
885MODULE_DEVICE_TABLE(i2c, rtl2830_id_table);
886
887static struct i2c_driver rtl2830_driver = {
888 .driver = {
Antti Palosaari95e7cdb2016-06-29 20:40:55 -0300889 .name = "rtl2830",
890 .suppress_bind_attrs = true,
Antti Palosaari28c08792014-12-07 04:07:29 -0300891 },
892 .probe = rtl2830_probe,
893 .remove = rtl2830_remove,
894 .id_table = rtl2830_id_table,
895};
896
897module_i2c_driver(rtl2830_driver);
898
Antti Palosaaric0adca72011-07-08 23:34:09 -0300899MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
900MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver");
901MODULE_LICENSE("GPL");