blob: ff73da9365e3c7083a6dea2343f0de0bb27a3bb6 [file] [log] [blame]
Thomas Mair82041c02012-05-18 14:47:40 -03001/*
2 * Realtek RTL2832 DVB-T demodulator driver
3 *
4 * Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com>
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 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21#include "rtl2832_priv.h"
Antti Palosaari73983492012-08-21 19:56:21 -030022#include "dvb_math.h"
Mauro Carvalho Chehab298f18a2012-07-05 12:16:26 -030023#include <linux/bitops.h>
Thomas Mair82041c02012-05-18 14:47:40 -030024
Mauro Carvalho Chehab37ebaf62013-11-02 05:11:47 -030025/* Max transfer size done by I2C transfer functions */
26#define MAX_XFER_SIZE 64
27
Thomas Mair82041c02012-05-18 14:47:40 -030028int rtl2832_debug;
29module_param_named(debug, rtl2832_debug, int, 0644);
30MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
31
Mauro Carvalho Chehab298f18a2012-07-05 12:16:26 -030032#define REG_MASK(b) (BIT(b + 1) - 1)
Thomas Mair82041c02012-05-18 14:47:40 -030033
34static const struct rtl2832_reg_entry registers[] = {
35 [DVBT_SOFT_RST] = {0x1, 0x1, 2, 2},
36 [DVBT_IIC_REPEAT] = {0x1, 0x1, 3, 3},
37 [DVBT_TR_WAIT_MIN_8K] = {0x1, 0x88, 11, 2},
38 [DVBT_RSD_BER_FAIL_VAL] = {0x1, 0x8f, 15, 0},
39 [DVBT_EN_BK_TRK] = {0x1, 0xa6, 7, 7},
40 [DVBT_AD_EN_REG] = {0x0, 0x8, 7, 7},
41 [DVBT_AD_EN_REG1] = {0x0, 0x8, 6, 6},
42 [DVBT_EN_BBIN] = {0x1, 0xb1, 0, 0},
43 [DVBT_MGD_THD0] = {0x1, 0x95, 7, 0},
44 [DVBT_MGD_THD1] = {0x1, 0x96, 7, 0},
45 [DVBT_MGD_THD2] = {0x1, 0x97, 7, 0},
46 [DVBT_MGD_THD3] = {0x1, 0x98, 7, 0},
47 [DVBT_MGD_THD4] = {0x1, 0x99, 7, 0},
48 [DVBT_MGD_THD5] = {0x1, 0x9a, 7, 0},
49 [DVBT_MGD_THD6] = {0x1, 0x9b, 7, 0},
50 [DVBT_MGD_THD7] = {0x1, 0x9c, 7, 0},
51 [DVBT_EN_CACQ_NOTCH] = {0x1, 0x61, 4, 4},
52 [DVBT_AD_AV_REF] = {0x0, 0x9, 6, 0},
53 [DVBT_REG_PI] = {0x0, 0xa, 2, 0},
54 [DVBT_PIP_ON] = {0x0, 0x21, 3, 3},
55 [DVBT_SCALE1_B92] = {0x2, 0x92, 7, 0},
56 [DVBT_SCALE1_B93] = {0x2, 0x93, 7, 0},
57 [DVBT_SCALE1_BA7] = {0x2, 0xa7, 7, 0},
58 [DVBT_SCALE1_BA9] = {0x2, 0xa9, 7, 0},
59 [DVBT_SCALE1_BAA] = {0x2, 0xaa, 7, 0},
60 [DVBT_SCALE1_BAB] = {0x2, 0xab, 7, 0},
61 [DVBT_SCALE1_BAC] = {0x2, 0xac, 7, 0},
62 [DVBT_SCALE1_BB0] = {0x2, 0xb0, 7, 0},
63 [DVBT_SCALE1_BB1] = {0x2, 0xb1, 7, 0},
64 [DVBT_KB_P1] = {0x1, 0x64, 3, 1},
65 [DVBT_KB_P2] = {0x1, 0x64, 6, 4},
66 [DVBT_KB_P3] = {0x1, 0x65, 2, 0},
67 [DVBT_OPT_ADC_IQ] = {0x0, 0x6, 5, 4},
68 [DVBT_AD_AVI] = {0x0, 0x9, 1, 0},
69 [DVBT_AD_AVQ] = {0x0, 0x9, 3, 2},
70 [DVBT_K1_CR_STEP12] = {0x2, 0xad, 9, 4},
71 [DVBT_TRK_KS_P2] = {0x1, 0x6f, 2, 0},
72 [DVBT_TRK_KS_I2] = {0x1, 0x70, 5, 3},
73 [DVBT_TR_THD_SET2] = {0x1, 0x72, 3, 0},
74 [DVBT_TRK_KC_P2] = {0x1, 0x73, 5, 3},
75 [DVBT_TRK_KC_I2] = {0x1, 0x75, 2, 0},
76 [DVBT_CR_THD_SET2] = {0x1, 0x76, 7, 6},
77 [DVBT_PSET_IFFREQ] = {0x1, 0x19, 21, 0},
78 [DVBT_SPEC_INV] = {0x1, 0x15, 0, 0},
79 [DVBT_RSAMP_RATIO] = {0x1, 0x9f, 27, 2},
80 [DVBT_CFREQ_OFF_RATIO] = {0x1, 0x9d, 23, 4},
81 [DVBT_FSM_STAGE] = {0x3, 0x51, 6, 3},
82 [DVBT_RX_CONSTEL] = {0x3, 0x3c, 3, 2},
83 [DVBT_RX_HIER] = {0x3, 0x3c, 6, 4},
84 [DVBT_RX_C_RATE_LP] = {0x3, 0x3d, 2, 0},
85 [DVBT_RX_C_RATE_HP] = {0x3, 0x3d, 5, 3},
86 [DVBT_GI_IDX] = {0x3, 0x51, 1, 0},
87 [DVBT_FFT_MODE_IDX] = {0x3, 0x51, 2, 2},
88 [DVBT_RSD_BER_EST] = {0x3, 0x4e, 15, 0},
89 [DVBT_CE_EST_EVM] = {0x4, 0xc, 15, 0},
90 [DVBT_RF_AGC_VAL] = {0x3, 0x5b, 13, 0},
91 [DVBT_IF_AGC_VAL] = {0x3, 0x59, 13, 0},
92 [DVBT_DAGC_VAL] = {0x3, 0x5, 7, 0},
93 [DVBT_SFREQ_OFF] = {0x3, 0x18, 13, 0},
94 [DVBT_CFREQ_OFF] = {0x3, 0x5f, 17, 0},
95 [DVBT_POLAR_RF_AGC] = {0x0, 0xe, 1, 1},
96 [DVBT_POLAR_IF_AGC] = {0x0, 0xe, 0, 0},
97 [DVBT_AAGC_HOLD] = {0x1, 0x4, 5, 5},
98 [DVBT_EN_RF_AGC] = {0x1, 0x4, 6, 6},
99 [DVBT_EN_IF_AGC] = {0x1, 0x4, 7, 7},
100 [DVBT_IF_AGC_MIN] = {0x1, 0x8, 7, 0},
101 [DVBT_IF_AGC_MAX] = {0x1, 0x9, 7, 0},
102 [DVBT_RF_AGC_MIN] = {0x1, 0xa, 7, 0},
103 [DVBT_RF_AGC_MAX] = {0x1, 0xb, 7, 0},
104 [DVBT_IF_AGC_MAN] = {0x1, 0xc, 6, 6},
105 [DVBT_IF_AGC_MAN_VAL] = {0x1, 0xc, 13, 0},
106 [DVBT_RF_AGC_MAN] = {0x1, 0xe, 6, 6},
107 [DVBT_RF_AGC_MAN_VAL] = {0x1, 0xe, 13, 0},
108 [DVBT_DAGC_TRG_VAL] = {0x1, 0x12, 7, 0},
109 [DVBT_AGC_TARG_VAL_0] = {0x1, 0x2, 0, 0},
110 [DVBT_AGC_TARG_VAL_8_1] = {0x1, 0x3, 7, 0},
111 [DVBT_AAGC_LOOP_GAIN] = {0x1, 0xc7, 5, 1},
112 [DVBT_LOOP_GAIN2_3_0] = {0x1, 0x4, 4, 1},
113 [DVBT_LOOP_GAIN2_4] = {0x1, 0x5, 7, 7},
114 [DVBT_LOOP_GAIN3] = {0x1, 0xc8, 4, 0},
115 [DVBT_VTOP1] = {0x1, 0x6, 5, 0},
116 [DVBT_VTOP2] = {0x1, 0xc9, 5, 0},
117 [DVBT_VTOP3] = {0x1, 0xca, 5, 0},
118 [DVBT_KRF1] = {0x1, 0xcb, 7, 0},
119 [DVBT_KRF2] = {0x1, 0x7, 7, 0},
120 [DVBT_KRF3] = {0x1, 0xcd, 7, 0},
121 [DVBT_KRF4] = {0x1, 0xce, 7, 0},
122 [DVBT_EN_GI_PGA] = {0x1, 0xe5, 0, 0},
123 [DVBT_THD_LOCK_UP] = {0x1, 0xd9, 8, 0},
124 [DVBT_THD_LOCK_DW] = {0x1, 0xdb, 8, 0},
125 [DVBT_THD_UP1] = {0x1, 0xdd, 7, 0},
126 [DVBT_THD_DW1] = {0x1, 0xde, 7, 0},
127 [DVBT_INTER_CNT_LEN] = {0x1, 0xd8, 3, 0},
128 [DVBT_GI_PGA_STATE] = {0x1, 0xe6, 3, 3},
129 [DVBT_EN_AGC_PGA] = {0x1, 0xd7, 0, 0},
130 [DVBT_CKOUTPAR] = {0x1, 0x7b, 5, 5},
131 [DVBT_CKOUT_PWR] = {0x1, 0x7b, 6, 6},
132 [DVBT_SYNC_DUR] = {0x1, 0x7b, 7, 7},
133 [DVBT_ERR_DUR] = {0x1, 0x7c, 0, 0},
134 [DVBT_SYNC_LVL] = {0x1, 0x7c, 1, 1},
135 [DVBT_ERR_LVL] = {0x1, 0x7c, 2, 2},
136 [DVBT_VAL_LVL] = {0x1, 0x7c, 3, 3},
137 [DVBT_SERIAL] = {0x1, 0x7c, 4, 4},
138 [DVBT_SER_LSB] = {0x1, 0x7c, 5, 5},
139 [DVBT_CDIV_PH0] = {0x1, 0x7d, 3, 0},
140 [DVBT_CDIV_PH1] = {0x1, 0x7d, 7, 4},
141 [DVBT_MPEG_IO_OPT_2_2] = {0x0, 0x6, 7, 7},
142 [DVBT_MPEG_IO_OPT_1_0] = {0x0, 0x7, 7, 6},
143 [DVBT_CKOUTPAR_PIP] = {0x0, 0xb7, 4, 4},
144 [DVBT_CKOUT_PWR_PIP] = {0x0, 0xb7, 3, 3},
145 [DVBT_SYNC_LVL_PIP] = {0x0, 0xb7, 2, 2},
146 [DVBT_ERR_LVL_PIP] = {0x0, 0xb7, 1, 1},
147 [DVBT_VAL_LVL_PIP] = {0x0, 0xb7, 0, 0},
148 [DVBT_CKOUTPAR_PID] = {0x0, 0xb9, 4, 4},
149 [DVBT_CKOUT_PWR_PID] = {0x0, 0xb9, 3, 3},
150 [DVBT_SYNC_LVL_PID] = {0x0, 0xb9, 2, 2},
151 [DVBT_ERR_LVL_PID] = {0x0, 0xb9, 1, 1},
152 [DVBT_VAL_LVL_PID] = {0x0, 0xb9, 0, 0},
153 [DVBT_SM_PASS] = {0x1, 0x93, 11, 0},
154 [DVBT_AD7_SETTING] = {0x0, 0x11, 15, 0},
155 [DVBT_RSSI_R] = {0x3, 0x1, 6, 0},
156 [DVBT_ACI_DET_IND] = {0x3, 0x12, 0, 0},
157 [DVBT_REG_MON] = {0x0, 0xd, 1, 0},
158 [DVBT_REG_MONSEL] = {0x0, 0xd, 2, 2},
159 [DVBT_REG_GPE] = {0x0, 0xd, 7, 7},
160 [DVBT_REG_GPO] = {0x0, 0x10, 0, 0},
161 [DVBT_REG_4MSEL] = {0x0, 0x13, 0, 0},
162};
163
164/* write multiple hardware registers */
165static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
166{
167 int ret;
Mauro Carvalho Chehab37ebaf62013-11-02 05:11:47 -0300168 u8 buf[MAX_XFER_SIZE];
Thomas Mair82041c02012-05-18 14:47:40 -0300169 struct i2c_msg msg[1] = {
170 {
171 .addr = priv->cfg.i2c_addr,
172 .flags = 0,
Mauro Carvalho Chehab37ebaf62013-11-02 05:11:47 -0300173 .len = 1 + len,
Thomas Mair82041c02012-05-18 14:47:40 -0300174 .buf = buf,
175 }
176 };
177
Mauro Carvalho Chehab37ebaf62013-11-02 05:11:47 -0300178 if (1 + len > sizeof(buf)) {
179 dev_warn(&priv->i2c->dev,
180 "%s: i2c wr reg=%04x: len=%d is too big!\n",
181 KBUILD_MODNAME, reg, len);
182 return -EINVAL;
183 }
184
Thomas Mair82041c02012-05-18 14:47:40 -0300185 buf[0] = reg;
186 memcpy(&buf[1], val, len);
187
188 ret = i2c_transfer(priv->i2c, msg, 1);
189 if (ret == 1) {
190 ret = 0;
191 } else {
Antti Palosaari298efdd2012-09-11 22:27:11 -0300192 dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
193 "len=%d\n", KBUILD_MODNAME, ret, reg, len);
Thomas Mair82041c02012-05-18 14:47:40 -0300194 ret = -EREMOTEIO;
195 }
196 return ret;
197}
198
199/* read multiple hardware registers */
200static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
201{
202 int ret;
203 struct i2c_msg msg[2] = {
204 {
205 .addr = priv->cfg.i2c_addr,
206 .flags = 0,
207 .len = 1,
208 .buf = &reg,
209 }, {
210 .addr = priv->cfg.i2c_addr,
211 .flags = I2C_M_RD,
212 .len = len,
213 .buf = val,
214 }
215 };
216
217 ret = i2c_transfer(priv->i2c, msg, 2);
218 if (ret == 2) {
219 ret = 0;
220 } else {
Antti Palosaari298efdd2012-09-11 22:27:11 -0300221 dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
222 "len=%d\n", KBUILD_MODNAME, ret, reg, len);
Thomas Mair82041c02012-05-18 14:47:40 -0300223 ret = -EREMOTEIO;
Antti Palosaari298efdd2012-09-11 22:27:11 -0300224 }
225 return ret;
Thomas Mair82041c02012-05-18 14:47:40 -0300226}
227
228/* write multiple registers */
229static int rtl2832_wr_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val,
230 int len)
231{
232 int ret;
233
Thomas Mair82041c02012-05-18 14:47:40 -0300234 /* switch bank if needed */
235 if (page != priv->page) {
236 ret = rtl2832_wr(priv, 0x00, &page, 1);
237 if (ret)
238 return ret;
239
240 priv->page = page;
241}
242
243return rtl2832_wr(priv, reg, val, len);
244}
245
246/* read multiple registers */
247static int rtl2832_rd_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val,
248 int len)
249{
250 int ret;
251
252 /* switch bank if needed */
253 if (page != priv->page) {
254 ret = rtl2832_wr(priv, 0x00, &page, 1);
255 if (ret)
256 return ret;
257
258 priv->page = page;
259 }
260
261 return rtl2832_rd(priv, reg, val, len);
262}
263
264#if 0 /* currently not used */
265/* write single register */
266static int rtl2832_wr_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 val)
267{
268 return rtl2832_wr_regs(priv, reg, page, &val, 1);
269}
270#endif
271
272/* read single register */
273static int rtl2832_rd_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val)
274{
275 return rtl2832_rd_regs(priv, reg, page, val, 1);
276}
277
Mauro Carvalho Chehabb0944ea2012-10-27 11:24:37 -0300278static int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val)
Thomas Mair82041c02012-05-18 14:47:40 -0300279{
280 int ret;
281
282 u8 reg_start_addr;
283 u8 msb, lsb;
284 u8 page;
285 u8 reading[4];
286 u32 reading_tmp;
287 int i;
288
289 u8 len;
290 u32 mask;
291
292 reg_start_addr = registers[reg].start_address;
293 msb = registers[reg].msb;
294 lsb = registers[reg].lsb;
295 page = registers[reg].page;
296
297 len = (msb >> 3) + 1;
Mauro Carvalho Chehab298f18a2012-07-05 12:16:26 -0300298 mask = REG_MASK(msb - lsb);
Thomas Mair82041c02012-05-18 14:47:40 -0300299
300 ret = rtl2832_rd_regs(priv, reg_start_addr, page, &reading[0], len);
301 if (ret)
302 goto err;
303
304 reading_tmp = 0;
305 for (i = 0; i < len; i++)
306 reading_tmp |= reading[i] << ((len - 1 - i) * 8);
307
308 *val = (reading_tmp >> lsb) & mask;
309
310 return ret;
311
312err:
Antti Palosaari298efdd2012-09-11 22:27:11 -0300313 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Thomas Mair82041c02012-05-18 14:47:40 -0300314 return ret;
315
316}
317
Mauro Carvalho Chehabb0944ea2012-10-27 11:24:37 -0300318static int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val)
Thomas Mair82041c02012-05-18 14:47:40 -0300319{
320 int ret, i;
321 u8 len;
322 u8 reg_start_addr;
323 u8 msb, lsb;
324 u8 page;
325 u32 mask;
326
327
328 u8 reading[4];
329 u8 writing[4];
330 u32 reading_tmp;
331 u32 writing_tmp;
332
333
334 reg_start_addr = registers[reg].start_address;
335 msb = registers[reg].msb;
336 lsb = registers[reg].lsb;
337 page = registers[reg].page;
338
339 len = (msb >> 3) + 1;
Mauro Carvalho Chehab298f18a2012-07-05 12:16:26 -0300340 mask = REG_MASK(msb - lsb);
Thomas Mair82041c02012-05-18 14:47:40 -0300341
342
343 ret = rtl2832_rd_regs(priv, reg_start_addr, page, &reading[0], len);
344 if (ret)
345 goto err;
346
347 reading_tmp = 0;
348 for (i = 0; i < len; i++)
349 reading_tmp |= reading[i] << ((len - 1 - i) * 8);
350
351 writing_tmp = reading_tmp & ~(mask << lsb);
352 writing_tmp |= ((val & mask) << lsb);
353
354
355 for (i = 0; i < len; i++)
356 writing[i] = (writing_tmp >> ((len - 1 - i) * 8)) & 0xff;
357
358 ret = rtl2832_wr_regs(priv, reg_start_addr, page, &writing[0], len);
359 if (ret)
360 goto err;
361
362 return ret;
363
364err:
Antti Palosaari298efdd2012-09-11 22:27:11 -0300365 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Thomas Mair82041c02012-05-18 14:47:40 -0300366 return ret;
367
368}
369
Thomas Mair82041c02012-05-18 14:47:40 -0300370static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
371{
372 int ret;
373 struct rtl2832_priv *priv = fe->demodulator_priv;
374
Antti Palosaari298efdd2012-09-11 22:27:11 -0300375 dev_dbg(&priv->i2c->dev, "%s: enable=%d\n", __func__, enable);
Thomas Mair82041c02012-05-18 14:47:40 -0300376
377 /* gate already open or close */
378 if (priv->i2c_gate_state == enable)
379 return 0;
380
381 ret = rtl2832_wr_demod_reg(priv, DVBT_IIC_REPEAT, (enable ? 0x1 : 0x0));
382 if (ret)
383 goto err;
384
385 priv->i2c_gate_state = enable;
386
387 return ret;
388err:
Antti Palosaari298efdd2012-09-11 22:27:11 -0300389 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Thomas Mair82041c02012-05-18 14:47:40 -0300390 return ret;
391}
392
Mauro Carvalho Chehab884655a2013-04-09 22:16:52 -0300393
394static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq)
395{
396 struct rtl2832_priv *priv = fe->demodulator_priv;
397 int ret;
398 u64 pset_iffreq;
399 u8 en_bbin = (if_freq == 0 ? 0x1 : 0x0);
400
401 /*
402 * PSET_IFFREQ = - floor((IfFreqHz % CrystalFreqHz) * pow(2, 22)
403 * / CrystalFreqHz)
404 */
405
406 pset_iffreq = if_freq % priv->cfg.xtal;
407 pset_iffreq *= 0x400000;
408 pset_iffreq = div_u64(pset_iffreq, priv->cfg.xtal);
Mauro Carvalho Chehabc8832e82013-04-15 19:44:39 -0300409 pset_iffreq = -pset_iffreq;
Mauro Carvalho Chehab884655a2013-04-09 22:16:52 -0300410 pset_iffreq = pset_iffreq & 0x3fffff;
Mauro Carvalho Chehabc8832e82013-04-15 19:44:39 -0300411 dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d pset_iffreq=%08x\n",
412 __func__, if_freq, (unsigned)pset_iffreq);
413
Mauro Carvalho Chehab884655a2013-04-09 22:16:52 -0300414 ret = rtl2832_wr_demod_reg(priv, DVBT_EN_BBIN, en_bbin);
415 if (ret)
416 return ret;
417
418 ret = rtl2832_wr_demod_reg(priv, DVBT_PSET_IFFREQ, pset_iffreq);
419
420 return (ret);
421}
422
Thomas Mair82041c02012-05-18 14:47:40 -0300423static int rtl2832_init(struct dvb_frontend *fe)
424{
425 struct rtl2832_priv *priv = fe->demodulator_priv;
Antti Palosaari832cc7c2012-09-11 22:27:04 -0300426 const struct rtl2832_reg_value *init;
Mauro Carvalho Chehab884655a2013-04-09 22:16:52 -0300427 int i, ret, len;
Thomas Mair82041c02012-05-18 14:47:40 -0300428
429 /* initialization values for the demodulator registers */
430 struct rtl2832_reg_value rtl2832_initial_regs[] = {
431 {DVBT_AD_EN_REG, 0x1},
432 {DVBT_AD_EN_REG1, 0x1},
433 {DVBT_RSD_BER_FAIL_VAL, 0x2800},
434 {DVBT_MGD_THD0, 0x10},
435 {DVBT_MGD_THD1, 0x20},
436 {DVBT_MGD_THD2, 0x20},
437 {DVBT_MGD_THD3, 0x40},
438 {DVBT_MGD_THD4, 0x22},
439 {DVBT_MGD_THD5, 0x32},
440 {DVBT_MGD_THD6, 0x37},
441 {DVBT_MGD_THD7, 0x39},
442 {DVBT_EN_BK_TRK, 0x0},
443 {DVBT_EN_CACQ_NOTCH, 0x0},
444 {DVBT_AD_AV_REF, 0x2a},
445 {DVBT_REG_PI, 0x6},
446 {DVBT_PIP_ON, 0x0},
447 {DVBT_CDIV_PH0, 0x8},
448 {DVBT_CDIV_PH1, 0x8},
449 {DVBT_SCALE1_B92, 0x4},
450 {DVBT_SCALE1_B93, 0xb0},
451 {DVBT_SCALE1_BA7, 0x78},
452 {DVBT_SCALE1_BA9, 0x28},
453 {DVBT_SCALE1_BAA, 0x59},
454 {DVBT_SCALE1_BAB, 0x83},
455 {DVBT_SCALE1_BAC, 0xd4},
456 {DVBT_SCALE1_BB0, 0x65},
457 {DVBT_SCALE1_BB1, 0x43},
458 {DVBT_KB_P1, 0x1},
459 {DVBT_KB_P2, 0x4},
460 {DVBT_KB_P3, 0x7},
461 {DVBT_K1_CR_STEP12, 0xa},
462 {DVBT_REG_GPE, 0x1},
463 {DVBT_SERIAL, 0x0},
464 {DVBT_CDIV_PH0, 0x9},
465 {DVBT_CDIV_PH1, 0x9},
466 {DVBT_MPEG_IO_OPT_2_2, 0x0},
467 {DVBT_MPEG_IO_OPT_1_0, 0x0},
468 {DVBT_TRK_KS_P2, 0x4},
469 {DVBT_TRK_KS_I2, 0x7},
470 {DVBT_TR_THD_SET2, 0x6},
471 {DVBT_TRK_KC_I2, 0x5},
472 {DVBT_CR_THD_SET2, 0x1},
Thomas Mair82041c02012-05-18 14:47:40 -0300473 };
474
Antti Palosaari298efdd2012-09-11 22:27:11 -0300475 dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
Thomas Mair82041c02012-05-18 14:47:40 -0300476
Thomas Mair82041c02012-05-18 14:47:40 -0300477 for (i = 0; i < ARRAY_SIZE(rtl2832_initial_regs); i++) {
478 ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs[i].reg,
479 rtl2832_initial_regs[i].value);
480 if (ret)
481 goto err;
482 }
483
Antti Palosaari832cc7c2012-09-11 22:27:04 -0300484 /* load tuner specific settings */
Antti Palosaari298efdd2012-09-11 22:27:11 -0300485 dev_dbg(&priv->i2c->dev, "%s: load settings for tuner=%02x\n",
486 __func__, priv->cfg.tuner);
Antti Palosaari832cc7c2012-09-11 22:27:04 -0300487 switch (priv->cfg.tuner) {
488 case RTL2832_TUNER_FC0012:
489 case RTL2832_TUNER_FC0013:
490 len = ARRAY_SIZE(rtl2832_tuner_init_fc0012);
491 init = rtl2832_tuner_init_fc0012;
492 break;
Antti Palosaari5db41872012-09-11 22:27:08 -0300493 case RTL2832_TUNER_TUA9001:
494 len = ARRAY_SIZE(rtl2832_tuner_init_tua9001);
495 init = rtl2832_tuner_init_tua9001;
496 break;
Antti Palosaari7e688de2012-09-17 17:53:04 -0300497 case RTL2832_TUNER_E4000:
498 len = ARRAY_SIZE(rtl2832_tuner_init_e4000);
499 init = rtl2832_tuner_init_e4000;
500 break;
Mauro Carvalho Chehabfa4bfd22013-04-09 18:19:50 -0300501 case RTL2832_TUNER_R820T:
Antti Palosaaria26758e2013-10-30 00:36:38 -0300502 case RTL2832_TUNER_R828D:
Mauro Carvalho Chehabfa4bfd22013-04-09 18:19:50 -0300503 len = ARRAY_SIZE(rtl2832_tuner_init_r820t);
504 init = rtl2832_tuner_init_r820t;
505 break;
Antti Palosaari832cc7c2012-09-11 22:27:04 -0300506 default:
507 ret = -EINVAL;
508 goto err;
509 }
510
511 for (i = 0; i < len; i++) {
Antti Palosaari5db41872012-09-11 22:27:08 -0300512 ret = rtl2832_wr_demod_reg(priv, init[i].reg, init[i].value);
Antti Palosaari832cc7c2012-09-11 22:27:04 -0300513 if (ret)
514 goto err;
515 }
516
Mauro Carvalho Chehabfa4bfd22013-04-09 18:19:50 -0300517 if (!fe->ops.tuner_ops.get_if_frequency) {
Mauro Carvalho Chehab884655a2013-04-09 22:16:52 -0300518 ret = rtl2832_set_if(fe, priv->cfg.if_dvbt);
519 if (ret)
520 goto err;
Mauro Carvalho Chehabfa4bfd22013-04-09 18:19:50 -0300521 }
522
523 /*
524 * r820t NIM code does a software reset here at the demod -
525 * may not be needed, as there's already a software reset at set_params()
526 */
527#if 1
528 /* soft reset */
529 ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1);
530 if (ret)
531 goto err;
532
533 ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0);
534 if (ret)
535 goto err;
536#endif
Thomas Mair82041c02012-05-18 14:47:40 -0300537
538 priv->sleeping = false;
539
540 return ret;
541
542err:
Antti Palosaari298efdd2012-09-11 22:27:11 -0300543 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Thomas Mair82041c02012-05-18 14:47:40 -0300544 return ret;
545}
546
547static int rtl2832_sleep(struct dvb_frontend *fe)
548{
549 struct rtl2832_priv *priv = fe->demodulator_priv;
550
Antti Palosaari298efdd2012-09-11 22:27:11 -0300551 dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
Thomas Mair82041c02012-05-18 14:47:40 -0300552 priv->sleeping = true;
553 return 0;
554}
555
Mauro Carvalho Chehabb0944ea2012-10-27 11:24:37 -0300556static int rtl2832_get_tune_settings(struct dvb_frontend *fe,
Thomas Mair82041c02012-05-18 14:47:40 -0300557 struct dvb_frontend_tune_settings *s)
558{
Antti Palosaari298efdd2012-09-11 22:27:11 -0300559 struct rtl2832_priv *priv = fe->demodulator_priv;
560
561 dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
Thomas Mair82041c02012-05-18 14:47:40 -0300562 s->min_delay_ms = 1000;
563 s->step_size = fe->ops.info.frequency_stepsize * 2;
564 s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
565 return 0;
566}
567
568static int rtl2832_set_frontend(struct dvb_frontend *fe)
569{
570 struct rtl2832_priv *priv = fe->demodulator_priv;
571 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
572 int ret, i, j;
573 u64 bw_mode, num, num2;
574 u32 resamp_ratio, cfreq_off_ratio;
Thomas Mair82041c02012-05-18 14:47:40 -0300575 static u8 bw_params[3][32] = {
576 /* 6 MHz bandwidth */
577 {
578 0xf5, 0xff, 0x15, 0x38, 0x5d, 0x6d, 0x52, 0x07, 0xfa, 0x2f,
579 0x53, 0xf5, 0x3f, 0xca, 0x0b, 0x91, 0xea, 0x30, 0x63, 0xb2,
580 0x13, 0xda, 0x0b, 0xc4, 0x18, 0x7e, 0x16, 0x66, 0x08, 0x67,
581 0x19, 0xe0,
582 },
583
584 /* 7 MHz bandwidth */
585 {
586 0xe7, 0xcc, 0xb5, 0xba, 0xe8, 0x2f, 0x67, 0x61, 0x00, 0xaf,
587 0x86, 0xf2, 0xbf, 0x59, 0x04, 0x11, 0xb6, 0x33, 0xa4, 0x30,
588 0x15, 0x10, 0x0a, 0x42, 0x18, 0xf8, 0x17, 0xd9, 0x07, 0x22,
589 0x19, 0x10,
590 },
591
592 /* 8 MHz bandwidth */
593 {
594 0x09, 0xf6, 0xd2, 0xa7, 0x9a, 0xc9, 0x27, 0x77, 0x06, 0xbf,
595 0xec, 0xf4, 0x4f, 0x0b, 0xfc, 0x01, 0x63, 0x35, 0x54, 0xa7,
596 0x16, 0x66, 0x08, 0xb4, 0x19, 0x6e, 0x19, 0x65, 0x05, 0xc8,
597 0x19, 0xe0,
598 },
599 };
600
601
Antti Palosaari298efdd2012-09-11 22:27:11 -0300602 dev_dbg(&priv->i2c->dev, "%s: frequency=%d bandwidth_hz=%d " \
603 "inversion=%d\n", __func__, c->frequency,
604 c->bandwidth_hz, c->inversion);
Thomas Mair82041c02012-05-18 14:47:40 -0300605
606 /* program tuner */
607 if (fe->ops.tuner_ops.set_params)
608 fe->ops.tuner_ops.set_params(fe);
609
Mauro Carvalho Chehabfa4bfd22013-04-09 18:19:50 -0300610 /* If the frontend has get_if_frequency(), use it */
611 if (fe->ops.tuner_ops.get_if_frequency) {
612 u32 if_freq;
Mauro Carvalho Chehabfa4bfd22013-04-09 18:19:50 -0300613
614 ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
615 if (ret)
616 goto err;
617
Mauro Carvalho Chehab884655a2013-04-09 22:16:52 -0300618 ret = rtl2832_set_if(fe, if_freq);
Mauro Carvalho Chehabfa4bfd22013-04-09 18:19:50 -0300619 if (ret)
620 goto err;
621 }
622
Thomas Mair82041c02012-05-18 14:47:40 -0300623 switch (c->bandwidth_hz) {
624 case 6000000:
625 i = 0;
626 bw_mode = 48000000;
627 break;
628 case 7000000:
629 i = 1;
630 bw_mode = 56000000;
631 break;
632 case 8000000:
633 i = 2;
634 bw_mode = 64000000;
635 break;
636 default:
Antti Palosaari298efdd2012-09-11 22:27:11 -0300637 dev_dbg(&priv->i2c->dev, "%s: invalid bandwidth\n", __func__);
Thomas Mair82041c02012-05-18 14:47:40 -0300638 return -EINVAL;
639 }
640
Hans-Frieder Vogtfc4b3fa2012-07-15 13:56:47 -0300641 for (j = 0; j < sizeof(bw_params[0]); j++) {
Thomas Mair82041c02012-05-18 14:47:40 -0300642 ret = rtl2832_wr_regs(priv, 0x1c+j, 1, &bw_params[i][j], 1);
643 if (ret)
644 goto err;
645 }
646
647 /* calculate and set resample ratio
648 * RSAMP_RATIO = floor(CrystalFreqHz * 7 * pow(2, 22)
649 * / ConstWithBandwidthMode)
650 */
651 num = priv->cfg.xtal * 7;
652 num *= 0x400000;
653 num = div_u64(num, bw_mode);
654 resamp_ratio = num & 0x3ffffff;
655 ret = rtl2832_wr_demod_reg(priv, DVBT_RSAMP_RATIO, resamp_ratio);
656 if (ret)
657 goto err;
658
659 /* calculate and set cfreq off ratio
660 * CFREQ_OFF_RATIO = - floor(ConstWithBandwidthMode * pow(2, 20)
661 * / (CrystalFreqHz * 7))
662 */
663 num = bw_mode << 20;
664 num2 = priv->cfg.xtal * 7;
665 num = div_u64(num, num2);
666 num = -num;
667 cfreq_off_ratio = num & 0xfffff;
668 ret = rtl2832_wr_demod_reg(priv, DVBT_CFREQ_OFF_RATIO, cfreq_off_ratio);
669 if (ret)
670 goto err;
671
672
673 /* soft reset */
674 ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1);
675 if (ret)
676 goto err;
677
678 ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0);
679 if (ret)
680 goto err;
681
682 return ret;
683err:
Antti Palosaari298efdd2012-09-11 22:27:11 -0300684 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Thomas Mair82041c02012-05-18 14:47:40 -0300685 return ret;
686}
687
Antti Palosaari0ce67a22012-08-21 19:56:20 -0300688static int rtl2832_get_frontend(struct dvb_frontend *fe)
689{
690 struct rtl2832_priv *priv = fe->demodulator_priv;
691 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
692 int ret;
693 u8 buf[3];
694
695 if (priv->sleeping)
696 return 0;
697
698 ret = rtl2832_rd_regs(priv, 0x3c, 3, buf, 2);
699 if (ret)
700 goto err;
701
702 ret = rtl2832_rd_reg(priv, 0x51, 3, &buf[2]);
703 if (ret)
704 goto err;
705
Antti Palosaari298efdd2012-09-11 22:27:11 -0300706 dev_dbg(&priv->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf);
Antti Palosaari0ce67a22012-08-21 19:56:20 -0300707
708 switch ((buf[0] >> 2) & 3) {
709 case 0:
710 c->modulation = QPSK;
711 break;
712 case 1:
713 c->modulation = QAM_16;
714 break;
715 case 2:
716 c->modulation = QAM_64;
717 break;
718 }
719
720 switch ((buf[2] >> 2) & 1) {
721 case 0:
722 c->transmission_mode = TRANSMISSION_MODE_2K;
723 break;
724 case 1:
725 c->transmission_mode = TRANSMISSION_MODE_8K;
726 }
727
728 switch ((buf[2] >> 0) & 3) {
729 case 0:
730 c->guard_interval = GUARD_INTERVAL_1_32;
731 break;
732 case 1:
733 c->guard_interval = GUARD_INTERVAL_1_16;
734 break;
735 case 2:
736 c->guard_interval = GUARD_INTERVAL_1_8;
737 break;
738 case 3:
739 c->guard_interval = GUARD_INTERVAL_1_4;
740 break;
741 }
742
743 switch ((buf[0] >> 4) & 7) {
744 case 0:
745 c->hierarchy = HIERARCHY_NONE;
746 break;
747 case 1:
748 c->hierarchy = HIERARCHY_1;
749 break;
750 case 2:
751 c->hierarchy = HIERARCHY_2;
752 break;
753 case 3:
754 c->hierarchy = HIERARCHY_4;
755 break;
756 }
757
758 switch ((buf[1] >> 3) & 7) {
759 case 0:
760 c->code_rate_HP = FEC_1_2;
761 break;
762 case 1:
763 c->code_rate_HP = FEC_2_3;
764 break;
765 case 2:
766 c->code_rate_HP = FEC_3_4;
767 break;
768 case 3:
769 c->code_rate_HP = FEC_5_6;
770 break;
771 case 4:
772 c->code_rate_HP = FEC_7_8;
773 break;
774 }
775
776 switch ((buf[1] >> 0) & 7) {
777 case 0:
778 c->code_rate_LP = FEC_1_2;
779 break;
780 case 1:
781 c->code_rate_LP = FEC_2_3;
782 break;
783 case 2:
784 c->code_rate_LP = FEC_3_4;
785 break;
786 case 3:
787 c->code_rate_LP = FEC_5_6;
788 break;
789 case 4:
790 c->code_rate_LP = FEC_7_8;
791 break;
792 }
793
794 return 0;
795err:
Antti Palosaari298efdd2012-09-11 22:27:11 -0300796 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaari0ce67a22012-08-21 19:56:20 -0300797 return ret;
798}
799
Thomas Mair82041c02012-05-18 14:47:40 -0300800static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status)
801{
802 struct rtl2832_priv *priv = fe->demodulator_priv;
803 int ret;
804 u32 tmp;
805 *status = 0;
806
Antti Palosaari298efdd2012-09-11 22:27:11 -0300807 dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
Thomas Mair82041c02012-05-18 14:47:40 -0300808 if (priv->sleeping)
809 return 0;
810
811 ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE, &tmp);
812 if (ret)
813 goto err;
814
815 if (tmp == 11) {
816 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
817 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
818 }
819 /* TODO find out if this is also true for rtl2832? */
820 /*else if (tmp == 10) {
821 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
822 FE_HAS_VITERBI;
823 }*/
824
825 return ret;
826err:
Antti Palosaari298efdd2012-09-11 22:27:11 -0300827 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Thomas Mair82041c02012-05-18 14:47:40 -0300828 return ret;
829}
830
Antti Palosaari73983492012-08-21 19:56:21 -0300831static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr)
832{
833 struct rtl2832_priv *priv = fe->demodulator_priv;
834 int ret, hierarchy, constellation;
835 u8 buf[2], tmp;
836 u16 tmp16;
837#define CONSTELLATION_NUM 3
838#define HIERARCHY_NUM 4
839 static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
840 { 85387325, 85387325, 85387325, 85387325 },
841 { 86676178, 86676178, 87167949, 87795660 },
842 { 87659938, 87659938, 87885178, 88241743 },
843 };
844
845 /* reports SNR in resolution of 0.1 dB */
846
847 ret = rtl2832_rd_reg(priv, 0x3c, 3, &tmp);
848 if (ret)
849 goto err;
850
851 constellation = (tmp >> 2) & 0x03; /* [3:2] */
852 if (constellation > CONSTELLATION_NUM - 1)
853 goto err;
854
855 hierarchy = (tmp >> 4) & 0x07; /* [6:4] */
856 if (hierarchy > HIERARCHY_NUM - 1)
857 goto err;
858
859 ret = rtl2832_rd_regs(priv, 0x0c, 4, buf, 2);
860 if (ret)
861 goto err;
862
863 tmp16 = buf[0] << 8 | buf[1];
864
865 if (tmp16)
866 *snr = (snr_constant[constellation][hierarchy] -
867 intlog10(tmp16)) / ((1 << 24) / 100);
868 else
869 *snr = 0;
870
871 return 0;
872err:
Antti Palosaari298efdd2012-09-11 22:27:11 -0300873 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaari73983492012-08-21 19:56:21 -0300874 return ret;
875}
876
Antti Palosaaridb32d742012-08-21 19:56:22 -0300877static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber)
878{
879 struct rtl2832_priv *priv = fe->demodulator_priv;
880 int ret;
881 u8 buf[2];
882
883 ret = rtl2832_rd_regs(priv, 0x4e, 3, buf, 2);
884 if (ret)
885 goto err;
886
887 *ber = buf[0] << 8 | buf[1];
888
889 return 0;
890err:
Antti Palosaari298efdd2012-09-11 22:27:11 -0300891 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaaridb32d742012-08-21 19:56:22 -0300892 return ret;
893}
894
Thomas Mair82041c02012-05-18 14:47:40 -0300895static struct dvb_frontend_ops rtl2832_ops;
896
897static void rtl2832_release(struct dvb_frontend *fe)
898{
899 struct rtl2832_priv *priv = fe->demodulator_priv;
900
Antti Palosaari298efdd2012-09-11 22:27:11 -0300901 dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
Thomas Mair82041c02012-05-18 14:47:40 -0300902 kfree(priv);
903}
904
905struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
906 struct i2c_adapter *i2c)
907{
908 struct rtl2832_priv *priv = NULL;
909 int ret = 0;
910 u8 tmp;
911
Antti Palosaari298efdd2012-09-11 22:27:11 -0300912 dev_dbg(&i2c->dev, "%s:\n", __func__);
Thomas Mair82041c02012-05-18 14:47:40 -0300913
914 /* allocate memory for the internal state */
915 priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL);
916 if (priv == NULL)
917 goto err;
918
919 /* setup the priv */
920 priv->i2c = i2c;
921 priv->tuner = cfg->tuner;
922 memcpy(&priv->cfg, cfg, sizeof(struct rtl2832_config));
923
924 /* check if the demod is there */
925 ret = rtl2832_rd_reg(priv, 0x00, 0x0, &tmp);
926 if (ret)
927 goto err;
928
929 /* create dvb_frontend */
930 memcpy(&priv->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops));
931 priv->fe.demodulator_priv = priv;
932
933 /* TODO implement sleep mode */
934 priv->sleeping = true;
935
936 return &priv->fe;
937err:
Antti Palosaari298efdd2012-09-11 22:27:11 -0300938 dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
Thomas Mair82041c02012-05-18 14:47:40 -0300939 kfree(priv);
940 return NULL;
941}
942EXPORT_SYMBOL(rtl2832_attach);
943
944static struct dvb_frontend_ops rtl2832_ops = {
945 .delsys = { SYS_DVBT },
946 .info = {
947 .name = "Realtek RTL2832 (DVB-T)",
948 .frequency_min = 174000000,
949 .frequency_max = 862000000,
950 .frequency_stepsize = 166667,
951 .caps = FE_CAN_FEC_1_2 |
952 FE_CAN_FEC_2_3 |
953 FE_CAN_FEC_3_4 |
954 FE_CAN_FEC_5_6 |
955 FE_CAN_FEC_7_8 |
956 FE_CAN_FEC_AUTO |
957 FE_CAN_QPSK |
958 FE_CAN_QAM_16 |
959 FE_CAN_QAM_64 |
960 FE_CAN_QAM_AUTO |
961 FE_CAN_TRANSMISSION_MODE_AUTO |
962 FE_CAN_GUARD_INTERVAL_AUTO |
963 FE_CAN_HIERARCHY_AUTO |
964 FE_CAN_RECOVER |
965 FE_CAN_MUTE_TS
966 },
967
968 .release = rtl2832_release,
969
970 .init = rtl2832_init,
971 .sleep = rtl2832_sleep,
972
973 .get_tune_settings = rtl2832_get_tune_settings,
974
975 .set_frontend = rtl2832_set_frontend,
Antti Palosaari0ce67a22012-08-21 19:56:20 -0300976 .get_frontend = rtl2832_get_frontend,
Thomas Mair82041c02012-05-18 14:47:40 -0300977
978 .read_status = rtl2832_read_status,
Antti Palosaari73983492012-08-21 19:56:21 -0300979 .read_snr = rtl2832_read_snr,
Antti Palosaaridb32d742012-08-21 19:56:22 -0300980 .read_ber = rtl2832_read_ber,
Antti Palosaari73983492012-08-21 19:56:21 -0300981
Thomas Mair82041c02012-05-18 14:47:40 -0300982 .i2c_gate_ctrl = rtl2832_i2c_gate_ctrl,
983};
984
985MODULE_AUTHOR("Thomas Mair <mair.thomas86@gmail.com>");
986MODULE_DESCRIPTION("Realtek RTL2832 DVB-T demodulator driver");
987MODULE_LICENSE("GPL");
988MODULE_VERSION("0.5");