blob: 77dcfdf547ac8f62e4cc2ea5a8fa086478e545b5 [file] [log] [blame]
Antti Palosaari831e0b72011-07-08 23:36:07 -03001/*
2 * Realtek RTL28xxU DVB USB driver
3 *
4 * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
5 * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
Thomas Mair5cf66312012-05-18 14:47:41 -03006 * Copyright (C) 2012 Thomas Mair <thomas.mair86@googlemail.com>
Antti Palosaari831e0b72011-07-08 23:36:07 -03007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23#include "rtl28xxu.h"
24
Antti Palosaari94b5fa62013-11-22 14:20:14 -030025static int rtl28xxu_disable_rc;
26module_param_named(disable_rc, rtl28xxu_disable_rc, int, 0644);
27MODULE_PARM_DESC(disable_rc, "disable RTL2832U remote controller");
Antti Palosaari831e0b72011-07-08 23:36:07 -030028DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
29
30static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
31{
Antti Palosaaric56222a2014-12-21 18:33:14 -030032 struct rtl28xxu_dev *dev = d->priv;
Antti Palosaari831e0b72011-07-08 23:36:07 -030033 int ret;
34 unsigned int pipe;
35 u8 requesttype;
Antti Palosaari831e0b72011-07-08 23:36:07 -030036
37 if (req->index & CMD_WR_FLAG) {
38 /* write */
Antti Palosaaric56222a2014-12-21 18:33:14 -030039 memcpy(dev->buf, req->data, req->size);
Antti Palosaari831e0b72011-07-08 23:36:07 -030040 requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
41 pipe = usb_sndctrlpipe(d->udev, 0);
42 } else {
43 /* read */
44 requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
45 pipe = usb_rcvctrlpipe(d->udev, 0);
46 }
47
48 ret = usb_control_msg(d->udev, pipe, 0, requesttype, req->value,
Antti Palosaaric56222a2014-12-21 18:33:14 -030049 req->index, dev->buf, req->size, 1000);
Antti Palosaarid89b9362012-08-22 19:42:00 -030050 dvb_usb_dbg_usb_control_msg(d->udev, 0, requesttype, req->value,
Antti Palosaaric56222a2014-12-21 18:33:14 -030051 req->index, dev->buf, req->size);
52 if (ret < 0)
Antti Palosaari9935eea2012-01-21 22:26:52 -030053 goto err;
54
Antti Palosaaric56222a2014-12-21 18:33:14 -030055 /* read request, copy returned data to return buf */
56 if (requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
57 memcpy(req->data, dev->buf, req->size);
58
59 return 0;
Antti Palosaari831e0b72011-07-08 23:36:07 -030060err:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -030061 dev_dbg(&d->intf->dev, "failed=%d\n", ret);
Antti Palosaari831e0b72011-07-08 23:36:07 -030062 return ret;
63}
64
Antti Palosaari670ef052014-12-23 14:32:35 -030065static int rtl28xxu_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
Antti Palosaari831e0b72011-07-08 23:36:07 -030066{
67 struct rtl28xxu_req req;
68
69 if (reg < 0x3000)
70 req.index = CMD_USB_WR;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -030071 else if (reg < 0x4000)
Antti Palosaari831e0b72011-07-08 23:36:07 -030072 req.index = CMD_SYS_WR;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -030073 else
74 req.index = CMD_IR_WR;
Antti Palosaari831e0b72011-07-08 23:36:07 -030075
76 req.value = reg;
77 req.size = len;
78 req.data = val;
79
80 return rtl28xxu_ctrl_msg(d, &req);
81}
82
Antti Palosaari670ef052014-12-23 14:32:35 -030083static int rtl28xxu_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
Antti Palosaari831e0b72011-07-08 23:36:07 -030084{
85 struct rtl28xxu_req req;
86
87 if (reg < 0x3000)
88 req.index = CMD_USB_RD;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -030089 else if (reg < 0x4000)
Antti Palosaari831e0b72011-07-08 23:36:07 -030090 req.index = CMD_SYS_RD;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -030091 else
92 req.index = CMD_IR_RD;
Antti Palosaari831e0b72011-07-08 23:36:07 -030093
94 req.value = reg;
95 req.size = len;
96 req.data = val;
97
98 return rtl28xxu_ctrl_msg(d, &req);
99}
100
Antti Palosaari670ef052014-12-23 14:32:35 -0300101static int rtl28xxu_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val)
Antti Palosaari831e0b72011-07-08 23:36:07 -0300102{
Antti Palosaari670ef052014-12-23 14:32:35 -0300103 return rtl28xxu_wr_regs(d, reg, &val, 1);
Antti Palosaari831e0b72011-07-08 23:36:07 -0300104}
105
Antti Palosaari670ef052014-12-23 14:32:35 -0300106static int rtl28xxu_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val)
Antti Palosaari831e0b72011-07-08 23:36:07 -0300107{
Antti Palosaari670ef052014-12-23 14:32:35 -0300108 return rtl28xxu_rd_regs(d, reg, val, 1);
Antti Palosaari831e0b72011-07-08 23:36:07 -0300109}
110
Antti Palosaari670ef052014-12-23 14:32:35 -0300111static int rtl28xxu_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val,
Antti Palosaari4005c1a2012-09-17 15:43:57 -0300112 u8 mask)
113{
114 int ret;
115 u8 tmp;
116
117 /* no need for read if whole reg is written */
118 if (mask != 0xff) {
Antti Palosaari670ef052014-12-23 14:32:35 -0300119 ret = rtl28xxu_rd_reg(d, reg, &tmp);
Antti Palosaari4005c1a2012-09-17 15:43:57 -0300120 if (ret)
121 return ret;
122
123 val &= mask;
124 tmp &= ~mask;
125 val |= tmp;
126 }
127
Antti Palosaari670ef052014-12-23 14:32:35 -0300128 return rtl28xxu_wr_reg(d, reg, val);
Antti Palosaari4005c1a2012-09-17 15:43:57 -0300129}
130
Antti Palosaari831e0b72011-07-08 23:36:07 -0300131/* I2C */
132static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
133 int num)
134{
135 int ret;
136 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300137 struct rtl28xxu_dev *dev = d->priv;
Antti Palosaari831e0b72011-07-08 23:36:07 -0300138 struct rtl28xxu_req req;
139
140 /*
141 * It is not known which are real I2C bus xfer limits, but testing
142 * with RTL2831U + MT2060 gives max RD 24 and max WR 22 bytes.
Antti Palosaari34ec2932011-08-04 20:21:16 -0300143 * TODO: find out RTL2832U lens
144 */
145
146 /*
147 * I2C adapter logic looks rather complicated due to fact it handles
148 * three different access methods. Those methods are;
149 * 1) integrated demod access
150 * 2) old I2C access
151 * 3) new I2C access
152 *
153 * Used method is selected in order 1, 2, 3. Method 3 can handle all
154 * requests but there is two reasons why not use it always;
155 * 1) It is most expensive, usually two USB messages are needed
156 * 2) At least RTL2831U does not support it
157 *
158 * Method 3 is needed in case of I2C write+read (typical register read)
159 * where write is more than one byte.
Antti Palosaari831e0b72011-07-08 23:36:07 -0300160 */
161
162 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
163 return -EAGAIN;
164
165 if (num == 2 && !(msg[0].flags & I2C_M_RD) &&
166 (msg[1].flags & I2C_M_RD)) {
Antti Palosaari34ec2932011-08-04 20:21:16 -0300167 if (msg[0].len > 24 || msg[1].len > 24) {
168 /* TODO: check msg[0].len max */
Antti Palosaari831e0b72011-07-08 23:36:07 -0300169 ret = -EOPNOTSUPP;
Antti Palosaari9935eea2012-01-21 22:26:52 -0300170 goto err_mutex_unlock;
Antti Palosaari34ec2932011-08-04 20:21:16 -0300171 } else if (msg[0].addr == 0x10) {
172 /* method 1 - integrated demod */
173 req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300174 req.index = CMD_DEMOD_RD | dev->page;
Antti Palosaari831e0b72011-07-08 23:36:07 -0300175 req.size = msg[1].len;
176 req.data = &msg[1].buf[0];
177 ret = rtl28xxu_ctrl_msg(d, &req);
Antti Palosaari34ec2932011-08-04 20:21:16 -0300178 } else if (msg[0].len < 2) {
179 /* method 2 - old I2C */
Antti Palosaari831e0b72011-07-08 23:36:07 -0300180 req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
181 req.index = CMD_I2C_RD;
182 req.size = msg[1].len;
183 req.data = &msg[1].buf[0];
184 ret = rtl28xxu_ctrl_msg(d, &req);
Antti Palosaari34ec2932011-08-04 20:21:16 -0300185 } else {
186 /* method 3 - new I2C */
187 req.value = (msg[0].addr << 1);
188 req.index = CMD_I2C_DA_WR;
189 req.size = msg[0].len;
190 req.data = msg[0].buf;
191 ret = rtl28xxu_ctrl_msg(d, &req);
192 if (ret)
Antti Palosaari9935eea2012-01-21 22:26:52 -0300193 goto err_mutex_unlock;
Antti Palosaari34ec2932011-08-04 20:21:16 -0300194
195 req.value = (msg[0].addr << 1);
196 req.index = CMD_I2C_DA_RD;
197 req.size = msg[1].len;
198 req.data = msg[1].buf;
199 ret = rtl28xxu_ctrl_msg(d, &req);
Antti Palosaari831e0b72011-07-08 23:36:07 -0300200 }
201 } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
202 if (msg[0].len > 22) {
Antti Palosaari34ec2932011-08-04 20:21:16 -0300203 /* TODO: check msg[0].len max */
Antti Palosaari831e0b72011-07-08 23:36:07 -0300204 ret = -EOPNOTSUPP;
Antti Palosaari9935eea2012-01-21 22:26:52 -0300205 goto err_mutex_unlock;
Antti Palosaari34ec2932011-08-04 20:21:16 -0300206 } else if (msg[0].addr == 0x10) {
207 /* method 1 - integrated demod */
208 if (msg[0].buf[0] == 0x00) {
209 /* save demod page for later demod access */
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300210 dev->page = msg[0].buf[1];
Antti Palosaari34ec2932011-08-04 20:21:16 -0300211 ret = 0;
212 } else {
213 req.value = (msg[0].buf[0] << 8) |
214 (msg[0].addr << 1);
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300215 req.index = CMD_DEMOD_WR | dev->page;
Antti Palosaari34ec2932011-08-04 20:21:16 -0300216 req.size = msg[0].len-1;
217 req.data = &msg[0].buf[1];
218 ret = rtl28xxu_ctrl_msg(d, &req);
219 }
220 } else if (msg[0].len < 23) {
221 /* method 2 - old I2C */
Antti Palosaari831e0b72011-07-08 23:36:07 -0300222 req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
223 req.index = CMD_I2C_WR;
224 req.size = msg[0].len-1;
225 req.data = &msg[0].buf[1];
226 ret = rtl28xxu_ctrl_msg(d, &req);
Antti Palosaari34ec2932011-08-04 20:21:16 -0300227 } else {
228 /* method 3 - new I2C */
229 req.value = (msg[0].addr << 1);
230 req.index = CMD_I2C_DA_WR;
231 req.size = msg[0].len;
232 req.data = msg[0].buf;
233 ret = rtl28xxu_ctrl_msg(d, &req);
Antti Palosaari831e0b72011-07-08 23:36:07 -0300234 }
235 } else {
236 ret = -EINVAL;
237 }
238
Antti Palosaari9935eea2012-01-21 22:26:52 -0300239err_mutex_unlock:
Antti Palosaari831e0b72011-07-08 23:36:07 -0300240 mutex_unlock(&d->i2c_mutex);
241
242 return ret ? ret : num;
243}
244
245static u32 rtl28xxu_i2c_func(struct i2c_adapter *adapter)
246{
247 return I2C_FUNC_I2C;
248}
249
250static struct i2c_algorithm rtl28xxu_i2c_algo = {
251 .master_xfer = rtl28xxu_i2c_xfer,
252 .functionality = rtl28xxu_i2c_func,
253};
254
Antti Palosaari81347f52012-09-17 16:50:36 -0300255static int rtl2831u_read_config(struct dvb_usb_device *d)
256{
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300257 struct rtl28xxu_dev *dev = d_to_priv(d);
Antti Palosaari81347f52012-09-17 16:50:36 -0300258 int ret;
259 u8 buf[1];
260 /* open RTL2831U/RTL2830 I2C gate */
261 struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x08"};
262 /* tuner probes */
263 struct rtl28xxu_req req_mt2060 = {0x00c0, CMD_I2C_RD, 1, buf};
264 struct rtl28xxu_req req_qt1010 = {0x0fc4, CMD_I2C_RD, 1, buf};
265
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300266 dev_dbg(&d->intf->dev, "\n");
Antti Palosaari81347f52012-09-17 16:50:36 -0300267
268 /*
269 * RTL2831U GPIOs
270 * =========================================================
271 * GPIO0 | tuner#0 | 0 off | 1 on | MXL5005S (?)
272 * GPIO2 | LED | 0 off | 1 on |
273 * GPIO4 | tuner#1 | 0 on | 1 off | MT2060
274 */
275
276 /* GPIO direction */
Antti Palosaari670ef052014-12-23 14:32:35 -0300277 ret = rtl28xxu_wr_reg(d, SYS_GPIO_DIR, 0x0a);
Antti Palosaari81347f52012-09-17 16:50:36 -0300278 if (ret)
279 goto err;
280
281 /* enable as output GPIO0, GPIO2, GPIO4 */
Antti Palosaari670ef052014-12-23 14:32:35 -0300282 ret = rtl28xxu_wr_reg(d, SYS_GPIO_OUT_EN, 0x15);
Antti Palosaari81347f52012-09-17 16:50:36 -0300283 if (ret)
284 goto err;
285
286 /*
287 * Probe used tuner. We need to know used tuner before demod attach
288 * since there is some demod params needed to set according to tuner.
289 */
290
291 /* demod needs some time to wake up */
292 msleep(20);
293
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300294 dev->tuner_name = "NONE";
Antti Palosaari81347f52012-09-17 16:50:36 -0300295
296 /* open demod I2C gate */
297 ret = rtl28xxu_ctrl_msg(d, &req_gate_open);
298 if (ret)
299 goto err;
300
301 /* check QT1010 ID(?) register; reg=0f val=2c */
302 ret = rtl28xxu_ctrl_msg(d, &req_qt1010);
303 if (ret == 0 && buf[0] == 0x2c) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300304 dev->tuner = TUNER_RTL2830_QT1010;
305 dev->tuner_name = "QT1010";
Antti Palosaari81347f52012-09-17 16:50:36 -0300306 goto found;
307 }
308
309 /* open demod I2C gate */
310 ret = rtl28xxu_ctrl_msg(d, &req_gate_open);
311 if (ret)
312 goto err;
313
314 /* check MT2060 ID register; reg=00 val=63 */
315 ret = rtl28xxu_ctrl_msg(d, &req_mt2060);
316 if (ret == 0 && buf[0] == 0x63) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300317 dev->tuner = TUNER_RTL2830_MT2060;
318 dev->tuner_name = "MT2060";
Antti Palosaari81347f52012-09-17 16:50:36 -0300319 goto found;
320 }
321
322 /* assume MXL5005S */
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300323 dev->tuner = TUNER_RTL2830_MXL5005S;
324 dev->tuner_name = "MXL5005S";
Antti Palosaari81347f52012-09-17 16:50:36 -0300325 goto found;
326
327found:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300328 dev_dbg(&d->intf->dev, "tuner=%s\n", dev->tuner_name);
Antti Palosaari81347f52012-09-17 16:50:36 -0300329
330 return 0;
331err:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300332 dev_dbg(&d->intf->dev, "failed=%d\n", ret);
Antti Palosaari81347f52012-09-17 16:50:36 -0300333 return ret;
334}
335
Antti Palosaarief37be12012-09-17 14:01:35 -0300336static int rtl2832u_read_config(struct dvb_usb_device *d)
337{
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300338 struct rtl28xxu_dev *dev = d_to_priv(d);
Antti Palosaarief37be12012-09-17 14:01:35 -0300339 int ret;
Antti Palosaari4005c1a2012-09-17 15:43:57 -0300340 u8 buf[2];
Antti Palosaarief37be12012-09-17 14:01:35 -0300341 /* open RTL2832U/RTL2832 I2C gate */
342 struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"};
343 /* close RTL2832U/RTL2832 I2C gate */
344 struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"};
345 /* tuner probes */
346 struct rtl28xxu_req req_fc0012 = {0x00c6, CMD_I2C_RD, 1, buf};
347 struct rtl28xxu_req req_fc0013 = {0x00c6, CMD_I2C_RD, 1, buf};
348 struct rtl28xxu_req req_mt2266 = {0x00c0, CMD_I2C_RD, 1, buf};
349 struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf};
350 struct rtl28xxu_req req_mt2063 = {0x00c0, CMD_I2C_RD, 1, buf};
351 struct rtl28xxu_req req_max3543 = {0x00c0, CMD_I2C_RD, 1, buf};
352 struct rtl28xxu_req req_tua9001 = {0x7ec0, CMD_I2C_RD, 2, buf};
353 struct rtl28xxu_req req_mxl5007t = {0xd9c0, CMD_I2C_RD, 1, buf};
354 struct rtl28xxu_req req_e4000 = {0x02c8, CMD_I2C_RD, 1, buf};
355 struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf};
Gianluca Gennaria908eb92013-06-02 17:24:24 -0300356 struct rtl28xxu_req req_r820t = {0x0034, CMD_I2C_RD, 1, buf};
Antti Palosaari8b4cac12013-10-30 00:45:38 -0300357 struct rtl28xxu_req req_r828d = {0x0074, CMD_I2C_RD, 1, buf};
Antti Palosaari80f189a2013-12-01 13:44:23 -0300358 struct rtl28xxu_req req_mn88472 = {0xff38, CMD_I2C_RD, 1, buf};
Antti Palosaarifc694e42014-09-30 01:03:04 -0300359 struct rtl28xxu_req req_mn88473 = {0xff38, CMD_I2C_RD, 1, buf};
Antti Palosaarief37be12012-09-17 14:01:35 -0300360
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300361 dev_dbg(&d->intf->dev, "\n");
Antti Palosaarief37be12012-09-17 14:01:35 -0300362
Antti Palosaari4005c1a2012-09-17 15:43:57 -0300363 /* enable GPIO3 and GPIO6 as output */
Antti Palosaari670ef052014-12-23 14:32:35 -0300364 ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x40);
Antti Palosaarief37be12012-09-17 14:01:35 -0300365 if (ret)
366 goto err;
367
Antti Palosaari670ef052014-12-23 14:32:35 -0300368 ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x48, 0x48);
Antti Palosaarief37be12012-09-17 14:01:35 -0300369 if (ret)
370 goto err;
371
372 /*
373 * Probe used tuner. We need to know used tuner before demod attach
374 * since there is some demod params needed to set according to tuner.
375 */
376
377 /* open demod I2C gate */
378 ret = rtl28xxu_ctrl_msg(d, &req_gate_open);
379 if (ret)
380 goto err;
381
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300382 dev->tuner_name = "NONE";
Antti Palosaarief37be12012-09-17 14:01:35 -0300383
384 /* check FC0012 ID register; reg=00 val=a1 */
385 ret = rtl28xxu_ctrl_msg(d, &req_fc0012);
386 if (ret == 0 && buf[0] == 0xa1) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300387 dev->tuner = TUNER_RTL2832_FC0012;
388 dev->tuner_name = "FC0012";
Antti Palosaari80f189a2013-12-01 13:44:23 -0300389 goto tuner_found;
Antti Palosaarief37be12012-09-17 14:01:35 -0300390 }
391
392 /* check FC0013 ID register; reg=00 val=a3 */
393 ret = rtl28xxu_ctrl_msg(d, &req_fc0013);
394 if (ret == 0 && buf[0] == 0xa3) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300395 dev->tuner = TUNER_RTL2832_FC0013;
396 dev->tuner_name = "FC0013";
Antti Palosaari80f189a2013-12-01 13:44:23 -0300397 goto tuner_found;
Antti Palosaarief37be12012-09-17 14:01:35 -0300398 }
399
400 /* check MT2266 ID register; reg=00 val=85 */
401 ret = rtl28xxu_ctrl_msg(d, &req_mt2266);
402 if (ret == 0 && buf[0] == 0x85) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300403 dev->tuner = TUNER_RTL2832_MT2266;
404 dev->tuner_name = "MT2266";
Antti Palosaari80f189a2013-12-01 13:44:23 -0300405 goto tuner_found;
Antti Palosaarief37be12012-09-17 14:01:35 -0300406 }
407
408 /* check FC2580 ID register; reg=01 val=56 */
409 ret = rtl28xxu_ctrl_msg(d, &req_fc2580);
410 if (ret == 0 && buf[0] == 0x56) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300411 dev->tuner = TUNER_RTL2832_FC2580;
412 dev->tuner_name = "FC2580";
Antti Palosaari80f189a2013-12-01 13:44:23 -0300413 goto tuner_found;
Antti Palosaarief37be12012-09-17 14:01:35 -0300414 }
415
416 /* check MT2063 ID register; reg=00 val=9e || 9c */
417 ret = rtl28xxu_ctrl_msg(d, &req_mt2063);
418 if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300419 dev->tuner = TUNER_RTL2832_MT2063;
420 dev->tuner_name = "MT2063";
Antti Palosaari80f189a2013-12-01 13:44:23 -0300421 goto tuner_found;
Antti Palosaarief37be12012-09-17 14:01:35 -0300422 }
423
424 /* check MAX3543 ID register; reg=00 val=38 */
425 ret = rtl28xxu_ctrl_msg(d, &req_max3543);
426 if (ret == 0 && buf[0] == 0x38) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300427 dev->tuner = TUNER_RTL2832_MAX3543;
428 dev->tuner_name = "MAX3543";
Antti Palosaari80f189a2013-12-01 13:44:23 -0300429 goto tuner_found;
Antti Palosaarief37be12012-09-17 14:01:35 -0300430 }
431
432 /* check TUA9001 ID register; reg=7e val=2328 */
433 ret = rtl28xxu_ctrl_msg(d, &req_tua9001);
434 if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300435 dev->tuner = TUNER_RTL2832_TUA9001;
436 dev->tuner_name = "TUA9001";
Antti Palosaari80f189a2013-12-01 13:44:23 -0300437 goto tuner_found;
Antti Palosaarief37be12012-09-17 14:01:35 -0300438 }
439
440 /* check MXL5007R ID register; reg=d9 val=14 */
441 ret = rtl28xxu_ctrl_msg(d, &req_mxl5007t);
442 if (ret == 0 && buf[0] == 0x14) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300443 dev->tuner = TUNER_RTL2832_MXL5007T;
444 dev->tuner_name = "MXL5007T";
Antti Palosaari80f189a2013-12-01 13:44:23 -0300445 goto tuner_found;
Antti Palosaarief37be12012-09-17 14:01:35 -0300446 }
447
448 /* check E4000 ID register; reg=02 val=40 */
449 ret = rtl28xxu_ctrl_msg(d, &req_e4000);
450 if (ret == 0 && buf[0] == 0x40) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300451 dev->tuner = TUNER_RTL2832_E4000;
452 dev->tuner_name = "E4000";
Antti Palosaari80f189a2013-12-01 13:44:23 -0300453 goto tuner_found;
Antti Palosaarief37be12012-09-17 14:01:35 -0300454 }
455
456 /* check TDA18272 ID register; reg=00 val=c760 */
457 ret = rtl28xxu_ctrl_msg(d, &req_tda18272);
458 if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300459 dev->tuner = TUNER_RTL2832_TDA18272;
460 dev->tuner_name = "TDA18272";
Antti Palosaari80f189a2013-12-01 13:44:23 -0300461 goto tuner_found;
Antti Palosaarief37be12012-09-17 14:01:35 -0300462 }
463
Gianluca Gennaria908eb92013-06-02 17:24:24 -0300464 /* check R820T ID register; reg=00 val=69 */
Mauro Carvalho Chehab6889ab22013-04-06 09:40:11 -0300465 ret = rtl28xxu_ctrl_msg(d, &req_r820t);
Gianluca Gennaria908eb92013-06-02 17:24:24 -0300466 if (ret == 0 && buf[0] == 0x69) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300467 dev->tuner = TUNER_RTL2832_R820T;
468 dev->tuner_name = "R820T";
Antti Palosaari80f189a2013-12-01 13:44:23 -0300469 goto tuner_found;
Mauro Carvalho Chehab6889ab22013-04-06 09:40:11 -0300470 }
471
Antti Palosaari8b4cac12013-10-30 00:45:38 -0300472 /* check R828D ID register; reg=00 val=69 */
473 ret = rtl28xxu_ctrl_msg(d, &req_r828d);
474 if (ret == 0 && buf[0] == 0x69) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300475 dev->tuner = TUNER_RTL2832_R828D;
476 dev->tuner_name = "R828D";
Antti Palosaari80f189a2013-12-01 13:44:23 -0300477 goto tuner_found;
Antti Palosaari8b4cac12013-10-30 00:45:38 -0300478 }
479
Antti Palosaari80f189a2013-12-01 13:44:23 -0300480tuner_found:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300481 dev_dbg(&d->intf->dev, "tuner=%s\n", dev->tuner_name);
Antti Palosaarief37be12012-09-17 14:01:35 -0300482
Antti Palosaari80f189a2013-12-01 13:44:23 -0300483 /* probe slave demod */
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300484 if (dev->tuner == TUNER_RTL2832_R828D) {
Antti Palosaari80f189a2013-12-01 13:44:23 -0300485 /* power on MN88472 demod on GPIO0 */
Antti Palosaari670ef052014-12-23 14:32:35 -0300486 ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x01, 0x01);
Antti Palosaari80f189a2013-12-01 13:44:23 -0300487 if (ret)
488 goto err;
489
Antti Palosaari670ef052014-12-23 14:32:35 -0300490 ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x01);
Antti Palosaari80f189a2013-12-01 13:44:23 -0300491 if (ret)
492 goto err;
493
Antti Palosaari670ef052014-12-23 14:32:35 -0300494 ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x01, 0x01);
Antti Palosaari80f189a2013-12-01 13:44:23 -0300495 if (ret)
496 goto err;
497
498 /* check MN88472 answers */
499 ret = rtl28xxu_ctrl_msg(d, &req_mn88472);
500 if (ret == 0 && buf[0] == 0x02) {
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300501 dev_dbg(&d->intf->dev, "MN88472 found\n");
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300502 dev->slave_demod = SLAVE_DEMOD_MN88472;
Antti Palosaari80f189a2013-12-01 13:44:23 -0300503 goto demod_found;
504 }
Antti Palosaarifc694e42014-09-30 01:03:04 -0300505
506 ret = rtl28xxu_ctrl_msg(d, &req_mn88473);
507 if (ret == 0 && buf[0] == 0x03) {
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300508 dev_dbg(&d->intf->dev, "MN88473 found\n");
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300509 dev->slave_demod = SLAVE_DEMOD_MN88473;
Antti Palosaarifc694e42014-09-30 01:03:04 -0300510 goto demod_found;
511 }
Antti Palosaari80f189a2013-12-01 13:44:23 -0300512 }
513
514demod_found:
Antti Palosaarief37be12012-09-17 14:01:35 -0300515 /* close demod I2C gate */
516 ret = rtl28xxu_ctrl_msg(d, &req_gate_close);
517 if (ret < 0)
518 goto err;
519
520 return 0;
521err:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300522 dev_dbg(&d->intf->dev, "failed=%d\n", ret);
Antti Palosaarief37be12012-09-17 14:01:35 -0300523 return ret;
524}
525
Antti Palosaaride701f02014-12-23 14:09:13 -0300526static int rtl28xxu_read_config(struct dvb_usb_device *d)
527{
528 struct rtl28xxu_dev *dev = d_to_priv(d);
529
530 if (dev->chip_id == CHIP_ID_RTL2831U)
531 return rtl2831u_read_config(d);
532 else
533 return rtl2832u_read_config(d);
534}
535
Antti Palosaarid0f232e2014-12-23 13:14:36 -0300536static int rtl28xxu_identify_state(struct dvb_usb_device *d, const char **name)
537{
538 struct rtl28xxu_dev *dev = d_to_priv(d);
539 int ret;
540 struct rtl28xxu_req req_demod_i2c = {0x0020, CMD_I2C_DA_RD, 0, NULL};
541
542 dev_dbg(&d->intf->dev, "\n");
543
544 /*
545 * Detect chip type using I2C command that is not supported
546 * by old RTL2831U.
547 */
548 ret = rtl28xxu_ctrl_msg(d, &req_demod_i2c);
549 if (ret == -EPIPE) {
550 dev->chip_id = CHIP_ID_RTL2831U;
551 } else if (ret == 0) {
552 dev->chip_id = CHIP_ID_RTL2832U;
553 } else {
554 dev_err(&d->intf->dev, "chip type detection failed %d\n", ret);
555 goto err;
556 }
557 dev_dbg(&d->intf->dev, "chip_id=%u\n", dev->chip_id);
558
559 return WARM;
560err:
561 dev_dbg(&d->intf->dev, "failed=%d\n", ret);
562 return ret;
563}
564
Antti Palosaaric0ceac92014-12-07 22:02:23 -0300565static const struct rtl2830_platform_data rtl2830_mt2060_platform_data = {
566 .clk = 28800000,
Antti Palosaari831e0b72011-07-08 23:36:07 -0300567 .spec_inv = 1,
Antti Palosaari831e0b72011-07-08 23:36:07 -0300568 .vtop = 0x20,
569 .krf = 0x04,
570 .agc_targ_val = 0x2d,
571
572};
573
Antti Palosaaric0ceac92014-12-07 22:02:23 -0300574static const struct rtl2830_platform_data rtl2830_qt1010_platform_data = {
575 .clk = 28800000,
Antti Palosaari831e0b72011-07-08 23:36:07 -0300576 .spec_inv = 1,
Antti Palosaari831e0b72011-07-08 23:36:07 -0300577 .vtop = 0x20,
578 .krf = 0x04,
579 .agc_targ_val = 0x2d,
580};
581
Antti Palosaaric0ceac92014-12-07 22:02:23 -0300582static const struct rtl2830_platform_data rtl2830_mxl5005s_platform_data = {
583 .clk = 28800000,
Antti Palosaari831e0b72011-07-08 23:36:07 -0300584 .spec_inv = 0,
Antti Palosaari831e0b72011-07-08 23:36:07 -0300585 .vtop = 0x3f,
586 .krf = 0x04,
587 .agc_targ_val = 0x3e,
588};
589
Antti Palosaarib5cbaa42011-08-04 13:26:10 -0300590static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
Antti Palosaari831e0b72011-07-08 23:36:07 -0300591{
Antti Palosaaric01a3592012-08-12 22:27:07 -0300592 struct dvb_usb_device *d = adap_to_d(adap);
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300593 struct rtl28xxu_dev *dev = d_to_priv(d);
594 struct rtl2830_platform_data *pdata = &dev->rtl2830_platform_data;
Antti Palosaaric0ceac92014-12-07 22:02:23 -0300595 struct i2c_board_info board_info;
596 struct i2c_client *client;
Antti Palosaari81347f52012-09-17 16:50:36 -0300597 int ret;
Antti Palosaari831e0b72011-07-08 23:36:07 -0300598
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300599 dev_dbg(&d->intf->dev, "\n");
Antti Palosaari831e0b72011-07-08 23:36:07 -0300600
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300601 switch (dev->tuner) {
Antti Palosaari81347f52012-09-17 16:50:36 -0300602 case TUNER_RTL2830_QT1010:
Antti Palosaaric0ceac92014-12-07 22:02:23 -0300603 *pdata = rtl2830_qt1010_platform_data;
Antti Palosaari81347f52012-09-17 16:50:36 -0300604 break;
605 case TUNER_RTL2830_MT2060:
Antti Palosaaric0ceac92014-12-07 22:02:23 -0300606 *pdata = rtl2830_mt2060_platform_data;
Antti Palosaari81347f52012-09-17 16:50:36 -0300607 break;
608 case TUNER_RTL2830_MXL5005S:
Antti Palosaaric0ceac92014-12-07 22:02:23 -0300609 *pdata = rtl2830_mxl5005s_platform_data;
Antti Palosaari81347f52012-09-17 16:50:36 -0300610 break;
611 default:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300612 dev_err(&d->intf->dev, "unknown tuner %s\n", dev->tuner_name);
Antti Palosaari831e0b72011-07-08 23:36:07 -0300613 ret = -ENODEV;
614 goto err;
615 }
616
Antti Palosaari81347f52012-09-17 16:50:36 -0300617 /* attach demodulator */
Antti Palosaaric0ceac92014-12-07 22:02:23 -0300618 memset(&board_info, 0, sizeof(board_info));
619 strlcpy(board_info.type, "rtl2830", I2C_NAME_SIZE);
620 board_info.addr = 0x10;
621 board_info.platform_data = pdata;
622 request_module("%s", board_info.type);
623 client = i2c_new_device(&d->i2c_adap, &board_info);
624 if (client == NULL || client->dev.driver == NULL) {
Antti Palosaari81347f52012-09-17 16:50:36 -0300625 ret = -ENODEV;
626 goto err;
627 }
628
Antti Palosaaric0ceac92014-12-07 22:02:23 -0300629 if (!try_module_get(client->dev.driver->owner)) {
630 i2c_unregister_device(client);
631 ret = -ENODEV;
632 goto err;
633 }
634
635 adap->fe[0] = pdata->get_dvb_frontend(client);
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300636 dev->demod_i2c_adapter = pdata->get_i2c_adapter(client);
Antti Palosaaric0ceac92014-12-07 22:02:23 -0300637
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300638 dev->i2c_client_demod = client;
Antti Palosaaric0ceac92014-12-07 22:02:23 -0300639
Antti Palosaari81347f52012-09-17 16:50:36 -0300640 return 0;
Antti Palosaari831e0b72011-07-08 23:36:07 -0300641err:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300642 dev_dbg(&d->intf->dev, "failed=%d\n", ret);
Antti Palosaari831e0b72011-07-08 23:36:07 -0300643 return ret;
644}
645
Antti Palosaaride0a5f12014-12-13 05:44:05 -0300646static const struct rtl2832_platform_data rtl2832_fc0012_platform_data = {
647 .clk = 28800000,
648 .tuner = TUNER_RTL2832_FC0012
649};
650
651static const struct rtl2832_platform_data rtl2832_fc0013_platform_data = {
652 .clk = 28800000,
653 .tuner = TUNER_RTL2832_FC0013
654};
655
656static const struct rtl2832_platform_data rtl2832_tua9001_platform_data = {
657 .clk = 28800000,
658 .tuner = TUNER_RTL2832_TUA9001,
659};
660
661static const struct rtl2832_platform_data rtl2832_e4000_platform_data = {
662 .clk = 28800000,
663 .tuner = TUNER_RTL2832_E4000,
664};
665
666static const struct rtl2832_platform_data rtl2832_r820t_platform_data = {
667 .clk = 28800000,
668 .tuner = TUNER_RTL2832_R820T,
669};
670
Thomas Mair5cf66312012-05-18 14:47:41 -0300671static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d,
672 int cmd, int arg)
673{
674 int ret;
675 u8 val;
676
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300677 dev_dbg(&d->intf->dev, "cmd=%d arg=%d\n", cmd, arg);
Antti Palosaaric01a3592012-08-12 22:27:07 -0300678
Thomas Mair5cf66312012-05-18 14:47:41 -0300679 switch (cmd) {
680 case FC_FE_CALLBACK_VHF_ENABLE:
681 /* set output values */
Antti Palosaari670ef052014-12-23 14:32:35 -0300682 ret = rtl28xxu_rd_reg(d, SYS_GPIO_OUT_VAL, &val);
Thomas Mair5cf66312012-05-18 14:47:41 -0300683 if (ret)
684 goto err;
685
686 if (arg)
687 val &= 0xbf; /* set GPIO6 low */
688 else
689 val |= 0x40; /* set GPIO6 high */
690
691
Antti Palosaari670ef052014-12-23 14:32:35 -0300692 ret = rtl28xxu_wr_reg(d, SYS_GPIO_OUT_VAL, val);
Thomas Mair5cf66312012-05-18 14:47:41 -0300693 if (ret)
694 goto err;
695 break;
696 default:
697 ret = -EINVAL;
698 goto err;
699 }
700 return 0;
Thomas Mair5cf66312012-05-18 14:47:41 -0300701err:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300702 dev_dbg(&d->intf->dev, "failed=%d\n", ret);
Thomas Mair5cf66312012-05-18 14:47:41 -0300703 return ret;
704}
705
Antti Palosaari5be65722012-09-11 22:27:09 -0300706static int rtl2832u_tua9001_tuner_callback(struct dvb_usb_device *d,
707 int cmd, int arg)
708{
709 int ret;
710 u8 val;
711
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300712 dev_dbg(&d->intf->dev, "cmd=%d arg=%d\n", cmd, arg);
Antti Palosaari5be65722012-09-11 22:27:09 -0300713
714 /*
715 * CEN always enabled by hardware wiring
716 * RESETN GPIO4
717 * RXEN GPIO1
718 */
719
Antti Palosaari5be65722012-09-11 22:27:09 -0300720 switch (cmd) {
721 case TUA9001_CMD_RESETN:
722 if (arg)
Antti Palosaari4005c1a2012-09-17 15:43:57 -0300723 val = (1 << 4);
Antti Palosaari5be65722012-09-11 22:27:09 -0300724 else
Antti Palosaari4005c1a2012-09-17 15:43:57 -0300725 val = (0 << 4);
Antti Palosaari5be65722012-09-11 22:27:09 -0300726
Antti Palosaari670ef052014-12-23 14:32:35 -0300727 ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, val, 0x10);
Antti Palosaari4005c1a2012-09-17 15:43:57 -0300728 if (ret)
Antti Palosaari5be65722012-09-11 22:27:09 -0300729 goto err;
730 break;
731 case TUA9001_CMD_RXEN:
732 if (arg)
Antti Palosaari4005c1a2012-09-17 15:43:57 -0300733 val = (1 << 1);
Antti Palosaari5be65722012-09-11 22:27:09 -0300734 else
Antti Palosaari4005c1a2012-09-17 15:43:57 -0300735 val = (0 << 1);
Antti Palosaari5be65722012-09-11 22:27:09 -0300736
Antti Palosaari670ef052014-12-23 14:32:35 -0300737 ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, val, 0x02);
Antti Palosaari4005c1a2012-09-17 15:43:57 -0300738 if (ret)
Antti Palosaari5be65722012-09-11 22:27:09 -0300739 goto err;
740 break;
741 }
742
743 return 0;
Antti Palosaari5be65722012-09-11 22:27:09 -0300744err:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300745 dev_dbg(&d->intf->dev, "failed=%d\n", ret);
Antti Palosaari5be65722012-09-11 22:27:09 -0300746 return ret;
747}
748
Thomas Mair5cf66312012-05-18 14:47:41 -0300749static int rtl2832u_frontend_callback(void *adapter_priv, int component,
Antti Palosaari8acc91c2012-09-17 16:55:39 -0300750 int cmd, int arg)
Thomas Mair5cf66312012-05-18 14:47:41 -0300751{
Antti Palosaari1dbbdce2014-12-17 02:55:41 -0300752 struct i2c_adapter *adapter = adapter_priv;
753 struct device *parent = adapter->dev.parent;
754 struct i2c_adapter *parent_adapter;
755 struct dvb_usb_device *d;
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300756 struct rtl28xxu_dev *dev;
Antti Palosaari1dbbdce2014-12-17 02:55:41 -0300757
758 /*
759 * All tuners are connected to demod muxed I2C adapter. We have to
760 * resolve its parent adapter in order to get handle for this driver
761 * private data. That is a bit hackish solution, GPIO or direct driver
762 * callback would be better...
763 */
764 if (parent != NULL && parent->type == &i2c_adapter_type)
765 parent_adapter = to_i2c_adapter(parent);
766 else
767 return -EINVAL;
768
769 d = i2c_get_adapdata(parent_adapter);
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300770 dev = d->priv;
Thomas Mair5cf66312012-05-18 14:47:41 -0300771
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300772 dev_dbg(&d->intf->dev, "component=%d cmd=%d arg=%d\n",
773 component, cmd, arg);
Antti Palosaari8acc91c2012-09-17 16:55:39 -0300774
Thomas Mair5cf66312012-05-18 14:47:41 -0300775 switch (component) {
776 case DVB_FRONTEND_COMPONENT_TUNER:
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300777 switch (dev->tuner) {
Antti Palosaaria6f62432014-12-17 03:09:32 -0300778 case TUNER_RTL2832_FC0012:
779 return rtl2832u_fc0012_tuner_callback(d, cmd, arg);
780 case TUNER_RTL2832_TUA9001:
781 return rtl2832u_tua9001_tuner_callback(d, cmd, arg);
782 }
Thomas Mair5cf66312012-05-18 14:47:41 -0300783 default:
Antti Palosaaria6f62432014-12-17 03:09:32 -0300784 return -EINVAL;
Thomas Mair5cf66312012-05-18 14:47:41 -0300785 }
786
Antti Palosaari97efe782012-09-17 15:49:54 -0300787 return 0;
Thomas Mair5cf66312012-05-18 14:47:41 -0300788}
789
Antti Palosaarib5cbaa42011-08-04 13:26:10 -0300790static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
791{
Antti Palosaaric01a3592012-08-12 22:27:07 -0300792 struct dvb_usb_device *d = adap_to_d(adap);
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300793 struct rtl28xxu_dev *dev = d_to_priv(d);
794 struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data;
Antti Palosaari77a2e762014-12-13 00:09:57 -0300795 struct i2c_board_info board_info;
Antti Palosaari83b2f842014-12-02 11:00:23 -0300796 struct i2c_client *client;
Antti Palosaari77a2e762014-12-13 00:09:57 -0300797 int ret;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -0300798
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300799 dev_dbg(&d->intf->dev, "\n");
Antti Palosaarib5cbaa42011-08-04 13:26:10 -0300800
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300801 switch (dev->tuner) {
Antti Palosaarief37be12012-09-17 14:01:35 -0300802 case TUNER_RTL2832_FC0012:
Antti Palosaaride0a5f12014-12-13 05:44:05 -0300803 *pdata = rtl2832_fc0012_platform_data;
Antti Palosaarief37be12012-09-17 14:01:35 -0300804 break;
805 case TUNER_RTL2832_FC0013:
Antti Palosaaride0a5f12014-12-13 05:44:05 -0300806 *pdata = rtl2832_fc0013_platform_data;
Antti Palosaarief37be12012-09-17 14:01:35 -0300807 break;
808 case TUNER_RTL2832_FC2580:
Antti Palosaari384df492012-09-08 22:07:25 -0300809 /* FIXME: do not abuse fc0012 settings */
Antti Palosaaride0a5f12014-12-13 05:44:05 -0300810 *pdata = rtl2832_fc0012_platform_data;
Antti Palosaarief37be12012-09-17 14:01:35 -0300811 break;
812 case TUNER_RTL2832_TUA9001:
Antti Palosaaride0a5f12014-12-13 05:44:05 -0300813 *pdata = rtl2832_tua9001_platform_data;
Antti Palosaarief37be12012-09-17 14:01:35 -0300814 break;
815 case TUNER_RTL2832_E4000:
Antti Palosaaride0a5f12014-12-13 05:44:05 -0300816 *pdata = rtl2832_e4000_platform_data;
Antti Palosaarief37be12012-09-17 14:01:35 -0300817 break;
Mauro Carvalho Chehab6889ab22013-04-06 09:40:11 -0300818 case TUNER_RTL2832_R820T:
Antti Palosaari8b4cac12013-10-30 00:45:38 -0300819 case TUNER_RTL2832_R828D:
Antti Palosaaride0a5f12014-12-13 05:44:05 -0300820 *pdata = rtl2832_r820t_platform_data;
Mauro Carvalho Chehab6889ab22013-04-06 09:40:11 -0300821 break;
Antti Palosaarief37be12012-09-17 14:01:35 -0300822 default:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300823 dev_err(&d->intf->dev, "unknown tuner %s\n", dev->tuner_name);
Antti Palosaarief37be12012-09-17 14:01:35 -0300824 ret = -ENODEV;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -0300825 goto err;
Antti Palosaarief37be12012-09-17 14:01:35 -0300826 }
Antti Palosaarib5cbaa42011-08-04 13:26:10 -0300827
828 /* attach demodulator */
Antti Palosaari77a2e762014-12-13 00:09:57 -0300829 memset(&board_info, 0, sizeof(board_info));
Antti Palosaari83b2f842014-12-02 11:00:23 -0300830 strlcpy(board_info.type, "rtl2832", I2C_NAME_SIZE);
831 board_info.addr = 0x10;
Antti Palosaari77a2e762014-12-13 00:09:57 -0300832 board_info.platform_data = pdata;
Antti Palosaari83b2f842014-12-02 11:00:23 -0300833 request_module("%s", board_info.type);
834 client = i2c_new_device(&d->i2c_adap, &board_info);
835 if (client == NULL || client->dev.driver == NULL) {
Antti Palosaarief37be12012-09-17 14:01:35 -0300836 ret = -ENODEV;
837 goto err;
838 }
Thomas Mair5cf66312012-05-18 14:47:41 -0300839
Antti Palosaari83b2f842014-12-02 11:00:23 -0300840 if (!try_module_get(client->dev.driver->owner)) {
841 i2c_unregister_device(client);
842 ret = -ENODEV;
843 goto err;
844 }
845
Antti Palosaari77a2e762014-12-13 00:09:57 -0300846 adap->fe[0] = pdata->get_dvb_frontend(client);
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300847 dev->demod_i2c_adapter = pdata->get_i2c_adapter(client);
Antti Palosaari83b2f842014-12-02 11:00:23 -0300848
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300849 dev->i2c_client_demod = client;
Antti Palosaariae1f8452014-02-08 04:03:57 -0300850
Antti Palosaarief37be12012-09-17 14:01:35 -0300851 /* set fe callback */
Antti Palosaaric01a3592012-08-12 22:27:07 -0300852 adap->fe[0]->callback = rtl2832u_frontend_callback;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -0300853
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300854 if (dev->slave_demod) {
Antti Palosaari80f189a2013-12-01 13:44:23 -0300855 struct i2c_board_info info = {};
Antti Palosaari80f189a2013-12-01 13:44:23 -0300856
857 /*
858 * We continue on reduced mode, without DVB-T2/C, using master
859 * demod, when slave demod fails.
860 */
861 ret = 0;
862
863 /* attach slave demodulator */
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300864 if (dev->slave_demod == SLAVE_DEMOD_MN88472) {
Antti Palosaari80f189a2013-12-01 13:44:23 -0300865 struct mn88472_config mn88472_config = {};
866
867 mn88472_config.fe = &adap->fe[1];
868 mn88472_config.i2c_wr_max = 22,
869 strlcpy(info.type, "mn88472", I2C_NAME_SIZE);
Benjamin Larssond2fb7852014-11-26 18:51:46 -0300870 mn88472_config.xtal = 20500000;
Antti Palosaari80f189a2013-12-01 13:44:23 -0300871 info.addr = 0x18;
872 info.platform_data = &mn88472_config;
873 request_module(info.type);
Antti Palosaari488be132014-12-16 11:05:08 -0300874 client = i2c_new_device(&d->i2c_adap, &info);
Antti Palosaari80f189a2013-12-01 13:44:23 -0300875 if (client == NULL || client->dev.driver == NULL) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300876 dev->slave_demod = SLAVE_DEMOD_NONE;
Antti Palosaari80f189a2013-12-01 13:44:23 -0300877 goto err_slave_demod_failed;
878 }
879
880 if (!try_module_get(client->dev.driver->owner)) {
881 i2c_unregister_device(client);
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300882 dev->slave_demod = SLAVE_DEMOD_NONE;
Antti Palosaari80f189a2013-12-01 13:44:23 -0300883 goto err_slave_demod_failed;
884 }
885
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300886 dev->i2c_client_slave_demod = client;
Antti Palosaarifc694e42014-09-30 01:03:04 -0300887 } else {
888 struct mn88473_config mn88473_config = {};
889
890 mn88473_config.fe = &adap->fe[1];
891 mn88473_config.i2c_wr_max = 22,
892 strlcpy(info.type, "mn88473", I2C_NAME_SIZE);
893 info.addr = 0x18;
894 info.platform_data = &mn88473_config;
895 request_module(info.type);
Antti Palosaari488be132014-12-16 11:05:08 -0300896 client = i2c_new_device(&d->i2c_adap, &info);
Antti Palosaarifc694e42014-09-30 01:03:04 -0300897 if (client == NULL || client->dev.driver == NULL) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300898 dev->slave_demod = SLAVE_DEMOD_NONE;
Antti Palosaarifc694e42014-09-30 01:03:04 -0300899 goto err_slave_demod_failed;
900 }
901
902 if (!try_module_get(client->dev.driver->owner)) {
903 i2c_unregister_device(client);
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300904 dev->slave_demod = SLAVE_DEMOD_NONE;
Antti Palosaarifc694e42014-09-30 01:03:04 -0300905 goto err_slave_demod_failed;
906 }
907
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300908 dev->i2c_client_slave_demod = client;
Antti Palosaari80f189a2013-12-01 13:44:23 -0300909 }
910 }
911
Antti Palosaarief37be12012-09-17 14:01:35 -0300912 return 0;
Antti Palosaari80f189a2013-12-01 13:44:23 -0300913err_slave_demod_failed:
Antti Palosaarib5cbaa42011-08-04 13:26:10 -0300914err:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300915 dev_dbg(&d->intf->dev, "failed=%d\n", ret);
Antti Palosaarib5cbaa42011-08-04 13:26:10 -0300916 return ret;
917}
918
Antti Palosaaride701f02014-12-23 14:09:13 -0300919static int rtl28xxu_frontend_attach(struct dvb_usb_adapter *adap)
920{
921 struct rtl28xxu_dev *dev = adap_to_priv(adap);
922
923 if (dev->chip_id == CHIP_ID_RTL2831U)
924 return rtl2831u_frontend_attach(adap);
925 else
926 return rtl2832u_frontend_attach(adap);
927}
928
929static int rtl28xxu_frontend_detach(struct dvb_usb_adapter *adap)
Antti Palosaari8d44aee2014-12-02 11:23:49 -0300930{
931 struct dvb_usb_device *d = adap_to_d(adap);
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300932 struct rtl28xxu_dev *dev = d_to_priv(d);
Antti Palosaari8d44aee2014-12-02 11:23:49 -0300933 struct i2c_client *client;
934
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300935 dev_dbg(&d->intf->dev, "\n");
Antti Palosaari8d44aee2014-12-02 11:23:49 -0300936
937 /* remove I2C slave demod */
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300938 client = dev->i2c_client_slave_demod;
Antti Palosaari8d44aee2014-12-02 11:23:49 -0300939 if (client) {
940 module_put(client->dev.driver->owner);
941 i2c_unregister_device(client);
942 }
943
944 /* remove I2C demod */
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300945 client = dev->i2c_client_demod;
Antti Palosaari8d44aee2014-12-02 11:23:49 -0300946 if (client) {
947 module_put(client->dev.driver->owner);
948 i2c_unregister_device(client);
949 }
950
951 return 0;
952}
953
Antti Palosaari831e0b72011-07-08 23:36:07 -0300954static struct qt1010_config rtl28xxu_qt1010_config = {
955 .i2c_address = 0x62, /* 0xc4 */
956};
957
958static struct mt2060_config rtl28xxu_mt2060_config = {
959 .i2c_address = 0x60, /* 0xc0 */
960 .clock_out = 0,
961};
962
963static struct mxl5005s_config rtl28xxu_mxl5005s_config = {
964 .i2c_address = 0x63, /* 0xc6 */
965 .if_freq = IF_FREQ_4570000HZ,
966 .xtal_freq = CRYSTAL_FREQ_16000000HZ,
967 .agc_mode = MXL_SINGLE_AGC,
968 .tracking_filter = MXL_TF_C_H,
969 .rssi_enable = MXL_RSSI_ENABLE,
970 .cap_select = MXL_CAP_SEL_ENABLE,
971 .div_out = MXL_DIV_OUT_4,
972 .clock_out = MXL_CLOCK_OUT_DISABLE,
973 .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
974 .top = MXL5005S_TOP_25P2,
975 .mod_mode = MXL_DIGITAL_MODE,
976 .if_mode = MXL_ZERO_IF,
977 .AgcMasterByte = 0x00,
978};
979
Antti Palosaarib5cbaa42011-08-04 13:26:10 -0300980static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap)
Antti Palosaari831e0b72011-07-08 23:36:07 -0300981{
982 int ret;
Antti Palosaaric01a3592012-08-12 22:27:07 -0300983 struct dvb_usb_device *d = adap_to_d(adap);
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300984 struct rtl28xxu_dev *dev = d_to_priv(d);
Antti Palosaari9935eea2012-01-21 22:26:52 -0300985 struct dvb_frontend *fe;
Antti Palosaari831e0b72011-07-08 23:36:07 -0300986
Antti Palosaari5ba4ca12014-12-21 11:25:57 -0300987 dev_dbg(&d->intf->dev, "\n");
Antti Palosaari831e0b72011-07-08 23:36:07 -0300988
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300989 switch (dev->tuner) {
Antti Palosaari831e0b72011-07-08 23:36:07 -0300990 case TUNER_RTL2830_QT1010:
Antti Palosaaric01a3592012-08-12 22:27:07 -0300991 fe = dvb_attach(qt1010_attach, adap->fe[0],
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300992 dev->demod_i2c_adapter,
Antti Palosaaric0ceac92014-12-07 22:02:23 -0300993 &rtl28xxu_qt1010_config);
Antti Palosaari831e0b72011-07-08 23:36:07 -0300994 break;
995 case TUNER_RTL2830_MT2060:
Antti Palosaaric01a3592012-08-12 22:27:07 -0300996 fe = dvb_attach(mt2060_attach, adap->fe[0],
Antti Palosaari9a02e8f2014-12-18 08:05:23 -0300997 dev->demod_i2c_adapter,
Antti Palosaaric0ceac92014-12-07 22:02:23 -0300998 &rtl28xxu_mt2060_config, 1220);
Antti Palosaari831e0b72011-07-08 23:36:07 -0300999 break;
1000 case TUNER_RTL2830_MXL5005S:
Antti Palosaaric01a3592012-08-12 22:27:07 -03001001 fe = dvb_attach(mxl5005s_attach, adap->fe[0],
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001002 dev->demod_i2c_adapter,
Antti Palosaaric0ceac92014-12-07 22:02:23 -03001003 &rtl28xxu_mxl5005s_config);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001004 break;
1005 default:
Antti Palosaari9935eea2012-01-21 22:26:52 -03001006 fe = NULL;
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001007 dev_err(&d->intf->dev, "unknown tuner %d\n", dev->tuner);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001008 }
1009
1010 if (fe == NULL) {
1011 ret = -ENODEV;
1012 goto err;
1013 }
1014
1015 return 0;
1016err:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001017 dev_dbg(&d->intf->dev, "failed=%d\n", ret);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001018 return ret;
1019}
1020
Antti Palosaari384df492012-09-08 22:07:25 -03001021static const struct fc2580_config rtl2832u_fc2580_config = {
1022 .i2c_addr = 0x56,
1023 .clock = 16384000,
1024};
1025
Antti Palosaari5be65722012-09-11 22:27:09 -03001026static struct tua9001_config rtl2832u_tua9001_config = {
1027 .i2c_addr = 0x60,
1028};
1029
Antti Palosaariad3a7582012-12-08 23:27:49 -03001030static const struct fc0012_config rtl2832u_fc0012_config = {
1031 .i2c_address = 0x63, /* 0xc6 >> 1 */
1032 .xtal_freq = FC_XTAL_28_8_MHZ,
1033};
1034
Mauro Carvalho Chehab6889ab22013-04-06 09:40:11 -03001035static const struct r820t_config rtl2832u_r820t_config = {
1036 .i2c_addr = 0x1a,
1037 .xtal = 28800000,
1038 .max_i2c_msg_len = 2,
1039 .rafael_chip = CHIP_R820T,
1040};
1041
Antti Palosaari8b4cac12013-10-30 00:45:38 -03001042static const struct r820t_config rtl2832u_r828d_config = {
1043 .i2c_addr = 0x3a,
1044 .xtal = 16000000,
1045 .max_i2c_msg_len = 2,
1046 .rafael_chip = CHIP_R828D,
1047};
1048
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001049static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
1050{
1051 int ret;
Antti Palosaaric01a3592012-08-12 22:27:07 -03001052 struct dvb_usb_device *d = adap_to_d(adap);
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001053 struct rtl28xxu_dev *dev = d_to_priv(d);
Antti Palosaari28fd31f2013-10-15 19:22:45 -03001054 struct dvb_frontend *fe = NULL;
1055 struct i2c_board_info info;
1056 struct i2c_client *client;
Antti Palosaaria2f7f222014-12-16 10:50:54 -03001057 struct v4l2_subdev *subdev = NULL;
Mauro Carvalho Chehabe181b1f2015-02-03 16:36:28 -02001058 struct platform_device *pdev;
1059 struct rtl2832_sdr_platform_data pdata;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001060
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001061 dev_dbg(&d->intf->dev, "\n");
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001062
Antti Palosaari28fd31f2013-10-15 19:22:45 -03001063 memset(&info, 0, sizeof(struct i2c_board_info));
Mauro Carvalho Chehabe181b1f2015-02-03 16:36:28 -02001064 memset(&pdata, 0, sizeof(pdata));
Antti Palosaari28fd31f2013-10-15 19:22:45 -03001065
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001066 switch (dev->tuner) {
Thomas Mair5cf66312012-05-18 14:47:41 -03001067 case TUNER_RTL2832_FC0012:
Antti Palosaaric01a3592012-08-12 22:27:07 -03001068 fe = dvb_attach(fc0012_attach, adap->fe[0],
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001069 dev->demod_i2c_adapter, &rtl2832u_fc0012_config);
Thomas Mair5cf66312012-05-18 14:47:41 -03001070
1071 /* since fc0012 includs reading the signal strength delegate
1072 * that to the tuner driver */
Antti Palosaaric01a3592012-08-12 22:27:07 -03001073 adap->fe[0]->ops.read_signal_strength =
1074 adap->fe[0]->ops.tuner_ops.get_rf_strength;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001075 break;
Thomas Mair5cf66312012-05-18 14:47:41 -03001076 case TUNER_RTL2832_FC0013:
Antti Palosaaric01a3592012-08-12 22:27:07 -03001077 fe = dvb_attach(fc0013_attach, adap->fe[0],
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001078 dev->demod_i2c_adapter, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);
Thomas Mair5cf66312012-05-18 14:47:41 -03001079
1080 /* fc0013 also supports signal strength reading */
Antti Palosaaric01a3592012-08-12 22:27:07 -03001081 adap->fe[0]->ops.read_signal_strength =
1082 adap->fe[0]->ops.tuner_ops.get_rf_strength;
Antti Palosaari55cdb7d2014-02-03 23:07:21 -03001083 break;
Antti Palosaari28fd31f2013-10-15 19:22:45 -03001084 case TUNER_RTL2832_E4000: {
1085 struct e4000_config e4000_config = {
1086 .fe = adap->fe[0],
1087 .clock = 28800000,
1088 };
1089
1090 strlcpy(info.type, "e4000", I2C_NAME_SIZE);
1091 info.addr = 0x64;
1092 info.platform_data = &e4000_config;
1093
1094 request_module(info.type);
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001095 client = i2c_new_device(dev->demod_i2c_adapter, &info);
Antti Palosaari28fd31f2013-10-15 19:22:45 -03001096 if (client == NULL || client->dev.driver == NULL)
1097 break;
1098
1099 if (!try_module_get(client->dev.driver->owner)) {
1100 i2c_unregister_device(client);
1101 break;
1102 }
1103
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001104 dev->i2c_client_tuner = client;
Antti Palosaaria2f7f222014-12-16 10:50:54 -03001105 subdev = i2c_get_clientdata(client);
Antti Palosaari28fd31f2013-10-15 19:22:45 -03001106 }
Antti Palosaari542f6a52012-09-01 21:09:22 -03001107 break;
Antti Palosaari384df492012-09-08 22:07:25 -03001108 case TUNER_RTL2832_FC2580:
Antti Palosaari164f3d22014-12-14 11:45:55 -03001109 fe = dvb_attach(fc2580_attach, adap->fe[0],
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001110 dev->demod_i2c_adapter,
Antti Palosaari384df492012-09-08 22:07:25 -03001111 &rtl2832u_fc2580_config);
1112 break;
Antti Palosaari5be65722012-09-11 22:27:09 -03001113 case TUNER_RTL2832_TUA9001:
1114 /* enable GPIO1 and GPIO4 as output */
Antti Palosaari670ef052014-12-23 14:32:35 -03001115 ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x12);
Antti Palosaari4005c1a2012-09-17 15:43:57 -03001116 if (ret)
Antti Palosaari5be65722012-09-11 22:27:09 -03001117 goto err;
1118
Antti Palosaari670ef052014-12-23 14:32:35 -03001119 ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x12, 0x12);
Antti Palosaari4005c1a2012-09-17 15:43:57 -03001120 if (ret)
Antti Palosaari5be65722012-09-11 22:27:09 -03001121 goto err;
1122
Antti Palosaari164f3d22014-12-14 11:45:55 -03001123 fe = dvb_attach(tua9001_attach, adap->fe[0],
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001124 dev->demod_i2c_adapter,
Antti Palosaari5be65722012-09-11 22:27:09 -03001125 &rtl2832u_tua9001_config);
1126 break;
Mauro Carvalho Chehab6889ab22013-04-06 09:40:11 -03001127 case TUNER_RTL2832_R820T:
Antti Palosaari164f3d22014-12-14 11:45:55 -03001128 fe = dvb_attach(r820t_attach, adap->fe[0],
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001129 dev->demod_i2c_adapter,
Mauro Carvalho Chehab6889ab22013-04-06 09:40:11 -03001130 &rtl2832u_r820t_config);
Mauro Carvalho Chehab9e30edd2013-04-07 18:57:15 -03001131
1132 /* Use tuner to get the signal strength */
1133 adap->fe[0]->ops.read_signal_strength =
1134 adap->fe[0]->ops.tuner_ops.get_rf_strength;
Mauro Carvalho Chehab6889ab22013-04-06 09:40:11 -03001135 break;
Antti Palosaari8b4cac12013-10-30 00:45:38 -03001136 case TUNER_RTL2832_R828D:
Antti Palosaari80f189a2013-12-01 13:44:23 -03001137 fe = dvb_attach(r820t_attach, adap->fe[0],
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001138 dev->demod_i2c_adapter,
Antti Palosaari8b4cac12013-10-30 00:45:38 -03001139 &rtl2832u_r828d_config);
Antti Palosaari8b4cac12013-10-30 00:45:38 -03001140 adap->fe[0]->ops.read_signal_strength =
1141 adap->fe[0]->ops.tuner_ops.get_rf_strength;
Antti Palosaari80f189a2013-12-01 13:44:23 -03001142
1143 if (adap->fe[1]) {
1144 fe = dvb_attach(r820t_attach, adap->fe[1],
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001145 dev->demod_i2c_adapter,
Antti Palosaari80f189a2013-12-01 13:44:23 -03001146 &rtl2832u_r828d_config);
1147 adap->fe[1]->ops.read_signal_strength =
1148 adap->fe[1]->ops.tuner_ops.get_rf_strength;
1149 }
Antti Palosaari8b4cac12013-10-30 00:45:38 -03001150 break;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001151 default:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001152 dev_err(&d->intf->dev, "unknown tuner %d\n", dev->tuner);
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001153 }
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001154 if (fe == NULL && dev->i2c_client_tuner == NULL) {
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001155 ret = -ENODEV;
1156 goto err;
1157 }
1158
Antti Palosaaria2f7f222014-12-16 10:50:54 -03001159 /* register SDR */
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001160 switch (dev->tuner) {
Antti Palosaaria2f7f222014-12-16 10:50:54 -03001161 case TUNER_RTL2832_FC0012:
1162 case TUNER_RTL2832_FC0013:
1163 case TUNER_RTL2832_E4000:
1164 case TUNER_RTL2832_R820T:
1165 case TUNER_RTL2832_R828D:
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001166 pdata.clk = dev->rtl2832_platform_data.clk;
1167 pdata.tuner = dev->tuner;
1168 pdata.i2c_client = dev->i2c_client_demod;
1169 pdata.bulk_read = dev->rtl2832_platform_data.bulk_read;
1170 pdata.bulk_write = dev->rtl2832_platform_data.bulk_write;
1171 pdata.update_bits = dev->rtl2832_platform_data.update_bits;
Antti Palosaaria2f7f222014-12-16 10:50:54 -03001172 pdata.dvb_frontend = adap->fe[0];
1173 pdata.dvb_usb_device = d;
1174 pdata.v4l2_subdev = subdev;
1175
1176 request_module("%s", "rtl2832_sdr");
Antti Palosaari6a53fa22014-12-17 08:16:10 -03001177 pdev = platform_device_register_data(&d->intf->dev,
Antti Palosaaria2f7f222014-12-16 10:50:54 -03001178 "rtl2832_sdr",
1179 PLATFORM_DEVID_AUTO,
1180 &pdata, sizeof(pdata));
1181 if (pdev == NULL || pdev->dev.driver == NULL)
1182 break;
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001183 dev->platform_device_sdr = pdev;
Antti Palosaaria2f7f222014-12-16 10:50:54 -03001184 break;
1185 default:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001186 dev_dbg(&d->intf->dev, "no SDR for tuner=%d\n", dev->tuner);
Antti Palosaaria2f7f222014-12-16 10:50:54 -03001187 }
1188
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001189 return 0;
1190err:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001191 dev_dbg(&d->intf->dev, "failed=%d\n", ret);
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001192 return ret;
1193}
1194
Antti Palosaaride701f02014-12-23 14:09:13 -03001195static int rtl28xxu_tuner_attach(struct dvb_usb_adapter *adap)
1196{
1197 struct rtl28xxu_dev *dev = adap_to_priv(adap);
1198
1199 if (dev->chip_id == CHIP_ID_RTL2831U)
1200 return rtl2831u_tuner_attach(adap);
1201 else
1202 return rtl2832u_tuner_attach(adap);
1203}
1204
1205static int rtl28xxu_tuner_detach(struct dvb_usb_adapter *adap)
Antti Palosaari8d44aee2014-12-02 11:23:49 -03001206{
1207 struct dvb_usb_device *d = adap_to_d(adap);
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001208 struct rtl28xxu_dev *dev = d_to_priv(d);
Antti Palosaari8d44aee2014-12-02 11:23:49 -03001209 struct i2c_client *client;
Antti Palosaaria2f7f222014-12-16 10:50:54 -03001210 struct platform_device *pdev;
Antti Palosaari8d44aee2014-12-02 11:23:49 -03001211
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001212 dev_dbg(&d->intf->dev, "\n");
Antti Palosaari8d44aee2014-12-02 11:23:49 -03001213
Antti Palosaaria2f7f222014-12-16 10:50:54 -03001214 /* remove platform SDR */
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001215 pdev = dev->platform_device_sdr;
Antti Palosaari6a53fa22014-12-17 08:16:10 -03001216 if (pdev)
Antti Palosaaria2f7f222014-12-16 10:50:54 -03001217 platform_device_unregister(pdev);
Antti Palosaaria2f7f222014-12-16 10:50:54 -03001218
Antti Palosaari8d44aee2014-12-02 11:23:49 -03001219 /* remove I2C tuner */
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001220 client = dev->i2c_client_tuner;
Antti Palosaari8d44aee2014-12-02 11:23:49 -03001221 if (client) {
1222 module_put(client->dev.driver->owner);
1223 i2c_unregister_device(client);
1224 }
1225
1226 return 0;
1227}
1228
Antti Palosaaric01a3592012-08-12 22:27:07 -03001229static int rtl28xxu_init(struct dvb_usb_device *d)
1230{
1231 int ret;
1232 u8 val;
1233
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001234 dev_dbg(&d->intf->dev, "\n");
Antti Palosaaric01a3592012-08-12 22:27:07 -03001235
1236 /* init USB endpoints */
Antti Palosaari670ef052014-12-23 14:32:35 -03001237 ret = rtl28xxu_rd_reg(d, USB_SYSCTL_0, &val);
Antti Palosaaric01a3592012-08-12 22:27:07 -03001238 if (ret)
1239 goto err;
1240
1241 /* enable DMA and Full Packet Mode*/
1242 val |= 0x09;
Antti Palosaari670ef052014-12-23 14:32:35 -03001243 ret = rtl28xxu_wr_reg(d, USB_SYSCTL_0, val);
Antti Palosaaric01a3592012-08-12 22:27:07 -03001244 if (ret)
1245 goto err;
1246
1247 /* set EPA maximum packet size to 0x0200 */
Antti Palosaari670ef052014-12-23 14:32:35 -03001248 ret = rtl28xxu_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4);
Antti Palosaaric01a3592012-08-12 22:27:07 -03001249 if (ret)
1250 goto err;
1251
1252 /* change EPA FIFO length */
Antti Palosaari670ef052014-12-23 14:32:35 -03001253 ret = rtl28xxu_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4);
Antti Palosaaric01a3592012-08-12 22:27:07 -03001254 if (ret)
1255 goto err;
1256
1257 return ret;
1258err:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001259 dev_dbg(&d->intf->dev, "failed=%d\n", ret);
Antti Palosaaric01a3592012-08-12 22:27:07 -03001260 return ret;
1261}
1262
Thomas Mair5cf66312012-05-18 14:47:41 -03001263static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff)
Antti Palosaari831e0b72011-07-08 23:36:07 -03001264{
1265 int ret;
Antti Palosaari8b036632012-09-01 09:54:43 -03001266 u8 gpio, sys0, epa_ctl[2];
Antti Palosaari831e0b72011-07-08 23:36:07 -03001267
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001268 dev_dbg(&d->intf->dev, "onoff=%d\n", onoff);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001269
1270 /* demod adc */
Antti Palosaari670ef052014-12-23 14:32:35 -03001271 ret = rtl28xxu_rd_reg(d, SYS_SYS0, &sys0);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001272 if (ret)
1273 goto err;
1274
1275 /* tuner power, read GPIOs */
Antti Palosaari670ef052014-12-23 14:32:35 -03001276 ret = rtl28xxu_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001277 if (ret)
1278 goto err;
1279
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001280 dev_dbg(&d->intf->dev, "RD SYS0=%02x GPIO_OUT_VAL=%02x\n", sys0, gpio);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001281
1282 if (onoff) {
1283 gpio |= 0x01; /* GPIO0 = 1 */
1284 gpio &= (~0x10); /* GPIO4 = 0 */
Antti Palosaari991452a2012-08-12 22:27:08 -03001285 gpio |= 0x04; /* GPIO2 = 1, LED on */
Antti Palosaari831e0b72011-07-08 23:36:07 -03001286 sys0 = sys0 & 0x0f;
1287 sys0 |= 0xe0;
Antti Palosaari8b036632012-09-01 09:54:43 -03001288 epa_ctl[0] = 0x00; /* clear stall */
1289 epa_ctl[1] = 0x00; /* clear reset */
Antti Palosaari831e0b72011-07-08 23:36:07 -03001290 } else {
Antti Palosaari831e0b72011-07-08 23:36:07 -03001291 gpio &= (~0x01); /* GPIO0 = 0 */
1292 gpio |= 0x10; /* GPIO4 = 1 */
Antti Palosaari991452a2012-08-12 22:27:08 -03001293 gpio &= (~0x04); /* GPIO2 = 1, LED off */
Antti Palosaari831e0b72011-07-08 23:36:07 -03001294 sys0 = sys0 & (~0xc0);
Antti Palosaari8b036632012-09-01 09:54:43 -03001295 epa_ctl[0] = 0x10; /* set stall */
1296 epa_ctl[1] = 0x02; /* set reset */
Antti Palosaari831e0b72011-07-08 23:36:07 -03001297 }
1298
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001299 dev_dbg(&d->intf->dev, "WR SYS0=%02x GPIO_OUT_VAL=%02x\n", sys0, gpio);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001300
1301 /* demod adc */
Antti Palosaari670ef052014-12-23 14:32:35 -03001302 ret = rtl28xxu_wr_reg(d, SYS_SYS0, sys0);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001303 if (ret)
1304 goto err;
1305
1306 /* tuner power, write GPIOs */
Antti Palosaari670ef052014-12-23 14:32:35 -03001307 ret = rtl28xxu_wr_reg(d, SYS_GPIO_OUT_VAL, gpio);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001308 if (ret)
1309 goto err;
1310
Antti Palosaari8b036632012-09-01 09:54:43 -03001311 /* streaming EP: stall & reset */
Antti Palosaari670ef052014-12-23 14:32:35 -03001312 ret = rtl28xxu_wr_regs(d, USB_EPA_CTL, epa_ctl, 2);
Antti Palosaari8b036632012-09-01 09:54:43 -03001313 if (ret)
1314 goto err;
1315
1316 if (onoff)
1317 usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x81));
1318
Antti Palosaari831e0b72011-07-08 23:36:07 -03001319 return ret;
1320err:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001321 dev_dbg(&d->intf->dev, "failed=%d\n", ret);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001322 return ret;
1323}
1324
Thomas Mair5cf66312012-05-18 14:47:41 -03001325static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff)
1326{
1327 int ret;
Thomas Mair5cf66312012-05-18 14:47:41 -03001328
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001329 dev_dbg(&d->intf->dev, "onoff=%d\n", onoff);
Thomas Mair5cf66312012-05-18 14:47:41 -03001330
1331 if (onoff) {
Antti Palosaari526ca8d2013-06-04 18:26:54 -03001332 /* GPIO3=1, GPIO4=0 */
Antti Palosaari670ef052014-12-23 14:32:35 -03001333 ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x08, 0x18);
Thomas Mair5cf66312012-05-18 14:47:41 -03001334 if (ret)
1335 goto err;
1336
Antti Palosaari526ca8d2013-06-04 18:26:54 -03001337 /* suspend? */
Antti Palosaari670ef052014-12-23 14:32:35 -03001338 ret = rtl28xxu_wr_reg_mask(d, SYS_DEMOD_CTL1, 0x00, 0x10);
Thomas Mair5cf66312012-05-18 14:47:41 -03001339 if (ret)
1340 goto err;
1341
Antti Palosaari526ca8d2013-06-04 18:26:54 -03001342 /* enable PLL */
Antti Palosaari670ef052014-12-23 14:32:35 -03001343 ret = rtl28xxu_wr_reg_mask(d, SYS_DEMOD_CTL, 0x80, 0x80);
Thomas Mair5cf66312012-05-18 14:47:41 -03001344 if (ret)
1345 goto err;
1346
Antti Palosaari526ca8d2013-06-04 18:26:54 -03001347 /* disable reset */
Antti Palosaari670ef052014-12-23 14:32:35 -03001348 ret = rtl28xxu_wr_reg_mask(d, SYS_DEMOD_CTL, 0x20, 0x20);
Thomas Mair5cf66312012-05-18 14:47:41 -03001349 if (ret)
1350 goto err;
1351
Antti Palosaari8b036632012-09-01 09:54:43 -03001352 /* streaming EP: clear stall & reset */
Antti Palosaari670ef052014-12-23 14:32:35 -03001353 ret = rtl28xxu_wr_regs(d, USB_EPA_CTL, "\x00\x00", 2);
Antti Palosaari8b036632012-09-01 09:54:43 -03001354 if (ret)
1355 goto err;
1356
1357 ret = usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x81));
1358 if (ret)
1359 goto err;
Thomas Mair5cf66312012-05-18 14:47:41 -03001360 } else {
Antti Palosaari526ca8d2013-06-04 18:26:54 -03001361 /* GPIO4=1 */
Antti Palosaari670ef052014-12-23 14:32:35 -03001362 ret = rtl28xxu_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x10, 0x10);
Thomas Mair5cf66312012-05-18 14:47:41 -03001363 if (ret)
1364 goto err;
1365
Antti Palosaari526ca8d2013-06-04 18:26:54 -03001366 /* disable PLL */
Antti Palosaari670ef052014-12-23 14:32:35 -03001367 ret = rtl28xxu_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x80);
Thomas Mair5cf66312012-05-18 14:47:41 -03001368 if (ret)
1369 goto err;
1370
Antti Palosaari8b036632012-09-01 09:54:43 -03001371 /* streaming EP: set stall & reset */
Antti Palosaari670ef052014-12-23 14:32:35 -03001372 ret = rtl28xxu_wr_regs(d, USB_EPA_CTL, "\x10\x02", 2);
Antti Palosaari8b036632012-09-01 09:54:43 -03001373 if (ret)
1374 goto err;
Thomas Mair5cf66312012-05-18 14:47:41 -03001375 }
1376
1377 return ret;
1378err:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001379 dev_dbg(&d->intf->dev, "failed=%d\n", ret);
Thomas Mair5cf66312012-05-18 14:47:41 -03001380 return ret;
1381}
1382
Antti Palosaaride701f02014-12-23 14:09:13 -03001383static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff)
1384{
1385 struct rtl28xxu_dev *dev = d_to_priv(d);
1386
1387 if (dev->chip_id == CHIP_ID_RTL2831U)
1388 return rtl2831u_power_ctrl(d, onoff);
1389 else
1390 return rtl2832u_power_ctrl(d, onoff);
1391}
1392
1393static int rtl28xxu_frontend_ctrl(struct dvb_frontend *fe, int onoff)
Antti Palosaari698f6262014-09-27 01:22:45 -03001394{
1395 struct dvb_usb_device *d = fe_to_d(fe);
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001396 struct rtl28xxu_dev *dev = fe_to_priv(fe);
1397 struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data;
Antti Palosaari698f6262014-09-27 01:22:45 -03001398 int ret;
1399 u8 val;
1400
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001401 dev_dbg(&d->intf->dev, "fe=%d onoff=%d\n", fe->id, onoff);
Antti Palosaari698f6262014-09-27 01:22:45 -03001402
Antti Palosaaride701f02014-12-23 14:09:13 -03001403 if (dev->chip_id == CHIP_ID_RTL2831U)
1404 return 0;
1405
Antti Palosaari698f6262014-09-27 01:22:45 -03001406 /* control internal demod ADC */
1407 if (fe->id == 0 && onoff)
1408 val = 0x48; /* enable ADC */
1409 else
1410 val = 0x00; /* disable ADC */
1411
Antti Palosaari670ef052014-12-23 14:32:35 -03001412 ret = rtl28xxu_wr_reg_mask(d, SYS_DEMOD_CTL, val, 0x48);
Antti Palosaari698f6262014-09-27 01:22:45 -03001413 if (ret)
1414 goto err;
1415
Antti Palosaari80f189a2013-12-01 13:44:23 -03001416 /* bypass slave demod TS through master demod */
1417 if (fe->id == 1 && onoff) {
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001418 ret = pdata->enable_slave_ts(dev->i2c_client_demod);
Antti Palosaari80f189a2013-12-01 13:44:23 -03001419 if (ret)
1420 goto err;
1421 }
1422
Antti Palosaari698f6262014-09-27 01:22:45 -03001423 return 0;
1424err:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001425 dev_dbg(&d->intf->dev, "failed=%d\n", ret);
Antti Palosaari698f6262014-09-27 01:22:45 -03001426 return ret;
1427}
1428
Antti Palosaari37b44a02013-01-04 15:21:26 -03001429#if IS_ENABLED(CONFIG_RC_CORE)
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001430static int rtl2831u_rc_query(struct dvb_usb_device *d)
Antti Palosaari831e0b72011-07-08 23:36:07 -03001431{
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001432 int ret, i;
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001433 struct rtl28xxu_dev *dev = d->priv;
Antti Palosaari831e0b72011-07-08 23:36:07 -03001434 u8 buf[5];
1435 u32 rc_code;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001436 struct rtl28xxu_reg_val rc_nec_tab[] = {
1437 { 0x3033, 0x80 },
1438 { 0x3020, 0x43 },
1439 { 0x3021, 0x16 },
1440 { 0x3022, 0x16 },
1441 { 0x3023, 0x5a },
1442 { 0x3024, 0x2d },
1443 { 0x3025, 0x16 },
1444 { 0x3026, 0x01 },
1445 { 0x3028, 0xb0 },
1446 { 0x3029, 0x04 },
1447 { 0x302c, 0x88 },
1448 { 0x302e, 0x13 },
1449 { 0x3030, 0xdf },
1450 { 0x3031, 0x05 },
1451 };
1452
1453 /* init remote controller */
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001454 if (!dev->rc_active) {
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001455 for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) {
Antti Palosaari670ef052014-12-23 14:32:35 -03001456 ret = rtl28xxu_wr_reg(d, rc_nec_tab[i].reg,
Antti Palosaari9935eea2012-01-21 22:26:52 -03001457 rc_nec_tab[i].val);
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001458 if (ret)
1459 goto err;
1460 }
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001461 dev->rc_active = true;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001462 }
Antti Palosaari831e0b72011-07-08 23:36:07 -03001463
Antti Palosaari670ef052014-12-23 14:32:35 -03001464 ret = rtl28xxu_rd_regs(d, SYS_IRRC_RP, buf, 5);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001465 if (ret)
1466 goto err;
1467
1468 if (buf[4] & 0x01) {
1469 if (buf[2] == (u8) ~buf[3]) {
1470 if (buf[0] == (u8) ~buf[1]) {
1471 /* NEC standard (16 bit) */
David Härdeman120703f2014-04-03 20:31:30 -03001472 rc_code = RC_SCANCODE_NEC(buf[0], buf[2]);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001473 } else {
1474 /* NEC extended (24 bit) */
David Härdeman120703f2014-04-03 20:31:30 -03001475 rc_code = RC_SCANCODE_NECX(buf[0] << 8 | buf[1],
1476 buf[2]);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001477 }
1478 } else {
1479 /* NEC full (32 bit) */
David Härdeman120703f2014-04-03 20:31:30 -03001480 rc_code = RC_SCANCODE_NEC32(buf[0] << 24 | buf[1] << 16 |
1481 buf[2] << 8 | buf[3]);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001482 }
1483
David Härdeman120703f2014-04-03 20:31:30 -03001484 rc_keydown(d->rc_dev, RC_TYPE_NEC, rc_code, 0);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001485
Antti Palosaari670ef052014-12-23 14:32:35 -03001486 ret = rtl28xxu_wr_reg(d, SYS_IRRC_SR, 1);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001487 if (ret)
1488 goto err;
1489
1490 /* repeated intentionally to avoid extra keypress */
Antti Palosaari670ef052014-12-23 14:32:35 -03001491 ret = rtl28xxu_wr_reg(d, SYS_IRRC_SR, 1);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001492 if (ret)
1493 goto err;
1494 }
1495
1496 return ret;
1497err:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001498 dev_dbg(&d->intf->dev, "failed=%d\n", ret);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001499 return ret;
1500}
1501
Antti Palosaaric01a3592012-08-12 22:27:07 -03001502static int rtl2831u_get_rc_config(struct dvb_usb_device *d,
1503 struct dvb_usb_rc *rc)
1504{
1505 rc->map_name = RC_MAP_EMPTY;
David Härdemanc003ab12012-10-11 19:11:54 -03001506 rc->allowed_protos = RC_BIT_NEC;
Antti Palosaaric01a3592012-08-12 22:27:07 -03001507 rc->query = rtl2831u_rc_query;
1508 rc->interval = 400;
1509
1510 return 0;
1511}
1512
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001513static int rtl2832u_rc_query(struct dvb_usb_device *d)
1514{
Antti Palosaarif39fac32013-06-04 09:17:03 -03001515 int ret, i, len;
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001516 struct rtl28xxu_dev *dev = d->priv;
Antti Palosaarif39fac32013-06-04 09:17:03 -03001517 struct ir_raw_event ev;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001518 u8 buf[128];
Antti Palosaarif39fac32013-06-04 09:17:03 -03001519 static const struct rtl28xxu_reg_val_mask refresh_tab[] = {
1520 {IR_RX_IF, 0x03, 0xff},
1521 {IR_RX_BUF_CTRL, 0x80, 0xff},
1522 {IR_RX_CTRL, 0x80, 0xff},
1523 };
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001524
1525 /* init remote controller */
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001526 if (!dev->rc_active) {
Antti Palosaarif39fac32013-06-04 09:17:03 -03001527 static const struct rtl28xxu_reg_val_mask init_tab[] = {
1528 {SYS_DEMOD_CTL1, 0x00, 0x04},
1529 {SYS_DEMOD_CTL1, 0x00, 0x08},
1530 {USB_CTRL, 0x20, 0x20},
1531 {SYS_GPIO_DIR, 0x00, 0x08},
1532 {SYS_GPIO_OUT_EN, 0x08, 0x08},
1533 {SYS_GPIO_OUT_VAL, 0x08, 0x08},
1534 {IR_MAX_DURATION0, 0xd0, 0xff},
1535 {IR_MAX_DURATION1, 0x07, 0xff},
1536 {IR_IDLE_LEN0, 0xc0, 0xff},
1537 {IR_IDLE_LEN1, 0x00, 0xff},
1538 {IR_GLITCH_LEN, 0x03, 0xff},
1539 {IR_RX_CLK, 0x09, 0xff},
1540 {IR_RX_CFG, 0x1c, 0xff},
1541 {IR_MAX_H_TOL_LEN, 0x1e, 0xff},
1542 {IR_MAX_L_TOL_LEN, 0x1e, 0xff},
1543 {IR_RX_CTRL, 0x80, 0xff},
1544 };
1545
1546 for (i = 0; i < ARRAY_SIZE(init_tab); i++) {
Antti Palosaari670ef052014-12-23 14:32:35 -03001547 ret = rtl28xxu_wr_reg_mask(d, init_tab[i].reg,
Antti Palosaarif39fac32013-06-04 09:17:03 -03001548 init_tab[i].val, init_tab[i].mask);
Rodrigo Tartajo1e414132013-04-20 20:02:12 -03001549 if (ret)
1550 goto err;
1551 }
Antti Palosaarif39fac32013-06-04 09:17:03 -03001552
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001553 dev->rc_active = true;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001554 }
1555
Antti Palosaari670ef052014-12-23 14:32:35 -03001556 ret = rtl28xxu_rd_reg(d, IR_RX_IF, &buf[0]);
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001557 if (ret)
1558 goto err;
1559
1560 if (buf[0] != 0x83)
Antti Palosaarif39fac32013-06-04 09:17:03 -03001561 goto exit;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001562
Antti Palosaari670ef052014-12-23 14:32:35 -03001563 ret = rtl28xxu_rd_reg(d, IR_RX_BC, &buf[0]);
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001564 if (ret)
1565 goto err;
1566
1567 len = buf[0];
Antti Palosaarif39fac32013-06-04 09:17:03 -03001568
1569 /* read raw code from hw */
Antti Palosaari670ef052014-12-23 14:32:35 -03001570 ret = rtl28xxu_rd_regs(d, IR_RX_BUF, buf, len);
Antti Palosaarif39fac32013-06-04 09:17:03 -03001571 if (ret)
1572 goto err;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001573
Antti Palosaarif39fac32013-06-04 09:17:03 -03001574 /* let hw receive new code */
1575 for (i = 0; i < ARRAY_SIZE(refresh_tab); i++) {
Antti Palosaari670ef052014-12-23 14:32:35 -03001576 ret = rtl28xxu_wr_reg_mask(d, refresh_tab[i].reg,
Antti Palosaarif39fac32013-06-04 09:17:03 -03001577 refresh_tab[i].val, refresh_tab[i].mask);
Rodrigo Tartajo1e414132013-04-20 20:02:12 -03001578 if (ret)
1579 goto err;
1580 }
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001581
Antti Palosaarif39fac32013-06-04 09:17:03 -03001582 /* pass data to Kernel IR decoder */
1583 init_ir_raw_event(&ev);
1584
1585 for (i = 0; i < len; i++) {
1586 ev.pulse = buf[i] >> 7;
1587 ev.duration = 50800 * (buf[i] & 0x7f);
1588 ir_raw_event_store_with_filter(d->rc_dev, &ev);
1589 }
1590
1591 /* 'flush' ir_raw_event_store_with_filter() */
1592 ir_raw_event_set_idle(d->rc_dev, true);
1593 ir_raw_event_handle(d->rc_dev);
1594exit:
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001595 return ret;
1596err:
Antti Palosaari5ba4ca12014-12-21 11:25:57 -03001597 dev_dbg(&d->intf->dev, "failed=%d\n", ret);
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001598 return ret;
1599}
1600
Antti Palosaaric01a3592012-08-12 22:27:07 -03001601static int rtl2832u_get_rc_config(struct dvb_usb_device *d,
1602 struct dvb_usb_rc *rc)
1603{
Antti Palosaari94b5fa62013-11-22 14:20:14 -03001604 /* disable IR interrupts in order to avoid SDR sample loss */
1605 if (rtl28xxu_disable_rc)
Antti Palosaari670ef052014-12-23 14:32:35 -03001606 return rtl28xxu_wr_reg(d, IR_RX_IE, 0x00);
Antti Palosaari94b5fa62013-11-22 14:20:14 -03001607
Antti Palosaarif39fac32013-06-04 09:17:03 -03001608 /* load empty to enable rc */
1609 if (!rc->map_name)
1610 rc->map_name = RC_MAP_EMPTY;
Rodrigo Tartajo1e414132013-04-20 20:02:12 -03001611 rc->allowed_protos = RC_BIT_ALL;
Antti Palosaarif39fac32013-06-04 09:17:03 -03001612 rc->driver_type = RC_DRIVER_IR_RAW;
Antti Palosaaric01a3592012-08-12 22:27:07 -03001613 rc->query = rtl2832u_rc_query;
1614 rc->interval = 400;
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001615
Antti Palosaaric01a3592012-08-12 22:27:07 -03001616 return 0;
1617}
Antti Palosaaride701f02014-12-23 14:09:13 -03001618
1619static int rtl28xxu_get_rc_config(struct dvb_usb_device *d,
1620 struct dvb_usb_rc *rc)
1621{
1622 struct rtl28xxu_dev *dev = d_to_priv(d);
1623
1624 if (dev->chip_id == CHIP_ID_RTL2831U)
1625 return rtl2831u_get_rc_config(d, rc);
1626 else
1627 return rtl2832u_get_rc_config(d, rc);
1628}
Antti Palosaaricedda372012-12-09 20:06:00 -03001629#else
Antti Palosaaride701f02014-12-23 14:09:13 -03001630#define rtl28xxu_get_rc_config NULL
Antti Palosaaricedda372012-12-09 20:06:00 -03001631#endif
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001632
Antti Palosaaride701f02014-12-23 14:09:13 -03001633static int rtl28xxu_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
Antti Palosaarid9bd3fa2014-12-09 16:10:14 -03001634{
Antti Palosaaride701f02014-12-23 14:09:13 -03001635 struct rtl28xxu_dev *dev = adap_to_priv(adap);
Antti Palosaarid9bd3fa2014-12-09 16:10:14 -03001636
Antti Palosaaride701f02014-12-23 14:09:13 -03001637 if (dev->chip_id == CHIP_ID_RTL2831U) {
1638 struct rtl2830_platform_data *pdata = &dev->rtl2830_platform_data;
1639
1640 return pdata->pid_filter_ctrl(adap->fe[0], onoff);
1641 } else {
1642 struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data;
1643
1644 return pdata->pid_filter_ctrl(adap->fe[0], onoff);
1645 }
Antti Palosaarid9bd3fa2014-12-09 16:10:14 -03001646}
1647
Antti Palosaaride701f02014-12-23 14:09:13 -03001648static int rtl28xxu_pid_filter(struct dvb_usb_adapter *adap, int index,
1649 u16 pid, int onoff)
Antti Palosaarie20b0cf2014-12-14 14:10:47 -03001650{
Antti Palosaaride701f02014-12-23 14:09:13 -03001651 struct rtl28xxu_dev *dev = adap_to_priv(adap);
Antti Palosaarie20b0cf2014-12-14 14:10:47 -03001652
Antti Palosaaride701f02014-12-23 14:09:13 -03001653 if (dev->chip_id == CHIP_ID_RTL2831U) {
1654 struct rtl2830_platform_data *pdata = &dev->rtl2830_platform_data;
Antti Palosaarie20b0cf2014-12-14 14:10:47 -03001655
Antti Palosaaride701f02014-12-23 14:09:13 -03001656 return pdata->pid_filter(adap->fe[0], index, pid, onoff);
1657 } else {
1658 struct rtl2832_platform_data *pdata = &dev->rtl2832_platform_data;
Antti Palosaarid9bd3fa2014-12-09 16:10:14 -03001659
Antti Palosaaride701f02014-12-23 14:09:13 -03001660 return pdata->pid_filter(adap->fe[0], index, pid, onoff);
1661 }
Antti Palosaarie20b0cf2014-12-14 14:10:47 -03001662}
1663
Antti Palosaari723abfd2014-12-23 14:21:10 -03001664static const struct dvb_usb_device_properties rtl28xxu_props = {
Antti Palosaaric01a3592012-08-12 22:27:07 -03001665 .driver_name = KBUILD_MODNAME,
1666 .owner = THIS_MODULE,
1667 .adapter_nr = adapter_nr,
Antti Palosaari9a02e8f2014-12-18 08:05:23 -03001668 .size_of_priv = sizeof(struct rtl28xxu_dev),
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001669
Antti Palosaarid0f232e2014-12-23 13:14:36 -03001670 .identify_state = rtl28xxu_identify_state,
Antti Palosaaride701f02014-12-23 14:09:13 -03001671 .power_ctrl = rtl28xxu_power_ctrl,
1672 .frontend_ctrl = rtl28xxu_frontend_ctrl,
Antti Palosaaric01a3592012-08-12 22:27:07 -03001673 .i2c_algo = &rtl28xxu_i2c_algo,
Antti Palosaaride701f02014-12-23 14:09:13 -03001674 .read_config = rtl28xxu_read_config,
1675 .frontend_attach = rtl28xxu_frontend_attach,
1676 .frontend_detach = rtl28xxu_frontend_detach,
1677 .tuner_attach = rtl28xxu_tuner_attach,
1678 .tuner_detach = rtl28xxu_tuner_detach,
Antti Palosaaric01a3592012-08-12 22:27:07 -03001679 .init = rtl28xxu_init,
Antti Palosaaride701f02014-12-23 14:09:13 -03001680 .get_rc_config = rtl28xxu_get_rc_config,
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001681
Antti Palosaaric01a3592012-08-12 22:27:07 -03001682 .num_adapters = 1,
1683 .adapter = {
1684 {
Antti Palosaarie20b0cf2014-12-14 14:10:47 -03001685 .caps = DVB_USB_ADAP_HAS_PID_FILTER |
1686 DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
1687
1688 .pid_filter_count = 32,
Antti Palosaaride701f02014-12-23 14:09:13 -03001689 .pid_filter_ctrl = rtl28xxu_pid_filter_ctrl,
1690 .pid_filter = rtl28xxu_pid_filter,
Antti Palosaarie20b0cf2014-12-14 14:10:47 -03001691
Antti Palosaaric01a3592012-08-12 22:27:07 -03001692 .stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512),
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001693 },
Antti Palosaarib5cbaa42011-08-04 13:26:10 -03001694 },
Antti Palosaari831e0b72011-07-08 23:36:07 -03001695};
1696
Antti Palosaaric01a3592012-08-12 22:27:07 -03001697static const struct usb_device_id rtl28xxu_id_table[] = {
Jan Vcelak60aa4c62014-02-26 15:33:40 -03001698 /* RTL2831U devices: */
Antti Palosaaric01a3592012-08-12 22:27:07 -03001699 { DVB_USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001700 &rtl28xxu_props, "Realtek RTL2831U reference design", NULL) },
Antti Palosaaric01a3592012-08-12 22:27:07 -03001701 { DVB_USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001702 &rtl28xxu_props, "Freecom USB2.0 DVB-T", NULL) },
Antti Palosaaric01a3592012-08-12 22:27:07 -03001703 { DVB_USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001704 &rtl28xxu_props, "Freecom USB2.0 DVB-T", NULL) },
Antti Palosaari831e0b72011-07-08 23:36:07 -03001705
Jan Vcelak60aa4c62014-02-26 15:33:40 -03001706 /* RTL2832U devices: */
Antti Palosaari254ee2e2012-09-18 10:27:05 -03001707 { DVB_USB_DEVICE(USB_VID_REALTEK, 0x2832,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001708 &rtl28xxu_props, "Realtek RTL2832U reference design", NULL) },
Antti Palosaari254ee2e2012-09-18 10:27:05 -03001709 { DVB_USB_DEVICE(USB_VID_REALTEK, 0x2838,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001710 &rtl28xxu_props, "Realtek RTL2832U reference design", NULL) },
Antti Palosaaric01a3592012-08-12 22:27:07 -03001711 { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001712 &rtl28xxu_props, "TerraTec Cinergy T Stick Black", RC_MAP_TERRATEC_SLIM) },
Antti Palosaaric01a3592012-08-12 22:27:07 -03001713 { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_DELOCK_USB2_DVBT,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001714 &rtl28xxu_props, "G-Tek Electronics Group Lifeview LV5TDLX DVB-T", NULL) },
Antti Palosaaric01a3592012-08-12 22:27:07 -03001715 { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001716 &rtl28xxu_props, "TerraTec NOXON DAB Stick", NULL) },
Juergen Locke9de0512012-11-13 14:09:28 -03001717 { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK_REV2,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001718 &rtl28xxu_props, "TerraTec NOXON DAB Stick (rev 2)", NULL) },
Till Dörgesa24bc322014-02-11 17:27:57 -03001719 { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK_REV3,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001720 &rtl28xxu_props, "TerraTec NOXON DAB Stick (rev 3)", NULL) },
Philipp Dreimann6d608052012-09-02 19:30:54 -03001721 { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_TREKSTOR_TERRES_2_0,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001722 &rtl28xxu_props, "Trekstor DVB-T Stick Terres 2.0", NULL) },
Antti Palosaaric2d246d12012-09-08 22:07:26 -03001723 { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1101,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001724 &rtl28xxu_props, "Dexatek DK DVB-T Dongle", NULL) },
Antti Palosaari3d8866d2012-09-20 18:34:50 -03001725 { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6680,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001726 &rtl28xxu_props, "DigitalNow Quad DVB-T Receiver", NULL) },
Robert Backhausd22d32e2013-12-13 09:59:10 -03001727 { DVB_USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_MINID,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001728 &rtl28xxu_props, "Leadtek Winfast DTV Dongle Mini D", NULL) },
Antti Palosaaria4f64402012-09-29 15:28:56 -03001729 { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d3,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001730 &rtl28xxu_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) },
Antti Palosaari08e57272012-11-06 16:03:35 -03001731 { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1102,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001732 &rtl28xxu_props, "Dexatek DK mini DVB-T Dongle", NULL) },
Andrew Karpow86163ad2012-11-06 20:01:16 -03001733 { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d7,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001734 &rtl28xxu_props, "TerraTec Cinergy T Stick+", NULL) },
Antti Palosaari3971e792012-12-16 11:47:07 -03001735 { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd3a8,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001736 &rtl28xxu_props, "ASUS My Cinema-U3100Mini Plus V2", NULL) },
Alexander Inyukhin78a5e702013-01-04 18:19:02 -03001737 { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd393,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001738 &rtl28xxu_props, "GIGABYTE U7300", NULL) },
Eddi De Pieri09f94082013-01-14 18:21:32 -03001739 { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1104,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001740 &rtl28xxu_props, "MSI DIGIVOX Micro HD", NULL) },
Alistair Buxtonb9e2aff2013-02-12 21:58:47 -03001741 { DVB_USB_DEVICE(USB_VID_COMPRO, 0x0620,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001742 &rtl28xxu_props, "Compro VideoMate U620F", NULL) },
Fabrizio Gazzatoe6a60d72013-02-15 18:54:54 -03001743 { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd394,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001744 &rtl28xxu_props, "MaxMedia HU394-T", NULL) },
Miroslav Šustek6c5a4062013-05-14 19:42:11 -03001745 { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a03,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001746 &rtl28xxu_props, "Leadtek WinFast DTV Dongle mini", NULL) },
Alessandro Micelic6be7522013-06-04 16:10:34 -03001747 { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_CPYTO_REDI_PC50A,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001748 &rtl28xxu_props, "Crypto ReDi PC 50 A", NULL) },
Jan Vcelakac298cc2014-02-26 15:33:39 -03001749 { DVB_USB_DEVICE(USB_VID_KYE, 0x707f,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001750 &rtl28xxu_props, "Genius TVGo DVB-T03", NULL) },
Brian Healy9ca24ae2014-05-04 18:43:39 -03001751 { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd395,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001752 &rtl28xxu_props, "Peak DVB-T USB", NULL) },
Alessandro Micelif27f5b02014-05-04 07:37:15 -03001753 { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20_RTL2832U,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001754 &rtl28xxu_props, "Sveon STV20", NULL) },
Sebastian89c5ff02014-06-12 03:22:45 -03001755 { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV21,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001756 &rtl28xxu_props, "Sveon STV21", NULL) },
Alessandro Miceli74a86272014-05-04 07:50:31 -03001757 { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV27,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001758 &rtl28xxu_props, "Sveon STV27", NULL) },
Antti Palosaari8fdd33b2013-10-30 02:33:42 -03001759
Jan Vcelak60aa4c62014-02-26 15:33:40 -03001760 /* RTL2832P devices: */
Antti Palosaari8fdd33b2013-10-30 02:33:42 -03001761 { DVB_USB_DEVICE(USB_VID_HANFTEK, 0x0131,
Antti Palosaari723abfd2014-12-23 14:21:10 -03001762 &rtl28xxu_props, "Astrometa DVB-T2", NULL) },
Antti Palosaaric01a3592012-08-12 22:27:07 -03001763 { }
1764};
1765MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001766
Antti Palosaaric01a3592012-08-12 22:27:07 -03001767static struct usb_driver rtl28xxu_usb_driver = {
1768 .name = KBUILD_MODNAME,
1769 .id_table = rtl28xxu_id_table,
1770 .probe = dvb_usbv2_probe,
1771 .disconnect = dvb_usbv2_disconnect,
1772 .suspend = dvb_usbv2_suspend,
1773 .resume = dvb_usbv2_resume,
Antti Palosaari78fa5902012-08-14 22:21:09 -03001774 .reset_resume = dvb_usbv2_reset_resume,
Antti Palosaaric01a3592012-08-12 22:27:07 -03001775 .no_dynamic_id = 1,
1776 .soft_unbind = 1,
Antti Palosaari831e0b72011-07-08 23:36:07 -03001777};
1778
Antti Palosaaric01a3592012-08-12 22:27:07 -03001779module_usb_driver(rtl28xxu_usb_driver);
Antti Palosaari831e0b72011-07-08 23:36:07 -03001780
1781MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver");
1782MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
Thomas Mair5cf66312012-05-18 14:47:41 -03001783MODULE_AUTHOR("Thomas Mair <thomas.mair86@googlemail.com>");
Antti Palosaari831e0b72011-07-08 23:36:07 -03001784MODULE_LICENSE("GPL");