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