blob: 0dc52918ce68102bf3ea5ee17a3f6fe37a25d696 [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
32#include "budget.h"
33
34#include <linux/module.h>
35#include <linux/errno.h>
36#include <linux/slab.h>
37#include <linux/interrupt.h>
38#include <linux/input.h>
39#include <linux/spinlock.h>
David Hardeman2520fff2006-12-02 21:16:05 -020040#include <media/ir-common.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42#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"
Perceval Anichini8cc2e372006-02-28 09:52:44 -030046#include "lnbp21.h"
47#include "bsbe1.h"
Perceval Anichini265366e2006-03-16 11:22:47 -030048#include "bsru6.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
David Härdemanecba77f2006-10-27 20:56:51 -030050/*
51 * Regarding DEBIADDR_IR:
52 * Some CI modules hang if random addresses are read.
53 * Using address 0x4000 for the IR read means that we
54 * use the same address as for CI version, which should
55 * be a safe default.
56 */
57#define DEBIADDR_IR 0x4000
Linus Torvalds1da177e2005-04-16 15:20:36 -070058#define DEBIADDR_CICONTROL 0x0000
59#define DEBIADDR_CIVERSION 0x4000
60#define DEBIADDR_IO 0x1000
61#define DEBIADDR_ATTR 0x3000
62
63#define CICONTROL_RESET 0x01
64#define CICONTROL_ENABLETS 0x02
65#define CICONTROL_CAMDETECT 0x08
66
67#define DEBICICTL 0x00420000
68#define DEBICICAM 0x02420000
69
70#define SLOTSTATUS_NONE 1
71#define SLOTSTATUS_PRESENT 2
72#define SLOTSTATUS_RESET 4
73#define SLOTSTATUS_READY 8
74#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
75
David Hardeman2520fff2006-12-02 21:16:05 -020076/* Milliseconds during which key presses are regarded as key repeat and during
77 * which the debounce logic is active
78 */
79#define IR_REPEAT_TIMEOUT 350
80
David Hardeman64741b72006-12-02 21:16:05 -020081/* RC5 device wildcard */
82#define IR_DEVICE_ANY 255
83
David Hardeman2520fff2006-12-02 21:16:05 -020084/* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two),
85 * this setting allows the superflous sequences to be ignored
86 */
87static int debounce = 0;
88module_param(debounce, int, 0644);
89MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)");
90
David Hardeman64741b72006-12-02 21:16:05 -020091static int rc5_device = -1;
92module_param(rc5_device, int, 0644);
93MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
94
David Hardemanb5471a22006-12-02 21:16:05 -020095static int ir_debug = 0;
96module_param(ir_debug, int, 0644);
97MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
98
David Hardemandd2f3982006-12-02 21:16:05 -020099struct budget_ci_ir {
100 struct input_dev *dev;
101 struct tasklet_struct msp430_irq_tasklet;
102 char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
David Hardeman5cc8ae02006-12-02 21:16:05 -0200103 char phys[32];
David Hardeman2520fff2006-12-02 21:16:05 -0200104 struct ir_input_state state;
David Hardeman64741b72006-12-02 21:16:05 -0200105 int rc5_device;
David Hardemandd2f3982006-12-02 21:16:05 -0200106};
107
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108struct budget_ci {
109 struct budget budget;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 struct tasklet_struct ciintf_irq_tasklet;
111 int slot_status;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300112 int ci_irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 struct dvb_ca_en50221 ca;
David Hardemandd2f3982006-12-02 21:16:05 -0200114 struct budget_ci_ir ir;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700115 u8 tuner_pll_address; /* used for philips_tdm1316l configs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116};
117
David Hardeman2520fff2006-12-02 21:16:05 -0200118static void msp430_ir_keyup(unsigned long data)
119{
120 struct budget_ci_ir *ir = (struct budget_ci_ir *) data;
121 ir_input_nokey(ir->dev, &ir->state);
122}
123
124static void msp430_ir_interrupt(unsigned long data)
125{
126 struct budget_ci *budget_ci = (struct budget_ci *) data;
127 struct input_dev *dev = budget_ci->ir.dev;
128 static int bounces = 0;
David Hardeman64741b72006-12-02 21:16:05 -0200129 int device;
130 int toggle;
131 static int prev_toggle = -1;
132 static u32 ir_key;
David Hardeman2520fff2006-12-02 21:16:05 -0200133 u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
134
David Hardeman64741b72006-12-02 21:16:05 -0200135 /*
136 * The msp430 chip can generate two different bytes, command and device
137 *
138 * type1: X1CCCCCC, C = command bits (0 - 63)
139 * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
140 *
141 * More than one command byte may be generated before the device byte
142 * Only when we have both, a correct keypress is generated
143 */
144
145 /* Is this a RC5 command byte? */
David Hardeman2520fff2006-12-02 21:16:05 -0200146 if (command & 0x40) {
David Hardemanb5471a22006-12-02 21:16:05 -0200147 if (ir_debug)
148 printk("budget_ci: received command byte 0x%02x\n", command);
David Hardeman2520fff2006-12-02 21:16:05 -0200149 ir_key = command & 0x3f;
David Hardeman64741b72006-12-02 21:16:05 -0200150 return;
David Hardeman2520fff2006-12-02 21:16:05 -0200151 }
David Hardeman64741b72006-12-02 21:16:05 -0200152
153 /* It's a RC5 device byte */
David Hardemanb5471a22006-12-02 21:16:05 -0200154 if (ir_debug)
155 printk("budget_ci: received device byte 0x%02x\n", command);
David Hardeman64741b72006-12-02 21:16:05 -0200156 device = command & 0x1f;
157 toggle = command & 0x20;
158
159 if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && budget_ci->ir.rc5_device != device)
160 return;
161
David Hardeman64741b72006-12-02 21:16:05 -0200162 /* Ignore repeated key sequences if requested */
David Hardeman59236d42006-12-02 21:16:06 -0200163 if (toggle == prev_toggle && ir_key == dev->repeat_key &&
164 bounces > 0 && timer_pending(&dev->timer)) {
165 if (ir_debug)
166 printk("budget_ci: debounce logic ignored IR command\n");
David Hardeman64741b72006-12-02 21:16:05 -0200167 bounces--;
168 return;
169 }
David Hardeman59236d42006-12-02 21:16:06 -0200170 prev_toggle = toggle;
David Hardeman64741b72006-12-02 21:16:05 -0200171
David Hardeman59236d42006-12-02 21:16:06 -0200172 /* Are we still waiting for a keyup event? */
173 if (del_timer(&dev->timer))
174 ir_input_nokey(dev, &budget_ci->ir.state);
175
176 /* Generate keypress */
177 if (ir_debug)
178 printk("budget_ci: generating keypress 0x%02x\n", ir_key);
179 ir_input_keydown(dev, &budget_ci->ir.state, ir_key, (ir_key & (command << 8)));
180
181 /* Do we want to delay the keyup event? */
182 if (debounce) {
David Hardeman64741b72006-12-02 21:16:05 -0200183 bounces = debounce;
David Hardeman59236d42006-12-02 21:16:06 -0200184 mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT));
185 } else {
186 ir_input_nokey(dev, &budget_ci->ir.state);
187 }
David Hardeman2520fff2006-12-02 21:16:05 -0200188}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190static int msp430_ir_init(struct budget_ci *budget_ci)
191{
192 struct saa7146_dev *saa = budget_ci->budget.dev;
David Hardemandd2f3982006-12-02 21:16:05 -0200193 struct input_dev *input_dev = budget_ci->ir.dev;
David Hardeman8cc532e2006-12-02 21:16:05 -0200194 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195
David Hardemandd2f3982006-12-02 21:16:05 -0200196 budget_ci->ir.dev = input_dev = input_allocate_device();
David Hardeman8cc532e2006-12-02 21:16:05 -0200197 if (!input_dev) {
David Hardemanee579bc2006-12-02 21:16:05 -0200198 printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
David Hardeman8cc532e2006-12-02 21:16:05 -0200199 error = -ENOMEM;
200 goto out1;
201 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202
David Hardemandd2f3982006-12-02 21:16:05 -0200203 snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
204 "Budget-CI dvb ir receiver %s", saa->name);
David Hardeman5cc8ae02006-12-02 21:16:05 -0200205 snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
206 "pci-%s/ir0", pci_name(saa->pci));
207
David Hardemandd2f3982006-12-02 21:16:05 -0200208 input_dev->name = budget_ci->ir.name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209
David Hardeman5cc8ae02006-12-02 21:16:05 -0200210 input_dev->phys = budget_ci->ir.phys;
211 input_dev->id.bustype = BUS_PCI;
212 input_dev->id.version = 1;
213 if (saa->pci->subsystem_vendor) {
214 input_dev->id.vendor = saa->pci->subsystem_vendor;
215 input_dev->id.product = saa->pci->subsystem_device;
216 } else {
217 input_dev->id.vendor = saa->pci->vendor;
218 input_dev->id.product = saa->pci->device;
219 }
David Hardeman5cc8ae02006-12-02 21:16:05 -0200220 input_dev->cdev.dev = &saa->pci->dev;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200221
David Hardeman64741b72006-12-02 21:16:05 -0200222 /* Select keymap and address */
David Hardeman2520fff2006-12-02 21:16:05 -0200223 switch (budget_ci->budget.dev->pci->subsystem_device) {
224 case 0x100c:
225 case 0x100f:
226 case 0x1010:
227 case 0x1011:
228 case 0x1012:
229 case 0x1017:
230 /* The hauppauge keymap is a superset of these remotes */
231 ir_input_init(input_dev, &budget_ci->ir.state,
232 IR_TYPE_RC5, ir_codes_hauppauge_new);
David Hardeman64741b72006-12-02 21:16:05 -0200233
234 if (rc5_device < 0)
235 budget_ci->ir.rc5_device = 0x1f;
236 else
237 budget_ci->ir.rc5_device = rc5_device;
David Hardeman2520fff2006-12-02 21:16:05 -0200238 break;
239 default:
240 /* unknown remote */
241 ir_input_init(input_dev, &budget_ci->ir.state,
242 IR_TYPE_RC5, ir_codes_budget_ci_old);
David Hardeman64741b72006-12-02 21:16:05 -0200243
244 if (rc5_device < 0)
245 budget_ci->ir.rc5_device = IR_DEVICE_ANY;
246 else
247 budget_ci->ir.rc5_device = rc5_device;
David Hardeman2520fff2006-12-02 21:16:05 -0200248 break;
249 }
250
David Hardeman59236d42006-12-02 21:16:06 -0200251 /* initialise the key-up debounce timeout handler */
David Hardeman2520fff2006-12-02 21:16:05 -0200252 input_dev->timer.function = msp430_ir_keyup;
253 input_dev->timer.data = (unsigned long) &budget_ci->ir;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
David Hardeman8cc532e2006-12-02 21:16:05 -0200255 error = input_register_device(input_dev);
256 if (error) {
257 printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
258 goto out2;
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300259 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260
David Hardeman8cc532e2006-12-02 21:16:05 -0200261 tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
262 (unsigned long) budget_ci);
263
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300264 SAA7146_IER_ENABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
266
267 return 0;
David Hardeman8cc532e2006-12-02 21:16:05 -0200268
269out2:
270 input_free_device(input_dev);
271out1:
272 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273}
274
275static void msp430_ir_deinit(struct budget_ci *budget_ci)
276{
277 struct saa7146_dev *saa = budget_ci->budget.dev;
David Hardemandd2f3982006-12-02 21:16:05 -0200278 struct input_dev *dev = budget_ci->ir.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300280 SAA7146_IER_DISABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
David Hardeman8cc532e2006-12-02 21:16:05 -0200282 tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300284 if (del_timer(&dev->timer)) {
David Hardeman2520fff2006-12-02 21:16:05 -0200285 ir_input_nokey(dev, &budget_ci->ir.state);
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300286 input_sync(dev);
287 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288
289 input_unregister_device(dev);
290}
291
292static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
293{
294 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
295
296 if (slot != 0)
297 return -EINVAL;
298
299 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
300 DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);
301}
302
303static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
304{
305 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
306
307 if (slot != 0)
308 return -EINVAL;
309
310 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
311 DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);
312}
313
314static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
315{
316 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
317
318 if (slot != 0)
319 return -EINVAL;
320
321 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
322 DEBIADDR_IO | (address & 3), 1, 1, 0);
323}
324
325static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
326{
327 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
328
329 if (slot != 0)
330 return -EINVAL;
331
332 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
333 DEBIADDR_IO | (address & 3), 1, value, 1, 0);
334}
335
336static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
337{
338 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
339 struct saa7146_dev *saa = budget_ci->budget.dev;
340
341 if (slot != 0)
342 return -EINVAL;
343
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300344 if (budget_ci->ci_irq) {
345 // trigger on RISING edge during reset so we know when READY is re-asserted
346 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
347 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 budget_ci->slot_status = SLOTSTATUS_RESET;
349 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
350 msleep(1);
351 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
352 CICONTROL_RESET, 1, 0);
353
354 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
355 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
356 return 0;
357}
358
359static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
360{
361 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
362 struct saa7146_dev *saa = budget_ci->budget.dev;
363
364 if (slot != 0)
365 return -EINVAL;
366
367 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
368 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
369 return 0;
370}
371
372static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
373{
374 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
375 struct saa7146_dev *saa = budget_ci->budget.dev;
376 int tmp;
377
378 if (slot != 0)
379 return -EINVAL;
380
381 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
382
383 tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
384 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
385 tmp | CICONTROL_ENABLETS, 1, 0);
386
387 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
388 return 0;
389}
390
391static void ciintf_interrupt(unsigned long data)
392{
393 struct budget_ci *budget_ci = (struct budget_ci *) data;
394 struct saa7146_dev *saa = budget_ci->budget.dev;
395 unsigned int flags;
396
397 // ensure we don't get spurious IRQs during initialisation
398 if (!budget_ci->budget.ci_present)
399 return;
400
401 // read the CAM status
402 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
403 if (flags & CICONTROL_CAMDETECT) {
404
405 // GPIO should be set to trigger on falling edge if a CAM is present
406 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
407
408 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
409 // CAM insertion IRQ
410 budget_ci->slot_status = SLOTSTATUS_PRESENT;
411 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
412 DVB_CA_EN50221_CAMCHANGE_INSERTED);
413
414 } else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
415 // CAM ready (reset completed)
416 budget_ci->slot_status = SLOTSTATUS_READY;
417 dvb_ca_en50221_camready_irq(&budget_ci->ca, 0);
418
419 } else if (budget_ci->slot_status & SLOTSTATUS_READY) {
420 // FR/DA IRQ
421 dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);
422 }
423 } else {
424
425 // trigger on rising edge if a CAM is not present - when a CAM is inserted, we
426 // only want to get the IRQ when it sets READY. If we trigger on the falling edge,
427 // the CAM might not actually be ready yet.
428 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
429
430 // generate a CAM removal IRQ if we haven't already
431 if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
432 // CAM removal IRQ
433 budget_ci->slot_status = SLOTSTATUS_NONE;
434 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
435 DVB_CA_EN50221_CAMCHANGE_REMOVED);
436 }
437 }
438}
439
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300440static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
441{
442 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
443 unsigned int flags;
444
445 // ensure we don't get spurious IRQs during initialisation
446 if (!budget_ci->budget.ci_present)
447 return -EINVAL;
448
449 // read the CAM status
450 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
451 if (flags & CICONTROL_CAMDETECT) {
452 // mark it as present if it wasn't before
453 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
454 budget_ci->slot_status = SLOTSTATUS_PRESENT;
455 }
456
457 // during a RESET, we check if we can read from IO memory to see when CAM is ready
458 if (budget_ci->slot_status & SLOTSTATUS_RESET) {
459 if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
460 budget_ci->slot_status = SLOTSTATUS_READY;
461 }
462 }
463 } else {
464 budget_ci->slot_status = SLOTSTATUS_NONE;
465 }
466
467 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
468 if (budget_ci->slot_status & SLOTSTATUS_READY) {
469 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
470 }
471 return DVB_CA_EN50221_POLL_CAM_PRESENT;
472 }
473
474 return 0;
475}
476
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477static int ciintf_init(struct budget_ci *budget_ci)
478{
479 struct saa7146_dev *saa = budget_ci->budget.dev;
480 int flags;
481 int result;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300482 int ci_version;
483 int ca_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484
485 memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
486
487 // enable DEBI pins
488 saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
489
490 // test if it is there
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300491 ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
492 if ((ci_version & 0xa0) != 0xa0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 result = -ENODEV;
494 goto error;
495 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300496
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 // determine whether a CAM is present or not
498 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
499 budget_ci->slot_status = SLOTSTATUS_NONE;
500 if (flags & CICONTROL_CAMDETECT)
501 budget_ci->slot_status = SLOTSTATUS_PRESENT;
502
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300503 // version 0xa2 of the CI firmware doesn't generate interrupts
504 if (ci_version == 0xa2) {
505 ca_flags = 0;
506 budget_ci->ci_irq = 0;
507 } else {
508 ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
509 DVB_CA_EN50221_FLAG_IRQ_FR |
510 DVB_CA_EN50221_FLAG_IRQ_DA;
511 budget_ci->ci_irq = 1;
512 }
513
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 // register CI interface
515 budget_ci->ca.owner = THIS_MODULE;
516 budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
517 budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
518 budget_ci->ca.read_cam_control = ciintf_read_cam_control;
519 budget_ci->ca.write_cam_control = ciintf_write_cam_control;
520 budget_ci->ca.slot_reset = ciintf_slot_reset;
521 budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
522 budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300523 budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 budget_ci->ca.data = budget_ci;
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700525 if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 &budget_ci->ca,
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300527 ca_flags, 1)) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 printk("budget_ci: CI interface detected, but initialisation failed.\n");
529 goto error;
530 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300531
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 // Setup CI slot IRQ
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300533 if (budget_ci->ci_irq) {
534 tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
535 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
536 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
537 } else {
538 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
539 }
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300540 SAA7146_IER_ENABLE(saa, MASK_03);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300542
543 // enable interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
545 CICONTROL_RESET, 1, 0);
546
547 // success!
548 printk("budget_ci: CI interface initialised\n");
549 budget_ci->budget.ci_present = 1;
550
551 // forge a fake CI IRQ so the CAM state is setup correctly
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300552 if (budget_ci->ci_irq) {
553 flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
554 if (budget_ci->slot_status != SLOTSTATUS_NONE)
555 flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
556 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
557 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558
559 return 0;
560
561error:
562 saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
563 return result;
564}
565
566static void ciintf_deinit(struct budget_ci *budget_ci)
567{
568 struct saa7146_dev *saa = budget_ci->budget.dev;
569
570 // disable CI interrupts
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300571 if (budget_ci->ci_irq) {
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300572 SAA7146_IER_DISABLE(saa, MASK_03);
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300573 saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
574 tasklet_kill(&budget_ci->ciintf_irq_tasklet);
575 }
576
577 // reset interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
579 msleep(1);
580 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
581 CICONTROL_RESET, 1, 0);
582
583 // disable TS data stream to CI interface
584 saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
585
586 // release the CA device
587 dvb_ca_en50221_release(&budget_ci->ca);
588
589 // disable DEBI pins
590 saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
591}
592
593static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
594{
595 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
596
597 dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
598
599 if (*isr & MASK_06)
David Hardemandd2f3982006-12-02 21:16:05 -0200600 tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601
602 if (*isr & MASK_10)
603 ttpci_budget_irq10_handler(dev, isr);
604
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300605 if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
607}
608
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609static u8 philips_su1278_tt_inittab[] = {
610 0x01, 0x0f,
611 0x02, 0x30,
612 0x03, 0x00,
613 0x04, 0x5b,
614 0x05, 0x85,
615 0x06, 0x02,
616 0x07, 0x00,
617 0x08, 0x02,
618 0x09, 0x00,
619 0x0C, 0x01,
620 0x0D, 0x81,
621 0x0E, 0x44,
622 0x0f, 0x14,
623 0x10, 0x3c,
624 0x11, 0x84,
625 0x12, 0xda,
626 0x13, 0x97,
627 0x14, 0x95,
628 0x15, 0xc9,
629 0x16, 0x19,
630 0x17, 0x8c,
631 0x18, 0x59,
632 0x19, 0xf8,
633 0x1a, 0xfe,
634 0x1c, 0x7f,
635 0x1d, 0x00,
636 0x1e, 0x00,
637 0x1f, 0x50,
638 0x20, 0x00,
639 0x21, 0x00,
640 0x22, 0x00,
641 0x23, 0x00,
642 0x28, 0x00,
643 0x29, 0x28,
644 0x2a, 0x14,
645 0x2b, 0x0f,
646 0x2c, 0x09,
647 0x2d, 0x09,
648 0x31, 0x1f,
649 0x32, 0x19,
650 0x33, 0xfc,
651 0x34, 0x93,
652 0xff, 0xff
653};
654
655static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
656{
657 stv0299_writereg(fe, 0x0e, 0x44);
658 if (srate >= 10000000) {
659 stv0299_writereg(fe, 0x13, 0x97);
660 stv0299_writereg(fe, 0x14, 0x95);
661 stv0299_writereg(fe, 0x15, 0xc9);
662 stv0299_writereg(fe, 0x17, 0x8c);
663 stv0299_writereg(fe, 0x1a, 0xfe);
664 stv0299_writereg(fe, 0x1c, 0x7f);
665 stv0299_writereg(fe, 0x2d, 0x09);
666 } else {
667 stv0299_writereg(fe, 0x13, 0x99);
668 stv0299_writereg(fe, 0x14, 0x8d);
669 stv0299_writereg(fe, 0x15, 0xce);
670 stv0299_writereg(fe, 0x17, 0x43);
671 stv0299_writereg(fe, 0x1a, 0x1d);
672 stv0299_writereg(fe, 0x1c, 0x12);
673 stv0299_writereg(fe, 0x2d, 0x05);
674 }
675 stv0299_writereg(fe, 0x0e, 0x23);
676 stv0299_writereg(fe, 0x0f, 0x94);
677 stv0299_writereg(fe, 0x10, 0x39);
678 stv0299_writereg(fe, 0x15, 0xc9);
679
680 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
681 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
682 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
683
684 return 0;
685}
686
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300687static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,
688 struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689{
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300690 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 u32 div;
692 u8 buf[4];
693 struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
694
695 if ((params->frequency < 950000) || (params->frequency > 2150000))
696 return -EINVAL;
697
698 div = (params->frequency + (500 - 1)) / 500; // round correctly
699 buf[0] = (div >> 8) & 0x7f;
700 buf[1] = div & 0xff;
701 buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
702 buf[3] = 0x20;
703
704 if (params->u.qpsk.symbol_rate < 4000000)
705 buf[3] |= 1;
706
707 if (params->frequency < 1250000)
708 buf[3] |= 0;
709 else if (params->frequency < 1550000)
710 buf[3] |= 0x40;
711 else if (params->frequency < 2050000)
712 buf[3] |= 0x80;
713 else if (params->frequency < 2150000)
714 buf[3] |= 0xC0;
715
Patrick Boettcherdea74862006-05-14 05:01:31 -0300716 if (fe->ops.i2c_gate_ctrl)
717 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300718 if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 return -EIO;
720 return 0;
721}
722
723static struct stv0299_config philips_su1278_tt_config = {
724
725 .demod_address = 0x68,
726 .inittab = philips_su1278_tt_inittab,
727 .mclk = 64000000UL,
728 .invert = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 .skip_reinit = 1,
730 .lock_output = STV0229_LOCKOUTPUT_1,
731 .volt13_op0_op1 = STV0299_VOLT13_OP1,
732 .min_delay_ms = 50,
733 .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734};
735
736
737
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300738static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739{
740 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
741 static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
742 static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700743 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 sizeof(td1316_init) };
745
746 // setup PLL configuration
Patrick Boettcherdea74862006-05-14 05:01:31 -0300747 if (fe->ops.i2c_gate_ctrl)
748 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
750 return -EIO;
751 msleep(1);
752
753 // disable the mc44BC374c (do not check for errors)
754 tuner_msg.addr = 0x65;
755 tuner_msg.buf = disable_mc44BC374c;
756 tuner_msg.len = sizeof(disable_mc44BC374c);
Patrick Boettcherdea74862006-05-14 05:01:31 -0300757 if (fe->ops.i2c_gate_ctrl)
758 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
Patrick Boettcherdea74862006-05-14 05:01:31 -0300760 if (fe->ops.i2c_gate_ctrl)
761 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
763 }
764
765 return 0;
766}
767
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300768static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769{
770 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
771 u8 tuner_buf[4];
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700772 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 -0700773 int tuner_frequency = 0;
774 u8 band, cp, filter;
775
776 // determine charge pump
777 tuner_frequency = params->frequency + 36130000;
778 if (tuner_frequency < 87000000)
779 return -EINVAL;
780 else if (tuner_frequency < 130000000)
781 cp = 3;
782 else if (tuner_frequency < 160000000)
783 cp = 5;
784 else if (tuner_frequency < 200000000)
785 cp = 6;
786 else if (tuner_frequency < 290000000)
787 cp = 3;
788 else if (tuner_frequency < 420000000)
789 cp = 5;
790 else if (tuner_frequency < 480000000)
791 cp = 6;
792 else if (tuner_frequency < 620000000)
793 cp = 3;
794 else if (tuner_frequency < 830000000)
795 cp = 5;
796 else if (tuner_frequency < 895000000)
797 cp = 7;
798 else
799 return -EINVAL;
800
801 // determine band
802 if (params->frequency < 49000000)
803 return -EINVAL;
804 else if (params->frequency < 159000000)
805 band = 1;
806 else if (params->frequency < 444000000)
807 band = 2;
808 else if (params->frequency < 861000000)
809 band = 4;
810 else
811 return -EINVAL;
812
813 // setup PLL filter and TDA9889
814 switch (params->u.ofdm.bandwidth) {
815 case BANDWIDTH_6_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300816 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 filter = 0;
818 break;
819
820 case BANDWIDTH_7_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300821 tda1004x_writereg(fe, 0x0C, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 filter = 0;
823 break;
824
825 case BANDWIDTH_8_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300826 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 filter = 1;
828 break;
829
830 default:
831 return -EINVAL;
832 }
833
834 // calculate divisor
835 // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
836 tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
837
838 // setup tuner buffer
839 tuner_buf[0] = tuner_frequency >> 8;
840 tuner_buf[1] = tuner_frequency & 0xff;
841 tuner_buf[2] = 0xca;
842 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
843
Patrick Boettcherdea74862006-05-14 05:01:31 -0300844 if (fe->ops.i2c_gate_ctrl)
845 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
847 return -EIO;
848
849 msleep(1);
850 return 0;
851}
852
853static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,
854 const struct firmware **fw, char *name)
855{
856 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
857
858 return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);
859}
860
861static struct tda1004x_config philips_tdm1316l_config = {
862
863 .demod_address = 0x8,
864 .invert = 0,
865 .invert_oclk = 0,
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700866 .xtal_freq = TDA10046_XTAL_4M,
867 .agc_config = TDA10046_AGC_DEFAULT,
868 .if_freq = TDA10046_FREQ_3617,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 .request_firmware = philips_tdm1316l_request_firmware,
870};
871
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300872static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700873{
874 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
875 u8 tuner_buf[5];
876 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
877 .flags = 0,
878 .buf = tuner_buf,
879 .len = sizeof(tuner_buf) };
880 int tuner_frequency = 0;
881 u8 band, cp, filter;
882
883 // determine charge pump
884 tuner_frequency = params->frequency + 36125000;
885 if (tuner_frequency < 87000000)
886 return -EINVAL;
887 else if (tuner_frequency < 130000000) {
888 cp = 3;
889 band = 1;
890 } else if (tuner_frequency < 160000000) {
891 cp = 5;
892 band = 1;
893 } else if (tuner_frequency < 200000000) {
894 cp = 6;
Thomas Kaiser9abec612006-11-22 18:15:19 -0300895 band = 2;
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700896 } else if (tuner_frequency < 290000000) {
897 cp = 3;
898 band = 2;
899 } else if (tuner_frequency < 420000000) {
900 cp = 5;
901 band = 2;
902 } else if (tuner_frequency < 480000000) {
903 cp = 6;
904 band = 2;
905 } else if (tuner_frequency < 620000000) {
906 cp = 3;
907 band = 4;
908 } else if (tuner_frequency < 830000000) {
909 cp = 5;
910 band = 4;
911 } else if (tuner_frequency < 895000000) {
912 cp = 7;
913 band = 4;
914 } else
915 return -EINVAL;
916
917 // assume PLL filter should always be 8MHz for the moment.
918 filter = 1;
919
920 // calculate divisor
921 tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
922
923 // setup tuner buffer
924 tuner_buf[0] = tuner_frequency >> 8;
925 tuner_buf[1] = tuner_frequency & 0xff;
926 tuner_buf[2] = 0xc8;
927 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
928 tuner_buf[4] = 0x80;
929
Patrick Boettcherdea74862006-05-14 05:01:31 -0300930 if (fe->ops.i2c_gate_ctrl)
931 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700932 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
933 return -EIO;
934
935 msleep(50);
936
Patrick Boettcherdea74862006-05-14 05:01:31 -0300937 if (fe->ops.i2c_gate_ctrl)
938 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700939 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
940 return -EIO;
941
942 msleep(1);
943
944 return 0;
945}
946
947static u8 dvbc_philips_tdm1316l_inittab[] = {
948 0x80, 0x01,
949 0x80, 0x00,
950 0x81, 0x01,
951 0x81, 0x00,
952 0x00, 0x09,
953 0x01, 0x69,
954 0x03, 0x00,
955 0x04, 0x00,
956 0x07, 0x00,
957 0x08, 0x00,
958 0x20, 0x00,
959 0x21, 0x40,
960 0x22, 0x00,
961 0x23, 0x00,
962 0x24, 0x40,
963 0x25, 0x88,
964 0x30, 0xff,
965 0x31, 0x00,
966 0x32, 0xff,
967 0x33, 0x00,
968 0x34, 0x50,
969 0x35, 0x7f,
970 0x36, 0x00,
971 0x37, 0x20,
972 0x38, 0x00,
973 0x40, 0x1c,
974 0x41, 0xff,
975 0x42, 0x29,
976 0x43, 0x20,
977 0x44, 0xff,
978 0x45, 0x00,
979 0x46, 0x00,
980 0x49, 0x04,
981 0x4a, 0x00,
982 0x4b, 0x7b,
983 0x52, 0x30,
984 0x55, 0xae,
985 0x56, 0x47,
986 0x57, 0xe1,
987 0x58, 0x3a,
988 0x5a, 0x1e,
989 0x5b, 0x34,
990 0x60, 0x00,
991 0x63, 0x00,
992 0x64, 0x00,
993 0x65, 0x00,
994 0x66, 0x00,
995 0x67, 0x00,
996 0x68, 0x00,
997 0x69, 0x00,
998 0x6a, 0x02,
999 0x6b, 0x00,
1000 0x70, 0xff,
1001 0x71, 0x00,
1002 0x72, 0x00,
1003 0x73, 0x00,
1004 0x74, 0x0c,
1005 0x80, 0x00,
1006 0x81, 0x00,
1007 0x82, 0x00,
1008 0x83, 0x00,
1009 0x84, 0x04,
1010 0x85, 0x80,
1011 0x86, 0x24,
1012 0x87, 0x78,
1013 0x88, 0x10,
1014 0x89, 0x00,
1015 0x90, 0x01,
1016 0x91, 0x01,
1017 0xa0, 0x04,
1018 0xa1, 0x00,
1019 0xa2, 0x00,
1020 0xb0, 0x91,
1021 0xb1, 0x0b,
1022 0xc0, 0x53,
1023 0xc1, 0x70,
1024 0xc2, 0x12,
1025 0xd0, 0x00,
1026 0xd1, 0x00,
1027 0xd2, 0x00,
1028 0xd3, 0x00,
1029 0xd4, 0x00,
1030 0xd5, 0x00,
1031 0xde, 0x00,
1032 0xdf, 0x00,
1033 0x61, 0x38,
1034 0x62, 0x0a,
1035 0x53, 0x13,
1036 0x59, 0x08,
1037 0xff, 0xff,
1038};
1039
1040static struct stv0297_config dvbc_philips_tdm1316l_config = {
1041 .demod_address = 0x1c,
1042 .inittab = dvbc_philips_tdm1316l_inittab,
1043 .invert = 0,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001044 .stop_during_read = 1,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001045};
1046
1047
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048
1049
1050static void frontend_init(struct budget_ci *budget_ci)
1051{
1052 switch (budget_ci->budget.dev->pci->subsystem_device) {
1053 case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
1054 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001055 dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001057 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001058 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 break;
1060 }
1061 break;
1062
1063 case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
1064 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001065 dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001067 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 break;
1069 }
1070 break;
1071
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001072 case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
1073 budget_ci->tuner_pll_address = 0x61;
1074 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001075 dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001076 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001077 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001078 break;
1079 }
1080 break;
1081
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001083 budget_ci->tuner_pll_address = 0x63;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001085 dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001087 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1088 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 break;
1090 }
1091 break;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001092
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001093 case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001094 budget_ci->tuner_pll_address = 0x60;
Raymond Mantchala9e741b72006-10-30 23:20:50 -03001095 philips_tdm1316l_config.invert = 1;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001096 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001097 dvb_attach(tda10046_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001098 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001099 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1100 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001101 break;
1102 }
1103 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001104
1105 case 0x1017: // TT S-1500 PCI
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001106 budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001107 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001108 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001109 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
1110
Patrick Boettcherdea74862006-05-14 05:01:31 -03001111 budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001112 if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) {
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001113 printk("%s: No LNBP21 found!\n", __FUNCTION__);
Andrew de Quincey2b100e72006-08-08 09:10:11 -03001114 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001115 budget_ci->budget.dvb_frontend = NULL;
1116 }
1117 }
1118
1119 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 }
1121
1122 if (budget_ci->budget.dvb_frontend == NULL) {
1123 printk("budget-ci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
1124 budget_ci->budget.dev->pci->vendor,
1125 budget_ci->budget.dev->pci->device,
1126 budget_ci->budget.dev->pci->subsystem_vendor,
1127 budget_ci->budget.dev->pci->subsystem_device);
1128 } else {
1129 if (dvb_register_frontend
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001130 (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 printk("budget-ci: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001132 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 budget_ci->budget.dvb_frontend = NULL;
1134 }
1135 }
1136}
1137
1138static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
1139{
1140 struct budget_ci *budget_ci;
1141 int err;
1142
David Hardemanee579bc2006-12-02 21:16:05 -02001143 budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
David Hardeman8cc532e2006-12-02 21:16:05 -02001144 if (!budget_ci) {
1145 err = -ENOMEM;
1146 goto out1;
1147 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148
1149 dprintk(2, "budget_ci: %p\n", budget_ci);
1150
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 dev->ext_priv = budget_ci;
1152
David Hardeman8cc532e2006-12-02 21:16:05 -02001153 err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE);
1154 if (err)
1155 goto out2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156
David Hardeman8cc532e2006-12-02 21:16:05 -02001157 err = msp430_ir_init(budget_ci);
1158 if (err)
1159 goto out3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160
1161 ciintf_init(budget_ci);
1162
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001163 budget_ci->budget.dvb_adapter.priv = budget_ci;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 frontend_init(budget_ci);
1165
Oliver Endriss32e4c3a2006-07-18 22:55:23 -03001166 ttpci_budget_init_hooks(&budget_ci->budget);
1167
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 return 0;
David Hardeman8cc532e2006-12-02 21:16:05 -02001169
1170out3:
1171 ttpci_budget_deinit(&budget_ci->budget);
1172out2:
1173 kfree(budget_ci);
1174out1:
1175 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176}
1177
1178static int budget_ci_detach(struct saa7146_dev *dev)
1179{
1180 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
1181 struct saa7146_dev *saa = budget_ci->budget.dev;
1182 int err;
1183
1184 if (budget_ci->budget.ci_present)
1185 ciintf_deinit(budget_ci);
David Hardeman8cc532e2006-12-02 21:16:05 -02001186 msp430_ir_deinit(budget_ci);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001187 if (budget_ci->budget.dvb_frontend) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001189 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001190 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 err = ttpci_budget_deinit(&budget_ci->budget);
1192
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 // disable frontend and CI interface
1194 saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
1195
1196 kfree(budget_ci);
1197
1198 return err;
1199}
1200
1201static struct saa7146_extension budget_extension;
1202
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001203MAKE_BUDGET_INFO(ttbs2, "TT-Budget/S-1500 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
1205MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001206MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001207MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208
1209static struct pci_device_id pci_tbl[] = {
1210 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
1211 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001212 MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001214 MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001215 MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 {
1217 .vendor = 0,
1218 }
1219};
1220
1221MODULE_DEVICE_TABLE(pci, pci_tbl);
1222
1223static struct saa7146_extension budget_extension = {
Dave Jones0e367a12006-08-07 13:18:56 -03001224 .name = "budget_ci dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03001225 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226
1227 .module = THIS_MODULE,
1228 .pci_tbl = &pci_tbl[0],
1229 .attach = budget_ci_attach,
1230 .detach = budget_ci_detach,
1231
1232 .irq_mask = MASK_03 | MASK_06 | MASK_10,
1233 .irq_func = budget_ci_irq,
1234};
1235
1236static int __init budget_ci_init(void)
1237{
1238 return saa7146_register_extension(&budget_extension);
1239}
1240
1241static void __exit budget_ci_exit(void)
1242{
1243 saa7146_unregister_extension(&budget_extension);
1244}
1245
1246module_init(budget_ci_init);
1247module_exit(budget_ci_exit);
1248
1249MODULE_LICENSE("GPL");
1250MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
1251MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1252 "budget PCI DVB cards w/ CI-module produced by "
1253 "Siemens, Technotrend, Hauppauge");