blob: ec89afd38917d8a60762660d5bcfa728e4faa874 [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
Mauro Carvalho Chehab727e6252010-03-12 21:18:14 -030057#define MODULE_NAME "budget_ci"
58
David Härdemanecba77f2006-10-27 20:56:51 -030059/*
60 * Regarding DEBIADDR_IR:
61 * Some CI modules hang if random addresses are read.
62 * Using address 0x4000 for the IR read means that we
63 * use the same address as for CI version, which should
64 * be a safe default.
65 */
66#define DEBIADDR_IR 0x4000
Linus Torvalds1da177e2005-04-16 15:20:36 -070067#define DEBIADDR_CICONTROL 0x0000
68#define DEBIADDR_CIVERSION 0x4000
69#define DEBIADDR_IO 0x1000
70#define DEBIADDR_ATTR 0x3000
71
72#define CICONTROL_RESET 0x01
73#define CICONTROL_ENABLETS 0x02
74#define CICONTROL_CAMDETECT 0x08
75
76#define DEBICICTL 0x00420000
77#define DEBICICAM 0x02420000
78
79#define SLOTSTATUS_NONE 1
80#define SLOTSTATUS_PRESENT 2
81#define SLOTSTATUS_RESET 4
82#define SLOTSTATUS_READY 8
83#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
84
David Härdeman145859c2007-04-27 12:31:22 -030085/*
86 * Milliseconds during which a key is regarded as pressed.
87 * If an identical command arrives within this time, the timer will start over.
David Hardeman2520fff2006-12-02 21:16:05 -020088 */
David Härdeman145859c2007-04-27 12:31:22 -030089#define IR_KEYPRESS_TIMEOUT 250
David Hardeman2520fff2006-12-02 21:16:05 -020090
David Hardeman64741b72006-12-02 21:16:05 -020091/* RC5 device wildcard */
92#define IR_DEVICE_ANY 255
93
David Hardeman64741b72006-12-02 21:16:05 -020094static int rc5_device = -1;
95module_param(rc5_device, int, 0644);
96MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
97
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030098static int ir_debug;
David Hardemanb5471a22006-12-02 21:16:05 -020099module_param(ir_debug, int, 0644);
100MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
101
Janne Grunau26dc4d02008-09-21 20:50:11 -0300102DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
103
David Hardemandd2f3982006-12-02 21:16:05 -0200104struct budget_ci_ir {
105 struct input_dev *dev;
106 struct tasklet_struct msp430_irq_tasklet;
David Härdeman145859c2007-04-27 12:31:22 -0300107 struct timer_list timer_keyup;
David Hardemandd2f3982006-12-02 21:16:05 -0200108 char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
David Hardeman5cc8ae02006-12-02 21:16:05 -0200109 char phys[32];
David Hardeman2520fff2006-12-02 21:16:05 -0200110 struct ir_input_state state;
David Hardeman64741b72006-12-02 21:16:05 -0200111 int rc5_device;
David Härdeman145859c2007-04-27 12:31:22 -0300112 u32 last_raw;
113 u32 ir_key;
114 bool have_command;
David Hardemandd2f3982006-12-02 21:16:05 -0200115};
116
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117struct budget_ci {
118 struct budget budget;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 struct tasklet_struct ciintf_irq_tasklet;
120 int slot_status;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300121 int ci_irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 struct dvb_ca_en50221 ca;
David Hardemandd2f3982006-12-02 21:16:05 -0200123 struct budget_ci_ir ir;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700124 u8 tuner_pll_address; /* used for philips_tdm1316l configs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125};
126
David Hardeman2520fff2006-12-02 21:16:05 -0200127static void msp430_ir_keyup(unsigned long data)
128{
129 struct budget_ci_ir *ir = (struct budget_ci_ir *) data;
130 ir_input_nokey(ir->dev, &ir->state);
131}
132
133static void msp430_ir_interrupt(unsigned long data)
134{
135 struct budget_ci *budget_ci = (struct budget_ci *) data;
136 struct input_dev *dev = budget_ci->ir.dev;
David Hardeman2520fff2006-12-02 21:16:05 -0200137 u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
David Härdeman145859c2007-04-27 12:31:22 -0300138 u32 raw;
David Hardeman2520fff2006-12-02 21:16:05 -0200139
David Hardeman64741b72006-12-02 21:16:05 -0200140 /*
141 * The msp430 chip can generate two different bytes, command and device
142 *
143 * type1: X1CCCCCC, C = command bits (0 - 63)
144 * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
145 *
David Härdeman59327a42007-02-13 09:39:58 -0300146 * Each signal from the remote control can generate one or more command
147 * bytes and one or more device bytes. For the repeated bytes, the
148 * highest bit (X) is set. The first command byte is always generated
149 * before the first device byte. Other than that, no specific order
David Härdeman145859c2007-04-27 12:31:22 -0300150 * seems to apply. To make life interesting, bytes can also be lost.
David Härdeman59327a42007-02-13 09:39:58 -0300151 *
152 * Only when we have a command and device byte, a keypress is
153 * generated.
David Hardeman64741b72006-12-02 21:16:05 -0200154 */
155
David Härdeman59327a42007-02-13 09:39:58 -0300156 if (ir_debug)
157 printk("budget_ci: received byte 0x%02x\n", command);
158
David Härdeman145859c2007-04-27 12:31:22 -0300159 /* Remove repeat bit, we use every command */
160 command = command & 0x7f;
David Härdeman59327a42007-02-13 09:39:58 -0300161
David Hardeman64741b72006-12-02 21:16:05 -0200162 /* Is this a RC5 command byte? */
David Hardeman2520fff2006-12-02 21:16:05 -0200163 if (command & 0x40) {
David Härdeman145859c2007-04-27 12:31:22 -0300164 budget_ci->ir.have_command = true;
165 budget_ci->ir.ir_key = command & 0x3f;
David Hardeman64741b72006-12-02 21:16:05 -0200166 return;
David Hardeman2520fff2006-12-02 21:16:05 -0200167 }
David Hardeman64741b72006-12-02 21:16:05 -0200168
169 /* It's a RC5 device byte */
David Härdeman145859c2007-04-27 12:31:22 -0300170 if (!budget_ci->ir.have_command)
David Härdeman59327a42007-02-13 09:39:58 -0300171 return;
David Härdeman145859c2007-04-27 12:31:22 -0300172 budget_ci->ir.have_command = false;
David Hardeman64741b72006-12-02 21:16:05 -0200173
David Härdeman145859c2007-04-27 12:31:22 -0300174 if (budget_ci->ir.rc5_device != IR_DEVICE_ANY &&
175 budget_ci->ir.rc5_device != (command & 0x1f))
David Hardeman64741b72006-12-02 21:16:05 -0200176 return;
177
David Härdeman145859c2007-04-27 12:31:22 -0300178 /* Is this a repeated key sequence? (same device, command, toggle) */
179 raw = budget_ci->ir.ir_key | (command << 8);
180 if (budget_ci->ir.last_raw != raw || !timer_pending(&budget_ci->ir.timer_keyup)) {
David Hardeman59236d42006-12-02 21:16:06 -0200181 ir_input_nokey(dev, &budget_ci->ir.state);
David Härdeman145859c2007-04-27 12:31:22 -0300182 ir_input_keydown(dev, &budget_ci->ir.state,
Mauro Carvalho Chehab8573b742009-11-27 22:40:22 -0300183 budget_ci->ir.ir_key);
David Härdeman145859c2007-04-27 12:31:22 -0300184 budget_ci->ir.last_raw = raw;
David Hardeman59236d42006-12-02 21:16:06 -0200185 }
David Härdeman145859c2007-04-27 12:31:22 -0300186
187 mod_timer(&budget_ci->ir.timer_keyup, jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT));
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;
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300195 struct ir_scancode_table *ir_codes;
196
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197
David Hardemandd2f3982006-12-02 21:16:05 -0200198 budget_ci->ir.dev = input_dev = input_allocate_device();
David Hardeman8cc532e2006-12-02 21:16:05 -0200199 if (!input_dev) {
David Hardemanee579bc2006-12-02 21:16:05 -0200200 printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300201 return -ENOMEM;
David Hardeman8cc532e2006-12-02 21:16:05 -0200202 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
David Hardemandd2f3982006-12-02 21:16:05 -0200204 snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
205 "Budget-CI dvb ir receiver %s", saa->name);
David Hardeman5cc8ae02006-12-02 21:16:05 -0200206 snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
207 "pci-%s/ir0", pci_name(saa->pci));
208
David Hardemandd2f3982006-12-02 21:16:05 -0200209 input_dev->name = budget_ci->ir.name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
David Hardeman5cc8ae02006-12-02 21:16:05 -0200211 input_dev->phys = budget_ci->ir.phys;
212 input_dev->id.bustype = BUS_PCI;
213 input_dev->id.version = 1;
214 if (saa->pci->subsystem_vendor) {
215 input_dev->id.vendor = saa->pci->subsystem_vendor;
216 input_dev->id.product = saa->pci->subsystem_device;
217 } else {
218 input_dev->id.vendor = saa->pci->vendor;
219 input_dev->id.product = saa->pci->device;
220 }
Dmitry Torokhov2c8a3a32007-07-16 09:28:15 -0300221 input_dev->dev.parent = &saa->pci->dev;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200222
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300223 if (rc5_device < 0)
224 budget_ci->ir.rc5_device = IR_DEVICE_ANY;
225 else
226 budget_ci->ir.rc5_device = rc5_device;
227
David Hardeman64741b72006-12-02 21:16:05 -0200228 /* Select keymap and address */
David Hardeman2520fff2006-12-02 21:16:05 -0200229 switch (budget_ci->budget.dev->pci->subsystem_device) {
230 case 0x100c:
231 case 0x100f:
David Hardeman2520fff2006-12-02 21:16:05 -0200232 case 0x1011:
233 case 0x1012:
David Hardeman2520fff2006-12-02 21:16:05 -0200234 /* The hauppauge keymap is a superset of these remotes */
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300235 ir_codes = &ir_codes_hauppauge_new_table;
David Hardeman64741b72006-12-02 21:16:05 -0200236
237 if (rc5_device < 0)
238 budget_ci->ir.rc5_device = 0x1f;
David Hardeman2520fff2006-12-02 21:16:05 -0200239 break;
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300240 case 0x1010:
Oliver Endrissf64899c2007-09-17 22:17:12 -0300241 case 0x1017:
Oliver Endrissbbfc4c22008-06-19 23:36:45 -0300242 case 0x101a:
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300243 /* for the Technotrend 1500 bundled remote */
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300244 ir_codes = &ir_codes_tt_1500_table;
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300245 break;
David Hardeman2520fff2006-12-02 21:16:05 -0200246 default:
247 /* unknown remote */
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300248 ir_codes = &ir_codes_budget_ci_old_table;
David Hardeman2520fff2006-12-02 21:16:05 -0200249 break;
250 }
251
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300252 ir_input_init(input_dev, &budget_ci->ir.state, IR_TYPE_RC5);
253
David Härdeman145859c2007-04-27 12:31:22 -0300254 /* initialise the key-up timeout handler */
255 init_timer(&budget_ci->ir.timer_keyup);
256 budget_ci->ir.timer_keyup.function = msp430_ir_keyup;
257 budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir;
258 budget_ci->ir.last_raw = 0xffff; /* An impossible value */
Mauro Carvalho Chehab727e6252010-03-12 21:18:14 -0300259 error = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME);
David Hardeman8cc532e2006-12-02 21:16:05 -0200260 if (error) {
261 printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300262 return error;
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300263 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
David Härdeman145859c2007-04-27 12:31:22 -0300265 /* note: these must be after input_register_device */
266 input_dev->rep[REP_DELAY] = 400;
267 input_dev->rep[REP_PERIOD] = 250;
268
David Hardeman8cc532e2006-12-02 21:16:05 -0200269 tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
270 (unsigned long) budget_ci);
271
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300272 SAA7146_IER_ENABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
274
275 return 0;
276}
277
278static void msp430_ir_deinit(struct budget_ci *budget_ci)
279{
280 struct saa7146_dev *saa = budget_ci->budget.dev;
David Hardemandd2f3982006-12-02 21:16:05 -0200281 struct input_dev *dev = budget_ci->ir.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300283 SAA7146_IER_DISABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
David Hardeman8cc532e2006-12-02 21:16:05 -0200285 tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
David Härdeman145859c2007-04-27 12:31:22 -0300287 del_timer_sync(&dev->timer);
288 ir_input_nokey(dev, &budget_ci->ir.state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
Mauro Carvalho Chehab38ef6aa2009-12-11 09:47:42 -0300290 ir_input_unregister(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291}
292
293static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
294{
295 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
296
297 if (slot != 0)
298 return -EINVAL;
299
300 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
301 DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);
302}
303
304static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
305{
306 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
307
308 if (slot != 0)
309 return -EINVAL;
310
311 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
312 DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);
313}
314
315static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
316{
317 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
318
319 if (slot != 0)
320 return -EINVAL;
321
322 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
323 DEBIADDR_IO | (address & 3), 1, 1, 0);
324}
325
326static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
327{
328 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
329
330 if (slot != 0)
331 return -EINVAL;
332
333 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
334 DEBIADDR_IO | (address & 3), 1, value, 1, 0);
335}
336
337static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
338{
339 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
340 struct saa7146_dev *saa = budget_ci->budget.dev;
341
342 if (slot != 0)
343 return -EINVAL;
344
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300345 if (budget_ci->ci_irq) {
346 // trigger on RISING edge during reset so we know when READY is re-asserted
347 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
348 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 budget_ci->slot_status = SLOTSTATUS_RESET;
350 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
351 msleep(1);
352 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
353 CICONTROL_RESET, 1, 0);
354
355 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
356 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
357 return 0;
358}
359
360static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
361{
362 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
363 struct saa7146_dev *saa = budget_ci->budget.dev;
364
365 if (slot != 0)
366 return -EINVAL;
367
368 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
369 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
370 return 0;
371}
372
373static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
374{
375 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
376 struct saa7146_dev *saa = budget_ci->budget.dev;
377 int tmp;
378
379 if (slot != 0)
380 return -EINVAL;
381
382 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
383
384 tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
385 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
386 tmp | CICONTROL_ENABLETS, 1, 0);
387
388 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
389 return 0;
390}
391
392static void ciintf_interrupt(unsigned long data)
393{
394 struct budget_ci *budget_ci = (struct budget_ci *) data;
395 struct saa7146_dev *saa = budget_ci->budget.dev;
396 unsigned int flags;
397
398 // ensure we don't get spurious IRQs during initialisation
399 if (!budget_ci->budget.ci_present)
400 return;
401
402 // read the CAM status
403 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
404 if (flags & CICONTROL_CAMDETECT) {
405
406 // GPIO should be set to trigger on falling edge if a CAM is present
407 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
408
409 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
410 // CAM insertion IRQ
411 budget_ci->slot_status = SLOTSTATUS_PRESENT;
412 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
413 DVB_CA_EN50221_CAMCHANGE_INSERTED);
414
415 } else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
416 // CAM ready (reset completed)
417 budget_ci->slot_status = SLOTSTATUS_READY;
418 dvb_ca_en50221_camready_irq(&budget_ci->ca, 0);
419
420 } else if (budget_ci->slot_status & SLOTSTATUS_READY) {
421 // FR/DA IRQ
422 dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);
423 }
424 } else {
425
426 // trigger on rising edge if a CAM is not present - when a CAM is inserted, we
427 // only want to get the IRQ when it sets READY. If we trigger on the falling edge,
428 // the CAM might not actually be ready yet.
429 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
430
431 // generate a CAM removal IRQ if we haven't already
432 if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
433 // CAM removal IRQ
434 budget_ci->slot_status = SLOTSTATUS_NONE;
435 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
436 DVB_CA_EN50221_CAMCHANGE_REMOVED);
437 }
438 }
439}
440
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300441static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
442{
443 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
444 unsigned int flags;
445
446 // ensure we don't get spurious IRQs during initialisation
447 if (!budget_ci->budget.ci_present)
448 return -EINVAL;
449
450 // read the CAM status
451 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
452 if (flags & CICONTROL_CAMDETECT) {
453 // mark it as present if it wasn't before
454 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
455 budget_ci->slot_status = SLOTSTATUS_PRESENT;
456 }
457
458 // during a RESET, we check if we can read from IO memory to see when CAM is ready
459 if (budget_ci->slot_status & SLOTSTATUS_RESET) {
460 if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
461 budget_ci->slot_status = SLOTSTATUS_READY;
462 }
463 }
464 } else {
465 budget_ci->slot_status = SLOTSTATUS_NONE;
466 }
467
468 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
469 if (budget_ci->slot_status & SLOTSTATUS_READY) {
470 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
471 }
472 return DVB_CA_EN50221_POLL_CAM_PRESENT;
473 }
474
475 return 0;
476}
477
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478static int ciintf_init(struct budget_ci *budget_ci)
479{
480 struct saa7146_dev *saa = budget_ci->budget.dev;
481 int flags;
482 int result;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300483 int ci_version;
484 int ca_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
486 memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
487
488 // enable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300489 saa7146_write(saa, MC1, MASK_27 | MASK_11);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490
491 // test if it is there
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300492 ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
493 if ((ci_version & 0xa0) != 0xa0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 result = -ENODEV;
495 goto error;
496 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300497
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 // determine whether a CAM is present or not
499 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
500 budget_ci->slot_status = SLOTSTATUS_NONE;
501 if (flags & CICONTROL_CAMDETECT)
502 budget_ci->slot_status = SLOTSTATUS_PRESENT;
503
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300504 // version 0xa2 of the CI firmware doesn't generate interrupts
505 if (ci_version == 0xa2) {
506 ca_flags = 0;
507 budget_ci->ci_irq = 0;
508 } else {
509 ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
510 DVB_CA_EN50221_FLAG_IRQ_FR |
511 DVB_CA_EN50221_FLAG_IRQ_DA;
512 budget_ci->ci_irq = 1;
513 }
514
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 // register CI interface
516 budget_ci->ca.owner = THIS_MODULE;
517 budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
518 budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
519 budget_ci->ca.read_cam_control = ciintf_read_cam_control;
520 budget_ci->ca.write_cam_control = ciintf_write_cam_control;
521 budget_ci->ca.slot_reset = ciintf_slot_reset;
522 budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
523 budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300524 budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 budget_ci->ca.data = budget_ci;
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700526 if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 &budget_ci->ca,
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300528 ca_flags, 1)) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 printk("budget_ci: CI interface detected, but initialisation failed.\n");
530 goto error;
531 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300532
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 // Setup CI slot IRQ
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300534 if (budget_ci->ci_irq) {
535 tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
536 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
537 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
538 } else {
539 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
540 }
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300541 SAA7146_IER_ENABLE(saa, MASK_03);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300543
544 // enable interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
546 CICONTROL_RESET, 1, 0);
547
548 // success!
549 printk("budget_ci: CI interface initialised\n");
550 budget_ci->budget.ci_present = 1;
551
552 // forge a fake CI IRQ so the CAM state is setup correctly
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300553 if (budget_ci->ci_irq) {
554 flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
555 if (budget_ci->slot_status != SLOTSTATUS_NONE)
556 flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
557 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
558 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
560 return 0;
561
562error:
Hartmut Birr2a893de2006-12-03 21:08:08 -0300563 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 return result;
565}
566
567static void ciintf_deinit(struct budget_ci *budget_ci)
568{
569 struct saa7146_dev *saa = budget_ci->budget.dev;
570
571 // disable CI interrupts
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300572 if (budget_ci->ci_irq) {
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300573 SAA7146_IER_DISABLE(saa, MASK_03);
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300574 saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
575 tasklet_kill(&budget_ci->ciintf_irq_tasklet);
576 }
577
578 // reset interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
580 msleep(1);
581 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
582 CICONTROL_RESET, 1, 0);
583
584 // disable TS data stream to CI interface
585 saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
586
587 // release the CA device
588 dvb_ca_en50221_release(&budget_ci->ca);
589
590 // disable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300591 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592}
593
594static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
595{
596 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
597
598 dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
599
600 if (*isr & MASK_06)
David Hardemandd2f3982006-12-02 21:16:05 -0200601 tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602
603 if (*isr & MASK_10)
604 ttpci_budget_irq10_handler(dev, isr);
605
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300606 if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
608}
609
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610static u8 philips_su1278_tt_inittab[] = {
611 0x01, 0x0f,
612 0x02, 0x30,
613 0x03, 0x00,
614 0x04, 0x5b,
615 0x05, 0x85,
616 0x06, 0x02,
617 0x07, 0x00,
618 0x08, 0x02,
619 0x09, 0x00,
620 0x0C, 0x01,
621 0x0D, 0x81,
622 0x0E, 0x44,
623 0x0f, 0x14,
624 0x10, 0x3c,
625 0x11, 0x84,
626 0x12, 0xda,
627 0x13, 0x97,
628 0x14, 0x95,
629 0x15, 0xc9,
630 0x16, 0x19,
631 0x17, 0x8c,
632 0x18, 0x59,
633 0x19, 0xf8,
634 0x1a, 0xfe,
635 0x1c, 0x7f,
636 0x1d, 0x00,
637 0x1e, 0x00,
638 0x1f, 0x50,
639 0x20, 0x00,
640 0x21, 0x00,
641 0x22, 0x00,
642 0x23, 0x00,
643 0x28, 0x00,
644 0x29, 0x28,
645 0x2a, 0x14,
646 0x2b, 0x0f,
647 0x2c, 0x09,
648 0x2d, 0x09,
649 0x31, 0x1f,
650 0x32, 0x19,
651 0x33, 0xfc,
652 0x34, 0x93,
653 0xff, 0xff
654};
655
656static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
657{
658 stv0299_writereg(fe, 0x0e, 0x44);
659 if (srate >= 10000000) {
660 stv0299_writereg(fe, 0x13, 0x97);
661 stv0299_writereg(fe, 0x14, 0x95);
662 stv0299_writereg(fe, 0x15, 0xc9);
663 stv0299_writereg(fe, 0x17, 0x8c);
664 stv0299_writereg(fe, 0x1a, 0xfe);
665 stv0299_writereg(fe, 0x1c, 0x7f);
666 stv0299_writereg(fe, 0x2d, 0x09);
667 } else {
668 stv0299_writereg(fe, 0x13, 0x99);
669 stv0299_writereg(fe, 0x14, 0x8d);
670 stv0299_writereg(fe, 0x15, 0xce);
671 stv0299_writereg(fe, 0x17, 0x43);
672 stv0299_writereg(fe, 0x1a, 0x1d);
673 stv0299_writereg(fe, 0x1c, 0x12);
674 stv0299_writereg(fe, 0x2d, 0x05);
675 }
676 stv0299_writereg(fe, 0x0e, 0x23);
677 stv0299_writereg(fe, 0x0f, 0x94);
678 stv0299_writereg(fe, 0x10, 0x39);
679 stv0299_writereg(fe, 0x15, 0xc9);
680
681 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
682 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
683 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
684
685 return 0;
686}
687
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300688static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,
689 struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690{
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300691 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 u32 div;
693 u8 buf[4];
694 struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
695
696 if ((params->frequency < 950000) || (params->frequency > 2150000))
697 return -EINVAL;
698
699 div = (params->frequency + (500 - 1)) / 500; // round correctly
700 buf[0] = (div >> 8) & 0x7f;
701 buf[1] = div & 0xff;
702 buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
703 buf[3] = 0x20;
704
705 if (params->u.qpsk.symbol_rate < 4000000)
706 buf[3] |= 1;
707
708 if (params->frequency < 1250000)
709 buf[3] |= 0;
710 else if (params->frequency < 1550000)
711 buf[3] |= 0x40;
712 else if (params->frequency < 2050000)
713 buf[3] |= 0x80;
714 else if (params->frequency < 2150000)
715 buf[3] |= 0xC0;
716
Patrick Boettcherdea74862006-05-14 05:01:31 -0300717 if (fe->ops.i2c_gate_ctrl)
718 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300719 if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 return -EIO;
721 return 0;
722}
723
724static struct stv0299_config philips_su1278_tt_config = {
725
726 .demod_address = 0x68,
727 .inittab = philips_su1278_tt_inittab,
728 .mclk = 64000000UL,
729 .invert = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 .skip_reinit = 1,
Oliver Endrissda2c7f62008-04-20 22:13:37 -0300731 .lock_output = STV0299_LOCKOUTPUT_1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 .volt13_op0_op1 = STV0299_VOLT13_OP1,
733 .min_delay_ms = 50,
734 .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735};
736
737
738
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300739static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740{
741 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
742 static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
743 static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700744 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 sizeof(td1316_init) };
746
747 // setup PLL configuration
Patrick Boettcherdea74862006-05-14 05:01:31 -0300748 if (fe->ops.i2c_gate_ctrl)
749 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
751 return -EIO;
752 msleep(1);
753
754 // disable the mc44BC374c (do not check for errors)
755 tuner_msg.addr = 0x65;
756 tuner_msg.buf = disable_mc44BC374c;
757 tuner_msg.len = sizeof(disable_mc44BC374c);
Patrick Boettcherdea74862006-05-14 05:01:31 -0300758 if (fe->ops.i2c_gate_ctrl)
759 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
Patrick Boettcherdea74862006-05-14 05:01:31 -0300761 if (fe->ops.i2c_gate_ctrl)
762 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
764 }
765
766 return 0;
767}
768
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300769static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770{
771 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
772 u8 tuner_buf[4];
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700773 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 -0700774 int tuner_frequency = 0;
775 u8 band, cp, filter;
776
777 // determine charge pump
778 tuner_frequency = params->frequency + 36130000;
779 if (tuner_frequency < 87000000)
780 return -EINVAL;
781 else if (tuner_frequency < 130000000)
782 cp = 3;
783 else if (tuner_frequency < 160000000)
784 cp = 5;
785 else if (tuner_frequency < 200000000)
786 cp = 6;
787 else if (tuner_frequency < 290000000)
788 cp = 3;
789 else if (tuner_frequency < 420000000)
790 cp = 5;
791 else if (tuner_frequency < 480000000)
792 cp = 6;
793 else if (tuner_frequency < 620000000)
794 cp = 3;
795 else if (tuner_frequency < 830000000)
796 cp = 5;
797 else if (tuner_frequency < 895000000)
798 cp = 7;
799 else
800 return -EINVAL;
801
802 // determine band
803 if (params->frequency < 49000000)
804 return -EINVAL;
805 else if (params->frequency < 159000000)
806 band = 1;
807 else if (params->frequency < 444000000)
808 band = 2;
809 else if (params->frequency < 861000000)
810 band = 4;
811 else
812 return -EINVAL;
813
814 // setup PLL filter and TDA9889
815 switch (params->u.ofdm.bandwidth) {
816 case BANDWIDTH_6_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300817 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 filter = 0;
819 break;
820
821 case BANDWIDTH_7_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300822 tda1004x_writereg(fe, 0x0C, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 filter = 0;
824 break;
825
826 case BANDWIDTH_8_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300827 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 filter = 1;
829 break;
830
831 default:
832 return -EINVAL;
833 }
834
835 // calculate divisor
836 // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
837 tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
838
839 // setup tuner buffer
840 tuner_buf[0] = tuner_frequency >> 8;
841 tuner_buf[1] = tuner_frequency & 0xff;
842 tuner_buf[2] = 0xca;
843 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
844
Patrick Boettcherdea74862006-05-14 05:01:31 -0300845 if (fe->ops.i2c_gate_ctrl)
846 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
848 return -EIO;
849
850 msleep(1);
851 return 0;
852}
853
854static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,
855 const struct firmware **fw, char *name)
856{
857 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
858
859 return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);
860}
861
862static struct tda1004x_config philips_tdm1316l_config = {
863
864 .demod_address = 0x8,
865 .invert = 0,
866 .invert_oclk = 0,
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700867 .xtal_freq = TDA10046_XTAL_4M,
868 .agc_config = TDA10046_AGC_DEFAULT,
869 .if_freq = TDA10046_FREQ_3617,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 .request_firmware = philips_tdm1316l_request_firmware,
871};
872
Oliver Endriss6c914492007-02-02 19:12:53 -0300873static struct tda1004x_config philips_tdm1316l_config_invert = {
874
875 .demod_address = 0x8,
876 .invert = 1,
877 .invert_oclk = 0,
878 .xtal_freq = TDA10046_XTAL_4M,
879 .agc_config = TDA10046_AGC_DEFAULT,
880 .if_freq = TDA10046_FREQ_3617,
881 .request_firmware = philips_tdm1316l_request_firmware,
882};
883
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300884static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700885{
886 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
887 u8 tuner_buf[5];
888 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
889 .flags = 0,
890 .buf = tuner_buf,
891 .len = sizeof(tuner_buf) };
892 int tuner_frequency = 0;
893 u8 band, cp, filter;
894
895 // determine charge pump
896 tuner_frequency = params->frequency + 36125000;
897 if (tuner_frequency < 87000000)
898 return -EINVAL;
899 else if (tuner_frequency < 130000000) {
900 cp = 3;
901 band = 1;
902 } else if (tuner_frequency < 160000000) {
903 cp = 5;
904 band = 1;
905 } else if (tuner_frequency < 200000000) {
906 cp = 6;
Oliver Endriss910a7b62007-05-03 13:16:12 -0300907 band = 1;
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700908 } else if (tuner_frequency < 290000000) {
909 cp = 3;
910 band = 2;
911 } else if (tuner_frequency < 420000000) {
912 cp = 5;
913 band = 2;
914 } else if (tuner_frequency < 480000000) {
915 cp = 6;
916 band = 2;
917 } else if (tuner_frequency < 620000000) {
918 cp = 3;
919 band = 4;
920 } else if (tuner_frequency < 830000000) {
921 cp = 5;
922 band = 4;
923 } else if (tuner_frequency < 895000000) {
924 cp = 7;
925 band = 4;
926 } else
927 return -EINVAL;
928
929 // assume PLL filter should always be 8MHz for the moment.
930 filter = 1;
931
932 // calculate divisor
933 tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
934
935 // setup tuner buffer
936 tuner_buf[0] = tuner_frequency >> 8;
937 tuner_buf[1] = tuner_frequency & 0xff;
938 tuner_buf[2] = 0xc8;
939 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
940 tuner_buf[4] = 0x80;
941
Patrick Boettcherdea74862006-05-14 05:01:31 -0300942 if (fe->ops.i2c_gate_ctrl)
943 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700944 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
945 return -EIO;
946
947 msleep(50);
948
Patrick Boettcherdea74862006-05-14 05:01:31 -0300949 if (fe->ops.i2c_gate_ctrl)
950 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700951 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
952 return -EIO;
953
954 msleep(1);
955
956 return 0;
957}
958
959static u8 dvbc_philips_tdm1316l_inittab[] = {
960 0x80, 0x01,
961 0x80, 0x00,
962 0x81, 0x01,
963 0x81, 0x00,
964 0x00, 0x09,
965 0x01, 0x69,
966 0x03, 0x00,
967 0x04, 0x00,
968 0x07, 0x00,
969 0x08, 0x00,
970 0x20, 0x00,
971 0x21, 0x40,
972 0x22, 0x00,
973 0x23, 0x00,
974 0x24, 0x40,
975 0x25, 0x88,
976 0x30, 0xff,
977 0x31, 0x00,
978 0x32, 0xff,
979 0x33, 0x00,
980 0x34, 0x50,
981 0x35, 0x7f,
982 0x36, 0x00,
983 0x37, 0x20,
984 0x38, 0x00,
985 0x40, 0x1c,
986 0x41, 0xff,
987 0x42, 0x29,
988 0x43, 0x20,
989 0x44, 0xff,
990 0x45, 0x00,
991 0x46, 0x00,
992 0x49, 0x04,
993 0x4a, 0x00,
994 0x4b, 0x7b,
995 0x52, 0x30,
996 0x55, 0xae,
997 0x56, 0x47,
998 0x57, 0xe1,
999 0x58, 0x3a,
1000 0x5a, 0x1e,
1001 0x5b, 0x34,
1002 0x60, 0x00,
1003 0x63, 0x00,
1004 0x64, 0x00,
1005 0x65, 0x00,
1006 0x66, 0x00,
1007 0x67, 0x00,
1008 0x68, 0x00,
1009 0x69, 0x00,
1010 0x6a, 0x02,
1011 0x6b, 0x00,
1012 0x70, 0xff,
1013 0x71, 0x00,
1014 0x72, 0x00,
1015 0x73, 0x00,
1016 0x74, 0x0c,
1017 0x80, 0x00,
1018 0x81, 0x00,
1019 0x82, 0x00,
1020 0x83, 0x00,
1021 0x84, 0x04,
1022 0x85, 0x80,
1023 0x86, 0x24,
1024 0x87, 0x78,
1025 0x88, 0x10,
1026 0x89, 0x00,
1027 0x90, 0x01,
1028 0x91, 0x01,
1029 0xa0, 0x04,
1030 0xa1, 0x00,
1031 0xa2, 0x00,
1032 0xb0, 0x91,
1033 0xb1, 0x0b,
1034 0xc0, 0x53,
1035 0xc1, 0x70,
1036 0xc2, 0x12,
1037 0xd0, 0x00,
1038 0xd1, 0x00,
1039 0xd2, 0x00,
1040 0xd3, 0x00,
1041 0xd4, 0x00,
1042 0xd5, 0x00,
1043 0xde, 0x00,
1044 0xdf, 0x00,
1045 0x61, 0x38,
1046 0x62, 0x0a,
1047 0x53, 0x13,
1048 0x59, 0x08,
1049 0xff, 0xff,
1050};
1051
1052static struct stv0297_config dvbc_philips_tdm1316l_config = {
1053 .demod_address = 0x1c,
1054 .inittab = dvbc_philips_tdm1316l_inittab,
1055 .invert = 0,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001056 .stop_during_read = 1,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001057};
1058
Sigmund Augdal11417da2008-06-15 17:25:46 -03001059static struct tda10023_config tda10023_config = {
1060 .demod_address = 0xc,
1061 .invert = 0,
1062 .xtal = 16000000,
1063 .pll_m = 11,
1064 .pll_p = 3,
1065 .pll_n = 1,
1066 .deltaf = 0xa511,
1067};
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001068
klaas de waalcf47d872009-03-25 17:53:02 -03001069static struct tda827x_config tda827x_config = {
1070 .config = 0,
1071};
1072
Manu Abrahama55bc842008-10-23 18:32:50 -03001073/* TT S2-3200 DVB-S (STB0899) Inittab */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001074static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001076 { STB0899_DEV_ID , 0x81 },
1077 { STB0899_DISCNTRL1 , 0x32 },
1078 { STB0899_DISCNTRL2 , 0x80 },
1079 { STB0899_DISRX_ST0 , 0x04 },
1080 { STB0899_DISRX_ST1 , 0x00 },
1081 { STB0899_DISPARITY , 0x00 },
1082 { STB0899_DISFIFO , 0x00 },
1083 { STB0899_DISSTATUS , 0x20 },
1084 { STB0899_DISF22 , 0x8c },
1085 { STB0899_DISF22RX , 0x9a },
Manu Abrahamef3052b2008-10-23 18:45:17 -03001086 { STB0899_SYSREG , 0x0b },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001087 { STB0899_ACRPRESC , 0x11 },
1088 { STB0899_ACRDIV1 , 0x0a },
1089 { STB0899_ACRDIV2 , 0x05 },
1090 { STB0899_DACR1 , 0x00 },
1091 { STB0899_DACR2 , 0x00 },
1092 { STB0899_OUTCFG , 0x00 },
1093 { STB0899_MODECFG , 0x00 },
1094 { STB0899_IRQSTATUS_3 , 0x30 },
1095 { STB0899_IRQSTATUS_2 , 0x00 },
1096 { STB0899_IRQSTATUS_1 , 0x00 },
1097 { STB0899_IRQSTATUS_0 , 0x00 },
1098 { STB0899_IRQMSK_3 , 0xf3 },
1099 { STB0899_IRQMSK_2 , 0xfc },
1100 { STB0899_IRQMSK_1 , 0xff },
1101 { STB0899_IRQMSK_0 , 0xff },
1102 { STB0899_IRQCFG , 0x00 },
1103 { STB0899_I2CCFG , 0x88 },
Manu Abraham40e8ce32008-02-03 19:37:02 -03001104 { STB0899_I2CRPT , 0x48 }, /* 12k Pullup, Repeater=16, Stop=disabled */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001105 { STB0899_IOPVALUE5 , 0x00 },
1106 { STB0899_IOPVALUE4 , 0x20 },
1107 { STB0899_IOPVALUE3 , 0xc9 },
1108 { STB0899_IOPVALUE2 , 0x90 },
1109 { STB0899_IOPVALUE1 , 0x40 },
1110 { STB0899_IOPVALUE0 , 0x00 },
1111 { STB0899_GPIO00CFG , 0x82 },
1112 { STB0899_GPIO01CFG , 0x82 },
1113 { STB0899_GPIO02CFG , 0x82 },
1114 { STB0899_GPIO03CFG , 0x82 },
1115 { STB0899_GPIO04CFG , 0x82 },
1116 { STB0899_GPIO05CFG , 0x82 },
1117 { STB0899_GPIO06CFG , 0x82 },
1118 { STB0899_GPIO07CFG , 0x82 },
1119 { STB0899_GPIO08CFG , 0x82 },
1120 { STB0899_GPIO09CFG , 0x82 },
1121 { STB0899_GPIO10CFG , 0x82 },
1122 { STB0899_GPIO11CFG , 0x82 },
1123 { STB0899_GPIO12CFG , 0x82 },
1124 { STB0899_GPIO13CFG , 0x82 },
1125 { STB0899_GPIO14CFG , 0x82 },
1126 { STB0899_GPIO15CFG , 0x82 },
1127 { STB0899_GPIO16CFG , 0x82 },
1128 { STB0899_GPIO17CFG , 0x82 },
1129 { STB0899_GPIO18CFG , 0x82 },
1130 { STB0899_GPIO19CFG , 0x82 },
1131 { STB0899_GPIO20CFG , 0x82 },
1132 { STB0899_SDATCFG , 0xb8 },
1133 { STB0899_SCLTCFG , 0xba },
Manu Abrahama55bc842008-10-23 18:32:50 -03001134 { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */
1135 { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */
1136 { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001137 { STB0899_DIRCLKCFG , 0x82 },
1138 { STB0899_CLKOUT27CFG , 0x7e },
1139 { STB0899_STDBYCFG , 0x82 },
1140 { STB0899_CS0CFG , 0x82 },
1141 { STB0899_CS1CFG , 0x82 },
1142 { STB0899_DISEQCOCFG , 0x20 },
1143 { STB0899_GPIO32CFG , 0x82 },
1144 { STB0899_GPIO33CFG , 0x82 },
1145 { STB0899_GPIO34CFG , 0x82 },
1146 { STB0899_GPIO35CFG , 0x82 },
1147 { STB0899_GPIO36CFG , 0x82 },
1148 { STB0899_GPIO37CFG , 0x82 },
1149 { STB0899_GPIO38CFG , 0x82 },
1150 { STB0899_GPIO39CFG , 0x82 },
Manu Abrahamf2e52cd2007-11-19 16:44:47 -03001151 { STB0899_NCOARSE , 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
Manu Abrahama55bc842008-10-23 18:32:50 -03001152 { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001153 { STB0899_FILTCTRL , 0x00 },
1154 { STB0899_SYSCTRL , 0x00 },
1155 { STB0899_STOPCLK1 , 0x20 },
1156 { STB0899_STOPCLK2 , 0x00 },
1157 { STB0899_INTBUFSTATUS , 0x00 },
1158 { STB0899_INTBUFCTRL , 0x0a },
1159 { 0xffff , 0xff },
1160};
1161
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001162static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = {
1163 { STB0899_DEMOD , 0x00 },
1164 { STB0899_RCOMPC , 0xc9 },
1165 { STB0899_AGC1CN , 0x41 },
1166 { STB0899_AGC1REF , 0x10 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001167 { STB0899_RTC , 0x7a },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001168 { STB0899_TMGCFG , 0x4e },
1169 { STB0899_AGC2REF , 0x34 },
1170 { STB0899_TLSR , 0x84 },
1171 { STB0899_CFD , 0xc7 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001172 { STB0899_ACLC , 0x87 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001173 { STB0899_BCLC , 0x94 },
1174 { STB0899_EQON , 0x41 },
1175 { STB0899_LDT , 0xdd },
1176 { STB0899_LDT2 , 0xc9 },
1177 { STB0899_EQUALREF , 0xb4 },
1178 { STB0899_TMGRAMP , 0x10 },
1179 { STB0899_TMGTHD , 0x30 },
1180 { STB0899_IDCCOMP , 0xfb },
1181 { STB0899_QDCCOMP , 0x03 },
1182 { STB0899_POWERI , 0x3b },
1183 { STB0899_POWERQ , 0x3d },
1184 { STB0899_RCOMP , 0x81 },
1185 { STB0899_AGCIQIN , 0x80 },
1186 { STB0899_AGC2I1 , 0x04 },
1187 { STB0899_AGC2I2 , 0xf5 },
1188 { STB0899_TLIR , 0x25 },
1189 { STB0899_RTF , 0x80 },
1190 { STB0899_DSTATUS , 0x00 },
1191 { STB0899_LDI , 0xca },
1192 { STB0899_CFRM , 0xf1 },
1193 { STB0899_CFRL , 0xf3 },
1194 { STB0899_NIRM , 0x2a },
1195 { STB0899_NIRL , 0x05 },
1196 { STB0899_ISYMB , 0x17 },
1197 { STB0899_QSYMB , 0xfa },
1198 { STB0899_SFRH , 0x2f },
1199 { STB0899_SFRM , 0x68 },
1200 { STB0899_SFRL , 0x40 },
1201 { STB0899_SFRUPH , 0x2f },
1202 { STB0899_SFRUPM , 0x68 },
1203 { STB0899_SFRUPL , 0x40 },
1204 { STB0899_EQUAI1 , 0xfd },
1205 { STB0899_EQUAQ1 , 0x04 },
1206 { STB0899_EQUAI2 , 0x0f },
1207 { STB0899_EQUAQ2 , 0xff },
1208 { STB0899_EQUAI3 , 0xdf },
1209 { STB0899_EQUAQ3 , 0xfa },
1210 { STB0899_EQUAI4 , 0x37 },
1211 { STB0899_EQUAQ4 , 0x0d },
1212 { STB0899_EQUAI5 , 0xbd },
1213 { STB0899_EQUAQ5 , 0xf7 },
1214 { STB0899_DSTATUS2 , 0x00 },
1215 { STB0899_VSTATUS , 0x00 },
1216 { STB0899_VERROR , 0xff },
1217 { STB0899_IQSWAP , 0x2a },
1218 { STB0899_ECNT1M , 0x00 },
1219 { STB0899_ECNT1L , 0x00 },
1220 { STB0899_ECNT2M , 0x00 },
1221 { STB0899_ECNT2L , 0x00 },
1222 { STB0899_ECNT3M , 0x00 },
1223 { STB0899_ECNT3L , 0x00 },
1224 { STB0899_FECAUTO1 , 0x06 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001225 { STB0899_FECM , 0x01 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001226 { STB0899_VTH12 , 0xf0 },
1227 { STB0899_VTH23 , 0xa0 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001228 { STB0899_VTH34 , 0x78 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001229 { STB0899_VTH56 , 0x4e },
1230 { STB0899_VTH67 , 0x48 },
1231 { STB0899_VTH78 , 0x38 },
1232 { STB0899_PRVIT , 0xff },
1233 { STB0899_VITSYNC , 0x19 },
Manu Abrahama55bc842008-10-23 18:32:50 -03001234 { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001235 { STB0899_TSULC , 0x42 },
1236 { STB0899_RSLLC , 0x40 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001237 { STB0899_TSLPL , 0x12 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001238 { STB0899_TSCFGH , 0x0c },
1239 { STB0899_TSCFGM , 0x00 },
1240 { STB0899_TSCFGL , 0x0c },
Manu Abrahamc1426df2009-11-13 18:51:39 -03001241 { STB0899_TSOUT , 0x4d }, /* 0x0d for CAM */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001242 { STB0899_RSSYNCDEL , 0x00 },
1243 { STB0899_TSINHDELH , 0x02 },
1244 { STB0899_TSINHDELM , 0x00 },
1245 { STB0899_TSINHDELL , 0x00 },
1246 { STB0899_TSLLSTKM , 0x00 },
1247 { STB0899_TSLLSTKL , 0x00 },
1248 { STB0899_TSULSTKM , 0x00 },
1249 { STB0899_TSULSTKL , 0xab },
1250 { STB0899_PCKLENUL , 0x00 },
1251 { STB0899_PCKLENLL , 0xcc },
1252 { STB0899_RSPCKLEN , 0xcc },
1253 { STB0899_TSSTATUS , 0x80 },
1254 { STB0899_ERRCTRL1 , 0xb6 },
1255 { STB0899_ERRCTRL2 , 0x96 },
1256 { STB0899_ERRCTRL3 , 0x89 },
1257 { STB0899_DMONMSK1 , 0x27 },
1258 { STB0899_DMONMSK0 , 0x03 },
1259 { STB0899_DEMAPVIT , 0x5c },
1260 { STB0899_PLPARM , 0x1f },
1261 { STB0899_PDELCTRL , 0x48 },
1262 { STB0899_PDELCTRL2 , 0x00 },
1263 { STB0899_BBHCTRL1 , 0x00 },
1264 { STB0899_BBHCTRL2 , 0x00 },
1265 { STB0899_HYSTTHRESH , 0x77 },
1266 { STB0899_MATCSTM , 0x00 },
1267 { STB0899_MATCSTL , 0x00 },
1268 { STB0899_UPLCSTM , 0x00 },
1269 { STB0899_UPLCSTL , 0x00 },
1270 { STB0899_DFLCSTM , 0x00 },
1271 { STB0899_DFLCSTL , 0x00 },
1272 { STB0899_SYNCCST , 0x00 },
1273 { STB0899_SYNCDCSTM , 0x00 },
1274 { STB0899_SYNCDCSTL , 0x00 },
1275 { STB0899_ISI_ENTRY , 0x00 },
1276 { STB0899_ISI_BIT_EN , 0x00 },
1277 { STB0899_MATSTRM , 0x00 },
1278 { STB0899_MATSTRL , 0x00 },
1279 { STB0899_UPLSTRM , 0x00 },
1280 { STB0899_UPLSTRL , 0x00 },
1281 { STB0899_DFLSTRM , 0x00 },
1282 { STB0899_DFLSTRL , 0x00 },
1283 { STB0899_SYNCSTR , 0x00 },
1284 { STB0899_SYNCDSTRM , 0x00 },
1285 { STB0899_SYNCDSTRL , 0x00 },
1286 { STB0899_CFGPDELSTATUS1 , 0x10 },
1287 { STB0899_CFGPDELSTATUS2 , 0x00 },
1288 { STB0899_BBFERRORM , 0x00 },
1289 { STB0899_BBFERRORL , 0x00 },
1290 { STB0899_UPKTERRORM , 0x00 },
1291 { STB0899_UPKTERRORL , 0x00 },
1292 { 0xffff , 0xff },
1293};
1294
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001295static struct stb0899_config tt3200_config = {
1296 .init_dev = tt3200_stb0899_s1_init_1,
Manu Abraham8be969b2008-01-25 18:20:48 -03001297 .init_s2_demod = stb0899_s2_init_2,
Manu Abrahama55bc842008-10-23 18:32:50 -03001298 .init_s1_demod = tt3200_stb0899_s1_init_3,
Manu Abraham8be969b2008-01-25 18:20:48 -03001299 .init_s2_fec = stb0899_s2_init_4,
1300 .init_tst = stb0899_s1_init_5,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001301
Manu Abraham043a68b2008-01-18 14:15:17 -03001302 .postproc = NULL,
1303
Manu Abrahama55bc842008-10-23 18:32:50 -03001304 .demod_address = 0x68,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001305
1306 .xtal_freq = 27000000,
Manu Abrahame99d00c2007-09-25 17:48:59 -03001307 .inversion = IQ_SWAP_ON, /* 1 */
Manu Abrahama55bc842008-10-23 18:32:50 -03001308
Manu Abrahamb91a7cb2008-03-04 19:19:58 -03001309 .lo_clk = 76500000,
1310 .hi_clk = 99000000,
1311
Manu Abraham8be969b2008-01-25 18:20:48 -03001312 .esno_ave = STB0899_DVBS2_ESNO_AVE,
1313 .esno_quant = STB0899_DVBS2_ESNO_QUANT,
1314 .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
1315 .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
1316 .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
1317 .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
1318 .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
1319 .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
1320 .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
Manu Abrahama55bc842008-10-23 18:32:50 -03001321
Manu Abraham8be969b2008-01-25 18:20:48 -03001322 .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
1323 .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
1324 .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
1325 .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
Manu Abrahama55bc842008-10-23 18:32:50 -03001326
1327 .tuner_get_frequency = stb6100_get_frequency,
1328 .tuner_set_frequency = stb6100_set_frequency,
1329 .tuner_set_bandwidth = stb6100_set_bandwidth,
1330 .tuner_get_bandwidth = stb6100_get_bandwidth,
Manu Abraham043a68b2008-01-18 14:15:17 -03001331 .tuner_set_rfsiggain = NULL
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001332};
1333
Mauro Carvalho Chehabffbc5f82009-01-05 01:34:20 -03001334static struct stb6100_config tt3200_stb6100_config = {
Manu Abrahamc14eaed2007-10-04 16:52:51 -03001335 .tuner_address = 0x60,
1336 .refclock = 27000000,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001337};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338
1339static void frontend_init(struct budget_ci *budget_ci)
1340{
1341 switch (budget_ci->budget.dev->pci->subsystem_device) {
1342 case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
1343 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001344 dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001346 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001347 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 break;
1349 }
1350 break;
1351
1352 case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
1353 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001354 dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001356 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 break;
1358 }
1359 break;
1360
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001361 case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
1362 budget_ci->tuner_pll_address = 0x61;
1363 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001364 dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001365 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001366 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001367 break;
1368 }
1369 break;
1370
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001372 budget_ci->tuner_pll_address = 0x63;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001374 dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001376 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1377 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 break;
1379 }
1380 break;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001381
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001382 case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001383 budget_ci->tuner_pll_address = 0x60;
1384 budget_ci->budget.dvb_frontend =
Oliver Endriss6c914492007-02-02 19:12:53 -03001385 dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001386 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001387 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1388 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001389 break;
1390 }
1391 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001392
1393 case 0x1017: // TT S-1500 PCI
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001394 budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001395 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001396 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001397 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
1398
Patrick Boettcherdea74862006-05-14 05:01:31 -03001399 budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001400 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 -03001401 printk("%s: No LNBP21 found!\n", __func__);
Andrew de Quincey2b100e72006-08-08 09:10:11 -03001402 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001403 budget_ci->budget.dvb_frontend = NULL;
1404 }
1405 }
Sigmund Augdal11417da2008-06-15 17:25:46 -03001406 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001407
Sigmund Augdal11417da2008-06-15 17:25:46 -03001408 case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */
1409 budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48);
1410 if (budget_ci->budget.dvb_frontend) {
klaas de waalcf47d872009-03-25 17:53:02 -03001411 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 -03001412 printk(KERN_ERR "%s: No tda827x found!\n", __func__);
1413 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1414 budget_ci->budget.dvb_frontend = NULL;
1415 }
1416 }
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001417 break;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001418
1419 case 0x1019: // TT S2-3200 PCI
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001420 /*
1421 * NOTE! on some STB0899 versions, the internal PLL takes a longer time
1422 * to settle, aka LOCK. On the older revisions of the chip, we don't see
1423 * this, as a result on the newer chips the entire clock tree, will not
1424 * be stable after a freshly POWER 'ed up situation.
1425 * In this case, we should RESET the STB0899 (Active LOW) and wait for
1426 * PLL stabilization.
1427 *
1428 * On the TT S2 3200 and clones, the STB0899 demodulator's RESETB is
1429 * connected to the SAA7146 GPIO, GPIO2, Pin 142
1430 */
1431 /* Reset Demodulator */
Manu Abraham0867f572007-10-15 13:07:16 -03001432 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001433 /* Wait for everything to die */
1434 msleep(50);
1435 /* Pull it up out of Reset state */
Manu Abraham0867f572007-10-15 13:07:16 -03001436 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001437 /* Wait for PLL to stabilize */
1438 msleep(250);
1439 /*
1440 * PLL state should be stable now. Ideally, we should check
1441 * for PLL LOCK status. But well, never mind!
1442 */
Manu Abrahamae9902d2007-10-08 18:51:54 -03001443 budget_ci->budget.dvb_frontend = dvb_attach(stb0899_attach, &tt3200_config, &budget_ci->budget.i2c_adap);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001444 if (budget_ci->budget.dvb_frontend) {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001445 if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {
1446 if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
Harvey Harrison9b4778f2009-01-07 14:42:41 -08001447 printk("%s: No LNBP21 found!\n", __func__);
Manu Abrahamae9902d2007-10-08 18:51:54 -03001448 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001449 budget_ci->budget.dvb_frontend = NULL;
1450 }
1451 } else {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001452 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1453 budget_ci->budget.dvb_frontend = NULL;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001454 }
1455 }
1456 break;
1457
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 }
1459
1460 if (budget_ci->budget.dvb_frontend == NULL) {
Bjorn Helgaas29e66a62008-09-04 17:24:51 -03001461 printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 budget_ci->budget.dev->pci->vendor,
1463 budget_ci->budget.dev->pci->device,
1464 budget_ci->budget.dev->pci->subsystem_vendor,
1465 budget_ci->budget.dev->pci->subsystem_device);
1466 } else {
1467 if (dvb_register_frontend
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001468 (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 printk("budget-ci: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001470 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 budget_ci->budget.dvb_frontend = NULL;
1472 }
1473 }
1474}
1475
1476static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
1477{
1478 struct budget_ci *budget_ci;
1479 int err;
1480
David Hardemanee579bc2006-12-02 21:16:05 -02001481 budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
David Hardeman8cc532e2006-12-02 21:16:05 -02001482 if (!budget_ci) {
1483 err = -ENOMEM;
1484 goto out1;
1485 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486
1487 dprintk(2, "budget_ci: %p\n", budget_ci);
1488
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 dev->ext_priv = budget_ci;
1490
Janne Grunau26dc4d02008-09-21 20:50:11 -03001491 err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE,
1492 adapter_nr);
David Hardeman8cc532e2006-12-02 21:16:05 -02001493 if (err)
1494 goto out2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495
David Hardeman8cc532e2006-12-02 21:16:05 -02001496 err = msp430_ir_init(budget_ci);
1497 if (err)
1498 goto out3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499
1500 ciintf_init(budget_ci);
1501
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001502 budget_ci->budget.dvb_adapter.priv = budget_ci;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 frontend_init(budget_ci);
1504
Oliver Endriss32e4c3a2006-07-18 22:55:23 -03001505 ttpci_budget_init_hooks(&budget_ci->budget);
1506
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 return 0;
David Hardeman8cc532e2006-12-02 21:16:05 -02001508
1509out3:
1510 ttpci_budget_deinit(&budget_ci->budget);
1511out2:
1512 kfree(budget_ci);
1513out1:
1514 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515}
1516
1517static int budget_ci_detach(struct saa7146_dev *dev)
1518{
1519 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
1520 struct saa7146_dev *saa = budget_ci->budget.dev;
1521 int err;
1522
1523 if (budget_ci->budget.ci_present)
1524 ciintf_deinit(budget_ci);
David Hardeman8cc532e2006-12-02 21:16:05 -02001525 msp430_ir_deinit(budget_ci);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001526 if (budget_ci->budget.dvb_frontend) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001528 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001529 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 err = ttpci_budget_deinit(&budget_ci->budget);
1531
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 // disable frontend and CI interface
1533 saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
1534
1535 kfree(budget_ci);
1536
1537 return err;
1538}
1539
1540static struct saa7146_extension budget_extension;
1541
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001542MAKE_BUDGET_INFO(ttbs2, "TT-Budget/S-1500 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
1544MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001545MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001546MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
Sigmund Augdal11417da2008-06-15 17:25:46 -03001547MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001548MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549
1550static struct pci_device_id pci_tbl[] = {
1551 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
1552 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001553 MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001555 MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001556 MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
Sigmund Augdal11417da2008-06-15 17:25:46 -03001557 MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001558 MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 {
1560 .vendor = 0,
1561 }
1562};
1563
1564MODULE_DEVICE_TABLE(pci, pci_tbl);
1565
1566static struct saa7146_extension budget_extension = {
Dave Jones0e367a12006-08-07 13:18:56 -03001567 .name = "budget_ci dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03001568 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569
1570 .module = THIS_MODULE,
1571 .pci_tbl = &pci_tbl[0],
1572 .attach = budget_ci_attach,
1573 .detach = budget_ci_detach,
1574
1575 .irq_mask = MASK_03 | MASK_06 | MASK_10,
1576 .irq_func = budget_ci_irq,
1577};
1578
1579static int __init budget_ci_init(void)
1580{
1581 return saa7146_register_extension(&budget_extension);
1582}
1583
1584static void __exit budget_ci_exit(void)
1585{
1586 saa7146_unregister_extension(&budget_extension);
1587}
1588
1589module_init(budget_ci_init);
1590module_exit(budget_ci_exit);
1591
1592MODULE_LICENSE("GPL");
1593MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
1594MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1595 "budget PCI DVB cards w/ CI-module produced by "
1596 "Siemens, Technotrend, Hauppauge");