Merge branch 'syscore' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspen...
[pandora-kernel.git] / drivers / media / dvb / ngene / ngene-cards.c
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
44
45 /****************************************************************************/
46 /* Demod/tuner attachment ***************************************************/
47 /****************************************************************************/
48
49 static int tuner_attach_stv6110(struct ngene_channel *chan)
50 {
51         struct i2c_adapter *i2c;
52         struct stv090x_config *feconf = (struct stv090x_config *)
53                 chan->dev->card_info->fe_config[chan->number];
54         struct stv6110x_config *tunerconf = (struct stv6110x_config *)
55                 chan->dev->card_info->tuner_config[chan->number];
56         struct stv6110x_devctl *ctl;
57
58         /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
59         if (chan->number < 2)
60                 i2c = &chan->dev->channel[0].i2c_adapter;
61         else
62                 i2c = &chan->dev->channel[1].i2c_adapter;
63
64         ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf, i2c);
65         if (ctl == NULL) {
66                 printk(KERN_ERR DEVICE_NAME ": No STV6110X found!\n");
67                 return -ENODEV;
68         }
69
70         feconf->tuner_init          = ctl->tuner_init;
71         feconf->tuner_sleep         = ctl->tuner_sleep;
72         feconf->tuner_set_mode      = ctl->tuner_set_mode;
73         feconf->tuner_set_frequency = ctl->tuner_set_frequency;
74         feconf->tuner_get_frequency = ctl->tuner_get_frequency;
75         feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth;
76         feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth;
77         feconf->tuner_set_bbgain    = ctl->tuner_set_bbgain;
78         feconf->tuner_get_bbgain    = ctl->tuner_get_bbgain;
79         feconf->tuner_set_refclk    = ctl->tuner_set_refclk;
80         feconf->tuner_get_status    = ctl->tuner_get_status;
81
82         return 0;
83 }
84
85
86 static int demod_attach_stv0900(struct ngene_channel *chan)
87 {
88         struct i2c_adapter *i2c;
89         struct stv090x_config *feconf = (struct stv090x_config *)
90                 chan->dev->card_info->fe_config[chan->number];
91
92         /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
93         /* Note: Both adapters share the same i2c bus, but the demod     */
94         /*       driver requires that each demod has its own i2c adapter */
95         if (chan->number < 2)
96                 i2c = &chan->dev->channel[0].i2c_adapter;
97         else
98                 i2c = &chan->dev->channel[1].i2c_adapter;
99
100         chan->fe = dvb_attach(stv090x_attach, feconf, i2c,
101                         (chan->number & 1) == 0 ? STV090x_DEMODULATOR_0
102                                                 : STV090x_DEMODULATOR_1);
103         if (chan->fe == NULL) {
104                 printk(KERN_ERR DEVICE_NAME ": No STV0900 found!\n");
105                 return -ENODEV;
106         }
107
108         /* store channel info */
109         if (feconf->tuner_i2c_lock)
110                 chan->fe->analog_demod_priv = chan;
111
112         if (!dvb_attach(lnbh24_attach, chan->fe, i2c, 0,
113                         0, chan->dev->card_info->lnb[chan->number])) {
114                 printk(KERN_ERR DEVICE_NAME ": No LNBH24 found!\n");
115                 dvb_frontend_detach(chan->fe);
116                 chan->fe = NULL;
117                 return -ENODEV;
118         }
119
120         return 0;
121 }
122
123 static void cineS2_tuner_i2c_lock(struct dvb_frontend *fe, int lock)
124 {
125         struct ngene_channel *chan = fe->analog_demod_priv;
126
127         if (lock)
128                 down(&chan->dev->pll_mutex);
129         else
130                 up(&chan->dev->pll_mutex);
131 }
132
133 static int cineS2_probe(struct ngene_channel *chan)
134 {
135         struct i2c_adapter *i2c;
136         struct stv090x_config *fe_conf;
137         u8 buf[3];
138         struct i2c_msg i2c_msg = { .flags = 0, .buf = buf };
139         int rc;
140
141         /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
142         if (chan->number < 2)
143                 i2c = &chan->dev->channel[0].i2c_adapter;
144         else
145                 i2c = &chan->dev->channel[1].i2c_adapter;
146
147         fe_conf = chan->dev->card_info->fe_config[chan->number];
148         i2c_msg.addr = fe_conf->address;
149
150         /* probe demod */
151         i2c_msg.len = 2;
152         buf[0] = 0xf1;
153         buf[1] = 0x00;
154         rc = i2c_transfer(i2c, &i2c_msg, 1);
155         if (rc != 1)
156                 return -ENODEV;
157
158         /* demod found, attach it */
159         rc = demod_attach_stv0900(chan);
160         if (rc < 0 || chan->number < 2)
161                 return rc;
162
163         /* demod #2: reprogram outputs DPN1 & DPN2 */
164         i2c_msg.len = 3;
165         buf[0] = 0xf1;
166         switch (chan->number) {
167         case 2:
168                 buf[1] = 0x5c;
169                 buf[2] = 0xc2;
170                 break;
171         case 3:
172                 buf[1] = 0x61;
173                 buf[2] = 0xcc;
174                 break;
175         default:
176                 return -ENODEV;
177         }
178         rc = i2c_transfer(i2c, &i2c_msg, 1);
179         if (rc != 1) {
180                 printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n");
181                 return -EIO;
182         }
183
184         return 0;
185 }
186
187
188 static struct lgdt330x_config aver_m780 = {
189         .demod_address = 0xb2 >> 1,
190         .demod_chip    = LGDT3303,
191         .serial_mpeg   = 0x00, /* PARALLEL */
192         .clock_polarity_flip = 1,
193 };
194
195 static struct mt2131_config m780_tunerconfig = {
196         0xc0 >> 1
197 };
198
199 /* A single func to attach the demo and tuner, rather than
200  * use two sep funcs like the current design mandates.
201  */
202 static int demod_attach_lg330x(struct ngene_channel *chan)
203 {
204         chan->fe = dvb_attach(lgdt330x_attach, &aver_m780, &chan->i2c_adapter);
205         if (chan->fe == NULL) {
206                 printk(KERN_ERR DEVICE_NAME ": No LGDT330x found!\n");
207                 return -ENODEV;
208         }
209
210         dvb_attach(mt2131_attach, chan->fe, &chan->i2c_adapter,
211                    &m780_tunerconfig, 0);
212
213         return (chan->fe) ? 0 : -ENODEV;
214 }
215
216 /****************************************************************************/
217 /* Switch control (I2C gates, etc.) *****************************************/
218 /****************************************************************************/
219
220
221 static struct stv090x_config fe_cineS2 = {
222         .device         = STV0900,
223         .demod_mode     = STV090x_DUAL,
224         .clk_mode       = STV090x_CLK_EXT,
225
226         .xtal           = 27000000,
227         .address        = 0x68,
228
229         .ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
230         .ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
231
232         .repeater_level = STV090x_RPTLEVEL_16,
233
234         .adc1_range     = STV090x_ADC_1Vpp,
235         .adc2_range     = STV090x_ADC_1Vpp,
236
237         .diseqc_envelope_mode = true,
238
239         .tuner_i2c_lock = cineS2_tuner_i2c_lock,
240 };
241
242 static struct stv090x_config fe_cineS2_2 = {
243         .device         = STV0900,
244         .demod_mode     = STV090x_DUAL,
245         .clk_mode       = STV090x_CLK_EXT,
246
247         .xtal           = 27000000,
248         .address        = 0x69,
249
250         .ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
251         .ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
252
253         .repeater_level = STV090x_RPTLEVEL_16,
254
255         .adc1_range     = STV090x_ADC_1Vpp,
256         .adc2_range     = STV090x_ADC_1Vpp,
257
258         .diseqc_envelope_mode = true,
259
260         .tuner_i2c_lock = cineS2_tuner_i2c_lock,
261 };
262
263 static struct stv6110x_config tuner_cineS2_0 = {
264         .addr   = 0x60,
265         .refclk = 27000000,
266         .clk_div = 1,
267 };
268
269 static struct stv6110x_config tuner_cineS2_1 = {
270         .addr   = 0x63,
271         .refclk = 27000000,
272         .clk_div = 1,
273 };
274
275 static struct ngene_info ngene_info_cineS2 = {
276         .type           = NGENE_SIDEWINDER,
277         .name           = "Linux4Media cineS2 DVB-S2 Twin Tuner",
278         .io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN},
279         .demod_attach   = {demod_attach_stv0900, demod_attach_stv0900},
280         .tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110},
281         .fe_config      = {&fe_cineS2, &fe_cineS2},
282         .tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1},
283         .lnb            = {0x0b, 0x08},
284         .tsf            = {3, 3},
285         .fw_version     = 18,
286         .msi_supported  = true,
287 };
288
289 static struct ngene_info ngene_info_satixS2 = {
290         .type           = NGENE_SIDEWINDER,
291         .name           = "Mystique SaTiX-S2 Dual",
292         .io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN},
293         .demod_attach   = {demod_attach_stv0900, demod_attach_stv0900},
294         .tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110},
295         .fe_config      = {&fe_cineS2, &fe_cineS2},
296         .tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1},
297         .lnb            = {0x0b, 0x08},
298         .tsf            = {3, 3},
299         .fw_version     = 18,
300         .msi_supported  = true,
301 };
302
303 static struct ngene_info ngene_info_satixS2v2 = {
304         .type           = NGENE_SIDEWINDER,
305         .name           = "Mystique SaTiX-S2 Dual (v2)",
306         .io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
307                            NGENE_IO_TSOUT},
308         .demod_attach   = {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe},
309         .tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110},
310         .fe_config      = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
311         .tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
312         .lnb            = {0x0a, 0x08, 0x0b, 0x09},
313         .tsf            = {3, 3},
314         .fw_version     = 18,
315         .msi_supported  = true,
316 };
317
318 static struct ngene_info ngene_info_cineS2v5 = {
319         .type           = NGENE_SIDEWINDER,
320         .name           = "Linux4Media cineS2 DVB-S2 Twin Tuner (v5)",
321         .io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
322                            NGENE_IO_TSOUT},
323         .demod_attach   = {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe},
324         .tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110},
325         .fe_config      = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
326         .tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
327         .lnb            = {0x0a, 0x08, 0x0b, 0x09},
328         .tsf            = {3, 3},
329         .fw_version     = 18,
330         .msi_supported  = true,
331 };
332
333
334 static struct ngene_info ngene_info_duoFlexS2 = {
335         .type           = NGENE_SIDEWINDER,
336         .name           = "Digital Devices DuoFlex S2 miniPCIe",
337         .io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
338                            NGENE_IO_TSOUT},
339         .demod_attach   = {cineS2_probe, cineS2_probe, cineS2_probe, cineS2_probe},
340         .tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110},
341         .fe_config      = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
342         .tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
343         .lnb            = {0x0a, 0x08, 0x0b, 0x09},
344         .tsf            = {3, 3},
345         .fw_version     = 18,
346         .msi_supported  = true,
347 };
348
349 static struct ngene_info ngene_info_m780 = {
350         .type           = NGENE_APP,
351         .name           = "Aver M780 ATSC/QAM-B",
352
353         /* Channel 0 is analog, which is currently unsupported */
354         .io_type        = { NGENE_IO_NONE, NGENE_IO_TSIN },
355         .demod_attach   = { NULL, demod_attach_lg330x },
356
357         /* Ensure these are NULL else the frame will call them (as funcs) */
358         .tuner_attach   = { 0, 0, 0, 0 },
359         .fe_config      = { NULL, &aver_m780 },
360         .avf            = { 0 },
361
362         /* A custom electrical interface config for the demod to bridge */
363         .tsf            = { 4, 4 },
364         .fw_version     = 15,
365 };
366
367 /****************************************************************************/
368
369
370
371 /****************************************************************************/
372 /* PCI Subsystem ID *********************************************************/
373 /****************************************************************************/
374
375 #define NGENE_ID(_subvend, _subdev, _driverdata) { \
376         .vendor = NGENE_VID, .device = NGENE_PID, \
377         .subvendor = _subvend, .subdevice = _subdev, \
378         .driver_data = (unsigned long) &_driverdata }
379
380 /****************************************************************************/
381
382 static const struct pci_device_id ngene_id_tbl[] __devinitdata = {
383         NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2),
384         NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2),
385         NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2),
386         NGENE_ID(0x18c3, 0xdb02, ngene_info_satixS2v2),
387         NGENE_ID(0x18c3, 0xdd00, ngene_info_cineS2v5),
388         NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlexS2),
389         NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlexS2),
390         NGENE_ID(0x1461, 0x062e, ngene_info_m780),
391         {0}
392 };
393 MODULE_DEVICE_TABLE(pci, ngene_id_tbl);
394
395 /****************************************************************************/
396 /* Init/Exit ****************************************************************/
397 /****************************************************************************/
398
399 static pci_ers_result_t ngene_error_detected(struct pci_dev *dev,
400                                              enum pci_channel_state state)
401 {
402         printk(KERN_ERR DEVICE_NAME ": PCI error\n");
403         if (state == pci_channel_io_perm_failure)
404                 return PCI_ERS_RESULT_DISCONNECT;
405         if (state == pci_channel_io_frozen)
406                 return PCI_ERS_RESULT_NEED_RESET;
407         return PCI_ERS_RESULT_CAN_RECOVER;
408 }
409
410 static pci_ers_result_t ngene_link_reset(struct pci_dev *dev)
411 {
412         printk(KERN_INFO DEVICE_NAME ": link reset\n");
413         return 0;
414 }
415
416 static pci_ers_result_t ngene_slot_reset(struct pci_dev *dev)
417 {
418         printk(KERN_INFO DEVICE_NAME ": slot reset\n");
419         return 0;
420 }
421
422 static void ngene_resume(struct pci_dev *dev)
423 {
424         printk(KERN_INFO DEVICE_NAME ": resume\n");
425 }
426
427 static struct pci_error_handlers ngene_errors = {
428         .error_detected = ngene_error_detected,
429         .link_reset = ngene_link_reset,
430         .slot_reset = ngene_slot_reset,
431         .resume = ngene_resume,
432 };
433
434 static struct pci_driver ngene_pci_driver = {
435         .name        = "ngene",
436         .id_table    = ngene_id_tbl,
437         .probe       = ngene_probe,
438         .remove      = __devexit_p(ngene_remove),
439         .err_handler = &ngene_errors,
440         .shutdown    = ngene_shutdown,
441 };
442
443 static __init int module_init_ngene(void)
444 {
445         printk(KERN_INFO
446                "nGene PCIE bridge driver, Copyright (C) 2005-2007 Micronas\n");
447         return pci_register_driver(&ngene_pci_driver);
448 }
449
450 static __exit void module_exit_ngene(void)
451 {
452         pci_unregister_driver(&ngene_pci_driver);
453 }
454
455 module_init(module_init_ngene);
456 module_exit(module_exit_ngene);
457
458 MODULE_DESCRIPTION("nGene");
459 MODULE_AUTHOR("Micronas, Ralph Metzler, Manfred Voelkel");
460 MODULE_LICENSE("GPL");