Linux Audio

Check our new training course

Loading...
  1/*
  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 *
 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
 22/*
 23 * Driver implements own I2C-adapter for tuner I2C access. That's since chip
 24 * have unusual I2C-gate control which closes gate automatically after each
 25 * I2C transfer. Using own I2C adapter we can workaround that.
 26 */
 27
 28#include "rtl2830_priv.h"
 29
 30int rtl2830_debug;
 31module_param_named(debug, rtl2830_debug, int, 0644);
 32MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
 33
 34/* write multiple hardware registers */
 35static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
 36{
 37	int ret;
 38	u8 buf[1+len];
 39	struct i2c_msg msg[1] = {
 40		{
 41			.addr = priv->cfg.i2c_addr,
 42			.flags = 0,
 43			.len = 1+len,
 44			.buf = buf,
 45		}
 46	};
 47
 48	buf[0] = reg;
 49	memcpy(&buf[1], val, len);
 50
 51	ret = i2c_transfer(priv->i2c, msg, 1);
 52	if (ret == 1) {
 53		ret = 0;
 54	} else {
 55		warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
 56		ret = -EREMOTEIO;
 57	}
 58	return ret;
 59}
 60
 61/* read multiple hardware registers */
 62static int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
 63{
 64	int ret;
 65	struct i2c_msg msg[2] = {
 66		{
 67			.addr = priv->cfg.i2c_addr,
 68			.flags = 0,
 69			.len = 1,
 70			.buf = &reg,
 71		}, {
 72			.addr = priv->cfg.i2c_addr,
 73			.flags = I2C_M_RD,
 74			.len = len,
 75			.buf = val,
 76		}
 77	};
 78
 79	ret = i2c_transfer(priv->i2c, msg, 2);
 80	if (ret == 2) {
 81		ret = 0;
 82	} else {
 83		warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
 84		ret = -EREMOTEIO;
 85	}
 86	return ret;
 87}
 88
 89/* write multiple registers */
 90static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
 91{
 92	int ret;
 93	u8 reg2 = (reg >> 0) & 0xff;
 94	u8 page = (reg >> 8) & 0xff;
 95
 96	/* switch bank if needed */
 97	if (page != priv->page) {
 98		ret = rtl2830_wr(priv, 0x00, &page, 1);
 99		if (ret)
100			return ret;
101
102		priv->page = page;
103	}
104
105	return rtl2830_wr(priv, reg2, val, len);
106}
107
108/* read multiple registers */
109static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
110{
111	int ret;
112	u8 reg2 = (reg >> 0) & 0xff;
113	u8 page = (reg >> 8) & 0xff;
114
115	/* switch bank if needed */
116	if (page != priv->page) {
117		ret = rtl2830_wr(priv, 0x00, &page, 1);
118		if (ret)
119			return ret;
120
121		priv->page = page;
122	}
123
124	return rtl2830_rd(priv, reg2, val, len);
125}
126
127#if 0 /* currently not used */
128/* write single register */
129static int rtl2830_wr_reg(struct rtl2830_priv *priv, u16 reg, u8 val)
130{
131	return rtl2830_wr_regs(priv, reg, &val, 1);
132}
133#endif
134
135/* read single register */
136static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val)
137{
138	return rtl2830_rd_regs(priv, reg, val, 1);
139}
140
141/* write single register with mask */
142int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask)
143{
144	int ret;
145	u8 tmp;
146
147	/* no need for read if whole reg is written */
148	if (mask != 0xff) {
149		ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
150		if (ret)
151			return ret;
152
153		val &= mask;
154		tmp &= ~mask;
155		val |= tmp;
156	}
157
158	return rtl2830_wr_regs(priv, reg, &val, 1);
159}
160
161/* read single register with mask */
162int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask)
163{
164	int ret, i;
165	u8 tmp;
166
167	ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
168	if (ret)
169		return ret;
170
171	tmp &= mask;
172
173	/* find position of the first bit */
174	for (i = 0; i < 8; i++) {
175		if ((mask >> i) & 0x01)
176			break;
177	}
178	*val = tmp >> i;
179
180	return 0;
181}
182
183static int rtl2830_init(struct dvb_frontend *fe)
184{
185	struct rtl2830_priv *priv = fe->demodulator_priv;
186	int ret, i;
187	u64 num;
188	u8 buf[3], tmp;
189	u32 if_ctl;
190	struct rtl2830_reg_val_mask tab[] = {
191		{ 0x00d, 0x01, 0x03 },
192		{ 0x00d, 0x10, 0x10 },
193		{ 0x104, 0x00, 0x1e },
194		{ 0x105, 0x80, 0x80 },
195		{ 0x110, 0x02, 0x03 },
196		{ 0x110, 0x08, 0x0c },
197		{ 0x17b, 0x00, 0x40 },
198		{ 0x17d, 0x05, 0x0f },
199		{ 0x17d, 0x50, 0xf0 },
200		{ 0x18c, 0x08, 0x0f },
201		{ 0x18d, 0x00, 0xc0 },
202		{ 0x188, 0x05, 0x0f },
203		{ 0x189, 0x00, 0xfc },
204		{ 0x2d5, 0x02, 0x02 },
205		{ 0x2f1, 0x02, 0x06 },
206		{ 0x2f1, 0x20, 0xf8 },
207		{ 0x16d, 0x00, 0x01 },
208		{ 0x1a6, 0x00, 0x80 },
209		{ 0x106, priv->cfg.vtop, 0x3f },
210		{ 0x107, priv->cfg.krf, 0x3f },
211		{ 0x112, 0x28, 0xff },
212		{ 0x103, priv->cfg.agc_targ_val, 0xff },
213		{ 0x00a, 0x02, 0x07 },
214		{ 0x140, 0x0c, 0x3c },
215		{ 0x140, 0x40, 0xc0 },
216		{ 0x15b, 0x05, 0x07 },
217		{ 0x15b, 0x28, 0x38 },
218		{ 0x15c, 0x05, 0x07 },
219		{ 0x15c, 0x28, 0x38 },
220		{ 0x115, priv->cfg.spec_inv, 0x01 },
221		{ 0x16f, 0x01, 0x07 },
222		{ 0x170, 0x18, 0x38 },
223		{ 0x172, 0x0f, 0x0f },
224		{ 0x173, 0x08, 0x38 },
225		{ 0x175, 0x01, 0x07 },
226		{ 0x176, 0x00, 0xc0 },
227	};
228
229	for (i = 0; i < ARRAY_SIZE(tab); i++) {
230		ret = rtl2830_wr_reg_mask(priv, tab[i].reg, tab[i].val,
231			tab[i].mask);
232		if (ret)
233			goto err;
234	}
235
236	ret = rtl2830_wr_regs(priv, 0x18f, "\x28\x00", 2);
237	if (ret)
238		goto err;
239
240	ret = rtl2830_wr_regs(priv, 0x195,
241		"\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8);
242	if (ret)
243		goto err;
244
245	num = priv->cfg.if_dvbt % priv->cfg.xtal;
246	num *= 0x400000;
247	num = div_u64(num, priv->cfg.xtal);
248	num = -num;
249	if_ctl = num & 0x3fffff;
250	dbg("%s: if_ctl=%08x", __func__, if_ctl);
251
252	ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */
253	if (ret)
254		goto err;
255
256	buf[0] = tmp << 6;
257	buf[0] = (if_ctl >> 16) & 0x3f;
258	buf[1] = (if_ctl >>  8) & 0xff;
259	buf[2] = (if_ctl >>  0) & 0xff;
260
261	ret = rtl2830_wr_regs(priv, 0x119, buf, 3);
262	if (ret)
263		goto err;
264
265	/* TODO: spec init */
266
267	/* soft reset */
268	ret = rtl2830_wr_reg_mask(priv, 0x101, 0x04, 0x04);
269	if (ret)
270		goto err;
271
272	ret = rtl2830_wr_reg_mask(priv, 0x101, 0x00, 0x04);
273	if (ret)
274		goto err;
275
276	priv->sleeping = false;
277
278	return ret;
279err:
280	dbg("%s: failed=%d", __func__, ret);
281	return ret;
282}
283
284static int rtl2830_sleep(struct dvb_frontend *fe)
285{
286	struct rtl2830_priv *priv = fe->demodulator_priv;
287	priv->sleeping = true;
288	return 0;
289}
290
291int rtl2830_get_tune_settings(struct dvb_frontend *fe,
292	struct dvb_frontend_tune_settings *s)
293{
294	s->min_delay_ms = 500;
295	s->step_size = fe->ops.info.frequency_stepsize * 2;
296	s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
297
298	return 0;
299}
300
301static int rtl2830_set_frontend(struct dvb_frontend *fe)
302{
303	struct rtl2830_priv *priv = fe->demodulator_priv;
304	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
305	int ret, i;
306	static u8 bw_params1[3][34] = {
307		{
308		0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41,
309		0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a,
310		0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82,
311		0x03, 0x73, 0x03, 0xcf, /* 6 MHz */
312		}, {
313		0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca,
314		0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca,
315		0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e,
316		0x03, 0xd0, 0x04, 0x53, /* 7 MHz */
317		}, {
318		0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0,
319		0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a,
320		0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f,
321		0x04, 0x24, 0x04, 0xdb, /* 8 MHz */
322		},
323	};
324	static u8 bw_params2[3][6] = {
325		{0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30,}, /* 6 MHz */
326		{0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98,}, /* 7 MHz */
327		{0xae, 0xba, 0xf3, 0x26, 0x66, 0x64,}, /* 8 MHz */
328	};
329
330
331	dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__,
332		c->frequency, c->bandwidth_hz, c->inversion);
333
334	/* program tuner */
335	if (fe->ops.tuner_ops.set_params)
336		fe->ops.tuner_ops.set_params(fe);
337
338	switch (c->bandwidth_hz) {
339	case 6000000:
340		i = 0;
341		break;
342	case 7000000:
343		i = 1;
344		break;
345	case 8000000:
346		i = 2;
347		break;
348	default:
349		dbg("invalid bandwidth");
350		return -EINVAL;
351	}
352
353	ret = rtl2830_wr_reg_mask(priv, 0x008, i << 1, 0x06);
354	if (ret)
355		goto err;
356
357	/* 1/2 split I2C write */
358	ret = rtl2830_wr_regs(priv, 0x11c, &bw_params1[i][0], 17);
359	if (ret)
360		goto err;
361
362	/* 2/2 split I2C write */
363	ret = rtl2830_wr_regs(priv, 0x12d, &bw_params1[i][17], 17);
364	if (ret)
365		goto err;
366
367	ret = rtl2830_wr_regs(priv, 0x19d, bw_params2[i], 6);
368	if (ret)
369		goto err;
370
371	return ret;
372err:
373	dbg("%s: failed=%d", __func__, ret);
374	return ret;
375}
376
377static int rtl2830_get_frontend(struct dvb_frontend *fe)
378{
379	struct rtl2830_priv *priv = fe->demodulator_priv;
380	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
381	int ret;
382	u8 buf[3];
383
384	if (priv->sleeping)
385		return 0;
386
387	ret = rtl2830_rd_regs(priv, 0x33c, buf, 2);
388	if (ret)
389		goto err;
390
391	ret = rtl2830_rd_reg(priv, 0x351, &buf[2]);
392	if (ret)
393		goto err;
394
395	dbg("%s: TPS=%02x %02x %02x", __func__, buf[0], buf[1], buf[2]);
396
397	switch ((buf[0] >> 2) & 3) {
398	case 0:
399		c->modulation = QPSK;
400		break;
401	case 1:
402		c->modulation = QAM_16;
403		break;
404	case 2:
405		c->modulation = QAM_64;
406		break;
407	}
408
409	switch ((buf[2] >> 2) & 1) {
410	case 0:
411		c->transmission_mode = TRANSMISSION_MODE_2K;
412		break;
413	case 1:
414		c->transmission_mode = TRANSMISSION_MODE_8K;
415	}
416
417	switch ((buf[2] >> 0) & 3) {
418	case 0:
419		c->guard_interval = GUARD_INTERVAL_1_32;
420		break;
421	case 1:
422		c->guard_interval = GUARD_INTERVAL_1_16;
423		break;
424	case 2:
425		c->guard_interval = GUARD_INTERVAL_1_8;
426		break;
427	case 3:
428		c->guard_interval = GUARD_INTERVAL_1_4;
429		break;
430	}
431
432	switch ((buf[0] >> 4) & 7) {
433	case 0:
434		c->hierarchy = HIERARCHY_NONE;
435		break;
436	case 1:
437		c->hierarchy = HIERARCHY_1;
438		break;
439	case 2:
440		c->hierarchy = HIERARCHY_2;
441		break;
442	case 3:
443		c->hierarchy = HIERARCHY_4;
444		break;
445	}
446
447	switch ((buf[1] >> 3) & 7) {
448	case 0:
449		c->code_rate_HP = FEC_1_2;
450		break;
451	case 1:
452		c->code_rate_HP = FEC_2_3;
453		break;
454	case 2:
455		c->code_rate_HP = FEC_3_4;
456		break;
457	case 3:
458		c->code_rate_HP = FEC_5_6;
459		break;
460	case 4:
461		c->code_rate_HP = FEC_7_8;
462		break;
463	}
464
465	switch ((buf[1] >> 0) & 7) {
466	case 0:
467		c->code_rate_LP = FEC_1_2;
468		break;
469	case 1:
470		c->code_rate_LP = FEC_2_3;
471		break;
472	case 2:
473		c->code_rate_LP = FEC_3_4;
474		break;
475	case 3:
476		c->code_rate_LP = FEC_5_6;
477		break;
478	case 4:
479		c->code_rate_LP = FEC_7_8;
480		break;
481	}
482
483	return 0;
484err:
485	dbg("%s: failed=%d", __func__, ret);
486	return ret;
487}
488
489static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status)
490{
491	struct rtl2830_priv *priv = fe->demodulator_priv;
492	int ret;
493	u8 tmp;
494	*status = 0;
495
496	if (priv->sleeping)
497		return 0;
498
499	ret = rtl2830_rd_reg_mask(priv, 0x351, &tmp, 0x78); /* [6:3] */
500	if (ret)
501		goto err;
502
503	if (tmp == 11) {
504		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
505			FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
506	} else if (tmp == 10) {
507		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
508			FE_HAS_VITERBI;
509	}
510
511	return ret;
512err:
513	dbg("%s: failed=%d", __func__, ret);
514	return ret;
515}
516
517static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
518{
519	struct rtl2830_priv *priv = fe->demodulator_priv;
520	int ret, hierarchy, constellation;
521	u8 buf[2], tmp;
522	u16 tmp16;
523#define CONSTELLATION_NUM 3
524#define HIERARCHY_NUM 4
525	static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
526		{ 70705899, 70705899, 70705899, 70705899 },
527		{ 82433173, 82433173, 87483115, 94445660 },
528		{ 92888734, 92888734, 95487525, 99770748 },
529	};
530
531	if (priv->sleeping)
532		return 0;
533
534	/* reports SNR in resolution of 0.1 dB */
535
536	ret = rtl2830_rd_reg(priv, 0x33c, &tmp);
537	if (ret)
538		goto err;
539
540	constellation = (tmp >> 2) & 0x03; /* [3:2] */
541	if (constellation > CONSTELLATION_NUM - 1)
542		goto err;
543
544	hierarchy = (tmp >> 4) & 0x07; /* [6:4] */
545	if (hierarchy > HIERARCHY_NUM - 1)
546		goto err;
547
548	ret = rtl2830_rd_regs(priv, 0x40c, buf, 2);
549	if (ret)
550		goto err;
551
552	tmp16 = buf[0] << 8 | buf[1];
553
554	if (tmp16)
555		*snr = (snr_constant[constellation][hierarchy] -
556				intlog10(tmp16)) / ((1 << 24) / 100);
557	else
558		*snr = 0;
559
560	return 0;
561err:
562	dbg("%s: failed=%d", __func__, ret);
563	return ret;
564}
565
566static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
567{
568	struct rtl2830_priv *priv = fe->demodulator_priv;
569	int ret;
570	u8 buf[2];
571
572	if (priv->sleeping)
573		return 0;
574
575	ret = rtl2830_rd_regs(priv, 0x34e, buf, 2);
576	if (ret)
577		goto err;
578
579	*ber = buf[0] << 8 | buf[1];
580
581	return 0;
582err:
583	dbg("%s: failed=%d", __func__, ret);
584	return ret;
585}
586
587static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
588{
589	*ucblocks = 0;
590	return 0;
591}
592
593static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
594{
595	struct rtl2830_priv *priv = fe->demodulator_priv;
596	int ret;
597	u8 buf[2];
598	u16 if_agc_raw, if_agc;
599
600	if (priv->sleeping)
601		return 0;
602
603	ret = rtl2830_rd_regs(priv, 0x359, buf, 2);
604	if (ret)
605		goto err;
606
607	if_agc_raw = (buf[0] << 8 | buf[1]) & 0x3fff;
608
609	if (if_agc_raw & (1 << 9))
610		if_agc = -(~(if_agc_raw - 1) & 0x1ff);
611	else
612		if_agc = if_agc_raw;
613
614	*strength = (u8) (55 - if_agc / 182);
615	*strength |= *strength << 8;
616
617	return 0;
618err:
619	dbg("%s: failed=%d", __func__, ret);
620	return ret;
621}
622
623static struct dvb_frontend_ops rtl2830_ops;
624
625static u32 rtl2830_tuner_i2c_func(struct i2c_adapter *adapter)
626{
627	return I2C_FUNC_I2C;
628}
629
630static int rtl2830_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
631	struct i2c_msg msg[], int num)
632{
633	struct rtl2830_priv *priv = i2c_get_adapdata(i2c_adap);
634	int ret;
635
636	/* open i2c-gate */
637	ret = rtl2830_wr_reg_mask(priv, 0x101, 0x08, 0x08);
638	if (ret)
639		goto err;
640
641	ret = i2c_transfer(priv->i2c, msg, num);
642	if (ret < 0)
643		warn("tuner i2c failed=%d", ret);
644
645	return ret;
646err:
647	dbg("%s: failed=%d", __func__, ret);
648	return ret;
649}
650
651static struct i2c_algorithm rtl2830_tuner_i2c_algo = {
652	.master_xfer   = rtl2830_tuner_i2c_xfer,
653	.functionality = rtl2830_tuner_i2c_func,
654};
655
656struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(struct dvb_frontend *fe)
657{
658	struct rtl2830_priv *priv = fe->demodulator_priv;
659	return &priv->tuner_i2c_adapter;
660}
661EXPORT_SYMBOL(rtl2830_get_tuner_i2c_adapter);
662
663static void rtl2830_release(struct dvb_frontend *fe)
664{
665	struct rtl2830_priv *priv = fe->demodulator_priv;
666
667	i2c_del_adapter(&priv->tuner_i2c_adapter);
668	kfree(priv);
669}
670
671struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg,
672	struct i2c_adapter *i2c)
673{
674	struct rtl2830_priv *priv = NULL;
675	int ret = 0;
676	u8 tmp;
677
678	/* allocate memory for the internal state */
679	priv = kzalloc(sizeof(struct rtl2830_priv), GFP_KERNEL);
680	if (priv == NULL)
681		goto err;
682
683	/* setup the priv */
684	priv->i2c = i2c;
685	memcpy(&priv->cfg, cfg, sizeof(struct rtl2830_config));
686
687	/* check if the demod is there */
688	ret = rtl2830_rd_reg(priv, 0x000, &tmp);
689	if (ret)
690		goto err;
691
692	/* create dvb_frontend */
693	memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(struct dvb_frontend_ops));
694	priv->fe.demodulator_priv = priv;
695
696	/* create tuner i2c adapter */
697	strlcpy(priv->tuner_i2c_adapter.name, "RTL2830 tuner I2C adapter",
698		sizeof(priv->tuner_i2c_adapter.name));
699	priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo;
700	priv->tuner_i2c_adapter.algo_data = NULL;
701	i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
702	if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
703		err("tuner I2C bus could not be initialized");
704		goto err;
705	}
706
707	priv->sleeping = true;
708
709	return &priv->fe;
710err:
711	dbg("%s: failed=%d", __func__, ret);
712	kfree(priv);
713	return NULL;
714}
715EXPORT_SYMBOL(rtl2830_attach);
716
717static struct dvb_frontend_ops rtl2830_ops = {
718	.delsys = { SYS_DVBT },
719	.info = {
720		.name = "Realtek RTL2830 (DVB-T)",
721		.caps = FE_CAN_FEC_1_2 |
722			FE_CAN_FEC_2_3 |
723			FE_CAN_FEC_3_4 |
724			FE_CAN_FEC_5_6 |
725			FE_CAN_FEC_7_8 |
726			FE_CAN_FEC_AUTO |
727			FE_CAN_QPSK |
728			FE_CAN_QAM_16 |
729			FE_CAN_QAM_64 |
730			FE_CAN_QAM_AUTO |
731			FE_CAN_TRANSMISSION_MODE_AUTO |
732			FE_CAN_GUARD_INTERVAL_AUTO |
733			FE_CAN_HIERARCHY_AUTO |
734			FE_CAN_RECOVER |
735			FE_CAN_MUTE_TS
736	},
737
738	.release = rtl2830_release,
739
740	.init = rtl2830_init,
741	.sleep = rtl2830_sleep,
742
743	.get_tune_settings = rtl2830_get_tune_settings,
744
745	.set_frontend = rtl2830_set_frontend,
746	.get_frontend = rtl2830_get_frontend,
747
748	.read_status = rtl2830_read_status,
749	.read_snr = rtl2830_read_snr,
750	.read_ber = rtl2830_read_ber,
751	.read_ucblocks = rtl2830_read_ucblocks,
752	.read_signal_strength = rtl2830_read_signal_strength,
753};
754
755MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
756MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver");
757MODULE_LICENSE("GPL");