1/*
2 * ngene-cards.c: nGene PCIe bridge driver - card specific info
3 *
4 * Copyright (C) 2005-2007 Micronas
5 *
6 * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de>
7 *                         Modifications for new nGene firmware,
8 *                         support for EEPROM-copying,
9 *                         support for new dual DVB-S2 card prototype
10 *
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * version 2 only, as published by the Free Software Foundation.
15 *
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 *
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 * 02110-1301, USA
27 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
28 */
29
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/pci.h>
33#include <linux/pci_ids.h>
34
35#include "ngene.h"
36
37/* demods/tuners */
38#include "stv6110x.h"
39#include "stv090x.h"
40#include "lnbh24.h"
41#include "lgdt330x.h"
42#include "mt2131.h"
43#include "tda18271c2dd.h"
44#include "drxk.h"
45
46
47/****************************************************************************/
48/* Demod/tuner attachment ***************************************************/
49/****************************************************************************/
50
51static int tuner_attach_stv6110(struct ngene_channel *chan)
52{
53	struct i2c_adapter *i2c;
54	struct stv090x_config *feconf = (struct stv090x_config *)
55		chan->dev->card_info->fe_config[chan->number];
56	struct stv6110x_config *tunerconf = (struct stv6110x_config *)
57		chan->dev->card_info->tuner_config[chan->number];
58	struct stv6110x_devctl *ctl;
59
60	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
61	if (chan->number < 2)
62		i2c = &chan->dev->channel[0].i2c_adapter;
63	else
64		i2c = &chan->dev->channel[1].i2c_adapter;
65
66	ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf, i2c);
67	if (ctl == NULL) {
68		printk(KERN_ERR	DEVICE_NAME ": No STV6110X found!\n");
69		return -ENODEV;
70	}
71
72	feconf->tuner_init          = ctl->tuner_init;
73	feconf->tuner_sleep         = ctl->tuner_sleep;
74	feconf->tuner_set_mode      = ctl->tuner_set_mode;
75	feconf->tuner_set_frequency = ctl->tuner_set_frequency;
76	feconf->tuner_get_frequency = ctl->tuner_get_frequency;
77	feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth;
78	feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth;
79	feconf->tuner_set_bbgain    = ctl->tuner_set_bbgain;
80	feconf->tuner_get_bbgain    = ctl->tuner_get_bbgain;
81	feconf->tuner_set_refclk    = ctl->tuner_set_refclk;
82	feconf->tuner_get_status    = ctl->tuner_get_status;
83
84	return 0;
85}
86
87
88static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
89{
90	struct ngene_channel *chan = fe->sec_priv;
91	int status;
92
93	if (enable) {
94		down(&chan->dev->pll_mutex);
95		status = chan->gate_ctrl(fe, 1);
96	} else {
97		status = chan->gate_ctrl(fe, 0);
98		up(&chan->dev->pll_mutex);
99	}
100	return status;
101}
102
103static int tuner_attach_tda18271(struct ngene_channel *chan)
104{
105	struct i2c_adapter *i2c;
106	struct dvb_frontend *fe;
107
108	i2c = &chan->dev->channel[0].i2c_adapter;
109	if (chan->fe->ops.i2c_gate_ctrl)
110		chan->fe->ops.i2c_gate_ctrl(chan->fe, 1);
111	fe = dvb_attach(tda18271c2dd_attach, chan->fe, i2c, 0x60);
112	if (chan->fe->ops.i2c_gate_ctrl)
113		chan->fe->ops.i2c_gate_ctrl(chan->fe, 0);
114	if (!fe) {
115		printk(KERN_ERR "No TDA18271 found!\n");
116		return -ENODEV;
117	}
118
119	return 0;
120}
121
122static int tuner_attach_probe(struct ngene_channel *chan)
123{
124	if (chan->demod_type == 0)
125		return tuner_attach_stv6110(chan);
126	if (chan->demod_type == 1)
127		return tuner_attach_tda18271(chan);
128	return -EINVAL;
129}
130
131static int demod_attach_stv0900(struct ngene_channel *chan)
132{
133	struct i2c_adapter *i2c;
134	struct stv090x_config *feconf = (struct stv090x_config *)
135		chan->dev->card_info->fe_config[chan->number];
136
137	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
138	/* Note: Both adapters share the same i2c bus, but the demod     */
139	/*       driver requires that each demod has its own i2c adapter */
140	if (chan->number < 2)
141		i2c = &chan->dev->channel[0].i2c_adapter;
142	else
143		i2c = &chan->dev->channel[1].i2c_adapter;
144
145	chan->fe = dvb_attach(stv090x_attach, feconf, i2c,
146			(chan->number & 1) == 0 ? STV090x_DEMODULATOR_0
147						: STV090x_DEMODULATOR_1);
148	if (chan->fe == NULL) {
149		printk(KERN_ERR	DEVICE_NAME ": No STV0900 found!\n");
150		return -ENODEV;
151	}
152
153	/* store channel info */
154	if (feconf->tuner_i2c_lock)
155		chan->fe->analog_demod_priv = chan;
156
157	if (!dvb_attach(lnbh24_attach, chan->fe, i2c, 0,
158			0, chan->dev->card_info->lnb[chan->number])) {
159		printk(KERN_ERR DEVICE_NAME ": No LNBH24 found!\n");
160		dvb_frontend_detach(chan->fe);
161		chan->fe = NULL;
162		return -ENODEV;
163	}
164
165	return 0;
166}
167
168static void cineS2_tuner_i2c_lock(struct dvb_frontend *fe, int lock)
169{
170	struct ngene_channel *chan = fe->analog_demod_priv;
171
172	if (lock)
173		down(&chan->dev->pll_mutex);
174	else
175		up(&chan->dev->pll_mutex);
176}
177
178static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
179{
180	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
181				   .buf  = val,  .len   = 1 } };
182	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
183}
184
185static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
186			  u16 reg, u8 *val)
187{
188	u8 msg[2] = {reg>>8, reg&0xff};
189	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
190				   .buf  = msg, .len   = 2},
191				  {.addr = adr, .flags = I2C_M_RD,
192				   .buf  = val, .len   = 1} };
193	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
194}
195
196static int port_has_stv0900(struct i2c_adapter *i2c, int port)
197{
198	u8 val;
199	if (i2c_read_reg16(i2c, 0x68+port/2, 0xf100, &val) < 0)
200		return 0;
201	return 1;
202}
203
204static int port_has_drxk(struct i2c_adapter *i2c, int port)
205{
206	u8 val;
207
208	if (i2c_read(i2c, 0x29+port, &val) < 0)
209		return 0;
210	return 1;
211}
212
213static int demod_attach_drxk(struct ngene_channel *chan,
214			     struct i2c_adapter *i2c)
215{
216	struct drxk_config config;
217
218	memset(&config, 0, sizeof(config));
219	config.microcode_name = "drxk_a3.mc";
220	config.adr = 0x29 + (chan->number ^ 2);
221
222	chan->fe = dvb_attach(drxk_attach, &config, i2c);
223	if (!chan->fe) {
224		printk(KERN_ERR "No DRXK found!\n");
225		return -ENODEV;
226	}
227	chan->fe->sec_priv = chan;
228	chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl;
229	chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
230	return 0;
231}
232
233static int cineS2_probe(struct ngene_channel *chan)
234{
235	struct i2c_adapter *i2c;
236	struct stv090x_config *fe_conf;
237	u8 buf[3];
238	struct i2c_msg i2c_msg = { .flags = 0, .buf = buf };
239	int rc;
240
241	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
242	if (chan->number < 2)
243		i2c = &chan->dev->channel[0].i2c_adapter;
244	else
245		i2c = &chan->dev->channel[1].i2c_adapter;
246
247	if (port_has_stv0900(i2c, chan->number)) {
248		chan->demod_type = 0;
249		fe_conf = chan->dev->card_info->fe_config[chan->number];
250		/* demod found, attach it */
251		rc = demod_attach_stv0900(chan);
252		if (rc < 0 || chan->number < 2)
253			return rc;
254
255		/* demod #2: reprogram outputs DPN1 & DPN2 */
256		i2c_msg.addr = fe_conf->address;
257		i2c_msg.len = 3;
258		buf[0] = 0xf1;
259		switch (chan->number) {
260		case 2:
261			buf[1] = 0x5c;
262			buf[2] = 0xc2;
263			break;
264		case 3:
265			buf[1] = 0x61;
266			buf[2] = 0xcc;
267			break;
268		default:
269			return -ENODEV;
270		}
271		rc = i2c_transfer(i2c, &i2c_msg, 1);
272		if (rc != 1) {
273			printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n");
274			return -EIO;
275		}
276	} else if (port_has_drxk(i2c, chan->number^2)) {
277		chan->demod_type = 1;
278		demod_attach_drxk(chan, i2c);
279	} else {
280		printk(KERN_ERR "No demod found on chan %d\n", chan->number);
281		return -ENODEV;
282	}
283	return 0;
284}
285
286
287static struct lgdt330x_config aver_m780 = {
288	.demod_address = 0xb2 >> 1,
289	.demod_chip    = LGDT3303,
290	.serial_mpeg   = 0x00, /* PARALLEL */
291	.clock_polarity_flip = 1,
292};
293
294static struct mt2131_config m780_tunerconfig = {
295	0xc0 >> 1
296};
297
298/* A single func to attach the demo and tuner, rather than
299 * use two sep funcs like the current design mandates.
300 */
301static int demod_attach_lg330x(struct ngene_channel *chan)
302{
303	chan->fe = dvb_attach(lgdt330x_attach, &aver_m780, &chan->i2c_adapter);
304	if (chan->fe == NULL) {
305		printk(KERN_ERR	DEVICE_NAME ": No LGDT330x found!\n");
306		return -ENODEV;
307	}
308
309	dvb_attach(mt2131_attach, chan->fe, &chan->i2c_adapter,
310		   &m780_tunerconfig, 0);
311
312	return (chan->fe) ? 0 : -ENODEV;
313}
314
315/****************************************************************************/
316/* Switch control (I2C gates, etc.) *****************************************/
317/****************************************************************************/
318
319
320static struct stv090x_config fe_cineS2 = {
321	.device         = STV0900,
322	.demod_mode     = STV090x_DUAL,
323	.clk_mode       = STV090x_CLK_EXT,
324
325	.xtal           = 27000000,
326	.address        = 0x68,
327
328	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
329	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
330
331	.repeater_level = STV090x_RPTLEVEL_16,
332
333	.adc1_range	= STV090x_ADC_1Vpp,
334	.adc2_range	= STV090x_ADC_1Vpp,
335
336	.diseqc_envelope_mode = true,
337
338	.tuner_i2c_lock = cineS2_tuner_i2c_lock,
339};
340
341static struct stv090x_config fe_cineS2_2 = {
342	.device         = STV0900,
343	.demod_mode     = STV090x_DUAL,
344	.clk_mode       = STV090x_CLK_EXT,
345
346	.xtal           = 27000000,
347	.address        = 0x69,
348
349	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
350	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
351
352	.repeater_level = STV090x_RPTLEVEL_16,
353
354	.adc1_range	= STV090x_ADC_1Vpp,
355	.adc2_range	= STV090x_ADC_1Vpp,
356
357	.diseqc_envelope_mode = true,
358
359	.tuner_i2c_lock = cineS2_tuner_i2c_lock,
360};
361
362static struct stv6110x_config tuner_cineS2_0 = {
363	.addr	= 0x60,
364	.refclk	= 27000000,
365	.clk_div = 1,
366};
367
368static struct stv6110x_config tuner_cineS2_1 = {
369	.addr	= 0x63,
370	.refclk	= 27000000,
371	.clk_div = 1,
372};
373
374static struct ngene_info ngene_info_cineS2 = {
375	.type		= NGENE_SIDEWINDER,
376	.name		= "Linux4Media cineS2 DVB-S2 Twin Tuner",
377	.io_type	= {NGENE_IO_TSIN, NGENE_IO_TSIN},
378	.demod_attach	= {demod_attach_stv0900, demod_attach_stv0900},
379	.tuner_attach	= {tuner_attach_stv6110, tuner_attach_stv6110},
380	.fe_config	= {&fe_cineS2, &fe_cineS2},
381	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1},
382	.lnb		= {0x0b, 0x08},
383	.tsf		= {3, 3},
384	.fw_version	= 18,
385	.msi_supported	= true,
386};
387
388static struct ngene_info ngene_info_satixS2 = {
389	.type		= NGENE_SIDEWINDER,
390	.name		= "Mystique SaTiX-S2 Dual",
391	.io_type	= {NGENE_IO_TSIN, NGENE_IO_TSIN},
392	.demod_attach	= {demod_attach_stv0900, demod_attach_stv0900},
393	.tuner_attach	= {tuner_attach_stv6110, tuner_attach_stv6110},
394	.fe_config	= {&fe_cineS2, &fe_cineS2},
395	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1},
396	.lnb		= {0x0b, 0x08},
397	.tsf		= {3, 3},
398	.fw_version	= 18,
399	.msi_supported	= true,
400};
401
402static struct ngene_info ngene_info_satixS2v2 = {
403	.type		= NGENE_SIDEWINDER,
404	.name		= "Mystique SaTiX-S2 Dual (v2)",
405	.io_type	= {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
406			   NGENE_IO_TSOUT},
407	.demod_attach	= {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe},
408	.tuner_attach	= {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_probe, tuner_attach_probe},
409	.fe_config	= {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
410	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
411	.lnb		= {0x0a, 0x08, 0x0b, 0x09},
412	.tsf		= {3, 3},
413	.fw_version	= 18,
414	.msi_supported	= true,
415};
416
417static struct ngene_info ngene_info_cineS2v5 = {
418	.type		= NGENE_SIDEWINDER,
419	.name		= "Linux4Media cineS2 DVB-S2 Twin Tuner (v5)",
420	.io_type	= {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
421			   NGENE_IO_TSOUT},
422	.demod_attach	= {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe},
423	.tuner_attach	= {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_probe, tuner_attach_probe},
424	.fe_config	= {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
425	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
426	.lnb		= {0x0a, 0x08, 0x0b, 0x09},
427	.tsf		= {3, 3},
428	.fw_version	= 18,
429	.msi_supported	= true,
430};
431
432
433static struct ngene_info ngene_info_duoFlex = {
434	.type           = NGENE_SIDEWINDER,
435	.name           = "Digital Devices DuoFlex PCIe or miniPCIe",
436	.io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
437			   NGENE_IO_TSOUT},
438	.demod_attach   = {cineS2_probe, cineS2_probe, cineS2_probe, cineS2_probe},
439	.tuner_attach   = {tuner_attach_probe, tuner_attach_probe, tuner_attach_probe, tuner_attach_probe},
440	.fe_config      = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
441	.tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
442	.lnb            = {0x0a, 0x08, 0x0b, 0x09},
443	.tsf            = {3, 3},
444	.fw_version     = 18,
445	.msi_supported	= true,
446};
447
448static struct ngene_info ngene_info_m780 = {
449	.type           = NGENE_APP,
450	.name           = "Aver M780 ATSC/QAM-B",
451
452	/* Channel 0 is analog, which is currently unsupported */
453	.io_type        = { NGENE_IO_NONE, NGENE_IO_TSIN },
454	.demod_attach   = { NULL, demod_attach_lg330x },
455
456	/* Ensure these are NULL else the frame will call them (as funcs) */
457	.tuner_attach   = { 0, 0, 0, 0 },
458	.fe_config      = { NULL, &aver_m780 },
459	.avf            = { 0 },
460
461	/* A custom electrical interface config for the demod to bridge */
462	.tsf		= { 4, 4 },
463	.fw_version	= 15,
464};
465
466/****************************************************************************/
467
468
469
470/****************************************************************************/
471/* PCI Subsystem ID *********************************************************/
472/****************************************************************************/
473
474#define NGENE_ID(_subvend, _subdev, _driverdata) { \
475	.vendor = NGENE_VID, .device = NGENE_PID, \
476	.subvendor = _subvend, .subdevice = _subdev, \
477	.driver_data = (unsigned long) &_driverdata }
478
479/****************************************************************************/
480
481static const struct pci_device_id ngene_id_tbl[] __devinitdata = {
482	NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2),
483	NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2),
484	NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2),
485	NGENE_ID(0x18c3, 0xdb02, ngene_info_satixS2v2),
486	NGENE_ID(0x18c3, 0xdd00, ngene_info_cineS2v5),
487	NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex),
488	NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex),
489	NGENE_ID(0x1461, 0x062e, ngene_info_m780),
490	{0}
491};
492MODULE_DEVICE_TABLE(pci, ngene_id_tbl);
493
494/****************************************************************************/
495/* Init/Exit ****************************************************************/
496/****************************************************************************/
497
498static pci_ers_result_t ngene_error_detected(struct pci_dev *dev,
499					     enum pci_channel_state state)
500{
501	printk(KERN_ERR DEVICE_NAME ": PCI error\n");
502	if (state == pci_channel_io_perm_failure)
503		return PCI_ERS_RESULT_DISCONNECT;
504	if (state == pci_channel_io_frozen)
505		return PCI_ERS_RESULT_NEED_RESET;
506	return PCI_ERS_RESULT_CAN_RECOVER;
507}
508
509static pci_ers_result_t ngene_link_reset(struct pci_dev *dev)
510{
511	printk(KERN_INFO DEVICE_NAME ": link reset\n");
512	return 0;
513}
514
515static pci_ers_result_t ngene_slot_reset(struct pci_dev *dev)
516{
517	printk(KERN_INFO DEVICE_NAME ": slot reset\n");
518	return 0;
519}
520
521static void ngene_resume(struct pci_dev *dev)
522{
523	printk(KERN_INFO DEVICE_NAME ": resume\n");
524}
525
526static struct pci_error_handlers ngene_errors = {
527	.error_detected = ngene_error_detected,
528	.link_reset = ngene_link_reset,
529	.slot_reset = ngene_slot_reset,
530	.resume = ngene_resume,
531};
532
533static struct pci_driver ngene_pci_driver = {
534	.name        = "ngene",
535	.id_table    = ngene_id_tbl,
536	.probe       = ngene_probe,
537	.remove      = __devexit_p(ngene_remove),
538	.err_handler = &ngene_errors,
539	.shutdown    = ngene_shutdown,
540};
541
542static __init int module_init_ngene(void)
543{
544	printk(KERN_INFO
545	       "nGene PCIE bridge driver, Copyright (C) 2005-2007 Micronas\n");
546	return pci_register_driver(&ngene_pci_driver);
547}
548
549static __exit void module_exit_ngene(void)
550{
551	pci_unregister_driver(&ngene_pci_driver);
552}
553
554module_init(module_init_ngene);
555module_exit(module_exit_ngene);
556
557MODULE_DESCRIPTION("nGene");
558MODULE_AUTHOR("Micronas, Ralph Metzler, Manfred Voelkel");
559MODULE_LICENSE("GPL");
560