1c0adca734013389ac81513da546947e75d95151aAntti Palosaari/*
2c0adca734013389ac81513da546947e75d95151aAntti Palosaari * Realtek RTL2830 DVB-T demodulator driver
3c0adca734013389ac81513da546947e75d95151aAntti Palosaari *
4c0adca734013389ac81513da546947e75d95151aAntti Palosaari * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
5c0adca734013389ac81513da546947e75d95151aAntti Palosaari *
6c0adca734013389ac81513da546947e75d95151aAntti Palosaari *    This program is free software; you can redistribute it and/or modify
7c0adca734013389ac81513da546947e75d95151aAntti Palosaari *    it under the terms of the GNU General Public License as published by
8c0adca734013389ac81513da546947e75d95151aAntti Palosaari *    the Free Software Foundation; either version 2 of the License, or
9c0adca734013389ac81513da546947e75d95151aAntti Palosaari *    (at your option) any later version.
10c0adca734013389ac81513da546947e75d95151aAntti Palosaari *
11c0adca734013389ac81513da546947e75d95151aAntti Palosaari *    This program is distributed in the hope that it will be useful,
12c0adca734013389ac81513da546947e75d95151aAntti Palosaari *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13c0adca734013389ac81513da546947e75d95151aAntti Palosaari *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14c0adca734013389ac81513da546947e75d95151aAntti Palosaari *    GNU General Public License for more details.
15c0adca734013389ac81513da546947e75d95151aAntti Palosaari *
16c0adca734013389ac81513da546947e75d95151aAntti Palosaari *    You should have received a copy of the GNU General Public License along
17c0adca734013389ac81513da546947e75d95151aAntti Palosaari *    with this program; if not, write to the Free Software Foundation, Inc.,
18c0adca734013389ac81513da546947e75d95151aAntti Palosaari *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19c0adca734013389ac81513da546947e75d95151aAntti Palosaari */
20c0adca734013389ac81513da546947e75d95151aAntti Palosaari
21c0adca734013389ac81513da546947e75d95151aAntti Palosaari
22c0adca734013389ac81513da546947e75d95151aAntti Palosaari/*
23c0adca734013389ac81513da546947e75d95151aAntti Palosaari * Driver implements own I2C-adapter for tuner I2C access. That's since chip
24c0adca734013389ac81513da546947e75d95151aAntti Palosaari * have unusual I2C-gate control which closes gate automatically after each
25c0adca734013389ac81513da546947e75d95151aAntti Palosaari * I2C transfer. Using own I2C adapter we can workaround that.
26c0adca734013389ac81513da546947e75d95151aAntti Palosaari */
27c0adca734013389ac81513da546947e75d95151aAntti Palosaari
28c0adca734013389ac81513da546947e75d95151aAntti Palosaari#include "rtl2830_priv.h"
29c0adca734013389ac81513da546947e75d95151aAntti Palosaari
3037ebaf6891ee81687bb558e8375c0712d8264ed8Mauro Carvalho Chehab/* Max transfer size done by I2C transfer functions */
3137ebaf6891ee81687bb558e8375c0712d8264ed8Mauro Carvalho Chehab#define MAX_XFER_SIZE  64
3237ebaf6891ee81687bb558e8375c0712d8264ed8Mauro Carvalho Chehab
330485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari/* write multiple hardware registers */
343a2fca2684bd8730a270197d231d8d023d759d3fAntti Palosaaristatic int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, const u8 *val, int len)
35c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
36c0adca734013389ac81513da546947e75d95151aAntti Palosaari	int ret;
3737ebaf6891ee81687bb558e8375c0712d8264ed8Mauro Carvalho Chehab	u8 buf[MAX_XFER_SIZE];
38c0adca734013389ac81513da546947e75d95151aAntti Palosaari	struct i2c_msg msg[1] = {
39c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{
40c0adca734013389ac81513da546947e75d95151aAntti Palosaari			.addr = priv->cfg.i2c_addr,
41c0adca734013389ac81513da546947e75d95151aAntti Palosaari			.flags = 0,
4237ebaf6891ee81687bb558e8375c0712d8264ed8Mauro Carvalho Chehab			.len = 1 + len,
43c0adca734013389ac81513da546947e75d95151aAntti Palosaari			.buf = buf,
44c0adca734013389ac81513da546947e75d95151aAntti Palosaari		}
45c0adca734013389ac81513da546947e75d95151aAntti Palosaari	};
46c0adca734013389ac81513da546947e75d95151aAntti Palosaari
4737ebaf6891ee81687bb558e8375c0712d8264ed8Mauro Carvalho Chehab	if (1 + len > sizeof(buf)) {
4837ebaf6891ee81687bb558e8375c0712d8264ed8Mauro Carvalho Chehab		dev_warn(&priv->i2c->dev,
4937ebaf6891ee81687bb558e8375c0712d8264ed8Mauro Carvalho Chehab			 "%s: i2c wr reg=%04x: len=%d is too big!\n",
5037ebaf6891ee81687bb558e8375c0712d8264ed8Mauro Carvalho Chehab			 KBUILD_MODNAME, reg, len);
5137ebaf6891ee81687bb558e8375c0712d8264ed8Mauro Carvalho Chehab		return -EINVAL;
5237ebaf6891ee81687bb558e8375c0712d8264ed8Mauro Carvalho Chehab	}
5337ebaf6891ee81687bb558e8375c0712d8264ed8Mauro Carvalho Chehab
540485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari	buf[0] = reg;
550485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari	memcpy(&buf[1], val, len);
56c0adca734013389ac81513da546947e75d95151aAntti Palosaari
57c0adca734013389ac81513da546947e75d95151aAntti Palosaari	ret = i2c_transfer(priv->i2c, msg, 1);
58c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (ret == 1) {
59c0adca734013389ac81513da546947e75d95151aAntti Palosaari		ret = 0;
60c0adca734013389ac81513da546947e75d95151aAntti Palosaari	} else {
6186ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari		dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
6286ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
63c0adca734013389ac81513da546947e75d95151aAntti Palosaari		ret = -EREMOTEIO;
64c0adca734013389ac81513da546947e75d95151aAntti Palosaari	}
65c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return ret;
66c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
67c0adca734013389ac81513da546947e75d95151aAntti Palosaari
680485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari/* read multiple hardware registers */
690485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaaristatic int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
70c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
71c0adca734013389ac81513da546947e75d95151aAntti Palosaari	int ret;
72c0adca734013389ac81513da546947e75d95151aAntti Palosaari	struct i2c_msg msg[2] = {
73c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{
74c0adca734013389ac81513da546947e75d95151aAntti Palosaari			.addr = priv->cfg.i2c_addr,
75c0adca734013389ac81513da546947e75d95151aAntti Palosaari			.flags = 0,
760485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari			.len = 1,
770485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari			.buf = &reg,
78c0adca734013389ac81513da546947e75d95151aAntti Palosaari		}, {
79c0adca734013389ac81513da546947e75d95151aAntti Palosaari			.addr = priv->cfg.i2c_addr,
80c0adca734013389ac81513da546947e75d95151aAntti Palosaari			.flags = I2C_M_RD,
81c0adca734013389ac81513da546947e75d95151aAntti Palosaari			.len = len,
82c0adca734013389ac81513da546947e75d95151aAntti Palosaari			.buf = val,
83c0adca734013389ac81513da546947e75d95151aAntti Palosaari		}
84c0adca734013389ac81513da546947e75d95151aAntti Palosaari	};
85c0adca734013389ac81513da546947e75d95151aAntti Palosaari
86c0adca734013389ac81513da546947e75d95151aAntti Palosaari	ret = i2c_transfer(priv->i2c, msg, 2);
87c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (ret == 2) {
88c0adca734013389ac81513da546947e75d95151aAntti Palosaari		ret = 0;
89c0adca734013389ac81513da546947e75d95151aAntti Palosaari	} else {
9086ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari		dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
9186ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
92c0adca734013389ac81513da546947e75d95151aAntti Palosaari		ret = -EREMOTEIO;
93c0adca734013389ac81513da546947e75d95151aAntti Palosaari	}
94c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return ret;
95c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
96c0adca734013389ac81513da546947e75d95151aAntti Palosaari
970485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari/* write multiple registers */
983a2fca2684bd8730a270197d231d8d023d759d3fAntti Palosaaristatic int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, const u8 *val,
993a2fca2684bd8730a270197d231d8d023d759d3fAntti Palosaari		int len)
1000485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari{
1010485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari	int ret;
1020485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari	u8 reg2 = (reg >> 0) & 0xff;
1030485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari	u8 page = (reg >> 8) & 0xff;
1040485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari
1050485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari	/* switch bank if needed */
1060485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari	if (page != priv->page) {
1070485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari		ret = rtl2830_wr(priv, 0x00, &page, 1);
1080485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari		if (ret)
1090485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari			return ret;
1100485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari
1110485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari		priv->page = page;
1120485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari	}
1130485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari
1140485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari	return rtl2830_wr(priv, reg2, val, len);
1150485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari}
1160485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari
1170485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari/* read multiple registers */
1180485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaaristatic int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
1190485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari{
1200485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari	int ret;
1210485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari	u8 reg2 = (reg >> 0) & 0xff;
1220485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari	u8 page = (reg >> 8) & 0xff;
1230485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari
1240485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari	/* switch bank if needed */
1250485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari	if (page != priv->page) {
1260485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari		ret = rtl2830_wr(priv, 0x00, &page, 1);
1270485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari		if (ret)
1280485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari			return ret;
1290485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari
1300485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari		priv->page = page;
1310485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari	}
1320485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari
1330485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari	return rtl2830_rd(priv, reg2, val, len);
1340485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari}
1350485a7089b8d6c11fe2db1123a1ed39a2676592fAntti Palosaari
136c0adca734013389ac81513da546947e75d95151aAntti Palosaari/* read single register */
137c0adca734013389ac81513da546947e75d95151aAntti Palosaaristatic int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val)
138c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
139c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return rtl2830_rd_regs(priv, reg, val, 1);
140c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
141c0adca734013389ac81513da546947e75d95151aAntti Palosaari
142c0adca734013389ac81513da546947e75d95151aAntti Palosaari/* write single register with mask */
143a17ff2eed6812eff319a4a74854db55298319bbeMauro Carvalho Chehabstatic int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask)
144c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
145c0adca734013389ac81513da546947e75d95151aAntti Palosaari	int ret;
146c0adca734013389ac81513da546947e75d95151aAntti Palosaari	u8 tmp;
147c0adca734013389ac81513da546947e75d95151aAntti Palosaari
148c0adca734013389ac81513da546947e75d95151aAntti Palosaari	/* no need for read if whole reg is written */
149c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (mask != 0xff) {
150c0adca734013389ac81513da546947e75d95151aAntti Palosaari		ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
151c0adca734013389ac81513da546947e75d95151aAntti Palosaari		if (ret)
152c0adca734013389ac81513da546947e75d95151aAntti Palosaari			return ret;
153c0adca734013389ac81513da546947e75d95151aAntti Palosaari
154c0adca734013389ac81513da546947e75d95151aAntti Palosaari		val &= mask;
155c0adca734013389ac81513da546947e75d95151aAntti Palosaari		tmp &= ~mask;
156c0adca734013389ac81513da546947e75d95151aAntti Palosaari		val |= tmp;
157c0adca734013389ac81513da546947e75d95151aAntti Palosaari	}
158c0adca734013389ac81513da546947e75d95151aAntti Palosaari
159c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return rtl2830_wr_regs(priv, reg, &val, 1);
160c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
161c0adca734013389ac81513da546947e75d95151aAntti Palosaari
162c0adca734013389ac81513da546947e75d95151aAntti Palosaari/* read single register with mask */
163a17ff2eed6812eff319a4a74854db55298319bbeMauro Carvalho Chehabstatic int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask)
164c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
165c0adca734013389ac81513da546947e75d95151aAntti Palosaari	int ret, i;
166c0adca734013389ac81513da546947e75d95151aAntti Palosaari	u8 tmp;
167c0adca734013389ac81513da546947e75d95151aAntti Palosaari
168c0adca734013389ac81513da546947e75d95151aAntti Palosaari	ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
169c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (ret)
170c0adca734013389ac81513da546947e75d95151aAntti Palosaari		return ret;
171c0adca734013389ac81513da546947e75d95151aAntti Palosaari
172c0adca734013389ac81513da546947e75d95151aAntti Palosaari	tmp &= mask;
173c0adca734013389ac81513da546947e75d95151aAntti Palosaari
174c0adca734013389ac81513da546947e75d95151aAntti Palosaari	/* find position of the first bit */
175c0adca734013389ac81513da546947e75d95151aAntti Palosaari	for (i = 0; i < 8; i++) {
176c0adca734013389ac81513da546947e75d95151aAntti Palosaari		if ((mask >> i) & 0x01)
177c0adca734013389ac81513da546947e75d95151aAntti Palosaari			break;
178c0adca734013389ac81513da546947e75d95151aAntti Palosaari	}
179c0adca734013389ac81513da546947e75d95151aAntti Palosaari	*val = tmp >> i;
180c0adca734013389ac81513da546947e75d95151aAntti Palosaari
181c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return 0;
182c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
183c0adca734013389ac81513da546947e75d95151aAntti Palosaari
184c0adca734013389ac81513da546947e75d95151aAntti Palosaaristatic int rtl2830_init(struct dvb_frontend *fe)
185c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
186c0adca734013389ac81513da546947e75d95151aAntti Palosaari	struct rtl2830_priv *priv = fe->demodulator_priv;
187c0adca734013389ac81513da546947e75d95151aAntti Palosaari	int ret, i;
188c0adca734013389ac81513da546947e75d95151aAntti Palosaari	struct rtl2830_reg_val_mask tab[] = {
189c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x00d, 0x01, 0x03 },
190c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x00d, 0x10, 0x10 },
191c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x104, 0x00, 0x1e },
192c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x105, 0x80, 0x80 },
193c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x110, 0x02, 0x03 },
194c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x110, 0x08, 0x0c },
195c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x17b, 0x00, 0x40 },
196c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x17d, 0x05, 0x0f },
197c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x17d, 0x50, 0xf0 },
198c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x18c, 0x08, 0x0f },
199c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x18d, 0x00, 0xc0 },
200c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x188, 0x05, 0x0f },
201c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x189, 0x00, 0xfc },
202c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x2d5, 0x02, 0x02 },
203c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x2f1, 0x02, 0x06 },
204c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x2f1, 0x20, 0xf8 },
205c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x16d, 0x00, 0x01 },
206c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x1a6, 0x00, 0x80 },
207c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x106, priv->cfg.vtop, 0x3f },
208c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x107, priv->cfg.krf, 0x3f },
209c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x112, 0x28, 0xff },
210c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x103, priv->cfg.agc_targ_val, 0xff },
211c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x00a, 0x02, 0x07 },
212c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x140, 0x0c, 0x3c },
213c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x140, 0x40, 0xc0 },
214c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x15b, 0x05, 0x07 },
215c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x15b, 0x28, 0x38 },
216c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x15c, 0x05, 0x07 },
217c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x15c, 0x28, 0x38 },
218c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x115, priv->cfg.spec_inv, 0x01 },
219c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x16f, 0x01, 0x07 },
220c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x170, 0x18, 0x38 },
221c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x172, 0x0f, 0x0f },
222c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x173, 0x08, 0x38 },
223c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x175, 0x01, 0x07 },
224c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{ 0x176, 0x00, 0xc0 },
225c0adca734013389ac81513da546947e75d95151aAntti Palosaari	};
226c0adca734013389ac81513da546947e75d95151aAntti Palosaari
227c0adca734013389ac81513da546947e75d95151aAntti Palosaari	for (i = 0; i < ARRAY_SIZE(tab); i++) {
228c0adca734013389ac81513da546947e75d95151aAntti Palosaari		ret = rtl2830_wr_reg_mask(priv, tab[i].reg, tab[i].val,
229c0adca734013389ac81513da546947e75d95151aAntti Palosaari			tab[i].mask);
230c0adca734013389ac81513da546947e75d95151aAntti Palosaari		if (ret)
231c0adca734013389ac81513da546947e75d95151aAntti Palosaari			goto err;
232c0adca734013389ac81513da546947e75d95151aAntti Palosaari	}
233c0adca734013389ac81513da546947e75d95151aAntti Palosaari
234c0adca734013389ac81513da546947e75d95151aAntti Palosaari	ret = rtl2830_wr_regs(priv, 0x18f, "\x28\x00", 2);
235c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (ret)
236c0adca734013389ac81513da546947e75d95151aAntti Palosaari		goto err;
237c0adca734013389ac81513da546947e75d95151aAntti Palosaari
238c0adca734013389ac81513da546947e75d95151aAntti Palosaari	ret = rtl2830_wr_regs(priv, 0x195,
239c0adca734013389ac81513da546947e75d95151aAntti Palosaari		"\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8);
240c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (ret)
241c0adca734013389ac81513da546947e75d95151aAntti Palosaari		goto err;
242c0adca734013389ac81513da546947e75d95151aAntti Palosaari
243c0adca734013389ac81513da546947e75d95151aAntti Palosaari	/* TODO: spec init */
244c0adca734013389ac81513da546947e75d95151aAntti Palosaari
245c0adca734013389ac81513da546947e75d95151aAntti Palosaari	/* soft reset */
246c0adca734013389ac81513da546947e75d95151aAntti Palosaari	ret = rtl2830_wr_reg_mask(priv, 0x101, 0x04, 0x04);
247c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (ret)
248c0adca734013389ac81513da546947e75d95151aAntti Palosaari		goto err;
249c0adca734013389ac81513da546947e75d95151aAntti Palosaari
250c0adca734013389ac81513da546947e75d95151aAntti Palosaari	ret = rtl2830_wr_reg_mask(priv, 0x101, 0x00, 0x04);
251c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (ret)
252c0adca734013389ac81513da546947e75d95151aAntti Palosaari		goto err;
253c0adca734013389ac81513da546947e75d95151aAntti Palosaari
254a8567cf22e0efb9faafa6cf33b607ca5aee3c2faAntti Palosaari	priv->sleeping = false;
255a8567cf22e0efb9faafa6cf33b607ca5aee3c2faAntti Palosaari
256c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return ret;
257c0adca734013389ac81513da546947e75d95151aAntti Palosaarierr:
25886ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
259c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return ret;
260c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
261c0adca734013389ac81513da546947e75d95151aAntti Palosaari
262a8567cf22e0efb9faafa6cf33b607ca5aee3c2faAntti Palosaaristatic int rtl2830_sleep(struct dvb_frontend *fe)
263a8567cf22e0efb9faafa6cf33b607ca5aee3c2faAntti Palosaari{
264a8567cf22e0efb9faafa6cf33b607ca5aee3c2faAntti Palosaari	struct rtl2830_priv *priv = fe->demodulator_priv;
265a8567cf22e0efb9faafa6cf33b607ca5aee3c2faAntti Palosaari	priv->sleeping = true;
266a8567cf22e0efb9faafa6cf33b607ca5aee3c2faAntti Palosaari	return 0;
267a8567cf22e0efb9faafa6cf33b607ca5aee3c2faAntti Palosaari}
268a8567cf22e0efb9faafa6cf33b607ca5aee3c2faAntti Palosaari
269a17ff2eed6812eff319a4a74854db55298319bbeMauro Carvalho Chehabstatic int rtl2830_get_tune_settings(struct dvb_frontend *fe,
270c0adca734013389ac81513da546947e75d95151aAntti Palosaari	struct dvb_frontend_tune_settings *s)
271c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
272c0adca734013389ac81513da546947e75d95151aAntti Palosaari	s->min_delay_ms = 500;
273c0adca734013389ac81513da546947e75d95151aAntti Palosaari	s->step_size = fe->ops.info.frequency_stepsize * 2;
274c0adca734013389ac81513da546947e75d95151aAntti Palosaari	s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
275c0adca734013389ac81513da546947e75d95151aAntti Palosaari
276c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return 0;
277c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
278c0adca734013389ac81513da546947e75d95151aAntti Palosaari
279c0adca734013389ac81513da546947e75d95151aAntti Palosaaristatic int rtl2830_set_frontend(struct dvb_frontend *fe)
280c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
281c0adca734013389ac81513da546947e75d95151aAntti Palosaari	struct rtl2830_priv *priv = fe->demodulator_priv;
282c0adca734013389ac81513da546947e75d95151aAntti Palosaari	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
283c0adca734013389ac81513da546947e75d95151aAntti Palosaari	int ret, i;
28466b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	u64 num;
28566b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	u8 buf[3], tmp;
28666b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	u32 if_ctl, if_frequency;
2873a2fca2684bd8730a270197d231d8d023d759d3fAntti Palosaari	static const u8 bw_params1[3][34] = {
288c0adca734013389ac81513da546947e75d95151aAntti Palosaari		{
289c0adca734013389ac81513da546947e75d95151aAntti Palosaari		0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41,
290c0adca734013389ac81513da546947e75d95151aAntti Palosaari		0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a,
291c0adca734013389ac81513da546947e75d95151aAntti Palosaari		0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82,
292c0adca734013389ac81513da546947e75d95151aAntti Palosaari		0x03, 0x73, 0x03, 0xcf, /* 6 MHz */
293c0adca734013389ac81513da546947e75d95151aAntti Palosaari		}, {
294c0adca734013389ac81513da546947e75d95151aAntti Palosaari		0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca,
295c0adca734013389ac81513da546947e75d95151aAntti Palosaari		0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca,
296c0adca734013389ac81513da546947e75d95151aAntti Palosaari		0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e,
297c0adca734013389ac81513da546947e75d95151aAntti Palosaari		0x03, 0xd0, 0x04, 0x53, /* 7 MHz */
298c0adca734013389ac81513da546947e75d95151aAntti Palosaari		}, {
299c0adca734013389ac81513da546947e75d95151aAntti Palosaari		0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0,
300c0adca734013389ac81513da546947e75d95151aAntti Palosaari		0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a,
301c0adca734013389ac81513da546947e75d95151aAntti Palosaari		0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f,
302c0adca734013389ac81513da546947e75d95151aAntti Palosaari		0x04, 0x24, 0x04, 0xdb, /* 8 MHz */
303c0adca734013389ac81513da546947e75d95151aAntti Palosaari		},
304c0adca734013389ac81513da546947e75d95151aAntti Palosaari	};
3053a2fca2684bd8730a270197d231d8d023d759d3fAntti Palosaari	static const u8 bw_params2[3][6] = {
3063a2fca2684bd8730a270197d231d8d023d759d3fAntti Palosaari		{0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30}, /* 6 MHz */
3073a2fca2684bd8730a270197d231d8d023d759d3fAntti Palosaari		{0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98}, /* 7 MHz */
3083a2fca2684bd8730a270197d231d8d023d759d3fAntti Palosaari		{0xae, 0xba, 0xf3, 0x26, 0x66, 0x64}, /* 8 MHz */
309c0adca734013389ac81513da546947e75d95151aAntti Palosaari	};
310c0adca734013389ac81513da546947e75d95151aAntti Palosaari
31186ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari	dev_dbg(&priv->i2c->dev,
31286ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari			"%s: frequency=%d bandwidth_hz=%d inversion=%d\n",
31386ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari			__func__, c->frequency, c->bandwidth_hz, c->inversion);
314c0adca734013389ac81513da546947e75d95151aAntti Palosaari
315c0adca734013389ac81513da546947e75d95151aAntti Palosaari	/* program tuner */
316c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (fe->ops.tuner_ops.set_params)
317c0adca734013389ac81513da546947e75d95151aAntti Palosaari		fe->ops.tuner_ops.set_params(fe);
318c0adca734013389ac81513da546947e75d95151aAntti Palosaari
319c0adca734013389ac81513da546947e75d95151aAntti Palosaari	switch (c->bandwidth_hz) {
320c0adca734013389ac81513da546947e75d95151aAntti Palosaari	case 6000000:
321c0adca734013389ac81513da546947e75d95151aAntti Palosaari		i = 0;
322c0adca734013389ac81513da546947e75d95151aAntti Palosaari		break;
323c0adca734013389ac81513da546947e75d95151aAntti Palosaari	case 7000000:
324c0adca734013389ac81513da546947e75d95151aAntti Palosaari		i = 1;
325c0adca734013389ac81513da546947e75d95151aAntti Palosaari		break;
326c0adca734013389ac81513da546947e75d95151aAntti Palosaari	case 8000000:
327c0adca734013389ac81513da546947e75d95151aAntti Palosaari		i = 2;
328c0adca734013389ac81513da546947e75d95151aAntti Palosaari		break;
329c0adca734013389ac81513da546947e75d95151aAntti Palosaari	default:
33086ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari		dev_dbg(&priv->i2c->dev, "%s: invalid bandwidth\n", __func__);
331c0adca734013389ac81513da546947e75d95151aAntti Palosaari		return -EINVAL;
332c0adca734013389ac81513da546947e75d95151aAntti Palosaari	}
333c0adca734013389ac81513da546947e75d95151aAntti Palosaari
334c0adca734013389ac81513da546947e75d95151aAntti Palosaari	ret = rtl2830_wr_reg_mask(priv, 0x008, i << 1, 0x06);
335c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (ret)
336c0adca734013389ac81513da546947e75d95151aAntti Palosaari		goto err;
337c0adca734013389ac81513da546947e75d95151aAntti Palosaari
33866b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	/* program if frequency */
33966b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	if (fe->ops.tuner_ops.get_if_frequency)
34066b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
34166b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	else
34266b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari		ret = -EINVAL;
34366b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari
34466b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	if (ret < 0)
34566b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari		goto err;
34666b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari
34766b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	num = if_frequency % priv->cfg.xtal;
34866b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	num *= 0x400000;
34966b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	num = div_u64(num, priv->cfg.xtal);
35066b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	num = -num;
35166b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	if_ctl = num & 0x3fffff;
35266b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d if_ctl=%08x\n",
35366b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari			__func__, if_frequency, if_ctl);
35466b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari
35566b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */
35666b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	if (ret)
35766b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari		goto err;
35866b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari
35966b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	buf[0] = tmp << 6;
36066b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	buf[0] |= (if_ctl >> 16) & 0x3f;
36166b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	buf[1] = (if_ctl >>  8) & 0xff;
36266b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	buf[2] = (if_ctl >>  0) & 0xff;
36366b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari
36466b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	ret = rtl2830_wr_regs(priv, 0x119, buf, 3);
36566b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari	if (ret)
36666b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari		goto err;
36766b3c4deb9735e18d5b71dbcbf9532bdf080d001Antti Palosaari
368c0adca734013389ac81513da546947e75d95151aAntti Palosaari	/* 1/2 split I2C write */
369c0adca734013389ac81513da546947e75d95151aAntti Palosaari	ret = rtl2830_wr_regs(priv, 0x11c, &bw_params1[i][0], 17);
370c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (ret)
371c0adca734013389ac81513da546947e75d95151aAntti Palosaari		goto err;
372c0adca734013389ac81513da546947e75d95151aAntti Palosaari
373c0adca734013389ac81513da546947e75d95151aAntti Palosaari	/* 2/2 split I2C write */
374c0adca734013389ac81513da546947e75d95151aAntti Palosaari	ret = rtl2830_wr_regs(priv, 0x12d, &bw_params1[i][17], 17);
375c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (ret)
376c0adca734013389ac81513da546947e75d95151aAntti Palosaari		goto err;
377c0adca734013389ac81513da546947e75d95151aAntti Palosaari
378c0adca734013389ac81513da546947e75d95151aAntti Palosaari	ret = rtl2830_wr_regs(priv, 0x19d, bw_params2[i], 6);
379c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (ret)
380c0adca734013389ac81513da546947e75d95151aAntti Palosaari		goto err;
381c0adca734013389ac81513da546947e75d95151aAntti Palosaari
382c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return ret;
383c0adca734013389ac81513da546947e75d95151aAntti Palosaarierr:
38486ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
385c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return ret;
386c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
387c0adca734013389ac81513da546947e75d95151aAntti Palosaari
388631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaaristatic int rtl2830_get_frontend(struct dvb_frontend *fe)
389631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari{
390631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	struct rtl2830_priv *priv = fe->demodulator_priv;
391631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
392631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	int ret;
393631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	u8 buf[3];
394631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari
395c188637dc5a25aec6a21279524405c8fe96f2f4bAntti Palosaari	if (priv->sleeping)
396c188637dc5a25aec6a21279524405c8fe96f2f4bAntti Palosaari		return 0;
397c188637dc5a25aec6a21279524405c8fe96f2f4bAntti Palosaari
398631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	ret = rtl2830_rd_regs(priv, 0x33c, buf, 2);
399631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	if (ret)
400631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		goto err;
401631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari
402631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	ret = rtl2830_rd_reg(priv, 0x351, &buf[2]);
403631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	if (ret)
404631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		goto err;
405631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari
40686ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari	dev_dbg(&priv->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf);
407631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari
408631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	switch ((buf[0] >> 2) & 3) {
409631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 0:
410631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->modulation = QPSK;
411631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
412631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 1:
413631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->modulation = QAM_16;
414631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
415631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 2:
416631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->modulation = QAM_64;
417631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
418631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	}
419631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari
420631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	switch ((buf[2] >> 2) & 1) {
421631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 0:
422631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->transmission_mode = TRANSMISSION_MODE_2K;
423631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
424631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 1:
425631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->transmission_mode = TRANSMISSION_MODE_8K;
426631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	}
427631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari
428631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	switch ((buf[2] >> 0) & 3) {
429631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 0:
430631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->guard_interval = GUARD_INTERVAL_1_32;
431631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
432631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 1:
433631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->guard_interval = GUARD_INTERVAL_1_16;
434631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
435631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 2:
436631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->guard_interval = GUARD_INTERVAL_1_8;
437631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
438631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 3:
439631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->guard_interval = GUARD_INTERVAL_1_4;
440631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
441631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	}
442631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari
443631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	switch ((buf[0] >> 4) & 7) {
444631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 0:
445631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->hierarchy = HIERARCHY_NONE;
446631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
447631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 1:
448631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->hierarchy = HIERARCHY_1;
449631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
450631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 2:
451631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->hierarchy = HIERARCHY_2;
452631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
453631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 3:
454631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->hierarchy = HIERARCHY_4;
455631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
456631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	}
457631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari
458631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	switch ((buf[1] >> 3) & 7) {
459631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 0:
460631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->code_rate_HP = FEC_1_2;
461631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
462631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 1:
463631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->code_rate_HP = FEC_2_3;
464631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
465631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 2:
466631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->code_rate_HP = FEC_3_4;
467631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
468631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 3:
469631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->code_rate_HP = FEC_5_6;
470631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
471631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 4:
472631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->code_rate_HP = FEC_7_8;
473631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
474631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	}
475631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari
476631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	switch ((buf[1] >> 0) & 7) {
477631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 0:
478631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->code_rate_LP = FEC_1_2;
479631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
480631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 1:
481631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->code_rate_LP = FEC_2_3;
482631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
483631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 2:
484631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->code_rate_LP = FEC_3_4;
485631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
486631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 3:
487631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->code_rate_LP = FEC_5_6;
488631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
489631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	case 4:
490631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		c->code_rate_LP = FEC_7_8;
491631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari		break;
492631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	}
493631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari
494631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	return 0;
495631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaarierr:
49686ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
497631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	return ret;
498631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari}
499631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari
500c0adca734013389ac81513da546947e75d95151aAntti Palosaaristatic int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status)
501c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
502c0adca734013389ac81513da546947e75d95151aAntti Palosaari	struct rtl2830_priv *priv = fe->demodulator_priv;
503c0adca734013389ac81513da546947e75d95151aAntti Palosaari	int ret;
504c0adca734013389ac81513da546947e75d95151aAntti Palosaari	u8 tmp;
505c0adca734013389ac81513da546947e75d95151aAntti Palosaari	*status = 0;
506c0adca734013389ac81513da546947e75d95151aAntti Palosaari
507a8567cf22e0efb9faafa6cf33b607ca5aee3c2faAntti Palosaari	if (priv->sleeping)
508a8567cf22e0efb9faafa6cf33b607ca5aee3c2faAntti Palosaari		return 0;
509a8567cf22e0efb9faafa6cf33b607ca5aee3c2faAntti Palosaari
510c0adca734013389ac81513da546947e75d95151aAntti Palosaari	ret = rtl2830_rd_reg_mask(priv, 0x351, &tmp, 0x78); /* [6:3] */
511c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (ret)
512c0adca734013389ac81513da546947e75d95151aAntti Palosaari		goto err;
513c0adca734013389ac81513da546947e75d95151aAntti Palosaari
514c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (tmp == 11) {
515c0adca734013389ac81513da546947e75d95151aAntti Palosaari		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
516c0adca734013389ac81513da546947e75d95151aAntti Palosaari			FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
517c0adca734013389ac81513da546947e75d95151aAntti Palosaari	} else if (tmp == 10) {
518c0adca734013389ac81513da546947e75d95151aAntti Palosaari		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
519c0adca734013389ac81513da546947e75d95151aAntti Palosaari			FE_HAS_VITERBI;
520c0adca734013389ac81513da546947e75d95151aAntti Palosaari	}
521c0adca734013389ac81513da546947e75d95151aAntti Palosaari
522c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return ret;
523c0adca734013389ac81513da546947e75d95151aAntti Palosaarierr:
52486ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
525c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return ret;
526c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
527c0adca734013389ac81513da546947e75d95151aAntti Palosaari
528c0adca734013389ac81513da546947e75d95151aAntti Palosaaristatic int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
529c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
530eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	struct rtl2830_priv *priv = fe->demodulator_priv;
531eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	int ret, hierarchy, constellation;
532eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	u8 buf[2], tmp;
533eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	u16 tmp16;
534eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari#define CONSTELLATION_NUM 3
535eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari#define HIERARCHY_NUM 4
536eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
537eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari		{ 70705899, 70705899, 70705899, 70705899 },
538eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari		{ 82433173, 82433173, 87483115, 94445660 },
539eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari		{ 92888734, 92888734, 95487525, 99770748 },
540eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	};
541eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari
542c188637dc5a25aec6a21279524405c8fe96f2f4bAntti Palosaari	if (priv->sleeping)
543c188637dc5a25aec6a21279524405c8fe96f2f4bAntti Palosaari		return 0;
544c188637dc5a25aec6a21279524405c8fe96f2f4bAntti Palosaari
545eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	/* reports SNR in resolution of 0.1 dB */
546eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari
547eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	ret = rtl2830_rd_reg(priv, 0x33c, &tmp);
548eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	if (ret)
549eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari		goto err;
550eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari
551eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	constellation = (tmp >> 2) & 0x03; /* [3:2] */
552eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	if (constellation > CONSTELLATION_NUM - 1)
553eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari		goto err;
554eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari
555eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	hierarchy = (tmp >> 4) & 0x07; /* [6:4] */
556eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	if (hierarchy > HIERARCHY_NUM - 1)
557eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari		goto err;
558eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari
559eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	ret = rtl2830_rd_regs(priv, 0x40c, buf, 2);
560eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	if (ret)
561eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari		goto err;
562eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari
563eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	tmp16 = buf[0] << 8 | buf[1];
564eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari
565eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	if (tmp16)
566eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari		*snr = (snr_constant[constellation][hierarchy] -
567eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari				intlog10(tmp16)) / ((1 << 24) / 100);
568eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	else
569eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari		*snr = 0;
570eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari
571c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return 0;
572eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaarierr:
57386ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
574eba672a045d8fbf62b229eac74ef444b6000c4c2Antti Palosaari	return ret;
575c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
576c0adca734013389ac81513da546947e75d95151aAntti Palosaari
577c0adca734013389ac81513da546947e75d95151aAntti Palosaaristatic int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
578c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
579525ffc19b992f5d6a25413c36ba543a82585ed89Antti Palosaari	struct rtl2830_priv *priv = fe->demodulator_priv;
580525ffc19b992f5d6a25413c36ba543a82585ed89Antti Palosaari	int ret;
581525ffc19b992f5d6a25413c36ba543a82585ed89Antti Palosaari	u8 buf[2];
582525ffc19b992f5d6a25413c36ba543a82585ed89Antti Palosaari
583c188637dc5a25aec6a21279524405c8fe96f2f4bAntti Palosaari	if (priv->sleeping)
584c188637dc5a25aec6a21279524405c8fe96f2f4bAntti Palosaari		return 0;
585c188637dc5a25aec6a21279524405c8fe96f2f4bAntti Palosaari
586525ffc19b992f5d6a25413c36ba543a82585ed89Antti Palosaari	ret = rtl2830_rd_regs(priv, 0x34e, buf, 2);
587525ffc19b992f5d6a25413c36ba543a82585ed89Antti Palosaari	if (ret)
588525ffc19b992f5d6a25413c36ba543a82585ed89Antti Palosaari		goto err;
589525ffc19b992f5d6a25413c36ba543a82585ed89Antti Palosaari
590525ffc19b992f5d6a25413c36ba543a82585ed89Antti Palosaari	*ber = buf[0] << 8 | buf[1];
591525ffc19b992f5d6a25413c36ba543a82585ed89Antti Palosaari
592c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return 0;
593525ffc19b992f5d6a25413c36ba543a82585ed89Antti Palosaarierr:
59486ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
595525ffc19b992f5d6a25413c36ba543a82585ed89Antti Palosaari	return ret;
596c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
597c0adca734013389ac81513da546947e75d95151aAntti Palosaari
598c0adca734013389ac81513da546947e75d95151aAntti Palosaaristatic int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
599c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
600c0adca734013389ac81513da546947e75d95151aAntti Palosaari	*ucblocks = 0;
601c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return 0;
602c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
603c0adca734013389ac81513da546947e75d95151aAntti Palosaari
604c0adca734013389ac81513da546947e75d95151aAntti Palosaaristatic int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
605c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
60678e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari	struct rtl2830_priv *priv = fe->demodulator_priv;
60778e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari	int ret;
60878e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari	u8 buf[2];
60978e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari	u16 if_agc_raw, if_agc;
61078e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari
611c188637dc5a25aec6a21279524405c8fe96f2f4bAntti Palosaari	if (priv->sleeping)
612c188637dc5a25aec6a21279524405c8fe96f2f4bAntti Palosaari		return 0;
613c188637dc5a25aec6a21279524405c8fe96f2f4bAntti Palosaari
61478e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari	ret = rtl2830_rd_regs(priv, 0x359, buf, 2);
61578e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari	if (ret)
61678e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari		goto err;
61778e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari
61878e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari	if_agc_raw = (buf[0] << 8 | buf[1]) & 0x3fff;
61978e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari
62078e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari	if (if_agc_raw & (1 << 9))
62178e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari		if_agc = -(~(if_agc_raw - 1) & 0x1ff);
62278e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari	else
62378e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari		if_agc = if_agc_raw;
62478e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari
62578e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari	*strength = (u8) (55 - if_agc / 182);
62678e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari	*strength |= *strength << 8;
62778e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari
628c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return 0;
62978e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaarierr:
63086ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
63178e750754bf0cc86d36149536bc7f3382710a2eeAntti Palosaari	return ret;
632c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
633c0adca734013389ac81513da546947e75d95151aAntti Palosaari
634c0adca734013389ac81513da546947e75d95151aAntti Palosaaristatic struct dvb_frontend_ops rtl2830_ops;
635c0adca734013389ac81513da546947e75d95151aAntti Palosaari
636c0adca734013389ac81513da546947e75d95151aAntti Palosaaristatic u32 rtl2830_tuner_i2c_func(struct i2c_adapter *adapter)
637c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
638c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return I2C_FUNC_I2C;
639c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
640c0adca734013389ac81513da546947e75d95151aAntti Palosaari
641c0adca734013389ac81513da546947e75d95151aAntti Palosaaristatic int rtl2830_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
642c0adca734013389ac81513da546947e75d95151aAntti Palosaari	struct i2c_msg msg[], int num)
643c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
644c0adca734013389ac81513da546947e75d95151aAntti Palosaari	struct rtl2830_priv *priv = i2c_get_adapdata(i2c_adap);
645c0adca734013389ac81513da546947e75d95151aAntti Palosaari	int ret;
646c0adca734013389ac81513da546947e75d95151aAntti Palosaari
647c0adca734013389ac81513da546947e75d95151aAntti Palosaari	/* open i2c-gate */
648c0adca734013389ac81513da546947e75d95151aAntti Palosaari	ret = rtl2830_wr_reg_mask(priv, 0x101, 0x08, 0x08);
649c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (ret)
650c0adca734013389ac81513da546947e75d95151aAntti Palosaari		goto err;
651c0adca734013389ac81513da546947e75d95151aAntti Palosaari
652c0adca734013389ac81513da546947e75d95151aAntti Palosaari	ret = i2c_transfer(priv->i2c, msg, num);
653c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (ret < 0)
65486ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari		dev_warn(&priv->i2c->dev, "%s: tuner i2c failed=%d\n",
65586ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari			KBUILD_MODNAME, ret);
656c0adca734013389ac81513da546947e75d95151aAntti Palosaari
657c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return ret;
658c0adca734013389ac81513da546947e75d95151aAntti Palosaarierr:
65986ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
660c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return ret;
661c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
662c0adca734013389ac81513da546947e75d95151aAntti Palosaari
663c0adca734013389ac81513da546947e75d95151aAntti Palosaaristatic struct i2c_algorithm rtl2830_tuner_i2c_algo = {
664c0adca734013389ac81513da546947e75d95151aAntti Palosaari	.master_xfer   = rtl2830_tuner_i2c_xfer,
665c0adca734013389ac81513da546947e75d95151aAntti Palosaari	.functionality = rtl2830_tuner_i2c_func,
666c0adca734013389ac81513da546947e75d95151aAntti Palosaari};
667c0adca734013389ac81513da546947e75d95151aAntti Palosaari
668c0adca734013389ac81513da546947e75d95151aAntti Palosaaristruct i2c_adapter *rtl2830_get_tuner_i2c_adapter(struct dvb_frontend *fe)
669c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
670c0adca734013389ac81513da546947e75d95151aAntti Palosaari	struct rtl2830_priv *priv = fe->demodulator_priv;
671c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return &priv->tuner_i2c_adapter;
672c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
673c0adca734013389ac81513da546947e75d95151aAntti PalosaariEXPORT_SYMBOL(rtl2830_get_tuner_i2c_adapter);
674c0adca734013389ac81513da546947e75d95151aAntti Palosaari
675c0adca734013389ac81513da546947e75d95151aAntti Palosaaristatic void rtl2830_release(struct dvb_frontend *fe)
676c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
677c0adca734013389ac81513da546947e75d95151aAntti Palosaari	struct rtl2830_priv *priv = fe->demodulator_priv;
678c0adca734013389ac81513da546947e75d95151aAntti Palosaari
679c0adca734013389ac81513da546947e75d95151aAntti Palosaari	i2c_del_adapter(&priv->tuner_i2c_adapter);
680c0adca734013389ac81513da546947e75d95151aAntti Palosaari	kfree(priv);
681c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
682c0adca734013389ac81513da546947e75d95151aAntti Palosaari
683c0adca734013389ac81513da546947e75d95151aAntti Palosaaristruct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg,
684c0adca734013389ac81513da546947e75d95151aAntti Palosaari	struct i2c_adapter *i2c)
685c0adca734013389ac81513da546947e75d95151aAntti Palosaari{
686c0adca734013389ac81513da546947e75d95151aAntti Palosaari	struct rtl2830_priv *priv = NULL;
687c0adca734013389ac81513da546947e75d95151aAntti Palosaari	int ret = 0;
688c0adca734013389ac81513da546947e75d95151aAntti Palosaari	u8 tmp;
689c0adca734013389ac81513da546947e75d95151aAntti Palosaari
690c0adca734013389ac81513da546947e75d95151aAntti Palosaari	/* allocate memory for the internal state */
691c0adca734013389ac81513da546947e75d95151aAntti Palosaari	priv = kzalloc(sizeof(struct rtl2830_priv), GFP_KERNEL);
692c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (priv == NULL)
693c0adca734013389ac81513da546947e75d95151aAntti Palosaari		goto err;
694c0adca734013389ac81513da546947e75d95151aAntti Palosaari
695c0adca734013389ac81513da546947e75d95151aAntti Palosaari	/* setup the priv */
696c0adca734013389ac81513da546947e75d95151aAntti Palosaari	priv->i2c = i2c;
697c0adca734013389ac81513da546947e75d95151aAntti Palosaari	memcpy(&priv->cfg, cfg, sizeof(struct rtl2830_config));
698c0adca734013389ac81513da546947e75d95151aAntti Palosaari
699c0adca734013389ac81513da546947e75d95151aAntti Palosaari	/* check if the demod is there */
700c0adca734013389ac81513da546947e75d95151aAntti Palosaari	ret = rtl2830_rd_reg(priv, 0x000, &tmp);
701c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (ret)
702c0adca734013389ac81513da546947e75d95151aAntti Palosaari		goto err;
703c0adca734013389ac81513da546947e75d95151aAntti Palosaari
704c0adca734013389ac81513da546947e75d95151aAntti Palosaari	/* create dvb_frontend */
705c0adca734013389ac81513da546947e75d95151aAntti Palosaari	memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(struct dvb_frontend_ops));
706c0adca734013389ac81513da546947e75d95151aAntti Palosaari	priv->fe.demodulator_priv = priv;
707c0adca734013389ac81513da546947e75d95151aAntti Palosaari
708c0adca734013389ac81513da546947e75d95151aAntti Palosaari	/* create tuner i2c adapter */
709c0adca734013389ac81513da546947e75d95151aAntti Palosaari	strlcpy(priv->tuner_i2c_adapter.name, "RTL2830 tuner I2C adapter",
710c0adca734013389ac81513da546947e75d95151aAntti Palosaari		sizeof(priv->tuner_i2c_adapter.name));
711c0adca734013389ac81513da546947e75d95151aAntti Palosaari	priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo;
712c0adca734013389ac81513da546947e75d95151aAntti Palosaari	priv->tuner_i2c_adapter.algo_data = NULL;
713eed5b0cfb4f1ac0715106b79b24f19fad6000416Antti Palosaari	priv->tuner_i2c_adapter.dev.parent = &i2c->dev;
714c0adca734013389ac81513da546947e75d95151aAntti Palosaari	i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
715c0adca734013389ac81513da546947e75d95151aAntti Palosaari	if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
71686ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari		dev_err(&i2c->dev,
71786ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari				"%s: tuner i2c bus could not be initialized\n",
71886ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari				KBUILD_MODNAME);
719c0adca734013389ac81513da546947e75d95151aAntti Palosaari		goto err;
720c0adca734013389ac81513da546947e75d95151aAntti Palosaari	}
721c0adca734013389ac81513da546947e75d95151aAntti Palosaari
722a8567cf22e0efb9faafa6cf33b607ca5aee3c2faAntti Palosaari	priv->sleeping = true;
723a8567cf22e0efb9faafa6cf33b607ca5aee3c2faAntti Palosaari
724c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return &priv->fe;
725c0adca734013389ac81513da546947e75d95151aAntti Palosaarierr:
72686ad0f1dd72b39159065fdf089afe0913b9bef41Antti Palosaari	dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
727c0adca734013389ac81513da546947e75d95151aAntti Palosaari	kfree(priv);
728c0adca734013389ac81513da546947e75d95151aAntti Palosaari	return NULL;
729c0adca734013389ac81513da546947e75d95151aAntti Palosaari}
730c0adca734013389ac81513da546947e75d95151aAntti PalosaariEXPORT_SYMBOL(rtl2830_attach);
731c0adca734013389ac81513da546947e75d95151aAntti Palosaari
732c0adca734013389ac81513da546947e75d95151aAntti Palosaaristatic struct dvb_frontend_ops rtl2830_ops = {
733c0adca734013389ac81513da546947e75d95151aAntti Palosaari	.delsys = { SYS_DVBT },
734c0adca734013389ac81513da546947e75d95151aAntti Palosaari	.info = {
735c0adca734013389ac81513da546947e75d95151aAntti Palosaari		.name = "Realtek RTL2830 (DVB-T)",
736c0adca734013389ac81513da546947e75d95151aAntti Palosaari		.caps = FE_CAN_FEC_1_2 |
737c0adca734013389ac81513da546947e75d95151aAntti Palosaari			FE_CAN_FEC_2_3 |
738c0adca734013389ac81513da546947e75d95151aAntti Palosaari			FE_CAN_FEC_3_4 |
739c0adca734013389ac81513da546947e75d95151aAntti Palosaari			FE_CAN_FEC_5_6 |
740c0adca734013389ac81513da546947e75d95151aAntti Palosaari			FE_CAN_FEC_7_8 |
741c0adca734013389ac81513da546947e75d95151aAntti Palosaari			FE_CAN_FEC_AUTO |
742c0adca734013389ac81513da546947e75d95151aAntti Palosaari			FE_CAN_QPSK |
743c0adca734013389ac81513da546947e75d95151aAntti Palosaari			FE_CAN_QAM_16 |
744c0adca734013389ac81513da546947e75d95151aAntti Palosaari			FE_CAN_QAM_64 |
745c0adca734013389ac81513da546947e75d95151aAntti Palosaari			FE_CAN_QAM_AUTO |
746c0adca734013389ac81513da546947e75d95151aAntti Palosaari			FE_CAN_TRANSMISSION_MODE_AUTO |
747c0adca734013389ac81513da546947e75d95151aAntti Palosaari			FE_CAN_GUARD_INTERVAL_AUTO |
748c0adca734013389ac81513da546947e75d95151aAntti Palosaari			FE_CAN_HIERARCHY_AUTO |
749c0adca734013389ac81513da546947e75d95151aAntti Palosaari			FE_CAN_RECOVER |
750c0adca734013389ac81513da546947e75d95151aAntti Palosaari			FE_CAN_MUTE_TS
751c0adca734013389ac81513da546947e75d95151aAntti Palosaari	},
752c0adca734013389ac81513da546947e75d95151aAntti Palosaari
753c0adca734013389ac81513da546947e75d95151aAntti Palosaari	.release = rtl2830_release,
754c0adca734013389ac81513da546947e75d95151aAntti Palosaari
755c0adca734013389ac81513da546947e75d95151aAntti Palosaari	.init = rtl2830_init,
756a8567cf22e0efb9faafa6cf33b607ca5aee3c2faAntti Palosaari	.sleep = rtl2830_sleep,
757c0adca734013389ac81513da546947e75d95151aAntti Palosaari
758c0adca734013389ac81513da546947e75d95151aAntti Palosaari	.get_tune_settings = rtl2830_get_tune_settings,
759c0adca734013389ac81513da546947e75d95151aAntti Palosaari
760c0adca734013389ac81513da546947e75d95151aAntti Palosaari	.set_frontend = rtl2830_set_frontend,
761631a2b611288f87de4ef1098d1fb4bc4d246b103Antti Palosaari	.get_frontend = rtl2830_get_frontend,
762c0adca734013389ac81513da546947e75d95151aAntti Palosaari
763c0adca734013389ac81513da546947e75d95151aAntti Palosaari	.read_status = rtl2830_read_status,
764c0adca734013389ac81513da546947e75d95151aAntti Palosaari	.read_snr = rtl2830_read_snr,
765c0adca734013389ac81513da546947e75d95151aAntti Palosaari	.read_ber = rtl2830_read_ber,
766c0adca734013389ac81513da546947e75d95151aAntti Palosaari	.read_ucblocks = rtl2830_read_ucblocks,
767c0adca734013389ac81513da546947e75d95151aAntti Palosaari	.read_signal_strength = rtl2830_read_signal_strength,
768c0adca734013389ac81513da546947e75d95151aAntti Palosaari};
769c0adca734013389ac81513da546947e75d95151aAntti Palosaari
770c0adca734013389ac81513da546947e75d95151aAntti PalosaariMODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
771c0adca734013389ac81513da546947e75d95151aAntti PalosaariMODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver");
772c0adca734013389ac81513da546947e75d95151aAntti PalosaariMODULE_LICENSE("GPL");
773