blob: 1d79ada864d6a9c9510529309f0a486e9f0e9b79 [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 *
Mauro Carvalho Chehabaf86ce72011-01-24 12:18:48 -030029 * 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;
Mauro Carvalho Chehabaf86ce72011-01-24 12:18:48 -0300105 bool full_rc5; /* Outputs a full RC5 code */
David Hardemandd2f3982006-12-02 21:16:05 -0200106};
107
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108struct budget_ci {
109 struct budget budget;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 struct tasklet_struct ciintf_irq_tasklet;
111 int slot_status;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300112 int ci_irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 struct dvb_ca_en50221 ca;
David Hardemandd2f3982006-12-02 21:16:05 -0200114 struct budget_ci_ir ir;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700115 u8 tuner_pll_address; /* used for philips_tdm1316l configs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116};
117
David Hardeman2520fff2006-12-02 21:16:05 -0200118static void msp430_ir_interrupt(unsigned long data)
119{
120 struct budget_ci *budget_ci = (struct budget_ci *) data;
David Härdemand8b4b582010-10-29 16:08:23 -0300121 struct rc_dev *dev = budget_ci->ir.dev;
David Hardeman2520fff2006-12-02 21:16:05 -0200122 u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
123
David Hardeman64741b72006-12-02 21:16:05 -0200124 /*
125 * The msp430 chip can generate two different bytes, command and device
126 *
127 * type1: X1CCCCCC, C = command bits (0 - 63)
128 * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
129 *
David Härdeman59327a42007-02-13 09:39:58 -0300130 * Each signal from the remote control can generate one or more command
131 * bytes and one or more device bytes. For the repeated bytes, the
132 * highest bit (X) is set. The first command byte is always generated
133 * before the first device byte. Other than that, no specific order
David Härdeman145859c2007-04-27 12:31:22 -0300134 * seems to apply. To make life interesting, bytes can also be lost.
David Härdeman59327a42007-02-13 09:39:58 -0300135 *
136 * Only when we have a command and device byte, a keypress is
137 * generated.
David Hardeman64741b72006-12-02 21:16:05 -0200138 */
139
David Härdeman59327a42007-02-13 09:39:58 -0300140 if (ir_debug)
141 printk("budget_ci: received byte 0x%02x\n", command);
142
David Härdeman145859c2007-04-27 12:31:22 -0300143 /* Remove repeat bit, we use every command */
144 command = command & 0x7f;
David Härdeman59327a42007-02-13 09:39:58 -0300145
David Hardeman64741b72006-12-02 21:16:05 -0200146 /* Is this a RC5 command byte? */
David Hardeman2520fff2006-12-02 21:16:05 -0200147 if (command & 0x40) {
David Härdeman145859c2007-04-27 12:31:22 -0300148 budget_ci->ir.have_command = true;
149 budget_ci->ir.ir_key = command & 0x3f;
David Hardeman64741b72006-12-02 21:16:05 -0200150 return;
David Hardeman2520fff2006-12-02 21:16:05 -0200151 }
David Hardeman64741b72006-12-02 21:16:05 -0200152
153 /* It's a RC5 device byte */
David Härdeman145859c2007-04-27 12:31:22 -0300154 if (!budget_ci->ir.have_command)
David Härdeman59327a42007-02-13 09:39:58 -0300155 return;
David Härdeman145859c2007-04-27 12:31:22 -0300156 budget_ci->ir.have_command = false;
David Hardeman64741b72006-12-02 21:16:05 -0200157
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 Chehabaf86ce72011-01-24 12:18:48 -0300162 if (budget_ci->ir.full_rc5) {
163 rc_keydown(dev,
164 budget_ci->ir.rc5_device <<8 | budget_ci->ir.ir_key,
165 (command & 0x20) ? 1 : 0);
166 return;
167 }
168
169 /* FIXME: We should generate complete scancodes for all devices */
Mauro Carvalho Chehabca866742010-11-17 13:53:11 -0300170 rc_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0);
David Hardeman2520fff2006-12-02 21:16:05 -0200171}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173static int msp430_ir_init(struct budget_ci *budget_ci)
174{
175 struct saa7146_dev *saa = budget_ci->budget.dev;
David Härdemand8b4b582010-10-29 16:08:23 -0300176 struct rc_dev *dev;
David Hardeman8cc532e2006-12-02 21:16:05 -0200177 int error;
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300178
David Härdemand8b4b582010-10-29 16:08:23 -0300179 dev = rc_allocate_device();
180 if (!dev) {
David Hardemanee579bc2006-12-02 21:16:05 -0200181 printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300182 return -ENOMEM;
David Hardeman8cc532e2006-12-02 21:16:05 -0200183 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184
David Hardemandd2f3982006-12-02 21:16:05 -0200185 snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
186 "Budget-CI dvb ir receiver %s", saa->name);
David Hardeman5cc8ae02006-12-02 21:16:05 -0200187 snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
188 "pci-%s/ir0", pci_name(saa->pci));
189
David Härdemand8b4b582010-10-29 16:08:23 -0300190 dev->driver_name = MODULE_NAME;
191 dev->input_name = budget_ci->ir.name;
192 dev->input_phys = budget_ci->ir.phys;
193 dev->input_id.bustype = BUS_PCI;
194 dev->input_id.version = 1;
David Henningsson730726a2010-12-27 15:41:58 -0300195 dev->scanmask = 0xff;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200196 if (saa->pci->subsystem_vendor) {
David Härdemand8b4b582010-10-29 16:08:23 -0300197 dev->input_id.vendor = saa->pci->subsystem_vendor;
198 dev->input_id.product = saa->pci->subsystem_device;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200199 } else {
David Härdemand8b4b582010-10-29 16:08:23 -0300200 dev->input_id.vendor = saa->pci->vendor;
201 dev->input_id.product = saa->pci->device;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200202 }
David Härdemand8b4b582010-10-29 16:08:23 -0300203 dev->dev.parent = &saa->pci->dev;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200204
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300205 if (rc5_device < 0)
206 budget_ci->ir.rc5_device = IR_DEVICE_ANY;
207 else
208 budget_ci->ir.rc5_device = rc5_device;
209
David Hardeman64741b72006-12-02 21:16:05 -0200210 /* Select keymap and address */
David Hardeman2520fff2006-12-02 21:16:05 -0200211 switch (budget_ci->budget.dev->pci->subsystem_device) {
212 case 0x100c:
213 case 0x100f:
David Hardeman2520fff2006-12-02 21:16:05 -0200214 case 0x1011:
215 case 0x1012:
David Hardeman2520fff2006-12-02 21:16:05 -0200216 /* The hauppauge keymap is a superset of these remotes */
Mauro Carvalho Chehabaf86ce72011-01-24 12:18:48 -0300217 dev->map_name = RC_MAP_HAUPPAUGE;
218 budget_ci->ir.full_rc5 = true;
David Hardeman64741b72006-12-02 21:16:05 -0200219
220 if (rc5_device < 0)
221 budget_ci->ir.rc5_device = 0x1f;
David Hardeman2520fff2006-12-02 21:16:05 -0200222 break;
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300223 case 0x1010:
Oliver Endrissf64899c2007-09-17 22:17:12 -0300224 case 0x1017:
Hermann Gaustererf137f9d2010-05-18 04:26:17 -0300225 case 0x1019:
Oliver Endrissbbfc4c22008-06-19 23:36:45 -0300226 case 0x101a:
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300227 /* for the Technotrend 1500 bundled remote */
David Härdemand8b4b582010-10-29 16:08:23 -0300228 dev->map_name = RC_MAP_TT_1500;
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300229 break;
David Hardeman2520fff2006-12-02 21:16:05 -0200230 default:
231 /* unknown remote */
David Härdemand8b4b582010-10-29 16:08:23 -0300232 dev->map_name = RC_MAP_BUDGET_CI_OLD;
David Hardeman2520fff2006-12-02 21:16:05 -0200233 break;
234 }
235
David Härdemand8b4b582010-10-29 16:08:23 -0300236 error = rc_register_device(dev);
David Hardeman8cc532e2006-12-02 21:16:05 -0200237 if (error) {
238 printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
David Härdemand8b4b582010-10-29 16:08:23 -0300239 rc_free_device(dev);
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300240 return error;
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300241 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242
David Härdemand8b4b582010-10-29 16:08:23 -0300243 budget_ci->ir.dev = dev;
David Härdeman145859c2007-04-27 12:31:22 -0300244
David Hardeman8cc532e2006-12-02 21:16:05 -0200245 tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
246 (unsigned long) budget_ci);
247
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300248 SAA7146_IER_ENABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
250
251 return 0;
252}
253
254static void msp430_ir_deinit(struct budget_ci *budget_ci)
255{
256 struct saa7146_dev *saa = budget_ci->budget.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300258 SAA7146_IER_DISABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
David Hardeman8cc532e2006-12-02 21:16:05 -0200260 tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
David Härdemand8b4b582010-10-29 16:08:23 -0300262 rc_unregister_device(budget_ci->ir.dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263}
264
265static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
266{
267 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
268
269 if (slot != 0)
270 return -EINVAL;
271
272 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
273 DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);
274}
275
276static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
277{
278 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
279
280 if (slot != 0)
281 return -EINVAL;
282
283 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
284 DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);
285}
286
287static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
288{
289 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
290
291 if (slot != 0)
292 return -EINVAL;
293
294 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
295 DEBIADDR_IO | (address & 3), 1, 1, 0);
296}
297
298static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
299{
300 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
301
302 if (slot != 0)
303 return -EINVAL;
304
305 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
306 DEBIADDR_IO | (address & 3), 1, value, 1, 0);
307}
308
309static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
310{
311 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
312 struct saa7146_dev *saa = budget_ci->budget.dev;
313
314 if (slot != 0)
315 return -EINVAL;
316
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300317 if (budget_ci->ci_irq) {
318 // trigger on RISING edge during reset so we know when READY is re-asserted
319 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
320 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 budget_ci->slot_status = SLOTSTATUS_RESET;
322 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
323 msleep(1);
324 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
325 CICONTROL_RESET, 1, 0);
326
327 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
328 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
329 return 0;
330}
331
332static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
333{
334 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
335 struct saa7146_dev *saa = budget_ci->budget.dev;
336
337 if (slot != 0)
338 return -EINVAL;
339
340 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
341 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
342 return 0;
343}
344
345static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
346{
347 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
348 struct saa7146_dev *saa = budget_ci->budget.dev;
349 int tmp;
350
351 if (slot != 0)
352 return -EINVAL;
353
354 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
355
356 tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
357 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
358 tmp | CICONTROL_ENABLETS, 1, 0);
359
360 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
361 return 0;
362}
363
364static void ciintf_interrupt(unsigned long data)
365{
366 struct budget_ci *budget_ci = (struct budget_ci *) data;
367 struct saa7146_dev *saa = budget_ci->budget.dev;
368 unsigned int flags;
369
370 // ensure we don't get spurious IRQs during initialisation
371 if (!budget_ci->budget.ci_present)
372 return;
373
374 // read the CAM status
375 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
376 if (flags & CICONTROL_CAMDETECT) {
377
378 // GPIO should be set to trigger on falling edge if a CAM is present
379 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
380
381 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
382 // CAM insertion IRQ
383 budget_ci->slot_status = SLOTSTATUS_PRESENT;
384 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
385 DVB_CA_EN50221_CAMCHANGE_INSERTED);
386
387 } else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
388 // CAM ready (reset completed)
389 budget_ci->slot_status = SLOTSTATUS_READY;
390 dvb_ca_en50221_camready_irq(&budget_ci->ca, 0);
391
392 } else if (budget_ci->slot_status & SLOTSTATUS_READY) {
393 // FR/DA IRQ
394 dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);
395 }
396 } else {
397
398 // trigger on rising edge if a CAM is not present - when a CAM is inserted, we
399 // only want to get the IRQ when it sets READY. If we trigger on the falling edge,
400 // the CAM might not actually be ready yet.
401 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
402
403 // generate a CAM removal IRQ if we haven't already
404 if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
405 // CAM removal IRQ
406 budget_ci->slot_status = SLOTSTATUS_NONE;
407 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
408 DVB_CA_EN50221_CAMCHANGE_REMOVED);
409 }
410 }
411}
412
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300413static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
414{
415 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
416 unsigned int flags;
417
418 // ensure we don't get spurious IRQs during initialisation
419 if (!budget_ci->budget.ci_present)
420 return -EINVAL;
421
422 // read the CAM status
423 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
424 if (flags & CICONTROL_CAMDETECT) {
425 // mark it as present if it wasn't before
426 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
427 budget_ci->slot_status = SLOTSTATUS_PRESENT;
428 }
429
430 // during a RESET, we check if we can read from IO memory to see when CAM is ready
431 if (budget_ci->slot_status & SLOTSTATUS_RESET) {
432 if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
433 budget_ci->slot_status = SLOTSTATUS_READY;
434 }
435 }
436 } else {
437 budget_ci->slot_status = SLOTSTATUS_NONE;
438 }
439
440 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
441 if (budget_ci->slot_status & SLOTSTATUS_READY) {
442 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
443 }
444 return DVB_CA_EN50221_POLL_CAM_PRESENT;
445 }
446
447 return 0;
448}
449
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450static int ciintf_init(struct budget_ci *budget_ci)
451{
452 struct saa7146_dev *saa = budget_ci->budget.dev;
453 int flags;
454 int result;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300455 int ci_version;
456 int ca_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457
458 memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
459
460 // enable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300461 saa7146_write(saa, MC1, MASK_27 | MASK_11);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462
463 // test if it is there
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300464 ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
465 if ((ci_version & 0xa0) != 0xa0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 result = -ENODEV;
467 goto error;
468 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300469
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 // determine whether a CAM is present or not
471 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
472 budget_ci->slot_status = SLOTSTATUS_NONE;
473 if (flags & CICONTROL_CAMDETECT)
474 budget_ci->slot_status = SLOTSTATUS_PRESENT;
475
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300476 // version 0xa2 of the CI firmware doesn't generate interrupts
477 if (ci_version == 0xa2) {
478 ca_flags = 0;
479 budget_ci->ci_irq = 0;
480 } else {
481 ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
482 DVB_CA_EN50221_FLAG_IRQ_FR |
483 DVB_CA_EN50221_FLAG_IRQ_DA;
484 budget_ci->ci_irq = 1;
485 }
486
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 // register CI interface
488 budget_ci->ca.owner = THIS_MODULE;
489 budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
490 budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
491 budget_ci->ca.read_cam_control = ciintf_read_cam_control;
492 budget_ci->ca.write_cam_control = ciintf_write_cam_control;
493 budget_ci->ca.slot_reset = ciintf_slot_reset;
494 budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
495 budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300496 budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 budget_ci->ca.data = budget_ci;
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700498 if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 &budget_ci->ca,
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300500 ca_flags, 1)) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 printk("budget_ci: CI interface detected, but initialisation failed.\n");
502 goto error;
503 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300504
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 // Setup CI slot IRQ
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300506 if (budget_ci->ci_irq) {
507 tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
508 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
509 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
510 } else {
511 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
512 }
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300513 SAA7146_IER_ENABLE(saa, MASK_03);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300515
516 // enable interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
518 CICONTROL_RESET, 1, 0);
519
520 // success!
521 printk("budget_ci: CI interface initialised\n");
522 budget_ci->budget.ci_present = 1;
523
524 // forge a fake CI IRQ so the CAM state is setup correctly
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300525 if (budget_ci->ci_irq) {
526 flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
527 if (budget_ci->slot_status != SLOTSTATUS_NONE)
528 flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
529 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
530 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531
532 return 0;
533
534error:
Hartmut Birr2a893de2006-12-03 21:08:08 -0300535 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 return result;
537}
538
539static void ciintf_deinit(struct budget_ci *budget_ci)
540{
541 struct saa7146_dev *saa = budget_ci->budget.dev;
542
543 // disable CI interrupts
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300544 if (budget_ci->ci_irq) {
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300545 SAA7146_IER_DISABLE(saa, MASK_03);
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300546 saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
547 tasklet_kill(&budget_ci->ciintf_irq_tasklet);
548 }
549
550 // reset interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
552 msleep(1);
553 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
554 CICONTROL_RESET, 1, 0);
555
556 // disable TS data stream to CI interface
557 saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
558
559 // release the CA device
560 dvb_ca_en50221_release(&budget_ci->ca);
561
562 // disable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300563 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564}
565
566static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
567{
568 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
569
570 dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
571
572 if (*isr & MASK_06)
David Hardemandd2f3982006-12-02 21:16:05 -0200573 tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574
575 if (*isr & MASK_10)
576 ttpci_budget_irq10_handler(dev, isr);
577
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300578 if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
580}
581
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582static u8 philips_su1278_tt_inittab[] = {
583 0x01, 0x0f,
584 0x02, 0x30,
585 0x03, 0x00,
586 0x04, 0x5b,
587 0x05, 0x85,
588 0x06, 0x02,
589 0x07, 0x00,
590 0x08, 0x02,
591 0x09, 0x00,
592 0x0C, 0x01,
593 0x0D, 0x81,
594 0x0E, 0x44,
595 0x0f, 0x14,
596 0x10, 0x3c,
597 0x11, 0x84,
598 0x12, 0xda,
599 0x13, 0x97,
600 0x14, 0x95,
601 0x15, 0xc9,
602 0x16, 0x19,
603 0x17, 0x8c,
604 0x18, 0x59,
605 0x19, 0xf8,
606 0x1a, 0xfe,
607 0x1c, 0x7f,
608 0x1d, 0x00,
609 0x1e, 0x00,
610 0x1f, 0x50,
611 0x20, 0x00,
612 0x21, 0x00,
613 0x22, 0x00,
614 0x23, 0x00,
615 0x28, 0x00,
616 0x29, 0x28,
617 0x2a, 0x14,
618 0x2b, 0x0f,
619 0x2c, 0x09,
620 0x2d, 0x09,
621 0x31, 0x1f,
622 0x32, 0x19,
623 0x33, 0xfc,
624 0x34, 0x93,
625 0xff, 0xff
626};
627
628static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
629{
630 stv0299_writereg(fe, 0x0e, 0x44);
631 if (srate >= 10000000) {
632 stv0299_writereg(fe, 0x13, 0x97);
633 stv0299_writereg(fe, 0x14, 0x95);
634 stv0299_writereg(fe, 0x15, 0xc9);
635 stv0299_writereg(fe, 0x17, 0x8c);
636 stv0299_writereg(fe, 0x1a, 0xfe);
637 stv0299_writereg(fe, 0x1c, 0x7f);
638 stv0299_writereg(fe, 0x2d, 0x09);
639 } else {
640 stv0299_writereg(fe, 0x13, 0x99);
641 stv0299_writereg(fe, 0x14, 0x8d);
642 stv0299_writereg(fe, 0x15, 0xce);
643 stv0299_writereg(fe, 0x17, 0x43);
644 stv0299_writereg(fe, 0x1a, 0x1d);
645 stv0299_writereg(fe, 0x1c, 0x12);
646 stv0299_writereg(fe, 0x2d, 0x05);
647 }
648 stv0299_writereg(fe, 0x0e, 0x23);
649 stv0299_writereg(fe, 0x0f, 0x94);
650 stv0299_writereg(fe, 0x10, 0x39);
651 stv0299_writereg(fe, 0x15, 0xc9);
652
653 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
654 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
655 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
656
657 return 0;
658}
659
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300660static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,
661 struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662{
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300663 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 u32 div;
665 u8 buf[4];
666 struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
667
668 if ((params->frequency < 950000) || (params->frequency > 2150000))
669 return -EINVAL;
670
671 div = (params->frequency + (500 - 1)) / 500; // round correctly
672 buf[0] = (div >> 8) & 0x7f;
673 buf[1] = div & 0xff;
674 buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
675 buf[3] = 0x20;
676
677 if (params->u.qpsk.symbol_rate < 4000000)
678 buf[3] |= 1;
679
680 if (params->frequency < 1250000)
681 buf[3] |= 0;
682 else if (params->frequency < 1550000)
683 buf[3] |= 0x40;
684 else if (params->frequency < 2050000)
685 buf[3] |= 0x80;
686 else if (params->frequency < 2150000)
687 buf[3] |= 0xC0;
688
Patrick Boettcherdea74862006-05-14 05:01:31 -0300689 if (fe->ops.i2c_gate_ctrl)
690 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300691 if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 return -EIO;
693 return 0;
694}
695
696static struct stv0299_config philips_su1278_tt_config = {
697
698 .demod_address = 0x68,
699 .inittab = philips_su1278_tt_inittab,
700 .mclk = 64000000UL,
701 .invert = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 .skip_reinit = 1,
Oliver Endrissda2c7f62008-04-20 22:13:37 -0300703 .lock_output = STV0299_LOCKOUTPUT_1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 .volt13_op0_op1 = STV0299_VOLT13_OP1,
705 .min_delay_ms = 50,
706 .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707};
708
709
710
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300711static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712{
713 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
714 static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
715 static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700716 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 sizeof(td1316_init) };
718
719 // setup PLL configuration
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)
723 return -EIO;
724 msleep(1);
725
726 // disable the mc44BC374c (do not check for errors)
727 tuner_msg.addr = 0x65;
728 tuner_msg.buf = disable_mc44BC374c;
729 tuner_msg.len = sizeof(disable_mc44BC374c);
Patrick Boettcherdea74862006-05-14 05:01:31 -0300730 if (fe->ops.i2c_gate_ctrl)
731 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
Patrick Boettcherdea74862006-05-14 05:01:31 -0300733 if (fe->ops.i2c_gate_ctrl)
734 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
736 }
737
738 return 0;
739}
740
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300741static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742{
743 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
744 u8 tuner_buf[4];
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700745 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 -0700746 int tuner_frequency = 0;
747 u8 band, cp, filter;
748
749 // determine charge pump
750 tuner_frequency = params->frequency + 36130000;
751 if (tuner_frequency < 87000000)
752 return -EINVAL;
753 else if (tuner_frequency < 130000000)
754 cp = 3;
755 else if (tuner_frequency < 160000000)
756 cp = 5;
757 else if (tuner_frequency < 200000000)
758 cp = 6;
759 else if (tuner_frequency < 290000000)
760 cp = 3;
761 else if (tuner_frequency < 420000000)
762 cp = 5;
763 else if (tuner_frequency < 480000000)
764 cp = 6;
765 else if (tuner_frequency < 620000000)
766 cp = 3;
767 else if (tuner_frequency < 830000000)
768 cp = 5;
769 else if (tuner_frequency < 895000000)
770 cp = 7;
771 else
772 return -EINVAL;
773
774 // determine band
775 if (params->frequency < 49000000)
776 return -EINVAL;
777 else if (params->frequency < 159000000)
778 band = 1;
779 else if (params->frequency < 444000000)
780 band = 2;
781 else if (params->frequency < 861000000)
782 band = 4;
783 else
784 return -EINVAL;
785
786 // setup PLL filter and TDA9889
787 switch (params->u.ofdm.bandwidth) {
788 case BANDWIDTH_6_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300789 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 filter = 0;
791 break;
792
793 case BANDWIDTH_7_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300794 tda1004x_writereg(fe, 0x0C, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 filter = 0;
796 break;
797
798 case BANDWIDTH_8_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300799 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 filter = 1;
801 break;
802
803 default:
804 return -EINVAL;
805 }
806
807 // calculate divisor
808 // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
809 tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
810
811 // setup tuner buffer
812 tuner_buf[0] = tuner_frequency >> 8;
813 tuner_buf[1] = tuner_frequency & 0xff;
814 tuner_buf[2] = 0xca;
815 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
816
Patrick Boettcherdea74862006-05-14 05:01:31 -0300817 if (fe->ops.i2c_gate_ctrl)
818 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
820 return -EIO;
821
822 msleep(1);
823 return 0;
824}
825
826static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,
827 const struct firmware **fw, char *name)
828{
829 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
830
831 return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);
832}
833
834static struct tda1004x_config philips_tdm1316l_config = {
835
836 .demod_address = 0x8,
837 .invert = 0,
838 .invert_oclk = 0,
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700839 .xtal_freq = TDA10046_XTAL_4M,
840 .agc_config = TDA10046_AGC_DEFAULT,
841 .if_freq = TDA10046_FREQ_3617,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 .request_firmware = philips_tdm1316l_request_firmware,
843};
844
Oliver Endriss6c914492007-02-02 19:12:53 -0300845static struct tda1004x_config philips_tdm1316l_config_invert = {
846
847 .demod_address = 0x8,
848 .invert = 1,
849 .invert_oclk = 0,
850 .xtal_freq = TDA10046_XTAL_4M,
851 .agc_config = TDA10046_AGC_DEFAULT,
852 .if_freq = TDA10046_FREQ_3617,
853 .request_firmware = philips_tdm1316l_request_firmware,
854};
855
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300856static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700857{
858 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
859 u8 tuner_buf[5];
860 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
861 .flags = 0,
862 .buf = tuner_buf,
863 .len = sizeof(tuner_buf) };
864 int tuner_frequency = 0;
865 u8 band, cp, filter;
866
867 // determine charge pump
868 tuner_frequency = params->frequency + 36125000;
869 if (tuner_frequency < 87000000)
870 return -EINVAL;
871 else if (tuner_frequency < 130000000) {
872 cp = 3;
873 band = 1;
874 } else if (tuner_frequency < 160000000) {
875 cp = 5;
876 band = 1;
877 } else if (tuner_frequency < 200000000) {
878 cp = 6;
Oliver Endriss910a7b62007-05-03 13:16:12 -0300879 band = 1;
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700880 } else if (tuner_frequency < 290000000) {
881 cp = 3;
882 band = 2;
883 } else if (tuner_frequency < 420000000) {
884 cp = 5;
885 band = 2;
886 } else if (tuner_frequency < 480000000) {
887 cp = 6;
888 band = 2;
889 } else if (tuner_frequency < 620000000) {
890 cp = 3;
891 band = 4;
892 } else if (tuner_frequency < 830000000) {
893 cp = 5;
894 band = 4;
895 } else if (tuner_frequency < 895000000) {
896 cp = 7;
897 band = 4;
898 } else
899 return -EINVAL;
900
901 // assume PLL filter should always be 8MHz for the moment.
902 filter = 1;
903
904 // calculate divisor
905 tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
906
907 // setup tuner buffer
908 tuner_buf[0] = tuner_frequency >> 8;
909 tuner_buf[1] = tuner_frequency & 0xff;
910 tuner_buf[2] = 0xc8;
911 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
912 tuner_buf[4] = 0x80;
913
Patrick Boettcherdea74862006-05-14 05:01:31 -0300914 if (fe->ops.i2c_gate_ctrl)
915 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700916 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
917 return -EIO;
918
919 msleep(50);
920
Patrick Boettcherdea74862006-05-14 05:01:31 -0300921 if (fe->ops.i2c_gate_ctrl)
922 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700923 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
924 return -EIO;
925
926 msleep(1);
927
928 return 0;
929}
930
931static u8 dvbc_philips_tdm1316l_inittab[] = {
932 0x80, 0x01,
933 0x80, 0x00,
934 0x81, 0x01,
935 0x81, 0x00,
936 0x00, 0x09,
937 0x01, 0x69,
938 0x03, 0x00,
939 0x04, 0x00,
940 0x07, 0x00,
941 0x08, 0x00,
942 0x20, 0x00,
943 0x21, 0x40,
944 0x22, 0x00,
945 0x23, 0x00,
946 0x24, 0x40,
947 0x25, 0x88,
948 0x30, 0xff,
949 0x31, 0x00,
950 0x32, 0xff,
951 0x33, 0x00,
952 0x34, 0x50,
953 0x35, 0x7f,
954 0x36, 0x00,
955 0x37, 0x20,
956 0x38, 0x00,
957 0x40, 0x1c,
958 0x41, 0xff,
959 0x42, 0x29,
960 0x43, 0x20,
961 0x44, 0xff,
962 0x45, 0x00,
963 0x46, 0x00,
964 0x49, 0x04,
965 0x4a, 0x00,
966 0x4b, 0x7b,
967 0x52, 0x30,
968 0x55, 0xae,
969 0x56, 0x47,
970 0x57, 0xe1,
971 0x58, 0x3a,
972 0x5a, 0x1e,
973 0x5b, 0x34,
974 0x60, 0x00,
975 0x63, 0x00,
976 0x64, 0x00,
977 0x65, 0x00,
978 0x66, 0x00,
979 0x67, 0x00,
980 0x68, 0x00,
981 0x69, 0x00,
982 0x6a, 0x02,
983 0x6b, 0x00,
984 0x70, 0xff,
985 0x71, 0x00,
986 0x72, 0x00,
987 0x73, 0x00,
988 0x74, 0x0c,
989 0x80, 0x00,
990 0x81, 0x00,
991 0x82, 0x00,
992 0x83, 0x00,
993 0x84, 0x04,
994 0x85, 0x80,
995 0x86, 0x24,
996 0x87, 0x78,
997 0x88, 0x10,
998 0x89, 0x00,
999 0x90, 0x01,
1000 0x91, 0x01,
1001 0xa0, 0x04,
1002 0xa1, 0x00,
1003 0xa2, 0x00,
1004 0xb0, 0x91,
1005 0xb1, 0x0b,
1006 0xc0, 0x53,
1007 0xc1, 0x70,
1008 0xc2, 0x12,
1009 0xd0, 0x00,
1010 0xd1, 0x00,
1011 0xd2, 0x00,
1012 0xd3, 0x00,
1013 0xd4, 0x00,
1014 0xd5, 0x00,
1015 0xde, 0x00,
1016 0xdf, 0x00,
1017 0x61, 0x38,
1018 0x62, 0x0a,
1019 0x53, 0x13,
1020 0x59, 0x08,
1021 0xff, 0xff,
1022};
1023
1024static struct stv0297_config dvbc_philips_tdm1316l_config = {
1025 .demod_address = 0x1c,
1026 .inittab = dvbc_philips_tdm1316l_inittab,
1027 .invert = 0,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001028 .stop_during_read = 1,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001029};
1030
Sigmund Augdal11417da2008-06-15 17:25:46 -03001031static struct tda10023_config tda10023_config = {
1032 .demod_address = 0xc,
1033 .invert = 0,
1034 .xtal = 16000000,
1035 .pll_m = 11,
1036 .pll_p = 3,
1037 .pll_n = 1,
1038 .deltaf = 0xa511,
1039};
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001040
klaas de waalcf47d872009-03-25 17:53:02 -03001041static struct tda827x_config tda827x_config = {
1042 .config = 0,
1043};
1044
Manu Abrahama55bc842008-10-23 18:32:50 -03001045/* TT S2-3200 DVB-S (STB0899) Inittab */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001046static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001048 { STB0899_DEV_ID , 0x81 },
1049 { STB0899_DISCNTRL1 , 0x32 },
1050 { STB0899_DISCNTRL2 , 0x80 },
1051 { STB0899_DISRX_ST0 , 0x04 },
1052 { STB0899_DISRX_ST1 , 0x00 },
1053 { STB0899_DISPARITY , 0x00 },
1054 { STB0899_DISFIFO , 0x00 },
1055 { STB0899_DISSTATUS , 0x20 },
1056 { STB0899_DISF22 , 0x8c },
1057 { STB0899_DISF22RX , 0x9a },
Manu Abrahamef3052b2008-10-23 18:45:17 -03001058 { STB0899_SYSREG , 0x0b },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001059 { STB0899_ACRPRESC , 0x11 },
1060 { STB0899_ACRDIV1 , 0x0a },
1061 { STB0899_ACRDIV2 , 0x05 },
1062 { STB0899_DACR1 , 0x00 },
1063 { STB0899_DACR2 , 0x00 },
1064 { STB0899_OUTCFG , 0x00 },
1065 { STB0899_MODECFG , 0x00 },
1066 { STB0899_IRQSTATUS_3 , 0x30 },
1067 { STB0899_IRQSTATUS_2 , 0x00 },
1068 { STB0899_IRQSTATUS_1 , 0x00 },
1069 { STB0899_IRQSTATUS_0 , 0x00 },
1070 { STB0899_IRQMSK_3 , 0xf3 },
1071 { STB0899_IRQMSK_2 , 0xfc },
1072 { STB0899_IRQMSK_1 , 0xff },
1073 { STB0899_IRQMSK_0 , 0xff },
1074 { STB0899_IRQCFG , 0x00 },
1075 { STB0899_I2CCFG , 0x88 },
Manu Abraham40e8ce32008-02-03 19:37:02 -03001076 { STB0899_I2CRPT , 0x48 }, /* 12k Pullup, Repeater=16, Stop=disabled */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001077 { STB0899_IOPVALUE5 , 0x00 },
1078 { STB0899_IOPVALUE4 , 0x20 },
1079 { STB0899_IOPVALUE3 , 0xc9 },
1080 { STB0899_IOPVALUE2 , 0x90 },
1081 { STB0899_IOPVALUE1 , 0x40 },
1082 { STB0899_IOPVALUE0 , 0x00 },
1083 { STB0899_GPIO00CFG , 0x82 },
1084 { STB0899_GPIO01CFG , 0x82 },
1085 { STB0899_GPIO02CFG , 0x82 },
1086 { STB0899_GPIO03CFG , 0x82 },
1087 { STB0899_GPIO04CFG , 0x82 },
1088 { STB0899_GPIO05CFG , 0x82 },
1089 { STB0899_GPIO06CFG , 0x82 },
1090 { STB0899_GPIO07CFG , 0x82 },
1091 { STB0899_GPIO08CFG , 0x82 },
1092 { STB0899_GPIO09CFG , 0x82 },
1093 { STB0899_GPIO10CFG , 0x82 },
1094 { STB0899_GPIO11CFG , 0x82 },
1095 { STB0899_GPIO12CFG , 0x82 },
1096 { STB0899_GPIO13CFG , 0x82 },
1097 { STB0899_GPIO14CFG , 0x82 },
1098 { STB0899_GPIO15CFG , 0x82 },
1099 { STB0899_GPIO16CFG , 0x82 },
1100 { STB0899_GPIO17CFG , 0x82 },
1101 { STB0899_GPIO18CFG , 0x82 },
1102 { STB0899_GPIO19CFG , 0x82 },
1103 { STB0899_GPIO20CFG , 0x82 },
1104 { STB0899_SDATCFG , 0xb8 },
1105 { STB0899_SCLTCFG , 0xba },
Manu Abrahama55bc842008-10-23 18:32:50 -03001106 { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */
1107 { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */
1108 { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001109 { STB0899_DIRCLKCFG , 0x82 },
1110 { STB0899_CLKOUT27CFG , 0x7e },
1111 { STB0899_STDBYCFG , 0x82 },
1112 { STB0899_CS0CFG , 0x82 },
1113 { STB0899_CS1CFG , 0x82 },
1114 { STB0899_DISEQCOCFG , 0x20 },
1115 { STB0899_GPIO32CFG , 0x82 },
1116 { STB0899_GPIO33CFG , 0x82 },
1117 { STB0899_GPIO34CFG , 0x82 },
1118 { STB0899_GPIO35CFG , 0x82 },
1119 { STB0899_GPIO36CFG , 0x82 },
1120 { STB0899_GPIO37CFG , 0x82 },
1121 { STB0899_GPIO38CFG , 0x82 },
1122 { STB0899_GPIO39CFG , 0x82 },
Manu Abrahamf2e52cd2007-11-19 16:44:47 -03001123 { STB0899_NCOARSE , 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
Manu Abrahama55bc842008-10-23 18:32:50 -03001124 { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001125 { STB0899_FILTCTRL , 0x00 },
1126 { STB0899_SYSCTRL , 0x00 },
1127 { STB0899_STOPCLK1 , 0x20 },
1128 { STB0899_STOPCLK2 , 0x00 },
1129 { STB0899_INTBUFSTATUS , 0x00 },
1130 { STB0899_INTBUFCTRL , 0x0a },
1131 { 0xffff , 0xff },
1132};
1133
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001134static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = {
1135 { STB0899_DEMOD , 0x00 },
1136 { STB0899_RCOMPC , 0xc9 },
1137 { STB0899_AGC1CN , 0x41 },
1138 { STB0899_AGC1REF , 0x10 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001139 { STB0899_RTC , 0x7a },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001140 { STB0899_TMGCFG , 0x4e },
1141 { STB0899_AGC2REF , 0x34 },
1142 { STB0899_TLSR , 0x84 },
1143 { STB0899_CFD , 0xc7 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001144 { STB0899_ACLC , 0x87 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001145 { STB0899_BCLC , 0x94 },
1146 { STB0899_EQON , 0x41 },
1147 { STB0899_LDT , 0xdd },
1148 { STB0899_LDT2 , 0xc9 },
1149 { STB0899_EQUALREF , 0xb4 },
1150 { STB0899_TMGRAMP , 0x10 },
1151 { STB0899_TMGTHD , 0x30 },
1152 { STB0899_IDCCOMP , 0xfb },
1153 { STB0899_QDCCOMP , 0x03 },
1154 { STB0899_POWERI , 0x3b },
1155 { STB0899_POWERQ , 0x3d },
1156 { STB0899_RCOMP , 0x81 },
1157 { STB0899_AGCIQIN , 0x80 },
1158 { STB0899_AGC2I1 , 0x04 },
1159 { STB0899_AGC2I2 , 0xf5 },
1160 { STB0899_TLIR , 0x25 },
1161 { STB0899_RTF , 0x80 },
1162 { STB0899_DSTATUS , 0x00 },
1163 { STB0899_LDI , 0xca },
1164 { STB0899_CFRM , 0xf1 },
1165 { STB0899_CFRL , 0xf3 },
1166 { STB0899_NIRM , 0x2a },
1167 { STB0899_NIRL , 0x05 },
1168 { STB0899_ISYMB , 0x17 },
1169 { STB0899_QSYMB , 0xfa },
1170 { STB0899_SFRH , 0x2f },
1171 { STB0899_SFRM , 0x68 },
1172 { STB0899_SFRL , 0x40 },
1173 { STB0899_SFRUPH , 0x2f },
1174 { STB0899_SFRUPM , 0x68 },
1175 { STB0899_SFRUPL , 0x40 },
1176 { STB0899_EQUAI1 , 0xfd },
1177 { STB0899_EQUAQ1 , 0x04 },
1178 { STB0899_EQUAI2 , 0x0f },
1179 { STB0899_EQUAQ2 , 0xff },
1180 { STB0899_EQUAI3 , 0xdf },
1181 { STB0899_EQUAQ3 , 0xfa },
1182 { STB0899_EQUAI4 , 0x37 },
1183 { STB0899_EQUAQ4 , 0x0d },
1184 { STB0899_EQUAI5 , 0xbd },
1185 { STB0899_EQUAQ5 , 0xf7 },
1186 { STB0899_DSTATUS2 , 0x00 },
1187 { STB0899_VSTATUS , 0x00 },
1188 { STB0899_VERROR , 0xff },
1189 { STB0899_IQSWAP , 0x2a },
1190 { STB0899_ECNT1M , 0x00 },
1191 { STB0899_ECNT1L , 0x00 },
1192 { STB0899_ECNT2M , 0x00 },
1193 { STB0899_ECNT2L , 0x00 },
1194 { STB0899_ECNT3M , 0x00 },
1195 { STB0899_ECNT3L , 0x00 },
1196 { STB0899_FECAUTO1 , 0x06 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001197 { STB0899_FECM , 0x01 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001198 { STB0899_VTH12 , 0xf0 },
1199 { STB0899_VTH23 , 0xa0 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001200 { STB0899_VTH34 , 0x78 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001201 { STB0899_VTH56 , 0x4e },
1202 { STB0899_VTH67 , 0x48 },
1203 { STB0899_VTH78 , 0x38 },
1204 { STB0899_PRVIT , 0xff },
1205 { STB0899_VITSYNC , 0x19 },
Manu Abrahama55bc842008-10-23 18:32:50 -03001206 { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001207 { STB0899_TSULC , 0x42 },
1208 { STB0899_RSLLC , 0x40 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001209 { STB0899_TSLPL , 0x12 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001210 { STB0899_TSCFGH , 0x0c },
1211 { STB0899_TSCFGM , 0x00 },
1212 { STB0899_TSCFGL , 0x0c },
Manu Abrahamc1426df2009-11-13 18:51:39 -03001213 { STB0899_TSOUT , 0x4d }, /* 0x0d for CAM */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001214 { STB0899_RSSYNCDEL , 0x00 },
1215 { STB0899_TSINHDELH , 0x02 },
1216 { STB0899_TSINHDELM , 0x00 },
1217 { STB0899_TSINHDELL , 0x00 },
1218 { STB0899_TSLLSTKM , 0x00 },
1219 { STB0899_TSLLSTKL , 0x00 },
1220 { STB0899_TSULSTKM , 0x00 },
1221 { STB0899_TSULSTKL , 0xab },
1222 { STB0899_PCKLENUL , 0x00 },
1223 { STB0899_PCKLENLL , 0xcc },
1224 { STB0899_RSPCKLEN , 0xcc },
1225 { STB0899_TSSTATUS , 0x80 },
1226 { STB0899_ERRCTRL1 , 0xb6 },
1227 { STB0899_ERRCTRL2 , 0x96 },
1228 { STB0899_ERRCTRL3 , 0x89 },
1229 { STB0899_DMONMSK1 , 0x27 },
1230 { STB0899_DMONMSK0 , 0x03 },
1231 { STB0899_DEMAPVIT , 0x5c },
1232 { STB0899_PLPARM , 0x1f },
1233 { STB0899_PDELCTRL , 0x48 },
1234 { STB0899_PDELCTRL2 , 0x00 },
1235 { STB0899_BBHCTRL1 , 0x00 },
1236 { STB0899_BBHCTRL2 , 0x00 },
1237 { STB0899_HYSTTHRESH , 0x77 },
1238 { STB0899_MATCSTM , 0x00 },
1239 { STB0899_MATCSTL , 0x00 },
1240 { STB0899_UPLCSTM , 0x00 },
1241 { STB0899_UPLCSTL , 0x00 },
1242 { STB0899_DFLCSTM , 0x00 },
1243 { STB0899_DFLCSTL , 0x00 },
1244 { STB0899_SYNCCST , 0x00 },
1245 { STB0899_SYNCDCSTM , 0x00 },
1246 { STB0899_SYNCDCSTL , 0x00 },
1247 { STB0899_ISI_ENTRY , 0x00 },
1248 { STB0899_ISI_BIT_EN , 0x00 },
1249 { STB0899_MATSTRM , 0x00 },
1250 { STB0899_MATSTRL , 0x00 },
1251 { STB0899_UPLSTRM , 0x00 },
1252 { STB0899_UPLSTRL , 0x00 },
1253 { STB0899_DFLSTRM , 0x00 },
1254 { STB0899_DFLSTRL , 0x00 },
1255 { STB0899_SYNCSTR , 0x00 },
1256 { STB0899_SYNCDSTRM , 0x00 },
1257 { STB0899_SYNCDSTRL , 0x00 },
1258 { STB0899_CFGPDELSTATUS1 , 0x10 },
1259 { STB0899_CFGPDELSTATUS2 , 0x00 },
1260 { STB0899_BBFERRORM , 0x00 },
1261 { STB0899_BBFERRORL , 0x00 },
1262 { STB0899_UPKTERRORM , 0x00 },
1263 { STB0899_UPKTERRORL , 0x00 },
1264 { 0xffff , 0xff },
1265};
1266
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001267static struct stb0899_config tt3200_config = {
1268 .init_dev = tt3200_stb0899_s1_init_1,
Manu Abraham8be969b2008-01-25 18:20:48 -03001269 .init_s2_demod = stb0899_s2_init_2,
Manu Abrahama55bc842008-10-23 18:32:50 -03001270 .init_s1_demod = tt3200_stb0899_s1_init_3,
Manu Abraham8be969b2008-01-25 18:20:48 -03001271 .init_s2_fec = stb0899_s2_init_4,
1272 .init_tst = stb0899_s1_init_5,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001273
Manu Abraham043a68b2008-01-18 14:15:17 -03001274 .postproc = NULL,
1275
Manu Abrahama55bc842008-10-23 18:32:50 -03001276 .demod_address = 0x68,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001277
1278 .xtal_freq = 27000000,
Manu Abrahame99d00c2007-09-25 17:48:59 -03001279 .inversion = IQ_SWAP_ON, /* 1 */
Manu Abrahama55bc842008-10-23 18:32:50 -03001280
Manu Abrahamb91a7cb2008-03-04 19:19:58 -03001281 .lo_clk = 76500000,
1282 .hi_clk = 99000000,
1283
Manu Abraham8be969b2008-01-25 18:20:48 -03001284 .esno_ave = STB0899_DVBS2_ESNO_AVE,
1285 .esno_quant = STB0899_DVBS2_ESNO_QUANT,
1286 .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
1287 .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
1288 .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
1289 .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
1290 .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
1291 .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
1292 .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
Manu Abrahama55bc842008-10-23 18:32:50 -03001293
Manu Abraham8be969b2008-01-25 18:20:48 -03001294 .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
1295 .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
1296 .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
1297 .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
Manu Abrahama55bc842008-10-23 18:32:50 -03001298
1299 .tuner_get_frequency = stb6100_get_frequency,
1300 .tuner_set_frequency = stb6100_set_frequency,
1301 .tuner_set_bandwidth = stb6100_set_bandwidth,
1302 .tuner_get_bandwidth = stb6100_get_bandwidth,
Manu Abraham043a68b2008-01-18 14:15:17 -03001303 .tuner_set_rfsiggain = NULL
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001304};
1305
Mauro Carvalho Chehabffbc5f82009-01-05 01:34:20 -03001306static struct stb6100_config tt3200_stb6100_config = {
Manu Abrahamc14eaed2007-10-04 16:52:51 -03001307 .tuner_address = 0x60,
1308 .refclock = 27000000,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001309};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310
1311static void frontend_init(struct budget_ci *budget_ci)
1312{
1313 switch (budget_ci->budget.dev->pci->subsystem_device) {
1314 case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
1315 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001316 dvb_attach(stv0299_attach, &alps_bsru6_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 = alps_bsru6_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001319 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 break;
1321 }
1322 break;
1323
1324 case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
1325 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001326 dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -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 = philips_su1278_tt_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 break;
1330 }
1331 break;
1332
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001333 case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
1334 budget_ci->tuner_pll_address = 0x61;
1335 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001336 dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001337 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001338 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001339 break;
1340 }
1341 break;
1342
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001344 budget_ci->tuner_pll_address = 0x63;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001346 dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001348 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1349 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 break;
1351 }
1352 break;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001353
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001354 case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001355 budget_ci->tuner_pll_address = 0x60;
1356 budget_ci->budget.dvb_frontend =
Oliver Endriss6c914492007-02-02 19:12:53 -03001357 dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001358 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001359 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1360 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001361 break;
1362 }
1363 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001364
1365 case 0x1017: // TT S-1500 PCI
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001366 budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001367 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001368 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001369 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
1370
Patrick Boettcherdea74862006-05-14 05:01:31 -03001371 budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001372 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 -03001373 printk("%s: No LNBP21 found!\n", __func__);
Andrew de Quincey2b100e72006-08-08 09:10:11 -03001374 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001375 budget_ci->budget.dvb_frontend = NULL;
1376 }
1377 }
Sigmund Augdal11417da2008-06-15 17:25:46 -03001378 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001379
Sigmund Augdal11417da2008-06-15 17:25:46 -03001380 case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */
1381 budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48);
1382 if (budget_ci->budget.dvb_frontend) {
klaas de waalcf47d872009-03-25 17:53:02 -03001383 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 -03001384 printk(KERN_ERR "%s: No tda827x found!\n", __func__);
1385 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1386 budget_ci->budget.dvb_frontend = NULL;
1387 }
1388 }
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001389 break;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001390
1391 case 0x1019: // TT S2-3200 PCI
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001392 /*
1393 * NOTE! on some STB0899 versions, the internal PLL takes a longer time
1394 * to settle, aka LOCK. On the older revisions of the chip, we don't see
1395 * this, as a result on the newer chips the entire clock tree, will not
1396 * be stable after a freshly POWER 'ed up situation.
1397 * In this case, we should RESET the STB0899 (Active LOW) and wait for
1398 * PLL stabilization.
1399 *
1400 * On the TT S2 3200 and clones, the STB0899 demodulator's RESETB is
1401 * connected to the SAA7146 GPIO, GPIO2, Pin 142
1402 */
1403 /* Reset Demodulator */
Manu Abraham0867f572007-10-15 13:07:16 -03001404 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001405 /* Wait for everything to die */
1406 msleep(50);
1407 /* Pull it up out of Reset state */
Manu Abraham0867f572007-10-15 13:07:16 -03001408 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001409 /* Wait for PLL to stabilize */
1410 msleep(250);
1411 /*
1412 * PLL state should be stable now. Ideally, we should check
1413 * for PLL LOCK status. But well, never mind!
1414 */
Manu Abrahamae9902d2007-10-08 18:51:54 -03001415 budget_ci->budget.dvb_frontend = dvb_attach(stb0899_attach, &tt3200_config, &budget_ci->budget.i2c_adap);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001416 if (budget_ci->budget.dvb_frontend) {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001417 if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {
1418 if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
Harvey Harrison9b4778f2009-01-07 14:42:41 -08001419 printk("%s: No LNBP21 found!\n", __func__);
Manu Abrahamae9902d2007-10-08 18:51:54 -03001420 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001421 budget_ci->budget.dvb_frontend = NULL;
1422 }
1423 } else {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001424 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1425 budget_ci->budget.dvb_frontend = NULL;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001426 }
1427 }
1428 break;
1429
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 }
1431
1432 if (budget_ci->budget.dvb_frontend == NULL) {
Bjorn Helgaas29e66a62008-09-04 17:24:51 -03001433 printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 budget_ci->budget.dev->pci->vendor,
1435 budget_ci->budget.dev->pci->device,
1436 budget_ci->budget.dev->pci->subsystem_vendor,
1437 budget_ci->budget.dev->pci->subsystem_device);
1438 } else {
1439 if (dvb_register_frontend
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001440 (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 printk("budget-ci: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001442 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 budget_ci->budget.dvb_frontend = NULL;
1444 }
1445 }
1446}
1447
1448static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
1449{
1450 struct budget_ci *budget_ci;
1451 int err;
1452
David Hardemanee579bc2006-12-02 21:16:05 -02001453 budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
David Hardeman8cc532e2006-12-02 21:16:05 -02001454 if (!budget_ci) {
1455 err = -ENOMEM;
1456 goto out1;
1457 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
1459 dprintk(2, "budget_ci: %p\n", budget_ci);
1460
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 dev->ext_priv = budget_ci;
1462
Janne Grunau26dc4d02008-09-21 20:50:11 -03001463 err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE,
1464 adapter_nr);
David Hardeman8cc532e2006-12-02 21:16:05 -02001465 if (err)
1466 goto out2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
David Hardeman8cc532e2006-12-02 21:16:05 -02001468 err = msp430_ir_init(budget_ci);
1469 if (err)
1470 goto out3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
1472 ciintf_init(budget_ci);
1473
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001474 budget_ci->budget.dvb_adapter.priv = budget_ci;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 frontend_init(budget_ci);
1476
Oliver Endriss32e4c3a2006-07-18 22:55:23 -03001477 ttpci_budget_init_hooks(&budget_ci->budget);
1478
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 return 0;
David Hardeman8cc532e2006-12-02 21:16:05 -02001480
1481out3:
1482 ttpci_budget_deinit(&budget_ci->budget);
1483out2:
1484 kfree(budget_ci);
1485out1:
1486 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487}
1488
1489static int budget_ci_detach(struct saa7146_dev *dev)
1490{
1491 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
1492 struct saa7146_dev *saa = budget_ci->budget.dev;
1493 int err;
1494
1495 if (budget_ci->budget.ci_present)
1496 ciintf_deinit(budget_ci);
David Hardeman8cc532e2006-12-02 21:16:05 -02001497 msp430_ir_deinit(budget_ci);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001498 if (budget_ci->budget.dvb_frontend) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001500 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001501 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 err = ttpci_budget_deinit(&budget_ci->budget);
1503
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 // disable frontend and CI interface
1505 saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
1506
1507 kfree(budget_ci);
1508
1509 return err;
1510}
1511
1512static struct saa7146_extension budget_extension;
1513
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001514MAKE_BUDGET_INFO(ttbs2, "TT-Budget/S-1500 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
1516MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001517MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001518MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
Sigmund Augdal11417da2008-06-15 17:25:46 -03001519MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001520MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521
1522static struct pci_device_id pci_tbl[] = {
1523 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
1524 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001525 MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001527 MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001528 MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
Sigmund Augdal11417da2008-06-15 17:25:46 -03001529 MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001530 MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 {
1532 .vendor = 0,
1533 }
1534};
1535
1536MODULE_DEVICE_TABLE(pci, pci_tbl);
1537
1538static struct saa7146_extension budget_extension = {
Dave Jones0e367a12006-08-07 13:18:56 -03001539 .name = "budget_ci dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03001540 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541
1542 .module = THIS_MODULE,
1543 .pci_tbl = &pci_tbl[0],
1544 .attach = budget_ci_attach,
1545 .detach = budget_ci_detach,
1546
1547 .irq_mask = MASK_03 | MASK_06 | MASK_10,
1548 .irq_func = budget_ci_irq,
1549};
1550
1551static int __init budget_ci_init(void)
1552{
1553 return saa7146_register_extension(&budget_extension);
1554}
1555
1556static void __exit budget_ci_exit(void)
1557{
1558 saa7146_unregister_extension(&budget_extension);
1559}
1560
1561module_init(budget_ci_init);
1562module_exit(budget_ci_exit);
1563
1564MODULE_LICENSE("GPL");
1565MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
1566MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1567 "budget PCI DVB cards w/ CI-module produced by "
1568 "Siemens, Technotrend, Hauppauge");