blob: b792f305cf15f05fc1289a4bdd0566269bfd15e0 [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 /* start statistics polling */
139 schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
140
Antti Palosaarif544f102014-12-08 22:31:28 -0300141 dev->sleeping = false;
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300142
Antti Palosaaric0adca72011-07-08 23:34:09 -0300143 return ret;
144err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300145 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300146 return ret;
147}
148
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300149static int rtl2830_sleep(struct dvb_frontend *fe)
150{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300151 struct i2c_client *client = fe->demodulator_priv;
152 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari947debb2014-12-09 02:31:53 -0300153
Antti Palosaarif544f102014-12-08 22:31:28 -0300154 dev->sleeping = true;
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300155 /* stop statistics polling */
156 cancel_delayed_work_sync(&dev->stat_work);
157 dev->fe_status = 0;
Antti Palosaari947debb2014-12-09 02:31:53 -0300158
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300159 return 0;
160}
161
Mauro Carvalho Chehaba17ff2e2012-10-27 11:24:08 -0300162static int rtl2830_get_tune_settings(struct dvb_frontend *fe,
Antti Palosaari947debb2014-12-09 02:31:53 -0300163 struct dvb_frontend_tune_settings *s)
Antti Palosaaric0adca72011-07-08 23:34:09 -0300164{
165 s->min_delay_ms = 500;
166 s->step_size = fe->ops.info.frequency_stepsize * 2;
167 s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
168
169 return 0;
170}
171
172static int rtl2830_set_frontend(struct dvb_frontend *fe)
173{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300174 struct i2c_client *client = fe->demodulator_priv;
175 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300176 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
177 int ret, i;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300178 u64 num;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300179 u8 buf[3], u8tmp;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300180 u32 if_ctl, if_frequency;
Antti Palosaari3a2fca22012-09-12 20:23:49 -0300181 static const u8 bw_params1[3][34] = {
Antti Palosaaric0adca72011-07-08 23:34:09 -0300182 {
183 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41,
184 0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a,
185 0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82,
186 0x03, 0x73, 0x03, 0xcf, /* 6 MHz */
187 }, {
188 0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca,
189 0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca,
190 0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e,
191 0x03, 0xd0, 0x04, 0x53, /* 7 MHz */
192 }, {
193 0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0,
194 0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a,
195 0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f,
196 0x04, 0x24, 0x04, 0xdb, /* 8 MHz */
197 },
198 };
Antti Palosaari3a2fca22012-09-12 20:23:49 -0300199 static const u8 bw_params2[3][6] = {
200 {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30}, /* 6 MHz */
201 {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98}, /* 7 MHz */
202 {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64}, /* 8 MHz */
Antti Palosaaric0adca72011-07-08 23:34:09 -0300203 };
204
Antti Palosaari7cc39322014-12-08 23:32:19 -0300205 dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u inversion=%u\n",
Antti Palosaari947debb2014-12-09 02:31:53 -0300206 c->frequency, c->bandwidth_hz, c->inversion);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300207
208 /* program tuner */
209 if (fe->ops.tuner_ops.set_params)
210 fe->ops.tuner_ops.set_params(fe);
211
212 switch (c->bandwidth_hz) {
213 case 6000000:
214 i = 0;
215 break;
216 case 7000000:
217 i = 1;
218 break;
219 case 8000000:
220 i = 2;
221 break;
222 default:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300223 dev_err(&client->dev, "invalid bandwidth_hz %u\n",
Antti Palosaari947debb2014-12-09 02:31:53 -0300224 c->bandwidth_hz);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300225 return -EINVAL;
226 }
227
Antti Palosaari15d37f32014-12-12 01:03:51 -0300228 ret = rtl2830_update_bits(client, 0x008, 0x06, i << 1);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300229 if (ret)
230 goto err;
231
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300232 /* program if frequency */
233 if (fe->ops.tuner_ops.get_if_frequency)
234 ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
235 else
236 ret = -EINVAL;
Antti Palosaari947debb2014-12-09 02:31:53 -0300237 if (ret)
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300238 goto err;
239
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300240 num = if_frequency % dev->pdata->clk;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300241 num *= 0x400000;
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300242 num = div_u64(num, dev->pdata->clk);
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300243 num = -num;
244 if_ctl = num & 0x3fffff;
Antti Palosaari7cc39322014-12-08 23:32:19 -0300245 dev_dbg(&client->dev, "if_frequency=%d if_ctl=%08x\n",
Antti Palosaari947debb2014-12-09 02:31:53 -0300246 if_frequency, if_ctl);
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300247
Antti Palosaari15d37f32014-12-12 01:03:51 -0300248 buf[0] = (if_ctl >> 16) & 0x3f;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300249 buf[1] = (if_ctl >> 8) & 0xff;
250 buf[2] = (if_ctl >> 0) & 0xff;
251
Antti Palosaari15d37f32014-12-12 01:03:51 -0300252 ret = rtl2830_bulk_read(client, 0x119, &u8tmp, 1);
253 if (ret)
254 goto err;
255
256 buf[0] |= u8tmp & 0xc0; /* [7:6] */
257
258 ret = rtl2830_bulk_write(client, 0x119, buf, 3);
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300259 if (ret)
260 goto err;
261
Antti Palosaaric0adca72011-07-08 23:34:09 -0300262 /* 1/2 split I2C write */
Antti Palosaari15d37f32014-12-12 01:03:51 -0300263 ret = rtl2830_bulk_write(client, 0x11c, &bw_params1[i][0], 17);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300264 if (ret)
265 goto err;
266
267 /* 2/2 split I2C write */
Antti Palosaari15d37f32014-12-12 01:03:51 -0300268 ret = rtl2830_bulk_write(client, 0x12d, &bw_params1[i][17], 17);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300269 if (ret)
270 goto err;
271
Antti Palosaari15d37f32014-12-12 01:03:51 -0300272 ret = rtl2830_bulk_write(client, 0x19d, bw_params2[i], 6);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300273 if (ret)
274 goto err;
275
276 return ret;
277err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300278 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300279 return ret;
280}
281
Antti Palosaari631a2b62012-05-18 15:58:57 -0300282static int rtl2830_get_frontend(struct dvb_frontend *fe)
283{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300284 struct i2c_client *client = fe->demodulator_priv;
285 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300286 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
287 int ret;
288 u8 buf[3];
289
Antti Palosaarif544f102014-12-08 22:31:28 -0300290 if (dev->sleeping)
Antti Palosaaric1886372012-05-18 16:02:55 -0300291 return 0;
292
Antti Palosaari15d37f32014-12-12 01:03:51 -0300293 ret = rtl2830_bulk_read(client, 0x33c, buf, 2);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300294 if (ret)
295 goto err;
296
Antti Palosaari15d37f32014-12-12 01:03:51 -0300297 ret = rtl2830_bulk_read(client, 0x351, &buf[2], 1);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300298 if (ret)
299 goto err;
300
Antti Palosaari7cc39322014-12-08 23:32:19 -0300301 dev_dbg(&client->dev, "TPS=%*ph\n", 3, buf);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300302
303 switch ((buf[0] >> 2) & 3) {
304 case 0:
305 c->modulation = QPSK;
306 break;
307 case 1:
308 c->modulation = QAM_16;
309 break;
310 case 2:
311 c->modulation = QAM_64;
312 break;
313 }
314
315 switch ((buf[2] >> 2) & 1) {
316 case 0:
317 c->transmission_mode = TRANSMISSION_MODE_2K;
318 break;
319 case 1:
320 c->transmission_mode = TRANSMISSION_MODE_8K;
321 }
322
323 switch ((buf[2] >> 0) & 3) {
324 case 0:
325 c->guard_interval = GUARD_INTERVAL_1_32;
326 break;
327 case 1:
328 c->guard_interval = GUARD_INTERVAL_1_16;
329 break;
330 case 2:
331 c->guard_interval = GUARD_INTERVAL_1_8;
332 break;
333 case 3:
334 c->guard_interval = GUARD_INTERVAL_1_4;
335 break;
336 }
337
338 switch ((buf[0] >> 4) & 7) {
339 case 0:
340 c->hierarchy = HIERARCHY_NONE;
341 break;
342 case 1:
343 c->hierarchy = HIERARCHY_1;
344 break;
345 case 2:
346 c->hierarchy = HIERARCHY_2;
347 break;
348 case 3:
349 c->hierarchy = HIERARCHY_4;
350 break;
351 }
352
353 switch ((buf[1] >> 3) & 7) {
354 case 0:
355 c->code_rate_HP = FEC_1_2;
356 break;
357 case 1:
358 c->code_rate_HP = FEC_2_3;
359 break;
360 case 2:
361 c->code_rate_HP = FEC_3_4;
362 break;
363 case 3:
364 c->code_rate_HP = FEC_5_6;
365 break;
366 case 4:
367 c->code_rate_HP = FEC_7_8;
368 break;
369 }
370
371 switch ((buf[1] >> 0) & 7) {
372 case 0:
373 c->code_rate_LP = FEC_1_2;
374 break;
375 case 1:
376 c->code_rate_LP = FEC_2_3;
377 break;
378 case 2:
379 c->code_rate_LP = FEC_3_4;
380 break;
381 case 3:
382 c->code_rate_LP = FEC_5_6;
383 break;
384 case 4:
385 c->code_rate_LP = FEC_7_8;
386 break;
387 }
388
389 return 0;
390err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300391 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300392 return ret;
393}
394
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -0300395static int rtl2830_read_status(struct dvb_frontend *fe, enum fe_status *status)
Antti Palosaaric0adca72011-07-08 23:34:09 -0300396{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300397 struct i2c_client *client = fe->demodulator_priv;
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300398 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300399 int ret;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300400 u8 u8tmp;
Antti Palosaari947debb2014-12-09 02:31:53 -0300401
Antti Palosaaric0adca72011-07-08 23:34:09 -0300402 *status = 0;
403
Antti Palosaarif544f102014-12-08 22:31:28 -0300404 if (dev->sleeping)
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300405 return 0;
406
Antti Palosaari15d37f32014-12-12 01:03:51 -0300407 ret = rtl2830_bulk_read(client, 0x351, &u8tmp, 1);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300408 if (ret)
409 goto err;
410
Antti Palosaari15d37f32014-12-12 01:03:51 -0300411 u8tmp = (u8tmp >> 3) & 0x0f; /* [6:3] */
412 if (u8tmp == 11) {
Antti Palosaaric0adca72011-07-08 23:34:09 -0300413 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
414 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300415 } else if (u8tmp == 10) {
Antti Palosaaric0adca72011-07-08 23:34:09 -0300416 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
417 FE_HAS_VITERBI;
418 }
419
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300420 dev->fe_status = *status;
421
Antti Palosaaric0adca72011-07-08 23:34:09 -0300422 return ret;
423err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300424 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300425 return ret;
426}
427
428static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
429{
Antti Palosaari6dcfe3c2014-12-09 10:48:10 -0300430 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Antti Palosaarieba672a2012-05-15 18:32:33 -0300431
Antti Palosaari6dcfe3c2014-12-09 10:48:10 -0300432 if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL)
433 *snr = div_s64(c->cnr.stat[0].svalue, 100);
Antti Palosaarieba672a2012-05-15 18:32:33 -0300434 else
435 *snr = 0;
436
Antti Palosaaric0adca72011-07-08 23:34:09 -0300437 return 0;
438}
439
440static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
441{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300442 struct i2c_client *client = fe->demodulator_priv;
443 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari525ffc12012-05-18 12:23:42 -0300444
Antti Palosaarif4913912014-12-09 10:27:32 -0300445 *ber = (dev->post_bit_error - dev->post_bit_error_prev);
446 dev->post_bit_error_prev = dev->post_bit_error;
Antti Palosaari525ffc12012-05-18 12:23:42 -0300447
Antti Palosaaric0adca72011-07-08 23:34:09 -0300448 return 0;
449}
450
451static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
452{
453 *ucblocks = 0;
Antti Palosaari947debb2014-12-09 02:31:53 -0300454
Antti Palosaaric0adca72011-07-08 23:34:09 -0300455 return 0;
456}
457
458static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
459{
Antti Palosaarid512e2862014-12-09 10:20:01 -0300460 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Antti Palosaari78e75072012-05-18 15:17:51 -0300461
Antti Palosaarid512e2862014-12-09 10:20:01 -0300462 if (c->strength.stat[0].scale == FE_SCALE_RELATIVE)
463 *strength = c->strength.stat[0].uvalue;
Antti Palosaari78e75072012-05-18 15:17:51 -0300464 else
Antti Palosaarid512e2862014-12-09 10:20:01 -0300465 *strength = 0;
Antti Palosaari78e75072012-05-18 15:17:51 -0300466
Antti Palosaaric0adca72011-07-08 23:34:09 -0300467 return 0;
468}
469
Antti Palosaaric0adca72011-07-08 23:34:09 -0300470static struct dvb_frontend_ops rtl2830_ops = {
Antti Palosaari947debb2014-12-09 02:31:53 -0300471 .delsys = {SYS_DVBT},
Antti Palosaaric0adca72011-07-08 23:34:09 -0300472 .info = {
473 .name = "Realtek RTL2830 (DVB-T)",
474 .caps = FE_CAN_FEC_1_2 |
475 FE_CAN_FEC_2_3 |
476 FE_CAN_FEC_3_4 |
477 FE_CAN_FEC_5_6 |
478 FE_CAN_FEC_7_8 |
479 FE_CAN_FEC_AUTO |
480 FE_CAN_QPSK |
481 FE_CAN_QAM_16 |
482 FE_CAN_QAM_64 |
483 FE_CAN_QAM_AUTO |
484 FE_CAN_TRANSMISSION_MODE_AUTO |
485 FE_CAN_GUARD_INTERVAL_AUTO |
486 FE_CAN_HIERARCHY_AUTO |
487 FE_CAN_RECOVER |
488 FE_CAN_MUTE_TS
489 },
490
Antti Palosaaric0adca72011-07-08 23:34:09 -0300491 .init = rtl2830_init,
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300492 .sleep = rtl2830_sleep,
Antti Palosaaric0adca72011-07-08 23:34:09 -0300493
494 .get_tune_settings = rtl2830_get_tune_settings,
495
496 .set_frontend = rtl2830_set_frontend,
Antti Palosaari631a2b62012-05-18 15:58:57 -0300497 .get_frontend = rtl2830_get_frontend,
Antti Palosaaric0adca72011-07-08 23:34:09 -0300498
499 .read_status = rtl2830_read_status,
500 .read_snr = rtl2830_read_snr,
501 .read_ber = rtl2830_read_ber,
502 .read_ucblocks = rtl2830_read_ucblocks,
503 .read_signal_strength = rtl2830_read_signal_strength,
504};
505
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300506static void rtl2830_stat_work(struct work_struct *work)
507{
508 struct rtl2830_dev *dev = container_of(work, struct rtl2830_dev, stat_work.work);
509 struct i2c_client *client = dev->client;
510 struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
511 int ret, tmp;
512 u8 u8tmp, buf[2];
513 u16 u16tmp;
514
515 dev_dbg(&client->dev, "\n");
516
Antti Palosaari871f7022014-12-09 08:49:44 -0300517 /* signal strength */
518 if (dev->fe_status & FE_HAS_SIGNAL) {
519 struct {signed int x:14; } s;
520
521 /* read IF AGC */
Antti Palosaari15d37f32014-12-12 01:03:51 -0300522 ret = rtl2830_bulk_read(client, 0x359, buf, 2);
Antti Palosaari871f7022014-12-09 08:49:44 -0300523 if (ret)
524 goto err;
525
526 u16tmp = buf[0] << 8 | buf[1] << 0;
527 u16tmp &= 0x3fff; /* [13:0] */
528 tmp = s.x = u16tmp; /* 14-bit bin to 2 complement */
529 u16tmp = clamp_val(-4 * tmp + 32767, 0x0000, 0xffff);
530
531 dev_dbg(&client->dev, "IF AGC=%d\n", tmp);
532
533 c->strength.stat[0].scale = FE_SCALE_RELATIVE;
534 c->strength.stat[0].uvalue = u16tmp;
535 } else {
536 c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
537 }
538
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300539 /* CNR */
540 if (dev->fe_status & FE_HAS_VITERBI) {
541 unsigned hierarchy, constellation;
542 #define CONSTELLATION_NUM 3
543 #define HIERARCHY_NUM 4
544 static const u32 constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
545 {70705899, 70705899, 70705899, 70705899},
546 {82433173, 82433173, 87483115, 94445660},
547 {92888734, 92888734, 95487525, 99770748},
548 };
549
Antti Palosaari15d37f32014-12-12 01:03:51 -0300550 ret = rtl2830_bulk_read(client, 0x33c, &u8tmp, 1);
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300551 if (ret)
552 goto err;
553
554 constellation = (u8tmp >> 2) & 0x03; /* [3:2] */
555 if (constellation > CONSTELLATION_NUM - 1)
556 goto err_schedule_delayed_work;
557
558 hierarchy = (u8tmp >> 4) & 0x07; /* [6:4] */
559 if (hierarchy > HIERARCHY_NUM - 1)
560 goto err_schedule_delayed_work;
561
Antti Palosaari15d37f32014-12-12 01:03:51 -0300562 ret = rtl2830_bulk_read(client, 0x40c, buf, 2);
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300563 if (ret)
564 goto err;
565
566 u16tmp = buf[0] << 8 | buf[1] << 0;
567 if (u16tmp)
568 tmp = (constant[constellation][hierarchy] -
569 intlog10(u16tmp)) / ((1 << 24) / 10000);
570 else
571 tmp = 0;
572
573 dev_dbg(&client->dev, "CNR raw=%u\n", u16tmp);
574
575 c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
576 c->cnr.stat[0].svalue = tmp;
577 } else {
578 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
579 }
580
Antti Palosaari5bb11ca2014-12-09 09:45:16 -0300581 /* BER */
582 if (dev->fe_status & FE_HAS_LOCK) {
Antti Palosaari15d37f32014-12-12 01:03:51 -0300583 ret = rtl2830_bulk_read(client, 0x34e, buf, 2);
Antti Palosaari5bb11ca2014-12-09 09:45:16 -0300584 if (ret)
585 goto err;
586
587 u16tmp = buf[0] << 8 | buf[1] << 0;
588 dev->post_bit_error += u16tmp;
589 dev->post_bit_count += 1000000;
590
591 dev_dbg(&client->dev, "BER errors=%u total=1000000\n", u16tmp);
592
593 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
594 c->post_bit_error.stat[0].uvalue = dev->post_bit_error;
595 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
596 c->post_bit_count.stat[0].uvalue = dev->post_bit_count;
597 } else {
598 c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
599 c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
600 }
601
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300602err_schedule_delayed_work:
603 schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
604 return;
605err:
606 dev_dbg(&client->dev, "failed=%d\n", ret);
607}
608
Antti Palosaaridf70dda2014-12-09 16:08:44 -0300609static int rtl2830_pid_filter_ctrl(struct dvb_frontend *fe, int onoff)
610{
611 struct i2c_client *client = fe->demodulator_priv;
612 int ret;
613 u8 u8tmp;
614
615 dev_dbg(&client->dev, "onoff=%d\n", onoff);
616
617 /* enable / disable PID filter */
618 if (onoff)
619 u8tmp = 0x80;
620 else
621 u8tmp = 0x00;
622
Antti Palosaari15d37f32014-12-12 01:03:51 -0300623 ret = rtl2830_update_bits(client, 0x061, 0x80, u8tmp);
Antti Palosaaridf70dda2014-12-09 16:08:44 -0300624 if (ret)
625 goto err;
626
627 return 0;
628err:
629 dev_dbg(&client->dev, "failed=%d\n", ret);
630 return ret;
631}
632
633static int rtl2830_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid, int onoff)
634{
635 struct i2c_client *client = fe->demodulator_priv;
636 struct rtl2830_dev *dev = i2c_get_clientdata(client);
637 int ret;
638 u8 buf[4];
639
640 dev_dbg(&client->dev, "index=%d pid=%04x onoff=%d\n",
641 index, pid, onoff);
642
643 /* skip invalid PIDs (0x2000) */
644 if (pid > 0x1fff || index > 32)
645 return 0;
646
647 if (onoff)
648 set_bit(index, &dev->filters);
649 else
650 clear_bit(index, &dev->filters);
651
652 /* enable / disable PIDs */
653 buf[0] = (dev->filters >> 0) & 0xff;
654 buf[1] = (dev->filters >> 8) & 0xff;
655 buf[2] = (dev->filters >> 16) & 0xff;
656 buf[3] = (dev->filters >> 24) & 0xff;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300657 ret = rtl2830_bulk_write(client, 0x062, buf, 4);
Antti Palosaaridf70dda2014-12-09 16:08:44 -0300658 if (ret)
659 goto err;
660
661 /* add PID */
662 buf[0] = (pid >> 8) & 0xff;
663 buf[1] = (pid >> 0) & 0xff;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300664 ret = rtl2830_bulk_write(client, 0x066 + 2 * index, buf, 2);
Antti Palosaaridf70dda2014-12-09 16:08:44 -0300665 if (ret)
666 goto err;
667
668 return 0;
669err:
670 dev_dbg(&client->dev, "failed=%d\n", ret);
671 return ret;
672}
673
Antti Palosaari28c08792014-12-07 04:07:29 -0300674/*
Antti Palosaari15d37f32014-12-12 01:03:51 -0300675 * I2C gate/mux/repeater logic
676 * We must use unlocked __i2c_transfer() here (through regmap) because of I2C
677 * adapter lock is already taken by tuner driver.
678 * Gate is closed automatically after single I2C transfer.
Antti Palosaari28c08792014-12-07 04:07:29 -0300679 */
680static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
681{
682 struct i2c_client *client = mux_priv;
Antti Palosaarif544f102014-12-08 22:31:28 -0300683 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300684 int ret;
685
Antti Palosaarifd4cfa82014-12-09 16:14:41 -0300686 dev_dbg(&client->dev, "\n");
687
Antti Palosaari15d37f32014-12-12 01:03:51 -0300688 /* open I2C repeater for 1 transfer, closes automatically */
689 /* XXX: regmap_update_bits() does not lock I2C adapter */
690 ret = regmap_update_bits(dev->regmap, 0x101, 0x08, 0x08);
691 if (ret)
Antti Palosaari28c08792014-12-07 04:07:29 -0300692 goto err;
Antti Palosaari28c08792014-12-07 04:07:29 -0300693
694 return 0;
Antti Palosaari28c08792014-12-07 04:07:29 -0300695err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300696 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaari28c08792014-12-07 04:07:29 -0300697 return ret;
698}
699
700static struct dvb_frontend *rtl2830_get_dvb_frontend(struct i2c_client *client)
701{
Antti Palosaarif544f102014-12-08 22:31:28 -0300702 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300703
704 dev_dbg(&client->dev, "\n");
705
Antti Palosaarif544f102014-12-08 22:31:28 -0300706 return &dev->fe;
Antti Palosaari28c08792014-12-07 04:07:29 -0300707}
708
709static struct i2c_adapter *rtl2830_get_i2c_adapter(struct i2c_client *client)
710{
Antti Palosaarif544f102014-12-08 22:31:28 -0300711 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300712
713 dev_dbg(&client->dev, "\n");
714
Antti Palosaarif544f102014-12-08 22:31:28 -0300715 return dev->adapter;
Antti Palosaari28c08792014-12-07 04:07:29 -0300716}
717
Antti Palosaari15d37f32014-12-12 01:03:51 -0300718/*
719 * We implement own I2C access routines for regmap in order to get manual access
720 * to I2C adapter lock, which is needed for I2C mux adapter.
721 */
722static int rtl2830_regmap_read(void *context, const void *reg_buf,
723 size_t reg_size, void *val_buf, size_t val_size)
724{
725 struct i2c_client *client = context;
726 int ret;
727 struct i2c_msg msg[2] = {
728 {
729 .addr = client->addr,
730 .flags = 0,
731 .len = reg_size,
732 .buf = (u8 *)reg_buf,
733 }, {
734 .addr = client->addr,
735 .flags = I2C_M_RD,
736 .len = val_size,
737 .buf = val_buf,
738 }
739 };
740
741 ret = __i2c_transfer(client->adapter, msg, 2);
742 if (ret != 2) {
743 dev_warn(&client->dev, "i2c reg read failed %d\n", ret);
744 if (ret >= 0)
745 ret = -EREMOTEIO;
746 return ret;
747 }
748 return 0;
749}
750
751static int rtl2830_regmap_write(void *context, const void *data, size_t count)
752{
753 struct i2c_client *client = context;
754 int ret;
755 struct i2c_msg msg[1] = {
756 {
757 .addr = client->addr,
758 .flags = 0,
759 .len = count,
760 .buf = (u8 *)data,
761 }
762 };
763
764 ret = __i2c_transfer(client->adapter, msg, 1);
765 if (ret != 1) {
766 dev_warn(&client->dev, "i2c reg write failed %d\n", ret);
767 if (ret >= 0)
768 ret = -EREMOTEIO;
769 return ret;
770 }
771 return 0;
772}
773
774static int rtl2830_regmap_gather_write(void *context, const void *reg,
775 size_t reg_len, const void *val,
776 size_t val_len)
777{
778 struct i2c_client *client = context;
779 int ret;
780 u8 buf[256];
781 struct i2c_msg msg[1] = {
782 {
783 .addr = client->addr,
784 .flags = 0,
785 .len = 1 + val_len,
786 .buf = buf,
787 }
788 };
789
790 buf[0] = *(u8 const *)reg;
791 memcpy(&buf[1], val, val_len);
792
793 ret = __i2c_transfer(client->adapter, msg, 1);
794 if (ret != 1) {
795 dev_warn(&client->dev, "i2c reg write failed %d\n", ret);
796 if (ret >= 0)
797 ret = -EREMOTEIO;
798 return ret;
799 }
800 return 0;
801}
802
Antti Palosaari28c08792014-12-07 04:07:29 -0300803static int rtl2830_probe(struct i2c_client *client,
Antti Palosaari947debb2014-12-09 02:31:53 -0300804 const struct i2c_device_id *id)
Antti Palosaari28c08792014-12-07 04:07:29 -0300805{
806 struct rtl2830_platform_data *pdata = client->dev.platform_data;
Antti Palosaarif544f102014-12-08 22:31:28 -0300807 struct rtl2830_dev *dev;
Antti Palosaari28c08792014-12-07 04:07:29 -0300808 int ret;
809 u8 u8tmp;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300810 static const struct regmap_bus regmap_bus = {
811 .read = rtl2830_regmap_read,
812 .write = rtl2830_regmap_write,
813 .gather_write = rtl2830_regmap_gather_write,
814 .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
815 };
816 static const struct regmap_range_cfg regmap_range_cfg[] = {
817 {
818 .selector_reg = 0x00,
819 .selector_mask = 0xff,
820 .selector_shift = 0,
821 .window_start = 0,
822 .window_len = 0x100,
823 .range_min = 0 * 0x100,
824 .range_max = 5 * 0x100,
825 },
826 };
827 static const struct regmap_config regmap_config = {
828 .reg_bits = 8,
829 .val_bits = 8,
830 .max_register = 5 * 0x100,
831 .ranges = regmap_range_cfg,
832 .num_ranges = ARRAY_SIZE(regmap_range_cfg),
833 };
Antti Palosaari28c08792014-12-07 04:07:29 -0300834
835 dev_dbg(&client->dev, "\n");
836
837 if (pdata == NULL) {
838 ret = -EINVAL;
839 goto err;
840 }
841
842 /* allocate memory for the internal state */
Antti Palosaarif544f102014-12-08 22:31:28 -0300843 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
844 if (dev == NULL) {
Antti Palosaari28c08792014-12-07 04:07:29 -0300845 ret = -ENOMEM;
846 goto err;
847 }
848
849 /* setup the state */
Antti Palosaarif544f102014-12-08 22:31:28 -0300850 i2c_set_clientdata(client, dev);
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300851 dev->client = client;
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300852 dev->pdata = client->dev.platform_data;
Antti Palosaarif544f102014-12-08 22:31:28 -0300853 dev->sleeping = true;
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300854 INIT_DELAYED_WORK(&dev->stat_work, rtl2830_stat_work);
Antti Palosaari15d37f32014-12-12 01:03:51 -0300855 dev->regmap = regmap_init(&client->dev, &regmap_bus, client,
856 &regmap_config);
857 if (IS_ERR(dev->regmap)) {
858 ret = PTR_ERR(dev->regmap);
859 goto err_kfree;
860 }
Antti Palosaari28c08792014-12-07 04:07:29 -0300861
862 /* check if the demod is there */
Antti Palosaari15d37f32014-12-12 01:03:51 -0300863 ret = rtl2830_bulk_read(client, 0x000, &u8tmp, 1);
Antti Palosaari28c08792014-12-07 04:07:29 -0300864 if (ret)
Antti Palosaari15d37f32014-12-12 01:03:51 -0300865 goto err_regmap_exit;
Antti Palosaari28c08792014-12-07 04:07:29 -0300866
867 /* create muxed i2c adapter for tuner */
Antti Palosaarif544f102014-12-08 22:31:28 -0300868 dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
Antti Palosaari15d37f32014-12-12 01:03:51 -0300869 client, 0, 0, 0, rtl2830_select, NULL);
Antti Palosaarif544f102014-12-08 22:31:28 -0300870 if (dev->adapter == NULL) {
Antti Palosaari28c08792014-12-07 04:07:29 -0300871 ret = -ENODEV;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300872 goto err_regmap_exit;
Antti Palosaari28c08792014-12-07 04:07:29 -0300873 }
874
875 /* create dvb frontend */
Antti Palosaarif544f102014-12-08 22:31:28 -0300876 memcpy(&dev->fe.ops, &rtl2830_ops, sizeof(dev->fe.ops));
Antti Palosaari1f153c42014-12-08 22:47:21 -0300877 dev->fe.demodulator_priv = client;
Antti Palosaari28c08792014-12-07 04:07:29 -0300878
879 /* setup callbacks */
880 pdata->get_dvb_frontend = rtl2830_get_dvb_frontend;
881 pdata->get_i2c_adapter = rtl2830_get_i2c_adapter;
Antti Palosaaridf70dda2014-12-09 16:08:44 -0300882 pdata->pid_filter = rtl2830_pid_filter;
883 pdata->pid_filter_ctrl = rtl2830_pid_filter_ctrl;
Antti Palosaari28c08792014-12-07 04:07:29 -0300884
885 dev_info(&client->dev, "Realtek RTL2830 successfully attached\n");
Antti Palosaari28c08792014-12-07 04:07:29 -0300886
Antti Palosaari947debb2014-12-09 02:31:53 -0300887 return 0;
Antti Palosaari15d37f32014-12-12 01:03:51 -0300888err_regmap_exit:
889 regmap_exit(dev->regmap);
Antti Palosaari28c08792014-12-07 04:07:29 -0300890err_kfree:
Antti Palosaarif544f102014-12-08 22:31:28 -0300891 kfree(dev);
Antti Palosaari28c08792014-12-07 04:07:29 -0300892err:
893 dev_dbg(&client->dev, "failed=%d\n", ret);
894 return ret;
895}
896
897static int rtl2830_remove(struct i2c_client *client)
898{
Antti Palosaarif544f102014-12-08 22:31:28 -0300899 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300900
901 dev_dbg(&client->dev, "\n");
902
Antti Palosaarif544f102014-12-08 22:31:28 -0300903 i2c_del_mux_adapter(dev->adapter);
Antti Palosaari15d37f32014-12-12 01:03:51 -0300904 regmap_exit(dev->regmap);
Antti Palosaarif544f102014-12-08 22:31:28 -0300905 kfree(dev);
Antti Palosaari947debb2014-12-09 02:31:53 -0300906
Antti Palosaari28c08792014-12-07 04:07:29 -0300907 return 0;
908}
909
910static const struct i2c_device_id rtl2830_id_table[] = {
911 {"rtl2830", 0},
912 {}
913};
914MODULE_DEVICE_TABLE(i2c, rtl2830_id_table);
915
916static struct i2c_driver rtl2830_driver = {
917 .driver = {
Antti Palosaari28c08792014-12-07 04:07:29 -0300918 .name = "rtl2830",
919 },
920 .probe = rtl2830_probe,
921 .remove = rtl2830_remove,
922 .id_table = rtl2830_id_table,
923};
924
925module_i2c_driver(rtl2830_driver);
926
Antti Palosaaric0adca72011-07-08 23:34:09 -0300927MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
928MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver");
929MODULE_LICENSE("GPL");