blob: 7d193ebc0aea30baaf82896b7ed8b4f3444c0a47 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * budget-ci.c: driver for the SAA7146 based Budget DVB cards
3 *
4 * Compiled from various sources by Michael Hunold <michael@mihu.de>
5 *
6 * msp430 IR support contributed by Jack Thomasson <jkt@Helius.COM>
7 * partially based on the Siemens DVB driver by Ralph+Marcus Metzler
8 *
9 * CI interface support (c) 2004 Andrew de Quincey <adq_dvb@lidskialf.net>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
27 *
28 *
29 * the project's page is at http://www.linuxtv.org/dvb/
30 */
31
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/module.h>
33#include <linux/errno.h>
34#include <linux/slab.h>
35#include <linux/interrupt.h>
36#include <linux/input.h>
37#include <linux/spinlock.h>
David Hardeman2520fff2006-12-02 21:16:05 -020038#include <media/ir-common.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
Trent Piepho68277092007-01-30 23:25:46 -030040#include "budget.h"
41
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include "dvb_ca_en50221.h"
43#include "stv0299.h"
Andrew de Quinceydc27a162005-09-09 13:03:07 -070044#include "stv0297.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include "tda1004x.h"
Marko Schluessler9e0dc662008-10-23 18:16:40 -030046#include "stb0899_drv.h"
47#include "stb0899_reg.h"
Manu Abraham8be969b2008-01-25 18:20:48 -030048#include "stb0899_cfg.h"
Marko Schluessler9e0dc662008-10-23 18:16:40 -030049#include "stb6100.h"
Manu Abraham8be969b2008-01-25 18:20:48 -030050#include "stb6100_cfg.h"
Perceval Anichini8cc2e372006-02-28 09:52:44 -030051#include "lnbp21.h"
52#include "bsbe1.h"
Perceval Anichini265366e2006-03-16 11:22:47 -030053#include "bsru6.h"
Sigmund Augdal11417da2008-06-15 17:25:46 -030054#include "tda1002x.h"
55#include "tda827x.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
David Härdemanecba77f2006-10-27 20:56:51 -030057/*
58 * Regarding DEBIADDR_IR:
59 * Some CI modules hang if random addresses are read.
60 * Using address 0x4000 for the IR read means that we
61 * use the same address as for CI version, which should
62 * be a safe default.
63 */
64#define DEBIADDR_IR 0x4000
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#define DEBIADDR_CICONTROL 0x0000
66#define DEBIADDR_CIVERSION 0x4000
67#define DEBIADDR_IO 0x1000
68#define DEBIADDR_ATTR 0x3000
69
70#define CICONTROL_RESET 0x01
71#define CICONTROL_ENABLETS 0x02
72#define CICONTROL_CAMDETECT 0x08
73
74#define DEBICICTL 0x00420000
75#define DEBICICAM 0x02420000
76
77#define SLOTSTATUS_NONE 1
78#define SLOTSTATUS_PRESENT 2
79#define SLOTSTATUS_RESET 4
80#define SLOTSTATUS_READY 8
81#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
82
David Härdeman145859c2007-04-27 12:31:22 -030083/*
84 * Milliseconds during which a key is regarded as pressed.
85 * If an identical command arrives within this time, the timer will start over.
David Hardeman2520fff2006-12-02 21:16:05 -020086 */
David Härdeman145859c2007-04-27 12:31:22 -030087#define IR_KEYPRESS_TIMEOUT 250
David Hardeman2520fff2006-12-02 21:16:05 -020088
David Hardeman64741b72006-12-02 21:16:05 -020089/* RC5 device wildcard */
90#define IR_DEVICE_ANY 255
91
David Hardeman64741b72006-12-02 21:16:05 -020092static int rc5_device = -1;
93module_param(rc5_device, int, 0644);
94MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
95
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030096static int ir_debug;
David Hardemanb5471a22006-12-02 21:16:05 -020097module_param(ir_debug, int, 0644);
98MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
99
Janne Grunau26dc4d02008-09-21 20:50:11 -0300100DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
101
David Hardemandd2f3982006-12-02 21:16:05 -0200102struct budget_ci_ir {
103 struct input_dev *dev;
104 struct tasklet_struct msp430_irq_tasklet;
David Härdeman145859c2007-04-27 12:31:22 -0300105 struct timer_list timer_keyup;
David Hardemandd2f3982006-12-02 21:16:05 -0200106 char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
David Hardeman5cc8ae02006-12-02 21:16:05 -0200107 char phys[32];
David Hardeman2520fff2006-12-02 21:16:05 -0200108 struct ir_input_state state;
David Hardeman64741b72006-12-02 21:16:05 -0200109 int rc5_device;
David Härdeman145859c2007-04-27 12:31:22 -0300110 u32 last_raw;
111 u32 ir_key;
112 bool have_command;
David Hardemandd2f3982006-12-02 21:16:05 -0200113};
114
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115struct budget_ci {
116 struct budget budget;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 struct tasklet_struct ciintf_irq_tasklet;
118 int slot_status;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300119 int ci_irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 struct dvb_ca_en50221 ca;
David Hardemandd2f3982006-12-02 21:16:05 -0200121 struct budget_ci_ir ir;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700122 u8 tuner_pll_address; /* used for philips_tdm1316l configs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123};
124
David Hardeman2520fff2006-12-02 21:16:05 -0200125static void msp430_ir_keyup(unsigned long data)
126{
127 struct budget_ci_ir *ir = (struct budget_ci_ir *) data;
128 ir_input_nokey(ir->dev, &ir->state);
129}
130
131static void msp430_ir_interrupt(unsigned long data)
132{
133 struct budget_ci *budget_ci = (struct budget_ci *) data;
134 struct input_dev *dev = budget_ci->ir.dev;
David Hardeman2520fff2006-12-02 21:16:05 -0200135 u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
David Härdeman145859c2007-04-27 12:31:22 -0300136 u32 raw;
David Hardeman2520fff2006-12-02 21:16:05 -0200137
David Hardeman64741b72006-12-02 21:16:05 -0200138 /*
139 * The msp430 chip can generate two different bytes, command and device
140 *
141 * type1: X1CCCCCC, C = command bits (0 - 63)
142 * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
143 *
David Härdeman59327a42007-02-13 09:39:58 -0300144 * Each signal from the remote control can generate one or more command
145 * bytes and one or more device bytes. For the repeated bytes, the
146 * highest bit (X) is set. The first command byte is always generated
147 * before the first device byte. Other than that, no specific order
David Härdeman145859c2007-04-27 12:31:22 -0300148 * seems to apply. To make life interesting, bytes can also be lost.
David Härdeman59327a42007-02-13 09:39:58 -0300149 *
150 * Only when we have a command and device byte, a keypress is
151 * generated.
David Hardeman64741b72006-12-02 21:16:05 -0200152 */
153
David Härdeman59327a42007-02-13 09:39:58 -0300154 if (ir_debug)
155 printk("budget_ci: received byte 0x%02x\n", command);
156
David Härdeman145859c2007-04-27 12:31:22 -0300157 /* Remove repeat bit, we use every command */
158 command = command & 0x7f;
David Härdeman59327a42007-02-13 09:39:58 -0300159
David Hardeman64741b72006-12-02 21:16:05 -0200160 /* Is this a RC5 command byte? */
David Hardeman2520fff2006-12-02 21:16:05 -0200161 if (command & 0x40) {
David Härdeman145859c2007-04-27 12:31:22 -0300162 budget_ci->ir.have_command = true;
163 budget_ci->ir.ir_key = command & 0x3f;
David Hardeman64741b72006-12-02 21:16:05 -0200164 return;
David Hardeman2520fff2006-12-02 21:16:05 -0200165 }
David Hardeman64741b72006-12-02 21:16:05 -0200166
167 /* It's a RC5 device byte */
David Härdeman145859c2007-04-27 12:31:22 -0300168 if (!budget_ci->ir.have_command)
David Härdeman59327a42007-02-13 09:39:58 -0300169 return;
David Härdeman145859c2007-04-27 12:31:22 -0300170 budget_ci->ir.have_command = false;
David Hardeman64741b72006-12-02 21:16:05 -0200171
David Härdeman145859c2007-04-27 12:31:22 -0300172 if (budget_ci->ir.rc5_device != IR_DEVICE_ANY &&
173 budget_ci->ir.rc5_device != (command & 0x1f))
David Hardeman64741b72006-12-02 21:16:05 -0200174 return;
175
David Härdeman145859c2007-04-27 12:31:22 -0300176 /* Is this a repeated key sequence? (same device, command, toggle) */
177 raw = budget_ci->ir.ir_key | (command << 8);
178 if (budget_ci->ir.last_raw != raw || !timer_pending(&budget_ci->ir.timer_keyup)) {
David Hardeman59236d42006-12-02 21:16:06 -0200179 ir_input_nokey(dev, &budget_ci->ir.state);
David Härdeman145859c2007-04-27 12:31:22 -0300180 ir_input_keydown(dev, &budget_ci->ir.state,
Mauro Carvalho Chehab8573b742009-11-27 22:40:22 -0300181 budget_ci->ir.ir_key);
David Härdeman145859c2007-04-27 12:31:22 -0300182 budget_ci->ir.last_raw = raw;
David Hardeman59236d42006-12-02 21:16:06 -0200183 }
David Härdeman145859c2007-04-27 12:31:22 -0300184
185 mod_timer(&budget_ci->ir.timer_keyup, jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT));
David Hardeman2520fff2006-12-02 21:16:05 -0200186}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188static int msp430_ir_init(struct budget_ci *budget_ci)
189{
190 struct saa7146_dev *saa = budget_ci->budget.dev;
David Hardemandd2f3982006-12-02 21:16:05 -0200191 struct input_dev *input_dev = budget_ci->ir.dev;
David Hardeman8cc532e2006-12-02 21:16:05 -0200192 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
David Hardemandd2f3982006-12-02 21:16:05 -0200194 budget_ci->ir.dev = input_dev = input_allocate_device();
David Hardeman8cc532e2006-12-02 21:16:05 -0200195 if (!input_dev) {
David Hardemanee579bc2006-12-02 21:16:05 -0200196 printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
David Hardeman8cc532e2006-12-02 21:16:05 -0200197 error = -ENOMEM;
198 goto out1;
199 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
David Hardemandd2f3982006-12-02 21:16:05 -0200201 snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
202 "Budget-CI dvb ir receiver %s", saa->name);
David Hardeman5cc8ae02006-12-02 21:16:05 -0200203 snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
204 "pci-%s/ir0", pci_name(saa->pci));
205
David Hardemandd2f3982006-12-02 21:16:05 -0200206 input_dev->name = budget_ci->ir.name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207
David Hardeman5cc8ae02006-12-02 21:16:05 -0200208 input_dev->phys = budget_ci->ir.phys;
209 input_dev->id.bustype = BUS_PCI;
210 input_dev->id.version = 1;
211 if (saa->pci->subsystem_vendor) {
212 input_dev->id.vendor = saa->pci->subsystem_vendor;
213 input_dev->id.product = saa->pci->subsystem_device;
214 } else {
215 input_dev->id.vendor = saa->pci->vendor;
216 input_dev->id.product = saa->pci->device;
217 }
Dmitry Torokhov2c8a3a32007-07-16 09:28:15 -0300218 input_dev->dev.parent = &saa->pci->dev;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200219
David Hardeman64741b72006-12-02 21:16:05 -0200220 /* Select keymap and address */
David Hardeman2520fff2006-12-02 21:16:05 -0200221 switch (budget_ci->budget.dev->pci->subsystem_device) {
222 case 0x100c:
223 case 0x100f:
David Hardeman2520fff2006-12-02 21:16:05 -0200224 case 0x1011:
225 case 0x1012:
David Hardeman2520fff2006-12-02 21:16:05 -0200226 /* The hauppauge keymap is a superset of these remotes */
Mauro Carvalho Chehab055cd552009-11-29 08:19:59 -0300227 error = ir_input_init(input_dev, &budget_ci->ir.state,
Mauro Carvalho Chehab715a2232009-08-29 14:15:55 -0300228 IR_TYPE_RC5, &ir_codes_hauppauge_new_table);
Mauro Carvalho Chehab055cd552009-11-29 08:19:59 -0300229 if (error < 0)
230 goto out2;
David Hardeman64741b72006-12-02 21:16:05 -0200231
232 if (rc5_device < 0)
233 budget_ci->ir.rc5_device = 0x1f;
234 else
235 budget_ci->ir.rc5_device = rc5_device;
David Hardeman2520fff2006-12-02 21:16:05 -0200236 break;
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300237 case 0x1010:
Oliver Endrissf64899c2007-09-17 22:17:12 -0300238 case 0x1017:
Oliver Endrissbbfc4c22008-06-19 23:36:45 -0300239 case 0x101a:
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300240 /* for the Technotrend 1500 bundled remote */
Mauro Carvalho Chehab055cd552009-11-29 08:19:59 -0300241 error = ir_input_init(input_dev, &budget_ci->ir.state,
Mauro Carvalho Chehab715a2232009-08-29 14:15:55 -0300242 IR_TYPE_RC5, &ir_codes_tt_1500_table);
Mauro Carvalho Chehab055cd552009-11-29 08:19:59 -0300243 if (error < 0)
244 goto out2;
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300245
246 if (rc5_device < 0)
247 budget_ci->ir.rc5_device = IR_DEVICE_ANY;
248 else
249 budget_ci->ir.rc5_device = rc5_device;
250 break;
David Hardeman2520fff2006-12-02 21:16:05 -0200251 default:
252 /* unknown remote */
Mauro Carvalho Chehab055cd552009-11-29 08:19:59 -0300253 error = ir_input_init(input_dev, &budget_ci->ir.state,
Mauro Carvalho Chehab715a2232009-08-29 14:15:55 -0300254 IR_TYPE_RC5, &ir_codes_budget_ci_old_table);
Mauro Carvalho Chehab055cd552009-11-29 08:19:59 -0300255 if (error < 0)
256 goto out2;
David Hardeman64741b72006-12-02 21:16:05 -0200257
258 if (rc5_device < 0)
259 budget_ci->ir.rc5_device = IR_DEVICE_ANY;
260 else
261 budget_ci->ir.rc5_device = rc5_device;
David Hardeman2520fff2006-12-02 21:16:05 -0200262 break;
263 }
264
David Härdeman145859c2007-04-27 12:31:22 -0300265 /* initialise the key-up timeout handler */
266 init_timer(&budget_ci->ir.timer_keyup);
267 budget_ci->ir.timer_keyup.function = msp430_ir_keyup;
268 budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir;
269 budget_ci->ir.last_raw = 0xffff; /* An impossible value */
David Hardeman8cc532e2006-12-02 21:16:05 -0200270 error = input_register_device(input_dev);
271 if (error) {
272 printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
273 goto out2;
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300274 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275
David Härdeman145859c2007-04-27 12:31:22 -0300276 /* note: these must be after input_register_device */
277 input_dev->rep[REP_DELAY] = 400;
278 input_dev->rep[REP_PERIOD] = 250;
279
David Hardeman8cc532e2006-12-02 21:16:05 -0200280 tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
281 (unsigned long) budget_ci);
282
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300283 SAA7146_IER_ENABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
285
286 return 0;
David Hardeman8cc532e2006-12-02 21:16:05 -0200287
288out2:
Mauro Carvalho Chehab055cd552009-11-29 08:19:59 -0300289 ir_input_free(input_dev);
David Hardeman8cc532e2006-12-02 21:16:05 -0200290 input_free_device(input_dev);
291out1:
292 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293}
294
295static void msp430_ir_deinit(struct budget_ci *budget_ci)
296{
297 struct saa7146_dev *saa = budget_ci->budget.dev;
David Hardemandd2f3982006-12-02 21:16:05 -0200298 struct input_dev *dev = budget_ci->ir.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300300 SAA7146_IER_DISABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
David Hardeman8cc532e2006-12-02 21:16:05 -0200302 tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
David Härdeman145859c2007-04-27 12:31:22 -0300304 del_timer_sync(&dev->timer);
305 ir_input_nokey(dev, &budget_ci->ir.state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306
Mauro Carvalho Chehab055cd552009-11-29 08:19:59 -0300307 ir_input_free(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 input_unregister_device(dev);
309}
310
311static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
312{
313 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
314
315 if (slot != 0)
316 return -EINVAL;
317
318 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
319 DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);
320}
321
322static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
323{
324 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
325
326 if (slot != 0)
327 return -EINVAL;
328
329 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
330 DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);
331}
332
333static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
334{
335 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
336
337 if (slot != 0)
338 return -EINVAL;
339
340 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
341 DEBIADDR_IO | (address & 3), 1, 1, 0);
342}
343
344static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
345{
346 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
347
348 if (slot != 0)
349 return -EINVAL;
350
351 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
352 DEBIADDR_IO | (address & 3), 1, value, 1, 0);
353}
354
355static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
356{
357 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
358 struct saa7146_dev *saa = budget_ci->budget.dev;
359
360 if (slot != 0)
361 return -EINVAL;
362
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300363 if (budget_ci->ci_irq) {
364 // trigger on RISING edge during reset so we know when READY is re-asserted
365 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
366 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 budget_ci->slot_status = SLOTSTATUS_RESET;
368 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
369 msleep(1);
370 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
371 CICONTROL_RESET, 1, 0);
372
373 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
374 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
375 return 0;
376}
377
378static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
379{
380 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
381 struct saa7146_dev *saa = budget_ci->budget.dev;
382
383 if (slot != 0)
384 return -EINVAL;
385
386 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
387 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
388 return 0;
389}
390
391static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
392{
393 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
394 struct saa7146_dev *saa = budget_ci->budget.dev;
395 int tmp;
396
397 if (slot != 0)
398 return -EINVAL;
399
400 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
401
402 tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
403 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
404 tmp | CICONTROL_ENABLETS, 1, 0);
405
406 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
407 return 0;
408}
409
410static void ciintf_interrupt(unsigned long data)
411{
412 struct budget_ci *budget_ci = (struct budget_ci *) data;
413 struct saa7146_dev *saa = budget_ci->budget.dev;
414 unsigned int flags;
415
416 // ensure we don't get spurious IRQs during initialisation
417 if (!budget_ci->budget.ci_present)
418 return;
419
420 // read the CAM status
421 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
422 if (flags & CICONTROL_CAMDETECT) {
423
424 // GPIO should be set to trigger on falling edge if a CAM is present
425 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
426
427 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
428 // CAM insertion IRQ
429 budget_ci->slot_status = SLOTSTATUS_PRESENT;
430 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
431 DVB_CA_EN50221_CAMCHANGE_INSERTED);
432
433 } else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
434 // CAM ready (reset completed)
435 budget_ci->slot_status = SLOTSTATUS_READY;
436 dvb_ca_en50221_camready_irq(&budget_ci->ca, 0);
437
438 } else if (budget_ci->slot_status & SLOTSTATUS_READY) {
439 // FR/DA IRQ
440 dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);
441 }
442 } else {
443
444 // trigger on rising edge if a CAM is not present - when a CAM is inserted, we
445 // only want to get the IRQ when it sets READY. If we trigger on the falling edge,
446 // the CAM might not actually be ready yet.
447 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
448
449 // generate a CAM removal IRQ if we haven't already
450 if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
451 // CAM removal IRQ
452 budget_ci->slot_status = SLOTSTATUS_NONE;
453 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
454 DVB_CA_EN50221_CAMCHANGE_REMOVED);
455 }
456 }
457}
458
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300459static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
460{
461 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
462 unsigned int flags;
463
464 // ensure we don't get spurious IRQs during initialisation
465 if (!budget_ci->budget.ci_present)
466 return -EINVAL;
467
468 // read the CAM status
469 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
470 if (flags & CICONTROL_CAMDETECT) {
471 // mark it as present if it wasn't before
472 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
473 budget_ci->slot_status = SLOTSTATUS_PRESENT;
474 }
475
476 // during a RESET, we check if we can read from IO memory to see when CAM is ready
477 if (budget_ci->slot_status & SLOTSTATUS_RESET) {
478 if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
479 budget_ci->slot_status = SLOTSTATUS_READY;
480 }
481 }
482 } else {
483 budget_ci->slot_status = SLOTSTATUS_NONE;
484 }
485
486 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
487 if (budget_ci->slot_status & SLOTSTATUS_READY) {
488 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
489 }
490 return DVB_CA_EN50221_POLL_CAM_PRESENT;
491 }
492
493 return 0;
494}
495
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496static int ciintf_init(struct budget_ci *budget_ci)
497{
498 struct saa7146_dev *saa = budget_ci->budget.dev;
499 int flags;
500 int result;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300501 int ci_version;
502 int ca_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503
504 memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
505
506 // enable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300507 saa7146_write(saa, MC1, MASK_27 | MASK_11);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508
509 // test if it is there
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300510 ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
511 if ((ci_version & 0xa0) != 0xa0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 result = -ENODEV;
513 goto error;
514 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300515
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 // determine whether a CAM is present or not
517 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
518 budget_ci->slot_status = SLOTSTATUS_NONE;
519 if (flags & CICONTROL_CAMDETECT)
520 budget_ci->slot_status = SLOTSTATUS_PRESENT;
521
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300522 // version 0xa2 of the CI firmware doesn't generate interrupts
523 if (ci_version == 0xa2) {
524 ca_flags = 0;
525 budget_ci->ci_irq = 0;
526 } else {
527 ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
528 DVB_CA_EN50221_FLAG_IRQ_FR |
529 DVB_CA_EN50221_FLAG_IRQ_DA;
530 budget_ci->ci_irq = 1;
531 }
532
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 // register CI interface
534 budget_ci->ca.owner = THIS_MODULE;
535 budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
536 budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
537 budget_ci->ca.read_cam_control = ciintf_read_cam_control;
538 budget_ci->ca.write_cam_control = ciintf_write_cam_control;
539 budget_ci->ca.slot_reset = ciintf_slot_reset;
540 budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
541 budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300542 budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 budget_ci->ca.data = budget_ci;
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700544 if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 &budget_ci->ca,
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300546 ca_flags, 1)) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 printk("budget_ci: CI interface detected, but initialisation failed.\n");
548 goto error;
549 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300550
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 // Setup CI slot IRQ
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300552 if (budget_ci->ci_irq) {
553 tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
554 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
555 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
556 } else {
557 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
558 }
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300559 SAA7146_IER_ENABLE(saa, MASK_03);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300561
562 // enable interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
564 CICONTROL_RESET, 1, 0);
565
566 // success!
567 printk("budget_ci: CI interface initialised\n");
568 budget_ci->budget.ci_present = 1;
569
570 // forge a fake CI IRQ so the CAM state is setup correctly
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300571 if (budget_ci->ci_irq) {
572 flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
573 if (budget_ci->slot_status != SLOTSTATUS_NONE)
574 flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
575 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
576 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577
578 return 0;
579
580error:
Hartmut Birr2a893de2006-12-03 21:08:08 -0300581 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 return result;
583}
584
585static void ciintf_deinit(struct budget_ci *budget_ci)
586{
587 struct saa7146_dev *saa = budget_ci->budget.dev;
588
589 // disable CI interrupts
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300590 if (budget_ci->ci_irq) {
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300591 SAA7146_IER_DISABLE(saa, MASK_03);
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300592 saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
593 tasklet_kill(&budget_ci->ciintf_irq_tasklet);
594 }
595
596 // reset interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
598 msleep(1);
599 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
600 CICONTROL_RESET, 1, 0);
601
602 // disable TS data stream to CI interface
603 saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
604
605 // release the CA device
606 dvb_ca_en50221_release(&budget_ci->ca);
607
608 // disable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300609 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610}
611
612static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
613{
614 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
615
616 dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
617
618 if (*isr & MASK_06)
David Hardemandd2f3982006-12-02 21:16:05 -0200619 tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
621 if (*isr & MASK_10)
622 ttpci_budget_irq10_handler(dev, isr);
623
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300624 if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
626}
627
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628static u8 philips_su1278_tt_inittab[] = {
629 0x01, 0x0f,
630 0x02, 0x30,
631 0x03, 0x00,
632 0x04, 0x5b,
633 0x05, 0x85,
634 0x06, 0x02,
635 0x07, 0x00,
636 0x08, 0x02,
637 0x09, 0x00,
638 0x0C, 0x01,
639 0x0D, 0x81,
640 0x0E, 0x44,
641 0x0f, 0x14,
642 0x10, 0x3c,
643 0x11, 0x84,
644 0x12, 0xda,
645 0x13, 0x97,
646 0x14, 0x95,
647 0x15, 0xc9,
648 0x16, 0x19,
649 0x17, 0x8c,
650 0x18, 0x59,
651 0x19, 0xf8,
652 0x1a, 0xfe,
653 0x1c, 0x7f,
654 0x1d, 0x00,
655 0x1e, 0x00,
656 0x1f, 0x50,
657 0x20, 0x00,
658 0x21, 0x00,
659 0x22, 0x00,
660 0x23, 0x00,
661 0x28, 0x00,
662 0x29, 0x28,
663 0x2a, 0x14,
664 0x2b, 0x0f,
665 0x2c, 0x09,
666 0x2d, 0x09,
667 0x31, 0x1f,
668 0x32, 0x19,
669 0x33, 0xfc,
670 0x34, 0x93,
671 0xff, 0xff
672};
673
674static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
675{
676 stv0299_writereg(fe, 0x0e, 0x44);
677 if (srate >= 10000000) {
678 stv0299_writereg(fe, 0x13, 0x97);
679 stv0299_writereg(fe, 0x14, 0x95);
680 stv0299_writereg(fe, 0x15, 0xc9);
681 stv0299_writereg(fe, 0x17, 0x8c);
682 stv0299_writereg(fe, 0x1a, 0xfe);
683 stv0299_writereg(fe, 0x1c, 0x7f);
684 stv0299_writereg(fe, 0x2d, 0x09);
685 } else {
686 stv0299_writereg(fe, 0x13, 0x99);
687 stv0299_writereg(fe, 0x14, 0x8d);
688 stv0299_writereg(fe, 0x15, 0xce);
689 stv0299_writereg(fe, 0x17, 0x43);
690 stv0299_writereg(fe, 0x1a, 0x1d);
691 stv0299_writereg(fe, 0x1c, 0x12);
692 stv0299_writereg(fe, 0x2d, 0x05);
693 }
694 stv0299_writereg(fe, 0x0e, 0x23);
695 stv0299_writereg(fe, 0x0f, 0x94);
696 stv0299_writereg(fe, 0x10, 0x39);
697 stv0299_writereg(fe, 0x15, 0xc9);
698
699 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
700 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
701 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
702
703 return 0;
704}
705
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300706static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,
707 struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708{
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300709 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 u32 div;
711 u8 buf[4];
712 struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
713
714 if ((params->frequency < 950000) || (params->frequency > 2150000))
715 return -EINVAL;
716
717 div = (params->frequency + (500 - 1)) / 500; // round correctly
718 buf[0] = (div >> 8) & 0x7f;
719 buf[1] = div & 0xff;
720 buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
721 buf[3] = 0x20;
722
723 if (params->u.qpsk.symbol_rate < 4000000)
724 buf[3] |= 1;
725
726 if (params->frequency < 1250000)
727 buf[3] |= 0;
728 else if (params->frequency < 1550000)
729 buf[3] |= 0x40;
730 else if (params->frequency < 2050000)
731 buf[3] |= 0x80;
732 else if (params->frequency < 2150000)
733 buf[3] |= 0xC0;
734
Patrick Boettcherdea74862006-05-14 05:01:31 -0300735 if (fe->ops.i2c_gate_ctrl)
736 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300737 if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 return -EIO;
739 return 0;
740}
741
742static struct stv0299_config philips_su1278_tt_config = {
743
744 .demod_address = 0x68,
745 .inittab = philips_su1278_tt_inittab,
746 .mclk = 64000000UL,
747 .invert = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 .skip_reinit = 1,
Oliver Endrissda2c7f62008-04-20 22:13:37 -0300749 .lock_output = STV0299_LOCKOUTPUT_1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 .volt13_op0_op1 = STV0299_VOLT13_OP1,
751 .min_delay_ms = 50,
752 .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753};
754
755
756
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300757static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758{
759 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
760 static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
761 static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700762 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 sizeof(td1316_init) };
764
765 // setup PLL configuration
Patrick Boettcherdea74862006-05-14 05:01:31 -0300766 if (fe->ops.i2c_gate_ctrl)
767 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
769 return -EIO;
770 msleep(1);
771
772 // disable the mc44BC374c (do not check for errors)
773 tuner_msg.addr = 0x65;
774 tuner_msg.buf = disable_mc44BC374c;
775 tuner_msg.len = sizeof(disable_mc44BC374c);
Patrick Boettcherdea74862006-05-14 05:01:31 -0300776 if (fe->ops.i2c_gate_ctrl)
777 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
Patrick Boettcherdea74862006-05-14 05:01:31 -0300779 if (fe->ops.i2c_gate_ctrl)
780 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
782 }
783
784 return 0;
785}
786
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300787static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788{
789 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
790 u8 tuner_buf[4];
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700791 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = tuner_buf,.len = sizeof(tuner_buf) };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 int tuner_frequency = 0;
793 u8 band, cp, filter;
794
795 // determine charge pump
796 tuner_frequency = params->frequency + 36130000;
797 if (tuner_frequency < 87000000)
798 return -EINVAL;
799 else if (tuner_frequency < 130000000)
800 cp = 3;
801 else if (tuner_frequency < 160000000)
802 cp = 5;
803 else if (tuner_frequency < 200000000)
804 cp = 6;
805 else if (tuner_frequency < 290000000)
806 cp = 3;
807 else if (tuner_frequency < 420000000)
808 cp = 5;
809 else if (tuner_frequency < 480000000)
810 cp = 6;
811 else if (tuner_frequency < 620000000)
812 cp = 3;
813 else if (tuner_frequency < 830000000)
814 cp = 5;
815 else if (tuner_frequency < 895000000)
816 cp = 7;
817 else
818 return -EINVAL;
819
820 // determine band
821 if (params->frequency < 49000000)
822 return -EINVAL;
823 else if (params->frequency < 159000000)
824 band = 1;
825 else if (params->frequency < 444000000)
826 band = 2;
827 else if (params->frequency < 861000000)
828 band = 4;
829 else
830 return -EINVAL;
831
832 // setup PLL filter and TDA9889
833 switch (params->u.ofdm.bandwidth) {
834 case BANDWIDTH_6_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300835 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 filter = 0;
837 break;
838
839 case BANDWIDTH_7_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300840 tda1004x_writereg(fe, 0x0C, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 filter = 0;
842 break;
843
844 case BANDWIDTH_8_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300845 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 filter = 1;
847 break;
848
849 default:
850 return -EINVAL;
851 }
852
853 // calculate divisor
854 // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
855 tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
856
857 // setup tuner buffer
858 tuner_buf[0] = tuner_frequency >> 8;
859 tuner_buf[1] = tuner_frequency & 0xff;
860 tuner_buf[2] = 0xca;
861 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
862
Patrick Boettcherdea74862006-05-14 05:01:31 -0300863 if (fe->ops.i2c_gate_ctrl)
864 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
866 return -EIO;
867
868 msleep(1);
869 return 0;
870}
871
872static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,
873 const struct firmware **fw, char *name)
874{
875 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
876
877 return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);
878}
879
880static struct tda1004x_config philips_tdm1316l_config = {
881
882 .demod_address = 0x8,
883 .invert = 0,
884 .invert_oclk = 0,
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700885 .xtal_freq = TDA10046_XTAL_4M,
886 .agc_config = TDA10046_AGC_DEFAULT,
887 .if_freq = TDA10046_FREQ_3617,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 .request_firmware = philips_tdm1316l_request_firmware,
889};
890
Oliver Endriss6c914492007-02-02 19:12:53 -0300891static struct tda1004x_config philips_tdm1316l_config_invert = {
892
893 .demod_address = 0x8,
894 .invert = 1,
895 .invert_oclk = 0,
896 .xtal_freq = TDA10046_XTAL_4M,
897 .agc_config = TDA10046_AGC_DEFAULT,
898 .if_freq = TDA10046_FREQ_3617,
899 .request_firmware = philips_tdm1316l_request_firmware,
900};
901
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300902static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700903{
904 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
905 u8 tuner_buf[5];
906 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
907 .flags = 0,
908 .buf = tuner_buf,
909 .len = sizeof(tuner_buf) };
910 int tuner_frequency = 0;
911 u8 band, cp, filter;
912
913 // determine charge pump
914 tuner_frequency = params->frequency + 36125000;
915 if (tuner_frequency < 87000000)
916 return -EINVAL;
917 else if (tuner_frequency < 130000000) {
918 cp = 3;
919 band = 1;
920 } else if (tuner_frequency < 160000000) {
921 cp = 5;
922 band = 1;
923 } else if (tuner_frequency < 200000000) {
924 cp = 6;
Oliver Endriss910a7b62007-05-03 13:16:12 -0300925 band = 1;
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700926 } else if (tuner_frequency < 290000000) {
927 cp = 3;
928 band = 2;
929 } else if (tuner_frequency < 420000000) {
930 cp = 5;
931 band = 2;
932 } else if (tuner_frequency < 480000000) {
933 cp = 6;
934 band = 2;
935 } else if (tuner_frequency < 620000000) {
936 cp = 3;
937 band = 4;
938 } else if (tuner_frequency < 830000000) {
939 cp = 5;
940 band = 4;
941 } else if (tuner_frequency < 895000000) {
942 cp = 7;
943 band = 4;
944 } else
945 return -EINVAL;
946
947 // assume PLL filter should always be 8MHz for the moment.
948 filter = 1;
949
950 // calculate divisor
951 tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
952
953 // setup tuner buffer
954 tuner_buf[0] = tuner_frequency >> 8;
955 tuner_buf[1] = tuner_frequency & 0xff;
956 tuner_buf[2] = 0xc8;
957 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
958 tuner_buf[4] = 0x80;
959
Patrick Boettcherdea74862006-05-14 05:01:31 -0300960 if (fe->ops.i2c_gate_ctrl)
961 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700962 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
963 return -EIO;
964
965 msleep(50);
966
Patrick Boettcherdea74862006-05-14 05:01:31 -0300967 if (fe->ops.i2c_gate_ctrl)
968 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700969 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
970 return -EIO;
971
972 msleep(1);
973
974 return 0;
975}
976
977static u8 dvbc_philips_tdm1316l_inittab[] = {
978 0x80, 0x01,
979 0x80, 0x00,
980 0x81, 0x01,
981 0x81, 0x00,
982 0x00, 0x09,
983 0x01, 0x69,
984 0x03, 0x00,
985 0x04, 0x00,
986 0x07, 0x00,
987 0x08, 0x00,
988 0x20, 0x00,
989 0x21, 0x40,
990 0x22, 0x00,
991 0x23, 0x00,
992 0x24, 0x40,
993 0x25, 0x88,
994 0x30, 0xff,
995 0x31, 0x00,
996 0x32, 0xff,
997 0x33, 0x00,
998 0x34, 0x50,
999 0x35, 0x7f,
1000 0x36, 0x00,
1001 0x37, 0x20,
1002 0x38, 0x00,
1003 0x40, 0x1c,
1004 0x41, 0xff,
1005 0x42, 0x29,
1006 0x43, 0x20,
1007 0x44, 0xff,
1008 0x45, 0x00,
1009 0x46, 0x00,
1010 0x49, 0x04,
1011 0x4a, 0x00,
1012 0x4b, 0x7b,
1013 0x52, 0x30,
1014 0x55, 0xae,
1015 0x56, 0x47,
1016 0x57, 0xe1,
1017 0x58, 0x3a,
1018 0x5a, 0x1e,
1019 0x5b, 0x34,
1020 0x60, 0x00,
1021 0x63, 0x00,
1022 0x64, 0x00,
1023 0x65, 0x00,
1024 0x66, 0x00,
1025 0x67, 0x00,
1026 0x68, 0x00,
1027 0x69, 0x00,
1028 0x6a, 0x02,
1029 0x6b, 0x00,
1030 0x70, 0xff,
1031 0x71, 0x00,
1032 0x72, 0x00,
1033 0x73, 0x00,
1034 0x74, 0x0c,
1035 0x80, 0x00,
1036 0x81, 0x00,
1037 0x82, 0x00,
1038 0x83, 0x00,
1039 0x84, 0x04,
1040 0x85, 0x80,
1041 0x86, 0x24,
1042 0x87, 0x78,
1043 0x88, 0x10,
1044 0x89, 0x00,
1045 0x90, 0x01,
1046 0x91, 0x01,
1047 0xa0, 0x04,
1048 0xa1, 0x00,
1049 0xa2, 0x00,
1050 0xb0, 0x91,
1051 0xb1, 0x0b,
1052 0xc0, 0x53,
1053 0xc1, 0x70,
1054 0xc2, 0x12,
1055 0xd0, 0x00,
1056 0xd1, 0x00,
1057 0xd2, 0x00,
1058 0xd3, 0x00,
1059 0xd4, 0x00,
1060 0xd5, 0x00,
1061 0xde, 0x00,
1062 0xdf, 0x00,
1063 0x61, 0x38,
1064 0x62, 0x0a,
1065 0x53, 0x13,
1066 0x59, 0x08,
1067 0xff, 0xff,
1068};
1069
1070static struct stv0297_config dvbc_philips_tdm1316l_config = {
1071 .demod_address = 0x1c,
1072 .inittab = dvbc_philips_tdm1316l_inittab,
1073 .invert = 0,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001074 .stop_during_read = 1,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001075};
1076
Sigmund Augdal11417da2008-06-15 17:25:46 -03001077static struct tda10023_config tda10023_config = {
1078 .demod_address = 0xc,
1079 .invert = 0,
1080 .xtal = 16000000,
1081 .pll_m = 11,
1082 .pll_p = 3,
1083 .pll_n = 1,
1084 .deltaf = 0xa511,
1085};
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001086
klaas de waalcf47d872009-03-25 17:53:02 -03001087static struct tda827x_config tda827x_config = {
1088 .config = 0,
1089};
1090
Manu Abrahama55bc842008-10-23 18:32:50 -03001091/* TT S2-3200 DVB-S (STB0899) Inittab */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001092static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001094 { STB0899_DEV_ID , 0x81 },
1095 { STB0899_DISCNTRL1 , 0x32 },
1096 { STB0899_DISCNTRL2 , 0x80 },
1097 { STB0899_DISRX_ST0 , 0x04 },
1098 { STB0899_DISRX_ST1 , 0x00 },
1099 { STB0899_DISPARITY , 0x00 },
1100 { STB0899_DISFIFO , 0x00 },
1101 { STB0899_DISSTATUS , 0x20 },
1102 { STB0899_DISF22 , 0x8c },
1103 { STB0899_DISF22RX , 0x9a },
Manu Abrahamef3052b2008-10-23 18:45:17 -03001104 { STB0899_SYSREG , 0x0b },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001105 { STB0899_ACRPRESC , 0x11 },
1106 { STB0899_ACRDIV1 , 0x0a },
1107 { STB0899_ACRDIV2 , 0x05 },
1108 { STB0899_DACR1 , 0x00 },
1109 { STB0899_DACR2 , 0x00 },
1110 { STB0899_OUTCFG , 0x00 },
1111 { STB0899_MODECFG , 0x00 },
1112 { STB0899_IRQSTATUS_3 , 0x30 },
1113 { STB0899_IRQSTATUS_2 , 0x00 },
1114 { STB0899_IRQSTATUS_1 , 0x00 },
1115 { STB0899_IRQSTATUS_0 , 0x00 },
1116 { STB0899_IRQMSK_3 , 0xf3 },
1117 { STB0899_IRQMSK_2 , 0xfc },
1118 { STB0899_IRQMSK_1 , 0xff },
1119 { STB0899_IRQMSK_0 , 0xff },
1120 { STB0899_IRQCFG , 0x00 },
1121 { STB0899_I2CCFG , 0x88 },
Manu Abraham40e8ce32008-02-03 19:37:02 -03001122 { STB0899_I2CRPT , 0x48 }, /* 12k Pullup, Repeater=16, Stop=disabled */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001123 { STB0899_IOPVALUE5 , 0x00 },
1124 { STB0899_IOPVALUE4 , 0x20 },
1125 { STB0899_IOPVALUE3 , 0xc9 },
1126 { STB0899_IOPVALUE2 , 0x90 },
1127 { STB0899_IOPVALUE1 , 0x40 },
1128 { STB0899_IOPVALUE0 , 0x00 },
1129 { STB0899_GPIO00CFG , 0x82 },
1130 { STB0899_GPIO01CFG , 0x82 },
1131 { STB0899_GPIO02CFG , 0x82 },
1132 { STB0899_GPIO03CFG , 0x82 },
1133 { STB0899_GPIO04CFG , 0x82 },
1134 { STB0899_GPIO05CFG , 0x82 },
1135 { STB0899_GPIO06CFG , 0x82 },
1136 { STB0899_GPIO07CFG , 0x82 },
1137 { STB0899_GPIO08CFG , 0x82 },
1138 { STB0899_GPIO09CFG , 0x82 },
1139 { STB0899_GPIO10CFG , 0x82 },
1140 { STB0899_GPIO11CFG , 0x82 },
1141 { STB0899_GPIO12CFG , 0x82 },
1142 { STB0899_GPIO13CFG , 0x82 },
1143 { STB0899_GPIO14CFG , 0x82 },
1144 { STB0899_GPIO15CFG , 0x82 },
1145 { STB0899_GPIO16CFG , 0x82 },
1146 { STB0899_GPIO17CFG , 0x82 },
1147 { STB0899_GPIO18CFG , 0x82 },
1148 { STB0899_GPIO19CFG , 0x82 },
1149 { STB0899_GPIO20CFG , 0x82 },
1150 { STB0899_SDATCFG , 0xb8 },
1151 { STB0899_SCLTCFG , 0xba },
Manu Abrahama55bc842008-10-23 18:32:50 -03001152 { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */
1153 { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */
1154 { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001155 { STB0899_DIRCLKCFG , 0x82 },
1156 { STB0899_CLKOUT27CFG , 0x7e },
1157 { STB0899_STDBYCFG , 0x82 },
1158 { STB0899_CS0CFG , 0x82 },
1159 { STB0899_CS1CFG , 0x82 },
1160 { STB0899_DISEQCOCFG , 0x20 },
1161 { STB0899_GPIO32CFG , 0x82 },
1162 { STB0899_GPIO33CFG , 0x82 },
1163 { STB0899_GPIO34CFG , 0x82 },
1164 { STB0899_GPIO35CFG , 0x82 },
1165 { STB0899_GPIO36CFG , 0x82 },
1166 { STB0899_GPIO37CFG , 0x82 },
1167 { STB0899_GPIO38CFG , 0x82 },
1168 { STB0899_GPIO39CFG , 0x82 },
Manu Abrahamf2e52cd2007-11-19 16:44:47 -03001169 { STB0899_NCOARSE , 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
Manu Abrahama55bc842008-10-23 18:32:50 -03001170 { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001171 { STB0899_FILTCTRL , 0x00 },
1172 { STB0899_SYSCTRL , 0x00 },
1173 { STB0899_STOPCLK1 , 0x20 },
1174 { STB0899_STOPCLK2 , 0x00 },
1175 { STB0899_INTBUFSTATUS , 0x00 },
1176 { STB0899_INTBUFCTRL , 0x0a },
1177 { 0xffff , 0xff },
1178};
1179
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001180static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = {
1181 { STB0899_DEMOD , 0x00 },
1182 { STB0899_RCOMPC , 0xc9 },
1183 { STB0899_AGC1CN , 0x41 },
1184 { STB0899_AGC1REF , 0x10 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001185 { STB0899_RTC , 0x7a },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001186 { STB0899_TMGCFG , 0x4e },
1187 { STB0899_AGC2REF , 0x34 },
1188 { STB0899_TLSR , 0x84 },
1189 { STB0899_CFD , 0xc7 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001190 { STB0899_ACLC , 0x87 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001191 { STB0899_BCLC , 0x94 },
1192 { STB0899_EQON , 0x41 },
1193 { STB0899_LDT , 0xdd },
1194 { STB0899_LDT2 , 0xc9 },
1195 { STB0899_EQUALREF , 0xb4 },
1196 { STB0899_TMGRAMP , 0x10 },
1197 { STB0899_TMGTHD , 0x30 },
1198 { STB0899_IDCCOMP , 0xfb },
1199 { STB0899_QDCCOMP , 0x03 },
1200 { STB0899_POWERI , 0x3b },
1201 { STB0899_POWERQ , 0x3d },
1202 { STB0899_RCOMP , 0x81 },
1203 { STB0899_AGCIQIN , 0x80 },
1204 { STB0899_AGC2I1 , 0x04 },
1205 { STB0899_AGC2I2 , 0xf5 },
1206 { STB0899_TLIR , 0x25 },
1207 { STB0899_RTF , 0x80 },
1208 { STB0899_DSTATUS , 0x00 },
1209 { STB0899_LDI , 0xca },
1210 { STB0899_CFRM , 0xf1 },
1211 { STB0899_CFRL , 0xf3 },
1212 { STB0899_NIRM , 0x2a },
1213 { STB0899_NIRL , 0x05 },
1214 { STB0899_ISYMB , 0x17 },
1215 { STB0899_QSYMB , 0xfa },
1216 { STB0899_SFRH , 0x2f },
1217 { STB0899_SFRM , 0x68 },
1218 { STB0899_SFRL , 0x40 },
1219 { STB0899_SFRUPH , 0x2f },
1220 { STB0899_SFRUPM , 0x68 },
1221 { STB0899_SFRUPL , 0x40 },
1222 { STB0899_EQUAI1 , 0xfd },
1223 { STB0899_EQUAQ1 , 0x04 },
1224 { STB0899_EQUAI2 , 0x0f },
1225 { STB0899_EQUAQ2 , 0xff },
1226 { STB0899_EQUAI3 , 0xdf },
1227 { STB0899_EQUAQ3 , 0xfa },
1228 { STB0899_EQUAI4 , 0x37 },
1229 { STB0899_EQUAQ4 , 0x0d },
1230 { STB0899_EQUAI5 , 0xbd },
1231 { STB0899_EQUAQ5 , 0xf7 },
1232 { STB0899_DSTATUS2 , 0x00 },
1233 { STB0899_VSTATUS , 0x00 },
1234 { STB0899_VERROR , 0xff },
1235 { STB0899_IQSWAP , 0x2a },
1236 { STB0899_ECNT1M , 0x00 },
1237 { STB0899_ECNT1L , 0x00 },
1238 { STB0899_ECNT2M , 0x00 },
1239 { STB0899_ECNT2L , 0x00 },
1240 { STB0899_ECNT3M , 0x00 },
1241 { STB0899_ECNT3L , 0x00 },
1242 { STB0899_FECAUTO1 , 0x06 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001243 { STB0899_FECM , 0x01 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001244 { STB0899_VTH12 , 0xf0 },
1245 { STB0899_VTH23 , 0xa0 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001246 { STB0899_VTH34 , 0x78 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001247 { STB0899_VTH56 , 0x4e },
1248 { STB0899_VTH67 , 0x48 },
1249 { STB0899_VTH78 , 0x38 },
1250 { STB0899_PRVIT , 0xff },
1251 { STB0899_VITSYNC , 0x19 },
Manu Abrahama55bc842008-10-23 18:32:50 -03001252 { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001253 { STB0899_TSULC , 0x42 },
1254 { STB0899_RSLLC , 0x40 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001255 { STB0899_TSLPL , 0x12 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001256 { STB0899_TSCFGH , 0x0c },
1257 { STB0899_TSCFGM , 0x00 },
1258 { STB0899_TSCFGL , 0x0c },
Manu Abrahamc1426df2009-11-13 18:51:39 -03001259 { STB0899_TSOUT , 0x4d }, /* 0x0d for CAM */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001260 { STB0899_RSSYNCDEL , 0x00 },
1261 { STB0899_TSINHDELH , 0x02 },
1262 { STB0899_TSINHDELM , 0x00 },
1263 { STB0899_TSINHDELL , 0x00 },
1264 { STB0899_TSLLSTKM , 0x00 },
1265 { STB0899_TSLLSTKL , 0x00 },
1266 { STB0899_TSULSTKM , 0x00 },
1267 { STB0899_TSULSTKL , 0xab },
1268 { STB0899_PCKLENUL , 0x00 },
1269 { STB0899_PCKLENLL , 0xcc },
1270 { STB0899_RSPCKLEN , 0xcc },
1271 { STB0899_TSSTATUS , 0x80 },
1272 { STB0899_ERRCTRL1 , 0xb6 },
1273 { STB0899_ERRCTRL2 , 0x96 },
1274 { STB0899_ERRCTRL3 , 0x89 },
1275 { STB0899_DMONMSK1 , 0x27 },
1276 { STB0899_DMONMSK0 , 0x03 },
1277 { STB0899_DEMAPVIT , 0x5c },
1278 { STB0899_PLPARM , 0x1f },
1279 { STB0899_PDELCTRL , 0x48 },
1280 { STB0899_PDELCTRL2 , 0x00 },
1281 { STB0899_BBHCTRL1 , 0x00 },
1282 { STB0899_BBHCTRL2 , 0x00 },
1283 { STB0899_HYSTTHRESH , 0x77 },
1284 { STB0899_MATCSTM , 0x00 },
1285 { STB0899_MATCSTL , 0x00 },
1286 { STB0899_UPLCSTM , 0x00 },
1287 { STB0899_UPLCSTL , 0x00 },
1288 { STB0899_DFLCSTM , 0x00 },
1289 { STB0899_DFLCSTL , 0x00 },
1290 { STB0899_SYNCCST , 0x00 },
1291 { STB0899_SYNCDCSTM , 0x00 },
1292 { STB0899_SYNCDCSTL , 0x00 },
1293 { STB0899_ISI_ENTRY , 0x00 },
1294 { STB0899_ISI_BIT_EN , 0x00 },
1295 { STB0899_MATSTRM , 0x00 },
1296 { STB0899_MATSTRL , 0x00 },
1297 { STB0899_UPLSTRM , 0x00 },
1298 { STB0899_UPLSTRL , 0x00 },
1299 { STB0899_DFLSTRM , 0x00 },
1300 { STB0899_DFLSTRL , 0x00 },
1301 { STB0899_SYNCSTR , 0x00 },
1302 { STB0899_SYNCDSTRM , 0x00 },
1303 { STB0899_SYNCDSTRL , 0x00 },
1304 { STB0899_CFGPDELSTATUS1 , 0x10 },
1305 { STB0899_CFGPDELSTATUS2 , 0x00 },
1306 { STB0899_BBFERRORM , 0x00 },
1307 { STB0899_BBFERRORL , 0x00 },
1308 { STB0899_UPKTERRORM , 0x00 },
1309 { STB0899_UPKTERRORL , 0x00 },
1310 { 0xffff , 0xff },
1311};
1312
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001313static struct stb0899_config tt3200_config = {
1314 .init_dev = tt3200_stb0899_s1_init_1,
Manu Abraham8be969b2008-01-25 18:20:48 -03001315 .init_s2_demod = stb0899_s2_init_2,
Manu Abrahama55bc842008-10-23 18:32:50 -03001316 .init_s1_demod = tt3200_stb0899_s1_init_3,
Manu Abraham8be969b2008-01-25 18:20:48 -03001317 .init_s2_fec = stb0899_s2_init_4,
1318 .init_tst = stb0899_s1_init_5,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001319
Manu Abraham043a68b2008-01-18 14:15:17 -03001320 .postproc = NULL,
1321
Manu Abrahama55bc842008-10-23 18:32:50 -03001322 .demod_address = 0x68,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001323
1324 .xtal_freq = 27000000,
Manu Abrahame99d00c2007-09-25 17:48:59 -03001325 .inversion = IQ_SWAP_ON, /* 1 */
Manu Abrahama55bc842008-10-23 18:32:50 -03001326
Manu Abrahamb91a7cb2008-03-04 19:19:58 -03001327 .lo_clk = 76500000,
1328 .hi_clk = 99000000,
1329
Manu Abraham8be969b2008-01-25 18:20:48 -03001330 .esno_ave = STB0899_DVBS2_ESNO_AVE,
1331 .esno_quant = STB0899_DVBS2_ESNO_QUANT,
1332 .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
1333 .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
1334 .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
1335 .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
1336 .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
1337 .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
1338 .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
Manu Abrahama55bc842008-10-23 18:32:50 -03001339
Manu Abraham8be969b2008-01-25 18:20:48 -03001340 .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
1341 .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
1342 .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
1343 .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
Manu Abrahama55bc842008-10-23 18:32:50 -03001344
1345 .tuner_get_frequency = stb6100_get_frequency,
1346 .tuner_set_frequency = stb6100_set_frequency,
1347 .tuner_set_bandwidth = stb6100_set_bandwidth,
1348 .tuner_get_bandwidth = stb6100_get_bandwidth,
Manu Abraham043a68b2008-01-18 14:15:17 -03001349 .tuner_set_rfsiggain = NULL
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001350};
1351
Mauro Carvalho Chehabffbc5f82009-01-05 01:34:20 -03001352static struct stb6100_config tt3200_stb6100_config = {
Manu Abrahamc14eaed2007-10-04 16:52:51 -03001353 .tuner_address = 0x60,
1354 .refclock = 27000000,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001355};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
1357static void frontend_init(struct budget_ci *budget_ci)
1358{
1359 switch (budget_ci->budget.dev->pci->subsystem_device) {
1360 case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
1361 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001362 dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001364 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001365 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 break;
1367 }
1368 break;
1369
1370 case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
1371 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001372 dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001374 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 break;
1376 }
1377 break;
1378
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001379 case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
1380 budget_ci->tuner_pll_address = 0x61;
1381 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001382 dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001383 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001384 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001385 break;
1386 }
1387 break;
1388
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001390 budget_ci->tuner_pll_address = 0x63;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001392 dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001394 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1395 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 break;
1397 }
1398 break;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001399
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001400 case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001401 budget_ci->tuner_pll_address = 0x60;
1402 budget_ci->budget.dvb_frontend =
Oliver Endriss6c914492007-02-02 19:12:53 -03001403 dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001404 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001405 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1406 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001407 break;
1408 }
1409 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001410
1411 case 0x1017: // TT S-1500 PCI
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001412 budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001413 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001414 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001415 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
1416
Patrick Boettcherdea74862006-05-14 05:01:31 -03001417 budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001418 if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) {
Harvey Harrison3ca7fc82008-04-08 23:20:00 -03001419 printk("%s: No LNBP21 found!\n", __func__);
Andrew de Quincey2b100e72006-08-08 09:10:11 -03001420 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001421 budget_ci->budget.dvb_frontend = NULL;
1422 }
1423 }
Sigmund Augdal11417da2008-06-15 17:25:46 -03001424 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001425
Sigmund Augdal11417da2008-06-15 17:25:46 -03001426 case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */
1427 budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48);
1428 if (budget_ci->budget.dvb_frontend) {
klaas de waalcf47d872009-03-25 17:53:02 -03001429 if (dvb_attach(tda827x_attach, budget_ci->budget.dvb_frontend, 0x61, &budget_ci->budget.i2c_adap, &tda827x_config) == NULL) {
Sigmund Augdal11417da2008-06-15 17:25:46 -03001430 printk(KERN_ERR "%s: No tda827x found!\n", __func__);
1431 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1432 budget_ci->budget.dvb_frontend = NULL;
1433 }
1434 }
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001435 break;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001436
1437 case 0x1019: // TT S2-3200 PCI
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001438 /*
1439 * NOTE! on some STB0899 versions, the internal PLL takes a longer time
1440 * to settle, aka LOCK. On the older revisions of the chip, we don't see
1441 * this, as a result on the newer chips the entire clock tree, will not
1442 * be stable after a freshly POWER 'ed up situation.
1443 * In this case, we should RESET the STB0899 (Active LOW) and wait for
1444 * PLL stabilization.
1445 *
1446 * On the TT S2 3200 and clones, the STB0899 demodulator's RESETB is
1447 * connected to the SAA7146 GPIO, GPIO2, Pin 142
1448 */
1449 /* Reset Demodulator */
Manu Abraham0867f572007-10-15 13:07:16 -03001450 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001451 /* Wait for everything to die */
1452 msleep(50);
1453 /* Pull it up out of Reset state */
Manu Abraham0867f572007-10-15 13:07:16 -03001454 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001455 /* Wait for PLL to stabilize */
1456 msleep(250);
1457 /*
1458 * PLL state should be stable now. Ideally, we should check
1459 * for PLL LOCK status. But well, never mind!
1460 */
Manu Abrahamae9902d2007-10-08 18:51:54 -03001461 budget_ci->budget.dvb_frontend = dvb_attach(stb0899_attach, &tt3200_config, &budget_ci->budget.i2c_adap);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001462 if (budget_ci->budget.dvb_frontend) {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001463 if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {
1464 if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
Harvey Harrison9b4778f2009-01-07 14:42:41 -08001465 printk("%s: No LNBP21 found!\n", __func__);
Manu Abrahamae9902d2007-10-08 18:51:54 -03001466 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001467 budget_ci->budget.dvb_frontend = NULL;
1468 }
1469 } else {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001470 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1471 budget_ci->budget.dvb_frontend = NULL;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001472 }
1473 }
1474 break;
1475
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 }
1477
1478 if (budget_ci->budget.dvb_frontend == NULL) {
Bjorn Helgaas29e66a62008-09-04 17:24:51 -03001479 printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 budget_ci->budget.dev->pci->vendor,
1481 budget_ci->budget.dev->pci->device,
1482 budget_ci->budget.dev->pci->subsystem_vendor,
1483 budget_ci->budget.dev->pci->subsystem_device);
1484 } else {
1485 if (dvb_register_frontend
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001486 (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 printk("budget-ci: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001488 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 budget_ci->budget.dvb_frontend = NULL;
1490 }
1491 }
1492}
1493
1494static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
1495{
1496 struct budget_ci *budget_ci;
1497 int err;
1498
David Hardemanee579bc2006-12-02 21:16:05 -02001499 budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
David Hardeman8cc532e2006-12-02 21:16:05 -02001500 if (!budget_ci) {
1501 err = -ENOMEM;
1502 goto out1;
1503 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504
1505 dprintk(2, "budget_ci: %p\n", budget_ci);
1506
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 dev->ext_priv = budget_ci;
1508
Janne Grunau26dc4d02008-09-21 20:50:11 -03001509 err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE,
1510 adapter_nr);
David Hardeman8cc532e2006-12-02 21:16:05 -02001511 if (err)
1512 goto out2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513
David Hardeman8cc532e2006-12-02 21:16:05 -02001514 err = msp430_ir_init(budget_ci);
1515 if (err)
1516 goto out3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517
1518 ciintf_init(budget_ci);
1519
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001520 budget_ci->budget.dvb_adapter.priv = budget_ci;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 frontend_init(budget_ci);
1522
Oliver Endriss32e4c3a2006-07-18 22:55:23 -03001523 ttpci_budget_init_hooks(&budget_ci->budget);
1524
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 return 0;
David Hardeman8cc532e2006-12-02 21:16:05 -02001526
1527out3:
1528 ttpci_budget_deinit(&budget_ci->budget);
1529out2:
1530 kfree(budget_ci);
1531out1:
1532 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533}
1534
1535static int budget_ci_detach(struct saa7146_dev *dev)
1536{
1537 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
1538 struct saa7146_dev *saa = budget_ci->budget.dev;
1539 int err;
1540
1541 if (budget_ci->budget.ci_present)
1542 ciintf_deinit(budget_ci);
David Hardeman8cc532e2006-12-02 21:16:05 -02001543 msp430_ir_deinit(budget_ci);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001544 if (budget_ci->budget.dvb_frontend) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001546 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001547 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 err = ttpci_budget_deinit(&budget_ci->budget);
1549
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 // disable frontend and CI interface
1551 saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
1552
1553 kfree(budget_ci);
1554
1555 return err;
1556}
1557
1558static struct saa7146_extension budget_extension;
1559
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001560MAKE_BUDGET_INFO(ttbs2, "TT-Budget/S-1500 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
1562MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001563MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001564MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
Sigmund Augdal11417da2008-06-15 17:25:46 -03001565MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001566MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567
1568static struct pci_device_id pci_tbl[] = {
1569 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
1570 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001571 MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001573 MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001574 MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
Sigmund Augdal11417da2008-06-15 17:25:46 -03001575 MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001576 MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 {
1578 .vendor = 0,
1579 }
1580};
1581
1582MODULE_DEVICE_TABLE(pci, pci_tbl);
1583
1584static struct saa7146_extension budget_extension = {
Dave Jones0e367a12006-08-07 13:18:56 -03001585 .name = "budget_ci dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03001586 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587
1588 .module = THIS_MODULE,
1589 .pci_tbl = &pci_tbl[0],
1590 .attach = budget_ci_attach,
1591 .detach = budget_ci_detach,
1592
1593 .irq_mask = MASK_03 | MASK_06 | MASK_10,
1594 .irq_func = budget_ci_irq,
1595};
1596
1597static int __init budget_ci_init(void)
1598{
1599 return saa7146_register_extension(&budget_extension);
1600}
1601
1602static void __exit budget_ci_exit(void)
1603{
1604 saa7146_unregister_extension(&budget_extension);
1605}
1606
1607module_init(budget_ci_init);
1608module_exit(budget_ci_exit);
1609
1610MODULE_LICENSE("GPL");
1611MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
1612MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1613 "budget PCI DVB cards w/ CI-module produced by "
1614 "Siemens, Technotrend, Hauppauge");