blob: b82756db5bd17aa2a870caf1fd4695777acbc3a4 [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 *
Justin P. Mattock631dd1a2010-10-18 11:03:14 +020029 * the project's page is at http://www.linuxtv.org/
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 */
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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/spinlock.h>
Mauro Carvalho Chehab6bda9642010-11-17 13:28:38 -030037#include <media/rc-core.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
Trent Piepho68277092007-01-30 23:25:46 -030039#include "budget.h"
40
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include "dvb_ca_en50221.h"
42#include "stv0299.h"
Andrew de Quinceydc27a162005-09-09 13:03:07 -070043#include "stv0297.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include "tda1004x.h"
Marko Schluessler9e0dc662008-10-23 18:16:40 -030045#include "stb0899_drv.h"
46#include "stb0899_reg.h"
Manu Abraham8be969b2008-01-25 18:20:48 -030047#include "stb0899_cfg.h"
Marko Schluessler9e0dc662008-10-23 18:16:40 -030048#include "stb6100.h"
Manu Abraham8be969b2008-01-25 18:20:48 -030049#include "stb6100_cfg.h"
Perceval Anichini8cc2e372006-02-28 09:52:44 -030050#include "lnbp21.h"
51#include "bsbe1.h"
Perceval Anichini265366e2006-03-16 11:22:47 -030052#include "bsru6.h"
Sigmund Augdal11417da2008-06-15 17:25:46 -030053#include "tda1002x.h"
54#include "tda827x.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
Mauro Carvalho Chehab727e6252010-03-12 21:18:14 -030056#define MODULE_NAME "budget_ci"
57
David Härdemanecba77f2006-10-27 20:56:51 -030058/*
59 * Regarding DEBIADDR_IR:
60 * Some CI modules hang if random addresses are read.
61 * Using address 0x4000 for the IR read means that we
62 * use the same address as for CI version, which should
63 * be a safe default.
64 */
65#define DEBIADDR_IR 0x4000
Linus Torvalds1da177e2005-04-16 15:20:36 -070066#define DEBIADDR_CICONTROL 0x0000
67#define DEBIADDR_CIVERSION 0x4000
68#define DEBIADDR_IO 0x1000
69#define DEBIADDR_ATTR 0x3000
70
71#define CICONTROL_RESET 0x01
72#define CICONTROL_ENABLETS 0x02
73#define CICONTROL_CAMDETECT 0x08
74
75#define DEBICICTL 0x00420000
76#define DEBICICAM 0x02420000
77
78#define SLOTSTATUS_NONE 1
79#define SLOTSTATUS_PRESENT 2
80#define SLOTSTATUS_RESET 4
81#define SLOTSTATUS_READY 8
82#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
83
David Hardeman64741b72006-12-02 21:16:05 -020084/* RC5 device wildcard */
85#define IR_DEVICE_ANY 255
86
David Hardeman64741b72006-12-02 21:16:05 -020087static int rc5_device = -1;
88module_param(rc5_device, int, 0644);
89MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
90
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030091static int ir_debug;
David Hardemanb5471a22006-12-02 21:16:05 -020092module_param(ir_debug, int, 0644);
93MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
94
Janne Grunau26dc4d02008-09-21 20:50:11 -030095DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
96
David Hardemandd2f3982006-12-02 21:16:05 -020097struct budget_ci_ir {
David Härdemand8b4b582010-10-29 16:08:23 -030098 struct rc_dev *dev;
David Hardemandd2f3982006-12-02 21:16:05 -020099 struct tasklet_struct msp430_irq_tasklet;
100 char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
David Hardeman5cc8ae02006-12-02 21:16:05 -0200101 char phys[32];
David Hardeman64741b72006-12-02 21:16:05 -0200102 int rc5_device;
David Härdeman145859c2007-04-27 12:31:22 -0300103 u32 ir_key;
104 bool have_command;
David Hardemandd2f3982006-12-02 21:16:05 -0200105};
106
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107struct budget_ci {
108 struct budget budget;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 struct tasklet_struct ciintf_irq_tasklet;
110 int slot_status;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300111 int ci_irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 struct dvb_ca_en50221 ca;
David Hardemandd2f3982006-12-02 21:16:05 -0200113 struct budget_ci_ir ir;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700114 u8 tuner_pll_address; /* used for philips_tdm1316l configs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115};
116
David Hardeman2520fff2006-12-02 21:16:05 -0200117static void msp430_ir_interrupt(unsigned long data)
118{
119 struct budget_ci *budget_ci = (struct budget_ci *) data;
David Härdemand8b4b582010-10-29 16:08:23 -0300120 struct rc_dev *dev = budget_ci->ir.dev;
David Hardeman2520fff2006-12-02 21:16:05 -0200121 u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
122
David Hardeman64741b72006-12-02 21:16:05 -0200123 /*
124 * The msp430 chip can generate two different bytes, command and device
125 *
126 * type1: X1CCCCCC, C = command bits (0 - 63)
127 * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
128 *
David Härdeman59327a42007-02-13 09:39:58 -0300129 * Each signal from the remote control can generate one or more command
130 * bytes and one or more device bytes. For the repeated bytes, the
131 * highest bit (X) is set. The first command byte is always generated
132 * before the first device byte. Other than that, no specific order
David Härdeman145859c2007-04-27 12:31:22 -0300133 * seems to apply. To make life interesting, bytes can also be lost.
David Härdeman59327a42007-02-13 09:39:58 -0300134 *
135 * Only when we have a command and device byte, a keypress is
136 * generated.
David Hardeman64741b72006-12-02 21:16:05 -0200137 */
138
David Härdeman59327a42007-02-13 09:39:58 -0300139 if (ir_debug)
140 printk("budget_ci: received byte 0x%02x\n", command);
141
David Härdeman145859c2007-04-27 12:31:22 -0300142 /* Remove repeat bit, we use every command */
143 command = command & 0x7f;
David Härdeman59327a42007-02-13 09:39:58 -0300144
David Hardeman64741b72006-12-02 21:16:05 -0200145 /* Is this a RC5 command byte? */
David Hardeman2520fff2006-12-02 21:16:05 -0200146 if (command & 0x40) {
David Härdeman145859c2007-04-27 12:31:22 -0300147 budget_ci->ir.have_command = true;
148 budget_ci->ir.ir_key = command & 0x3f;
David Hardeman64741b72006-12-02 21:16:05 -0200149 return;
David Hardeman2520fff2006-12-02 21:16:05 -0200150 }
David Hardeman64741b72006-12-02 21:16:05 -0200151
152 /* It's a RC5 device byte */
David Härdeman145859c2007-04-27 12:31:22 -0300153 if (!budget_ci->ir.have_command)
David Härdeman59327a42007-02-13 09:39:58 -0300154 return;
David Härdeman145859c2007-04-27 12:31:22 -0300155 budget_ci->ir.have_command = false;
David Hardeman64741b72006-12-02 21:16:05 -0200156
David Härdeman13c24492010-04-02 15:58:30 -0300157 /* FIXME: We should generate complete scancodes with device info */
David Härdeman145859c2007-04-27 12:31:22 -0300158 if (budget_ci->ir.rc5_device != IR_DEVICE_ANY &&
159 budget_ci->ir.rc5_device != (command & 0x1f))
David Hardeman64741b72006-12-02 21:16:05 -0200160 return;
161
Mauro Carvalho Chehabca866742010-11-17 13:53:11 -0300162 rc_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0);
David Hardeman2520fff2006-12-02 21:16:05 -0200163}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165static int msp430_ir_init(struct budget_ci *budget_ci)
166{
167 struct saa7146_dev *saa = budget_ci->budget.dev;
David Härdemand8b4b582010-10-29 16:08:23 -0300168 struct rc_dev *dev;
David Hardeman8cc532e2006-12-02 21:16:05 -0200169 int error;
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300170
David Härdemand8b4b582010-10-29 16:08:23 -0300171 dev = rc_allocate_device();
172 if (!dev) {
David Hardemanee579bc2006-12-02 21:16:05 -0200173 printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300174 return -ENOMEM;
David Hardeman8cc532e2006-12-02 21:16:05 -0200175 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176
David Hardemandd2f3982006-12-02 21:16:05 -0200177 snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
178 "Budget-CI dvb ir receiver %s", saa->name);
David Hardeman5cc8ae02006-12-02 21:16:05 -0200179 snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
180 "pci-%s/ir0", pci_name(saa->pci));
181
David Härdemand8b4b582010-10-29 16:08:23 -0300182 dev->driver_name = MODULE_NAME;
183 dev->input_name = budget_ci->ir.name;
184 dev->input_phys = budget_ci->ir.phys;
185 dev->input_id.bustype = BUS_PCI;
186 dev->input_id.version = 1;
David Henningsson730726a2010-12-27 15:41:58 -0300187 dev->scanmask = 0xff;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200188 if (saa->pci->subsystem_vendor) {
David Härdemand8b4b582010-10-29 16:08:23 -0300189 dev->input_id.vendor = saa->pci->subsystem_vendor;
190 dev->input_id.product = saa->pci->subsystem_device;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200191 } else {
David Härdemand8b4b582010-10-29 16:08:23 -0300192 dev->input_id.vendor = saa->pci->vendor;
193 dev->input_id.product = saa->pci->device;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200194 }
David Härdemand8b4b582010-10-29 16:08:23 -0300195 dev->dev.parent = &saa->pci->dev;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200196
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300197 if (rc5_device < 0)
198 budget_ci->ir.rc5_device = IR_DEVICE_ANY;
199 else
200 budget_ci->ir.rc5_device = rc5_device;
201
David Hardeman64741b72006-12-02 21:16:05 -0200202 /* Select keymap and address */
David Hardeman2520fff2006-12-02 21:16:05 -0200203 switch (budget_ci->budget.dev->pci->subsystem_device) {
204 case 0x100c:
205 case 0x100f:
David Hardeman2520fff2006-12-02 21:16:05 -0200206 case 0x1011:
207 case 0x1012:
David Hardeman2520fff2006-12-02 21:16:05 -0200208 /* The hauppauge keymap is a superset of these remotes */
David Härdemand8b4b582010-10-29 16:08:23 -0300209 dev->map_name = RC_MAP_HAUPPAUGE_NEW;
David Hardeman64741b72006-12-02 21:16:05 -0200210
211 if (rc5_device < 0)
212 budget_ci->ir.rc5_device = 0x1f;
David Hardeman2520fff2006-12-02 21:16:05 -0200213 break;
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300214 case 0x1010:
Oliver Endrissf64899c2007-09-17 22:17:12 -0300215 case 0x1017:
Hermann Gaustererf137f9d2010-05-18 04:26:17 -0300216 case 0x1019:
Oliver Endrissbbfc4c22008-06-19 23:36:45 -0300217 case 0x101a:
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300218 /* for the Technotrend 1500 bundled remote */
David Härdemand8b4b582010-10-29 16:08:23 -0300219 dev->map_name = RC_MAP_TT_1500;
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300220 break;
David Hardeman2520fff2006-12-02 21:16:05 -0200221 default:
222 /* unknown remote */
David Härdemand8b4b582010-10-29 16:08:23 -0300223 dev->map_name = RC_MAP_BUDGET_CI_OLD;
David Hardeman2520fff2006-12-02 21:16:05 -0200224 break;
225 }
226
David Härdemand8b4b582010-10-29 16:08:23 -0300227 error = rc_register_device(dev);
David Hardeman8cc532e2006-12-02 21:16:05 -0200228 if (error) {
229 printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
David Härdemand8b4b582010-10-29 16:08:23 -0300230 rc_free_device(dev);
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300231 return error;
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300232 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233
David Härdemand8b4b582010-10-29 16:08:23 -0300234 budget_ci->ir.dev = dev;
David Härdeman145859c2007-04-27 12:31:22 -0300235
David Hardeman8cc532e2006-12-02 21:16:05 -0200236 tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
237 (unsigned long) budget_ci);
238
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300239 SAA7146_IER_ENABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
241
242 return 0;
243}
244
245static void msp430_ir_deinit(struct budget_ci *budget_ci)
246{
247 struct saa7146_dev *saa = budget_ci->budget.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300249 SAA7146_IER_DISABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
David Hardeman8cc532e2006-12-02 21:16:05 -0200251 tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
David Härdemand8b4b582010-10-29 16:08:23 -0300253 rc_unregister_device(budget_ci->ir.dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254}
255
256static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
257{
258 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
259
260 if (slot != 0)
261 return -EINVAL;
262
263 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
264 DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);
265}
266
267static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
268{
269 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
270
271 if (slot != 0)
272 return -EINVAL;
273
274 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
275 DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);
276}
277
278static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
279{
280 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
281
282 if (slot != 0)
283 return -EINVAL;
284
285 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
286 DEBIADDR_IO | (address & 3), 1, 1, 0);
287}
288
289static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
290{
291 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
292
293 if (slot != 0)
294 return -EINVAL;
295
296 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
297 DEBIADDR_IO | (address & 3), 1, value, 1, 0);
298}
299
300static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
301{
302 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
303 struct saa7146_dev *saa = budget_ci->budget.dev;
304
305 if (slot != 0)
306 return -EINVAL;
307
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300308 if (budget_ci->ci_irq) {
309 // trigger on RISING edge during reset so we know when READY is re-asserted
310 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
311 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 budget_ci->slot_status = SLOTSTATUS_RESET;
313 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
314 msleep(1);
315 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
316 CICONTROL_RESET, 1, 0);
317
318 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
319 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
320 return 0;
321}
322
323static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
324{
325 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
326 struct saa7146_dev *saa = budget_ci->budget.dev;
327
328 if (slot != 0)
329 return -EINVAL;
330
331 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
332 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
333 return 0;
334}
335
336static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
337{
338 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
339 struct saa7146_dev *saa = budget_ci->budget.dev;
340 int tmp;
341
342 if (slot != 0)
343 return -EINVAL;
344
345 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
346
347 tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
348 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
349 tmp | CICONTROL_ENABLETS, 1, 0);
350
351 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
352 return 0;
353}
354
355static void ciintf_interrupt(unsigned long data)
356{
357 struct budget_ci *budget_ci = (struct budget_ci *) data;
358 struct saa7146_dev *saa = budget_ci->budget.dev;
359 unsigned int flags;
360
361 // ensure we don't get spurious IRQs during initialisation
362 if (!budget_ci->budget.ci_present)
363 return;
364
365 // read the CAM status
366 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
367 if (flags & CICONTROL_CAMDETECT) {
368
369 // GPIO should be set to trigger on falling edge if a CAM is present
370 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
371
372 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
373 // CAM insertion IRQ
374 budget_ci->slot_status = SLOTSTATUS_PRESENT;
375 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
376 DVB_CA_EN50221_CAMCHANGE_INSERTED);
377
378 } else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
379 // CAM ready (reset completed)
380 budget_ci->slot_status = SLOTSTATUS_READY;
381 dvb_ca_en50221_camready_irq(&budget_ci->ca, 0);
382
383 } else if (budget_ci->slot_status & SLOTSTATUS_READY) {
384 // FR/DA IRQ
385 dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);
386 }
387 } else {
388
389 // trigger on rising edge if a CAM is not present - when a CAM is inserted, we
390 // only want to get the IRQ when it sets READY. If we trigger on the falling edge,
391 // the CAM might not actually be ready yet.
392 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
393
394 // generate a CAM removal IRQ if we haven't already
395 if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
396 // CAM removal IRQ
397 budget_ci->slot_status = SLOTSTATUS_NONE;
398 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
399 DVB_CA_EN50221_CAMCHANGE_REMOVED);
400 }
401 }
402}
403
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300404static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
405{
406 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
407 unsigned int flags;
408
409 // ensure we don't get spurious IRQs during initialisation
410 if (!budget_ci->budget.ci_present)
411 return -EINVAL;
412
413 // read the CAM status
414 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
415 if (flags & CICONTROL_CAMDETECT) {
416 // mark it as present if it wasn't before
417 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
418 budget_ci->slot_status = SLOTSTATUS_PRESENT;
419 }
420
421 // during a RESET, we check if we can read from IO memory to see when CAM is ready
422 if (budget_ci->slot_status & SLOTSTATUS_RESET) {
423 if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
424 budget_ci->slot_status = SLOTSTATUS_READY;
425 }
426 }
427 } else {
428 budget_ci->slot_status = SLOTSTATUS_NONE;
429 }
430
431 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
432 if (budget_ci->slot_status & SLOTSTATUS_READY) {
433 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
434 }
435 return DVB_CA_EN50221_POLL_CAM_PRESENT;
436 }
437
438 return 0;
439}
440
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441static int ciintf_init(struct budget_ci *budget_ci)
442{
443 struct saa7146_dev *saa = budget_ci->budget.dev;
444 int flags;
445 int result;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300446 int ci_version;
447 int ca_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448
449 memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
450
451 // enable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300452 saa7146_write(saa, MC1, MASK_27 | MASK_11);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453
454 // test if it is there
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300455 ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
456 if ((ci_version & 0xa0) != 0xa0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 result = -ENODEV;
458 goto error;
459 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300460
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 // determine whether a CAM is present or not
462 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
463 budget_ci->slot_status = SLOTSTATUS_NONE;
464 if (flags & CICONTROL_CAMDETECT)
465 budget_ci->slot_status = SLOTSTATUS_PRESENT;
466
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300467 // version 0xa2 of the CI firmware doesn't generate interrupts
468 if (ci_version == 0xa2) {
469 ca_flags = 0;
470 budget_ci->ci_irq = 0;
471 } else {
472 ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
473 DVB_CA_EN50221_FLAG_IRQ_FR |
474 DVB_CA_EN50221_FLAG_IRQ_DA;
475 budget_ci->ci_irq = 1;
476 }
477
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 // register CI interface
479 budget_ci->ca.owner = THIS_MODULE;
480 budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
481 budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
482 budget_ci->ca.read_cam_control = ciintf_read_cam_control;
483 budget_ci->ca.write_cam_control = ciintf_write_cam_control;
484 budget_ci->ca.slot_reset = ciintf_slot_reset;
485 budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
486 budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300487 budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 budget_ci->ca.data = budget_ci;
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700489 if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 &budget_ci->ca,
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300491 ca_flags, 1)) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 printk("budget_ci: CI interface detected, but initialisation failed.\n");
493 goto error;
494 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300495
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 // Setup CI slot IRQ
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300497 if (budget_ci->ci_irq) {
498 tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
499 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
500 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
501 } else {
502 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
503 }
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300504 SAA7146_IER_ENABLE(saa, MASK_03);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300506
507 // enable interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
509 CICONTROL_RESET, 1, 0);
510
511 // success!
512 printk("budget_ci: CI interface initialised\n");
513 budget_ci->budget.ci_present = 1;
514
515 // forge a fake CI IRQ so the CAM state is setup correctly
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300516 if (budget_ci->ci_irq) {
517 flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
518 if (budget_ci->slot_status != SLOTSTATUS_NONE)
519 flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
520 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
521 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522
523 return 0;
524
525error:
Hartmut Birr2a893de2006-12-03 21:08:08 -0300526 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 return result;
528}
529
530static void ciintf_deinit(struct budget_ci *budget_ci)
531{
532 struct saa7146_dev *saa = budget_ci->budget.dev;
533
534 // disable CI interrupts
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300535 if (budget_ci->ci_irq) {
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300536 SAA7146_IER_DISABLE(saa, MASK_03);
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300537 saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
538 tasklet_kill(&budget_ci->ciintf_irq_tasklet);
539 }
540
541 // reset interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
543 msleep(1);
544 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
545 CICONTROL_RESET, 1, 0);
546
547 // disable TS data stream to CI interface
548 saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
549
550 // release the CA device
551 dvb_ca_en50221_release(&budget_ci->ca);
552
553 // disable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300554 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555}
556
557static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
558{
559 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
560
561 dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
562
563 if (*isr & MASK_06)
David Hardemandd2f3982006-12-02 21:16:05 -0200564 tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
566 if (*isr & MASK_10)
567 ttpci_budget_irq10_handler(dev, isr);
568
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300569 if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
571}
572
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573static u8 philips_su1278_tt_inittab[] = {
574 0x01, 0x0f,
575 0x02, 0x30,
576 0x03, 0x00,
577 0x04, 0x5b,
578 0x05, 0x85,
579 0x06, 0x02,
580 0x07, 0x00,
581 0x08, 0x02,
582 0x09, 0x00,
583 0x0C, 0x01,
584 0x0D, 0x81,
585 0x0E, 0x44,
586 0x0f, 0x14,
587 0x10, 0x3c,
588 0x11, 0x84,
589 0x12, 0xda,
590 0x13, 0x97,
591 0x14, 0x95,
592 0x15, 0xc9,
593 0x16, 0x19,
594 0x17, 0x8c,
595 0x18, 0x59,
596 0x19, 0xf8,
597 0x1a, 0xfe,
598 0x1c, 0x7f,
599 0x1d, 0x00,
600 0x1e, 0x00,
601 0x1f, 0x50,
602 0x20, 0x00,
603 0x21, 0x00,
604 0x22, 0x00,
605 0x23, 0x00,
606 0x28, 0x00,
607 0x29, 0x28,
608 0x2a, 0x14,
609 0x2b, 0x0f,
610 0x2c, 0x09,
611 0x2d, 0x09,
612 0x31, 0x1f,
613 0x32, 0x19,
614 0x33, 0xfc,
615 0x34, 0x93,
616 0xff, 0xff
617};
618
619static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
620{
621 stv0299_writereg(fe, 0x0e, 0x44);
622 if (srate >= 10000000) {
623 stv0299_writereg(fe, 0x13, 0x97);
624 stv0299_writereg(fe, 0x14, 0x95);
625 stv0299_writereg(fe, 0x15, 0xc9);
626 stv0299_writereg(fe, 0x17, 0x8c);
627 stv0299_writereg(fe, 0x1a, 0xfe);
628 stv0299_writereg(fe, 0x1c, 0x7f);
629 stv0299_writereg(fe, 0x2d, 0x09);
630 } else {
631 stv0299_writereg(fe, 0x13, 0x99);
632 stv0299_writereg(fe, 0x14, 0x8d);
633 stv0299_writereg(fe, 0x15, 0xce);
634 stv0299_writereg(fe, 0x17, 0x43);
635 stv0299_writereg(fe, 0x1a, 0x1d);
636 stv0299_writereg(fe, 0x1c, 0x12);
637 stv0299_writereg(fe, 0x2d, 0x05);
638 }
639 stv0299_writereg(fe, 0x0e, 0x23);
640 stv0299_writereg(fe, 0x0f, 0x94);
641 stv0299_writereg(fe, 0x10, 0x39);
642 stv0299_writereg(fe, 0x15, 0xc9);
643
644 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
645 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
646 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
647
648 return 0;
649}
650
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300651static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,
652 struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653{
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300654 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 u32 div;
656 u8 buf[4];
657 struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
658
659 if ((params->frequency < 950000) || (params->frequency > 2150000))
660 return -EINVAL;
661
662 div = (params->frequency + (500 - 1)) / 500; // round correctly
663 buf[0] = (div >> 8) & 0x7f;
664 buf[1] = div & 0xff;
665 buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
666 buf[3] = 0x20;
667
668 if (params->u.qpsk.symbol_rate < 4000000)
669 buf[3] |= 1;
670
671 if (params->frequency < 1250000)
672 buf[3] |= 0;
673 else if (params->frequency < 1550000)
674 buf[3] |= 0x40;
675 else if (params->frequency < 2050000)
676 buf[3] |= 0x80;
677 else if (params->frequency < 2150000)
678 buf[3] |= 0xC0;
679
Patrick Boettcherdea74862006-05-14 05:01:31 -0300680 if (fe->ops.i2c_gate_ctrl)
681 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300682 if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 return -EIO;
684 return 0;
685}
686
687static struct stv0299_config philips_su1278_tt_config = {
688
689 .demod_address = 0x68,
690 .inittab = philips_su1278_tt_inittab,
691 .mclk = 64000000UL,
692 .invert = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 .skip_reinit = 1,
Oliver Endrissda2c7f62008-04-20 22:13:37 -0300694 .lock_output = STV0299_LOCKOUTPUT_1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 .volt13_op0_op1 = STV0299_VOLT13_OP1,
696 .min_delay_ms = 50,
697 .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698};
699
700
701
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300702static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703{
704 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
705 static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
706 static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700707 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 sizeof(td1316_init) };
709
710 // setup PLL configuration
Patrick Boettcherdea74862006-05-14 05:01:31 -0300711 if (fe->ops.i2c_gate_ctrl)
712 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
714 return -EIO;
715 msleep(1);
716
717 // disable the mc44BC374c (do not check for errors)
718 tuner_msg.addr = 0x65;
719 tuner_msg.buf = disable_mc44BC374c;
720 tuner_msg.len = sizeof(disable_mc44BC374c);
Patrick Boettcherdea74862006-05-14 05:01:31 -0300721 if (fe->ops.i2c_gate_ctrl)
722 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
Patrick Boettcherdea74862006-05-14 05:01:31 -0300724 if (fe->ops.i2c_gate_ctrl)
725 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
727 }
728
729 return 0;
730}
731
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300732static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733{
734 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
735 u8 tuner_buf[4];
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700736 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 -0700737 int tuner_frequency = 0;
738 u8 band, cp, filter;
739
740 // determine charge pump
741 tuner_frequency = params->frequency + 36130000;
742 if (tuner_frequency < 87000000)
743 return -EINVAL;
744 else if (tuner_frequency < 130000000)
745 cp = 3;
746 else if (tuner_frequency < 160000000)
747 cp = 5;
748 else if (tuner_frequency < 200000000)
749 cp = 6;
750 else if (tuner_frequency < 290000000)
751 cp = 3;
752 else if (tuner_frequency < 420000000)
753 cp = 5;
754 else if (tuner_frequency < 480000000)
755 cp = 6;
756 else if (tuner_frequency < 620000000)
757 cp = 3;
758 else if (tuner_frequency < 830000000)
759 cp = 5;
760 else if (tuner_frequency < 895000000)
761 cp = 7;
762 else
763 return -EINVAL;
764
765 // determine band
766 if (params->frequency < 49000000)
767 return -EINVAL;
768 else if (params->frequency < 159000000)
769 band = 1;
770 else if (params->frequency < 444000000)
771 band = 2;
772 else if (params->frequency < 861000000)
773 band = 4;
774 else
775 return -EINVAL;
776
777 // setup PLL filter and TDA9889
778 switch (params->u.ofdm.bandwidth) {
779 case BANDWIDTH_6_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300780 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 filter = 0;
782 break;
783
784 case BANDWIDTH_7_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300785 tda1004x_writereg(fe, 0x0C, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 filter = 0;
787 break;
788
789 case BANDWIDTH_8_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300790 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 filter = 1;
792 break;
793
794 default:
795 return -EINVAL;
796 }
797
798 // calculate divisor
799 // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
800 tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
801
802 // setup tuner buffer
803 tuner_buf[0] = tuner_frequency >> 8;
804 tuner_buf[1] = tuner_frequency & 0xff;
805 tuner_buf[2] = 0xca;
806 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
807
Patrick Boettcherdea74862006-05-14 05:01:31 -0300808 if (fe->ops.i2c_gate_ctrl)
809 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
811 return -EIO;
812
813 msleep(1);
814 return 0;
815}
816
817static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,
818 const struct firmware **fw, char *name)
819{
820 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
821
822 return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);
823}
824
825static struct tda1004x_config philips_tdm1316l_config = {
826
827 .demod_address = 0x8,
828 .invert = 0,
829 .invert_oclk = 0,
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700830 .xtal_freq = TDA10046_XTAL_4M,
831 .agc_config = TDA10046_AGC_DEFAULT,
832 .if_freq = TDA10046_FREQ_3617,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 .request_firmware = philips_tdm1316l_request_firmware,
834};
835
Oliver Endriss6c914492007-02-02 19:12:53 -0300836static struct tda1004x_config philips_tdm1316l_config_invert = {
837
838 .demod_address = 0x8,
839 .invert = 1,
840 .invert_oclk = 0,
841 .xtal_freq = TDA10046_XTAL_4M,
842 .agc_config = TDA10046_AGC_DEFAULT,
843 .if_freq = TDA10046_FREQ_3617,
844 .request_firmware = philips_tdm1316l_request_firmware,
845};
846
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300847static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700848{
849 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
850 u8 tuner_buf[5];
851 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
852 .flags = 0,
853 .buf = tuner_buf,
854 .len = sizeof(tuner_buf) };
855 int tuner_frequency = 0;
856 u8 band, cp, filter;
857
858 // determine charge pump
859 tuner_frequency = params->frequency + 36125000;
860 if (tuner_frequency < 87000000)
861 return -EINVAL;
862 else if (tuner_frequency < 130000000) {
863 cp = 3;
864 band = 1;
865 } else if (tuner_frequency < 160000000) {
866 cp = 5;
867 band = 1;
868 } else if (tuner_frequency < 200000000) {
869 cp = 6;
Oliver Endriss910a7b62007-05-03 13:16:12 -0300870 band = 1;
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700871 } else if (tuner_frequency < 290000000) {
872 cp = 3;
873 band = 2;
874 } else if (tuner_frequency < 420000000) {
875 cp = 5;
876 band = 2;
877 } else if (tuner_frequency < 480000000) {
878 cp = 6;
879 band = 2;
880 } else if (tuner_frequency < 620000000) {
881 cp = 3;
882 band = 4;
883 } else if (tuner_frequency < 830000000) {
884 cp = 5;
885 band = 4;
886 } else if (tuner_frequency < 895000000) {
887 cp = 7;
888 band = 4;
889 } else
890 return -EINVAL;
891
892 // assume PLL filter should always be 8MHz for the moment.
893 filter = 1;
894
895 // calculate divisor
896 tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
897
898 // setup tuner buffer
899 tuner_buf[0] = tuner_frequency >> 8;
900 tuner_buf[1] = tuner_frequency & 0xff;
901 tuner_buf[2] = 0xc8;
902 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
903 tuner_buf[4] = 0x80;
904
Patrick Boettcherdea74862006-05-14 05:01:31 -0300905 if (fe->ops.i2c_gate_ctrl)
906 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700907 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
908 return -EIO;
909
910 msleep(50);
911
Patrick Boettcherdea74862006-05-14 05:01:31 -0300912 if (fe->ops.i2c_gate_ctrl)
913 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700914 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
915 return -EIO;
916
917 msleep(1);
918
919 return 0;
920}
921
922static u8 dvbc_philips_tdm1316l_inittab[] = {
923 0x80, 0x01,
924 0x80, 0x00,
925 0x81, 0x01,
926 0x81, 0x00,
927 0x00, 0x09,
928 0x01, 0x69,
929 0x03, 0x00,
930 0x04, 0x00,
931 0x07, 0x00,
932 0x08, 0x00,
933 0x20, 0x00,
934 0x21, 0x40,
935 0x22, 0x00,
936 0x23, 0x00,
937 0x24, 0x40,
938 0x25, 0x88,
939 0x30, 0xff,
940 0x31, 0x00,
941 0x32, 0xff,
942 0x33, 0x00,
943 0x34, 0x50,
944 0x35, 0x7f,
945 0x36, 0x00,
946 0x37, 0x20,
947 0x38, 0x00,
948 0x40, 0x1c,
949 0x41, 0xff,
950 0x42, 0x29,
951 0x43, 0x20,
952 0x44, 0xff,
953 0x45, 0x00,
954 0x46, 0x00,
955 0x49, 0x04,
956 0x4a, 0x00,
957 0x4b, 0x7b,
958 0x52, 0x30,
959 0x55, 0xae,
960 0x56, 0x47,
961 0x57, 0xe1,
962 0x58, 0x3a,
963 0x5a, 0x1e,
964 0x5b, 0x34,
965 0x60, 0x00,
966 0x63, 0x00,
967 0x64, 0x00,
968 0x65, 0x00,
969 0x66, 0x00,
970 0x67, 0x00,
971 0x68, 0x00,
972 0x69, 0x00,
973 0x6a, 0x02,
974 0x6b, 0x00,
975 0x70, 0xff,
976 0x71, 0x00,
977 0x72, 0x00,
978 0x73, 0x00,
979 0x74, 0x0c,
980 0x80, 0x00,
981 0x81, 0x00,
982 0x82, 0x00,
983 0x83, 0x00,
984 0x84, 0x04,
985 0x85, 0x80,
986 0x86, 0x24,
987 0x87, 0x78,
988 0x88, 0x10,
989 0x89, 0x00,
990 0x90, 0x01,
991 0x91, 0x01,
992 0xa0, 0x04,
993 0xa1, 0x00,
994 0xa2, 0x00,
995 0xb0, 0x91,
996 0xb1, 0x0b,
997 0xc0, 0x53,
998 0xc1, 0x70,
999 0xc2, 0x12,
1000 0xd0, 0x00,
1001 0xd1, 0x00,
1002 0xd2, 0x00,
1003 0xd3, 0x00,
1004 0xd4, 0x00,
1005 0xd5, 0x00,
1006 0xde, 0x00,
1007 0xdf, 0x00,
1008 0x61, 0x38,
1009 0x62, 0x0a,
1010 0x53, 0x13,
1011 0x59, 0x08,
1012 0xff, 0xff,
1013};
1014
1015static struct stv0297_config dvbc_philips_tdm1316l_config = {
1016 .demod_address = 0x1c,
1017 .inittab = dvbc_philips_tdm1316l_inittab,
1018 .invert = 0,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001019 .stop_during_read = 1,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001020};
1021
Sigmund Augdal11417da2008-06-15 17:25:46 -03001022static struct tda10023_config tda10023_config = {
1023 .demod_address = 0xc,
1024 .invert = 0,
1025 .xtal = 16000000,
1026 .pll_m = 11,
1027 .pll_p = 3,
1028 .pll_n = 1,
1029 .deltaf = 0xa511,
1030};
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001031
klaas de waalcf47d872009-03-25 17:53:02 -03001032static struct tda827x_config tda827x_config = {
1033 .config = 0,
1034};
1035
Manu Abrahama55bc842008-10-23 18:32:50 -03001036/* TT S2-3200 DVB-S (STB0899) Inittab */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001037static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001039 { STB0899_DEV_ID , 0x81 },
1040 { STB0899_DISCNTRL1 , 0x32 },
1041 { STB0899_DISCNTRL2 , 0x80 },
1042 { STB0899_DISRX_ST0 , 0x04 },
1043 { STB0899_DISRX_ST1 , 0x00 },
1044 { STB0899_DISPARITY , 0x00 },
1045 { STB0899_DISFIFO , 0x00 },
1046 { STB0899_DISSTATUS , 0x20 },
1047 { STB0899_DISF22 , 0x8c },
1048 { STB0899_DISF22RX , 0x9a },
Manu Abrahamef3052b2008-10-23 18:45:17 -03001049 { STB0899_SYSREG , 0x0b },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001050 { STB0899_ACRPRESC , 0x11 },
1051 { STB0899_ACRDIV1 , 0x0a },
1052 { STB0899_ACRDIV2 , 0x05 },
1053 { STB0899_DACR1 , 0x00 },
1054 { STB0899_DACR2 , 0x00 },
1055 { STB0899_OUTCFG , 0x00 },
1056 { STB0899_MODECFG , 0x00 },
1057 { STB0899_IRQSTATUS_3 , 0x30 },
1058 { STB0899_IRQSTATUS_2 , 0x00 },
1059 { STB0899_IRQSTATUS_1 , 0x00 },
1060 { STB0899_IRQSTATUS_0 , 0x00 },
1061 { STB0899_IRQMSK_3 , 0xf3 },
1062 { STB0899_IRQMSK_2 , 0xfc },
1063 { STB0899_IRQMSK_1 , 0xff },
1064 { STB0899_IRQMSK_0 , 0xff },
1065 { STB0899_IRQCFG , 0x00 },
1066 { STB0899_I2CCFG , 0x88 },
Manu Abraham40e8ce32008-02-03 19:37:02 -03001067 { STB0899_I2CRPT , 0x48 }, /* 12k Pullup, Repeater=16, Stop=disabled */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001068 { STB0899_IOPVALUE5 , 0x00 },
1069 { STB0899_IOPVALUE4 , 0x20 },
1070 { STB0899_IOPVALUE3 , 0xc9 },
1071 { STB0899_IOPVALUE2 , 0x90 },
1072 { STB0899_IOPVALUE1 , 0x40 },
1073 { STB0899_IOPVALUE0 , 0x00 },
1074 { STB0899_GPIO00CFG , 0x82 },
1075 { STB0899_GPIO01CFG , 0x82 },
1076 { STB0899_GPIO02CFG , 0x82 },
1077 { STB0899_GPIO03CFG , 0x82 },
1078 { STB0899_GPIO04CFG , 0x82 },
1079 { STB0899_GPIO05CFG , 0x82 },
1080 { STB0899_GPIO06CFG , 0x82 },
1081 { STB0899_GPIO07CFG , 0x82 },
1082 { STB0899_GPIO08CFG , 0x82 },
1083 { STB0899_GPIO09CFG , 0x82 },
1084 { STB0899_GPIO10CFG , 0x82 },
1085 { STB0899_GPIO11CFG , 0x82 },
1086 { STB0899_GPIO12CFG , 0x82 },
1087 { STB0899_GPIO13CFG , 0x82 },
1088 { STB0899_GPIO14CFG , 0x82 },
1089 { STB0899_GPIO15CFG , 0x82 },
1090 { STB0899_GPIO16CFG , 0x82 },
1091 { STB0899_GPIO17CFG , 0x82 },
1092 { STB0899_GPIO18CFG , 0x82 },
1093 { STB0899_GPIO19CFG , 0x82 },
1094 { STB0899_GPIO20CFG , 0x82 },
1095 { STB0899_SDATCFG , 0xb8 },
1096 { STB0899_SCLTCFG , 0xba },
Manu Abrahama55bc842008-10-23 18:32:50 -03001097 { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */
1098 { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */
1099 { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001100 { STB0899_DIRCLKCFG , 0x82 },
1101 { STB0899_CLKOUT27CFG , 0x7e },
1102 { STB0899_STDBYCFG , 0x82 },
1103 { STB0899_CS0CFG , 0x82 },
1104 { STB0899_CS1CFG , 0x82 },
1105 { STB0899_DISEQCOCFG , 0x20 },
1106 { STB0899_GPIO32CFG , 0x82 },
1107 { STB0899_GPIO33CFG , 0x82 },
1108 { STB0899_GPIO34CFG , 0x82 },
1109 { STB0899_GPIO35CFG , 0x82 },
1110 { STB0899_GPIO36CFG , 0x82 },
1111 { STB0899_GPIO37CFG , 0x82 },
1112 { STB0899_GPIO38CFG , 0x82 },
1113 { STB0899_GPIO39CFG , 0x82 },
Manu Abrahamf2e52cd2007-11-19 16:44:47 -03001114 { STB0899_NCOARSE , 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
Manu Abrahama55bc842008-10-23 18:32:50 -03001115 { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001116 { STB0899_FILTCTRL , 0x00 },
1117 { STB0899_SYSCTRL , 0x00 },
1118 { STB0899_STOPCLK1 , 0x20 },
1119 { STB0899_STOPCLK2 , 0x00 },
1120 { STB0899_INTBUFSTATUS , 0x00 },
1121 { STB0899_INTBUFCTRL , 0x0a },
1122 { 0xffff , 0xff },
1123};
1124
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001125static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = {
1126 { STB0899_DEMOD , 0x00 },
1127 { STB0899_RCOMPC , 0xc9 },
1128 { STB0899_AGC1CN , 0x41 },
1129 { STB0899_AGC1REF , 0x10 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001130 { STB0899_RTC , 0x7a },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001131 { STB0899_TMGCFG , 0x4e },
1132 { STB0899_AGC2REF , 0x34 },
1133 { STB0899_TLSR , 0x84 },
1134 { STB0899_CFD , 0xc7 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001135 { STB0899_ACLC , 0x87 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001136 { STB0899_BCLC , 0x94 },
1137 { STB0899_EQON , 0x41 },
1138 { STB0899_LDT , 0xdd },
1139 { STB0899_LDT2 , 0xc9 },
1140 { STB0899_EQUALREF , 0xb4 },
1141 { STB0899_TMGRAMP , 0x10 },
1142 { STB0899_TMGTHD , 0x30 },
1143 { STB0899_IDCCOMP , 0xfb },
1144 { STB0899_QDCCOMP , 0x03 },
1145 { STB0899_POWERI , 0x3b },
1146 { STB0899_POWERQ , 0x3d },
1147 { STB0899_RCOMP , 0x81 },
1148 { STB0899_AGCIQIN , 0x80 },
1149 { STB0899_AGC2I1 , 0x04 },
1150 { STB0899_AGC2I2 , 0xf5 },
1151 { STB0899_TLIR , 0x25 },
1152 { STB0899_RTF , 0x80 },
1153 { STB0899_DSTATUS , 0x00 },
1154 { STB0899_LDI , 0xca },
1155 { STB0899_CFRM , 0xf1 },
1156 { STB0899_CFRL , 0xf3 },
1157 { STB0899_NIRM , 0x2a },
1158 { STB0899_NIRL , 0x05 },
1159 { STB0899_ISYMB , 0x17 },
1160 { STB0899_QSYMB , 0xfa },
1161 { STB0899_SFRH , 0x2f },
1162 { STB0899_SFRM , 0x68 },
1163 { STB0899_SFRL , 0x40 },
1164 { STB0899_SFRUPH , 0x2f },
1165 { STB0899_SFRUPM , 0x68 },
1166 { STB0899_SFRUPL , 0x40 },
1167 { STB0899_EQUAI1 , 0xfd },
1168 { STB0899_EQUAQ1 , 0x04 },
1169 { STB0899_EQUAI2 , 0x0f },
1170 { STB0899_EQUAQ2 , 0xff },
1171 { STB0899_EQUAI3 , 0xdf },
1172 { STB0899_EQUAQ3 , 0xfa },
1173 { STB0899_EQUAI4 , 0x37 },
1174 { STB0899_EQUAQ4 , 0x0d },
1175 { STB0899_EQUAI5 , 0xbd },
1176 { STB0899_EQUAQ5 , 0xf7 },
1177 { STB0899_DSTATUS2 , 0x00 },
1178 { STB0899_VSTATUS , 0x00 },
1179 { STB0899_VERROR , 0xff },
1180 { STB0899_IQSWAP , 0x2a },
1181 { STB0899_ECNT1M , 0x00 },
1182 { STB0899_ECNT1L , 0x00 },
1183 { STB0899_ECNT2M , 0x00 },
1184 { STB0899_ECNT2L , 0x00 },
1185 { STB0899_ECNT3M , 0x00 },
1186 { STB0899_ECNT3L , 0x00 },
1187 { STB0899_FECAUTO1 , 0x06 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001188 { STB0899_FECM , 0x01 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001189 { STB0899_VTH12 , 0xf0 },
1190 { STB0899_VTH23 , 0xa0 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001191 { STB0899_VTH34 , 0x78 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001192 { STB0899_VTH56 , 0x4e },
1193 { STB0899_VTH67 , 0x48 },
1194 { STB0899_VTH78 , 0x38 },
1195 { STB0899_PRVIT , 0xff },
1196 { STB0899_VITSYNC , 0x19 },
Manu Abrahama55bc842008-10-23 18:32:50 -03001197 { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001198 { STB0899_TSULC , 0x42 },
1199 { STB0899_RSLLC , 0x40 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001200 { STB0899_TSLPL , 0x12 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001201 { STB0899_TSCFGH , 0x0c },
1202 { STB0899_TSCFGM , 0x00 },
1203 { STB0899_TSCFGL , 0x0c },
Manu Abrahamc1426df2009-11-13 18:51:39 -03001204 { STB0899_TSOUT , 0x4d }, /* 0x0d for CAM */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001205 { STB0899_RSSYNCDEL , 0x00 },
1206 { STB0899_TSINHDELH , 0x02 },
1207 { STB0899_TSINHDELM , 0x00 },
1208 { STB0899_TSINHDELL , 0x00 },
1209 { STB0899_TSLLSTKM , 0x00 },
1210 { STB0899_TSLLSTKL , 0x00 },
1211 { STB0899_TSULSTKM , 0x00 },
1212 { STB0899_TSULSTKL , 0xab },
1213 { STB0899_PCKLENUL , 0x00 },
1214 { STB0899_PCKLENLL , 0xcc },
1215 { STB0899_RSPCKLEN , 0xcc },
1216 { STB0899_TSSTATUS , 0x80 },
1217 { STB0899_ERRCTRL1 , 0xb6 },
1218 { STB0899_ERRCTRL2 , 0x96 },
1219 { STB0899_ERRCTRL3 , 0x89 },
1220 { STB0899_DMONMSK1 , 0x27 },
1221 { STB0899_DMONMSK0 , 0x03 },
1222 { STB0899_DEMAPVIT , 0x5c },
1223 { STB0899_PLPARM , 0x1f },
1224 { STB0899_PDELCTRL , 0x48 },
1225 { STB0899_PDELCTRL2 , 0x00 },
1226 { STB0899_BBHCTRL1 , 0x00 },
1227 { STB0899_BBHCTRL2 , 0x00 },
1228 { STB0899_HYSTTHRESH , 0x77 },
1229 { STB0899_MATCSTM , 0x00 },
1230 { STB0899_MATCSTL , 0x00 },
1231 { STB0899_UPLCSTM , 0x00 },
1232 { STB0899_UPLCSTL , 0x00 },
1233 { STB0899_DFLCSTM , 0x00 },
1234 { STB0899_DFLCSTL , 0x00 },
1235 { STB0899_SYNCCST , 0x00 },
1236 { STB0899_SYNCDCSTM , 0x00 },
1237 { STB0899_SYNCDCSTL , 0x00 },
1238 { STB0899_ISI_ENTRY , 0x00 },
1239 { STB0899_ISI_BIT_EN , 0x00 },
1240 { STB0899_MATSTRM , 0x00 },
1241 { STB0899_MATSTRL , 0x00 },
1242 { STB0899_UPLSTRM , 0x00 },
1243 { STB0899_UPLSTRL , 0x00 },
1244 { STB0899_DFLSTRM , 0x00 },
1245 { STB0899_DFLSTRL , 0x00 },
1246 { STB0899_SYNCSTR , 0x00 },
1247 { STB0899_SYNCDSTRM , 0x00 },
1248 { STB0899_SYNCDSTRL , 0x00 },
1249 { STB0899_CFGPDELSTATUS1 , 0x10 },
1250 { STB0899_CFGPDELSTATUS2 , 0x00 },
1251 { STB0899_BBFERRORM , 0x00 },
1252 { STB0899_BBFERRORL , 0x00 },
1253 { STB0899_UPKTERRORM , 0x00 },
1254 { STB0899_UPKTERRORL , 0x00 },
1255 { 0xffff , 0xff },
1256};
1257
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001258static struct stb0899_config tt3200_config = {
1259 .init_dev = tt3200_stb0899_s1_init_1,
Manu Abraham8be969b2008-01-25 18:20:48 -03001260 .init_s2_demod = stb0899_s2_init_2,
Manu Abrahama55bc842008-10-23 18:32:50 -03001261 .init_s1_demod = tt3200_stb0899_s1_init_3,
Manu Abraham8be969b2008-01-25 18:20:48 -03001262 .init_s2_fec = stb0899_s2_init_4,
1263 .init_tst = stb0899_s1_init_5,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001264
Manu Abraham043a68b2008-01-18 14:15:17 -03001265 .postproc = NULL,
1266
Manu Abrahama55bc842008-10-23 18:32:50 -03001267 .demod_address = 0x68,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001268
1269 .xtal_freq = 27000000,
Manu Abrahame99d00c2007-09-25 17:48:59 -03001270 .inversion = IQ_SWAP_ON, /* 1 */
Manu Abrahama55bc842008-10-23 18:32:50 -03001271
Manu Abrahamb91a7cb2008-03-04 19:19:58 -03001272 .lo_clk = 76500000,
1273 .hi_clk = 99000000,
1274
Manu Abraham8be969b2008-01-25 18:20:48 -03001275 .esno_ave = STB0899_DVBS2_ESNO_AVE,
1276 .esno_quant = STB0899_DVBS2_ESNO_QUANT,
1277 .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
1278 .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
1279 .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
1280 .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
1281 .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
1282 .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
1283 .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
Manu Abrahama55bc842008-10-23 18:32:50 -03001284
Manu Abraham8be969b2008-01-25 18:20:48 -03001285 .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
1286 .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
1287 .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
1288 .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
Manu Abrahama55bc842008-10-23 18:32:50 -03001289
1290 .tuner_get_frequency = stb6100_get_frequency,
1291 .tuner_set_frequency = stb6100_set_frequency,
1292 .tuner_set_bandwidth = stb6100_set_bandwidth,
1293 .tuner_get_bandwidth = stb6100_get_bandwidth,
Manu Abraham043a68b2008-01-18 14:15:17 -03001294 .tuner_set_rfsiggain = NULL
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001295};
1296
Mauro Carvalho Chehabffbc5f82009-01-05 01:34:20 -03001297static struct stb6100_config tt3200_stb6100_config = {
Manu Abrahamc14eaed2007-10-04 16:52:51 -03001298 .tuner_address = 0x60,
1299 .refclock = 27000000,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001300};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301
1302static void frontend_init(struct budget_ci *budget_ci)
1303{
1304 switch (budget_ci->budget.dev->pci->subsystem_device) {
1305 case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
1306 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001307 dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001309 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001310 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 break;
1312 }
1313 break;
1314
1315 case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
1316 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001317 dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001319 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 break;
1321 }
1322 break;
1323
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001324 case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
1325 budget_ci->tuner_pll_address = 0x61;
1326 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001327 dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001328 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001329 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001330 break;
1331 }
1332 break;
1333
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001335 budget_ci->tuner_pll_address = 0x63;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001337 dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001339 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1340 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 break;
1342 }
1343 break;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001344
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001345 case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001346 budget_ci->tuner_pll_address = 0x60;
1347 budget_ci->budget.dvb_frontend =
Oliver Endriss6c914492007-02-02 19:12:53 -03001348 dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001349 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001350 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1351 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001352 break;
1353 }
1354 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001355
1356 case 0x1017: // TT S-1500 PCI
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001357 budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001358 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001359 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001360 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
1361
Patrick Boettcherdea74862006-05-14 05:01:31 -03001362 budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001363 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 -03001364 printk("%s: No LNBP21 found!\n", __func__);
Andrew de Quincey2b100e72006-08-08 09:10:11 -03001365 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001366 budget_ci->budget.dvb_frontend = NULL;
1367 }
1368 }
Sigmund Augdal11417da2008-06-15 17:25:46 -03001369 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001370
Sigmund Augdal11417da2008-06-15 17:25:46 -03001371 case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */
1372 budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48);
1373 if (budget_ci->budget.dvb_frontend) {
klaas de waalcf47d872009-03-25 17:53:02 -03001374 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 -03001375 printk(KERN_ERR "%s: No tda827x found!\n", __func__);
1376 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1377 budget_ci->budget.dvb_frontend = NULL;
1378 }
1379 }
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001380 break;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001381
1382 case 0x1019: // TT S2-3200 PCI
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001383 /*
1384 * NOTE! on some STB0899 versions, the internal PLL takes a longer time
1385 * to settle, aka LOCK. On the older revisions of the chip, we don't see
1386 * this, as a result on the newer chips the entire clock tree, will not
1387 * be stable after a freshly POWER 'ed up situation.
1388 * In this case, we should RESET the STB0899 (Active LOW) and wait for
1389 * PLL stabilization.
1390 *
1391 * On the TT S2 3200 and clones, the STB0899 demodulator's RESETB is
1392 * connected to the SAA7146 GPIO, GPIO2, Pin 142
1393 */
1394 /* Reset Demodulator */
Manu Abraham0867f572007-10-15 13:07:16 -03001395 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001396 /* Wait for everything to die */
1397 msleep(50);
1398 /* Pull it up out of Reset state */
Manu Abraham0867f572007-10-15 13:07:16 -03001399 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001400 /* Wait for PLL to stabilize */
1401 msleep(250);
1402 /*
1403 * PLL state should be stable now. Ideally, we should check
1404 * for PLL LOCK status. But well, never mind!
1405 */
Manu Abrahamae9902d2007-10-08 18:51:54 -03001406 budget_ci->budget.dvb_frontend = dvb_attach(stb0899_attach, &tt3200_config, &budget_ci->budget.i2c_adap);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001407 if (budget_ci->budget.dvb_frontend) {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001408 if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {
1409 if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
Harvey Harrison9b4778f2009-01-07 14:42:41 -08001410 printk("%s: No LNBP21 found!\n", __func__);
Manu Abrahamae9902d2007-10-08 18:51:54 -03001411 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001412 budget_ci->budget.dvb_frontend = NULL;
1413 }
1414 } else {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001415 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1416 budget_ci->budget.dvb_frontend = NULL;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001417 }
1418 }
1419 break;
1420
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 }
1422
1423 if (budget_ci->budget.dvb_frontend == NULL) {
Bjorn Helgaas29e66a62008-09-04 17:24:51 -03001424 printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 budget_ci->budget.dev->pci->vendor,
1426 budget_ci->budget.dev->pci->device,
1427 budget_ci->budget.dev->pci->subsystem_vendor,
1428 budget_ci->budget.dev->pci->subsystem_device);
1429 } else {
1430 if (dvb_register_frontend
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001431 (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 printk("budget-ci: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001433 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 budget_ci->budget.dvb_frontend = NULL;
1435 }
1436 }
1437}
1438
1439static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
1440{
1441 struct budget_ci *budget_ci;
1442 int err;
1443
David Hardemanee579bc2006-12-02 21:16:05 -02001444 budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
David Hardeman8cc532e2006-12-02 21:16:05 -02001445 if (!budget_ci) {
1446 err = -ENOMEM;
1447 goto out1;
1448 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449
1450 dprintk(2, "budget_ci: %p\n", budget_ci);
1451
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 dev->ext_priv = budget_ci;
1453
Janne Grunau26dc4d02008-09-21 20:50:11 -03001454 err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE,
1455 adapter_nr);
David Hardeman8cc532e2006-12-02 21:16:05 -02001456 if (err)
1457 goto out2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
David Hardeman8cc532e2006-12-02 21:16:05 -02001459 err = msp430_ir_init(budget_ci);
1460 if (err)
1461 goto out3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462
1463 ciintf_init(budget_ci);
1464
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001465 budget_ci->budget.dvb_adapter.priv = budget_ci;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 frontend_init(budget_ci);
1467
Oliver Endriss32e4c3a2006-07-18 22:55:23 -03001468 ttpci_budget_init_hooks(&budget_ci->budget);
1469
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 return 0;
David Hardeman8cc532e2006-12-02 21:16:05 -02001471
1472out3:
1473 ttpci_budget_deinit(&budget_ci->budget);
1474out2:
1475 kfree(budget_ci);
1476out1:
1477 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478}
1479
1480static int budget_ci_detach(struct saa7146_dev *dev)
1481{
1482 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
1483 struct saa7146_dev *saa = budget_ci->budget.dev;
1484 int err;
1485
1486 if (budget_ci->budget.ci_present)
1487 ciintf_deinit(budget_ci);
David Hardeman8cc532e2006-12-02 21:16:05 -02001488 msp430_ir_deinit(budget_ci);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001489 if (budget_ci->budget.dvb_frontend) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001491 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001492 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 err = ttpci_budget_deinit(&budget_ci->budget);
1494
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 // disable frontend and CI interface
1496 saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
1497
1498 kfree(budget_ci);
1499
1500 return err;
1501}
1502
1503static struct saa7146_extension budget_extension;
1504
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001505MAKE_BUDGET_INFO(ttbs2, "TT-Budget/S-1500 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
1507MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001508MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001509MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
Sigmund Augdal11417da2008-06-15 17:25:46 -03001510MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001511MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512
1513static struct pci_device_id pci_tbl[] = {
1514 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
1515 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001516 MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001518 MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001519 MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
Sigmund Augdal11417da2008-06-15 17:25:46 -03001520 MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001521 MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 {
1523 .vendor = 0,
1524 }
1525};
1526
1527MODULE_DEVICE_TABLE(pci, pci_tbl);
1528
1529static struct saa7146_extension budget_extension = {
Dave Jones0e367a12006-08-07 13:18:56 -03001530 .name = "budget_ci dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03001531 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532
1533 .module = THIS_MODULE,
1534 .pci_tbl = &pci_tbl[0],
1535 .attach = budget_ci_attach,
1536 .detach = budget_ci_detach,
1537
1538 .irq_mask = MASK_03 | MASK_06 | MASK_10,
1539 .irq_func = budget_ci_irq,
1540};
1541
1542static int __init budget_ci_init(void)
1543{
1544 return saa7146_register_extension(&budget_extension);
1545}
1546
1547static void __exit budget_ci_exit(void)
1548{
1549 saa7146_unregister_extension(&budget_extension);
1550}
1551
1552module_init(budget_ci_init);
1553module_exit(budget_ci_exit);
1554
1555MODULE_LICENSE("GPL");
1556MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
1557MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1558 "budget PCI DVB cards w/ CI-module produced by "
1559 "Siemens, Technotrend, Hauppauge");