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