1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * ngene-cards.c: nGene PCIe bridge driver - card specific info |
4 | * |
5 | * Copyright (C) 2005-2007 Micronas |
6 | * |
7 | * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de> |
8 | * Modifications for new nGene firmware, |
9 | * support for EEPROM-copying, |
10 | * support for new dual DVB-S2 card prototype |
11 | */ |
12 | |
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
14 | |
15 | #include <linux/module.h> |
16 | #include <linux/init.h> |
17 | #include <linux/pci.h> |
18 | #include <linux/pci_ids.h> |
19 | |
20 | #include "ngene.h" |
21 | |
22 | /* demods/tuners */ |
23 | #include "stv6110x.h" |
24 | #include "stv090x.h" |
25 | #include "lnbh24.h" |
26 | #include "lgdt330x.h" |
27 | #include "mt2131.h" |
28 | #include "tda18271c2dd.h" |
29 | #include "drxk.h" |
30 | #include "drxd.h" |
31 | #include "dvb-pll.h" |
32 | #include "stv0367.h" |
33 | #include "stv0367_priv.h" |
34 | #include "tda18212.h" |
35 | #include "cxd2841er.h" |
36 | #include "stv0910.h" |
37 | #include "stv6111.h" |
38 | #include "lnbh25.h" |
39 | |
40 | /****************************************************************************/ |
41 | /* I2C transfer functions used for demod/tuner probing***********************/ |
42 | /****************************************************************************/ |
43 | |
44 | static int i2c_io(struct i2c_adapter *adapter, u8 adr, |
45 | u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) |
46 | { |
47 | struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, |
48 | .buf = wbuf, .len = wlen }, |
49 | {.addr = adr, .flags = I2C_M_RD, |
50 | .buf = rbuf, .len = rlen } }; |
51 | return (i2c_transfer(adap: adapter, msgs, num: 2) == 2) ? 0 : -1; |
52 | } |
53 | |
54 | static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) |
55 | { |
56 | struct i2c_msg msg = {.addr = adr, .flags = 0, |
57 | .buf = data, .len = len}; |
58 | |
59 | return (i2c_transfer(adap, msgs: &msg, num: 1) == 1) ? 0 : -1; |
60 | } |
61 | |
62 | static int i2c_write_reg(struct i2c_adapter *adap, u8 adr, |
63 | u8 reg, u8 val) |
64 | { |
65 | u8 msg[2] = {reg, val}; |
66 | |
67 | return i2c_write(adap, adr, data: msg, len: 2); |
68 | } |
69 | |
70 | static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) |
71 | { |
72 | struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, |
73 | .buf = val, .len = 1 } }; |
74 | return (i2c_transfer(adap: adapter, msgs, num: 1) == 1) ? 0 : -1; |
75 | } |
76 | |
77 | static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, |
78 | u16 reg, u8 *val) |
79 | { |
80 | u8 msg[2] = {reg >> 8, reg & 0xff}; |
81 | struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, |
82 | .buf = msg, .len = 2}, |
83 | {.addr = adr, .flags = I2C_M_RD, |
84 | .buf = val, .len = 1} }; |
85 | return (i2c_transfer(adap: adapter, msgs, num: 2) == 2) ? 0 : -1; |
86 | } |
87 | |
88 | static int i2c_read_regs(struct i2c_adapter *adapter, |
89 | u8 adr, u8 reg, u8 *val, u8 len) |
90 | { |
91 | struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, |
92 | .buf = ®, .len = 1}, |
93 | {.addr = adr, .flags = I2C_M_RD, |
94 | .buf = val, .len = len} }; |
95 | |
96 | return (i2c_transfer(adap: adapter, msgs, num: 2) == 2) ? 0 : -1; |
97 | } |
98 | |
99 | static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val) |
100 | { |
101 | return i2c_read_regs(adapter, adr, reg, val, len: 1); |
102 | } |
103 | |
104 | /****************************************************************************/ |
105 | /* Demod/tuner attachment ***************************************************/ |
106 | /****************************************************************************/ |
107 | |
108 | static struct i2c_adapter *i2c_adapter_from_chan(struct ngene_channel *chan) |
109 | { |
110 | /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */ |
111 | if (chan->number < 2) |
112 | return &chan->dev->channel[0].i2c_adapter; |
113 | |
114 | return &chan->dev->channel[1].i2c_adapter; |
115 | } |
116 | |
117 | static int tuner_attach_stv6110(struct ngene_channel *chan) |
118 | { |
119 | struct device *pdev = &chan->dev->pci_dev->dev; |
120 | struct i2c_adapter *i2c = i2c_adapter_from_chan(chan); |
121 | struct stv090x_config *feconf = (struct stv090x_config *) |
122 | chan->dev->card_info->fe_config[chan->number]; |
123 | struct stv6110x_config *tunerconf = (struct stv6110x_config *) |
124 | chan->dev->card_info->tuner_config[chan->number]; |
125 | const struct stv6110x_devctl *ctl; |
126 | |
127 | ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf, i2c); |
128 | if (ctl == NULL) { |
129 | dev_err(pdev, "No STV6110X found!\n" ); |
130 | return -ENODEV; |
131 | } |
132 | |
133 | feconf->tuner_init = ctl->tuner_init; |
134 | feconf->tuner_sleep = ctl->tuner_sleep; |
135 | feconf->tuner_set_mode = ctl->tuner_set_mode; |
136 | feconf->tuner_set_frequency = ctl->tuner_set_frequency; |
137 | feconf->tuner_get_frequency = ctl->tuner_get_frequency; |
138 | feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth; |
139 | feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth; |
140 | feconf->tuner_set_bbgain = ctl->tuner_set_bbgain; |
141 | feconf->tuner_get_bbgain = ctl->tuner_get_bbgain; |
142 | feconf->tuner_set_refclk = ctl->tuner_set_refclk; |
143 | feconf->tuner_get_status = ctl->tuner_get_status; |
144 | |
145 | return 0; |
146 | } |
147 | |
148 | static int tuner_attach_stv6111(struct ngene_channel *chan) |
149 | { |
150 | struct device *pdev = &chan->dev->pci_dev->dev; |
151 | struct i2c_adapter *i2c = i2c_adapter_from_chan(chan); |
152 | struct dvb_frontend *fe; |
153 | u8 adr = 4 + ((chan->number & 1) ? 0x63 : 0x60); |
154 | |
155 | fe = dvb_attach(stv6111_attach, chan->fe, i2c, adr); |
156 | if (!fe) { |
157 | fe = dvb_attach(stv6111_attach, chan->fe, i2c, adr & ~4); |
158 | if (!fe) { |
159 | dev_err(pdev, "stv6111_attach() failed!\n" ); |
160 | return -ENODEV; |
161 | } |
162 | } |
163 | return 0; |
164 | } |
165 | |
166 | static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) |
167 | { |
168 | struct ngene_channel *chan = fe->sec_priv; |
169 | int status; |
170 | |
171 | if (enable) { |
172 | down(sem: &chan->dev->pll_mutex); |
173 | status = chan->gate_ctrl(fe, 1); |
174 | } else { |
175 | status = chan->gate_ctrl(fe, 0); |
176 | up(sem: &chan->dev->pll_mutex); |
177 | } |
178 | return status; |
179 | } |
180 | |
181 | static int tuner_attach_tda18271(struct ngene_channel *chan) |
182 | { |
183 | struct device *pdev = &chan->dev->pci_dev->dev; |
184 | struct i2c_adapter *i2c = i2c_adapter_from_chan(chan); |
185 | struct dvb_frontend *fe; |
186 | |
187 | if (chan->fe->ops.i2c_gate_ctrl) |
188 | chan->fe->ops.i2c_gate_ctrl(chan->fe, 1); |
189 | fe = dvb_attach(tda18271c2dd_attach, chan->fe, i2c, 0x60); |
190 | if (chan->fe->ops.i2c_gate_ctrl) |
191 | chan->fe->ops.i2c_gate_ctrl(chan->fe, 0); |
192 | if (!fe) { |
193 | dev_err(pdev, "No TDA18271 found!\n" ); |
194 | return -ENODEV; |
195 | } |
196 | |
197 | return 0; |
198 | } |
199 | |
200 | static int tuner_tda18212_ping(struct ngene_channel *chan, |
201 | struct i2c_adapter *i2c, |
202 | unsigned short adr) |
203 | { |
204 | struct device *pdev = &chan->dev->pci_dev->dev; |
205 | u8 tda_id[2]; |
206 | u8 subaddr = 0x00; |
207 | |
208 | dev_dbg(pdev, "stv0367-tda18212 tuner ping\n" ); |
209 | if (chan->fe->ops.i2c_gate_ctrl) |
210 | chan->fe->ops.i2c_gate_ctrl(chan->fe, 1); |
211 | |
212 | if (i2c_read_regs(adapter: i2c, adr, reg: subaddr, val: tda_id, len: sizeof(tda_id)) < 0) |
213 | dev_dbg(pdev, "tda18212 ping 1 fail\n" ); |
214 | if (i2c_read_regs(adapter: i2c, adr, reg: subaddr, val: tda_id, len: sizeof(tda_id)) < 0) |
215 | dev_warn(pdev, "tda18212 ping failed, expect problems\n" ); |
216 | |
217 | if (chan->fe->ops.i2c_gate_ctrl) |
218 | chan->fe->ops.i2c_gate_ctrl(chan->fe, 0); |
219 | |
220 | return 0; |
221 | } |
222 | |
223 | static int tuner_attach_tda18212(struct ngene_channel *chan, u32 dmdtype) |
224 | { |
225 | struct device *pdev = &chan->dev->pci_dev->dev; |
226 | struct i2c_adapter *i2c = i2c_adapter_from_chan(chan); |
227 | struct i2c_client *client; |
228 | struct tda18212_config config = { |
229 | .fe = chan->fe, |
230 | .if_dvbt_6 = 3550, |
231 | .if_dvbt_7 = 3700, |
232 | .if_dvbt_8 = 4150, |
233 | .if_dvbt2_6 = 3250, |
234 | .if_dvbt2_7 = 4000, |
235 | .if_dvbt2_8 = 4000, |
236 | .if_dvbc = 5000, |
237 | }; |
238 | u8 addr = (chan->number & 1) ? 0x63 : 0x60; |
239 | |
240 | /* |
241 | * due to a hardware quirk with the I2C gate on the stv0367+tda18212 |
242 | * combo, the tda18212 must be probed by reading it's id _twice_ when |
243 | * cold started, or it very likely will fail. |
244 | */ |
245 | if (dmdtype == DEMOD_TYPE_STV0367) |
246 | tuner_tda18212_ping(chan, i2c, adr: addr); |
247 | |
248 | /* perform tuner probe/init/attach */ |
249 | client = dvb_module_probe(module_name: "tda18212" , NULL, adap: i2c, addr, platform_data: &config); |
250 | if (!client) |
251 | goto err; |
252 | |
253 | chan->i2c_client[0] = client; |
254 | chan->i2c_client_fe = 1; |
255 | |
256 | return 0; |
257 | err: |
258 | dev_err(pdev, "TDA18212 tuner not found. Device is not fully operational.\n" ); |
259 | return -ENODEV; |
260 | } |
261 | |
262 | static int tuner_attach_probe(struct ngene_channel *chan) |
263 | { |
264 | switch (chan->demod_type) { |
265 | case DEMOD_TYPE_STV090X: |
266 | return tuner_attach_stv6110(chan); |
267 | case DEMOD_TYPE_DRXK: |
268 | return tuner_attach_tda18271(chan); |
269 | case DEMOD_TYPE_STV0367: |
270 | case DEMOD_TYPE_SONY_CT2: |
271 | case DEMOD_TYPE_SONY_ISDBT: |
272 | case DEMOD_TYPE_SONY_C2T2: |
273 | case DEMOD_TYPE_SONY_C2T2I: |
274 | return tuner_attach_tda18212(chan, dmdtype: chan->demod_type); |
275 | case DEMOD_TYPE_STV0910: |
276 | return tuner_attach_stv6111(chan); |
277 | } |
278 | |
279 | return -EINVAL; |
280 | } |
281 | |
282 | static int demod_attach_stv0900(struct ngene_channel *chan) |
283 | { |
284 | struct device *pdev = &chan->dev->pci_dev->dev; |
285 | struct i2c_adapter *i2c = i2c_adapter_from_chan(chan); |
286 | struct stv090x_config *feconf = (struct stv090x_config *) |
287 | chan->dev->card_info->fe_config[chan->number]; |
288 | |
289 | chan->fe = dvb_attach(stv090x_attach, feconf, i2c, |
290 | (chan->number & 1) == 0 ? STV090x_DEMODULATOR_0 |
291 | : STV090x_DEMODULATOR_1); |
292 | if (chan->fe == NULL) { |
293 | dev_err(pdev, "No STV0900 found!\n" ); |
294 | return -ENODEV; |
295 | } |
296 | |
297 | /* store channel info */ |
298 | if (feconf->tuner_i2c_lock) |
299 | chan->fe->analog_demod_priv = chan; |
300 | |
301 | if (!dvb_attach(lnbh24_attach, chan->fe, i2c, 0, |
302 | 0, chan->dev->card_info->lnb[chan->number])) { |
303 | dev_err(pdev, "No LNBH24 found!\n" ); |
304 | dvb_frontend_detach(fe: chan->fe); |
305 | chan->fe = NULL; |
306 | return -ENODEV; |
307 | } |
308 | |
309 | return 0; |
310 | } |
311 | |
312 | static struct stv0910_cfg stv0910_p = { |
313 | .adr = 0x68, |
314 | .parallel = 1, |
315 | .rptlvl = 4, |
316 | .clk = 30000000, |
317 | .tsspeed = 0x28, |
318 | }; |
319 | |
320 | static struct lnbh25_config lnbh25_cfg = { |
321 | .i2c_address = 0x0c << 1, |
322 | .data2_config = LNBH25_TEN |
323 | }; |
324 | |
325 | static int demod_attach_stv0910(struct ngene_channel *chan, |
326 | struct i2c_adapter *i2c) |
327 | { |
328 | struct device *pdev = &chan->dev->pci_dev->dev; |
329 | struct stv0910_cfg cfg = stv0910_p; |
330 | struct lnbh25_config lnbcfg = lnbh25_cfg; |
331 | |
332 | chan->fe = dvb_attach(stv0910_attach, i2c, &cfg, (chan->number & 1)); |
333 | if (!chan->fe) { |
334 | cfg.adr = 0x6c; |
335 | chan->fe = dvb_attach(stv0910_attach, i2c, |
336 | &cfg, (chan->number & 1)); |
337 | } |
338 | if (!chan->fe) { |
339 | dev_err(pdev, "stv0910_attach() failed!\n" ); |
340 | return -ENODEV; |
341 | } |
342 | |
343 | /* |
344 | * attach lnbh25 - leftshift by one as the lnbh25 driver expects 8bit |
345 | * i2c addresses |
346 | */ |
347 | lnbcfg.i2c_address = (((chan->number & 1) ? 0x0d : 0x0c) << 1); |
348 | if (!dvb_attach(lnbh25_attach, chan->fe, &lnbcfg, i2c)) { |
349 | lnbcfg.i2c_address = (((chan->number & 1) ? 0x09 : 0x08) << 1); |
350 | if (!dvb_attach(lnbh25_attach, chan->fe, &lnbcfg, i2c)) { |
351 | dev_err(pdev, "lnbh25_attach() failed!\n" ); |
352 | dvb_frontend_detach(fe: chan->fe); |
353 | chan->fe = NULL; |
354 | return -ENODEV; |
355 | } |
356 | } |
357 | |
358 | return 0; |
359 | } |
360 | |
361 | static struct stv0367_config ddb_stv0367_config[] = { |
362 | { |
363 | .demod_address = 0x1f, |
364 | .xtal = 27000000, |
365 | .if_khz = 0, |
366 | .if_iq_mode = FE_TER_NORMAL_IF_TUNER, |
367 | .ts_mode = STV0367_SERIAL_PUNCT_CLOCK, |
368 | .clk_pol = STV0367_CLOCKPOLARITY_DEFAULT, |
369 | }, { |
370 | .demod_address = 0x1e, |
371 | .xtal = 27000000, |
372 | .if_khz = 0, |
373 | .if_iq_mode = FE_TER_NORMAL_IF_TUNER, |
374 | .ts_mode = STV0367_SERIAL_PUNCT_CLOCK, |
375 | .clk_pol = STV0367_CLOCKPOLARITY_DEFAULT, |
376 | }, |
377 | }; |
378 | |
379 | static int demod_attach_stv0367(struct ngene_channel *chan, |
380 | struct i2c_adapter *i2c) |
381 | { |
382 | struct device *pdev = &chan->dev->pci_dev->dev; |
383 | |
384 | chan->fe = dvb_attach(stv0367ddb_attach, |
385 | &ddb_stv0367_config[(chan->number & 1)], i2c); |
386 | |
387 | if (!chan->fe) { |
388 | dev_err(pdev, "stv0367ddb_attach() failed!\n" ); |
389 | return -ENODEV; |
390 | } |
391 | |
392 | chan->fe->sec_priv = chan; |
393 | chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl; |
394 | chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; |
395 | return 0; |
396 | } |
397 | |
398 | static int demod_attach_cxd28xx(struct ngene_channel *chan, |
399 | struct i2c_adapter *i2c, int osc24) |
400 | { |
401 | struct device *pdev = &chan->dev->pci_dev->dev; |
402 | struct cxd2841er_config cfg; |
403 | |
404 | /* the cxd2841er driver expects 8bit/shifted I2C addresses */ |
405 | cfg.i2c_addr = ((chan->number & 1) ? 0x6d : 0x6c) << 1; |
406 | |
407 | cfg.xtal = osc24 ? SONY_XTAL_24000 : SONY_XTAL_20500; |
408 | cfg.flags = CXD2841ER_AUTO_IFHZ | CXD2841ER_EARLY_TUNE | |
409 | CXD2841ER_NO_WAIT_LOCK | CXD2841ER_NO_AGCNEG | |
410 | CXD2841ER_TSBITS | CXD2841ER_TS_SERIAL; |
411 | |
412 | /* attach frontend */ |
413 | chan->fe = dvb_attach(cxd2841er_attach_t_c, &cfg, i2c); |
414 | |
415 | if (!chan->fe) { |
416 | dev_err(pdev, "CXD28XX attach failed!\n" ); |
417 | return -ENODEV; |
418 | } |
419 | |
420 | chan->fe->sec_priv = chan; |
421 | chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl; |
422 | chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; |
423 | return 0; |
424 | } |
425 | |
426 | static void cineS2_tuner_i2c_lock(struct dvb_frontend *fe, int lock) |
427 | { |
428 | struct ngene_channel *chan = fe->analog_demod_priv; |
429 | |
430 | if (lock) |
431 | down(sem: &chan->dev->pll_mutex); |
432 | else |
433 | up(sem: &chan->dev->pll_mutex); |
434 | } |
435 | |
436 | static int port_has_stv0900(struct i2c_adapter *i2c, int port) |
437 | { |
438 | u8 val; |
439 | if (i2c_read_reg16(adapter: i2c, adr: 0x68+port/2, reg: 0xf100, val: &val) < 0) |
440 | return 0; |
441 | return 1; |
442 | } |
443 | |
444 | static int port_has_drxk(struct i2c_adapter *i2c, int port) |
445 | { |
446 | u8 val; |
447 | |
448 | if (i2c_read(adapter: i2c, adr: 0x29+port, val: &val) < 0) |
449 | return 0; |
450 | return 1; |
451 | } |
452 | |
453 | static int port_has_stv0367(struct i2c_adapter *i2c) |
454 | { |
455 | u8 val; |
456 | |
457 | if (i2c_read_reg16(adapter: i2c, adr: 0x1e, reg: 0xf000, val: &val) < 0) |
458 | return 0; |
459 | if (val != 0x60) |
460 | return 0; |
461 | if (i2c_read_reg16(adapter: i2c, adr: 0x1f, reg: 0xf000, val: &val) < 0) |
462 | return 0; |
463 | if (val != 0x60) |
464 | return 0; |
465 | return 1; |
466 | } |
467 | |
468 | int ngene_port_has_cxd2099(struct i2c_adapter *i2c, u8 *type) |
469 | { |
470 | u8 val; |
471 | u8 probe[4] = { 0xe0, 0x00, 0x00, 0x00 }, data[4]; |
472 | struct i2c_msg msgs[2] = {{ .addr = 0x40, .flags = 0, |
473 | .buf = probe, .len = 4 }, |
474 | { .addr = 0x40, .flags = I2C_M_RD, |
475 | .buf = data, .len = 4 } }; |
476 | val = i2c_transfer(adap: i2c, msgs, num: 2); |
477 | if (val != 2) |
478 | return 0; |
479 | |
480 | if (data[0] == 0x02 && data[1] == 0x2b && data[3] == 0x43) |
481 | *type = 2; |
482 | else |
483 | *type = 1; |
484 | return 1; |
485 | } |
486 | |
487 | static int demod_attach_drxk(struct ngene_channel *chan, |
488 | struct i2c_adapter *i2c) |
489 | { |
490 | struct device *pdev = &chan->dev->pci_dev->dev; |
491 | struct drxk_config config; |
492 | |
493 | memset(&config, 0, sizeof(config)); |
494 | config.microcode_name = "drxk_a3.mc" ; |
495 | config.qam_demod_parameter_count = 4; |
496 | config.adr = 0x29 + (chan->number ^ 2); |
497 | |
498 | chan->fe = dvb_attach(drxk_attach, &config, i2c); |
499 | if (!chan->fe) { |
500 | dev_err(pdev, "No DRXK found!\n" ); |
501 | return -ENODEV; |
502 | } |
503 | chan->fe->sec_priv = chan; |
504 | chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl; |
505 | chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; |
506 | return 0; |
507 | } |
508 | |
509 | /****************************************************************************/ |
510 | /* XO2 related lists and functions ******************************************/ |
511 | /****************************************************************************/ |
512 | |
513 | static char *xo2names[] = { |
514 | "DUAL DVB-S2" , |
515 | "DUAL DVB-C/T/T2" , |
516 | "DUAL DVB-ISDBT" , |
517 | "DUAL DVB-C/C2/T/T2" , |
518 | "DUAL ATSC" , |
519 | "DUAL DVB-C/C2/T/T2/I" , |
520 | }; |
521 | |
522 | static int init_xo2(struct ngene_channel *chan, struct i2c_adapter *i2c) |
523 | { |
524 | struct device *pdev = &chan->dev->pci_dev->dev; |
525 | u8 addr = 0x10; |
526 | u8 val, data[2]; |
527 | int res; |
528 | |
529 | res = i2c_read_regs(adapter: i2c, adr: addr, reg: 0x04, val: data, len: 2); |
530 | if (res < 0) |
531 | return res; |
532 | |
533 | if (data[0] != 0x01) { |
534 | dev_info(pdev, "Invalid XO2 on channel %d\n" , chan->number); |
535 | return -1; |
536 | } |
537 | |
538 | i2c_read_reg(adapter: i2c, adr: addr, reg: 0x08, val: &val); |
539 | if (val != 0) { |
540 | i2c_write_reg(adap: i2c, adr: addr, reg: 0x08, val: 0x00); |
541 | msleep(msecs: 100); |
542 | } |
543 | /* Enable tuner power, disable pll, reset demods */ |
544 | i2c_write_reg(adap: i2c, adr: addr, reg: 0x08, val: 0x04); |
545 | usleep_range(min: 2000, max: 3000); |
546 | /* Release demod resets */ |
547 | i2c_write_reg(adap: i2c, adr: addr, reg: 0x08, val: 0x07); |
548 | |
549 | /* |
550 | * speed: 0=55,1=75,2=90,3=104 MBit/s |
551 | * Note: The ngene hardware must be run at 75 MBit/s compared |
552 | * to more modern ddbridge hardware which runs at 90 MBit/s, |
553 | * else there will be issues with the data transport and non- |
554 | * working secondary/slave demods/tuners. |
555 | */ |
556 | i2c_write_reg(adap: i2c, adr: addr, reg: 0x09, val: 1); |
557 | |
558 | i2c_write_reg(adap: i2c, adr: addr, reg: 0x0a, val: 0x01); |
559 | i2c_write_reg(adap: i2c, adr: addr, reg: 0x0b, val: 0x01); |
560 | |
561 | usleep_range(min: 2000, max: 3000); |
562 | /* Start XO2 PLL */ |
563 | i2c_write_reg(adap: i2c, adr: addr, reg: 0x08, val: 0x87); |
564 | |
565 | return 0; |
566 | } |
567 | |
568 | static int port_has_xo2(struct i2c_adapter *i2c, u8 *type, u8 *id) |
569 | { |
570 | u8 probe[1] = { 0x00 }, data[4]; |
571 | u8 addr = 0x10; |
572 | |
573 | *type = NGENE_XO2_TYPE_NONE; |
574 | |
575 | if (i2c_io(adapter: i2c, adr: addr, wbuf: probe, wlen: 1, rbuf: data, rlen: 4)) |
576 | return 0; |
577 | if (data[0] == 'D' && data[1] == 'F') { |
578 | *id = data[2]; |
579 | *type = NGENE_XO2_TYPE_DUOFLEX; |
580 | return 1; |
581 | } |
582 | if (data[0] == 'C' && data[1] == 'I') { |
583 | *id = data[2]; |
584 | *type = NGENE_XO2_TYPE_CI; |
585 | return 1; |
586 | } |
587 | return 0; |
588 | } |
589 | |
590 | /****************************************************************************/ |
591 | /* Probing and port/channel handling ****************************************/ |
592 | /****************************************************************************/ |
593 | |
594 | static int cineS2_probe(struct ngene_channel *chan) |
595 | { |
596 | struct device *pdev = &chan->dev->pci_dev->dev; |
597 | struct i2c_adapter *i2c = i2c_adapter_from_chan(chan); |
598 | struct stv090x_config *fe_conf; |
599 | u8 buf[3]; |
600 | u8 xo2_type, xo2_id, xo2_demodtype; |
601 | u8 sony_osc24 = 0; |
602 | struct i2c_msg i2c_msg = { .flags = 0, .buf = buf }; |
603 | int rc; |
604 | |
605 | if (port_has_xo2(i2c, type: &xo2_type, id: &xo2_id)) { |
606 | xo2_id >>= 2; |
607 | dev_dbg(pdev, "XO2 on channel %d (type %d, id %d)\n" , |
608 | chan->number, xo2_type, xo2_id); |
609 | |
610 | switch (xo2_type) { |
611 | case NGENE_XO2_TYPE_DUOFLEX: |
612 | if (chan->number & 1) |
613 | dev_dbg(pdev, |
614 | "skipping XO2 init on odd channel %d" , |
615 | chan->number); |
616 | else |
617 | init_xo2(chan, i2c); |
618 | |
619 | xo2_demodtype = DEMOD_TYPE_XO2 + xo2_id; |
620 | |
621 | switch (xo2_demodtype) { |
622 | case DEMOD_TYPE_SONY_CT2: |
623 | case DEMOD_TYPE_SONY_ISDBT: |
624 | case DEMOD_TYPE_SONY_C2T2: |
625 | case DEMOD_TYPE_SONY_C2T2I: |
626 | dev_info(pdev, "%s (XO2) on channel %d\n" , |
627 | xo2names[xo2_id], chan->number); |
628 | chan->demod_type = xo2_demodtype; |
629 | if (xo2_demodtype == DEMOD_TYPE_SONY_C2T2I) |
630 | sony_osc24 = 1; |
631 | |
632 | demod_attach_cxd28xx(chan, i2c, osc24: sony_osc24); |
633 | break; |
634 | case DEMOD_TYPE_STV0910: |
635 | dev_info(pdev, "%s (XO2) on channel %d\n" , |
636 | xo2names[xo2_id], chan->number); |
637 | chan->demod_type = xo2_demodtype; |
638 | demod_attach_stv0910(chan, i2c); |
639 | break; |
640 | default: |
641 | dev_warn(pdev, |
642 | "Unsupported XO2 module on channel %d\n" , |
643 | chan->number); |
644 | return -ENODEV; |
645 | } |
646 | break; |
647 | case NGENE_XO2_TYPE_CI: |
648 | dev_info(pdev, "DuoFlex CI modules not supported\n" ); |
649 | return -ENODEV; |
650 | default: |
651 | dev_info(pdev, "Unsupported XO2 module type\n" ); |
652 | return -ENODEV; |
653 | } |
654 | } else if (port_has_stv0900(i2c, port: chan->number)) { |
655 | chan->demod_type = DEMOD_TYPE_STV090X; |
656 | fe_conf = chan->dev->card_info->fe_config[chan->number]; |
657 | /* demod found, attach it */ |
658 | rc = demod_attach_stv0900(chan); |
659 | if (rc < 0 || chan->number < 2) |
660 | return rc; |
661 | |
662 | /* demod #2: reprogram outputs DPN1 & DPN2 */ |
663 | i2c_msg.addr = fe_conf->address; |
664 | i2c_msg.len = 3; |
665 | buf[0] = 0xf1; |
666 | switch (chan->number) { |
667 | case 2: |
668 | buf[1] = 0x5c; |
669 | buf[2] = 0xc2; |
670 | break; |
671 | case 3: |
672 | buf[1] = 0x61; |
673 | buf[2] = 0xcc; |
674 | break; |
675 | default: |
676 | return -ENODEV; |
677 | } |
678 | rc = i2c_transfer(adap: i2c, msgs: &i2c_msg, num: 1); |
679 | if (rc != 1) { |
680 | dev_err(pdev, "Could not setup DPNx\n" ); |
681 | return -EIO; |
682 | } |
683 | } else if (port_has_drxk(i2c, port: chan->number^2)) { |
684 | chan->demod_type = DEMOD_TYPE_DRXK; |
685 | demod_attach_drxk(chan, i2c); |
686 | } else if (port_has_stv0367(i2c)) { |
687 | chan->demod_type = DEMOD_TYPE_STV0367; |
688 | dev_info(pdev, "STV0367 on channel %d\n" , chan->number); |
689 | demod_attach_stv0367(chan, i2c); |
690 | } else { |
691 | dev_info(pdev, "No demod found on chan %d\n" , chan->number); |
692 | return -ENODEV; |
693 | } |
694 | return 0; |
695 | } |
696 | |
697 | |
698 | static struct lgdt330x_config aver_m780 = { |
699 | .demod_chip = LGDT3303, |
700 | .serial_mpeg = 0x00, /* PARALLEL */ |
701 | .clock_polarity_flip = 1, |
702 | }; |
703 | |
704 | static struct mt2131_config m780_tunerconfig = { |
705 | 0xc0 >> 1 |
706 | }; |
707 | |
708 | /* A single func to attach the demo and tuner, rather than |
709 | * use two sep funcs like the current design mandates. |
710 | */ |
711 | static int demod_attach_lg330x(struct ngene_channel *chan) |
712 | { |
713 | struct device *pdev = &chan->dev->pci_dev->dev; |
714 | |
715 | chan->fe = dvb_attach(lgdt330x_attach, &aver_m780, |
716 | 0xb2 >> 1, &chan->i2c_adapter); |
717 | if (chan->fe == NULL) { |
718 | dev_err(pdev, "No LGDT330x found!\n" ); |
719 | return -ENODEV; |
720 | } |
721 | |
722 | dvb_attach(mt2131_attach, chan->fe, &chan->i2c_adapter, |
723 | &m780_tunerconfig, 0); |
724 | |
725 | return (chan->fe) ? 0 : -ENODEV; |
726 | } |
727 | |
728 | static int demod_attach_drxd(struct ngene_channel *chan) |
729 | { |
730 | struct device *pdev = &chan->dev->pci_dev->dev; |
731 | struct drxd_config *feconf; |
732 | |
733 | feconf = chan->dev->card_info->fe_config[chan->number]; |
734 | |
735 | chan->fe = dvb_attach(drxd_attach, feconf, chan, |
736 | &chan->i2c_adapter, &chan->dev->pci_dev->dev); |
737 | if (!chan->fe) { |
738 | dev_err(pdev, "No DRXD found!\n" ); |
739 | return -ENODEV; |
740 | } |
741 | return 0; |
742 | } |
743 | |
744 | static int tuner_attach_dtt7520x(struct ngene_channel *chan) |
745 | { |
746 | struct device *pdev = &chan->dev->pci_dev->dev; |
747 | struct drxd_config *feconf; |
748 | |
749 | feconf = chan->dev->card_info->fe_config[chan->number]; |
750 | |
751 | if (!dvb_attach(dvb_pll_attach, chan->fe, feconf->pll_address, |
752 | &chan->i2c_adapter, |
753 | feconf->pll_type)) { |
754 | dev_err(pdev, "No pll(%d) found!\n" , feconf->pll_type); |
755 | return -ENODEV; |
756 | } |
757 | return 0; |
758 | } |
759 | |
760 | /****************************************************************************/ |
761 | /* EEPROM TAGS **************************************************************/ |
762 | /****************************************************************************/ |
763 | |
764 | #define MICNG_EE_START 0x0100 |
765 | #define MICNG_EE_END 0x0FF0 |
766 | |
767 | #define MICNG_EETAG_END0 0x0000 |
768 | #define MICNG_EETAG_END1 0xFFFF |
769 | |
770 | /* 0x0001 - 0x000F reserved for housekeeping */ |
771 | /* 0xFFFF - 0xFFFE reserved for housekeeping */ |
772 | |
773 | /* Micronas assigned tags |
774 | EEProm tags for hardware support */ |
775 | |
776 | #define MICNG_EETAG_DRXD1_OSCDEVIATION 0x1000 /* 2 Bytes data */ |
777 | #define MICNG_EETAG_DRXD2_OSCDEVIATION 0x1001 /* 2 Bytes data */ |
778 | |
779 | #define MICNG_EETAG_MT2060_1_1STIF 0x1100 /* 2 Bytes data */ |
780 | #define MICNG_EETAG_MT2060_2_1STIF 0x1101 /* 2 Bytes data */ |
781 | |
782 | /* Tag range for OEMs */ |
783 | |
784 | #define MICNG_EETAG_OEM_FIRST 0xC000 |
785 | #define MICNG_EETAG_OEM_LAST 0xFFEF |
786 | |
787 | static int i2c_write_eeprom(struct i2c_adapter *adapter, |
788 | u8 adr, u16 reg, u8 data) |
789 | { |
790 | struct device *pdev = adapter->dev.parent; |
791 | u8 m[3] = {(reg >> 8), (reg & 0xff), data}; |
792 | struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, |
793 | .len = sizeof(m)}; |
794 | |
795 | if (i2c_transfer(adap: adapter, msgs: &msg, num: 1) != 1) { |
796 | dev_err(pdev, "Error writing EEPROM!\n" ); |
797 | return -EIO; |
798 | } |
799 | return 0; |
800 | } |
801 | |
802 | static int i2c_read_eeprom(struct i2c_adapter *adapter, |
803 | u8 adr, u16 reg, u8 *data, int len) |
804 | { |
805 | struct device *pdev = adapter->dev.parent; |
806 | u8 msg[2] = {(reg >> 8), (reg & 0xff)}; |
807 | struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, |
808 | .buf = msg, .len = 2 }, |
809 | {.addr = adr, .flags = I2C_M_RD, |
810 | .buf = data, .len = len} }; |
811 | |
812 | if (i2c_transfer(adap: adapter, msgs, num: 2) != 2) { |
813 | dev_err(pdev, "Error reading EEPROM\n" ); |
814 | return -EIO; |
815 | } |
816 | return 0; |
817 | } |
818 | |
819 | static int ReadEEProm(struct i2c_adapter *adapter, |
820 | u16 Tag, u32 MaxLen, u8 *data, u32 *pLength) |
821 | { |
822 | struct device *pdev = adapter->dev.parent; |
823 | int status = 0; |
824 | u16 Addr = MICNG_EE_START, Length, tag = 0; |
825 | u8 EETag[3]; |
826 | |
827 | while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { |
828 | if (i2c_read_eeprom(adapter, adr: 0x50, reg: Addr, data: EETag, len: sizeof(EETag))) |
829 | return -1; |
830 | tag = (EETag[0] << 8) | EETag[1]; |
831 | if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) |
832 | return -1; |
833 | if (tag == Tag) |
834 | break; |
835 | Addr += sizeof(u16) + 1 + EETag[2]; |
836 | } |
837 | if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { |
838 | dev_err(pdev, "Reached EOEE @ Tag = %04x Length = %3d\n" , |
839 | tag, EETag[2]); |
840 | return -1; |
841 | } |
842 | Length = EETag[2]; |
843 | if (Length > MaxLen) |
844 | Length = (u16) MaxLen; |
845 | if (Length > 0) { |
846 | Addr += sizeof(u16) + 1; |
847 | status = i2c_read_eeprom(adapter, adr: 0x50, reg: Addr, data, len: Length); |
848 | if (!status) { |
849 | *pLength = EETag[2]; |
850 | #if 0 |
851 | if (Length < EETag[2]) |
852 | status = STATUS_BUFFER_OVERFLOW; |
853 | #endif |
854 | } |
855 | } |
856 | return status; |
857 | } |
858 | |
859 | static int WriteEEProm(struct i2c_adapter *adapter, |
860 | u16 Tag, u32 Length, u8 *data) |
861 | { |
862 | struct device *pdev = adapter->dev.parent; |
863 | int status = 0; |
864 | u16 Addr = MICNG_EE_START; |
865 | u8 EETag[3]; |
866 | u16 tag = 0; |
867 | int retry, i; |
868 | |
869 | while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { |
870 | if (i2c_read_eeprom(adapter, adr: 0x50, reg: Addr, data: EETag, len: sizeof(EETag))) |
871 | return -1; |
872 | tag = (EETag[0] << 8) | EETag[1]; |
873 | if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) |
874 | return -1; |
875 | if (tag == Tag) |
876 | break; |
877 | Addr += sizeof(u16) + 1 + EETag[2]; |
878 | } |
879 | if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { |
880 | dev_err(pdev, "Reached EOEE @ Tag = %04x Length = %3d\n" , |
881 | tag, EETag[2]); |
882 | return -1; |
883 | } |
884 | |
885 | if (Length > EETag[2]) |
886 | return -EINVAL; |
887 | /* Note: We write the data one byte at a time to avoid |
888 | issues with page sizes. (which are different for |
889 | each manufacture and eeprom size) |
890 | */ |
891 | Addr += sizeof(u16) + 1; |
892 | for (i = 0; i < Length; i++, Addr++) { |
893 | status = i2c_write_eeprom(adapter, adr: 0x50, reg: Addr, data: data[i]); |
894 | |
895 | if (status) |
896 | break; |
897 | |
898 | /* Poll for finishing write cycle */ |
899 | retry = 10; |
900 | while (retry) { |
901 | u8 Tmp; |
902 | |
903 | msleep(msecs: 50); |
904 | status = i2c_read_eeprom(adapter, adr: 0x50, reg: Addr, data: &Tmp, len: 1); |
905 | if (status) |
906 | break; |
907 | if (Tmp != data[i]) |
908 | dev_err(pdev, "eeprom write error\n" ); |
909 | retry -= 1; |
910 | } |
911 | if (status) { |
912 | dev_err(pdev, "Timeout polling eeprom\n" ); |
913 | break; |
914 | } |
915 | } |
916 | return status; |
917 | } |
918 | |
919 | static int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data) |
920 | { |
921 | int stat; |
922 | u8 buf[2]; |
923 | u32 len = 0; |
924 | |
925 | stat = ReadEEProm(adapter, Tag: tag, MaxLen: 2, data: buf, pLength: &len); |
926 | if (stat) |
927 | return stat; |
928 | if (len != 2) |
929 | return -EINVAL; |
930 | |
931 | *data = (buf[0] << 8) | buf[1]; |
932 | return 0; |
933 | } |
934 | |
935 | static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data) |
936 | { |
937 | u8 buf[2]; |
938 | |
939 | buf[0] = data >> 8; |
940 | buf[1] = data & 0xff; |
941 | return WriteEEProm(adapter, Tag: tag, Length: 2, data: buf); |
942 | } |
943 | |
944 | static s16 osc_deviation(void *priv, s16 deviation, int flag) |
945 | { |
946 | struct ngene_channel *chan = priv; |
947 | struct device *pdev = &chan->dev->pci_dev->dev; |
948 | struct i2c_adapter *adap = &chan->i2c_adapter; |
949 | u16 data = 0; |
950 | |
951 | if (flag) { |
952 | data = (u16) deviation; |
953 | dev_info(pdev, "write deviation %d\n" , |
954 | deviation); |
955 | eeprom_write_ushort(adapter: adap, tag: 0x1000 + chan->number, data); |
956 | } else { |
957 | if (eeprom_read_ushort(adapter: adap, tag: 0x1000 + chan->number, data: &data)) |
958 | data = 0; |
959 | dev_info(pdev, "read deviation %d\n" , |
960 | (s16)data); |
961 | } |
962 | |
963 | return (s16) data; |
964 | } |
965 | |
966 | /****************************************************************************/ |
967 | /* Switch control (I2C gates, etc.) *****************************************/ |
968 | /****************************************************************************/ |
969 | |
970 | |
971 | static struct stv090x_config fe_cineS2 = { |
972 | .device = STV0900, |
973 | .demod_mode = STV090x_DUAL, |
974 | .clk_mode = STV090x_CLK_EXT, |
975 | |
976 | .xtal = 27000000, |
977 | .address = 0x68, |
978 | |
979 | .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED, |
980 | .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, |
981 | |
982 | .repeater_level = STV090x_RPTLEVEL_16, |
983 | |
984 | .adc1_range = STV090x_ADC_1Vpp, |
985 | .adc2_range = STV090x_ADC_1Vpp, |
986 | |
987 | .diseqc_envelope_mode = true, |
988 | |
989 | .tuner_i2c_lock = cineS2_tuner_i2c_lock, |
990 | }; |
991 | |
992 | static struct stv090x_config fe_cineS2_2 = { |
993 | .device = STV0900, |
994 | .demod_mode = STV090x_DUAL, |
995 | .clk_mode = STV090x_CLK_EXT, |
996 | |
997 | .xtal = 27000000, |
998 | .address = 0x69, |
999 | |
1000 | .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED, |
1001 | .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, |
1002 | |
1003 | .repeater_level = STV090x_RPTLEVEL_16, |
1004 | |
1005 | .adc1_range = STV090x_ADC_1Vpp, |
1006 | .adc2_range = STV090x_ADC_1Vpp, |
1007 | |
1008 | .diseqc_envelope_mode = true, |
1009 | |
1010 | .tuner_i2c_lock = cineS2_tuner_i2c_lock, |
1011 | }; |
1012 | |
1013 | static struct stv6110x_config tuner_cineS2_0 = { |
1014 | .addr = 0x60, |
1015 | .refclk = 27000000, |
1016 | .clk_div = 1, |
1017 | }; |
1018 | |
1019 | static struct stv6110x_config tuner_cineS2_1 = { |
1020 | .addr = 0x63, |
1021 | .refclk = 27000000, |
1022 | .clk_div = 1, |
1023 | }; |
1024 | |
1025 | static const struct ngene_info ngene_info_cineS2 = { |
1026 | .type = NGENE_SIDEWINDER, |
1027 | .name = "Linux4Media cineS2 DVB-S2 Twin Tuner" , |
1028 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, |
1029 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, |
1030 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, |
1031 | .fe_config = {&fe_cineS2, &fe_cineS2}, |
1032 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, |
1033 | .lnb = {0x0b, 0x08}, |
1034 | .tsf = {3, 3}, |
1035 | .fw_version = 18, |
1036 | .msi_supported = true, |
1037 | }; |
1038 | |
1039 | static const struct ngene_info ngene_info_satixS2 = { |
1040 | .type = NGENE_SIDEWINDER, |
1041 | .name = "Mystique SaTiX-S2 Dual" , |
1042 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, |
1043 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, |
1044 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, |
1045 | .fe_config = {&fe_cineS2, &fe_cineS2}, |
1046 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, |
1047 | .lnb = {0x0b, 0x08}, |
1048 | .tsf = {3, 3}, |
1049 | .fw_version = 18, |
1050 | .msi_supported = true, |
1051 | }; |
1052 | |
1053 | static const struct ngene_info ngene_info_satixS2v2 = { |
1054 | .type = NGENE_SIDEWINDER, |
1055 | .name = "Mystique SaTiX-S2 Dual (v2)" , |
1056 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, |
1057 | NGENE_IO_TSOUT}, |
1058 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe}, |
1059 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_probe, tuner_attach_probe}, |
1060 | .fe_config = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2}, |
1061 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1}, |
1062 | .lnb = {0x0a, 0x08, 0x0b, 0x09}, |
1063 | .tsf = {3, 3}, |
1064 | .fw_version = 18, |
1065 | .msi_supported = true, |
1066 | }; |
1067 | |
1068 | static const struct ngene_info ngene_info_cineS2v5 = { |
1069 | .type = NGENE_SIDEWINDER, |
1070 | .name = "Linux4Media cineS2 DVB-S2 Twin Tuner (v5)" , |
1071 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, |
1072 | NGENE_IO_TSOUT}, |
1073 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe}, |
1074 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_probe, tuner_attach_probe}, |
1075 | .fe_config = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2}, |
1076 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1}, |
1077 | .lnb = {0x0a, 0x08, 0x0b, 0x09}, |
1078 | .tsf = {3, 3}, |
1079 | .fw_version = 18, |
1080 | .msi_supported = true, |
1081 | }; |
1082 | |
1083 | |
1084 | static const struct ngene_info ngene_info_duoFlex = { |
1085 | .type = NGENE_SIDEWINDER, |
1086 | .name = "Digital Devices DuoFlex PCIe or miniPCIe" , |
1087 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, |
1088 | NGENE_IO_TSOUT}, |
1089 | .demod_attach = {cineS2_probe, cineS2_probe, cineS2_probe, cineS2_probe}, |
1090 | .tuner_attach = {tuner_attach_probe, tuner_attach_probe, tuner_attach_probe, tuner_attach_probe}, |
1091 | .fe_config = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2}, |
1092 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1}, |
1093 | .lnb = {0x0a, 0x08, 0x0b, 0x09}, |
1094 | .tsf = {3, 3}, |
1095 | .fw_version = 18, |
1096 | .msi_supported = true, |
1097 | }; |
1098 | |
1099 | static const struct ngene_info ngene_info_m780 = { |
1100 | .type = NGENE_APP, |
1101 | .name = "Aver M780 ATSC/QAM-B" , |
1102 | |
1103 | /* Channel 0 is analog, which is currently unsupported */ |
1104 | .io_type = { NGENE_IO_NONE, NGENE_IO_TSIN }, |
1105 | .demod_attach = { NULL, demod_attach_lg330x }, |
1106 | |
1107 | /* Ensure these are NULL else the frame will call them (as funcs) */ |
1108 | .tuner_attach = { NULL, NULL, NULL, NULL }, |
1109 | .fe_config = { NULL, &aver_m780 }, |
1110 | .avf = { 0 }, |
1111 | |
1112 | /* A custom electrical interface config for the demod to bridge */ |
1113 | .tsf = { 4, 4 }, |
1114 | .fw_version = 15, |
1115 | }; |
1116 | |
1117 | static struct drxd_config fe_terratec_dvbt_0 = { |
1118 | .index = 0, |
1119 | .demod_address = 0x70, |
1120 | .demod_revision = 0xa2, |
1121 | .demoda_address = 0x00, |
1122 | .pll_address = 0x60, |
1123 | .pll_type = DVB_PLL_THOMSON_DTT7520X, |
1124 | .clock = 20000, |
1125 | .osc_deviation = osc_deviation, |
1126 | }; |
1127 | |
1128 | static struct drxd_config fe_terratec_dvbt_1 = { |
1129 | .index = 1, |
1130 | .demod_address = 0x71, |
1131 | .demod_revision = 0xa2, |
1132 | .demoda_address = 0x00, |
1133 | .pll_address = 0x60, |
1134 | .pll_type = DVB_PLL_THOMSON_DTT7520X, |
1135 | .clock = 20000, |
1136 | .osc_deviation = osc_deviation, |
1137 | }; |
1138 | |
1139 | static const struct ngene_info ngene_info_terratec = { |
1140 | .type = NGENE_TERRATEC, |
1141 | .name = "Terratec Integra/Cinergy2400i Dual DVB-T" , |
1142 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, |
1143 | .demod_attach = {demod_attach_drxd, demod_attach_drxd}, |
1144 | .tuner_attach = {tuner_attach_dtt7520x, tuner_attach_dtt7520x}, |
1145 | .fe_config = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1}, |
1146 | .i2c_access = 1, |
1147 | }; |
1148 | |
1149 | /****************************************************************************/ |
1150 | |
1151 | |
1152 | |
1153 | /****************************************************************************/ |
1154 | /* PCI Subsystem ID *********************************************************/ |
1155 | /****************************************************************************/ |
1156 | |
1157 | #define NGENE_ID(_subvend, _subdev, _driverdata) { \ |
1158 | .vendor = NGENE_VID, .device = NGENE_PID, \ |
1159 | .subvendor = _subvend, .subdevice = _subdev, \ |
1160 | .driver_data = (unsigned long) &_driverdata } |
1161 | |
1162 | /****************************************************************************/ |
1163 | |
1164 | static const struct pci_device_id ngene_id_tbl[] = { |
1165 | NGENE_ID(0x18c3, 0xab04, ngene_info_cineS2), |
1166 | NGENE_ID(0x18c3, 0xab05, ngene_info_cineS2v5), |
1167 | NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2), |
1168 | NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2), |
1169 | NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2), |
1170 | NGENE_ID(0x18c3, 0xdb02, ngene_info_satixS2v2), |
1171 | NGENE_ID(0x18c3, 0xdd00, ngene_info_cineS2v5), |
1172 | NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex), |
1173 | NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex), |
1174 | NGENE_ID(0x1461, 0x062e, ngene_info_m780), |
1175 | NGENE_ID(0x153b, 0x1167, ngene_info_terratec), |
1176 | {0} |
1177 | }; |
1178 | MODULE_DEVICE_TABLE(pci, ngene_id_tbl); |
1179 | |
1180 | /****************************************************************************/ |
1181 | /* Init/Exit ****************************************************************/ |
1182 | /****************************************************************************/ |
1183 | |
1184 | static pci_ers_result_t ngene_error_detected(struct pci_dev *dev, |
1185 | pci_channel_state_t state) |
1186 | { |
1187 | dev_err(&dev->dev, "PCI error\n" ); |
1188 | if (state == pci_channel_io_perm_failure) |
1189 | return PCI_ERS_RESULT_DISCONNECT; |
1190 | if (state == pci_channel_io_frozen) |
1191 | return PCI_ERS_RESULT_NEED_RESET; |
1192 | return PCI_ERS_RESULT_CAN_RECOVER; |
1193 | } |
1194 | |
1195 | static pci_ers_result_t ngene_slot_reset(struct pci_dev *dev) |
1196 | { |
1197 | dev_info(&dev->dev, "slot reset\n" ); |
1198 | return 0; |
1199 | } |
1200 | |
1201 | static void ngene_resume(struct pci_dev *dev) |
1202 | { |
1203 | dev_info(&dev->dev, "resume\n" ); |
1204 | } |
1205 | |
1206 | static const struct pci_error_handlers ngene_errors = { |
1207 | .error_detected = ngene_error_detected, |
1208 | .slot_reset = ngene_slot_reset, |
1209 | .resume = ngene_resume, |
1210 | }; |
1211 | |
1212 | static struct pci_driver ngene_pci_driver = { |
1213 | .name = "ngene" , |
1214 | .id_table = ngene_id_tbl, |
1215 | .probe = ngene_probe, |
1216 | .remove = ngene_remove, |
1217 | .err_handler = &ngene_errors, |
1218 | .shutdown = ngene_shutdown, |
1219 | }; |
1220 | |
1221 | static __init int module_init_ngene(void) |
1222 | { |
1223 | /* pr_*() since we don't have a device to use with dev_*() yet */ |
1224 | pr_info("nGene PCIE bridge driver, Copyright (C) 2005-2007 Micronas\n" ); |
1225 | |
1226 | return pci_register_driver(&ngene_pci_driver); |
1227 | } |
1228 | |
1229 | static __exit void module_exit_ngene(void) |
1230 | { |
1231 | pci_unregister_driver(dev: &ngene_pci_driver); |
1232 | } |
1233 | |
1234 | module_init(module_init_ngene); |
1235 | module_exit(module_exit_ngene); |
1236 | |
1237 | MODULE_DESCRIPTION("nGene" ); |
1238 | MODULE_AUTHOR("Micronas, Ralph Metzler, Manfred Voelkel" ); |
1239 | MODULE_LICENSE("GPL" ); |
1240 | |