blob: 9782e05937338fca46d65c1be4a54a95f9a3428c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * budget-ci.c: driver for the SAA7146 based Budget DVB cards
3 *
4 * Compiled from various sources by Michael Hunold <michael@mihu.de>
5 *
6 * msp430 IR support contributed by Jack Thomasson <jkt@Helius.COM>
7 * partially based on the Siemens DVB driver by Ralph+Marcus Metzler
8 *
9 * CI interface support (c) 2004 Andrew de Quincey <adq_dvb@lidskialf.net>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
27 *
28 *
29 * the project's page is at http://www.linuxtv.org/dvb/
30 */
31
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/module.h>
33#include <linux/errno.h>
34#include <linux/slab.h>
35#include <linux/interrupt.h>
36#include <linux/input.h>
37#include <linux/spinlock.h>
David Hardeman2520fff2006-12-02 21:16:05 -020038#include <media/ir-common.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
Trent Piepho68277092007-01-30 23:25:46 -030040#include "budget.h"
41
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include "dvb_ca_en50221.h"
43#include "stv0299.h"
Andrew de Quinceydc27a162005-09-09 13:03:07 -070044#include "stv0297.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include "tda1004x.h"
Marko Schluessler9e0dc662008-10-23 18:16:40 -030046#include "stb0899_drv.h"
47#include "stb0899_reg.h"
Manu Abraham8be969b2008-01-25 18:20:48 -030048#include "stb0899_cfg.h"
Marko Schluessler9e0dc662008-10-23 18:16:40 -030049#include "stb6100.h"
Manu Abraham8be969b2008-01-25 18:20:48 -030050#include "stb6100_cfg.h"
Perceval Anichini8cc2e372006-02-28 09:52:44 -030051#include "lnbp21.h"
52#include "bsbe1.h"
Perceval Anichini265366e2006-03-16 11:22:47 -030053#include "bsru6.h"
Sigmund Augdal11417da2008-06-15 17:25:46 -030054#include "tda1002x.h"
55#include "tda827x.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
David Härdemanecba77f2006-10-27 20:56:51 -030057/*
58 * Regarding DEBIADDR_IR:
59 * Some CI modules hang if random addresses are read.
60 * Using address 0x4000 for the IR read means that we
61 * use the same address as for CI version, which should
62 * be a safe default.
63 */
64#define DEBIADDR_IR 0x4000
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#define DEBIADDR_CICONTROL 0x0000
66#define DEBIADDR_CIVERSION 0x4000
67#define DEBIADDR_IO 0x1000
68#define DEBIADDR_ATTR 0x3000
69
70#define CICONTROL_RESET 0x01
71#define CICONTROL_ENABLETS 0x02
72#define CICONTROL_CAMDETECT 0x08
73
74#define DEBICICTL 0x00420000
75#define DEBICICAM 0x02420000
76
77#define SLOTSTATUS_NONE 1
78#define SLOTSTATUS_PRESENT 2
79#define SLOTSTATUS_RESET 4
80#define SLOTSTATUS_READY 8
81#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
82
David Härdeman145859c2007-04-27 12:31:22 -030083/*
84 * Milliseconds during which a key is regarded as pressed.
85 * If an identical command arrives within this time, the timer will start over.
David Hardeman2520fff2006-12-02 21:16:05 -020086 */
David Härdeman145859c2007-04-27 12:31:22 -030087#define IR_KEYPRESS_TIMEOUT 250
David Hardeman2520fff2006-12-02 21:16:05 -020088
David Hardeman64741b72006-12-02 21:16:05 -020089/* RC5 device wildcard */
90#define IR_DEVICE_ANY 255
91
David Hardeman64741b72006-12-02 21:16:05 -020092static int rc5_device = -1;
93module_param(rc5_device, int, 0644);
94MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
95
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030096static int ir_debug;
David Hardemanb5471a22006-12-02 21:16:05 -020097module_param(ir_debug, int, 0644);
98MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
99
Janne Grunau26dc4d02008-09-21 20:50:11 -0300100DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
101
David Hardemandd2f3982006-12-02 21:16:05 -0200102struct budget_ci_ir {
103 struct input_dev *dev;
104 struct tasklet_struct msp430_irq_tasklet;
David Härdeman145859c2007-04-27 12:31:22 -0300105 struct timer_list timer_keyup;
David Hardemandd2f3982006-12-02 21:16:05 -0200106 char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
David Hardeman5cc8ae02006-12-02 21:16:05 -0200107 char phys[32];
David Hardeman2520fff2006-12-02 21:16:05 -0200108 struct ir_input_state state;
David Hardeman64741b72006-12-02 21:16:05 -0200109 int rc5_device;
David Härdeman145859c2007-04-27 12:31:22 -0300110 u32 last_raw;
111 u32 ir_key;
112 bool have_command;
David Hardemandd2f3982006-12-02 21:16:05 -0200113};
114
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115struct budget_ci {
116 struct budget budget;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 struct tasklet_struct ciintf_irq_tasklet;
118 int slot_status;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300119 int ci_irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 struct dvb_ca_en50221 ca;
David Hardemandd2f3982006-12-02 21:16:05 -0200121 struct budget_ci_ir ir;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700122 u8 tuner_pll_address; /* used for philips_tdm1316l configs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123};
124
David Hardeman2520fff2006-12-02 21:16:05 -0200125static void msp430_ir_keyup(unsigned long data)
126{
127 struct budget_ci_ir *ir = (struct budget_ci_ir *) data;
128 ir_input_nokey(ir->dev, &ir->state);
129}
130
131static void msp430_ir_interrupt(unsigned long data)
132{
133 struct budget_ci *budget_ci = (struct budget_ci *) data;
134 struct input_dev *dev = budget_ci->ir.dev;
David Hardeman2520fff2006-12-02 21:16:05 -0200135 u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
David Härdeman145859c2007-04-27 12:31:22 -0300136 u32 raw;
David Hardeman2520fff2006-12-02 21:16:05 -0200137
David Hardeman64741b72006-12-02 21:16:05 -0200138 /*
139 * The msp430 chip can generate two different bytes, command and device
140 *
141 * type1: X1CCCCCC, C = command bits (0 - 63)
142 * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
143 *
David Härdeman59327a42007-02-13 09:39:58 -0300144 * Each signal from the remote control can generate one or more command
145 * bytes and one or more device bytes. For the repeated bytes, the
146 * highest bit (X) is set. The first command byte is always generated
147 * before the first device byte. Other than that, no specific order
David Härdeman145859c2007-04-27 12:31:22 -0300148 * seems to apply. To make life interesting, bytes can also be lost.
David Härdeman59327a42007-02-13 09:39:58 -0300149 *
150 * Only when we have a command and device byte, a keypress is
151 * generated.
David Hardeman64741b72006-12-02 21:16:05 -0200152 */
153
David Härdeman59327a42007-02-13 09:39:58 -0300154 if (ir_debug)
155 printk("budget_ci: received byte 0x%02x\n", command);
156
David Härdeman145859c2007-04-27 12:31:22 -0300157 /* Remove repeat bit, we use every command */
158 command = command & 0x7f;
David Härdeman59327a42007-02-13 09:39:58 -0300159
David Hardeman64741b72006-12-02 21:16:05 -0200160 /* Is this a RC5 command byte? */
David Hardeman2520fff2006-12-02 21:16:05 -0200161 if (command & 0x40) {
David Härdeman145859c2007-04-27 12:31:22 -0300162 budget_ci->ir.have_command = true;
163 budget_ci->ir.ir_key = command & 0x3f;
David Hardeman64741b72006-12-02 21:16:05 -0200164 return;
David Hardeman2520fff2006-12-02 21:16:05 -0200165 }
David Hardeman64741b72006-12-02 21:16:05 -0200166
167 /* It's a RC5 device byte */
David Härdeman145859c2007-04-27 12:31:22 -0300168 if (!budget_ci->ir.have_command)
David Härdeman59327a42007-02-13 09:39:58 -0300169 return;
David Härdeman145859c2007-04-27 12:31:22 -0300170 budget_ci->ir.have_command = false;
David Hardeman64741b72006-12-02 21:16:05 -0200171
David Härdeman145859c2007-04-27 12:31:22 -0300172 if (budget_ci->ir.rc5_device != IR_DEVICE_ANY &&
173 budget_ci->ir.rc5_device != (command & 0x1f))
David Hardeman64741b72006-12-02 21:16:05 -0200174 return;
175
David Härdeman145859c2007-04-27 12:31:22 -0300176 /* Is this a repeated key sequence? (same device, command, toggle) */
177 raw = budget_ci->ir.ir_key | (command << 8);
178 if (budget_ci->ir.last_raw != raw || !timer_pending(&budget_ci->ir.timer_keyup)) {
David Hardeman59236d42006-12-02 21:16:06 -0200179 ir_input_nokey(dev, &budget_ci->ir.state);
David Härdeman145859c2007-04-27 12:31:22 -0300180 ir_input_keydown(dev, &budget_ci->ir.state,
Mauro Carvalho Chehab8573b742009-11-27 22:40:22 -0300181 budget_ci->ir.ir_key);
David Härdeman145859c2007-04-27 12:31:22 -0300182 budget_ci->ir.last_raw = raw;
David Hardeman59236d42006-12-02 21:16:06 -0200183 }
David Härdeman145859c2007-04-27 12:31:22 -0300184
185 mod_timer(&budget_ci->ir.timer_keyup, jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT));
David Hardeman2520fff2006-12-02 21:16:05 -0200186}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188static int msp430_ir_init(struct budget_ci *budget_ci)
189{
190 struct saa7146_dev *saa = budget_ci->budget.dev;
David Hardemandd2f3982006-12-02 21:16:05 -0200191 struct input_dev *input_dev = budget_ci->ir.dev;
David Hardeman8cc532e2006-12-02 21:16:05 -0200192 int error;
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300193 struct ir_scancode_table *ir_codes;
194
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");
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300199 return -ENOMEM;
David Hardeman8cc532e2006-12-02 21:16:05 -0200200 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
David Hardemandd2f3982006-12-02 21:16:05 -0200202 snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
203 "Budget-CI dvb ir receiver %s", saa->name);
David Hardeman5cc8ae02006-12-02 21:16:05 -0200204 snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
205 "pci-%s/ir0", pci_name(saa->pci));
206
David Hardemandd2f3982006-12-02 21:16:05 -0200207 input_dev->name = budget_ci->ir.name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
David Hardeman5cc8ae02006-12-02 21:16:05 -0200209 input_dev->phys = budget_ci->ir.phys;
210 input_dev->id.bustype = BUS_PCI;
211 input_dev->id.version = 1;
212 if (saa->pci->subsystem_vendor) {
213 input_dev->id.vendor = saa->pci->subsystem_vendor;
214 input_dev->id.product = saa->pci->subsystem_device;
215 } else {
216 input_dev->id.vendor = saa->pci->vendor;
217 input_dev->id.product = saa->pci->device;
218 }
Dmitry Torokhov2c8a3a32007-07-16 09:28:15 -0300219 input_dev->dev.parent = &saa->pci->dev;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200220
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300221 if (rc5_device < 0)
222 budget_ci->ir.rc5_device = IR_DEVICE_ANY;
223 else
224 budget_ci->ir.rc5_device = rc5_device;
225
David Hardeman64741b72006-12-02 21:16:05 -0200226 /* Select keymap and address */
David Hardeman2520fff2006-12-02 21:16:05 -0200227 switch (budget_ci->budget.dev->pci->subsystem_device) {
228 case 0x100c:
229 case 0x100f:
David Hardeman2520fff2006-12-02 21:16:05 -0200230 case 0x1011:
231 case 0x1012:
David Hardeman2520fff2006-12-02 21:16:05 -0200232 /* The hauppauge keymap is a superset of these remotes */
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300233 ir_codes = &ir_codes_hauppauge_new_table;
David Hardeman64741b72006-12-02 21:16:05 -0200234
235 if (rc5_device < 0)
236 budget_ci->ir.rc5_device = 0x1f;
David Hardeman2520fff2006-12-02 21:16:05 -0200237 break;
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300238 case 0x1010:
Oliver Endrissf64899c2007-09-17 22:17:12 -0300239 case 0x1017:
Oliver Endrissbbfc4c22008-06-19 23:36:45 -0300240 case 0x101a:
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300241 /* for the Technotrend 1500 bundled remote */
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300242 ir_codes = &ir_codes_tt_1500_table;
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300243 break;
David Hardeman2520fff2006-12-02 21:16:05 -0200244 default:
245 /* unknown remote */
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300246 ir_codes = &ir_codes_budget_ci_old_table;
David Hardeman2520fff2006-12-02 21:16:05 -0200247 break;
248 }
249
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300250 ir_input_init(input_dev, &budget_ci->ir.state, IR_TYPE_RC5);
251
David Härdeman145859c2007-04-27 12:31:22 -0300252 /* initialise the key-up timeout handler */
253 init_timer(&budget_ci->ir.timer_keyup);
254 budget_ci->ir.timer_keyup.function = msp430_ir_keyup;
255 budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir;
256 budget_ci->ir.last_raw = 0xffff; /* An impossible value */
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300257 error = ir_input_register(input_dev, ir_codes);
David Hardeman8cc532e2006-12-02 21:16:05 -0200258 if (error) {
259 printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300260 return error;
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300261 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
David Härdeman145859c2007-04-27 12:31:22 -0300263 /* note: these must be after input_register_device */
264 input_dev->rep[REP_DELAY] = 400;
265 input_dev->rep[REP_PERIOD] = 250;
266
David Hardeman8cc532e2006-12-02 21:16:05 -0200267 tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
268 (unsigned long) budget_ci);
269
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300270 SAA7146_IER_ENABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
272
273 return 0;
274}
275
276static void msp430_ir_deinit(struct budget_ci *budget_ci)
277{
278 struct saa7146_dev *saa = budget_ci->budget.dev;
David Hardemandd2f3982006-12-02 21:16:05 -0200279 struct input_dev *dev = budget_ci->ir.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300281 SAA7146_IER_DISABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
David Hardeman8cc532e2006-12-02 21:16:05 -0200283 tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
David Härdeman145859c2007-04-27 12:31:22 -0300285 del_timer_sync(&dev->timer);
286 ir_input_nokey(dev, &budget_ci->ir.state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
Mauro Carvalho Chehab38ef6aa2009-12-11 09:47:42 -0300288 ir_input_unregister(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289}
290
291static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
292{
293 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
294
295 if (slot != 0)
296 return -EINVAL;
297
298 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
299 DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);
300}
301
302static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
303{
304 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
305
306 if (slot != 0)
307 return -EINVAL;
308
309 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
310 DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);
311}
312
313static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
314{
315 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
316
317 if (slot != 0)
318 return -EINVAL;
319
320 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
321 DEBIADDR_IO | (address & 3), 1, 1, 0);
322}
323
324static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
325{
326 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
327
328 if (slot != 0)
329 return -EINVAL;
330
331 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
332 DEBIADDR_IO | (address & 3), 1, value, 1, 0);
333}
334
335static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
336{
337 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
338 struct saa7146_dev *saa = budget_ci->budget.dev;
339
340 if (slot != 0)
341 return -EINVAL;
342
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300343 if (budget_ci->ci_irq) {
344 // trigger on RISING edge during reset so we know when READY is re-asserted
345 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
346 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 budget_ci->slot_status = SLOTSTATUS_RESET;
348 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
349 msleep(1);
350 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
351 CICONTROL_RESET, 1, 0);
352
353 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
354 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
355 return 0;
356}
357
358static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
359{
360 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
361 struct saa7146_dev *saa = budget_ci->budget.dev;
362
363 if (slot != 0)
364 return -EINVAL;
365
366 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
367 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
368 return 0;
369}
370
371static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
372{
373 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
374 struct saa7146_dev *saa = budget_ci->budget.dev;
375 int tmp;
376
377 if (slot != 0)
378 return -EINVAL;
379
380 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
381
382 tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
383 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
384 tmp | CICONTROL_ENABLETS, 1, 0);
385
386 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
387 return 0;
388}
389
390static void ciintf_interrupt(unsigned long data)
391{
392 struct budget_ci *budget_ci = (struct budget_ci *) data;
393 struct saa7146_dev *saa = budget_ci->budget.dev;
394 unsigned int flags;
395
396 // ensure we don't get spurious IRQs during initialisation
397 if (!budget_ci->budget.ci_present)
398 return;
399
400 // read the CAM status
401 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
402 if (flags & CICONTROL_CAMDETECT) {
403
404 // GPIO should be set to trigger on falling edge if a CAM is present
405 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
406
407 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
408 // CAM insertion IRQ
409 budget_ci->slot_status = SLOTSTATUS_PRESENT;
410 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
411 DVB_CA_EN50221_CAMCHANGE_INSERTED);
412
413 } else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
414 // CAM ready (reset completed)
415 budget_ci->slot_status = SLOTSTATUS_READY;
416 dvb_ca_en50221_camready_irq(&budget_ci->ca, 0);
417
418 } else if (budget_ci->slot_status & SLOTSTATUS_READY) {
419 // FR/DA IRQ
420 dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);
421 }
422 } else {
423
424 // trigger on rising edge if a CAM is not present - when a CAM is inserted, we
425 // only want to get the IRQ when it sets READY. If we trigger on the falling edge,
426 // the CAM might not actually be ready yet.
427 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
428
429 // generate a CAM removal IRQ if we haven't already
430 if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
431 // CAM removal IRQ
432 budget_ci->slot_status = SLOTSTATUS_NONE;
433 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
434 DVB_CA_EN50221_CAMCHANGE_REMOVED);
435 }
436 }
437}
438
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300439static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
440{
441 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
442 unsigned int flags;
443
444 // ensure we don't get spurious IRQs during initialisation
445 if (!budget_ci->budget.ci_present)
446 return -EINVAL;
447
448 // read the CAM status
449 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
450 if (flags & CICONTROL_CAMDETECT) {
451 // mark it as present if it wasn't before
452 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
453 budget_ci->slot_status = SLOTSTATUS_PRESENT;
454 }
455
456 // during a RESET, we check if we can read from IO memory to see when CAM is ready
457 if (budget_ci->slot_status & SLOTSTATUS_RESET) {
458 if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
459 budget_ci->slot_status = SLOTSTATUS_READY;
460 }
461 }
462 } else {
463 budget_ci->slot_status = SLOTSTATUS_NONE;
464 }
465
466 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
467 if (budget_ci->slot_status & SLOTSTATUS_READY) {
468 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
469 }
470 return DVB_CA_EN50221_POLL_CAM_PRESENT;
471 }
472
473 return 0;
474}
475
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476static int ciintf_init(struct budget_ci *budget_ci)
477{
478 struct saa7146_dev *saa = budget_ci->budget.dev;
479 int flags;
480 int result;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300481 int ci_version;
482 int ca_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
484 memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
485
486 // enable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300487 saa7146_write(saa, MC1, MASK_27 | MASK_11);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488
489 // test if it is there
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300490 ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
491 if ((ci_version & 0xa0) != 0xa0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 result = -ENODEV;
493 goto error;
494 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300495
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 // determine whether a CAM is present or not
497 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
498 budget_ci->slot_status = SLOTSTATUS_NONE;
499 if (flags & CICONTROL_CAMDETECT)
500 budget_ci->slot_status = SLOTSTATUS_PRESENT;
501
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300502 // version 0xa2 of the CI firmware doesn't generate interrupts
503 if (ci_version == 0xa2) {
504 ca_flags = 0;
505 budget_ci->ci_irq = 0;
506 } else {
507 ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
508 DVB_CA_EN50221_FLAG_IRQ_FR |
509 DVB_CA_EN50221_FLAG_IRQ_DA;
510 budget_ci->ci_irq = 1;
511 }
512
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 // register CI interface
514 budget_ci->ca.owner = THIS_MODULE;
515 budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
516 budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
517 budget_ci->ca.read_cam_control = ciintf_read_cam_control;
518 budget_ci->ca.write_cam_control = ciintf_write_cam_control;
519 budget_ci->ca.slot_reset = ciintf_slot_reset;
520 budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
521 budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300522 budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 budget_ci->ca.data = budget_ci;
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700524 if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 &budget_ci->ca,
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300526 ca_flags, 1)) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 printk("budget_ci: CI interface detected, but initialisation failed.\n");
528 goto error;
529 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300530
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 // Setup CI slot IRQ
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300532 if (budget_ci->ci_irq) {
533 tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
534 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
535 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
536 } else {
537 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
538 }
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300539 SAA7146_IER_ENABLE(saa, MASK_03);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300541
542 // enable interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
544 CICONTROL_RESET, 1, 0);
545
546 // success!
547 printk("budget_ci: CI interface initialised\n");
548 budget_ci->budget.ci_present = 1;
549
550 // forge a fake CI IRQ so the CAM state is setup correctly
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300551 if (budget_ci->ci_irq) {
552 flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
553 if (budget_ci->slot_status != SLOTSTATUS_NONE)
554 flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
555 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
556 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557
558 return 0;
559
560error:
Hartmut Birr2a893de2006-12-03 21:08:08 -0300561 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 return result;
563}
564
565static void ciintf_deinit(struct budget_ci *budget_ci)
566{
567 struct saa7146_dev *saa = budget_ci->budget.dev;
568
569 // disable CI interrupts
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300570 if (budget_ci->ci_irq) {
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300571 SAA7146_IER_DISABLE(saa, MASK_03);
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300572 saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
573 tasklet_kill(&budget_ci->ciintf_irq_tasklet);
574 }
575
576 // reset interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
578 msleep(1);
579 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
580 CICONTROL_RESET, 1, 0);
581
582 // disable TS data stream to CI interface
583 saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
584
585 // release the CA device
586 dvb_ca_en50221_release(&budget_ci->ca);
587
588 // disable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300589 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590}
591
592static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
593{
594 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
595
596 dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
597
598 if (*isr & MASK_06)
David Hardemandd2f3982006-12-02 21:16:05 -0200599 tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
601 if (*isr & MASK_10)
602 ttpci_budget_irq10_handler(dev, isr);
603
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300604 if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
606}
607
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608static u8 philips_su1278_tt_inittab[] = {
609 0x01, 0x0f,
610 0x02, 0x30,
611 0x03, 0x00,
612 0x04, 0x5b,
613 0x05, 0x85,
614 0x06, 0x02,
615 0x07, 0x00,
616 0x08, 0x02,
617 0x09, 0x00,
618 0x0C, 0x01,
619 0x0D, 0x81,
620 0x0E, 0x44,
621 0x0f, 0x14,
622 0x10, 0x3c,
623 0x11, 0x84,
624 0x12, 0xda,
625 0x13, 0x97,
626 0x14, 0x95,
627 0x15, 0xc9,
628 0x16, 0x19,
629 0x17, 0x8c,
630 0x18, 0x59,
631 0x19, 0xf8,
632 0x1a, 0xfe,
633 0x1c, 0x7f,
634 0x1d, 0x00,
635 0x1e, 0x00,
636 0x1f, 0x50,
637 0x20, 0x00,
638 0x21, 0x00,
639 0x22, 0x00,
640 0x23, 0x00,
641 0x28, 0x00,
642 0x29, 0x28,
643 0x2a, 0x14,
644 0x2b, 0x0f,
645 0x2c, 0x09,
646 0x2d, 0x09,
647 0x31, 0x1f,
648 0x32, 0x19,
649 0x33, 0xfc,
650 0x34, 0x93,
651 0xff, 0xff
652};
653
654static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
655{
656 stv0299_writereg(fe, 0x0e, 0x44);
657 if (srate >= 10000000) {
658 stv0299_writereg(fe, 0x13, 0x97);
659 stv0299_writereg(fe, 0x14, 0x95);
660 stv0299_writereg(fe, 0x15, 0xc9);
661 stv0299_writereg(fe, 0x17, 0x8c);
662 stv0299_writereg(fe, 0x1a, 0xfe);
663 stv0299_writereg(fe, 0x1c, 0x7f);
664 stv0299_writereg(fe, 0x2d, 0x09);
665 } else {
666 stv0299_writereg(fe, 0x13, 0x99);
667 stv0299_writereg(fe, 0x14, 0x8d);
668 stv0299_writereg(fe, 0x15, 0xce);
669 stv0299_writereg(fe, 0x17, 0x43);
670 stv0299_writereg(fe, 0x1a, 0x1d);
671 stv0299_writereg(fe, 0x1c, 0x12);
672 stv0299_writereg(fe, 0x2d, 0x05);
673 }
674 stv0299_writereg(fe, 0x0e, 0x23);
675 stv0299_writereg(fe, 0x0f, 0x94);
676 stv0299_writereg(fe, 0x10, 0x39);
677 stv0299_writereg(fe, 0x15, 0xc9);
678
679 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
680 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
681 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
682
683 return 0;
684}
685
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300686static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,
687 struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688{
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300689 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 u32 div;
691 u8 buf[4];
692 struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
693
694 if ((params->frequency < 950000) || (params->frequency > 2150000))
695 return -EINVAL;
696
697 div = (params->frequency + (500 - 1)) / 500; // round correctly
698 buf[0] = (div >> 8) & 0x7f;
699 buf[1] = div & 0xff;
700 buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
701 buf[3] = 0x20;
702
703 if (params->u.qpsk.symbol_rate < 4000000)
704 buf[3] |= 1;
705
706 if (params->frequency < 1250000)
707 buf[3] |= 0;
708 else if (params->frequency < 1550000)
709 buf[3] |= 0x40;
710 else if (params->frequency < 2050000)
711 buf[3] |= 0x80;
712 else if (params->frequency < 2150000)
713 buf[3] |= 0xC0;
714
Patrick Boettcherdea74862006-05-14 05:01:31 -0300715 if (fe->ops.i2c_gate_ctrl)
716 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300717 if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 return -EIO;
719 return 0;
720}
721
722static struct stv0299_config philips_su1278_tt_config = {
723
724 .demod_address = 0x68,
725 .inittab = philips_su1278_tt_inittab,
726 .mclk = 64000000UL,
727 .invert = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 .skip_reinit = 1,
Oliver Endrissda2c7f62008-04-20 22:13:37 -0300729 .lock_output = STV0299_LOCKOUTPUT_1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 .volt13_op0_op1 = STV0299_VOLT13_OP1,
731 .min_delay_ms = 50,
732 .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733};
734
735
736
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300737static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738{
739 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
740 static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
741 static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700742 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 sizeof(td1316_init) };
744
745 // setup PLL configuration
Patrick Boettcherdea74862006-05-14 05:01:31 -0300746 if (fe->ops.i2c_gate_ctrl)
747 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
749 return -EIO;
750 msleep(1);
751
752 // disable the mc44BC374c (do not check for errors)
753 tuner_msg.addr = 0x65;
754 tuner_msg.buf = disable_mc44BC374c;
755 tuner_msg.len = sizeof(disable_mc44BC374c);
Patrick Boettcherdea74862006-05-14 05:01:31 -0300756 if (fe->ops.i2c_gate_ctrl)
757 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
Patrick Boettcherdea74862006-05-14 05:01:31 -0300759 if (fe->ops.i2c_gate_ctrl)
760 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
762 }
763
764 return 0;
765}
766
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300767static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768{
769 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
770 u8 tuner_buf[4];
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700771 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 -0700772 int tuner_frequency = 0;
773 u8 band, cp, filter;
774
775 // determine charge pump
776 tuner_frequency = params->frequency + 36130000;
777 if (tuner_frequency < 87000000)
778 return -EINVAL;
779 else if (tuner_frequency < 130000000)
780 cp = 3;
781 else if (tuner_frequency < 160000000)
782 cp = 5;
783 else if (tuner_frequency < 200000000)
784 cp = 6;
785 else if (tuner_frequency < 290000000)
786 cp = 3;
787 else if (tuner_frequency < 420000000)
788 cp = 5;
789 else if (tuner_frequency < 480000000)
790 cp = 6;
791 else if (tuner_frequency < 620000000)
792 cp = 3;
793 else if (tuner_frequency < 830000000)
794 cp = 5;
795 else if (tuner_frequency < 895000000)
796 cp = 7;
797 else
798 return -EINVAL;
799
800 // determine band
801 if (params->frequency < 49000000)
802 return -EINVAL;
803 else if (params->frequency < 159000000)
804 band = 1;
805 else if (params->frequency < 444000000)
806 band = 2;
807 else if (params->frequency < 861000000)
808 band = 4;
809 else
810 return -EINVAL;
811
812 // setup PLL filter and TDA9889
813 switch (params->u.ofdm.bandwidth) {
814 case BANDWIDTH_6_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300815 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 filter = 0;
817 break;
818
819 case BANDWIDTH_7_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300820 tda1004x_writereg(fe, 0x0C, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 filter = 0;
822 break;
823
824 case BANDWIDTH_8_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300825 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 filter = 1;
827 break;
828
829 default:
830 return -EINVAL;
831 }
832
833 // calculate divisor
834 // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
835 tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
836
837 // setup tuner buffer
838 tuner_buf[0] = tuner_frequency >> 8;
839 tuner_buf[1] = tuner_frequency & 0xff;
840 tuner_buf[2] = 0xca;
841 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
842
Patrick Boettcherdea74862006-05-14 05:01:31 -0300843 if (fe->ops.i2c_gate_ctrl)
844 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
846 return -EIO;
847
848 msleep(1);
849 return 0;
850}
851
852static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,
853 const struct firmware **fw, char *name)
854{
855 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
856
857 return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);
858}
859
860static struct tda1004x_config philips_tdm1316l_config = {
861
862 .demod_address = 0x8,
863 .invert = 0,
864 .invert_oclk = 0,
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700865 .xtal_freq = TDA10046_XTAL_4M,
866 .agc_config = TDA10046_AGC_DEFAULT,
867 .if_freq = TDA10046_FREQ_3617,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 .request_firmware = philips_tdm1316l_request_firmware,
869};
870
Oliver Endriss6c914492007-02-02 19:12:53 -0300871static struct tda1004x_config philips_tdm1316l_config_invert = {
872
873 .demod_address = 0x8,
874 .invert = 1,
875 .invert_oclk = 0,
876 .xtal_freq = TDA10046_XTAL_4M,
877 .agc_config = TDA10046_AGC_DEFAULT,
878 .if_freq = TDA10046_FREQ_3617,
879 .request_firmware = philips_tdm1316l_request_firmware,
880};
881
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300882static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700883{
884 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
885 u8 tuner_buf[5];
886 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
887 .flags = 0,
888 .buf = tuner_buf,
889 .len = sizeof(tuner_buf) };
890 int tuner_frequency = 0;
891 u8 band, cp, filter;
892
893 // determine charge pump
894 tuner_frequency = params->frequency + 36125000;
895 if (tuner_frequency < 87000000)
896 return -EINVAL;
897 else if (tuner_frequency < 130000000) {
898 cp = 3;
899 band = 1;
900 } else if (tuner_frequency < 160000000) {
901 cp = 5;
902 band = 1;
903 } else if (tuner_frequency < 200000000) {
904 cp = 6;
Oliver Endriss910a7b62007-05-03 13:16:12 -0300905 band = 1;
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700906 } else if (tuner_frequency < 290000000) {
907 cp = 3;
908 band = 2;
909 } else if (tuner_frequency < 420000000) {
910 cp = 5;
911 band = 2;
912 } else if (tuner_frequency < 480000000) {
913 cp = 6;
914 band = 2;
915 } else if (tuner_frequency < 620000000) {
916 cp = 3;
917 band = 4;
918 } else if (tuner_frequency < 830000000) {
919 cp = 5;
920 band = 4;
921 } else if (tuner_frequency < 895000000) {
922 cp = 7;
923 band = 4;
924 } else
925 return -EINVAL;
926
927 // assume PLL filter should always be 8MHz for the moment.
928 filter = 1;
929
930 // calculate divisor
931 tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
932
933 // setup tuner buffer
934 tuner_buf[0] = tuner_frequency >> 8;
935 tuner_buf[1] = tuner_frequency & 0xff;
936 tuner_buf[2] = 0xc8;
937 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
938 tuner_buf[4] = 0x80;
939
Patrick Boettcherdea74862006-05-14 05:01:31 -0300940 if (fe->ops.i2c_gate_ctrl)
941 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700942 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
943 return -EIO;
944
945 msleep(50);
946
Patrick Boettcherdea74862006-05-14 05:01:31 -0300947 if (fe->ops.i2c_gate_ctrl)
948 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700949 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
950 return -EIO;
951
952 msleep(1);
953
954 return 0;
955}
956
957static u8 dvbc_philips_tdm1316l_inittab[] = {
958 0x80, 0x01,
959 0x80, 0x00,
960 0x81, 0x01,
961 0x81, 0x00,
962 0x00, 0x09,
963 0x01, 0x69,
964 0x03, 0x00,
965 0x04, 0x00,
966 0x07, 0x00,
967 0x08, 0x00,
968 0x20, 0x00,
969 0x21, 0x40,
970 0x22, 0x00,
971 0x23, 0x00,
972 0x24, 0x40,
973 0x25, 0x88,
974 0x30, 0xff,
975 0x31, 0x00,
976 0x32, 0xff,
977 0x33, 0x00,
978 0x34, 0x50,
979 0x35, 0x7f,
980 0x36, 0x00,
981 0x37, 0x20,
982 0x38, 0x00,
983 0x40, 0x1c,
984 0x41, 0xff,
985 0x42, 0x29,
986 0x43, 0x20,
987 0x44, 0xff,
988 0x45, 0x00,
989 0x46, 0x00,
990 0x49, 0x04,
991 0x4a, 0x00,
992 0x4b, 0x7b,
993 0x52, 0x30,
994 0x55, 0xae,
995 0x56, 0x47,
996 0x57, 0xe1,
997 0x58, 0x3a,
998 0x5a, 0x1e,
999 0x5b, 0x34,
1000 0x60, 0x00,
1001 0x63, 0x00,
1002 0x64, 0x00,
1003 0x65, 0x00,
1004 0x66, 0x00,
1005 0x67, 0x00,
1006 0x68, 0x00,
1007 0x69, 0x00,
1008 0x6a, 0x02,
1009 0x6b, 0x00,
1010 0x70, 0xff,
1011 0x71, 0x00,
1012 0x72, 0x00,
1013 0x73, 0x00,
1014 0x74, 0x0c,
1015 0x80, 0x00,
1016 0x81, 0x00,
1017 0x82, 0x00,
1018 0x83, 0x00,
1019 0x84, 0x04,
1020 0x85, 0x80,
1021 0x86, 0x24,
1022 0x87, 0x78,
1023 0x88, 0x10,
1024 0x89, 0x00,
1025 0x90, 0x01,
1026 0x91, 0x01,
1027 0xa0, 0x04,
1028 0xa1, 0x00,
1029 0xa2, 0x00,
1030 0xb0, 0x91,
1031 0xb1, 0x0b,
1032 0xc0, 0x53,
1033 0xc1, 0x70,
1034 0xc2, 0x12,
1035 0xd0, 0x00,
1036 0xd1, 0x00,
1037 0xd2, 0x00,
1038 0xd3, 0x00,
1039 0xd4, 0x00,
1040 0xd5, 0x00,
1041 0xde, 0x00,
1042 0xdf, 0x00,
1043 0x61, 0x38,
1044 0x62, 0x0a,
1045 0x53, 0x13,
1046 0x59, 0x08,
1047 0xff, 0xff,
1048};
1049
1050static struct stv0297_config dvbc_philips_tdm1316l_config = {
1051 .demod_address = 0x1c,
1052 .inittab = dvbc_philips_tdm1316l_inittab,
1053 .invert = 0,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001054 .stop_during_read = 1,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001055};
1056
Sigmund Augdal11417da2008-06-15 17:25:46 -03001057static struct tda10023_config tda10023_config = {
1058 .demod_address = 0xc,
1059 .invert = 0,
1060 .xtal = 16000000,
1061 .pll_m = 11,
1062 .pll_p = 3,
1063 .pll_n = 1,
1064 .deltaf = 0xa511,
1065};
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001066
klaas de waalcf47d872009-03-25 17:53:02 -03001067static struct tda827x_config tda827x_config = {
1068 .config = 0,
1069};
1070
Manu Abrahama55bc842008-10-23 18:32:50 -03001071/* TT S2-3200 DVB-S (STB0899) Inittab */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001072static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001074 { STB0899_DEV_ID , 0x81 },
1075 { STB0899_DISCNTRL1 , 0x32 },
1076 { STB0899_DISCNTRL2 , 0x80 },
1077 { STB0899_DISRX_ST0 , 0x04 },
1078 { STB0899_DISRX_ST1 , 0x00 },
1079 { STB0899_DISPARITY , 0x00 },
1080 { STB0899_DISFIFO , 0x00 },
1081 { STB0899_DISSTATUS , 0x20 },
1082 { STB0899_DISF22 , 0x8c },
1083 { STB0899_DISF22RX , 0x9a },
Manu Abrahamef3052b2008-10-23 18:45:17 -03001084 { STB0899_SYSREG , 0x0b },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001085 { STB0899_ACRPRESC , 0x11 },
1086 { STB0899_ACRDIV1 , 0x0a },
1087 { STB0899_ACRDIV2 , 0x05 },
1088 { STB0899_DACR1 , 0x00 },
1089 { STB0899_DACR2 , 0x00 },
1090 { STB0899_OUTCFG , 0x00 },
1091 { STB0899_MODECFG , 0x00 },
1092 { STB0899_IRQSTATUS_3 , 0x30 },
1093 { STB0899_IRQSTATUS_2 , 0x00 },
1094 { STB0899_IRQSTATUS_1 , 0x00 },
1095 { STB0899_IRQSTATUS_0 , 0x00 },
1096 { STB0899_IRQMSK_3 , 0xf3 },
1097 { STB0899_IRQMSK_2 , 0xfc },
1098 { STB0899_IRQMSK_1 , 0xff },
1099 { STB0899_IRQMSK_0 , 0xff },
1100 { STB0899_IRQCFG , 0x00 },
1101 { STB0899_I2CCFG , 0x88 },
Manu Abraham40e8ce32008-02-03 19:37:02 -03001102 { STB0899_I2CRPT , 0x48 }, /* 12k Pullup, Repeater=16, Stop=disabled */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001103 { STB0899_IOPVALUE5 , 0x00 },
1104 { STB0899_IOPVALUE4 , 0x20 },
1105 { STB0899_IOPVALUE3 , 0xc9 },
1106 { STB0899_IOPVALUE2 , 0x90 },
1107 { STB0899_IOPVALUE1 , 0x40 },
1108 { STB0899_IOPVALUE0 , 0x00 },
1109 { STB0899_GPIO00CFG , 0x82 },
1110 { STB0899_GPIO01CFG , 0x82 },
1111 { STB0899_GPIO02CFG , 0x82 },
1112 { STB0899_GPIO03CFG , 0x82 },
1113 { STB0899_GPIO04CFG , 0x82 },
1114 { STB0899_GPIO05CFG , 0x82 },
1115 { STB0899_GPIO06CFG , 0x82 },
1116 { STB0899_GPIO07CFG , 0x82 },
1117 { STB0899_GPIO08CFG , 0x82 },
1118 { STB0899_GPIO09CFG , 0x82 },
1119 { STB0899_GPIO10CFG , 0x82 },
1120 { STB0899_GPIO11CFG , 0x82 },
1121 { STB0899_GPIO12CFG , 0x82 },
1122 { STB0899_GPIO13CFG , 0x82 },
1123 { STB0899_GPIO14CFG , 0x82 },
1124 { STB0899_GPIO15CFG , 0x82 },
1125 { STB0899_GPIO16CFG , 0x82 },
1126 { STB0899_GPIO17CFG , 0x82 },
1127 { STB0899_GPIO18CFG , 0x82 },
1128 { STB0899_GPIO19CFG , 0x82 },
1129 { STB0899_GPIO20CFG , 0x82 },
1130 { STB0899_SDATCFG , 0xb8 },
1131 { STB0899_SCLTCFG , 0xba },
Manu Abrahama55bc842008-10-23 18:32:50 -03001132 { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */
1133 { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */
1134 { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001135 { STB0899_DIRCLKCFG , 0x82 },
1136 { STB0899_CLKOUT27CFG , 0x7e },
1137 { STB0899_STDBYCFG , 0x82 },
1138 { STB0899_CS0CFG , 0x82 },
1139 { STB0899_CS1CFG , 0x82 },
1140 { STB0899_DISEQCOCFG , 0x20 },
1141 { STB0899_GPIO32CFG , 0x82 },
1142 { STB0899_GPIO33CFG , 0x82 },
1143 { STB0899_GPIO34CFG , 0x82 },
1144 { STB0899_GPIO35CFG , 0x82 },
1145 { STB0899_GPIO36CFG , 0x82 },
1146 { STB0899_GPIO37CFG , 0x82 },
1147 { STB0899_GPIO38CFG , 0x82 },
1148 { STB0899_GPIO39CFG , 0x82 },
Manu Abrahamf2e52cd2007-11-19 16:44:47 -03001149 { STB0899_NCOARSE , 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
Manu Abrahama55bc842008-10-23 18:32:50 -03001150 { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001151 { STB0899_FILTCTRL , 0x00 },
1152 { STB0899_SYSCTRL , 0x00 },
1153 { STB0899_STOPCLK1 , 0x20 },
1154 { STB0899_STOPCLK2 , 0x00 },
1155 { STB0899_INTBUFSTATUS , 0x00 },
1156 { STB0899_INTBUFCTRL , 0x0a },
1157 { 0xffff , 0xff },
1158};
1159
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001160static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = {
1161 { STB0899_DEMOD , 0x00 },
1162 { STB0899_RCOMPC , 0xc9 },
1163 { STB0899_AGC1CN , 0x41 },
1164 { STB0899_AGC1REF , 0x10 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001165 { STB0899_RTC , 0x7a },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001166 { STB0899_TMGCFG , 0x4e },
1167 { STB0899_AGC2REF , 0x34 },
1168 { STB0899_TLSR , 0x84 },
1169 { STB0899_CFD , 0xc7 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001170 { STB0899_ACLC , 0x87 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001171 { STB0899_BCLC , 0x94 },
1172 { STB0899_EQON , 0x41 },
1173 { STB0899_LDT , 0xdd },
1174 { STB0899_LDT2 , 0xc9 },
1175 { STB0899_EQUALREF , 0xb4 },
1176 { STB0899_TMGRAMP , 0x10 },
1177 { STB0899_TMGTHD , 0x30 },
1178 { STB0899_IDCCOMP , 0xfb },
1179 { STB0899_QDCCOMP , 0x03 },
1180 { STB0899_POWERI , 0x3b },
1181 { STB0899_POWERQ , 0x3d },
1182 { STB0899_RCOMP , 0x81 },
1183 { STB0899_AGCIQIN , 0x80 },
1184 { STB0899_AGC2I1 , 0x04 },
1185 { STB0899_AGC2I2 , 0xf5 },
1186 { STB0899_TLIR , 0x25 },
1187 { STB0899_RTF , 0x80 },
1188 { STB0899_DSTATUS , 0x00 },
1189 { STB0899_LDI , 0xca },
1190 { STB0899_CFRM , 0xf1 },
1191 { STB0899_CFRL , 0xf3 },
1192 { STB0899_NIRM , 0x2a },
1193 { STB0899_NIRL , 0x05 },
1194 { STB0899_ISYMB , 0x17 },
1195 { STB0899_QSYMB , 0xfa },
1196 { STB0899_SFRH , 0x2f },
1197 { STB0899_SFRM , 0x68 },
1198 { STB0899_SFRL , 0x40 },
1199 { STB0899_SFRUPH , 0x2f },
1200 { STB0899_SFRUPM , 0x68 },
1201 { STB0899_SFRUPL , 0x40 },
1202 { STB0899_EQUAI1 , 0xfd },
1203 { STB0899_EQUAQ1 , 0x04 },
1204 { STB0899_EQUAI2 , 0x0f },
1205 { STB0899_EQUAQ2 , 0xff },
1206 { STB0899_EQUAI3 , 0xdf },
1207 { STB0899_EQUAQ3 , 0xfa },
1208 { STB0899_EQUAI4 , 0x37 },
1209 { STB0899_EQUAQ4 , 0x0d },
1210 { STB0899_EQUAI5 , 0xbd },
1211 { STB0899_EQUAQ5 , 0xf7 },
1212 { STB0899_DSTATUS2 , 0x00 },
1213 { STB0899_VSTATUS , 0x00 },
1214 { STB0899_VERROR , 0xff },
1215 { STB0899_IQSWAP , 0x2a },
1216 { STB0899_ECNT1M , 0x00 },
1217 { STB0899_ECNT1L , 0x00 },
1218 { STB0899_ECNT2M , 0x00 },
1219 { STB0899_ECNT2L , 0x00 },
1220 { STB0899_ECNT3M , 0x00 },
1221 { STB0899_ECNT3L , 0x00 },
1222 { STB0899_FECAUTO1 , 0x06 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001223 { STB0899_FECM , 0x01 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001224 { STB0899_VTH12 , 0xf0 },
1225 { STB0899_VTH23 , 0xa0 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001226 { STB0899_VTH34 , 0x78 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001227 { STB0899_VTH56 , 0x4e },
1228 { STB0899_VTH67 , 0x48 },
1229 { STB0899_VTH78 , 0x38 },
1230 { STB0899_PRVIT , 0xff },
1231 { STB0899_VITSYNC , 0x19 },
Manu Abrahama55bc842008-10-23 18:32:50 -03001232 { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001233 { STB0899_TSULC , 0x42 },
1234 { STB0899_RSLLC , 0x40 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001235 { STB0899_TSLPL , 0x12 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001236 { STB0899_TSCFGH , 0x0c },
1237 { STB0899_TSCFGM , 0x00 },
1238 { STB0899_TSCFGL , 0x0c },
Manu Abrahamc1426df2009-11-13 18:51:39 -03001239 { STB0899_TSOUT , 0x4d }, /* 0x0d for CAM */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001240 { STB0899_RSSYNCDEL , 0x00 },
1241 { STB0899_TSINHDELH , 0x02 },
1242 { STB0899_TSINHDELM , 0x00 },
1243 { STB0899_TSINHDELL , 0x00 },
1244 { STB0899_TSLLSTKM , 0x00 },
1245 { STB0899_TSLLSTKL , 0x00 },
1246 { STB0899_TSULSTKM , 0x00 },
1247 { STB0899_TSULSTKL , 0xab },
1248 { STB0899_PCKLENUL , 0x00 },
1249 { STB0899_PCKLENLL , 0xcc },
1250 { STB0899_RSPCKLEN , 0xcc },
1251 { STB0899_TSSTATUS , 0x80 },
1252 { STB0899_ERRCTRL1 , 0xb6 },
1253 { STB0899_ERRCTRL2 , 0x96 },
1254 { STB0899_ERRCTRL3 , 0x89 },
1255 { STB0899_DMONMSK1 , 0x27 },
1256 { STB0899_DMONMSK0 , 0x03 },
1257 { STB0899_DEMAPVIT , 0x5c },
1258 { STB0899_PLPARM , 0x1f },
1259 { STB0899_PDELCTRL , 0x48 },
1260 { STB0899_PDELCTRL2 , 0x00 },
1261 { STB0899_BBHCTRL1 , 0x00 },
1262 { STB0899_BBHCTRL2 , 0x00 },
1263 { STB0899_HYSTTHRESH , 0x77 },
1264 { STB0899_MATCSTM , 0x00 },
1265 { STB0899_MATCSTL , 0x00 },
1266 { STB0899_UPLCSTM , 0x00 },
1267 { STB0899_UPLCSTL , 0x00 },
1268 { STB0899_DFLCSTM , 0x00 },
1269 { STB0899_DFLCSTL , 0x00 },
1270 { STB0899_SYNCCST , 0x00 },
1271 { STB0899_SYNCDCSTM , 0x00 },
1272 { STB0899_SYNCDCSTL , 0x00 },
1273 { STB0899_ISI_ENTRY , 0x00 },
1274 { STB0899_ISI_BIT_EN , 0x00 },
1275 { STB0899_MATSTRM , 0x00 },
1276 { STB0899_MATSTRL , 0x00 },
1277 { STB0899_UPLSTRM , 0x00 },
1278 { STB0899_UPLSTRL , 0x00 },
1279 { STB0899_DFLSTRM , 0x00 },
1280 { STB0899_DFLSTRL , 0x00 },
1281 { STB0899_SYNCSTR , 0x00 },
1282 { STB0899_SYNCDSTRM , 0x00 },
1283 { STB0899_SYNCDSTRL , 0x00 },
1284 { STB0899_CFGPDELSTATUS1 , 0x10 },
1285 { STB0899_CFGPDELSTATUS2 , 0x00 },
1286 { STB0899_BBFERRORM , 0x00 },
1287 { STB0899_BBFERRORL , 0x00 },
1288 { STB0899_UPKTERRORM , 0x00 },
1289 { STB0899_UPKTERRORL , 0x00 },
1290 { 0xffff , 0xff },
1291};
1292
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001293static struct stb0899_config tt3200_config = {
1294 .init_dev = tt3200_stb0899_s1_init_1,
Manu Abraham8be969b2008-01-25 18:20:48 -03001295 .init_s2_demod = stb0899_s2_init_2,
Manu Abrahama55bc842008-10-23 18:32:50 -03001296 .init_s1_demod = tt3200_stb0899_s1_init_3,
Manu Abraham8be969b2008-01-25 18:20:48 -03001297 .init_s2_fec = stb0899_s2_init_4,
1298 .init_tst = stb0899_s1_init_5,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001299
Manu Abraham043a68b2008-01-18 14:15:17 -03001300 .postproc = NULL,
1301
Manu Abrahama55bc842008-10-23 18:32:50 -03001302 .demod_address = 0x68,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001303
1304 .xtal_freq = 27000000,
Manu Abrahame99d00c2007-09-25 17:48:59 -03001305 .inversion = IQ_SWAP_ON, /* 1 */
Manu Abrahama55bc842008-10-23 18:32:50 -03001306
Manu Abrahamb91a7cb2008-03-04 19:19:58 -03001307 .lo_clk = 76500000,
1308 .hi_clk = 99000000,
1309
Manu Abraham8be969b2008-01-25 18:20:48 -03001310 .esno_ave = STB0899_DVBS2_ESNO_AVE,
1311 .esno_quant = STB0899_DVBS2_ESNO_QUANT,
1312 .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
1313 .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
1314 .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
1315 .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
1316 .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
1317 .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
1318 .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
Manu Abrahama55bc842008-10-23 18:32:50 -03001319
Manu Abraham8be969b2008-01-25 18:20:48 -03001320 .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
1321 .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
1322 .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
1323 .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
Manu Abrahama55bc842008-10-23 18:32:50 -03001324
1325 .tuner_get_frequency = stb6100_get_frequency,
1326 .tuner_set_frequency = stb6100_set_frequency,
1327 .tuner_set_bandwidth = stb6100_set_bandwidth,
1328 .tuner_get_bandwidth = stb6100_get_bandwidth,
Manu Abraham043a68b2008-01-18 14:15:17 -03001329 .tuner_set_rfsiggain = NULL
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001330};
1331
Mauro Carvalho Chehabffbc5f82009-01-05 01:34:20 -03001332static struct stb6100_config tt3200_stb6100_config = {
Manu Abrahamc14eaed2007-10-04 16:52:51 -03001333 .tuner_address = 0x60,
1334 .refclock = 27000000,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001335};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
1337static void frontend_init(struct budget_ci *budget_ci)
1338{
1339 switch (budget_ci->budget.dev->pci->subsystem_device) {
1340 case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
1341 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001342 dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001344 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001345 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 break;
1347 }
1348 break;
1349
1350 case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
1351 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001352 dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001354 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 break;
1356 }
1357 break;
1358
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001359 case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
1360 budget_ci->tuner_pll_address = 0x61;
1361 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001362 dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001363 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001364 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001365 break;
1366 }
1367 break;
1368
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001370 budget_ci->tuner_pll_address = 0x63;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001372 dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001374 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1375 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 break;
1377 }
1378 break;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001379
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001380 case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001381 budget_ci->tuner_pll_address = 0x60;
1382 budget_ci->budget.dvb_frontend =
Oliver Endriss6c914492007-02-02 19:12:53 -03001383 dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001384 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001385 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1386 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001387 break;
1388 }
1389 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001390
1391 case 0x1017: // TT S-1500 PCI
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001392 budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001393 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001394 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001395 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
1396
Patrick Boettcherdea74862006-05-14 05:01:31 -03001397 budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001398 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 -03001399 printk("%s: No LNBP21 found!\n", __func__);
Andrew de Quincey2b100e72006-08-08 09:10:11 -03001400 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001401 budget_ci->budget.dvb_frontend = NULL;
1402 }
1403 }
Sigmund Augdal11417da2008-06-15 17:25:46 -03001404 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001405
Sigmund Augdal11417da2008-06-15 17:25:46 -03001406 case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */
1407 budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48);
1408 if (budget_ci->budget.dvb_frontend) {
klaas de waalcf47d872009-03-25 17:53:02 -03001409 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 -03001410 printk(KERN_ERR "%s: No tda827x found!\n", __func__);
1411 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1412 budget_ci->budget.dvb_frontend = NULL;
1413 }
1414 }
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001415 break;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001416
1417 case 0x1019: // TT S2-3200 PCI
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001418 /*
1419 * NOTE! on some STB0899 versions, the internal PLL takes a longer time
1420 * to settle, aka LOCK. On the older revisions of the chip, we don't see
1421 * this, as a result on the newer chips the entire clock tree, will not
1422 * be stable after a freshly POWER 'ed up situation.
1423 * In this case, we should RESET the STB0899 (Active LOW) and wait for
1424 * PLL stabilization.
1425 *
1426 * On the TT S2 3200 and clones, the STB0899 demodulator's RESETB is
1427 * connected to the SAA7146 GPIO, GPIO2, Pin 142
1428 */
1429 /* Reset Demodulator */
Manu Abraham0867f572007-10-15 13:07:16 -03001430 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001431 /* Wait for everything to die */
1432 msleep(50);
1433 /* Pull it up out of Reset state */
Manu Abraham0867f572007-10-15 13:07:16 -03001434 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001435 /* Wait for PLL to stabilize */
1436 msleep(250);
1437 /*
1438 * PLL state should be stable now. Ideally, we should check
1439 * for PLL LOCK status. But well, never mind!
1440 */
Manu Abrahamae9902d2007-10-08 18:51:54 -03001441 budget_ci->budget.dvb_frontend = dvb_attach(stb0899_attach, &tt3200_config, &budget_ci->budget.i2c_adap);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001442 if (budget_ci->budget.dvb_frontend) {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001443 if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {
1444 if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
Harvey Harrison9b4778f2009-01-07 14:42:41 -08001445 printk("%s: No LNBP21 found!\n", __func__);
Manu Abrahamae9902d2007-10-08 18:51:54 -03001446 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001447 budget_ci->budget.dvb_frontend = NULL;
1448 }
1449 } else {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001450 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1451 budget_ci->budget.dvb_frontend = NULL;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001452 }
1453 }
1454 break;
1455
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 }
1457
1458 if (budget_ci->budget.dvb_frontend == NULL) {
Bjorn Helgaas29e66a62008-09-04 17:24:51 -03001459 printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 budget_ci->budget.dev->pci->vendor,
1461 budget_ci->budget.dev->pci->device,
1462 budget_ci->budget.dev->pci->subsystem_vendor,
1463 budget_ci->budget.dev->pci->subsystem_device);
1464 } else {
1465 if (dvb_register_frontend
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001466 (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 printk("budget-ci: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001468 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 budget_ci->budget.dvb_frontend = NULL;
1470 }
1471 }
1472}
1473
1474static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
1475{
1476 struct budget_ci *budget_ci;
1477 int err;
1478
David Hardemanee579bc2006-12-02 21:16:05 -02001479 budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
David Hardeman8cc532e2006-12-02 21:16:05 -02001480 if (!budget_ci) {
1481 err = -ENOMEM;
1482 goto out1;
1483 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484
1485 dprintk(2, "budget_ci: %p\n", budget_ci);
1486
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 dev->ext_priv = budget_ci;
1488
Janne Grunau26dc4d02008-09-21 20:50:11 -03001489 err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE,
1490 adapter_nr);
David Hardeman8cc532e2006-12-02 21:16:05 -02001491 if (err)
1492 goto out2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493
David Hardeman8cc532e2006-12-02 21:16:05 -02001494 err = msp430_ir_init(budget_ci);
1495 if (err)
1496 goto out3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497
1498 ciintf_init(budget_ci);
1499
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001500 budget_ci->budget.dvb_adapter.priv = budget_ci;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 frontend_init(budget_ci);
1502
Oliver Endriss32e4c3a2006-07-18 22:55:23 -03001503 ttpci_budget_init_hooks(&budget_ci->budget);
1504
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 return 0;
David Hardeman8cc532e2006-12-02 21:16:05 -02001506
1507out3:
1508 ttpci_budget_deinit(&budget_ci->budget);
1509out2:
1510 kfree(budget_ci);
1511out1:
1512 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513}
1514
1515static int budget_ci_detach(struct saa7146_dev *dev)
1516{
1517 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
1518 struct saa7146_dev *saa = budget_ci->budget.dev;
1519 int err;
1520
1521 if (budget_ci->budget.ci_present)
1522 ciintf_deinit(budget_ci);
David Hardeman8cc532e2006-12-02 21:16:05 -02001523 msp430_ir_deinit(budget_ci);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001524 if (budget_ci->budget.dvb_frontend) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001526 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001527 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 err = ttpci_budget_deinit(&budget_ci->budget);
1529
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 // disable frontend and CI interface
1531 saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
1532
1533 kfree(budget_ci);
1534
1535 return err;
1536}
1537
1538static struct saa7146_extension budget_extension;
1539
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001540MAKE_BUDGET_INFO(ttbs2, "TT-Budget/S-1500 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
1542MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001543MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001544MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
Sigmund Augdal11417da2008-06-15 17:25:46 -03001545MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001546MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547
1548static struct pci_device_id pci_tbl[] = {
1549 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
1550 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001551 MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001553 MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001554 MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
Sigmund Augdal11417da2008-06-15 17:25:46 -03001555 MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001556 MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 {
1558 .vendor = 0,
1559 }
1560};
1561
1562MODULE_DEVICE_TABLE(pci, pci_tbl);
1563
1564static struct saa7146_extension budget_extension = {
Dave Jones0e367a12006-08-07 13:18:56 -03001565 .name = "budget_ci dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03001566 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567
1568 .module = THIS_MODULE,
1569 .pci_tbl = &pci_tbl[0],
1570 .attach = budget_ci_attach,
1571 .detach = budget_ci_detach,
1572
1573 .irq_mask = MASK_03 | MASK_06 | MASK_10,
1574 .irq_func = budget_ci_irq,
1575};
1576
1577static int __init budget_ci_init(void)
1578{
1579 return saa7146_register_extension(&budget_extension);
1580}
1581
1582static void __exit budget_ci_exit(void)
1583{
1584 saa7146_unregister_extension(&budget_extension);
1585}
1586
1587module_init(budget_ci_init);
1588module_exit(budget_ci_exit);
1589
1590MODULE_LICENSE("GPL");
1591MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
1592MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1593 "budget PCI DVB cards w/ CI-module produced by "
1594 "Siemens, Technotrend, Hauppauge");