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