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