blob: c484634a9fc9086b9b5fcda9b073a737df76ce5b [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
Mauro Carvalho Chehab37ebaf62013-11-02 05:11:47 -030020/* Max transfer size done by I2C transfer functions */
21#define MAX_XFER_SIZE 64
22
Antti Palosaari0485a702011-08-04 20:27:19 -030023/* write multiple hardware registers */
Antti Palosaari1f153c42014-12-08 22:47:21 -030024static int rtl2830_wr(struct i2c_client *client, u8 reg, const u8 *val, int len)
Antti Palosaaric0adca72011-07-08 23:34:09 -030025{
26 int ret;
Mauro Carvalho Chehab37ebaf62013-11-02 05:11:47 -030027 u8 buf[MAX_XFER_SIZE];
Antti Palosaaric0adca72011-07-08 23:34:09 -030028 struct i2c_msg msg[1] = {
29 {
Antti Palosaarib8cb50d22014-12-09 00:24:13 -030030 .addr = client->addr,
Antti Palosaaric0adca72011-07-08 23:34:09 -030031 .flags = 0,
Mauro Carvalho Chehab37ebaf62013-11-02 05:11:47 -030032 .len = 1 + len,
Antti Palosaaric0adca72011-07-08 23:34:09 -030033 .buf = buf,
34 }
35 };
36
Mauro Carvalho Chehab37ebaf62013-11-02 05:11:47 -030037 if (1 + len > sizeof(buf)) {
Antti Palosaari7cc39322014-12-08 23:32:19 -030038 dev_warn(&client->dev, "i2c wr reg=%04x: len=%d is too big!\n",
Antti Palosaari947debb2014-12-09 02:31:53 -030039 reg, len);
Mauro Carvalho Chehab37ebaf62013-11-02 05:11:47 -030040 return -EINVAL;
41 }
42
Antti Palosaari0485a702011-08-04 20:27:19 -030043 buf[0] = reg;
44 memcpy(&buf[1], val, len);
Antti Palosaaric0adca72011-07-08 23:34:09 -030045
Antti Palosaarib8cb50d22014-12-09 00:24:13 -030046 ret = i2c_transfer(client->adapter, msg, 1);
Antti Palosaaric0adca72011-07-08 23:34:09 -030047 if (ret == 1) {
48 ret = 0;
49 } else {
Antti Palosaari7cc39322014-12-08 23:32:19 -030050 dev_warn(&client->dev, "i2c wr failed=%d reg=%02x len=%d\n",
Antti Palosaari947debb2014-12-09 02:31:53 -030051 ret, reg, len);
Antti Palosaaric0adca72011-07-08 23:34:09 -030052 ret = -EREMOTEIO;
53 }
Antti Palosaari947debb2014-12-09 02:31:53 -030054
Antti Palosaaric0adca72011-07-08 23:34:09 -030055 return ret;
56}
57
Antti Palosaari0485a702011-08-04 20:27:19 -030058/* read multiple hardware registers */
Antti Palosaari1f153c42014-12-08 22:47:21 -030059static int rtl2830_rd(struct i2c_client *client, u8 reg, u8 *val, int len)
Antti Palosaaric0adca72011-07-08 23:34:09 -030060{
61 int ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -030062 struct i2c_msg msg[2] = {
63 {
Antti Palosaarib8cb50d22014-12-09 00:24:13 -030064 .addr = client->addr,
Antti Palosaaric0adca72011-07-08 23:34:09 -030065 .flags = 0,
Antti Palosaari0485a702011-08-04 20:27:19 -030066 .len = 1,
67 .buf = &reg,
Antti Palosaaric0adca72011-07-08 23:34:09 -030068 }, {
Antti Palosaarib8cb50d22014-12-09 00:24:13 -030069 .addr = client->addr,
Antti Palosaaric0adca72011-07-08 23:34:09 -030070 .flags = I2C_M_RD,
71 .len = len,
72 .buf = val,
73 }
74 };
75
Antti Palosaarib8cb50d22014-12-09 00:24:13 -030076 ret = i2c_transfer(client->adapter, msg, 2);
Antti Palosaaric0adca72011-07-08 23:34:09 -030077 if (ret == 2) {
78 ret = 0;
79 } else {
Antti Palosaari7cc39322014-12-08 23:32:19 -030080 dev_warn(&client->dev, "i2c rd failed=%d reg=%02x len=%d\n",
Antti Palosaari947debb2014-12-09 02:31:53 -030081 ret, reg, len);
Antti Palosaaric0adca72011-07-08 23:34:09 -030082 ret = -EREMOTEIO;
83 }
Antti Palosaari947debb2014-12-09 02:31:53 -030084
Antti Palosaaric0adca72011-07-08 23:34:09 -030085 return ret;
86}
87
Antti Palosaari0485a702011-08-04 20:27:19 -030088/* write multiple registers */
Antti Palosaari1f153c42014-12-08 22:47:21 -030089static int rtl2830_wr_regs(struct i2c_client *client, u16 reg, const u8 *val, int len)
Antti Palosaari0485a702011-08-04 20:27:19 -030090{
Antti Palosaari1f153c42014-12-08 22:47:21 -030091 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari0485a702011-08-04 20:27:19 -030092 int ret;
93 u8 reg2 = (reg >> 0) & 0xff;
94 u8 page = (reg >> 8) & 0xff;
95
96 /* switch bank if needed */
Antti Palosaarif544f102014-12-08 22:31:28 -030097 if (page != dev->page) {
Antti Palosaari1f153c42014-12-08 22:47:21 -030098 ret = rtl2830_wr(client, 0x00, &page, 1);
Antti Palosaari0485a702011-08-04 20:27:19 -030099 if (ret)
100 return ret;
101
Antti Palosaarif544f102014-12-08 22:31:28 -0300102 dev->page = page;
Antti Palosaari0485a702011-08-04 20:27:19 -0300103 }
104
Antti Palosaari1f153c42014-12-08 22:47:21 -0300105 return rtl2830_wr(client, reg2, val, len);
Antti Palosaari0485a702011-08-04 20:27:19 -0300106}
107
108/* read multiple registers */
Antti Palosaari1f153c42014-12-08 22:47:21 -0300109static int rtl2830_rd_regs(struct i2c_client *client, u16 reg, u8 *val, int len)
Antti Palosaari0485a702011-08-04 20:27:19 -0300110{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300111 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari0485a702011-08-04 20:27:19 -0300112 int ret;
113 u8 reg2 = (reg >> 0) & 0xff;
114 u8 page = (reg >> 8) & 0xff;
115
116 /* switch bank if needed */
Antti Palosaarif544f102014-12-08 22:31:28 -0300117 if (page != dev->page) {
Antti Palosaari1f153c42014-12-08 22:47:21 -0300118 ret = rtl2830_wr(client, 0x00, &page, 1);
Antti Palosaari0485a702011-08-04 20:27:19 -0300119 if (ret)
120 return ret;
121
Antti Palosaarif544f102014-12-08 22:31:28 -0300122 dev->page = page;
Antti Palosaari0485a702011-08-04 20:27:19 -0300123 }
124
Antti Palosaari1f153c42014-12-08 22:47:21 -0300125 return rtl2830_rd(client, reg2, val, len);
Antti Palosaari0485a702011-08-04 20:27:19 -0300126}
127
Antti Palosaaric0adca72011-07-08 23:34:09 -0300128/* read single register */
Antti Palosaari1f153c42014-12-08 22:47:21 -0300129static int rtl2830_rd_reg(struct i2c_client *client, u16 reg, u8 *val)
Antti Palosaaric0adca72011-07-08 23:34:09 -0300130{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300131 return rtl2830_rd_regs(client, reg, val, 1);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300132}
133
134/* write single register with mask */
Antti Palosaari1f153c42014-12-08 22:47:21 -0300135static int rtl2830_wr_reg_mask(struct i2c_client *client, u16 reg, u8 val, u8 mask)
Antti Palosaaric0adca72011-07-08 23:34:09 -0300136{
137 int ret;
138 u8 tmp;
139
140 /* no need for read if whole reg is written */
141 if (mask != 0xff) {
Antti Palosaari1f153c42014-12-08 22:47:21 -0300142 ret = rtl2830_rd_regs(client, reg, &tmp, 1);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300143 if (ret)
144 return ret;
145
146 val &= mask;
147 tmp &= ~mask;
148 val |= tmp;
149 }
150
Antti Palosaari1f153c42014-12-08 22:47:21 -0300151 return rtl2830_wr_regs(client, reg, &val, 1);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300152}
153
154/* read single register with mask */
Antti Palosaari1f153c42014-12-08 22:47:21 -0300155static int rtl2830_rd_reg_mask(struct i2c_client *client, u16 reg, u8 *val, u8 mask)
Antti Palosaaric0adca72011-07-08 23:34:09 -0300156{
157 int ret, i;
158 u8 tmp;
159
Antti Palosaari1f153c42014-12-08 22:47:21 -0300160 ret = rtl2830_rd_regs(client, reg, &tmp, 1);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300161 if (ret)
162 return ret;
163
164 tmp &= mask;
165
166 /* find position of the first bit */
167 for (i = 0; i < 8; i++) {
168 if ((mask >> i) & 0x01)
169 break;
170 }
171 *val = tmp >> i;
172
173 return 0;
174}
175
176static int rtl2830_init(struct dvb_frontend *fe)
177{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300178 struct i2c_client *client = fe->demodulator_priv;
179 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300180 struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300181 int ret, i;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300182 struct rtl2830_reg_val_mask tab[] = {
Antti Palosaari947debb2014-12-09 02:31:53 -0300183 {0x00d, 0x01, 0x03},
184 {0x00d, 0x10, 0x10},
185 {0x104, 0x00, 0x1e},
186 {0x105, 0x80, 0x80},
187 {0x110, 0x02, 0x03},
188 {0x110, 0x08, 0x0c},
189 {0x17b, 0x00, 0x40},
190 {0x17d, 0x05, 0x0f},
191 {0x17d, 0x50, 0xf0},
192 {0x18c, 0x08, 0x0f},
193 {0x18d, 0x00, 0xc0},
194 {0x188, 0x05, 0x0f},
195 {0x189, 0x00, 0xfc},
196 {0x2d5, 0x02, 0x02},
197 {0x2f1, 0x02, 0x06},
198 {0x2f1, 0x20, 0xf8},
199 {0x16d, 0x00, 0x01},
200 {0x1a6, 0x00, 0x80},
201 {0x106, dev->pdata->vtop, 0x3f},
202 {0x107, dev->pdata->krf, 0x3f},
203 {0x112, 0x28, 0xff},
204 {0x103, dev->pdata->agc_targ_val, 0xff},
205 {0x00a, 0x02, 0x07},
206 {0x140, 0x0c, 0x3c},
207 {0x140, 0x40, 0xc0},
208 {0x15b, 0x05, 0x07},
209 {0x15b, 0x28, 0x38},
210 {0x15c, 0x05, 0x07},
211 {0x15c, 0x28, 0x38},
212 {0x115, dev->pdata->spec_inv, 0x01},
213 {0x16f, 0x01, 0x07},
214 {0x170, 0x18, 0x38},
215 {0x172, 0x0f, 0x0f},
216 {0x173, 0x08, 0x38},
217 {0x175, 0x01, 0x07},
218 {0x176, 0x00, 0xc0},
Antti Palosaaric0adca72011-07-08 23:34:09 -0300219 };
220
221 for (i = 0; i < ARRAY_SIZE(tab); i++) {
Antti Palosaari1f153c42014-12-08 22:47:21 -0300222 ret = rtl2830_wr_reg_mask(client, tab[i].reg, tab[i].val,
Antti Palosaari947debb2014-12-09 02:31:53 -0300223 tab[i].mask);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300224 if (ret)
225 goto err;
226 }
227
Antti Palosaari1f153c42014-12-08 22:47:21 -0300228 ret = rtl2830_wr_regs(client, 0x18f, "\x28\x00", 2);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300229 if (ret)
230 goto err;
231
Antti Palosaari1f153c42014-12-08 22:47:21 -0300232 ret = rtl2830_wr_regs(client, 0x195,
Antti Palosaari947debb2014-12-09 02:31:53 -0300233 "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300234 if (ret)
235 goto err;
236
Antti Palosaaric0adca72011-07-08 23:34:09 -0300237 /* TODO: spec init */
238
239 /* soft reset */
Antti Palosaari1f153c42014-12-08 22:47:21 -0300240 ret = rtl2830_wr_reg_mask(client, 0x101, 0x04, 0x04);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300241 if (ret)
242 goto err;
243
Antti Palosaari1f153c42014-12-08 22:47:21 -0300244 ret = rtl2830_wr_reg_mask(client, 0x101, 0x00, 0x04);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300245 if (ret)
246 goto err;
247
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300248 /* init stats here in order signal app which stats are supported */
249 c->cnr.len = 1;
250 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
251 /* start statistics polling */
252 schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
253
Antti Palosaarif544f102014-12-08 22:31:28 -0300254 dev->sleeping = false;
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300255
Antti Palosaaric0adca72011-07-08 23:34:09 -0300256 return ret;
257err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300258 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300259 return ret;
260}
261
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300262static int rtl2830_sleep(struct dvb_frontend *fe)
263{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300264 struct i2c_client *client = fe->demodulator_priv;
265 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari947debb2014-12-09 02:31:53 -0300266
Antti Palosaarif544f102014-12-08 22:31:28 -0300267 dev->sleeping = true;
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300268 /* stop statistics polling */
269 cancel_delayed_work_sync(&dev->stat_work);
270 dev->fe_status = 0;
Antti Palosaari947debb2014-12-09 02:31:53 -0300271
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300272 return 0;
273}
274
Mauro Carvalho Chehaba17ff2e2012-10-27 11:24:08 -0300275static int rtl2830_get_tune_settings(struct dvb_frontend *fe,
Antti Palosaari947debb2014-12-09 02:31:53 -0300276 struct dvb_frontend_tune_settings *s)
Antti Palosaaric0adca72011-07-08 23:34:09 -0300277{
278 s->min_delay_ms = 500;
279 s->step_size = fe->ops.info.frequency_stepsize * 2;
280 s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
281
282 return 0;
283}
284
285static int rtl2830_set_frontend(struct dvb_frontend *fe)
286{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300287 struct i2c_client *client = fe->demodulator_priv;
288 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300289 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
290 int ret, i;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300291 u64 num;
292 u8 buf[3], tmp;
293 u32 if_ctl, if_frequency;
Antti Palosaari3a2fca22012-09-12 20:23:49 -0300294 static const u8 bw_params1[3][34] = {
Antti Palosaaric0adca72011-07-08 23:34:09 -0300295 {
296 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41,
297 0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a,
298 0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82,
299 0x03, 0x73, 0x03, 0xcf, /* 6 MHz */
300 }, {
301 0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca,
302 0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca,
303 0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e,
304 0x03, 0xd0, 0x04, 0x53, /* 7 MHz */
305 }, {
306 0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0,
307 0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a,
308 0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f,
309 0x04, 0x24, 0x04, 0xdb, /* 8 MHz */
310 },
311 };
Antti Palosaari3a2fca22012-09-12 20:23:49 -0300312 static const u8 bw_params2[3][6] = {
313 {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30}, /* 6 MHz */
314 {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98}, /* 7 MHz */
315 {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64}, /* 8 MHz */
Antti Palosaaric0adca72011-07-08 23:34:09 -0300316 };
317
Antti Palosaari7cc39322014-12-08 23:32:19 -0300318 dev_dbg(&client->dev, "frequency=%u bandwidth_hz=%u inversion=%u\n",
Antti Palosaari947debb2014-12-09 02:31:53 -0300319 c->frequency, c->bandwidth_hz, c->inversion);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300320
321 /* program tuner */
322 if (fe->ops.tuner_ops.set_params)
323 fe->ops.tuner_ops.set_params(fe);
324
325 switch (c->bandwidth_hz) {
326 case 6000000:
327 i = 0;
328 break;
329 case 7000000:
330 i = 1;
331 break;
332 case 8000000:
333 i = 2;
334 break;
335 default:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300336 dev_err(&client->dev, "invalid bandwidth_hz %u\n",
Antti Palosaari947debb2014-12-09 02:31:53 -0300337 c->bandwidth_hz);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300338 return -EINVAL;
339 }
340
Antti Palosaari1f153c42014-12-08 22:47:21 -0300341 ret = rtl2830_wr_reg_mask(client, 0x008, i << 1, 0x06);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300342 if (ret)
343 goto err;
344
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300345 /* program if frequency */
346 if (fe->ops.tuner_ops.get_if_frequency)
347 ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
348 else
349 ret = -EINVAL;
Antti Palosaari947debb2014-12-09 02:31:53 -0300350 if (ret)
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300351 goto err;
352
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300353 num = if_frequency % dev->pdata->clk;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300354 num *= 0x400000;
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300355 num = div_u64(num, dev->pdata->clk);
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300356 num = -num;
357 if_ctl = num & 0x3fffff;
Antti Palosaari7cc39322014-12-08 23:32:19 -0300358 dev_dbg(&client->dev, "if_frequency=%d if_ctl=%08x\n",
Antti Palosaari947debb2014-12-09 02:31:53 -0300359 if_frequency, if_ctl);
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300360
Antti Palosaari1f153c42014-12-08 22:47:21 -0300361 ret = rtl2830_rd_reg_mask(client, 0x119, &tmp, 0xc0); /* b[7:6] */
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300362 if (ret)
363 goto err;
364
365 buf[0] = tmp << 6;
366 buf[0] |= (if_ctl >> 16) & 0x3f;
367 buf[1] = (if_ctl >> 8) & 0xff;
368 buf[2] = (if_ctl >> 0) & 0xff;
369
Antti Palosaari1f153c42014-12-08 22:47:21 -0300370 ret = rtl2830_wr_regs(client, 0x119, buf, 3);
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300371 if (ret)
372 goto err;
373
Antti Palosaaric0adca72011-07-08 23:34:09 -0300374 /* 1/2 split I2C write */
Antti Palosaari1f153c42014-12-08 22:47:21 -0300375 ret = rtl2830_wr_regs(client, 0x11c, &bw_params1[i][0], 17);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300376 if (ret)
377 goto err;
378
379 /* 2/2 split I2C write */
Antti Palosaari1f153c42014-12-08 22:47:21 -0300380 ret = rtl2830_wr_regs(client, 0x12d, &bw_params1[i][17], 17);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300381 if (ret)
382 goto err;
383
Antti Palosaari1f153c42014-12-08 22:47:21 -0300384 ret = rtl2830_wr_regs(client, 0x19d, bw_params2[i], 6);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300385 if (ret)
386 goto err;
387
388 return ret;
389err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300390 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300391 return ret;
392}
393
Antti Palosaari631a2b62012-05-18 15:58:57 -0300394static int rtl2830_get_frontend(struct dvb_frontend *fe)
395{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300396 struct i2c_client *client = fe->demodulator_priv;
397 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300398 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
399 int ret;
400 u8 buf[3];
401
Antti Palosaarif544f102014-12-08 22:31:28 -0300402 if (dev->sleeping)
Antti Palosaaric1886372012-05-18 16:02:55 -0300403 return 0;
404
Antti Palosaari1f153c42014-12-08 22:47:21 -0300405 ret = rtl2830_rd_regs(client, 0x33c, buf, 2);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300406 if (ret)
407 goto err;
408
Antti Palosaari1f153c42014-12-08 22:47:21 -0300409 ret = rtl2830_rd_reg(client, 0x351, &buf[2]);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300410 if (ret)
411 goto err;
412
Antti Palosaari7cc39322014-12-08 23:32:19 -0300413 dev_dbg(&client->dev, "TPS=%*ph\n", 3, buf);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300414
415 switch ((buf[0] >> 2) & 3) {
416 case 0:
417 c->modulation = QPSK;
418 break;
419 case 1:
420 c->modulation = QAM_16;
421 break;
422 case 2:
423 c->modulation = QAM_64;
424 break;
425 }
426
427 switch ((buf[2] >> 2) & 1) {
428 case 0:
429 c->transmission_mode = TRANSMISSION_MODE_2K;
430 break;
431 case 1:
432 c->transmission_mode = TRANSMISSION_MODE_8K;
433 }
434
435 switch ((buf[2] >> 0) & 3) {
436 case 0:
437 c->guard_interval = GUARD_INTERVAL_1_32;
438 break;
439 case 1:
440 c->guard_interval = GUARD_INTERVAL_1_16;
441 break;
442 case 2:
443 c->guard_interval = GUARD_INTERVAL_1_8;
444 break;
445 case 3:
446 c->guard_interval = GUARD_INTERVAL_1_4;
447 break;
448 }
449
450 switch ((buf[0] >> 4) & 7) {
451 case 0:
452 c->hierarchy = HIERARCHY_NONE;
453 break;
454 case 1:
455 c->hierarchy = HIERARCHY_1;
456 break;
457 case 2:
458 c->hierarchy = HIERARCHY_2;
459 break;
460 case 3:
461 c->hierarchy = HIERARCHY_4;
462 break;
463 }
464
465 switch ((buf[1] >> 3) & 7) {
466 case 0:
467 c->code_rate_HP = FEC_1_2;
468 break;
469 case 1:
470 c->code_rate_HP = FEC_2_3;
471 break;
472 case 2:
473 c->code_rate_HP = FEC_3_4;
474 break;
475 case 3:
476 c->code_rate_HP = FEC_5_6;
477 break;
478 case 4:
479 c->code_rate_HP = FEC_7_8;
480 break;
481 }
482
483 switch ((buf[1] >> 0) & 7) {
484 case 0:
485 c->code_rate_LP = FEC_1_2;
486 break;
487 case 1:
488 c->code_rate_LP = FEC_2_3;
489 break;
490 case 2:
491 c->code_rate_LP = FEC_3_4;
492 break;
493 case 3:
494 c->code_rate_LP = FEC_5_6;
495 break;
496 case 4:
497 c->code_rate_LP = FEC_7_8;
498 break;
499 }
500
501 return 0;
502err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300503 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300504 return ret;
505}
506
Antti Palosaaric0adca72011-07-08 23:34:09 -0300507static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status)
508{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300509 struct i2c_client *client = fe->demodulator_priv;
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300510 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300511 int ret;
512 u8 tmp;
Antti Palosaari947debb2014-12-09 02:31:53 -0300513
Antti Palosaaric0adca72011-07-08 23:34:09 -0300514 *status = 0;
515
Antti Palosaarif544f102014-12-08 22:31:28 -0300516 if (dev->sleeping)
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300517 return 0;
518
Antti Palosaari1f153c42014-12-08 22:47:21 -0300519 ret = rtl2830_rd_reg_mask(client, 0x351, &tmp, 0x78); /* [6:3] */
Antti Palosaaric0adca72011-07-08 23:34:09 -0300520 if (ret)
521 goto err;
522
523 if (tmp == 11) {
524 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
525 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
526 } else if (tmp == 10) {
527 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
528 FE_HAS_VITERBI;
529 }
530
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300531 dev->fe_status = *status;
532
Antti Palosaaric0adca72011-07-08 23:34:09 -0300533 return ret;
534err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300535 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300536 return ret;
537}
538
539static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
540{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300541 struct i2c_client *client = fe->demodulator_priv;
542 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaarieba672a2012-05-15 18:32:33 -0300543 int ret, hierarchy, constellation;
544 u8 buf[2], tmp;
545 u16 tmp16;
546#define CONSTELLATION_NUM 3
547#define HIERARCHY_NUM 4
548 static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
Antti Palosaari947debb2014-12-09 02:31:53 -0300549 {70705899, 70705899, 70705899, 70705899},
550 {82433173, 82433173, 87483115, 94445660},
551 {92888734, 92888734, 95487525, 99770748},
Antti Palosaarieba672a2012-05-15 18:32:33 -0300552 };
553
Antti Palosaarif544f102014-12-08 22:31:28 -0300554 if (dev->sleeping)
Antti Palosaaric1886372012-05-18 16:02:55 -0300555 return 0;
556
Antti Palosaarieba672a2012-05-15 18:32:33 -0300557 /* reports SNR in resolution of 0.1 dB */
558
Antti Palosaari1f153c42014-12-08 22:47:21 -0300559 ret = rtl2830_rd_reg(client, 0x33c, &tmp);
Antti Palosaarieba672a2012-05-15 18:32:33 -0300560 if (ret)
561 goto err;
562
563 constellation = (tmp >> 2) & 0x03; /* [3:2] */
564 if (constellation > CONSTELLATION_NUM - 1)
565 goto err;
566
567 hierarchy = (tmp >> 4) & 0x07; /* [6:4] */
568 if (hierarchy > HIERARCHY_NUM - 1)
569 goto err;
570
Antti Palosaari1f153c42014-12-08 22:47:21 -0300571 ret = rtl2830_rd_regs(client, 0x40c, buf, 2);
Antti Palosaarieba672a2012-05-15 18:32:33 -0300572 if (ret)
573 goto err;
574
575 tmp16 = buf[0] << 8 | buf[1];
576
577 if (tmp16)
578 *snr = (snr_constant[constellation][hierarchy] -
579 intlog10(tmp16)) / ((1 << 24) / 100);
580 else
581 *snr = 0;
582
Antti Palosaaric0adca72011-07-08 23:34:09 -0300583 return 0;
Antti Palosaarieba672a2012-05-15 18:32:33 -0300584err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300585 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaarieba672a2012-05-15 18:32:33 -0300586 return ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300587}
588
589static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
590{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300591 struct i2c_client *client = fe->demodulator_priv;
592 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari525ffc12012-05-18 12:23:42 -0300593 int ret;
594 u8 buf[2];
595
Antti Palosaarif544f102014-12-08 22:31:28 -0300596 if (dev->sleeping)
Antti Palosaaric1886372012-05-18 16:02:55 -0300597 return 0;
598
Antti Palosaari1f153c42014-12-08 22:47:21 -0300599 ret = rtl2830_rd_regs(client, 0x34e, buf, 2);
Antti Palosaari525ffc12012-05-18 12:23:42 -0300600 if (ret)
601 goto err;
602
603 *ber = buf[0] << 8 | buf[1];
604
Antti Palosaaric0adca72011-07-08 23:34:09 -0300605 return 0;
Antti Palosaari525ffc12012-05-18 12:23:42 -0300606err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300607 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaari525ffc12012-05-18 12:23:42 -0300608 return ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300609}
610
611static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
612{
613 *ucblocks = 0;
Antti Palosaari947debb2014-12-09 02:31:53 -0300614
Antti Palosaaric0adca72011-07-08 23:34:09 -0300615 return 0;
616}
617
618static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
619{
Antti Palosaari1f153c42014-12-08 22:47:21 -0300620 struct i2c_client *client = fe->demodulator_priv;
621 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari78e75072012-05-18 15:17:51 -0300622 int ret;
623 u8 buf[2];
624 u16 if_agc_raw, if_agc;
625
Antti Palosaarif544f102014-12-08 22:31:28 -0300626 if (dev->sleeping)
Antti Palosaaric1886372012-05-18 16:02:55 -0300627 return 0;
628
Antti Palosaari1f153c42014-12-08 22:47:21 -0300629 ret = rtl2830_rd_regs(client, 0x359, buf, 2);
Antti Palosaari78e75072012-05-18 15:17:51 -0300630 if (ret)
631 goto err;
632
633 if_agc_raw = (buf[0] << 8 | buf[1]) & 0x3fff;
634
635 if (if_agc_raw & (1 << 9))
636 if_agc = -(~(if_agc_raw - 1) & 0x1ff);
637 else
638 if_agc = if_agc_raw;
639
Antti Palosaari947debb2014-12-09 02:31:53 -0300640 *strength = (u8)(55 - if_agc / 182);
Antti Palosaari78e75072012-05-18 15:17:51 -0300641 *strength |= *strength << 8;
642
Antti Palosaaric0adca72011-07-08 23:34:09 -0300643 return 0;
Antti Palosaari78e75072012-05-18 15:17:51 -0300644err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300645 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaari78e75072012-05-18 15:17:51 -0300646 return ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300647}
648
Antti Palosaaric0adca72011-07-08 23:34:09 -0300649static struct dvb_frontend_ops rtl2830_ops = {
Antti Palosaari947debb2014-12-09 02:31:53 -0300650 .delsys = {SYS_DVBT},
Antti Palosaaric0adca72011-07-08 23:34:09 -0300651 .info = {
652 .name = "Realtek RTL2830 (DVB-T)",
653 .caps = FE_CAN_FEC_1_2 |
654 FE_CAN_FEC_2_3 |
655 FE_CAN_FEC_3_4 |
656 FE_CAN_FEC_5_6 |
657 FE_CAN_FEC_7_8 |
658 FE_CAN_FEC_AUTO |
659 FE_CAN_QPSK |
660 FE_CAN_QAM_16 |
661 FE_CAN_QAM_64 |
662 FE_CAN_QAM_AUTO |
663 FE_CAN_TRANSMISSION_MODE_AUTO |
664 FE_CAN_GUARD_INTERVAL_AUTO |
665 FE_CAN_HIERARCHY_AUTO |
666 FE_CAN_RECOVER |
667 FE_CAN_MUTE_TS
668 },
669
Antti Palosaaric0adca72011-07-08 23:34:09 -0300670 .init = rtl2830_init,
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300671 .sleep = rtl2830_sleep,
Antti Palosaaric0adca72011-07-08 23:34:09 -0300672
673 .get_tune_settings = rtl2830_get_tune_settings,
674
675 .set_frontend = rtl2830_set_frontend,
Antti Palosaari631a2b62012-05-18 15:58:57 -0300676 .get_frontend = rtl2830_get_frontend,
Antti Palosaaric0adca72011-07-08 23:34:09 -0300677
678 .read_status = rtl2830_read_status,
679 .read_snr = rtl2830_read_snr,
680 .read_ber = rtl2830_read_ber,
681 .read_ucblocks = rtl2830_read_ucblocks,
682 .read_signal_strength = rtl2830_read_signal_strength,
683};
684
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300685static void rtl2830_stat_work(struct work_struct *work)
686{
687 struct rtl2830_dev *dev = container_of(work, struct rtl2830_dev, stat_work.work);
688 struct i2c_client *client = dev->client;
689 struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
690 int ret, tmp;
691 u8 u8tmp, buf[2];
692 u16 u16tmp;
693
694 dev_dbg(&client->dev, "\n");
695
696 /* CNR */
697 if (dev->fe_status & FE_HAS_VITERBI) {
698 unsigned hierarchy, constellation;
699 #define CONSTELLATION_NUM 3
700 #define HIERARCHY_NUM 4
701 static const u32 constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
702 {70705899, 70705899, 70705899, 70705899},
703 {82433173, 82433173, 87483115, 94445660},
704 {92888734, 92888734, 95487525, 99770748},
705 };
706
707 ret = rtl2830_rd_reg(client, 0x33c, &u8tmp);
708 if (ret)
709 goto err;
710
711 constellation = (u8tmp >> 2) & 0x03; /* [3:2] */
712 if (constellation > CONSTELLATION_NUM - 1)
713 goto err_schedule_delayed_work;
714
715 hierarchy = (u8tmp >> 4) & 0x07; /* [6:4] */
716 if (hierarchy > HIERARCHY_NUM - 1)
717 goto err_schedule_delayed_work;
718
719 ret = rtl2830_rd_regs(client, 0x40c, buf, 2);
720 if (ret)
721 goto err;
722
723 u16tmp = buf[0] << 8 | buf[1] << 0;
724 if (u16tmp)
725 tmp = (constant[constellation][hierarchy] -
726 intlog10(u16tmp)) / ((1 << 24) / 10000);
727 else
728 tmp = 0;
729
730 dev_dbg(&client->dev, "CNR raw=%u\n", u16tmp);
731
732 c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
733 c->cnr.stat[0].svalue = tmp;
734 } else {
735 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
736 }
737
738err_schedule_delayed_work:
739 schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
740 return;
741err:
742 dev_dbg(&client->dev, "failed=%d\n", ret);
743}
744
Antti Palosaari28c08792014-12-07 04:07:29 -0300745/*
746 * I2C gate/repeater logic
747 * We must use unlocked i2c_transfer() here because I2C lock is already taken
748 * by tuner driver. Gate is closed automatically after single I2C xfer.
749 */
750static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 chan_id)
751{
752 struct i2c_client *client = mux_priv;
Antti Palosaarif544f102014-12-08 22:31:28 -0300753 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300754 struct i2c_msg select_reg_page_msg[1] = {
755 {
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300756 .addr = client->addr,
Antti Palosaari28c08792014-12-07 04:07:29 -0300757 .flags = 0,
758 .len = 2,
759 .buf = "\x00\x01",
760 }
761 };
762 struct i2c_msg gate_open_msg[1] = {
763 {
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300764 .addr = client->addr,
Antti Palosaari28c08792014-12-07 04:07:29 -0300765 .flags = 0,
766 .len = 2,
767 .buf = "\x01\x08",
768 }
769 };
770 int ret;
771
772 /* select register page */
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300773 ret = __i2c_transfer(client->adapter, select_reg_page_msg, 1);
Antti Palosaari28c08792014-12-07 04:07:29 -0300774 if (ret != 1) {
775 dev_warn(&client->dev, "i2c write failed %d\n", ret);
776 if (ret >= 0)
777 ret = -EREMOTEIO;
778 goto err;
779 }
780
Antti Palosaarif544f102014-12-08 22:31:28 -0300781 dev->page = 1;
Antti Palosaari28c08792014-12-07 04:07:29 -0300782
783 /* open tuner I2C repeater for 1 xfer, closes automatically */
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300784 ret = __i2c_transfer(client->adapter, gate_open_msg, 1);
Antti Palosaari28c08792014-12-07 04:07:29 -0300785 if (ret != 1) {
786 dev_warn(&client->dev, "i2c write failed %d\n", ret);
787 if (ret >= 0)
788 ret = -EREMOTEIO;
789 goto err;
790 }
791
792 return 0;
Antti Palosaari28c08792014-12-07 04:07:29 -0300793err:
Antti Palosaari7cc39322014-12-08 23:32:19 -0300794 dev_dbg(&client->dev, "failed=%d\n", ret);
Antti Palosaari28c08792014-12-07 04:07:29 -0300795 return ret;
796}
797
798static struct dvb_frontend *rtl2830_get_dvb_frontend(struct i2c_client *client)
799{
Antti Palosaarif544f102014-12-08 22:31:28 -0300800 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300801
802 dev_dbg(&client->dev, "\n");
803
Antti Palosaarif544f102014-12-08 22:31:28 -0300804 return &dev->fe;
Antti Palosaari28c08792014-12-07 04:07:29 -0300805}
806
807static struct i2c_adapter *rtl2830_get_i2c_adapter(struct i2c_client *client)
808{
Antti Palosaarif544f102014-12-08 22:31:28 -0300809 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300810
811 dev_dbg(&client->dev, "\n");
812
Antti Palosaarif544f102014-12-08 22:31:28 -0300813 return dev->adapter;
Antti Palosaari28c08792014-12-07 04:07:29 -0300814}
815
816static int rtl2830_probe(struct i2c_client *client,
Antti Palosaari947debb2014-12-09 02:31:53 -0300817 const struct i2c_device_id *id)
Antti Palosaari28c08792014-12-07 04:07:29 -0300818{
819 struct rtl2830_platform_data *pdata = client->dev.platform_data;
Antti Palosaarif544f102014-12-08 22:31:28 -0300820 struct rtl2830_dev *dev;
Antti Palosaari28c08792014-12-07 04:07:29 -0300821 int ret;
822 u8 u8tmp;
823
824 dev_dbg(&client->dev, "\n");
825
826 if (pdata == NULL) {
827 ret = -EINVAL;
828 goto err;
829 }
830
831 /* allocate memory for the internal state */
Antti Palosaarif544f102014-12-08 22:31:28 -0300832 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
833 if (dev == NULL) {
Antti Palosaari28c08792014-12-07 04:07:29 -0300834 ret = -ENOMEM;
835 goto err;
836 }
837
838 /* setup the state */
Antti Palosaarif544f102014-12-08 22:31:28 -0300839 i2c_set_clientdata(client, dev);
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300840 dev->client = client;
Antti Palosaarib8cb50d22014-12-09 00:24:13 -0300841 dev->pdata = client->dev.platform_data;
Antti Palosaarif544f102014-12-08 22:31:28 -0300842 dev->sleeping = true;
Antti Palosaari47b4dbf2014-12-09 06:14:36 -0300843 INIT_DELAYED_WORK(&dev->stat_work, rtl2830_stat_work);
Antti Palosaari28c08792014-12-07 04:07:29 -0300844
845 /* check if the demod is there */
Antti Palosaari1f153c42014-12-08 22:47:21 -0300846 ret = rtl2830_rd_reg(client, 0x000, &u8tmp);
Antti Palosaari28c08792014-12-07 04:07:29 -0300847 if (ret)
848 goto err_kfree;
849
850 /* create muxed i2c adapter for tuner */
Antti Palosaarif544f102014-12-08 22:31:28 -0300851 dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
Antti Palosaari28c08792014-12-07 04:07:29 -0300852 client, 0, 0, 0, rtl2830_select, NULL);
Antti Palosaarif544f102014-12-08 22:31:28 -0300853 if (dev->adapter == NULL) {
Antti Palosaari28c08792014-12-07 04:07:29 -0300854 ret = -ENODEV;
855 goto err_kfree;
856 }
857
858 /* create dvb frontend */
Antti Palosaarif544f102014-12-08 22:31:28 -0300859 memcpy(&dev->fe.ops, &rtl2830_ops, sizeof(dev->fe.ops));
Antti Palosaari1f153c42014-12-08 22:47:21 -0300860 dev->fe.demodulator_priv = client;
Antti Palosaari28c08792014-12-07 04:07:29 -0300861
862 /* setup callbacks */
863 pdata->get_dvb_frontend = rtl2830_get_dvb_frontend;
864 pdata->get_i2c_adapter = rtl2830_get_i2c_adapter;
865
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 Palosaari28c08792014-12-07 04:07:29 -0300869err_kfree:
Antti Palosaarif544f102014-12-08 22:31:28 -0300870 kfree(dev);
Antti Palosaari28c08792014-12-07 04:07:29 -0300871err:
872 dev_dbg(&client->dev, "failed=%d\n", ret);
873 return ret;
874}
875
876static int rtl2830_remove(struct i2c_client *client)
877{
Antti Palosaarif544f102014-12-08 22:31:28 -0300878 struct rtl2830_dev *dev = i2c_get_clientdata(client);
Antti Palosaari28c08792014-12-07 04:07:29 -0300879
880 dev_dbg(&client->dev, "\n");
881
Antti Palosaarif544f102014-12-08 22:31:28 -0300882 i2c_del_mux_adapter(dev->adapter);
883 kfree(dev);
Antti Palosaari947debb2014-12-09 02:31:53 -0300884
Antti Palosaari28c08792014-12-07 04:07:29 -0300885 return 0;
886}
887
888static const struct i2c_device_id rtl2830_id_table[] = {
889 {"rtl2830", 0},
890 {}
891};
892MODULE_DEVICE_TABLE(i2c, rtl2830_id_table);
893
894static struct i2c_driver rtl2830_driver = {
895 .driver = {
896 .owner = THIS_MODULE,
897 .name = "rtl2830",
898 },
899 .probe = rtl2830_probe,
900 .remove = rtl2830_remove,
901 .id_table = rtl2830_id_table,
902};
903
904module_i2c_driver(rtl2830_driver);
905
Antti Palosaaric0adca72011-07-08 23:34:09 -0300906MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
907MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver");
908MODULE_LICENSE("GPL");