blob: a9c2c326df4b2ba895664b9841995de73b7b7528 [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>
36#include <linux/input.h>
37#include <linux/spinlock.h>
David Härdeman13c24492010-04-02 15:58:30 -030038#include <media/ir-core.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
Trent Piepho68277092007-01-30 23:25:46 -030040#include "budget.h"
41
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include "dvb_ca_en50221.h"
43#include "stv0299.h"
Andrew de Quinceydc27a162005-09-09 13:03:07 -070044#include "stv0297.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include "tda1004x.h"
Marko Schluessler9e0dc662008-10-23 18:16:40 -030046#include "stb0899_drv.h"
47#include "stb0899_reg.h"
Manu Abraham8be969b2008-01-25 18:20:48 -030048#include "stb0899_cfg.h"
Marko Schluessler9e0dc662008-10-23 18:16:40 -030049#include "stb6100.h"
Manu Abraham8be969b2008-01-25 18:20:48 -030050#include "stb6100_cfg.h"
Perceval Anichini8cc2e372006-02-28 09:52:44 -030051#include "lnbp21.h"
52#include "bsbe1.h"
Perceval Anichini265366e2006-03-16 11:22:47 -030053#include "bsru6.h"
Sigmund Augdal11417da2008-06-15 17:25:46 -030054#include "tda1002x.h"
55#include "tda827x.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
Mauro Carvalho Chehab727e6252010-03-12 21:18:14 -030057#define MODULE_NAME "budget_ci"
58
David Härdemanecba77f2006-10-27 20:56:51 -030059/*
60 * Regarding DEBIADDR_IR:
61 * Some CI modules hang if random addresses are read.
62 * Using address 0x4000 for the IR read means that we
63 * use the same address as for CI version, which should
64 * be a safe default.
65 */
66#define DEBIADDR_IR 0x4000
Linus Torvalds1da177e2005-04-16 15:20:36 -070067#define DEBIADDR_CICONTROL 0x0000
68#define DEBIADDR_CIVERSION 0x4000
69#define DEBIADDR_IO 0x1000
70#define DEBIADDR_ATTR 0x3000
71
72#define CICONTROL_RESET 0x01
73#define CICONTROL_ENABLETS 0x02
74#define CICONTROL_CAMDETECT 0x08
75
76#define DEBICICTL 0x00420000
77#define DEBICICAM 0x02420000
78
79#define SLOTSTATUS_NONE 1
80#define SLOTSTATUS_PRESENT 2
81#define SLOTSTATUS_RESET 4
82#define SLOTSTATUS_READY 8
83#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
84
David Hardeman64741b72006-12-02 21:16:05 -020085/* RC5 device wildcard */
86#define IR_DEVICE_ANY 255
87
David Hardeman64741b72006-12-02 21:16:05 -020088static int rc5_device = -1;
89module_param(rc5_device, int, 0644);
90MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
91
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030092static int ir_debug;
David Hardemanb5471a22006-12-02 21:16:05 -020093module_param(ir_debug, int, 0644);
94MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
95
Janne Grunau26dc4d02008-09-21 20:50:11 -030096DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
97
David Hardemandd2f3982006-12-02 21:16:05 -020098struct budget_ci_ir {
99 struct input_dev *dev;
100 struct tasklet_struct msp430_irq_tasklet;
101 char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
David Hardeman5cc8ae02006-12-02 21:16:05 -0200102 char phys[32];
David Hardeman64741b72006-12-02 21:16:05 -0200103 int rc5_device;
David Härdeman145859c2007-04-27 12:31:22 -0300104 u32 ir_key;
105 bool have_command;
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;
121 struct input_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ärdeman13c24492010-04-02 15:58:30 -0300158 /* FIXME: We should generate complete scancodes with device info */
David Härdeman145859c2007-04-27 12:31:22 -0300159 if (budget_ci->ir.rc5_device != IR_DEVICE_ANY &&
160 budget_ci->ir.rc5_device != (command & 0x1f))
David Hardeman64741b72006-12-02 21:16:05 -0200161 return;
162
David Härdeman13c24492010-04-02 15:58:30 -0300163 ir_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0);
David Hardeman2520fff2006-12-02 21:16:05 -0200164}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166static int msp430_ir_init(struct budget_ci *budget_ci)
167{
168 struct saa7146_dev *saa = budget_ci->budget.dev;
David Hardemandd2f3982006-12-02 21:16:05 -0200169 struct input_dev *input_dev = budget_ci->ir.dev;
David Hardeman8cc532e2006-12-02 21:16:05 -0200170 int error;
Mauro Carvalho Chehab02858ee2010-04-02 20:01:00 -0300171 char *ir_codes = NULL;
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300172
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173
David Hardemandd2f3982006-12-02 21:16:05 -0200174 budget_ci->ir.dev = input_dev = input_allocate_device();
David Hardeman8cc532e2006-12-02 21:16:05 -0200175 if (!input_dev) {
David Hardemanee579bc2006-12-02 21:16:05 -0200176 printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300177 return -ENOMEM;
David Hardeman8cc532e2006-12-02 21:16:05 -0200178 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179
David Hardemandd2f3982006-12-02 21:16:05 -0200180 snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
181 "Budget-CI dvb ir receiver %s", saa->name);
David Hardeman5cc8ae02006-12-02 21:16:05 -0200182 snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
183 "pci-%s/ir0", pci_name(saa->pci));
184
David Hardemandd2f3982006-12-02 21:16:05 -0200185 input_dev->name = budget_ci->ir.name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186
David Hardeman5cc8ae02006-12-02 21:16:05 -0200187 input_dev->phys = budget_ci->ir.phys;
188 input_dev->id.bustype = BUS_PCI;
189 input_dev->id.version = 1;
190 if (saa->pci->subsystem_vendor) {
191 input_dev->id.vendor = saa->pci->subsystem_vendor;
192 input_dev->id.product = saa->pci->subsystem_device;
193 } else {
194 input_dev->id.vendor = saa->pci->vendor;
195 input_dev->id.product = saa->pci->device;
196 }
Dmitry Torokhov2c8a3a32007-07-16 09:28:15 -0300197 input_dev->dev.parent = &saa->pci->dev;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200198
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300199 if (rc5_device < 0)
200 budget_ci->ir.rc5_device = IR_DEVICE_ANY;
201 else
202 budget_ci->ir.rc5_device = rc5_device;
203
David Hardeman64741b72006-12-02 21:16:05 -0200204 /* Select keymap and address */
David Hardeman2520fff2006-12-02 21:16:05 -0200205 switch (budget_ci->budget.dev->pci->subsystem_device) {
206 case 0x100c:
207 case 0x100f:
David Hardeman2520fff2006-12-02 21:16:05 -0200208 case 0x1011:
209 case 0x1012:
David Hardeman2520fff2006-12-02 21:16:05 -0200210 /* The hauppauge keymap is a superset of these remotes */
Mauro Carvalho Chehab02858ee2010-04-02 20:01:00 -0300211 ir_codes = RC_MAP_HAUPPAUGE_NEW;
David Hardeman64741b72006-12-02 21:16:05 -0200212
213 if (rc5_device < 0)
214 budget_ci->ir.rc5_device = 0x1f;
David Hardeman2520fff2006-12-02 21:16:05 -0200215 break;
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300216 case 0x1010:
Oliver Endrissf64899c2007-09-17 22:17:12 -0300217 case 0x1017:
Hermann Gaustererf137f9d2010-05-18 04:26:17 -0300218 case 0x1019:
Oliver Endrissbbfc4c22008-06-19 23:36:45 -0300219 case 0x101a:
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300220 /* for the Technotrend 1500 bundled remote */
Mauro Carvalho Chehab02858ee2010-04-02 20:01:00 -0300221 ir_codes = RC_MAP_TT_1500;
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300222 break;
David Hardeman2520fff2006-12-02 21:16:05 -0200223 default:
224 /* unknown remote */
Mauro Carvalho Chehab02858ee2010-04-02 20:01:00 -0300225 ir_codes = RC_MAP_BUDGET_CI_OLD;
David Hardeman2520fff2006-12-02 21:16:05 -0200226 break;
227 }
228
Mauro Carvalho Chehab02858ee2010-04-02 20:01:00 -0300229 error = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME);
David Hardeman8cc532e2006-12-02 21:16:05 -0200230 if (error) {
231 printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300232 return error;
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300233 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234
David Härdeman145859c2007-04-27 12:31:22 -0300235 /* note: these must be after input_register_device */
236 input_dev->rep[REP_DELAY] = 400;
237 input_dev->rep[REP_PERIOD] = 250;
238
David Hardeman8cc532e2006-12-02 21:16:05 -0200239 tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
240 (unsigned long) budget_ci);
241
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300242 SAA7146_IER_ENABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
244
245 return 0;
246}
247
248static void msp430_ir_deinit(struct budget_ci *budget_ci)
249{
250 struct saa7146_dev *saa = budget_ci->budget.dev;
David Hardemandd2f3982006-12-02 21:16:05 -0200251 struct input_dev *dev = budget_ci->ir.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300253 SAA7146_IER_DISABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
David Hardeman8cc532e2006-12-02 21:16:05 -0200255 tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256
Mauro Carvalho Chehab38ef6aa2009-12-11 09:47:42 -0300257 ir_input_unregister(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258}
259
260static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
261{
262 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
263
264 if (slot != 0)
265 return -EINVAL;
266
267 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
268 DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);
269}
270
271static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
272{
273 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
274
275 if (slot != 0)
276 return -EINVAL;
277
278 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
279 DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);
280}
281
282static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
283{
284 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
285
286 if (slot != 0)
287 return -EINVAL;
288
289 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
290 DEBIADDR_IO | (address & 3), 1, 1, 0);
291}
292
293static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
294{
295 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
296
297 if (slot != 0)
298 return -EINVAL;
299
300 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
301 DEBIADDR_IO | (address & 3), 1, value, 1, 0);
302}
303
304static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
305{
306 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
307 struct saa7146_dev *saa = budget_ci->budget.dev;
308
309 if (slot != 0)
310 return -EINVAL;
311
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300312 if (budget_ci->ci_irq) {
313 // trigger on RISING edge during reset so we know when READY is re-asserted
314 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
315 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 budget_ci->slot_status = SLOTSTATUS_RESET;
317 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
318 msleep(1);
319 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
320 CICONTROL_RESET, 1, 0);
321
322 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
323 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
324 return 0;
325}
326
327static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
328{
329 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
330 struct saa7146_dev *saa = budget_ci->budget.dev;
331
332 if (slot != 0)
333 return -EINVAL;
334
335 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
336 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
337 return 0;
338}
339
340static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
341{
342 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
343 struct saa7146_dev *saa = budget_ci->budget.dev;
344 int tmp;
345
346 if (slot != 0)
347 return -EINVAL;
348
349 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
350
351 tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
352 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
353 tmp | CICONTROL_ENABLETS, 1, 0);
354
355 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
356 return 0;
357}
358
359static void ciintf_interrupt(unsigned long data)
360{
361 struct budget_ci *budget_ci = (struct budget_ci *) data;
362 struct saa7146_dev *saa = budget_ci->budget.dev;
363 unsigned int flags;
364
365 // ensure we don't get spurious IRQs during initialisation
366 if (!budget_ci->budget.ci_present)
367 return;
368
369 // read the CAM status
370 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
371 if (flags & CICONTROL_CAMDETECT) {
372
373 // GPIO should be set to trigger on falling edge if a CAM is present
374 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
375
376 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
377 // CAM insertion IRQ
378 budget_ci->slot_status = SLOTSTATUS_PRESENT;
379 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
380 DVB_CA_EN50221_CAMCHANGE_INSERTED);
381
382 } else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
383 // CAM ready (reset completed)
384 budget_ci->slot_status = SLOTSTATUS_READY;
385 dvb_ca_en50221_camready_irq(&budget_ci->ca, 0);
386
387 } else if (budget_ci->slot_status & SLOTSTATUS_READY) {
388 // FR/DA IRQ
389 dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);
390 }
391 } else {
392
393 // trigger on rising edge if a CAM is not present - when a CAM is inserted, we
394 // only want to get the IRQ when it sets READY. If we trigger on the falling edge,
395 // the CAM might not actually be ready yet.
396 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
397
398 // generate a CAM removal IRQ if we haven't already
399 if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
400 // CAM removal IRQ
401 budget_ci->slot_status = SLOTSTATUS_NONE;
402 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
403 DVB_CA_EN50221_CAMCHANGE_REMOVED);
404 }
405 }
406}
407
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300408static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
409{
410 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
411 unsigned int flags;
412
413 // ensure we don't get spurious IRQs during initialisation
414 if (!budget_ci->budget.ci_present)
415 return -EINVAL;
416
417 // read the CAM status
418 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
419 if (flags & CICONTROL_CAMDETECT) {
420 // mark it as present if it wasn't before
421 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
422 budget_ci->slot_status = SLOTSTATUS_PRESENT;
423 }
424
425 // during a RESET, we check if we can read from IO memory to see when CAM is ready
426 if (budget_ci->slot_status & SLOTSTATUS_RESET) {
427 if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
428 budget_ci->slot_status = SLOTSTATUS_READY;
429 }
430 }
431 } else {
432 budget_ci->slot_status = SLOTSTATUS_NONE;
433 }
434
435 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
436 if (budget_ci->slot_status & SLOTSTATUS_READY) {
437 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
438 }
439 return DVB_CA_EN50221_POLL_CAM_PRESENT;
440 }
441
442 return 0;
443}
444
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445static int ciintf_init(struct budget_ci *budget_ci)
446{
447 struct saa7146_dev *saa = budget_ci->budget.dev;
448 int flags;
449 int result;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300450 int ci_version;
451 int ca_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
453 memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
454
455 // enable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300456 saa7146_write(saa, MC1, MASK_27 | MASK_11);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457
458 // test if it is there
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300459 ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
460 if ((ci_version & 0xa0) != 0xa0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 result = -ENODEV;
462 goto error;
463 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300464
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 // determine whether a CAM is present or not
466 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
467 budget_ci->slot_status = SLOTSTATUS_NONE;
468 if (flags & CICONTROL_CAMDETECT)
469 budget_ci->slot_status = SLOTSTATUS_PRESENT;
470
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300471 // version 0xa2 of the CI firmware doesn't generate interrupts
472 if (ci_version == 0xa2) {
473 ca_flags = 0;
474 budget_ci->ci_irq = 0;
475 } else {
476 ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
477 DVB_CA_EN50221_FLAG_IRQ_FR |
478 DVB_CA_EN50221_FLAG_IRQ_DA;
479 budget_ci->ci_irq = 1;
480 }
481
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 // register CI interface
483 budget_ci->ca.owner = THIS_MODULE;
484 budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
485 budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
486 budget_ci->ca.read_cam_control = ciintf_read_cam_control;
487 budget_ci->ca.write_cam_control = ciintf_write_cam_control;
488 budget_ci->ca.slot_reset = ciintf_slot_reset;
489 budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
490 budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300491 budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 budget_ci->ca.data = budget_ci;
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700493 if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 &budget_ci->ca,
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300495 ca_flags, 1)) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 printk("budget_ci: CI interface detected, but initialisation failed.\n");
497 goto error;
498 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300499
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 // Setup CI slot IRQ
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300501 if (budget_ci->ci_irq) {
502 tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
503 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
504 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
505 } else {
506 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
507 }
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300508 SAA7146_IER_ENABLE(saa, MASK_03);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300510
511 // enable interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
513 CICONTROL_RESET, 1, 0);
514
515 // success!
516 printk("budget_ci: CI interface initialised\n");
517 budget_ci->budget.ci_present = 1;
518
519 // forge a fake CI IRQ so the CAM state is setup correctly
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300520 if (budget_ci->ci_irq) {
521 flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
522 if (budget_ci->slot_status != SLOTSTATUS_NONE)
523 flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
524 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
525 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526
527 return 0;
528
529error:
Hartmut Birr2a893de2006-12-03 21:08:08 -0300530 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 return result;
532}
533
534static void ciintf_deinit(struct budget_ci *budget_ci)
535{
536 struct saa7146_dev *saa = budget_ci->budget.dev;
537
538 // disable CI interrupts
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300539 if (budget_ci->ci_irq) {
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300540 SAA7146_IER_DISABLE(saa, MASK_03);
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300541 saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
542 tasklet_kill(&budget_ci->ciintf_irq_tasklet);
543 }
544
545 // reset interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
547 msleep(1);
548 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
549 CICONTROL_RESET, 1, 0);
550
551 // disable TS data stream to CI interface
552 saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
553
554 // release the CA device
555 dvb_ca_en50221_release(&budget_ci->ca);
556
557 // disable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300558 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559}
560
561static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
562{
563 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
564
565 dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
566
567 if (*isr & MASK_06)
David Hardemandd2f3982006-12-02 21:16:05 -0200568 tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
570 if (*isr & MASK_10)
571 ttpci_budget_irq10_handler(dev, isr);
572
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300573 if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
575}
576
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577static u8 philips_su1278_tt_inittab[] = {
578 0x01, 0x0f,
579 0x02, 0x30,
580 0x03, 0x00,
581 0x04, 0x5b,
582 0x05, 0x85,
583 0x06, 0x02,
584 0x07, 0x00,
585 0x08, 0x02,
586 0x09, 0x00,
587 0x0C, 0x01,
588 0x0D, 0x81,
589 0x0E, 0x44,
590 0x0f, 0x14,
591 0x10, 0x3c,
592 0x11, 0x84,
593 0x12, 0xda,
594 0x13, 0x97,
595 0x14, 0x95,
596 0x15, 0xc9,
597 0x16, 0x19,
598 0x17, 0x8c,
599 0x18, 0x59,
600 0x19, 0xf8,
601 0x1a, 0xfe,
602 0x1c, 0x7f,
603 0x1d, 0x00,
604 0x1e, 0x00,
605 0x1f, 0x50,
606 0x20, 0x00,
607 0x21, 0x00,
608 0x22, 0x00,
609 0x23, 0x00,
610 0x28, 0x00,
611 0x29, 0x28,
612 0x2a, 0x14,
613 0x2b, 0x0f,
614 0x2c, 0x09,
615 0x2d, 0x09,
616 0x31, 0x1f,
617 0x32, 0x19,
618 0x33, 0xfc,
619 0x34, 0x93,
620 0xff, 0xff
621};
622
623static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
624{
625 stv0299_writereg(fe, 0x0e, 0x44);
626 if (srate >= 10000000) {
627 stv0299_writereg(fe, 0x13, 0x97);
628 stv0299_writereg(fe, 0x14, 0x95);
629 stv0299_writereg(fe, 0x15, 0xc9);
630 stv0299_writereg(fe, 0x17, 0x8c);
631 stv0299_writereg(fe, 0x1a, 0xfe);
632 stv0299_writereg(fe, 0x1c, 0x7f);
633 stv0299_writereg(fe, 0x2d, 0x09);
634 } else {
635 stv0299_writereg(fe, 0x13, 0x99);
636 stv0299_writereg(fe, 0x14, 0x8d);
637 stv0299_writereg(fe, 0x15, 0xce);
638 stv0299_writereg(fe, 0x17, 0x43);
639 stv0299_writereg(fe, 0x1a, 0x1d);
640 stv0299_writereg(fe, 0x1c, 0x12);
641 stv0299_writereg(fe, 0x2d, 0x05);
642 }
643 stv0299_writereg(fe, 0x0e, 0x23);
644 stv0299_writereg(fe, 0x0f, 0x94);
645 stv0299_writereg(fe, 0x10, 0x39);
646 stv0299_writereg(fe, 0x15, 0xc9);
647
648 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
649 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
650 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
651
652 return 0;
653}
654
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300655static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,
656 struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657{
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300658 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 u32 div;
660 u8 buf[4];
661 struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
662
663 if ((params->frequency < 950000) || (params->frequency > 2150000))
664 return -EINVAL;
665
666 div = (params->frequency + (500 - 1)) / 500; // round correctly
667 buf[0] = (div >> 8) & 0x7f;
668 buf[1] = div & 0xff;
669 buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
670 buf[3] = 0x20;
671
672 if (params->u.qpsk.symbol_rate < 4000000)
673 buf[3] |= 1;
674
675 if (params->frequency < 1250000)
676 buf[3] |= 0;
677 else if (params->frequency < 1550000)
678 buf[3] |= 0x40;
679 else if (params->frequency < 2050000)
680 buf[3] |= 0x80;
681 else if (params->frequency < 2150000)
682 buf[3] |= 0xC0;
683
Patrick Boettcherdea74862006-05-14 05:01:31 -0300684 if (fe->ops.i2c_gate_ctrl)
685 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300686 if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 return -EIO;
688 return 0;
689}
690
691static struct stv0299_config philips_su1278_tt_config = {
692
693 .demod_address = 0x68,
694 .inittab = philips_su1278_tt_inittab,
695 .mclk = 64000000UL,
696 .invert = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 .skip_reinit = 1,
Oliver Endrissda2c7f62008-04-20 22:13:37 -0300698 .lock_output = STV0299_LOCKOUTPUT_1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 .volt13_op0_op1 = STV0299_VOLT13_OP1,
700 .min_delay_ms = 50,
701 .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702};
703
704
705
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300706static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707{
708 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
709 static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
710 static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700711 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 sizeof(td1316_init) };
713
714 // setup PLL configuration
Patrick Boettcherdea74862006-05-14 05:01:31 -0300715 if (fe->ops.i2c_gate_ctrl)
716 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
718 return -EIO;
719 msleep(1);
720
721 // disable the mc44BC374c (do not check for errors)
722 tuner_msg.addr = 0x65;
723 tuner_msg.buf = disable_mc44BC374c;
724 tuner_msg.len = sizeof(disable_mc44BC374c);
Patrick Boettcherdea74862006-05-14 05:01:31 -0300725 if (fe->ops.i2c_gate_ctrl)
726 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
Patrick Boettcherdea74862006-05-14 05:01:31 -0300728 if (fe->ops.i2c_gate_ctrl)
729 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
731 }
732
733 return 0;
734}
735
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300736static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737{
738 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
739 u8 tuner_buf[4];
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700740 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 -0700741 int tuner_frequency = 0;
742 u8 band, cp, filter;
743
744 // determine charge pump
745 tuner_frequency = params->frequency + 36130000;
746 if (tuner_frequency < 87000000)
747 return -EINVAL;
748 else if (tuner_frequency < 130000000)
749 cp = 3;
750 else if (tuner_frequency < 160000000)
751 cp = 5;
752 else if (tuner_frequency < 200000000)
753 cp = 6;
754 else if (tuner_frequency < 290000000)
755 cp = 3;
756 else if (tuner_frequency < 420000000)
757 cp = 5;
758 else if (tuner_frequency < 480000000)
759 cp = 6;
760 else if (tuner_frequency < 620000000)
761 cp = 3;
762 else if (tuner_frequency < 830000000)
763 cp = 5;
764 else if (tuner_frequency < 895000000)
765 cp = 7;
766 else
767 return -EINVAL;
768
769 // determine band
770 if (params->frequency < 49000000)
771 return -EINVAL;
772 else if (params->frequency < 159000000)
773 band = 1;
774 else if (params->frequency < 444000000)
775 band = 2;
776 else if (params->frequency < 861000000)
777 band = 4;
778 else
779 return -EINVAL;
780
781 // setup PLL filter and TDA9889
782 switch (params->u.ofdm.bandwidth) {
783 case BANDWIDTH_6_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300784 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 filter = 0;
786 break;
787
788 case BANDWIDTH_7_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300789 tda1004x_writereg(fe, 0x0C, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 filter = 0;
791 break;
792
793 case BANDWIDTH_8_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300794 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 filter = 1;
796 break;
797
798 default:
799 return -EINVAL;
800 }
801
802 // calculate divisor
803 // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
804 tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
805
806 // setup tuner buffer
807 tuner_buf[0] = tuner_frequency >> 8;
808 tuner_buf[1] = tuner_frequency & 0xff;
809 tuner_buf[2] = 0xca;
810 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
811
Patrick Boettcherdea74862006-05-14 05:01:31 -0300812 if (fe->ops.i2c_gate_ctrl)
813 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
815 return -EIO;
816
817 msleep(1);
818 return 0;
819}
820
821static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,
822 const struct firmware **fw, char *name)
823{
824 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
825
826 return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);
827}
828
829static struct tda1004x_config philips_tdm1316l_config = {
830
831 .demod_address = 0x8,
832 .invert = 0,
833 .invert_oclk = 0,
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700834 .xtal_freq = TDA10046_XTAL_4M,
835 .agc_config = TDA10046_AGC_DEFAULT,
836 .if_freq = TDA10046_FREQ_3617,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 .request_firmware = philips_tdm1316l_request_firmware,
838};
839
Oliver Endriss6c914492007-02-02 19:12:53 -0300840static struct tda1004x_config philips_tdm1316l_config_invert = {
841
842 .demod_address = 0x8,
843 .invert = 1,
844 .invert_oclk = 0,
845 .xtal_freq = TDA10046_XTAL_4M,
846 .agc_config = TDA10046_AGC_DEFAULT,
847 .if_freq = TDA10046_FREQ_3617,
848 .request_firmware = philips_tdm1316l_request_firmware,
849};
850
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300851static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700852{
853 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
854 u8 tuner_buf[5];
855 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
856 .flags = 0,
857 .buf = tuner_buf,
858 .len = sizeof(tuner_buf) };
859 int tuner_frequency = 0;
860 u8 band, cp, filter;
861
862 // determine charge pump
863 tuner_frequency = params->frequency + 36125000;
864 if (tuner_frequency < 87000000)
865 return -EINVAL;
866 else if (tuner_frequency < 130000000) {
867 cp = 3;
868 band = 1;
869 } else if (tuner_frequency < 160000000) {
870 cp = 5;
871 band = 1;
872 } else if (tuner_frequency < 200000000) {
873 cp = 6;
Oliver Endriss910a7b62007-05-03 13:16:12 -0300874 band = 1;
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700875 } else if (tuner_frequency < 290000000) {
876 cp = 3;
877 band = 2;
878 } else if (tuner_frequency < 420000000) {
879 cp = 5;
880 band = 2;
881 } else if (tuner_frequency < 480000000) {
882 cp = 6;
883 band = 2;
884 } else if (tuner_frequency < 620000000) {
885 cp = 3;
886 band = 4;
887 } else if (tuner_frequency < 830000000) {
888 cp = 5;
889 band = 4;
890 } else if (tuner_frequency < 895000000) {
891 cp = 7;
892 band = 4;
893 } else
894 return -EINVAL;
895
896 // assume PLL filter should always be 8MHz for the moment.
897 filter = 1;
898
899 // calculate divisor
900 tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
901
902 // setup tuner buffer
903 tuner_buf[0] = tuner_frequency >> 8;
904 tuner_buf[1] = tuner_frequency & 0xff;
905 tuner_buf[2] = 0xc8;
906 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
907 tuner_buf[4] = 0x80;
908
Patrick Boettcherdea74862006-05-14 05:01:31 -0300909 if (fe->ops.i2c_gate_ctrl)
910 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700911 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
912 return -EIO;
913
914 msleep(50);
915
Patrick Boettcherdea74862006-05-14 05:01:31 -0300916 if (fe->ops.i2c_gate_ctrl)
917 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700918 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
919 return -EIO;
920
921 msleep(1);
922
923 return 0;
924}
925
926static u8 dvbc_philips_tdm1316l_inittab[] = {
927 0x80, 0x01,
928 0x80, 0x00,
929 0x81, 0x01,
930 0x81, 0x00,
931 0x00, 0x09,
932 0x01, 0x69,
933 0x03, 0x00,
934 0x04, 0x00,
935 0x07, 0x00,
936 0x08, 0x00,
937 0x20, 0x00,
938 0x21, 0x40,
939 0x22, 0x00,
940 0x23, 0x00,
941 0x24, 0x40,
942 0x25, 0x88,
943 0x30, 0xff,
944 0x31, 0x00,
945 0x32, 0xff,
946 0x33, 0x00,
947 0x34, 0x50,
948 0x35, 0x7f,
949 0x36, 0x00,
950 0x37, 0x20,
951 0x38, 0x00,
952 0x40, 0x1c,
953 0x41, 0xff,
954 0x42, 0x29,
955 0x43, 0x20,
956 0x44, 0xff,
957 0x45, 0x00,
958 0x46, 0x00,
959 0x49, 0x04,
960 0x4a, 0x00,
961 0x4b, 0x7b,
962 0x52, 0x30,
963 0x55, 0xae,
964 0x56, 0x47,
965 0x57, 0xe1,
966 0x58, 0x3a,
967 0x5a, 0x1e,
968 0x5b, 0x34,
969 0x60, 0x00,
970 0x63, 0x00,
971 0x64, 0x00,
972 0x65, 0x00,
973 0x66, 0x00,
974 0x67, 0x00,
975 0x68, 0x00,
976 0x69, 0x00,
977 0x6a, 0x02,
978 0x6b, 0x00,
979 0x70, 0xff,
980 0x71, 0x00,
981 0x72, 0x00,
982 0x73, 0x00,
983 0x74, 0x0c,
984 0x80, 0x00,
985 0x81, 0x00,
986 0x82, 0x00,
987 0x83, 0x00,
988 0x84, 0x04,
989 0x85, 0x80,
990 0x86, 0x24,
991 0x87, 0x78,
992 0x88, 0x10,
993 0x89, 0x00,
994 0x90, 0x01,
995 0x91, 0x01,
996 0xa0, 0x04,
997 0xa1, 0x00,
998 0xa2, 0x00,
999 0xb0, 0x91,
1000 0xb1, 0x0b,
1001 0xc0, 0x53,
1002 0xc1, 0x70,
1003 0xc2, 0x12,
1004 0xd0, 0x00,
1005 0xd1, 0x00,
1006 0xd2, 0x00,
1007 0xd3, 0x00,
1008 0xd4, 0x00,
1009 0xd5, 0x00,
1010 0xde, 0x00,
1011 0xdf, 0x00,
1012 0x61, 0x38,
1013 0x62, 0x0a,
1014 0x53, 0x13,
1015 0x59, 0x08,
1016 0xff, 0xff,
1017};
1018
1019static struct stv0297_config dvbc_philips_tdm1316l_config = {
1020 .demod_address = 0x1c,
1021 .inittab = dvbc_philips_tdm1316l_inittab,
1022 .invert = 0,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001023 .stop_during_read = 1,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001024};
1025
Sigmund Augdal11417da2008-06-15 17:25:46 -03001026static struct tda10023_config tda10023_config = {
1027 .demod_address = 0xc,
1028 .invert = 0,
1029 .xtal = 16000000,
1030 .pll_m = 11,
1031 .pll_p = 3,
1032 .pll_n = 1,
1033 .deltaf = 0xa511,
1034};
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001035
klaas de waalcf47d872009-03-25 17:53:02 -03001036static struct tda827x_config tda827x_config = {
1037 .config = 0,
1038};
1039
Manu Abrahama55bc842008-10-23 18:32:50 -03001040/* TT S2-3200 DVB-S (STB0899) Inittab */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001041static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001043 { STB0899_DEV_ID , 0x81 },
1044 { STB0899_DISCNTRL1 , 0x32 },
1045 { STB0899_DISCNTRL2 , 0x80 },
1046 { STB0899_DISRX_ST0 , 0x04 },
1047 { STB0899_DISRX_ST1 , 0x00 },
1048 { STB0899_DISPARITY , 0x00 },
1049 { STB0899_DISFIFO , 0x00 },
1050 { STB0899_DISSTATUS , 0x20 },
1051 { STB0899_DISF22 , 0x8c },
1052 { STB0899_DISF22RX , 0x9a },
Manu Abrahamef3052b2008-10-23 18:45:17 -03001053 { STB0899_SYSREG , 0x0b },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001054 { STB0899_ACRPRESC , 0x11 },
1055 { STB0899_ACRDIV1 , 0x0a },
1056 { STB0899_ACRDIV2 , 0x05 },
1057 { STB0899_DACR1 , 0x00 },
1058 { STB0899_DACR2 , 0x00 },
1059 { STB0899_OUTCFG , 0x00 },
1060 { STB0899_MODECFG , 0x00 },
1061 { STB0899_IRQSTATUS_3 , 0x30 },
1062 { STB0899_IRQSTATUS_2 , 0x00 },
1063 { STB0899_IRQSTATUS_1 , 0x00 },
1064 { STB0899_IRQSTATUS_0 , 0x00 },
1065 { STB0899_IRQMSK_3 , 0xf3 },
1066 { STB0899_IRQMSK_2 , 0xfc },
1067 { STB0899_IRQMSK_1 , 0xff },
1068 { STB0899_IRQMSK_0 , 0xff },
1069 { STB0899_IRQCFG , 0x00 },
1070 { STB0899_I2CCFG , 0x88 },
Manu Abraham40e8ce32008-02-03 19:37:02 -03001071 { STB0899_I2CRPT , 0x48 }, /* 12k Pullup, Repeater=16, Stop=disabled */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001072 { STB0899_IOPVALUE5 , 0x00 },
1073 { STB0899_IOPVALUE4 , 0x20 },
1074 { STB0899_IOPVALUE3 , 0xc9 },
1075 { STB0899_IOPVALUE2 , 0x90 },
1076 { STB0899_IOPVALUE1 , 0x40 },
1077 { STB0899_IOPVALUE0 , 0x00 },
1078 { STB0899_GPIO00CFG , 0x82 },
1079 { STB0899_GPIO01CFG , 0x82 },
1080 { STB0899_GPIO02CFG , 0x82 },
1081 { STB0899_GPIO03CFG , 0x82 },
1082 { STB0899_GPIO04CFG , 0x82 },
1083 { STB0899_GPIO05CFG , 0x82 },
1084 { STB0899_GPIO06CFG , 0x82 },
1085 { STB0899_GPIO07CFG , 0x82 },
1086 { STB0899_GPIO08CFG , 0x82 },
1087 { STB0899_GPIO09CFG , 0x82 },
1088 { STB0899_GPIO10CFG , 0x82 },
1089 { STB0899_GPIO11CFG , 0x82 },
1090 { STB0899_GPIO12CFG , 0x82 },
1091 { STB0899_GPIO13CFG , 0x82 },
1092 { STB0899_GPIO14CFG , 0x82 },
1093 { STB0899_GPIO15CFG , 0x82 },
1094 { STB0899_GPIO16CFG , 0x82 },
1095 { STB0899_GPIO17CFG , 0x82 },
1096 { STB0899_GPIO18CFG , 0x82 },
1097 { STB0899_GPIO19CFG , 0x82 },
1098 { STB0899_GPIO20CFG , 0x82 },
1099 { STB0899_SDATCFG , 0xb8 },
1100 { STB0899_SCLTCFG , 0xba },
Manu Abrahama55bc842008-10-23 18:32:50 -03001101 { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */
1102 { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */
1103 { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001104 { STB0899_DIRCLKCFG , 0x82 },
1105 { STB0899_CLKOUT27CFG , 0x7e },
1106 { STB0899_STDBYCFG , 0x82 },
1107 { STB0899_CS0CFG , 0x82 },
1108 { STB0899_CS1CFG , 0x82 },
1109 { STB0899_DISEQCOCFG , 0x20 },
1110 { STB0899_GPIO32CFG , 0x82 },
1111 { STB0899_GPIO33CFG , 0x82 },
1112 { STB0899_GPIO34CFG , 0x82 },
1113 { STB0899_GPIO35CFG , 0x82 },
1114 { STB0899_GPIO36CFG , 0x82 },
1115 { STB0899_GPIO37CFG , 0x82 },
1116 { STB0899_GPIO38CFG , 0x82 },
1117 { STB0899_GPIO39CFG , 0x82 },
Manu Abrahamf2e52cd2007-11-19 16:44:47 -03001118 { STB0899_NCOARSE , 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
Manu Abrahama55bc842008-10-23 18:32:50 -03001119 { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001120 { STB0899_FILTCTRL , 0x00 },
1121 { STB0899_SYSCTRL , 0x00 },
1122 { STB0899_STOPCLK1 , 0x20 },
1123 { STB0899_STOPCLK2 , 0x00 },
1124 { STB0899_INTBUFSTATUS , 0x00 },
1125 { STB0899_INTBUFCTRL , 0x0a },
1126 { 0xffff , 0xff },
1127};
1128
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001129static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = {
1130 { STB0899_DEMOD , 0x00 },
1131 { STB0899_RCOMPC , 0xc9 },
1132 { STB0899_AGC1CN , 0x41 },
1133 { STB0899_AGC1REF , 0x10 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001134 { STB0899_RTC , 0x7a },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001135 { STB0899_TMGCFG , 0x4e },
1136 { STB0899_AGC2REF , 0x34 },
1137 { STB0899_TLSR , 0x84 },
1138 { STB0899_CFD , 0xc7 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001139 { STB0899_ACLC , 0x87 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001140 { STB0899_BCLC , 0x94 },
1141 { STB0899_EQON , 0x41 },
1142 { STB0899_LDT , 0xdd },
1143 { STB0899_LDT2 , 0xc9 },
1144 { STB0899_EQUALREF , 0xb4 },
1145 { STB0899_TMGRAMP , 0x10 },
1146 { STB0899_TMGTHD , 0x30 },
1147 { STB0899_IDCCOMP , 0xfb },
1148 { STB0899_QDCCOMP , 0x03 },
1149 { STB0899_POWERI , 0x3b },
1150 { STB0899_POWERQ , 0x3d },
1151 { STB0899_RCOMP , 0x81 },
1152 { STB0899_AGCIQIN , 0x80 },
1153 { STB0899_AGC2I1 , 0x04 },
1154 { STB0899_AGC2I2 , 0xf5 },
1155 { STB0899_TLIR , 0x25 },
1156 { STB0899_RTF , 0x80 },
1157 { STB0899_DSTATUS , 0x00 },
1158 { STB0899_LDI , 0xca },
1159 { STB0899_CFRM , 0xf1 },
1160 { STB0899_CFRL , 0xf3 },
1161 { STB0899_NIRM , 0x2a },
1162 { STB0899_NIRL , 0x05 },
1163 { STB0899_ISYMB , 0x17 },
1164 { STB0899_QSYMB , 0xfa },
1165 { STB0899_SFRH , 0x2f },
1166 { STB0899_SFRM , 0x68 },
1167 { STB0899_SFRL , 0x40 },
1168 { STB0899_SFRUPH , 0x2f },
1169 { STB0899_SFRUPM , 0x68 },
1170 { STB0899_SFRUPL , 0x40 },
1171 { STB0899_EQUAI1 , 0xfd },
1172 { STB0899_EQUAQ1 , 0x04 },
1173 { STB0899_EQUAI2 , 0x0f },
1174 { STB0899_EQUAQ2 , 0xff },
1175 { STB0899_EQUAI3 , 0xdf },
1176 { STB0899_EQUAQ3 , 0xfa },
1177 { STB0899_EQUAI4 , 0x37 },
1178 { STB0899_EQUAQ4 , 0x0d },
1179 { STB0899_EQUAI5 , 0xbd },
1180 { STB0899_EQUAQ5 , 0xf7 },
1181 { STB0899_DSTATUS2 , 0x00 },
1182 { STB0899_VSTATUS , 0x00 },
1183 { STB0899_VERROR , 0xff },
1184 { STB0899_IQSWAP , 0x2a },
1185 { STB0899_ECNT1M , 0x00 },
1186 { STB0899_ECNT1L , 0x00 },
1187 { STB0899_ECNT2M , 0x00 },
1188 { STB0899_ECNT2L , 0x00 },
1189 { STB0899_ECNT3M , 0x00 },
1190 { STB0899_ECNT3L , 0x00 },
1191 { STB0899_FECAUTO1 , 0x06 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001192 { STB0899_FECM , 0x01 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001193 { STB0899_VTH12 , 0xf0 },
1194 { STB0899_VTH23 , 0xa0 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001195 { STB0899_VTH34 , 0x78 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001196 { STB0899_VTH56 , 0x4e },
1197 { STB0899_VTH67 , 0x48 },
1198 { STB0899_VTH78 , 0x38 },
1199 { STB0899_PRVIT , 0xff },
1200 { STB0899_VITSYNC , 0x19 },
Manu Abrahama55bc842008-10-23 18:32:50 -03001201 { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001202 { STB0899_TSULC , 0x42 },
1203 { STB0899_RSLLC , 0x40 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001204 { STB0899_TSLPL , 0x12 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001205 { STB0899_TSCFGH , 0x0c },
1206 { STB0899_TSCFGM , 0x00 },
1207 { STB0899_TSCFGL , 0x0c },
Manu Abrahamc1426df2009-11-13 18:51:39 -03001208 { STB0899_TSOUT , 0x4d }, /* 0x0d for CAM */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001209 { STB0899_RSSYNCDEL , 0x00 },
1210 { STB0899_TSINHDELH , 0x02 },
1211 { STB0899_TSINHDELM , 0x00 },
1212 { STB0899_TSINHDELL , 0x00 },
1213 { STB0899_TSLLSTKM , 0x00 },
1214 { STB0899_TSLLSTKL , 0x00 },
1215 { STB0899_TSULSTKM , 0x00 },
1216 { STB0899_TSULSTKL , 0xab },
1217 { STB0899_PCKLENUL , 0x00 },
1218 { STB0899_PCKLENLL , 0xcc },
1219 { STB0899_RSPCKLEN , 0xcc },
1220 { STB0899_TSSTATUS , 0x80 },
1221 { STB0899_ERRCTRL1 , 0xb6 },
1222 { STB0899_ERRCTRL2 , 0x96 },
1223 { STB0899_ERRCTRL3 , 0x89 },
1224 { STB0899_DMONMSK1 , 0x27 },
1225 { STB0899_DMONMSK0 , 0x03 },
1226 { STB0899_DEMAPVIT , 0x5c },
1227 { STB0899_PLPARM , 0x1f },
1228 { STB0899_PDELCTRL , 0x48 },
1229 { STB0899_PDELCTRL2 , 0x00 },
1230 { STB0899_BBHCTRL1 , 0x00 },
1231 { STB0899_BBHCTRL2 , 0x00 },
1232 { STB0899_HYSTTHRESH , 0x77 },
1233 { STB0899_MATCSTM , 0x00 },
1234 { STB0899_MATCSTL , 0x00 },
1235 { STB0899_UPLCSTM , 0x00 },
1236 { STB0899_UPLCSTL , 0x00 },
1237 { STB0899_DFLCSTM , 0x00 },
1238 { STB0899_DFLCSTL , 0x00 },
1239 { STB0899_SYNCCST , 0x00 },
1240 { STB0899_SYNCDCSTM , 0x00 },
1241 { STB0899_SYNCDCSTL , 0x00 },
1242 { STB0899_ISI_ENTRY , 0x00 },
1243 { STB0899_ISI_BIT_EN , 0x00 },
1244 { STB0899_MATSTRM , 0x00 },
1245 { STB0899_MATSTRL , 0x00 },
1246 { STB0899_UPLSTRM , 0x00 },
1247 { STB0899_UPLSTRL , 0x00 },
1248 { STB0899_DFLSTRM , 0x00 },
1249 { STB0899_DFLSTRL , 0x00 },
1250 { STB0899_SYNCSTR , 0x00 },
1251 { STB0899_SYNCDSTRM , 0x00 },
1252 { STB0899_SYNCDSTRL , 0x00 },
1253 { STB0899_CFGPDELSTATUS1 , 0x10 },
1254 { STB0899_CFGPDELSTATUS2 , 0x00 },
1255 { STB0899_BBFERRORM , 0x00 },
1256 { STB0899_BBFERRORL , 0x00 },
1257 { STB0899_UPKTERRORM , 0x00 },
1258 { STB0899_UPKTERRORL , 0x00 },
1259 { 0xffff , 0xff },
1260};
1261
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001262static struct stb0899_config tt3200_config = {
1263 .init_dev = tt3200_stb0899_s1_init_1,
Manu Abraham8be969b2008-01-25 18:20:48 -03001264 .init_s2_demod = stb0899_s2_init_2,
Manu Abrahama55bc842008-10-23 18:32:50 -03001265 .init_s1_demod = tt3200_stb0899_s1_init_3,
Manu Abraham8be969b2008-01-25 18:20:48 -03001266 .init_s2_fec = stb0899_s2_init_4,
1267 .init_tst = stb0899_s1_init_5,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001268
Manu Abraham043a68b2008-01-18 14:15:17 -03001269 .postproc = NULL,
1270
Manu Abrahama55bc842008-10-23 18:32:50 -03001271 .demod_address = 0x68,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001272
1273 .xtal_freq = 27000000,
Manu Abrahame99d00c2007-09-25 17:48:59 -03001274 .inversion = IQ_SWAP_ON, /* 1 */
Manu Abrahama55bc842008-10-23 18:32:50 -03001275
Manu Abrahamb91a7cb2008-03-04 19:19:58 -03001276 .lo_clk = 76500000,
1277 .hi_clk = 99000000,
1278
Manu Abraham8be969b2008-01-25 18:20:48 -03001279 .esno_ave = STB0899_DVBS2_ESNO_AVE,
1280 .esno_quant = STB0899_DVBS2_ESNO_QUANT,
1281 .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
1282 .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
1283 .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
1284 .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
1285 .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
1286 .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
1287 .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
Manu Abrahama55bc842008-10-23 18:32:50 -03001288
Manu Abraham8be969b2008-01-25 18:20:48 -03001289 .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
1290 .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
1291 .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
1292 .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
Manu Abrahama55bc842008-10-23 18:32:50 -03001293
1294 .tuner_get_frequency = stb6100_get_frequency,
1295 .tuner_set_frequency = stb6100_set_frequency,
1296 .tuner_set_bandwidth = stb6100_set_bandwidth,
1297 .tuner_get_bandwidth = stb6100_get_bandwidth,
Manu Abraham043a68b2008-01-18 14:15:17 -03001298 .tuner_set_rfsiggain = NULL
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001299};
1300
Mauro Carvalho Chehabffbc5f82009-01-05 01:34:20 -03001301static struct stb6100_config tt3200_stb6100_config = {
Manu Abrahamc14eaed2007-10-04 16:52:51 -03001302 .tuner_address = 0x60,
1303 .refclock = 27000000,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001304};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305
1306static void frontend_init(struct budget_ci *budget_ci)
1307{
1308 switch (budget_ci->budget.dev->pci->subsystem_device) {
1309 case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
1310 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001311 dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001313 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001314 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 break;
1316 }
1317 break;
1318
1319 case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
1320 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001321 dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001323 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 break;
1325 }
1326 break;
1327
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001328 case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
1329 budget_ci->tuner_pll_address = 0x61;
1330 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001331 dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001332 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001333 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001334 break;
1335 }
1336 break;
1337
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001339 budget_ci->tuner_pll_address = 0x63;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001341 dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001343 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1344 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 break;
1346 }
1347 break;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001348
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001349 case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001350 budget_ci->tuner_pll_address = 0x60;
1351 budget_ci->budget.dvb_frontend =
Oliver Endriss6c914492007-02-02 19:12:53 -03001352 dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001353 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001354 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1355 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001356 break;
1357 }
1358 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001359
1360 case 0x1017: // TT S-1500 PCI
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001361 budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001362 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001363 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001364 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
1365
Patrick Boettcherdea74862006-05-14 05:01:31 -03001366 budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001367 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 -03001368 printk("%s: No LNBP21 found!\n", __func__);
Andrew de Quincey2b100e72006-08-08 09:10:11 -03001369 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001370 budget_ci->budget.dvb_frontend = NULL;
1371 }
1372 }
Sigmund Augdal11417da2008-06-15 17:25:46 -03001373 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001374
Sigmund Augdal11417da2008-06-15 17:25:46 -03001375 case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */
1376 budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48);
1377 if (budget_ci->budget.dvb_frontend) {
klaas de waalcf47d872009-03-25 17:53:02 -03001378 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 -03001379 printk(KERN_ERR "%s: No tda827x found!\n", __func__);
1380 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1381 budget_ci->budget.dvb_frontend = NULL;
1382 }
1383 }
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001384 break;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001385
1386 case 0x1019: // TT S2-3200 PCI
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001387 /*
1388 * NOTE! on some STB0899 versions, the internal PLL takes a longer time
1389 * to settle, aka LOCK. On the older revisions of the chip, we don't see
1390 * this, as a result on the newer chips the entire clock tree, will not
1391 * be stable after a freshly POWER 'ed up situation.
1392 * In this case, we should RESET the STB0899 (Active LOW) and wait for
1393 * PLL stabilization.
1394 *
1395 * On the TT S2 3200 and clones, the STB0899 demodulator's RESETB is
1396 * connected to the SAA7146 GPIO, GPIO2, Pin 142
1397 */
1398 /* Reset Demodulator */
Manu Abraham0867f572007-10-15 13:07:16 -03001399 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001400 /* Wait for everything to die */
1401 msleep(50);
1402 /* Pull it up out of Reset state */
Manu Abraham0867f572007-10-15 13:07:16 -03001403 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001404 /* Wait for PLL to stabilize */
1405 msleep(250);
1406 /*
1407 * PLL state should be stable now. Ideally, we should check
1408 * for PLL LOCK status. But well, never mind!
1409 */
Manu Abrahamae9902d2007-10-08 18:51:54 -03001410 budget_ci->budget.dvb_frontend = dvb_attach(stb0899_attach, &tt3200_config, &budget_ci->budget.i2c_adap);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001411 if (budget_ci->budget.dvb_frontend) {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001412 if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {
1413 if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
Harvey Harrison9b4778f2009-01-07 14:42:41 -08001414 printk("%s: No LNBP21 found!\n", __func__);
Manu Abrahamae9902d2007-10-08 18:51:54 -03001415 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001416 budget_ci->budget.dvb_frontend = NULL;
1417 }
1418 } else {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001419 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1420 budget_ci->budget.dvb_frontend = NULL;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001421 }
1422 }
1423 break;
1424
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 }
1426
1427 if (budget_ci->budget.dvb_frontend == NULL) {
Bjorn Helgaas29e66a62008-09-04 17:24:51 -03001428 printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 budget_ci->budget.dev->pci->vendor,
1430 budget_ci->budget.dev->pci->device,
1431 budget_ci->budget.dev->pci->subsystem_vendor,
1432 budget_ci->budget.dev->pci->subsystem_device);
1433 } else {
1434 if (dvb_register_frontend
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001435 (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 printk("budget-ci: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001437 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 budget_ci->budget.dvb_frontend = NULL;
1439 }
1440 }
1441}
1442
1443static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
1444{
1445 struct budget_ci *budget_ci;
1446 int err;
1447
David Hardemanee579bc2006-12-02 21:16:05 -02001448 budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
David Hardeman8cc532e2006-12-02 21:16:05 -02001449 if (!budget_ci) {
1450 err = -ENOMEM;
1451 goto out1;
1452 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
1454 dprintk(2, "budget_ci: %p\n", budget_ci);
1455
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 dev->ext_priv = budget_ci;
1457
Janne Grunau26dc4d02008-09-21 20:50:11 -03001458 err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE,
1459 adapter_nr);
David Hardeman8cc532e2006-12-02 21:16:05 -02001460 if (err)
1461 goto out2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462
David Hardeman8cc532e2006-12-02 21:16:05 -02001463 err = msp430_ir_init(budget_ci);
1464 if (err)
1465 goto out3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
1467 ciintf_init(budget_ci);
1468
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001469 budget_ci->budget.dvb_adapter.priv = budget_ci;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 frontend_init(budget_ci);
1471
Oliver Endriss32e4c3a2006-07-18 22:55:23 -03001472 ttpci_budget_init_hooks(&budget_ci->budget);
1473
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 return 0;
David Hardeman8cc532e2006-12-02 21:16:05 -02001475
1476out3:
1477 ttpci_budget_deinit(&budget_ci->budget);
1478out2:
1479 kfree(budget_ci);
1480out1:
1481 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482}
1483
1484static int budget_ci_detach(struct saa7146_dev *dev)
1485{
1486 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
1487 struct saa7146_dev *saa = budget_ci->budget.dev;
1488 int err;
1489
1490 if (budget_ci->budget.ci_present)
1491 ciintf_deinit(budget_ci);
David Hardeman8cc532e2006-12-02 21:16:05 -02001492 msp430_ir_deinit(budget_ci);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001493 if (budget_ci->budget.dvb_frontend) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001495 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001496 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 err = ttpci_budget_deinit(&budget_ci->budget);
1498
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 // disable frontend and CI interface
1500 saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
1501
1502 kfree(budget_ci);
1503
1504 return err;
1505}
1506
1507static struct saa7146_extension budget_extension;
1508
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001509MAKE_BUDGET_INFO(ttbs2, "TT-Budget/S-1500 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
1511MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001512MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001513MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
Sigmund Augdal11417da2008-06-15 17:25:46 -03001514MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001515MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516
1517static struct pci_device_id pci_tbl[] = {
1518 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
1519 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001520 MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001522 MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001523 MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
Sigmund Augdal11417da2008-06-15 17:25:46 -03001524 MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001525 MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 {
1527 .vendor = 0,
1528 }
1529};
1530
1531MODULE_DEVICE_TABLE(pci, pci_tbl);
1532
1533static struct saa7146_extension budget_extension = {
Dave Jones0e367a12006-08-07 13:18:56 -03001534 .name = "budget_ci dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03001535 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
1537 .module = THIS_MODULE,
1538 .pci_tbl = &pci_tbl[0],
1539 .attach = budget_ci_attach,
1540 .detach = budget_ci_detach,
1541
1542 .irq_mask = MASK_03 | MASK_06 | MASK_10,
1543 .irq_func = budget_ci_irq,
1544};
1545
1546static int __init budget_ci_init(void)
1547{
1548 return saa7146_register_extension(&budget_extension);
1549}
1550
1551static void __exit budget_ci_exit(void)
1552{
1553 saa7146_unregister_extension(&budget_extension);
1554}
1555
1556module_init(budget_ci_init);
1557module_exit(budget_ci_exit);
1558
1559MODULE_LICENSE("GPL");
1560MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
1561MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1562 "budget PCI DVB cards w/ CI-module produced by "
1563 "Siemens, Technotrend, Hauppauge");