]>
Commit | Line | Data |
---|---|---|
831e0b71 AP |
1 | /* |
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> | |
5cf6631e | 6 | * Copyright (C) 2012 Thomas Mair <thomas.mair86@googlemail.com> |
831e0b71 AP |
7 | * |
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 | ||
25 | #include "rtl2830.h" | |
5cf6631e | 26 | #include "rtl2832.h" |
831e0b71 AP |
27 | |
28 | #include "qt1010.h" | |
29 | #include "mt2060.h" | |
30 | #include "mxl5005s.h" | |
5cf6631e TM |
31 | #include "fc0012.h" |
32 | #include "fc0013.h" | |
542f6a52 | 33 | #include "e4000.h" |
384df49a | 34 | #include "fc2580.h" |
5be65721 | 35 | #include "tua9001.h" |
6889ab2a | 36 | #include "r820t.h" |
831e0b71 | 37 | |
831e0b71 AP |
38 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
39 | ||
40 | static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) | |
41 | { | |
42 | int ret; | |
43 | unsigned int pipe; | |
44 | u8 requesttype; | |
45 | u8 *buf; | |
46 | ||
47 | buf = kmalloc(req->size, GFP_KERNEL); | |
48 | if (!buf) { | |
49 | ret = -ENOMEM; | |
50 | goto err; | |
51 | } | |
52 | ||
53 | if (req->index & CMD_WR_FLAG) { | |
54 | /* write */ | |
55 | memcpy(buf, req->data, req->size); | |
56 | requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); | |
57 | pipe = usb_sndctrlpipe(d->udev, 0); | |
58 | } else { | |
59 | /* read */ | |
60 | requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); | |
61 | pipe = usb_rcvctrlpipe(d->udev, 0); | |
62 | } | |
63 | ||
64 | ret = usb_control_msg(d->udev, pipe, 0, requesttype, req->value, | |
9935eea5 | 65 | req->index, buf, req->size, 1000); |
d89b9369 AP |
66 | |
67 | dvb_usb_dbg_usb_control_msg(d->udev, 0, requesttype, req->value, | |
68 | req->index, buf, req->size); | |
69 | ||
9935eea5 AP |
70 | if (ret > 0) |
71 | ret = 0; | |
831e0b71 | 72 | |
831e0b71 AP |
73 | /* read request, copy returned data to return buf */ |
74 | if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) | |
75 | memcpy(req->data, buf, req->size); | |
76 | ||
77 | kfree(buf); | |
831e0b71 | 78 | |
9935eea5 AP |
79 | if (ret) |
80 | goto err; | |
81 | ||
82 | return ret; | |
831e0b71 | 83 | err: |
c01a3595 | 84 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
831e0b71 AP |
85 | return ret; |
86 | } | |
87 | ||
40a2d3c7 | 88 | static int rtl28xx_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) |
831e0b71 AP |
89 | { |
90 | struct rtl28xxu_req req; | |
91 | ||
92 | if (reg < 0x3000) | |
93 | req.index = CMD_USB_WR; | |
b5cbaa43 | 94 | else if (reg < 0x4000) |
831e0b71 | 95 | req.index = CMD_SYS_WR; |
b5cbaa43 AP |
96 | else |
97 | req.index = CMD_IR_WR; | |
831e0b71 AP |
98 | |
99 | req.value = reg; | |
100 | req.size = len; | |
101 | req.data = val; | |
102 | ||
103 | return rtl28xxu_ctrl_msg(d, &req); | |
104 | } | |
105 | ||
106 | static int rtl2831_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) | |
107 | { | |
108 | struct rtl28xxu_req req; | |
109 | ||
110 | if (reg < 0x3000) | |
111 | req.index = CMD_USB_RD; | |
b5cbaa43 | 112 | else if (reg < 0x4000) |
831e0b71 | 113 | req.index = CMD_SYS_RD; |
b5cbaa43 AP |
114 | else |
115 | req.index = CMD_IR_RD; | |
831e0b71 AP |
116 | |
117 | req.value = reg; | |
118 | req.size = len; | |
119 | req.data = val; | |
120 | ||
121 | return rtl28xxu_ctrl_msg(d, &req); | |
122 | } | |
123 | ||
40a2d3c7 | 124 | static int rtl28xx_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val) |
831e0b71 | 125 | { |
40a2d3c7 | 126 | return rtl28xx_wr_regs(d, reg, &val, 1); |
831e0b71 AP |
127 | } |
128 | ||
40a2d3c7 | 129 | static int rtl28xx_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val) |
831e0b71 AP |
130 | { |
131 | return rtl2831_rd_regs(d, reg, val, 1); | |
132 | } | |
133 | ||
4005c1a9 AP |
134 | static int rtl28xx_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val, |
135 | u8 mask) | |
136 | { | |
137 | int ret; | |
138 | u8 tmp; | |
139 | ||
140 | /* no need for read if whole reg is written */ | |
141 | if (mask != 0xff) { | |
142 | ret = rtl28xx_rd_reg(d, reg, &tmp); | |
143 | if (ret) | |
144 | return ret; | |
145 | ||
146 | val &= mask; | |
147 | tmp &= ~mask; | |
148 | val |= tmp; | |
149 | } | |
150 | ||
151 | return rtl28xx_wr_reg(d, reg, val); | |
152 | } | |
153 | ||
831e0b71 AP |
154 | /* I2C */ |
155 | static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |
156 | int num) | |
157 | { | |
158 | int ret; | |
159 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | |
34ec2933 | 160 | struct rtl28xxu_priv *priv = d->priv; |
831e0b71 AP |
161 | struct rtl28xxu_req req; |
162 | ||
163 | /* | |
164 | * It is not known which are real I2C bus xfer limits, but testing | |
165 | * with RTL2831U + MT2060 gives max RD 24 and max WR 22 bytes. | |
34ec2933 AP |
166 | * TODO: find out RTL2832U lens |
167 | */ | |
168 | ||
169 | /* | |
170 | * I2C adapter logic looks rather complicated due to fact it handles | |
171 | * three different access methods. Those methods are; | |
172 | * 1) integrated demod access | |
173 | * 2) old I2C access | |
174 | * 3) new I2C access | |
175 | * | |
176 | * Used method is selected in order 1, 2, 3. Method 3 can handle all | |
177 | * requests but there is two reasons why not use it always; | |
178 | * 1) It is most expensive, usually two USB messages are needed | |
179 | * 2) At least RTL2831U does not support it | |
180 | * | |
181 | * Method 3 is needed in case of I2C write+read (typical register read) | |
182 | * where write is more than one byte. | |
831e0b71 AP |
183 | */ |
184 | ||
185 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | |
186 | return -EAGAIN; | |
187 | ||
188 | if (num == 2 && !(msg[0].flags & I2C_M_RD) && | |
189 | (msg[1].flags & I2C_M_RD)) { | |
34ec2933 AP |
190 | if (msg[0].len > 24 || msg[1].len > 24) { |
191 | /* TODO: check msg[0].len max */ | |
831e0b71 | 192 | ret = -EOPNOTSUPP; |
9935eea5 | 193 | goto err_mutex_unlock; |
34ec2933 AP |
194 | } else if (msg[0].addr == 0x10) { |
195 | /* method 1 - integrated demod */ | |
196 | req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); | |
197 | req.index = CMD_DEMOD_RD | priv->page; | |
831e0b71 AP |
198 | req.size = msg[1].len; |
199 | req.data = &msg[1].buf[0]; | |
200 | ret = rtl28xxu_ctrl_msg(d, &req); | |
34ec2933 AP |
201 | } else if (msg[0].len < 2) { |
202 | /* method 2 - old I2C */ | |
831e0b71 AP |
203 | req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); |
204 | req.index = CMD_I2C_RD; | |
205 | req.size = msg[1].len; | |
206 | req.data = &msg[1].buf[0]; | |
207 | ret = rtl28xxu_ctrl_msg(d, &req); | |
34ec2933 AP |
208 | } else { |
209 | /* method 3 - new I2C */ | |
210 | req.value = (msg[0].addr << 1); | |
211 | req.index = CMD_I2C_DA_WR; | |
212 | req.size = msg[0].len; | |
213 | req.data = msg[0].buf; | |
214 | ret = rtl28xxu_ctrl_msg(d, &req); | |
215 | if (ret) | |
9935eea5 | 216 | goto err_mutex_unlock; |
34ec2933 AP |
217 | |
218 | req.value = (msg[0].addr << 1); | |
219 | req.index = CMD_I2C_DA_RD; | |
220 | req.size = msg[1].len; | |
221 | req.data = msg[1].buf; | |
222 | ret = rtl28xxu_ctrl_msg(d, &req); | |
831e0b71 AP |
223 | } |
224 | } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { | |
225 | if (msg[0].len > 22) { | |
34ec2933 | 226 | /* TODO: check msg[0].len max */ |
831e0b71 | 227 | ret = -EOPNOTSUPP; |
9935eea5 | 228 | goto err_mutex_unlock; |
34ec2933 AP |
229 | } else if (msg[0].addr == 0x10) { |
230 | /* method 1 - integrated demod */ | |
231 | if (msg[0].buf[0] == 0x00) { | |
232 | /* save demod page for later demod access */ | |
233 | priv->page = msg[0].buf[1]; | |
234 | ret = 0; | |
235 | } else { | |
236 | req.value = (msg[0].buf[0] << 8) | | |
237 | (msg[0].addr << 1); | |
238 | req.index = CMD_DEMOD_WR | priv->page; | |
239 | req.size = msg[0].len-1; | |
240 | req.data = &msg[0].buf[1]; | |
241 | ret = rtl28xxu_ctrl_msg(d, &req); | |
242 | } | |
243 | } else if (msg[0].len < 23) { | |
244 | /* method 2 - old I2C */ | |
831e0b71 AP |
245 | req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); |
246 | req.index = CMD_I2C_WR; | |
247 | req.size = msg[0].len-1; | |
248 | req.data = &msg[0].buf[1]; | |
249 | ret = rtl28xxu_ctrl_msg(d, &req); | |
34ec2933 AP |
250 | } else { |
251 | /* method 3 - new I2C */ | |
252 | req.value = (msg[0].addr << 1); | |
253 | req.index = CMD_I2C_DA_WR; | |
254 | req.size = msg[0].len; | |
255 | req.data = msg[0].buf; | |
256 | ret = rtl28xxu_ctrl_msg(d, &req); | |
831e0b71 AP |
257 | } |
258 | } else { | |
259 | ret = -EINVAL; | |
260 | } | |
261 | ||
9935eea5 | 262 | err_mutex_unlock: |
831e0b71 AP |
263 | mutex_unlock(&d->i2c_mutex); |
264 | ||
265 | return ret ? ret : num; | |
266 | } | |
267 | ||
268 | static u32 rtl28xxu_i2c_func(struct i2c_adapter *adapter) | |
269 | { | |
270 | return I2C_FUNC_I2C; | |
271 | } | |
272 | ||
273 | static struct i2c_algorithm rtl28xxu_i2c_algo = { | |
274 | .master_xfer = rtl28xxu_i2c_xfer, | |
275 | .functionality = rtl28xxu_i2c_func, | |
276 | }; | |
277 | ||
81347f5a AP |
278 | static int rtl2831u_read_config(struct dvb_usb_device *d) |
279 | { | |
280 | struct rtl28xxu_priv *priv = d_to_priv(d); | |
281 | int ret; | |
282 | u8 buf[1]; | |
283 | /* open RTL2831U/RTL2830 I2C gate */ | |
284 | struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x08"}; | |
285 | /* tuner probes */ | |
286 | struct rtl28xxu_req req_mt2060 = {0x00c0, CMD_I2C_RD, 1, buf}; | |
287 | struct rtl28xxu_req req_qt1010 = {0x0fc4, CMD_I2C_RD, 1, buf}; | |
288 | ||
289 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | |
290 | ||
291 | /* | |
292 | * RTL2831U GPIOs | |
293 | * ========================================================= | |
294 | * GPIO0 | tuner#0 | 0 off | 1 on | MXL5005S (?) | |
295 | * GPIO2 | LED | 0 off | 1 on | | |
296 | * GPIO4 | tuner#1 | 0 on | 1 off | MT2060 | |
297 | */ | |
298 | ||
299 | /* GPIO direction */ | |
300 | ret = rtl28xx_wr_reg(d, SYS_GPIO_DIR, 0x0a); | |
301 | if (ret) | |
302 | goto err; | |
303 | ||
304 | /* enable as output GPIO0, GPIO2, GPIO4 */ | |
305 | ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_EN, 0x15); | |
306 | if (ret) | |
307 | goto err; | |
308 | ||
309 | /* | |
310 | * Probe used tuner. We need to know used tuner before demod attach | |
311 | * since there is some demod params needed to set according to tuner. | |
312 | */ | |
313 | ||
314 | /* demod needs some time to wake up */ | |
315 | msleep(20); | |
316 | ||
317 | priv->tuner_name = "NONE"; | |
318 | ||
319 | /* open demod I2C gate */ | |
320 | ret = rtl28xxu_ctrl_msg(d, &req_gate_open); | |
321 | if (ret) | |
322 | goto err; | |
323 | ||
324 | /* check QT1010 ID(?) register; reg=0f val=2c */ | |
325 | ret = rtl28xxu_ctrl_msg(d, &req_qt1010); | |
326 | if (ret == 0 && buf[0] == 0x2c) { | |
327 | priv->tuner = TUNER_RTL2830_QT1010; | |
328 | priv->tuner_name = "QT1010"; | |
329 | goto found; | |
330 | } | |
331 | ||
332 | /* open demod I2C gate */ | |
333 | ret = rtl28xxu_ctrl_msg(d, &req_gate_open); | |
334 | if (ret) | |
335 | goto err; | |
336 | ||
337 | /* check MT2060 ID register; reg=00 val=63 */ | |
338 | ret = rtl28xxu_ctrl_msg(d, &req_mt2060); | |
339 | if (ret == 0 && buf[0] == 0x63) { | |
340 | priv->tuner = TUNER_RTL2830_MT2060; | |
341 | priv->tuner_name = "MT2060"; | |
342 | goto found; | |
343 | } | |
344 | ||
345 | /* assume MXL5005S */ | |
346 | priv->tuner = TUNER_RTL2830_MXL5005S; | |
347 | priv->tuner_name = "MXL5005S"; | |
348 | goto found; | |
349 | ||
350 | found: | |
351 | dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name); | |
352 | ||
353 | return 0; | |
354 | err: | |
355 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | |
356 | return ret; | |
357 | } | |
358 | ||
ef37be1b AP |
359 | static int rtl2832u_read_config(struct dvb_usb_device *d) |
360 | { | |
361 | struct rtl28xxu_priv *priv = d_to_priv(d); | |
362 | int ret; | |
4005c1a9 | 363 | u8 buf[2]; |
ef37be1b AP |
364 | /* open RTL2832U/RTL2832 I2C gate */ |
365 | struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"}; | |
366 | /* close RTL2832U/RTL2832 I2C gate */ | |
367 | struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"}; | |
368 | /* tuner probes */ | |
369 | struct rtl28xxu_req req_fc0012 = {0x00c6, CMD_I2C_RD, 1, buf}; | |
370 | struct rtl28xxu_req req_fc0013 = {0x00c6, CMD_I2C_RD, 1, buf}; | |
371 | struct rtl28xxu_req req_mt2266 = {0x00c0, CMD_I2C_RD, 1, buf}; | |
372 | struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf}; | |
373 | struct rtl28xxu_req req_mt2063 = {0x00c0, CMD_I2C_RD, 1, buf}; | |
374 | struct rtl28xxu_req req_max3543 = {0x00c0, CMD_I2C_RD, 1, buf}; | |
375 | struct rtl28xxu_req req_tua9001 = {0x7ec0, CMD_I2C_RD, 2, buf}; | |
376 | struct rtl28xxu_req req_mxl5007t = {0xd9c0, CMD_I2C_RD, 1, buf}; | |
377 | struct rtl28xxu_req req_e4000 = {0x02c8, CMD_I2C_RD, 1, buf}; | |
378 | struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf}; | |
a908eb99 | 379 | struct rtl28xxu_req req_r820t = {0x0034, CMD_I2C_RD, 1, buf}; |
8b4cac1a | 380 | struct rtl28xxu_req req_r828d = {0x0074, CMD_I2C_RD, 1, buf}; |
ef37be1b AP |
381 | |
382 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | |
383 | ||
4005c1a9 AP |
384 | /* enable GPIO3 and GPIO6 as output */ |
385 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x40); | |
ef37be1b AP |
386 | if (ret) |
387 | goto err; | |
388 | ||
4005c1a9 | 389 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x48, 0x48); |
ef37be1b AP |
390 | if (ret) |
391 | goto err; | |
392 | ||
393 | /* | |
394 | * Probe used tuner. We need to know used tuner before demod attach | |
395 | * since there is some demod params needed to set according to tuner. | |
396 | */ | |
397 | ||
398 | /* open demod I2C gate */ | |
399 | ret = rtl28xxu_ctrl_msg(d, &req_gate_open); | |
400 | if (ret) | |
401 | goto err; | |
402 | ||
403 | priv->tuner_name = "NONE"; | |
404 | ||
405 | /* check FC0012 ID register; reg=00 val=a1 */ | |
406 | ret = rtl28xxu_ctrl_msg(d, &req_fc0012); | |
407 | if (ret == 0 && buf[0] == 0xa1) { | |
408 | priv->tuner = TUNER_RTL2832_FC0012; | |
409 | priv->tuner_name = "FC0012"; | |
410 | goto found; | |
411 | } | |
412 | ||
413 | /* check FC0013 ID register; reg=00 val=a3 */ | |
414 | ret = rtl28xxu_ctrl_msg(d, &req_fc0013); | |
415 | if (ret == 0 && buf[0] == 0xa3) { | |
416 | priv->tuner = TUNER_RTL2832_FC0013; | |
417 | priv->tuner_name = "FC0013"; | |
418 | goto found; | |
419 | } | |
420 | ||
421 | /* check MT2266 ID register; reg=00 val=85 */ | |
422 | ret = rtl28xxu_ctrl_msg(d, &req_mt2266); | |
423 | if (ret == 0 && buf[0] == 0x85) { | |
424 | priv->tuner = TUNER_RTL2832_MT2266; | |
425 | priv->tuner_name = "MT2266"; | |
426 | goto found; | |
427 | } | |
428 | ||
429 | /* check FC2580 ID register; reg=01 val=56 */ | |
430 | ret = rtl28xxu_ctrl_msg(d, &req_fc2580); | |
431 | if (ret == 0 && buf[0] == 0x56) { | |
432 | priv->tuner = TUNER_RTL2832_FC2580; | |
433 | priv->tuner_name = "FC2580"; | |
434 | goto found; | |
435 | } | |
436 | ||
437 | /* check MT2063 ID register; reg=00 val=9e || 9c */ | |
438 | ret = rtl28xxu_ctrl_msg(d, &req_mt2063); | |
439 | if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) { | |
440 | priv->tuner = TUNER_RTL2832_MT2063; | |
441 | priv->tuner_name = "MT2063"; | |
442 | goto found; | |
443 | } | |
444 | ||
445 | /* check MAX3543 ID register; reg=00 val=38 */ | |
446 | ret = rtl28xxu_ctrl_msg(d, &req_max3543); | |
447 | if (ret == 0 && buf[0] == 0x38) { | |
448 | priv->tuner = TUNER_RTL2832_MAX3543; | |
449 | priv->tuner_name = "MAX3543"; | |
450 | goto found; | |
451 | } | |
452 | ||
453 | /* check TUA9001 ID register; reg=7e val=2328 */ | |
454 | ret = rtl28xxu_ctrl_msg(d, &req_tua9001); | |
455 | if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) { | |
456 | priv->tuner = TUNER_RTL2832_TUA9001; | |
457 | priv->tuner_name = "TUA9001"; | |
458 | goto found; | |
459 | } | |
460 | ||
461 | /* check MXL5007R ID register; reg=d9 val=14 */ | |
462 | ret = rtl28xxu_ctrl_msg(d, &req_mxl5007t); | |
463 | if (ret == 0 && buf[0] == 0x14) { | |
464 | priv->tuner = TUNER_RTL2832_MXL5007T; | |
465 | priv->tuner_name = "MXL5007T"; | |
466 | goto found; | |
467 | } | |
468 | ||
469 | /* check E4000 ID register; reg=02 val=40 */ | |
470 | ret = rtl28xxu_ctrl_msg(d, &req_e4000); | |
471 | if (ret == 0 && buf[0] == 0x40) { | |
472 | priv->tuner = TUNER_RTL2832_E4000; | |
473 | priv->tuner_name = "E4000"; | |
474 | goto found; | |
475 | } | |
476 | ||
477 | /* check TDA18272 ID register; reg=00 val=c760 */ | |
478 | ret = rtl28xxu_ctrl_msg(d, &req_tda18272); | |
479 | if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) { | |
480 | priv->tuner = TUNER_RTL2832_TDA18272; | |
481 | priv->tuner_name = "TDA18272"; | |
482 | goto found; | |
483 | } | |
484 | ||
a908eb99 | 485 | /* check R820T ID register; reg=00 val=69 */ |
6889ab2a | 486 | ret = rtl28xxu_ctrl_msg(d, &req_r820t); |
a908eb99 | 487 | if (ret == 0 && buf[0] == 0x69) { |
6889ab2a MCC |
488 | priv->tuner = TUNER_RTL2832_R820T; |
489 | priv->tuner_name = "R820T"; | |
490 | goto found; | |
491 | } | |
492 | ||
8b4cac1a AP |
493 | /* check R828D ID register; reg=00 val=69 */ |
494 | ret = rtl28xxu_ctrl_msg(d, &req_r828d); | |
495 | if (ret == 0 && buf[0] == 0x69) { | |
496 | priv->tuner = TUNER_RTL2832_R828D; | |
497 | priv->tuner_name = "R828D"; | |
498 | goto found; | |
499 | } | |
500 | ||
501 | ||
ef37be1b AP |
502 | found: |
503 | dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name); | |
504 | ||
505 | /* close demod I2C gate */ | |
506 | ret = rtl28xxu_ctrl_msg(d, &req_gate_close); | |
507 | if (ret < 0) | |
508 | goto err; | |
509 | ||
510 | return 0; | |
511 | err: | |
512 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | |
513 | return ret; | |
514 | } | |
515 | ||
831e0b71 AP |
516 | static struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = { |
517 | .i2c_addr = 0x10, /* 0x20 */ | |
518 | .xtal = 28800000, | |
519 | .ts_mode = 0, | |
520 | .spec_inv = 1, | |
831e0b71 AP |
521 | .vtop = 0x20, |
522 | .krf = 0x04, | |
523 | .agc_targ_val = 0x2d, | |
524 | ||
525 | }; | |
526 | ||
527 | static struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = { | |
528 | .i2c_addr = 0x10, /* 0x20 */ | |
529 | .xtal = 28800000, | |
530 | .ts_mode = 0, | |
531 | .spec_inv = 1, | |
831e0b71 AP |
532 | .vtop = 0x20, |
533 | .krf = 0x04, | |
534 | .agc_targ_val = 0x2d, | |
535 | }; | |
536 | ||
537 | static struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = { | |
538 | .i2c_addr = 0x10, /* 0x20 */ | |
539 | .xtal = 28800000, | |
540 | .ts_mode = 0, | |
541 | .spec_inv = 0, | |
831e0b71 AP |
542 | .vtop = 0x3f, |
543 | .krf = 0x04, | |
544 | .agc_targ_val = 0x3e, | |
545 | }; | |
546 | ||
b5cbaa43 | 547 | static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) |
831e0b71 | 548 | { |
c01a3595 AP |
549 | struct dvb_usb_device *d = adap_to_d(adap); |
550 | struct rtl28xxu_priv *priv = d_to_priv(d); | |
831e0b71 | 551 | struct rtl2830_config *rtl2830_config; |
81347f5a | 552 | int ret; |
831e0b71 | 553 | |
c01a3595 | 554 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
831e0b71 | 555 | |
81347f5a AP |
556 | switch (priv->tuner) { |
557 | case TUNER_RTL2830_QT1010: | |
831e0b71 | 558 | rtl2830_config = &rtl28xxu_rtl2830_qt1010_config; |
81347f5a AP |
559 | break; |
560 | case TUNER_RTL2830_MT2060: | |
831e0b71 | 561 | rtl2830_config = &rtl28xxu_rtl2830_mt2060_config; |
81347f5a AP |
562 | break; |
563 | case TUNER_RTL2830_MXL5005S: | |
564 | rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config; | |
565 | break; | |
566 | default: | |
567 | dev_err(&d->udev->dev, "%s: unknown tuner=%s\n", | |
568 | KBUILD_MODNAME, priv->tuner_name); | |
569 | ret = -ENODEV; | |
570 | goto err; | |
831e0b71 AP |
571 | } |
572 | ||
831e0b71 | 573 | /* attach demodulator */ |
81347f5a AP |
574 | adap->fe[0] = dvb_attach(rtl2830_attach, rtl2830_config, &d->i2c_adap); |
575 | if (!adap->fe[0]) { | |
831e0b71 AP |
576 | ret = -ENODEV; |
577 | goto err; | |
578 | } | |
579 | ||
81347f5a | 580 | return 0; |
831e0b71 | 581 | err: |
c01a3595 | 582 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
831e0b71 AP |
583 | return ret; |
584 | } | |
585 | ||
5cf6631e TM |
586 | static struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = { |
587 | .i2c_addr = 0x10, /* 0x20 */ | |
588 | .xtal = 28800000, | |
589 | .if_dvbt = 0, | |
590 | .tuner = TUNER_RTL2832_FC0012 | |
591 | }; | |
592 | ||
593 | static struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = { | |
594 | .i2c_addr = 0x10, /* 0x20 */ | |
595 | .xtal = 28800000, | |
596 | .if_dvbt = 0, | |
597 | .tuner = TUNER_RTL2832_FC0013 | |
598 | }; | |
599 | ||
5be65721 AP |
600 | static struct rtl2832_config rtl28xxu_rtl2832_tua9001_config = { |
601 | .i2c_addr = 0x10, /* 0x20 */ | |
602 | .xtal = 28800000, | |
603 | .tuner = TUNER_RTL2832_TUA9001, | |
604 | }; | |
605 | ||
3d8a60d5 AP |
606 | static struct rtl2832_config rtl28xxu_rtl2832_e4000_config = { |
607 | .i2c_addr = 0x10, /* 0x20 */ | |
608 | .xtal = 28800000, | |
609 | .tuner = TUNER_RTL2832_E4000, | |
610 | }; | |
611 | ||
6889ab2a MCC |
612 | static struct rtl2832_config rtl28xxu_rtl2832_r820t_config = { |
613 | .i2c_addr = 0x10, | |
614 | .xtal = 28800000, | |
615 | .tuner = TUNER_RTL2832_R820T, | |
616 | }; | |
617 | ||
5cf6631e TM |
618 | static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d, |
619 | int cmd, int arg) | |
620 | { | |
621 | int ret; | |
622 | u8 val; | |
623 | ||
c01a3595 AP |
624 | dev_dbg(&d->udev->dev, "%s: cmd=%d arg=%d\n", __func__, cmd, arg); |
625 | ||
5cf6631e TM |
626 | switch (cmd) { |
627 | case FC_FE_CALLBACK_VHF_ENABLE: | |
628 | /* set output values */ | |
40a2d3c7 | 629 | ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); |
5cf6631e TM |
630 | if (ret) |
631 | goto err; | |
632 | ||
633 | if (arg) | |
634 | val &= 0xbf; /* set GPIO6 low */ | |
635 | else | |
636 | val |= 0x40; /* set GPIO6 high */ | |
637 | ||
638 | ||
40a2d3c7 | 639 | ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val); |
5cf6631e TM |
640 | if (ret) |
641 | goto err; | |
642 | break; | |
643 | default: | |
644 | ret = -EINVAL; | |
645 | goto err; | |
646 | } | |
647 | return 0; | |
5cf6631e | 648 | err: |
c01a3595 | 649 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
5cf6631e TM |
650 | return ret; |
651 | } | |
652 | ||
5be65721 AP |
653 | static int rtl2832u_tua9001_tuner_callback(struct dvb_usb_device *d, |
654 | int cmd, int arg) | |
655 | { | |
656 | int ret; | |
657 | u8 val; | |
658 | ||
659 | dev_dbg(&d->udev->dev, "%s: cmd=%d arg=%d\n", __func__, cmd, arg); | |
660 | ||
661 | /* | |
662 | * CEN always enabled by hardware wiring | |
663 | * RESETN GPIO4 | |
664 | * RXEN GPIO1 | |
665 | */ | |
666 | ||
5be65721 AP |
667 | switch (cmd) { |
668 | case TUA9001_CMD_RESETN: | |
669 | if (arg) | |
4005c1a9 | 670 | val = (1 << 4); |
5be65721 | 671 | else |
4005c1a9 | 672 | val = (0 << 4); |
5be65721 | 673 | |
4005c1a9 AP |
674 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, val, 0x10); |
675 | if (ret) | |
5be65721 AP |
676 | goto err; |
677 | break; | |
678 | case TUA9001_CMD_RXEN: | |
679 | if (arg) | |
4005c1a9 | 680 | val = (1 << 1); |
5be65721 | 681 | else |
4005c1a9 | 682 | val = (0 << 1); |
5be65721 | 683 | |
4005c1a9 AP |
684 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, val, 0x02); |
685 | if (ret) | |
5be65721 AP |
686 | goto err; |
687 | break; | |
688 | } | |
689 | ||
690 | return 0; | |
5be65721 AP |
691 | err: |
692 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | |
693 | return ret; | |
694 | } | |
695 | ||
5cf6631e TM |
696 | static int rtl2832u_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) |
697 | { | |
698 | struct rtl28xxu_priv *priv = d->priv; | |
699 | ||
700 | switch (priv->tuner) { | |
701 | case TUNER_RTL2832_FC0012: | |
702 | return rtl2832u_fc0012_tuner_callback(d, cmd, arg); | |
5be65721 AP |
703 | case TUNER_RTL2832_TUA9001: |
704 | return rtl2832u_tua9001_tuner_callback(d, cmd, arg); | |
5cf6631e TM |
705 | default: |
706 | break; | |
707 | } | |
708 | ||
97efe781 | 709 | return 0; |
5cf6631e TM |
710 | } |
711 | ||
712 | static int rtl2832u_frontend_callback(void *adapter_priv, int component, | |
8acc91cd | 713 | int cmd, int arg) |
5cf6631e TM |
714 | { |
715 | struct i2c_adapter *adap = adapter_priv; | |
716 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | |
717 | ||
8acc91cd AP |
718 | dev_dbg(&d->udev->dev, "%s: component=%d cmd=%d arg=%d\n", |
719 | __func__, component, cmd, arg); | |
720 | ||
5cf6631e TM |
721 | switch (component) { |
722 | case DVB_FRONTEND_COMPONENT_TUNER: | |
723 | return rtl2832u_tuner_callback(d, cmd, arg); | |
724 | default: | |
725 | break; | |
726 | } | |
727 | ||
97efe781 | 728 | return 0; |
5cf6631e TM |
729 | } |
730 | ||
b5cbaa43 AP |
731 | static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) |
732 | { | |
733 | int ret; | |
c01a3595 AP |
734 | struct dvb_usb_device *d = adap_to_d(adap); |
735 | struct rtl28xxu_priv *priv = d_to_priv(d); | |
5cf6631e | 736 | struct rtl2832_config *rtl2832_config; |
b5cbaa43 | 737 | |
c01a3595 | 738 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
b5cbaa43 | 739 | |
ef37be1b AP |
740 | switch (priv->tuner) { |
741 | case TUNER_RTL2832_FC0012: | |
5cf6631e | 742 | rtl2832_config = &rtl28xxu_rtl2832_fc0012_config; |
ef37be1b AP |
743 | break; |
744 | case TUNER_RTL2832_FC0013: | |
5cf6631e | 745 | rtl2832_config = &rtl28xxu_rtl2832_fc0013_config; |
ef37be1b AP |
746 | break; |
747 | case TUNER_RTL2832_FC2580: | |
384df49a AP |
748 | /* FIXME: do not abuse fc0012 settings */ |
749 | rtl2832_config = &rtl28xxu_rtl2832_fc0012_config; | |
ef37be1b AP |
750 | break; |
751 | case TUNER_RTL2832_TUA9001: | |
5be65721 | 752 | rtl2832_config = &rtl28xxu_rtl2832_tua9001_config; |
ef37be1b AP |
753 | break; |
754 | case TUNER_RTL2832_E4000: | |
3d8a60d5 | 755 | rtl2832_config = &rtl28xxu_rtl2832_e4000_config; |
ef37be1b | 756 | break; |
6889ab2a | 757 | case TUNER_RTL2832_R820T: |
8b4cac1a | 758 | case TUNER_RTL2832_R828D: |
6889ab2a MCC |
759 | rtl2832_config = &rtl28xxu_rtl2832_r820t_config; |
760 | break; | |
ef37be1b AP |
761 | default: |
762 | dev_err(&d->udev->dev, "%s: unknown tuner=%s\n", | |
763 | KBUILD_MODNAME, priv->tuner_name); | |
764 | ret = -ENODEV; | |
b5cbaa43 | 765 | goto err; |
ef37be1b | 766 | } |
b5cbaa43 AP |
767 | |
768 | /* attach demodulator */ | |
ef37be1b AP |
769 | adap->fe[0] = dvb_attach(rtl2832_attach, rtl2832_config, &d->i2c_adap); |
770 | if (!adap->fe[0]) { | |
771 | ret = -ENODEV; | |
772 | goto err; | |
773 | } | |
5cf6631e | 774 | |
ef37be1b | 775 | /* set fe callback */ |
c01a3595 | 776 | adap->fe[0]->callback = rtl2832u_frontend_callback; |
b5cbaa43 | 777 | |
ef37be1b | 778 | return 0; |
b5cbaa43 | 779 | err: |
c01a3595 | 780 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
b5cbaa43 AP |
781 | return ret; |
782 | } | |
783 | ||
831e0b71 AP |
784 | static struct qt1010_config rtl28xxu_qt1010_config = { |
785 | .i2c_address = 0x62, /* 0xc4 */ | |
786 | }; | |
787 | ||
788 | static struct mt2060_config rtl28xxu_mt2060_config = { | |
789 | .i2c_address = 0x60, /* 0xc0 */ | |
790 | .clock_out = 0, | |
791 | }; | |
792 | ||
793 | static struct mxl5005s_config rtl28xxu_mxl5005s_config = { | |
794 | .i2c_address = 0x63, /* 0xc6 */ | |
795 | .if_freq = IF_FREQ_4570000HZ, | |
796 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | |
797 | .agc_mode = MXL_SINGLE_AGC, | |
798 | .tracking_filter = MXL_TF_C_H, | |
799 | .rssi_enable = MXL_RSSI_ENABLE, | |
800 | .cap_select = MXL_CAP_SEL_ENABLE, | |
801 | .div_out = MXL_DIV_OUT_4, | |
802 | .clock_out = MXL_CLOCK_OUT_DISABLE, | |
803 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | |
804 | .top = MXL5005S_TOP_25P2, | |
805 | .mod_mode = MXL_DIGITAL_MODE, | |
806 | .if_mode = MXL_ZERO_IF, | |
807 | .AgcMasterByte = 0x00, | |
808 | }; | |
809 | ||
b5cbaa43 | 810 | static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap) |
831e0b71 AP |
811 | { |
812 | int ret; | |
c01a3595 AP |
813 | struct dvb_usb_device *d = adap_to_d(adap); |
814 | struct rtl28xxu_priv *priv = d_to_priv(d); | |
831e0b71 | 815 | struct i2c_adapter *rtl2830_tuner_i2c; |
9935eea5 | 816 | struct dvb_frontend *fe; |
831e0b71 | 817 | |
c01a3595 | 818 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
831e0b71 AP |
819 | |
820 | /* use rtl2830 driver I2C adapter, for more info see rtl2830 driver */ | |
c01a3595 | 821 | rtl2830_tuner_i2c = rtl2830_get_tuner_i2c_adapter(adap->fe[0]); |
831e0b71 AP |
822 | |
823 | switch (priv->tuner) { | |
824 | case TUNER_RTL2830_QT1010: | |
c01a3595 | 825 | fe = dvb_attach(qt1010_attach, adap->fe[0], |
fba16b13 | 826 | rtl2830_tuner_i2c, &rtl28xxu_qt1010_config); |
831e0b71 AP |
827 | break; |
828 | case TUNER_RTL2830_MT2060: | |
c01a3595 | 829 | fe = dvb_attach(mt2060_attach, adap->fe[0], |
fba16b13 AP |
830 | rtl2830_tuner_i2c, &rtl28xxu_mt2060_config, |
831 | 1220); | |
831e0b71 AP |
832 | break; |
833 | case TUNER_RTL2830_MXL5005S: | |
c01a3595 | 834 | fe = dvb_attach(mxl5005s_attach, adap->fe[0], |
9935eea5 | 835 | rtl2830_tuner_i2c, &rtl28xxu_mxl5005s_config); |
831e0b71 AP |
836 | break; |
837 | default: | |
9935eea5 | 838 | fe = NULL; |
c01a3595 AP |
839 | dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME, |
840 | priv->tuner); | |
831e0b71 AP |
841 | } |
842 | ||
843 | if (fe == NULL) { | |
844 | ret = -ENODEV; | |
845 | goto err; | |
846 | } | |
847 | ||
848 | return 0; | |
849 | err: | |
c01a3595 | 850 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
831e0b71 AP |
851 | return ret; |
852 | } | |
853 | ||
542f6a52 AP |
854 | static const struct e4000_config rtl2832u_e4000_config = { |
855 | .i2c_addr = 0x64, | |
856 | .clock = 28800000, | |
857 | }; | |
858 | ||
384df49a AP |
859 | static const struct fc2580_config rtl2832u_fc2580_config = { |
860 | .i2c_addr = 0x56, | |
861 | .clock = 16384000, | |
862 | }; | |
863 | ||
5be65721 AP |
864 | static struct tua9001_config rtl2832u_tua9001_config = { |
865 | .i2c_addr = 0x60, | |
866 | }; | |
867 | ||
ad3a758b AP |
868 | static const struct fc0012_config rtl2832u_fc0012_config = { |
869 | .i2c_address = 0x63, /* 0xc6 >> 1 */ | |
870 | .xtal_freq = FC_XTAL_28_8_MHZ, | |
871 | }; | |
872 | ||
6889ab2a MCC |
873 | static const struct r820t_config rtl2832u_r820t_config = { |
874 | .i2c_addr = 0x1a, | |
875 | .xtal = 28800000, | |
876 | .max_i2c_msg_len = 2, | |
877 | .rafael_chip = CHIP_R820T, | |
878 | }; | |
879 | ||
8b4cac1a AP |
880 | static const struct r820t_config rtl2832u_r828d_config = { |
881 | .i2c_addr = 0x3a, | |
882 | .xtal = 16000000, | |
883 | .max_i2c_msg_len = 2, | |
884 | .rafael_chip = CHIP_R828D, | |
885 | }; | |
886 | ||
b5cbaa43 AP |
887 | static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) |
888 | { | |
889 | int ret; | |
c01a3595 AP |
890 | struct dvb_usb_device *d = adap_to_d(adap); |
891 | struct rtl28xxu_priv *priv = d_to_priv(d); | |
9935eea5 | 892 | struct dvb_frontend *fe; |
b5cbaa43 | 893 | |
c01a3595 | 894 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
b5cbaa43 AP |
895 | |
896 | switch (priv->tuner) { | |
5cf6631e | 897 | case TUNER_RTL2832_FC0012: |
c01a3595 | 898 | fe = dvb_attach(fc0012_attach, adap->fe[0], |
ad3a758b | 899 | &d->i2c_adap, &rtl2832u_fc0012_config); |
5cf6631e TM |
900 | |
901 | /* since fc0012 includs reading the signal strength delegate | |
902 | * that to the tuner driver */ | |
c01a3595 AP |
903 | adap->fe[0]->ops.read_signal_strength = |
904 | adap->fe[0]->ops.tuner_ops.get_rf_strength; | |
5cf6631e | 905 | return 0; |
b5cbaa43 | 906 | break; |
5cf6631e | 907 | case TUNER_RTL2832_FC0013: |
c01a3595 AP |
908 | fe = dvb_attach(fc0013_attach, adap->fe[0], |
909 | &d->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ); | |
5cf6631e TM |
910 | |
911 | /* fc0013 also supports signal strength reading */ | |
c01a3595 AP |
912 | adap->fe[0]->ops.read_signal_strength = |
913 | adap->fe[0]->ops.tuner_ops.get_rf_strength; | |
5cf6631e | 914 | return 0; |
542f6a52 AP |
915 | case TUNER_RTL2832_E4000: |
916 | fe = dvb_attach(e4000_attach, adap->fe[0], &d->i2c_adap, | |
917 | &rtl2832u_e4000_config); | |
918 | break; | |
384df49a AP |
919 | case TUNER_RTL2832_FC2580: |
920 | fe = dvb_attach(fc2580_attach, adap->fe[0], &d->i2c_adap, | |
921 | &rtl2832u_fc2580_config); | |
922 | break; | |
5be65721 AP |
923 | case TUNER_RTL2832_TUA9001: |
924 | /* enable GPIO1 and GPIO4 as output */ | |
4005c1a9 AP |
925 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x12); |
926 | if (ret) | |
5be65721 AP |
927 | goto err; |
928 | ||
4005c1a9 AP |
929 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x12, 0x12); |
930 | if (ret) | |
5be65721 AP |
931 | goto err; |
932 | ||
933 | fe = dvb_attach(tua9001_attach, adap->fe[0], &d->i2c_adap, | |
934 | &rtl2832u_tua9001_config); | |
935 | break; | |
6889ab2a MCC |
936 | case TUNER_RTL2832_R820T: |
937 | fe = dvb_attach(r820t_attach, adap->fe[0], &d->i2c_adap, | |
938 | &rtl2832u_r820t_config); | |
9e30edd8 | 939 | |
8b4cac1a AP |
940 | /* Use tuner to get the signal strength */ |
941 | adap->fe[0]->ops.read_signal_strength = | |
942 | adap->fe[0]->ops.tuner_ops.get_rf_strength; | |
943 | break; | |
944 | case TUNER_RTL2832_R828D: | |
945 | /* power off mn88472 demod on GPIO0 */ | |
946 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x00, 0x01); | |
947 | if (ret) | |
948 | goto err; | |
949 | ||
950 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x01); | |
951 | if (ret) | |
952 | goto err; | |
953 | ||
954 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x01, 0x01); | |
955 | if (ret) | |
956 | goto err; | |
957 | ||
958 | fe = dvb_attach(r820t_attach, adap->fe[0], &d->i2c_adap, | |
959 | &rtl2832u_r828d_config); | |
960 | ||
9e30edd8 MCC |
961 | /* Use tuner to get the signal strength */ |
962 | adap->fe[0]->ops.read_signal_strength = | |
963 | adap->fe[0]->ops.tuner_ops.get_rf_strength; | |
6889ab2a | 964 | break; |
b5cbaa43 | 965 | default: |
9935eea5 | 966 | fe = NULL; |
c01a3595 AP |
967 | dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME, |
968 | priv->tuner); | |
b5cbaa43 AP |
969 | } |
970 | ||
971 | if (fe == NULL) { | |
972 | ret = -ENODEV; | |
973 | goto err; | |
974 | } | |
975 | ||
976 | return 0; | |
977 | err: | |
c01a3595 | 978 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
b5cbaa43 AP |
979 | return ret; |
980 | } | |
981 | ||
c01a3595 AP |
982 | static int rtl28xxu_init(struct dvb_usb_device *d) |
983 | { | |
984 | int ret; | |
985 | u8 val; | |
986 | ||
987 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | |
988 | ||
989 | /* init USB endpoints */ | |
990 | ret = rtl28xx_rd_reg(d, USB_SYSCTL_0, &val); | |
991 | if (ret) | |
992 | goto err; | |
993 | ||
994 | /* enable DMA and Full Packet Mode*/ | |
995 | val |= 0x09; | |
996 | ret = rtl28xx_wr_reg(d, USB_SYSCTL_0, val); | |
997 | if (ret) | |
998 | goto err; | |
999 | ||
1000 | /* set EPA maximum packet size to 0x0200 */ | |
1001 | ret = rtl28xx_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4); | |
1002 | if (ret) | |
1003 | goto err; | |
1004 | ||
1005 | /* change EPA FIFO length */ | |
1006 | ret = rtl28xx_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4); | |
1007 | if (ret) | |
1008 | goto err; | |
1009 | ||
1010 | return ret; | |
1011 | err: | |
1012 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | |
1013 | return ret; | |
1014 | } | |
1015 | ||
5cf6631e | 1016 | static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) |
831e0b71 AP |
1017 | { |
1018 | int ret; | |
8b036636 | 1019 | u8 gpio, sys0, epa_ctl[2]; |
831e0b71 | 1020 | |
c01a3595 | 1021 | dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); |
831e0b71 AP |
1022 | |
1023 | /* demod adc */ | |
40a2d3c7 | 1024 | ret = rtl28xx_rd_reg(d, SYS_SYS0, &sys0); |
831e0b71 AP |
1025 | if (ret) |
1026 | goto err; | |
1027 | ||
1028 | /* tuner power, read GPIOs */ | |
40a2d3c7 | 1029 | ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio); |
831e0b71 AP |
1030 | if (ret) |
1031 | goto err; | |
1032 | ||
c01a3595 AP |
1033 | dev_dbg(&d->udev->dev, "%s: RD SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, |
1034 | sys0, gpio); | |
831e0b71 AP |
1035 | |
1036 | if (onoff) { | |
1037 | gpio |= 0x01; /* GPIO0 = 1 */ | |
1038 | gpio &= (~0x10); /* GPIO4 = 0 */ | |
991452a2 | 1039 | gpio |= 0x04; /* GPIO2 = 1, LED on */ |
831e0b71 AP |
1040 | sys0 = sys0 & 0x0f; |
1041 | sys0 |= 0xe0; | |
8b036636 AP |
1042 | epa_ctl[0] = 0x00; /* clear stall */ |
1043 | epa_ctl[1] = 0x00; /* clear reset */ | |
831e0b71 | 1044 | } else { |
831e0b71 AP |
1045 | gpio &= (~0x01); /* GPIO0 = 0 */ |
1046 | gpio |= 0x10; /* GPIO4 = 1 */ | |
991452a2 | 1047 | gpio &= (~0x04); /* GPIO2 = 1, LED off */ |
831e0b71 | 1048 | sys0 = sys0 & (~0xc0); |
8b036636 AP |
1049 | epa_ctl[0] = 0x10; /* set stall */ |
1050 | epa_ctl[1] = 0x02; /* set reset */ | |
831e0b71 AP |
1051 | } |
1052 | ||
c01a3595 AP |
1053 | dev_dbg(&d->udev->dev, "%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, |
1054 | sys0, gpio); | |
831e0b71 AP |
1055 | |
1056 | /* demod adc */ | |
40a2d3c7 | 1057 | ret = rtl28xx_wr_reg(d, SYS_SYS0, sys0); |
831e0b71 AP |
1058 | if (ret) |
1059 | goto err; | |
1060 | ||
1061 | /* tuner power, write GPIOs */ | |
40a2d3c7 | 1062 | ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, gpio); |
831e0b71 AP |
1063 | if (ret) |
1064 | goto err; | |
1065 | ||
8b036636 AP |
1066 | /* streaming EP: stall & reset */ |
1067 | ret = rtl28xx_wr_regs(d, USB_EPA_CTL, epa_ctl, 2); | |
1068 | if (ret) | |
1069 | goto err; | |
1070 | ||
1071 | if (onoff) | |
1072 | usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x81)); | |
1073 | ||
831e0b71 AP |
1074 | return ret; |
1075 | err: | |
c01a3595 | 1076 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
831e0b71 AP |
1077 | return ret; |
1078 | } | |
1079 | ||
5cf6631e TM |
1080 | static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) |
1081 | { | |
1082 | int ret; | |
5cf6631e | 1083 | |
c01a3595 | 1084 | dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); |
5cf6631e TM |
1085 | |
1086 | if (onoff) { | |
526ca8dc AP |
1087 | /* GPIO3=1, GPIO4=0 */ |
1088 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x08, 0x18); | |
5cf6631e TM |
1089 | if (ret) |
1090 | goto err; | |
1091 | ||
526ca8dc AP |
1092 | /* suspend? */ |
1093 | ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL1, 0x00, 0x10); | |
5cf6631e TM |
1094 | if (ret) |
1095 | goto err; | |
1096 | ||
526ca8dc AP |
1097 | /* enable PLL */ |
1098 | ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x80, 0x80); | |
5cf6631e TM |
1099 | if (ret) |
1100 | goto err; | |
1101 | ||
526ca8dc AP |
1102 | /* disable reset */ |
1103 | ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x20, 0x20); | |
5cf6631e TM |
1104 | if (ret) |
1105 | goto err; | |
1106 | ||
1107 | mdelay(5); | |
1108 | ||
526ca8dc AP |
1109 | /* enable ADC */ |
1110 | ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x48, 0x48); | |
5cf6631e TM |
1111 | if (ret) |
1112 | goto err; | |
1113 | ||
8b036636 AP |
1114 | /* streaming EP: clear stall & reset */ |
1115 | ret = rtl28xx_wr_regs(d, USB_EPA_CTL, "\x00\x00", 2); | |
1116 | if (ret) | |
1117 | goto err; | |
1118 | ||
1119 | ret = usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x81)); | |
1120 | if (ret) | |
1121 | goto err; | |
5cf6631e | 1122 | } else { |
526ca8dc AP |
1123 | /* GPIO4=1 */ |
1124 | ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x10, 0x10); | |
5cf6631e TM |
1125 | if (ret) |
1126 | goto err; | |
1127 | ||
526ca8dc AP |
1128 | /* disable ADC */ |
1129 | ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x48); | |
5cf6631e TM |
1130 | if (ret) |
1131 | goto err; | |
1132 | ||
526ca8dc AP |
1133 | /* disable PLL */ |
1134 | ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x80); | |
5cf6631e TM |
1135 | if (ret) |
1136 | goto err; | |
1137 | ||
8b036636 AP |
1138 | /* streaming EP: set stall & reset */ |
1139 | ret = rtl28xx_wr_regs(d, USB_EPA_CTL, "\x10\x02", 2); | |
1140 | if (ret) | |
1141 | goto err; | |
5cf6631e TM |
1142 | } |
1143 | ||
1144 | return ret; | |
1145 | err: | |
c01a3595 | 1146 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
5cf6631e TM |
1147 | return ret; |
1148 | } | |
1149 | ||
37b44a0f | 1150 | #if IS_ENABLED(CONFIG_RC_CORE) |
b5cbaa43 | 1151 | static int rtl2831u_rc_query(struct dvb_usb_device *d) |
831e0b71 | 1152 | { |
b5cbaa43 AP |
1153 | int ret, i; |
1154 | struct rtl28xxu_priv *priv = d->priv; | |
831e0b71 AP |
1155 | u8 buf[5]; |
1156 | u32 rc_code; | |
b5cbaa43 AP |
1157 | struct rtl28xxu_reg_val rc_nec_tab[] = { |
1158 | { 0x3033, 0x80 }, | |
1159 | { 0x3020, 0x43 }, | |
1160 | { 0x3021, 0x16 }, | |
1161 | { 0x3022, 0x16 }, | |
1162 | { 0x3023, 0x5a }, | |
1163 | { 0x3024, 0x2d }, | |
1164 | { 0x3025, 0x16 }, | |
1165 | { 0x3026, 0x01 }, | |
1166 | { 0x3028, 0xb0 }, | |
1167 | { 0x3029, 0x04 }, | |
1168 | { 0x302c, 0x88 }, | |
1169 | { 0x302e, 0x13 }, | |
1170 | { 0x3030, 0xdf }, | |
1171 | { 0x3031, 0x05 }, | |
1172 | }; | |
1173 | ||
1174 | /* init remote controller */ | |
1175 | if (!priv->rc_active) { | |
1176 | for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { | |
40a2d3c7 | 1177 | ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg, |
9935eea5 | 1178 | rc_nec_tab[i].val); |
b5cbaa43 AP |
1179 | if (ret) |
1180 | goto err; | |
1181 | } | |
1182 | priv->rc_active = true; | |
1183 | } | |
831e0b71 AP |
1184 | |
1185 | ret = rtl2831_rd_regs(d, SYS_IRRC_RP, buf, 5); | |
1186 | if (ret) | |
1187 | goto err; | |
1188 | ||
1189 | if (buf[4] & 0x01) { | |
1190 | if (buf[2] == (u8) ~buf[3]) { | |
1191 | if (buf[0] == (u8) ~buf[1]) { | |
1192 | /* NEC standard (16 bit) */ | |
1193 | rc_code = buf[0] << 8 | buf[2]; | |
1194 | } else { | |
1195 | /* NEC extended (24 bit) */ | |
1196 | rc_code = buf[0] << 16 | | |
9935eea5 | 1197 | buf[1] << 8 | buf[2]; |
831e0b71 AP |
1198 | } |
1199 | } else { | |
1200 | /* NEC full (32 bit) */ | |
1201 | rc_code = buf[0] << 24 | buf[1] << 16 | | |
1202 | buf[2] << 8 | buf[3]; | |
1203 | } | |
1204 | ||
1205 | rc_keydown(d->rc_dev, rc_code, 0); | |
1206 | ||
40a2d3c7 | 1207 | ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1); |
831e0b71 AP |
1208 | if (ret) |
1209 | goto err; | |
1210 | ||
1211 | /* repeated intentionally to avoid extra keypress */ | |
40a2d3c7 | 1212 | ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1); |
831e0b71 AP |
1213 | if (ret) |
1214 | goto err; | |
1215 | } | |
1216 | ||
1217 | return ret; | |
1218 | err: | |
c01a3595 | 1219 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
831e0b71 AP |
1220 | return ret; |
1221 | } | |
1222 | ||
c01a3595 AP |
1223 | static int rtl2831u_get_rc_config(struct dvb_usb_device *d, |
1224 | struct dvb_usb_rc *rc) | |
1225 | { | |
1226 | rc->map_name = RC_MAP_EMPTY; | |
c003ab1b | 1227 | rc->allowed_protos = RC_BIT_NEC; |
c01a3595 AP |
1228 | rc->query = rtl2831u_rc_query; |
1229 | rc->interval = 400; | |
1230 | ||
1231 | return 0; | |
1232 | } | |
1233 | ||
b5cbaa43 AP |
1234 | static int rtl2832u_rc_query(struct dvb_usb_device *d) |
1235 | { | |
f39fac3e | 1236 | int ret, i, len; |
b5cbaa43 | 1237 | struct rtl28xxu_priv *priv = d->priv; |
f39fac3e | 1238 | struct ir_raw_event ev; |
b5cbaa43 | 1239 | u8 buf[128]; |
f39fac3e AP |
1240 | static const struct rtl28xxu_reg_val_mask refresh_tab[] = { |
1241 | {IR_RX_IF, 0x03, 0xff}, | |
1242 | {IR_RX_BUF_CTRL, 0x80, 0xff}, | |
1243 | {IR_RX_CTRL, 0x80, 0xff}, | |
1244 | }; | |
b5cbaa43 AP |
1245 | |
1246 | /* init remote controller */ | |
1247 | if (!priv->rc_active) { | |
f39fac3e AP |
1248 | static const struct rtl28xxu_reg_val_mask init_tab[] = { |
1249 | {SYS_DEMOD_CTL1, 0x00, 0x04}, | |
1250 | {SYS_DEMOD_CTL1, 0x00, 0x08}, | |
1251 | {USB_CTRL, 0x20, 0x20}, | |
1252 | {SYS_GPIO_DIR, 0x00, 0x08}, | |
1253 | {SYS_GPIO_OUT_EN, 0x08, 0x08}, | |
1254 | {SYS_GPIO_OUT_VAL, 0x08, 0x08}, | |
1255 | {IR_MAX_DURATION0, 0xd0, 0xff}, | |
1256 | {IR_MAX_DURATION1, 0x07, 0xff}, | |
1257 | {IR_IDLE_LEN0, 0xc0, 0xff}, | |
1258 | {IR_IDLE_LEN1, 0x00, 0xff}, | |
1259 | {IR_GLITCH_LEN, 0x03, 0xff}, | |
1260 | {IR_RX_CLK, 0x09, 0xff}, | |
1261 | {IR_RX_CFG, 0x1c, 0xff}, | |
1262 | {IR_MAX_H_TOL_LEN, 0x1e, 0xff}, | |
1263 | {IR_MAX_L_TOL_LEN, 0x1e, 0xff}, | |
1264 | {IR_RX_CTRL, 0x80, 0xff}, | |
1265 | }; | |
1266 | ||
1267 | for (i = 0; i < ARRAY_SIZE(init_tab); i++) { | |
1268 | ret = rtl28xx_wr_reg_mask(d, init_tab[i].reg, | |
1269 | init_tab[i].val, init_tab[i].mask); | |
b5cbaa43 AP |
1270 | if (ret) |
1271 | goto err; | |
1272 | } | |
f39fac3e | 1273 | |
b5cbaa43 AP |
1274 | priv->rc_active = true; |
1275 | } | |
1276 | ||
40a2d3c7 | 1277 | ret = rtl28xx_rd_reg(d, IR_RX_IF, &buf[0]); |
b5cbaa43 AP |
1278 | if (ret) |
1279 | goto err; | |
1280 | ||
1281 | if (buf[0] != 0x83) | |
f39fac3e | 1282 | goto exit; |
b5cbaa43 | 1283 | |
40a2d3c7 | 1284 | ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]); |
b5cbaa43 AP |
1285 | if (ret) |
1286 | goto err; | |
1287 | ||
1288 | len = buf[0]; | |
b5cbaa43 | 1289 | |
f39fac3e AP |
1290 | /* read raw code from hw */ |
1291 | ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); | |
1292 | if (ret) | |
1293 | goto err; | |
b5cbaa43 | 1294 | |
f39fac3e AP |
1295 | /* let hw receive new code */ |
1296 | for (i = 0; i < ARRAY_SIZE(refresh_tab); i++) { | |
1297 | ret = rtl28xx_wr_reg_mask(d, refresh_tab[i].reg, | |
1298 | refresh_tab[i].val, refresh_tab[i].mask); | |
1e41413f RT |
1299 | if (ret) |
1300 | goto err; | |
1301 | } | |
b5cbaa43 | 1302 | |
f39fac3e AP |
1303 | /* pass data to Kernel IR decoder */ |
1304 | init_ir_raw_event(&ev); | |
1305 | ||
1306 | for (i = 0; i < len; i++) { | |
1307 | ev.pulse = buf[i] >> 7; | |
1308 | ev.duration = 50800 * (buf[i] & 0x7f); | |
1309 | ir_raw_event_store_with_filter(d->rc_dev, &ev); | |
1310 | } | |
1311 | ||
1312 | /* 'flush' ir_raw_event_store_with_filter() */ | |
1313 | ir_raw_event_set_idle(d->rc_dev, true); | |
1314 | ir_raw_event_handle(d->rc_dev); | |
1315 | exit: | |
b5cbaa43 AP |
1316 | return ret; |
1317 | err: | |
c01a3595 | 1318 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); |
b5cbaa43 AP |
1319 | return ret; |
1320 | } | |
1321 | ||
c01a3595 AP |
1322 | static int rtl2832u_get_rc_config(struct dvb_usb_device *d, |
1323 | struct dvb_usb_rc *rc) | |
1324 | { | |
f39fac3e AP |
1325 | /* load empty to enable rc */ |
1326 | if (!rc->map_name) | |
1327 | rc->map_name = RC_MAP_EMPTY; | |
1e41413f | 1328 | rc->allowed_protos = RC_BIT_ALL; |
f39fac3e | 1329 | rc->driver_type = RC_DRIVER_IR_RAW; |
c01a3595 AP |
1330 | rc->query = rtl2832u_rc_query; |
1331 | rc->interval = 400; | |
831e0b71 | 1332 | |
c01a3595 AP |
1333 | return 0; |
1334 | } | |
cedda370 | 1335 | #else |
5a18664e AP |
1336 | #define rtl2831u_get_rc_config NULL |
1337 | #define rtl2832u_get_rc_config NULL | |
cedda370 | 1338 | #endif |
831e0b71 | 1339 | |
c01a3595 AP |
1340 | static const struct dvb_usb_device_properties rtl2831u_props = { |
1341 | .driver_name = KBUILD_MODNAME, | |
1342 | .owner = THIS_MODULE, | |
1343 | .adapter_nr = adapter_nr, | |
1344 | .size_of_priv = sizeof(struct rtl28xxu_priv), | |
1345 | ||
1346 | .power_ctrl = rtl2831u_power_ctrl, | |
1347 | .i2c_algo = &rtl28xxu_i2c_algo, | |
81347f5a | 1348 | .read_config = rtl2831u_read_config, |
c01a3595 AP |
1349 | .frontend_attach = rtl2831u_frontend_attach, |
1350 | .tuner_attach = rtl2831u_tuner_attach, | |
1351 | .init = rtl28xxu_init, | |
1352 | .get_rc_config = rtl2831u_get_rc_config, | |
c01a3595 AP |
1353 | |
1354 | .num_adapters = 1, | |
1355 | .adapter = { | |
1356 | { | |
1357 | .stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512), | |
831e0b71 | 1358 | }, |
831e0b71 | 1359 | }, |
c01a3595 | 1360 | }; |
b5cbaa43 | 1361 | |
c01a3595 AP |
1362 | static const struct dvb_usb_device_properties rtl2832u_props = { |
1363 | .driver_name = KBUILD_MODNAME, | |
1364 | .owner = THIS_MODULE, | |
1365 | .adapter_nr = adapter_nr, | |
1366 | .size_of_priv = sizeof(struct rtl28xxu_priv), | |
1367 | ||
1368 | .power_ctrl = rtl2832u_power_ctrl, | |
1369 | .i2c_algo = &rtl28xxu_i2c_algo, | |
ef37be1b | 1370 | .read_config = rtl2832u_read_config, |
c01a3595 AP |
1371 | .frontend_attach = rtl2832u_frontend_attach, |
1372 | .tuner_attach = rtl2832u_tuner_attach, | |
1373 | .init = rtl28xxu_init, | |
1374 | .get_rc_config = rtl2832u_get_rc_config, | |
c01a3595 AP |
1375 | |
1376 | .num_adapters = 1, | |
1377 | .adapter = { | |
1378 | { | |
1379 | .stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512), | |
b5cbaa43 | 1380 | }, |
b5cbaa43 | 1381 | }, |
831e0b71 AP |
1382 | }; |
1383 | ||
c01a3595 AP |
1384 | static const struct usb_device_id rtl28xxu_id_table[] = { |
1385 | { DVB_USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U, | |
1386 | &rtl2831u_props, "Realtek RTL2831U reference design", NULL) }, | |
1387 | { DVB_USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT, | |
1388 | &rtl2831u_props, "Freecom USB2.0 DVB-T", NULL) }, | |
1389 | { DVB_USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2, | |
1390 | &rtl2831u_props, "Freecom USB2.0 DVB-T", NULL) }, | |
1391 | ||
254ee2e0 AP |
1392 | { DVB_USB_DEVICE(USB_VID_REALTEK, 0x2832, |
1393 | &rtl2832u_props, "Realtek RTL2832U reference design", NULL) }, | |
1394 | { DVB_USB_DEVICE(USB_VID_REALTEK, 0x2838, | |
1395 | &rtl2832u_props, "Realtek RTL2832U reference design", NULL) }, | |
c01a3595 | 1396 | { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1, |
bc6fc53d | 1397 | &rtl2832u_props, "TerraTec Cinergy T Stick Black", RC_MAP_TERRATEC_SLIM) }, |
c01a3595 AP |
1398 | { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_DELOCK_USB2_DVBT, |
1399 | &rtl2832u_props, "G-Tek Electronics Group Lifeview LV5TDLX DVB-T", NULL) }, | |
1400 | { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK, | |
9db15638 | 1401 | &rtl2832u_props, "TerraTec NOXON DAB Stick", NULL) }, |
e9de0516 | 1402 | { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK_REV2, |
9db15638 | 1403 | &rtl2832u_props, "TerraTec NOXON DAB Stick (rev 2)", NULL) }, |
6d60805f PD |
1404 | { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_TREKSTOR_TERRES_2_0, |
1405 | &rtl2832u_props, "Trekstor DVB-T Stick Terres 2.0", NULL) }, | |
c2d246d1 AP |
1406 | { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1101, |
1407 | &rtl2832u_props, "Dexatek DK DVB-T Dongle", NULL) }, | |
3d8866db AP |
1408 | { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6680, |
1409 | &rtl2832u_props, "DigitalNow Quad DVB-T Receiver", NULL) }, | |
d22d32e1 RB |
1410 | { DVB_USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_MINID, |
1411 | &rtl2832u_props, "Leadtek Winfast DTV Dongle Mini D", NULL) }, | |
a4f64407 AP |
1412 | { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d3, |
1413 | &rtl2832u_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) }, | |
08e57274 AP |
1414 | { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1102, |
1415 | &rtl2832u_props, "Dexatek DK mini DVB-T Dongle", NULL) }, | |
86163adb AK |
1416 | { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d7, |
1417 | &rtl2832u_props, "TerraTec Cinergy T Stick+", NULL) }, | |
3971e79a AP |
1418 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd3a8, |
1419 | &rtl2832u_props, "ASUS My Cinema-U3100Mini Plus V2", NULL) }, | |
78a5e709 | 1420 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd393, |
9db15638 | 1421 | &rtl2832u_props, "GIGABYTE U7300", NULL) }, |
09f9408d | 1422 | { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1104, |
7dc0a016 | 1423 | &rtl2832u_props, "MSI DIGIVOX Micro HD", NULL) }, |
b9e2afff AB |
1424 | { DVB_USB_DEVICE(USB_VID_COMPRO, 0x0620, |
1425 | &rtl2832u_props, "Compro VideoMate U620F", NULL) }, | |
e6a60d76 FG |
1426 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd394, |
1427 | &rtl2832u_props, "MaxMedia HU394-T", NULL) }, | |
6c5a4065 | 1428 | { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a03, |
7dc0a016 | 1429 | &rtl2832u_props, "Leadtek WinFast DTV Dongle mini", NULL) }, |
c6be7526 | 1430 | { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_CPYTO_REDI_PC50A, |
7df27256 | 1431 | &rtl2832u_props, "Crypto ReDi PC 50 A", NULL) }, |
8fdd33b1 AP |
1432 | |
1433 | { DVB_USB_DEVICE(USB_VID_HANFTEK, 0x0131, | |
1434 | &rtl2832u_props, "Astrometa DVB-T2", NULL) }, | |
c01a3595 AP |
1435 | { } |
1436 | }; | |
1437 | MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table); | |
1438 | ||
1439 | static struct usb_driver rtl28xxu_usb_driver = { | |
1440 | .name = KBUILD_MODNAME, | |
1441 | .id_table = rtl28xxu_id_table, | |
1442 | .probe = dvb_usbv2_probe, | |
1443 | .disconnect = dvb_usbv2_disconnect, | |
1444 | .suspend = dvb_usbv2_suspend, | |
1445 | .resume = dvb_usbv2_resume, | |
78fa5903 | 1446 | .reset_resume = dvb_usbv2_reset_resume, |
c01a3595 AP |
1447 | .no_dynamic_id = 1, |
1448 | .soft_unbind = 1, | |
831e0b71 AP |
1449 | }; |
1450 | ||
c01a3595 | 1451 | module_usb_driver(rtl28xxu_usb_driver); |
831e0b71 AP |
1452 | |
1453 | MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver"); | |
1454 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | |
5cf6631e | 1455 | MODULE_AUTHOR("Thomas Mair <thomas.mair86@googlemail.com>"); |
831e0b71 | 1456 | MODULE_LICENSE("GPL"); |