blob: 8ae67c1751a932a1a1260ccf60be0cdfec0604b1 [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 Hardeman5cc8ae02006-12-02 21:16:05 -0200187 if (saa->pci->subsystem_vendor) {
David Härdemand8b4b582010-10-29 16:08:23 -0300188 dev->input_id.vendor = saa->pci->subsystem_vendor;
189 dev->input_id.product = saa->pci->subsystem_device;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200190 } else {
David Härdemand8b4b582010-10-29 16:08:23 -0300191 dev->input_id.vendor = saa->pci->vendor;
192 dev->input_id.product = saa->pci->device;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200193 }
David Härdemand8b4b582010-10-29 16:08:23 -0300194 dev->dev.parent = &saa->pci->dev;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200195
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300196 if (rc5_device < 0)
197 budget_ci->ir.rc5_device = IR_DEVICE_ANY;
198 else
199 budget_ci->ir.rc5_device = rc5_device;
200
David Hardeman64741b72006-12-02 21:16:05 -0200201 /* Select keymap and address */
David Hardeman2520fff2006-12-02 21:16:05 -0200202 switch (budget_ci->budget.dev->pci->subsystem_device) {
203 case 0x100c:
204 case 0x100f:
David Hardeman2520fff2006-12-02 21:16:05 -0200205 case 0x1011:
206 case 0x1012:
David Hardeman2520fff2006-12-02 21:16:05 -0200207 /* The hauppauge keymap is a superset of these remotes */
David Härdemand8b4b582010-10-29 16:08:23 -0300208 dev->map_name = RC_MAP_HAUPPAUGE_NEW;
David Hardeman64741b72006-12-02 21:16:05 -0200209
210 if (rc5_device < 0)
211 budget_ci->ir.rc5_device = 0x1f;
David Hardeman2520fff2006-12-02 21:16:05 -0200212 break;
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300213 case 0x1010:
Oliver Endrissf64899c2007-09-17 22:17:12 -0300214 case 0x1017:
Hermann Gaustererf137f9d2010-05-18 04:26:17 -0300215 case 0x1019:
Oliver Endrissbbfc4c22008-06-19 23:36:45 -0300216 case 0x101a:
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300217 /* for the Technotrend 1500 bundled remote */
David Härdemand8b4b582010-10-29 16:08:23 -0300218 dev->map_name = RC_MAP_TT_1500;
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300219 break;
David Hardeman2520fff2006-12-02 21:16:05 -0200220 default:
221 /* unknown remote */
David Härdemand8b4b582010-10-29 16:08:23 -0300222 dev->map_name = RC_MAP_BUDGET_CI_OLD;
David Hardeman2520fff2006-12-02 21:16:05 -0200223 break;
224 }
225
David Härdemand8b4b582010-10-29 16:08:23 -0300226 error = rc_register_device(dev);
David Hardeman8cc532e2006-12-02 21:16:05 -0200227 if (error) {
228 printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
David Härdemand8b4b582010-10-29 16:08:23 -0300229 rc_free_device(dev);
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300230 return error;
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300231 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232
David Härdemand8b4b582010-10-29 16:08:23 -0300233 budget_ci->ir.dev = dev;
David Härdeman145859c2007-04-27 12:31:22 -0300234
David Hardeman8cc532e2006-12-02 21:16:05 -0200235 tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
236 (unsigned long) budget_ci);
237
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300238 SAA7146_IER_ENABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
240
241 return 0;
242}
243
244static void msp430_ir_deinit(struct budget_ci *budget_ci)
245{
246 struct saa7146_dev *saa = budget_ci->budget.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300248 SAA7146_IER_DISABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
David Hardeman8cc532e2006-12-02 21:16:05 -0200250 tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251
David Härdemand8b4b582010-10-29 16:08:23 -0300252 rc_unregister_device(budget_ci->ir.dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253}
254
255static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
256{
257 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
258
259 if (slot != 0)
260 return -EINVAL;
261
262 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
263 DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);
264}
265
266static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
267{
268 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
269
270 if (slot != 0)
271 return -EINVAL;
272
273 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
274 DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);
275}
276
277static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
278{
279 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
280
281 if (slot != 0)
282 return -EINVAL;
283
284 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
285 DEBIADDR_IO | (address & 3), 1, 1, 0);
286}
287
288static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
289{
290 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
291
292 if (slot != 0)
293 return -EINVAL;
294
295 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
296 DEBIADDR_IO | (address & 3), 1, value, 1, 0);
297}
298
299static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
300{
301 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
302 struct saa7146_dev *saa = budget_ci->budget.dev;
303
304 if (slot != 0)
305 return -EINVAL;
306
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300307 if (budget_ci->ci_irq) {
308 // trigger on RISING edge during reset so we know when READY is re-asserted
309 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
310 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 budget_ci->slot_status = SLOTSTATUS_RESET;
312 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
313 msleep(1);
314 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
315 CICONTROL_RESET, 1, 0);
316
317 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
318 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
319 return 0;
320}
321
322static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
323{
324 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
325 struct saa7146_dev *saa = budget_ci->budget.dev;
326
327 if (slot != 0)
328 return -EINVAL;
329
330 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
331 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
332 return 0;
333}
334
335static int ciintf_slot_ts_enable(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 int tmp;
340
341 if (slot != 0)
342 return -EINVAL;
343
344 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
345
346 tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
347 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
348 tmp | CICONTROL_ENABLETS, 1, 0);
349
350 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
351 return 0;
352}
353
354static void ciintf_interrupt(unsigned long data)
355{
356 struct budget_ci *budget_ci = (struct budget_ci *) data;
357 struct saa7146_dev *saa = budget_ci->budget.dev;
358 unsigned int flags;
359
360 // ensure we don't get spurious IRQs during initialisation
361 if (!budget_ci->budget.ci_present)
362 return;
363
364 // read the CAM status
365 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
366 if (flags & CICONTROL_CAMDETECT) {
367
368 // GPIO should be set to trigger on falling edge if a CAM is present
369 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
370
371 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
372 // CAM insertion IRQ
373 budget_ci->slot_status = SLOTSTATUS_PRESENT;
374 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
375 DVB_CA_EN50221_CAMCHANGE_INSERTED);
376
377 } else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
378 // CAM ready (reset completed)
379 budget_ci->slot_status = SLOTSTATUS_READY;
380 dvb_ca_en50221_camready_irq(&budget_ci->ca, 0);
381
382 } else if (budget_ci->slot_status & SLOTSTATUS_READY) {
383 // FR/DA IRQ
384 dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);
385 }
386 } else {
387
388 // trigger on rising edge if a CAM is not present - when a CAM is inserted, we
389 // only want to get the IRQ when it sets READY. If we trigger on the falling edge,
390 // the CAM might not actually be ready yet.
391 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
392
393 // generate a CAM removal IRQ if we haven't already
394 if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
395 // CAM removal IRQ
396 budget_ci->slot_status = SLOTSTATUS_NONE;
397 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
398 DVB_CA_EN50221_CAMCHANGE_REMOVED);
399 }
400 }
401}
402
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300403static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
404{
405 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
406 unsigned int flags;
407
408 // ensure we don't get spurious IRQs during initialisation
409 if (!budget_ci->budget.ci_present)
410 return -EINVAL;
411
412 // read the CAM status
413 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
414 if (flags & CICONTROL_CAMDETECT) {
415 // mark it as present if it wasn't before
416 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
417 budget_ci->slot_status = SLOTSTATUS_PRESENT;
418 }
419
420 // during a RESET, we check if we can read from IO memory to see when CAM is ready
421 if (budget_ci->slot_status & SLOTSTATUS_RESET) {
422 if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
423 budget_ci->slot_status = SLOTSTATUS_READY;
424 }
425 }
426 } else {
427 budget_ci->slot_status = SLOTSTATUS_NONE;
428 }
429
430 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
431 if (budget_ci->slot_status & SLOTSTATUS_READY) {
432 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
433 }
434 return DVB_CA_EN50221_POLL_CAM_PRESENT;
435 }
436
437 return 0;
438}
439
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440static int ciintf_init(struct budget_ci *budget_ci)
441{
442 struct saa7146_dev *saa = budget_ci->budget.dev;
443 int flags;
444 int result;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300445 int ci_version;
446 int ca_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
448 memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
449
450 // enable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300451 saa7146_write(saa, MC1, MASK_27 | MASK_11);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
453 // test if it is there
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300454 ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
455 if ((ci_version & 0xa0) != 0xa0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 result = -ENODEV;
457 goto error;
458 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300459
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 // determine whether a CAM is present or not
461 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
462 budget_ci->slot_status = SLOTSTATUS_NONE;
463 if (flags & CICONTROL_CAMDETECT)
464 budget_ci->slot_status = SLOTSTATUS_PRESENT;
465
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300466 // version 0xa2 of the CI firmware doesn't generate interrupts
467 if (ci_version == 0xa2) {
468 ca_flags = 0;
469 budget_ci->ci_irq = 0;
470 } else {
471 ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
472 DVB_CA_EN50221_FLAG_IRQ_FR |
473 DVB_CA_EN50221_FLAG_IRQ_DA;
474 budget_ci->ci_irq = 1;
475 }
476
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 // register CI interface
478 budget_ci->ca.owner = THIS_MODULE;
479 budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
480 budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
481 budget_ci->ca.read_cam_control = ciintf_read_cam_control;
482 budget_ci->ca.write_cam_control = ciintf_write_cam_control;
483 budget_ci->ca.slot_reset = ciintf_slot_reset;
484 budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
485 budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300486 budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 budget_ci->ca.data = budget_ci;
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700488 if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 &budget_ci->ca,
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300490 ca_flags, 1)) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 printk("budget_ci: CI interface detected, but initialisation failed.\n");
492 goto error;
493 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300494
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 // Setup CI slot IRQ
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300496 if (budget_ci->ci_irq) {
497 tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
498 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
499 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
500 } else {
501 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
502 }
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300503 SAA7146_IER_ENABLE(saa, MASK_03);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300505
506 // enable interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
508 CICONTROL_RESET, 1, 0);
509
510 // success!
511 printk("budget_ci: CI interface initialised\n");
512 budget_ci->budget.ci_present = 1;
513
514 // forge a fake CI IRQ so the CAM state is setup correctly
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300515 if (budget_ci->ci_irq) {
516 flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
517 if (budget_ci->slot_status != SLOTSTATUS_NONE)
518 flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
519 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
520 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521
522 return 0;
523
524error:
Hartmut Birr2a893de2006-12-03 21:08:08 -0300525 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 return result;
527}
528
529static void ciintf_deinit(struct budget_ci *budget_ci)
530{
531 struct saa7146_dev *saa = budget_ci->budget.dev;
532
533 // disable CI interrupts
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300534 if (budget_ci->ci_irq) {
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300535 SAA7146_IER_DISABLE(saa, MASK_03);
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300536 saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
537 tasklet_kill(&budget_ci->ciintf_irq_tasklet);
538 }
539
540 // reset interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
542 msleep(1);
543 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
544 CICONTROL_RESET, 1, 0);
545
546 // disable TS data stream to CI interface
547 saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
548
549 // release the CA device
550 dvb_ca_en50221_release(&budget_ci->ca);
551
552 // disable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300553 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554}
555
556static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
557{
558 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
559
560 dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
561
562 if (*isr & MASK_06)
David Hardemandd2f3982006-12-02 21:16:05 -0200563 tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
565 if (*isr & MASK_10)
566 ttpci_budget_irq10_handler(dev, isr);
567
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300568 if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
570}
571
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572static u8 philips_su1278_tt_inittab[] = {
573 0x01, 0x0f,
574 0x02, 0x30,
575 0x03, 0x00,
576 0x04, 0x5b,
577 0x05, 0x85,
578 0x06, 0x02,
579 0x07, 0x00,
580 0x08, 0x02,
581 0x09, 0x00,
582 0x0C, 0x01,
583 0x0D, 0x81,
584 0x0E, 0x44,
585 0x0f, 0x14,
586 0x10, 0x3c,
587 0x11, 0x84,
588 0x12, 0xda,
589 0x13, 0x97,
590 0x14, 0x95,
591 0x15, 0xc9,
592 0x16, 0x19,
593 0x17, 0x8c,
594 0x18, 0x59,
595 0x19, 0xf8,
596 0x1a, 0xfe,
597 0x1c, 0x7f,
598 0x1d, 0x00,
599 0x1e, 0x00,
600 0x1f, 0x50,
601 0x20, 0x00,
602 0x21, 0x00,
603 0x22, 0x00,
604 0x23, 0x00,
605 0x28, 0x00,
606 0x29, 0x28,
607 0x2a, 0x14,
608 0x2b, 0x0f,
609 0x2c, 0x09,
610 0x2d, 0x09,
611 0x31, 0x1f,
612 0x32, 0x19,
613 0x33, 0xfc,
614 0x34, 0x93,
615 0xff, 0xff
616};
617
618static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
619{
620 stv0299_writereg(fe, 0x0e, 0x44);
621 if (srate >= 10000000) {
622 stv0299_writereg(fe, 0x13, 0x97);
623 stv0299_writereg(fe, 0x14, 0x95);
624 stv0299_writereg(fe, 0x15, 0xc9);
625 stv0299_writereg(fe, 0x17, 0x8c);
626 stv0299_writereg(fe, 0x1a, 0xfe);
627 stv0299_writereg(fe, 0x1c, 0x7f);
628 stv0299_writereg(fe, 0x2d, 0x09);
629 } else {
630 stv0299_writereg(fe, 0x13, 0x99);
631 stv0299_writereg(fe, 0x14, 0x8d);
632 stv0299_writereg(fe, 0x15, 0xce);
633 stv0299_writereg(fe, 0x17, 0x43);
634 stv0299_writereg(fe, 0x1a, 0x1d);
635 stv0299_writereg(fe, 0x1c, 0x12);
636 stv0299_writereg(fe, 0x2d, 0x05);
637 }
638 stv0299_writereg(fe, 0x0e, 0x23);
639 stv0299_writereg(fe, 0x0f, 0x94);
640 stv0299_writereg(fe, 0x10, 0x39);
641 stv0299_writereg(fe, 0x15, 0xc9);
642
643 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
644 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
645 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
646
647 return 0;
648}
649
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300650static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,
651 struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652{
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300653 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 u32 div;
655 u8 buf[4];
656 struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
657
658 if ((params->frequency < 950000) || (params->frequency > 2150000))
659 return -EINVAL;
660
661 div = (params->frequency + (500 - 1)) / 500; // round correctly
662 buf[0] = (div >> 8) & 0x7f;
663 buf[1] = div & 0xff;
664 buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
665 buf[3] = 0x20;
666
667 if (params->u.qpsk.symbol_rate < 4000000)
668 buf[3] |= 1;
669
670 if (params->frequency < 1250000)
671 buf[3] |= 0;
672 else if (params->frequency < 1550000)
673 buf[3] |= 0x40;
674 else if (params->frequency < 2050000)
675 buf[3] |= 0x80;
676 else if (params->frequency < 2150000)
677 buf[3] |= 0xC0;
678
Patrick Boettcherdea74862006-05-14 05:01:31 -0300679 if (fe->ops.i2c_gate_ctrl)
680 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300681 if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 return -EIO;
683 return 0;
684}
685
686static struct stv0299_config philips_su1278_tt_config = {
687
688 .demod_address = 0x68,
689 .inittab = philips_su1278_tt_inittab,
690 .mclk = 64000000UL,
691 .invert = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 .skip_reinit = 1,
Oliver Endrissda2c7f62008-04-20 22:13:37 -0300693 .lock_output = STV0299_LOCKOUTPUT_1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 .volt13_op0_op1 = STV0299_VOLT13_OP1,
695 .min_delay_ms = 50,
696 .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697};
698
699
700
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300701static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702{
703 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
704 static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
705 static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700706 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 sizeof(td1316_init) };
708
709 // setup PLL configuration
Patrick Boettcherdea74862006-05-14 05:01:31 -0300710 if (fe->ops.i2c_gate_ctrl)
711 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
713 return -EIO;
714 msleep(1);
715
716 // disable the mc44BC374c (do not check for errors)
717 tuner_msg.addr = 0x65;
718 tuner_msg.buf = disable_mc44BC374c;
719 tuner_msg.len = sizeof(disable_mc44BC374c);
Patrick Boettcherdea74862006-05-14 05:01:31 -0300720 if (fe->ops.i2c_gate_ctrl)
721 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
Patrick Boettcherdea74862006-05-14 05:01:31 -0300723 if (fe->ops.i2c_gate_ctrl)
724 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
726 }
727
728 return 0;
729}
730
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300731static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732{
733 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
734 u8 tuner_buf[4];
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700735 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 -0700736 int tuner_frequency = 0;
737 u8 band, cp, filter;
738
739 // determine charge pump
740 tuner_frequency = params->frequency + 36130000;
741 if (tuner_frequency < 87000000)
742 return -EINVAL;
743 else if (tuner_frequency < 130000000)
744 cp = 3;
745 else if (tuner_frequency < 160000000)
746 cp = 5;
747 else if (tuner_frequency < 200000000)
748 cp = 6;
749 else if (tuner_frequency < 290000000)
750 cp = 3;
751 else if (tuner_frequency < 420000000)
752 cp = 5;
753 else if (tuner_frequency < 480000000)
754 cp = 6;
755 else if (tuner_frequency < 620000000)
756 cp = 3;
757 else if (tuner_frequency < 830000000)
758 cp = 5;
759 else if (tuner_frequency < 895000000)
760 cp = 7;
761 else
762 return -EINVAL;
763
764 // determine band
765 if (params->frequency < 49000000)
766 return -EINVAL;
767 else if (params->frequency < 159000000)
768 band = 1;
769 else if (params->frequency < 444000000)
770 band = 2;
771 else if (params->frequency < 861000000)
772 band = 4;
773 else
774 return -EINVAL;
775
776 // setup PLL filter and TDA9889
777 switch (params->u.ofdm.bandwidth) {
778 case BANDWIDTH_6_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300779 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 filter = 0;
781 break;
782
783 case BANDWIDTH_7_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300784 tda1004x_writereg(fe, 0x0C, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 filter = 0;
786 break;
787
788 case BANDWIDTH_8_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300789 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 filter = 1;
791 break;
792
793 default:
794 return -EINVAL;
795 }
796
797 // calculate divisor
798 // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
799 tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
800
801 // setup tuner buffer
802 tuner_buf[0] = tuner_frequency >> 8;
803 tuner_buf[1] = tuner_frequency & 0xff;
804 tuner_buf[2] = 0xca;
805 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
806
Patrick Boettcherdea74862006-05-14 05:01:31 -0300807 if (fe->ops.i2c_gate_ctrl)
808 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
810 return -EIO;
811
812 msleep(1);
813 return 0;
814}
815
816static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,
817 const struct firmware **fw, char *name)
818{
819 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
820
821 return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);
822}
823
824static struct tda1004x_config philips_tdm1316l_config = {
825
826 .demod_address = 0x8,
827 .invert = 0,
828 .invert_oclk = 0,
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700829 .xtal_freq = TDA10046_XTAL_4M,
830 .agc_config = TDA10046_AGC_DEFAULT,
831 .if_freq = TDA10046_FREQ_3617,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 .request_firmware = philips_tdm1316l_request_firmware,
833};
834
Oliver Endriss6c914492007-02-02 19:12:53 -0300835static struct tda1004x_config philips_tdm1316l_config_invert = {
836
837 .demod_address = 0x8,
838 .invert = 1,
839 .invert_oclk = 0,
840 .xtal_freq = TDA10046_XTAL_4M,
841 .agc_config = TDA10046_AGC_DEFAULT,
842 .if_freq = TDA10046_FREQ_3617,
843 .request_firmware = philips_tdm1316l_request_firmware,
844};
845
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300846static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700847{
848 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
849 u8 tuner_buf[5];
850 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
851 .flags = 0,
852 .buf = tuner_buf,
853 .len = sizeof(tuner_buf) };
854 int tuner_frequency = 0;
855 u8 band, cp, filter;
856
857 // determine charge pump
858 tuner_frequency = params->frequency + 36125000;
859 if (tuner_frequency < 87000000)
860 return -EINVAL;
861 else if (tuner_frequency < 130000000) {
862 cp = 3;
863 band = 1;
864 } else if (tuner_frequency < 160000000) {
865 cp = 5;
866 band = 1;
867 } else if (tuner_frequency < 200000000) {
868 cp = 6;
Oliver Endriss910a7b62007-05-03 13:16:12 -0300869 band = 1;
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700870 } else if (tuner_frequency < 290000000) {
871 cp = 3;
872 band = 2;
873 } else if (tuner_frequency < 420000000) {
874 cp = 5;
875 band = 2;
876 } else if (tuner_frequency < 480000000) {
877 cp = 6;
878 band = 2;
879 } else if (tuner_frequency < 620000000) {
880 cp = 3;
881 band = 4;
882 } else if (tuner_frequency < 830000000) {
883 cp = 5;
884 band = 4;
885 } else if (tuner_frequency < 895000000) {
886 cp = 7;
887 band = 4;
888 } else
889 return -EINVAL;
890
891 // assume PLL filter should always be 8MHz for the moment.
892 filter = 1;
893
894 // calculate divisor
895 tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
896
897 // setup tuner buffer
898 tuner_buf[0] = tuner_frequency >> 8;
899 tuner_buf[1] = tuner_frequency & 0xff;
900 tuner_buf[2] = 0xc8;
901 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
902 tuner_buf[4] = 0x80;
903
Patrick Boettcherdea74862006-05-14 05:01:31 -0300904 if (fe->ops.i2c_gate_ctrl)
905 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700906 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
907 return -EIO;
908
909 msleep(50);
910
Patrick Boettcherdea74862006-05-14 05:01:31 -0300911 if (fe->ops.i2c_gate_ctrl)
912 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700913 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
914 return -EIO;
915
916 msleep(1);
917
918 return 0;
919}
920
921static u8 dvbc_philips_tdm1316l_inittab[] = {
922 0x80, 0x01,
923 0x80, 0x00,
924 0x81, 0x01,
925 0x81, 0x00,
926 0x00, 0x09,
927 0x01, 0x69,
928 0x03, 0x00,
929 0x04, 0x00,
930 0x07, 0x00,
931 0x08, 0x00,
932 0x20, 0x00,
933 0x21, 0x40,
934 0x22, 0x00,
935 0x23, 0x00,
936 0x24, 0x40,
937 0x25, 0x88,
938 0x30, 0xff,
939 0x31, 0x00,
940 0x32, 0xff,
941 0x33, 0x00,
942 0x34, 0x50,
943 0x35, 0x7f,
944 0x36, 0x00,
945 0x37, 0x20,
946 0x38, 0x00,
947 0x40, 0x1c,
948 0x41, 0xff,
949 0x42, 0x29,
950 0x43, 0x20,
951 0x44, 0xff,
952 0x45, 0x00,
953 0x46, 0x00,
954 0x49, 0x04,
955 0x4a, 0x00,
956 0x4b, 0x7b,
957 0x52, 0x30,
958 0x55, 0xae,
959 0x56, 0x47,
960 0x57, 0xe1,
961 0x58, 0x3a,
962 0x5a, 0x1e,
963 0x5b, 0x34,
964 0x60, 0x00,
965 0x63, 0x00,
966 0x64, 0x00,
967 0x65, 0x00,
968 0x66, 0x00,
969 0x67, 0x00,
970 0x68, 0x00,
971 0x69, 0x00,
972 0x6a, 0x02,
973 0x6b, 0x00,
974 0x70, 0xff,
975 0x71, 0x00,
976 0x72, 0x00,
977 0x73, 0x00,
978 0x74, 0x0c,
979 0x80, 0x00,
980 0x81, 0x00,
981 0x82, 0x00,
982 0x83, 0x00,
983 0x84, 0x04,
984 0x85, 0x80,
985 0x86, 0x24,
986 0x87, 0x78,
987 0x88, 0x10,
988 0x89, 0x00,
989 0x90, 0x01,
990 0x91, 0x01,
991 0xa0, 0x04,
992 0xa1, 0x00,
993 0xa2, 0x00,
994 0xb0, 0x91,
995 0xb1, 0x0b,
996 0xc0, 0x53,
997 0xc1, 0x70,
998 0xc2, 0x12,
999 0xd0, 0x00,
1000 0xd1, 0x00,
1001 0xd2, 0x00,
1002 0xd3, 0x00,
1003 0xd4, 0x00,
1004 0xd5, 0x00,
1005 0xde, 0x00,
1006 0xdf, 0x00,
1007 0x61, 0x38,
1008 0x62, 0x0a,
1009 0x53, 0x13,
1010 0x59, 0x08,
1011 0xff, 0xff,
1012};
1013
1014static struct stv0297_config dvbc_philips_tdm1316l_config = {
1015 .demod_address = 0x1c,
1016 .inittab = dvbc_philips_tdm1316l_inittab,
1017 .invert = 0,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001018 .stop_during_read = 1,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001019};
1020
Sigmund Augdal11417da2008-06-15 17:25:46 -03001021static struct tda10023_config tda10023_config = {
1022 .demod_address = 0xc,
1023 .invert = 0,
1024 .xtal = 16000000,
1025 .pll_m = 11,
1026 .pll_p = 3,
1027 .pll_n = 1,
1028 .deltaf = 0xa511,
1029};
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001030
klaas de waalcf47d872009-03-25 17:53:02 -03001031static struct tda827x_config tda827x_config = {
1032 .config = 0,
1033};
1034
Manu Abrahama55bc842008-10-23 18:32:50 -03001035/* TT S2-3200 DVB-S (STB0899) Inittab */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001036static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001038 { STB0899_DEV_ID , 0x81 },
1039 { STB0899_DISCNTRL1 , 0x32 },
1040 { STB0899_DISCNTRL2 , 0x80 },
1041 { STB0899_DISRX_ST0 , 0x04 },
1042 { STB0899_DISRX_ST1 , 0x00 },
1043 { STB0899_DISPARITY , 0x00 },
1044 { STB0899_DISFIFO , 0x00 },
1045 { STB0899_DISSTATUS , 0x20 },
1046 { STB0899_DISF22 , 0x8c },
1047 { STB0899_DISF22RX , 0x9a },
Manu Abrahamef3052b2008-10-23 18:45:17 -03001048 { STB0899_SYSREG , 0x0b },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001049 { STB0899_ACRPRESC , 0x11 },
1050 { STB0899_ACRDIV1 , 0x0a },
1051 { STB0899_ACRDIV2 , 0x05 },
1052 { STB0899_DACR1 , 0x00 },
1053 { STB0899_DACR2 , 0x00 },
1054 { STB0899_OUTCFG , 0x00 },
1055 { STB0899_MODECFG , 0x00 },
1056 { STB0899_IRQSTATUS_3 , 0x30 },
1057 { STB0899_IRQSTATUS_2 , 0x00 },
1058 { STB0899_IRQSTATUS_1 , 0x00 },
1059 { STB0899_IRQSTATUS_0 , 0x00 },
1060 { STB0899_IRQMSK_3 , 0xf3 },
1061 { STB0899_IRQMSK_2 , 0xfc },
1062 { STB0899_IRQMSK_1 , 0xff },
1063 { STB0899_IRQMSK_0 , 0xff },
1064 { STB0899_IRQCFG , 0x00 },
1065 { STB0899_I2CCFG , 0x88 },
Manu Abraham40e8ce32008-02-03 19:37:02 -03001066 { STB0899_I2CRPT , 0x48 }, /* 12k Pullup, Repeater=16, Stop=disabled */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001067 { STB0899_IOPVALUE5 , 0x00 },
1068 { STB0899_IOPVALUE4 , 0x20 },
1069 { STB0899_IOPVALUE3 , 0xc9 },
1070 { STB0899_IOPVALUE2 , 0x90 },
1071 { STB0899_IOPVALUE1 , 0x40 },
1072 { STB0899_IOPVALUE0 , 0x00 },
1073 { STB0899_GPIO00CFG , 0x82 },
1074 { STB0899_GPIO01CFG , 0x82 },
1075 { STB0899_GPIO02CFG , 0x82 },
1076 { STB0899_GPIO03CFG , 0x82 },
1077 { STB0899_GPIO04CFG , 0x82 },
1078 { STB0899_GPIO05CFG , 0x82 },
1079 { STB0899_GPIO06CFG , 0x82 },
1080 { STB0899_GPIO07CFG , 0x82 },
1081 { STB0899_GPIO08CFG , 0x82 },
1082 { STB0899_GPIO09CFG , 0x82 },
1083 { STB0899_GPIO10CFG , 0x82 },
1084 { STB0899_GPIO11CFG , 0x82 },
1085 { STB0899_GPIO12CFG , 0x82 },
1086 { STB0899_GPIO13CFG , 0x82 },
1087 { STB0899_GPIO14CFG , 0x82 },
1088 { STB0899_GPIO15CFG , 0x82 },
1089 { STB0899_GPIO16CFG , 0x82 },
1090 { STB0899_GPIO17CFG , 0x82 },
1091 { STB0899_GPIO18CFG , 0x82 },
1092 { STB0899_GPIO19CFG , 0x82 },
1093 { STB0899_GPIO20CFG , 0x82 },
1094 { STB0899_SDATCFG , 0xb8 },
1095 { STB0899_SCLTCFG , 0xba },
Manu Abrahama55bc842008-10-23 18:32:50 -03001096 { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */
1097 { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */
1098 { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001099 { STB0899_DIRCLKCFG , 0x82 },
1100 { STB0899_CLKOUT27CFG , 0x7e },
1101 { STB0899_STDBYCFG , 0x82 },
1102 { STB0899_CS0CFG , 0x82 },
1103 { STB0899_CS1CFG , 0x82 },
1104 { STB0899_DISEQCOCFG , 0x20 },
1105 { STB0899_GPIO32CFG , 0x82 },
1106 { STB0899_GPIO33CFG , 0x82 },
1107 { STB0899_GPIO34CFG , 0x82 },
1108 { STB0899_GPIO35CFG , 0x82 },
1109 { STB0899_GPIO36CFG , 0x82 },
1110 { STB0899_GPIO37CFG , 0x82 },
1111 { STB0899_GPIO38CFG , 0x82 },
1112 { STB0899_GPIO39CFG , 0x82 },
Manu Abrahamf2e52cd2007-11-19 16:44:47 -03001113 { STB0899_NCOARSE , 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
Manu Abrahama55bc842008-10-23 18:32:50 -03001114 { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001115 { STB0899_FILTCTRL , 0x00 },
1116 { STB0899_SYSCTRL , 0x00 },
1117 { STB0899_STOPCLK1 , 0x20 },
1118 { STB0899_STOPCLK2 , 0x00 },
1119 { STB0899_INTBUFSTATUS , 0x00 },
1120 { STB0899_INTBUFCTRL , 0x0a },
1121 { 0xffff , 0xff },
1122};
1123
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001124static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = {
1125 { STB0899_DEMOD , 0x00 },
1126 { STB0899_RCOMPC , 0xc9 },
1127 { STB0899_AGC1CN , 0x41 },
1128 { STB0899_AGC1REF , 0x10 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001129 { STB0899_RTC , 0x7a },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001130 { STB0899_TMGCFG , 0x4e },
1131 { STB0899_AGC2REF , 0x34 },
1132 { STB0899_TLSR , 0x84 },
1133 { STB0899_CFD , 0xc7 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001134 { STB0899_ACLC , 0x87 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001135 { STB0899_BCLC , 0x94 },
1136 { STB0899_EQON , 0x41 },
1137 { STB0899_LDT , 0xdd },
1138 { STB0899_LDT2 , 0xc9 },
1139 { STB0899_EQUALREF , 0xb4 },
1140 { STB0899_TMGRAMP , 0x10 },
1141 { STB0899_TMGTHD , 0x30 },
1142 { STB0899_IDCCOMP , 0xfb },
1143 { STB0899_QDCCOMP , 0x03 },
1144 { STB0899_POWERI , 0x3b },
1145 { STB0899_POWERQ , 0x3d },
1146 { STB0899_RCOMP , 0x81 },
1147 { STB0899_AGCIQIN , 0x80 },
1148 { STB0899_AGC2I1 , 0x04 },
1149 { STB0899_AGC2I2 , 0xf5 },
1150 { STB0899_TLIR , 0x25 },
1151 { STB0899_RTF , 0x80 },
1152 { STB0899_DSTATUS , 0x00 },
1153 { STB0899_LDI , 0xca },
1154 { STB0899_CFRM , 0xf1 },
1155 { STB0899_CFRL , 0xf3 },
1156 { STB0899_NIRM , 0x2a },
1157 { STB0899_NIRL , 0x05 },
1158 { STB0899_ISYMB , 0x17 },
1159 { STB0899_QSYMB , 0xfa },
1160 { STB0899_SFRH , 0x2f },
1161 { STB0899_SFRM , 0x68 },
1162 { STB0899_SFRL , 0x40 },
1163 { STB0899_SFRUPH , 0x2f },
1164 { STB0899_SFRUPM , 0x68 },
1165 { STB0899_SFRUPL , 0x40 },
1166 { STB0899_EQUAI1 , 0xfd },
1167 { STB0899_EQUAQ1 , 0x04 },
1168 { STB0899_EQUAI2 , 0x0f },
1169 { STB0899_EQUAQ2 , 0xff },
1170 { STB0899_EQUAI3 , 0xdf },
1171 { STB0899_EQUAQ3 , 0xfa },
1172 { STB0899_EQUAI4 , 0x37 },
1173 { STB0899_EQUAQ4 , 0x0d },
1174 { STB0899_EQUAI5 , 0xbd },
1175 { STB0899_EQUAQ5 , 0xf7 },
1176 { STB0899_DSTATUS2 , 0x00 },
1177 { STB0899_VSTATUS , 0x00 },
1178 { STB0899_VERROR , 0xff },
1179 { STB0899_IQSWAP , 0x2a },
1180 { STB0899_ECNT1M , 0x00 },
1181 { STB0899_ECNT1L , 0x00 },
1182 { STB0899_ECNT2M , 0x00 },
1183 { STB0899_ECNT2L , 0x00 },
1184 { STB0899_ECNT3M , 0x00 },
1185 { STB0899_ECNT3L , 0x00 },
1186 { STB0899_FECAUTO1 , 0x06 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001187 { STB0899_FECM , 0x01 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001188 { STB0899_VTH12 , 0xf0 },
1189 { STB0899_VTH23 , 0xa0 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001190 { STB0899_VTH34 , 0x78 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001191 { STB0899_VTH56 , 0x4e },
1192 { STB0899_VTH67 , 0x48 },
1193 { STB0899_VTH78 , 0x38 },
1194 { STB0899_PRVIT , 0xff },
1195 { STB0899_VITSYNC , 0x19 },
Manu Abrahama55bc842008-10-23 18:32:50 -03001196 { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001197 { STB0899_TSULC , 0x42 },
1198 { STB0899_RSLLC , 0x40 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001199 { STB0899_TSLPL , 0x12 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001200 { STB0899_TSCFGH , 0x0c },
1201 { STB0899_TSCFGM , 0x00 },
1202 { STB0899_TSCFGL , 0x0c },
Manu Abrahamc1426df2009-11-13 18:51:39 -03001203 { STB0899_TSOUT , 0x4d }, /* 0x0d for CAM */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001204 { STB0899_RSSYNCDEL , 0x00 },
1205 { STB0899_TSINHDELH , 0x02 },
1206 { STB0899_TSINHDELM , 0x00 },
1207 { STB0899_TSINHDELL , 0x00 },
1208 { STB0899_TSLLSTKM , 0x00 },
1209 { STB0899_TSLLSTKL , 0x00 },
1210 { STB0899_TSULSTKM , 0x00 },
1211 { STB0899_TSULSTKL , 0xab },
1212 { STB0899_PCKLENUL , 0x00 },
1213 { STB0899_PCKLENLL , 0xcc },
1214 { STB0899_RSPCKLEN , 0xcc },
1215 { STB0899_TSSTATUS , 0x80 },
1216 { STB0899_ERRCTRL1 , 0xb6 },
1217 { STB0899_ERRCTRL2 , 0x96 },
1218 { STB0899_ERRCTRL3 , 0x89 },
1219 { STB0899_DMONMSK1 , 0x27 },
1220 { STB0899_DMONMSK0 , 0x03 },
1221 { STB0899_DEMAPVIT , 0x5c },
1222 { STB0899_PLPARM , 0x1f },
1223 { STB0899_PDELCTRL , 0x48 },
1224 { STB0899_PDELCTRL2 , 0x00 },
1225 { STB0899_BBHCTRL1 , 0x00 },
1226 { STB0899_BBHCTRL2 , 0x00 },
1227 { STB0899_HYSTTHRESH , 0x77 },
1228 { STB0899_MATCSTM , 0x00 },
1229 { STB0899_MATCSTL , 0x00 },
1230 { STB0899_UPLCSTM , 0x00 },
1231 { STB0899_UPLCSTL , 0x00 },
1232 { STB0899_DFLCSTM , 0x00 },
1233 { STB0899_DFLCSTL , 0x00 },
1234 { STB0899_SYNCCST , 0x00 },
1235 { STB0899_SYNCDCSTM , 0x00 },
1236 { STB0899_SYNCDCSTL , 0x00 },
1237 { STB0899_ISI_ENTRY , 0x00 },
1238 { STB0899_ISI_BIT_EN , 0x00 },
1239 { STB0899_MATSTRM , 0x00 },
1240 { STB0899_MATSTRL , 0x00 },
1241 { STB0899_UPLSTRM , 0x00 },
1242 { STB0899_UPLSTRL , 0x00 },
1243 { STB0899_DFLSTRM , 0x00 },
1244 { STB0899_DFLSTRL , 0x00 },
1245 { STB0899_SYNCSTR , 0x00 },
1246 { STB0899_SYNCDSTRM , 0x00 },
1247 { STB0899_SYNCDSTRL , 0x00 },
1248 { STB0899_CFGPDELSTATUS1 , 0x10 },
1249 { STB0899_CFGPDELSTATUS2 , 0x00 },
1250 { STB0899_BBFERRORM , 0x00 },
1251 { STB0899_BBFERRORL , 0x00 },
1252 { STB0899_UPKTERRORM , 0x00 },
1253 { STB0899_UPKTERRORL , 0x00 },
1254 { 0xffff , 0xff },
1255};
1256
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001257static struct stb0899_config tt3200_config = {
1258 .init_dev = tt3200_stb0899_s1_init_1,
Manu Abraham8be969b2008-01-25 18:20:48 -03001259 .init_s2_demod = stb0899_s2_init_2,
Manu Abrahama55bc842008-10-23 18:32:50 -03001260 .init_s1_demod = tt3200_stb0899_s1_init_3,
Manu Abraham8be969b2008-01-25 18:20:48 -03001261 .init_s2_fec = stb0899_s2_init_4,
1262 .init_tst = stb0899_s1_init_5,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001263
Manu Abraham043a68b2008-01-18 14:15:17 -03001264 .postproc = NULL,
1265
Manu Abrahama55bc842008-10-23 18:32:50 -03001266 .demod_address = 0x68,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001267
1268 .xtal_freq = 27000000,
Manu Abrahame99d00c2007-09-25 17:48:59 -03001269 .inversion = IQ_SWAP_ON, /* 1 */
Manu Abrahama55bc842008-10-23 18:32:50 -03001270
Manu Abrahamb91a7cb2008-03-04 19:19:58 -03001271 .lo_clk = 76500000,
1272 .hi_clk = 99000000,
1273
Manu Abraham8be969b2008-01-25 18:20:48 -03001274 .esno_ave = STB0899_DVBS2_ESNO_AVE,
1275 .esno_quant = STB0899_DVBS2_ESNO_QUANT,
1276 .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
1277 .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
1278 .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
1279 .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
1280 .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
1281 .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
1282 .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
Manu Abrahama55bc842008-10-23 18:32:50 -03001283
Manu Abraham8be969b2008-01-25 18:20:48 -03001284 .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
1285 .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
1286 .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
1287 .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
Manu Abrahama55bc842008-10-23 18:32:50 -03001288
1289 .tuner_get_frequency = stb6100_get_frequency,
1290 .tuner_set_frequency = stb6100_set_frequency,
1291 .tuner_set_bandwidth = stb6100_set_bandwidth,
1292 .tuner_get_bandwidth = stb6100_get_bandwidth,
Manu Abraham043a68b2008-01-18 14:15:17 -03001293 .tuner_set_rfsiggain = NULL
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001294};
1295
Mauro Carvalho Chehabffbc5f82009-01-05 01:34:20 -03001296static struct stb6100_config tt3200_stb6100_config = {
Manu Abrahamc14eaed2007-10-04 16:52:51 -03001297 .tuner_address = 0x60,
1298 .refclock = 27000000,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001299};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300
1301static void frontend_init(struct budget_ci *budget_ci)
1302{
1303 switch (budget_ci->budget.dev->pci->subsystem_device) {
1304 case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
1305 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001306 dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001308 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001309 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 break;
1311 }
1312 break;
1313
1314 case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
1315 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001316 dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001318 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 break;
1320 }
1321 break;
1322
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001323 case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
1324 budget_ci->tuner_pll_address = 0x61;
1325 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001326 dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001327 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001328 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001329 break;
1330 }
1331 break;
1332
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001334 budget_ci->tuner_pll_address = 0x63;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001336 dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001338 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1339 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 break;
1341 }
1342 break;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001343
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001344 case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001345 budget_ci->tuner_pll_address = 0x60;
1346 budget_ci->budget.dvb_frontend =
Oliver Endriss6c914492007-02-02 19:12:53 -03001347 dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001348 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001349 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1350 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001351 break;
1352 }
1353 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001354
1355 case 0x1017: // TT S-1500 PCI
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001356 budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001357 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001358 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001359 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
1360
Patrick Boettcherdea74862006-05-14 05:01:31 -03001361 budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001362 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 -03001363 printk("%s: No LNBP21 found!\n", __func__);
Andrew de Quincey2b100e72006-08-08 09:10:11 -03001364 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001365 budget_ci->budget.dvb_frontend = NULL;
1366 }
1367 }
Sigmund Augdal11417da2008-06-15 17:25:46 -03001368 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001369
Sigmund Augdal11417da2008-06-15 17:25:46 -03001370 case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */
1371 budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48);
1372 if (budget_ci->budget.dvb_frontend) {
klaas de waalcf47d872009-03-25 17:53:02 -03001373 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 -03001374 printk(KERN_ERR "%s: No tda827x found!\n", __func__);
1375 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1376 budget_ci->budget.dvb_frontend = NULL;
1377 }
1378 }
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001379 break;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001380
1381 case 0x1019: // TT S2-3200 PCI
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001382 /*
1383 * NOTE! on some STB0899 versions, the internal PLL takes a longer time
1384 * to settle, aka LOCK. On the older revisions of the chip, we don't see
1385 * this, as a result on the newer chips the entire clock tree, will not
1386 * be stable after a freshly POWER 'ed up situation.
1387 * In this case, we should RESET the STB0899 (Active LOW) and wait for
1388 * PLL stabilization.
1389 *
1390 * On the TT S2 3200 and clones, the STB0899 demodulator's RESETB is
1391 * connected to the SAA7146 GPIO, GPIO2, Pin 142
1392 */
1393 /* Reset Demodulator */
Manu Abraham0867f572007-10-15 13:07:16 -03001394 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001395 /* Wait for everything to die */
1396 msleep(50);
1397 /* Pull it up out of Reset state */
Manu Abraham0867f572007-10-15 13:07:16 -03001398 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001399 /* Wait for PLL to stabilize */
1400 msleep(250);
1401 /*
1402 * PLL state should be stable now. Ideally, we should check
1403 * for PLL LOCK status. But well, never mind!
1404 */
Manu Abrahamae9902d2007-10-08 18:51:54 -03001405 budget_ci->budget.dvb_frontend = dvb_attach(stb0899_attach, &tt3200_config, &budget_ci->budget.i2c_adap);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001406 if (budget_ci->budget.dvb_frontend) {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001407 if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {
1408 if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
Harvey Harrison9b4778f2009-01-07 14:42:41 -08001409 printk("%s: No LNBP21 found!\n", __func__);
Manu Abrahamae9902d2007-10-08 18:51:54 -03001410 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001411 budget_ci->budget.dvb_frontend = NULL;
1412 }
1413 } else {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001414 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1415 budget_ci->budget.dvb_frontend = NULL;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001416 }
1417 }
1418 break;
1419
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 }
1421
1422 if (budget_ci->budget.dvb_frontend == NULL) {
Bjorn Helgaas29e66a62008-09-04 17:24:51 -03001423 printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 budget_ci->budget.dev->pci->vendor,
1425 budget_ci->budget.dev->pci->device,
1426 budget_ci->budget.dev->pci->subsystem_vendor,
1427 budget_ci->budget.dev->pci->subsystem_device);
1428 } else {
1429 if (dvb_register_frontend
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001430 (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 printk("budget-ci: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001432 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 budget_ci->budget.dvb_frontend = NULL;
1434 }
1435 }
1436}
1437
1438static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
1439{
1440 struct budget_ci *budget_ci;
1441 int err;
1442
David Hardemanee579bc2006-12-02 21:16:05 -02001443 budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
David Hardeman8cc532e2006-12-02 21:16:05 -02001444 if (!budget_ci) {
1445 err = -ENOMEM;
1446 goto out1;
1447 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448
1449 dprintk(2, "budget_ci: %p\n", budget_ci);
1450
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 dev->ext_priv = budget_ci;
1452
Janne Grunau26dc4d02008-09-21 20:50:11 -03001453 err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE,
1454 adapter_nr);
David Hardeman8cc532e2006-12-02 21:16:05 -02001455 if (err)
1456 goto out2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457
David Hardeman8cc532e2006-12-02 21:16:05 -02001458 err = msp430_ir_init(budget_ci);
1459 if (err)
1460 goto out3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461
1462 ciintf_init(budget_ci);
1463
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001464 budget_ci->budget.dvb_adapter.priv = budget_ci;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 frontend_init(budget_ci);
1466
Oliver Endriss32e4c3a2006-07-18 22:55:23 -03001467 ttpci_budget_init_hooks(&budget_ci->budget);
1468
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 return 0;
David Hardeman8cc532e2006-12-02 21:16:05 -02001470
1471out3:
1472 ttpci_budget_deinit(&budget_ci->budget);
1473out2:
1474 kfree(budget_ci);
1475out1:
1476 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477}
1478
1479static int budget_ci_detach(struct saa7146_dev *dev)
1480{
1481 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
1482 struct saa7146_dev *saa = budget_ci->budget.dev;
1483 int err;
1484
1485 if (budget_ci->budget.ci_present)
1486 ciintf_deinit(budget_ci);
David Hardeman8cc532e2006-12-02 21:16:05 -02001487 msp430_ir_deinit(budget_ci);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001488 if (budget_ci->budget.dvb_frontend) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001490 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001491 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 err = ttpci_budget_deinit(&budget_ci->budget);
1493
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 // disable frontend and CI interface
1495 saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
1496
1497 kfree(budget_ci);
1498
1499 return err;
1500}
1501
1502static struct saa7146_extension budget_extension;
1503
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001504MAKE_BUDGET_INFO(ttbs2, "TT-Budget/S-1500 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
1506MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001507MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001508MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
Sigmund Augdal11417da2008-06-15 17:25:46 -03001509MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001510MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511
1512static struct pci_device_id pci_tbl[] = {
1513 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
1514 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001515 MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001517 MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001518 MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
Sigmund Augdal11417da2008-06-15 17:25:46 -03001519 MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001520 MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 {
1522 .vendor = 0,
1523 }
1524};
1525
1526MODULE_DEVICE_TABLE(pci, pci_tbl);
1527
1528static struct saa7146_extension budget_extension = {
Dave Jones0e367a12006-08-07 13:18:56 -03001529 .name = "budget_ci dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03001530 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531
1532 .module = THIS_MODULE,
1533 .pci_tbl = &pci_tbl[0],
1534 .attach = budget_ci_attach,
1535 .detach = budget_ci_detach,
1536
1537 .irq_mask = MASK_03 | MASK_06 | MASK_10,
1538 .irq_func = budget_ci_irq,
1539};
1540
1541static int __init budget_ci_init(void)
1542{
1543 return saa7146_register_extension(&budget_extension);
1544}
1545
1546static void __exit budget_ci_exit(void)
1547{
1548 saa7146_unregister_extension(&budget_extension);
1549}
1550
1551module_init(budget_ci_init);
1552module_exit(budget_ci_exit);
1553
1554MODULE_LICENSE("GPL");
1555MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
1556MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1557 "budget PCI DVB cards w/ CI-module produced by "
1558 "Siemens, Technotrend, Hauppauge");