blob: 46171439633136fc23b6b8e869abba15b1a9a8e9 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * budget-ci.c: driver for the SAA7146 based Budget DVB cards
3 *
4 * Compiled from various sources by Michael Hunold <michael@mihu.de>
5 *
6 * msp430 IR support contributed by Jack Thomasson <jkt@Helius.COM>
7 * partially based on the Siemens DVB driver by Ralph+Marcus Metzler
8 *
9 * CI interface support (c) 2004 Andrew de Quincey <adq_dvb@lidskialf.net>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
27 *
28 *
29 * the project's page is at http://www.linuxtv.org/dvb/
30 */
31
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/module.h>
33#include <linux/errno.h>
34#include <linux/slab.h>
35#include <linux/interrupt.h>
36#include <linux/input.h>
37#include <linux/spinlock.h>
David 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:
Oliver Endrissbbfc4c22008-06-19 23:36:45 -0300218 case 0x101a:
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300219 /* for the Technotrend 1500 bundled remote */
Mauro Carvalho Chehab02858ee2010-04-02 20:01:00 -0300220 ir_codes = RC_MAP_TT_1500;
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300221 break;
David Hardeman2520fff2006-12-02 21:16:05 -0200222 default:
223 /* unknown remote */
Mauro Carvalho Chehab02858ee2010-04-02 20:01:00 -0300224 ir_codes = RC_MAP_BUDGET_CI_OLD;
David Hardeman2520fff2006-12-02 21:16:05 -0200225 break;
226 }
227
Mauro Carvalho Chehab02858ee2010-04-02 20:01:00 -0300228 error = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME);
David Hardeman8cc532e2006-12-02 21:16:05 -0200229 if (error) {
230 printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
Mauro Carvalho Chehab579e7d62009-12-11 11:20:59 -0300231 return error;
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300232 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233
David Härdeman145859c2007-04-27 12:31:22 -0300234 /* note: these must be after input_register_device */
235 input_dev->rep[REP_DELAY] = 400;
236 input_dev->rep[REP_PERIOD] = 250;
237
David Hardeman8cc532e2006-12-02 21:16:05 -0200238 tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
239 (unsigned long) budget_ci);
240
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300241 SAA7146_IER_ENABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
243
244 return 0;
245}
246
247static void msp430_ir_deinit(struct budget_ci *budget_ci)
248{
249 struct saa7146_dev *saa = budget_ci->budget.dev;
David Hardemandd2f3982006-12-02 21:16:05 -0200250 struct input_dev *dev = budget_ci->ir.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300252 SAA7146_IER_DISABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
David Hardeman8cc532e2006-12-02 21:16:05 -0200254 tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255
Mauro Carvalho Chehab38ef6aa2009-12-11 09:47:42 -0300256 ir_input_unregister(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257}
258
259static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
260{
261 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
262
263 if (slot != 0)
264 return -EINVAL;
265
266 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
267 DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);
268}
269
270static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
271{
272 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
273
274 if (slot != 0)
275 return -EINVAL;
276
277 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
278 DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);
279}
280
281static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
282{
283 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
284
285 if (slot != 0)
286 return -EINVAL;
287
288 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
289 DEBIADDR_IO | (address & 3), 1, 1, 0);
290}
291
292static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
293{
294 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
295
296 if (slot != 0)
297 return -EINVAL;
298
299 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
300 DEBIADDR_IO | (address & 3), 1, value, 1, 0);
301}
302
303static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
304{
305 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
306 struct saa7146_dev *saa = budget_ci->budget.dev;
307
308 if (slot != 0)
309 return -EINVAL;
310
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300311 if (budget_ci->ci_irq) {
312 // trigger on RISING edge during reset so we know when READY is re-asserted
313 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
314 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 budget_ci->slot_status = SLOTSTATUS_RESET;
316 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
317 msleep(1);
318 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
319 CICONTROL_RESET, 1, 0);
320
321 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
322 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
323 return 0;
324}
325
326static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
327{
328 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
329 struct saa7146_dev *saa = budget_ci->budget.dev;
330
331 if (slot != 0)
332 return -EINVAL;
333
334 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
335 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
336 return 0;
337}
338
339static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
340{
341 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
342 struct saa7146_dev *saa = budget_ci->budget.dev;
343 int tmp;
344
345 if (slot != 0)
346 return -EINVAL;
347
348 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
349
350 tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
351 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
352 tmp | CICONTROL_ENABLETS, 1, 0);
353
354 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
355 return 0;
356}
357
358static void ciintf_interrupt(unsigned long data)
359{
360 struct budget_ci *budget_ci = (struct budget_ci *) data;
361 struct saa7146_dev *saa = budget_ci->budget.dev;
362 unsigned int flags;
363
364 // ensure we don't get spurious IRQs during initialisation
365 if (!budget_ci->budget.ci_present)
366 return;
367
368 // read the CAM status
369 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
370 if (flags & CICONTROL_CAMDETECT) {
371
372 // GPIO should be set to trigger on falling edge if a CAM is present
373 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
374
375 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
376 // CAM insertion IRQ
377 budget_ci->slot_status = SLOTSTATUS_PRESENT;
378 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
379 DVB_CA_EN50221_CAMCHANGE_INSERTED);
380
381 } else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
382 // CAM ready (reset completed)
383 budget_ci->slot_status = SLOTSTATUS_READY;
384 dvb_ca_en50221_camready_irq(&budget_ci->ca, 0);
385
386 } else if (budget_ci->slot_status & SLOTSTATUS_READY) {
387 // FR/DA IRQ
388 dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);
389 }
390 } else {
391
392 // trigger on rising edge if a CAM is not present - when a CAM is inserted, we
393 // only want to get the IRQ when it sets READY. If we trigger on the falling edge,
394 // the CAM might not actually be ready yet.
395 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
396
397 // generate a CAM removal IRQ if we haven't already
398 if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
399 // CAM removal IRQ
400 budget_ci->slot_status = SLOTSTATUS_NONE;
401 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
402 DVB_CA_EN50221_CAMCHANGE_REMOVED);
403 }
404 }
405}
406
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300407static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
408{
409 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
410 unsigned int flags;
411
412 // ensure we don't get spurious IRQs during initialisation
413 if (!budget_ci->budget.ci_present)
414 return -EINVAL;
415
416 // read the CAM status
417 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
418 if (flags & CICONTROL_CAMDETECT) {
419 // mark it as present if it wasn't before
420 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
421 budget_ci->slot_status = SLOTSTATUS_PRESENT;
422 }
423
424 // during a RESET, we check if we can read from IO memory to see when CAM is ready
425 if (budget_ci->slot_status & SLOTSTATUS_RESET) {
426 if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
427 budget_ci->slot_status = SLOTSTATUS_READY;
428 }
429 }
430 } else {
431 budget_ci->slot_status = SLOTSTATUS_NONE;
432 }
433
434 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
435 if (budget_ci->slot_status & SLOTSTATUS_READY) {
436 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
437 }
438 return DVB_CA_EN50221_POLL_CAM_PRESENT;
439 }
440
441 return 0;
442}
443
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444static int ciintf_init(struct budget_ci *budget_ci)
445{
446 struct saa7146_dev *saa = budget_ci->budget.dev;
447 int flags;
448 int result;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300449 int ci_version;
450 int ca_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
452 memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
453
454 // enable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300455 saa7146_write(saa, MC1, MASK_27 | MASK_11);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456
457 // test if it is there
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300458 ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
459 if ((ci_version & 0xa0) != 0xa0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 result = -ENODEV;
461 goto error;
462 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300463
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 // determine whether a CAM is present or not
465 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
466 budget_ci->slot_status = SLOTSTATUS_NONE;
467 if (flags & CICONTROL_CAMDETECT)
468 budget_ci->slot_status = SLOTSTATUS_PRESENT;
469
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300470 // version 0xa2 of the CI firmware doesn't generate interrupts
471 if (ci_version == 0xa2) {
472 ca_flags = 0;
473 budget_ci->ci_irq = 0;
474 } else {
475 ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
476 DVB_CA_EN50221_FLAG_IRQ_FR |
477 DVB_CA_EN50221_FLAG_IRQ_DA;
478 budget_ci->ci_irq = 1;
479 }
480
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 // register CI interface
482 budget_ci->ca.owner = THIS_MODULE;
483 budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
484 budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
485 budget_ci->ca.read_cam_control = ciintf_read_cam_control;
486 budget_ci->ca.write_cam_control = ciintf_write_cam_control;
487 budget_ci->ca.slot_reset = ciintf_slot_reset;
488 budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
489 budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300490 budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 budget_ci->ca.data = budget_ci;
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700492 if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 &budget_ci->ca,
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300494 ca_flags, 1)) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 printk("budget_ci: CI interface detected, but initialisation failed.\n");
496 goto error;
497 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300498
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 // Setup CI slot IRQ
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300500 if (budget_ci->ci_irq) {
501 tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
502 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
503 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
504 } else {
505 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
506 }
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300507 SAA7146_IER_ENABLE(saa, MASK_03);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300509
510 // enable interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
512 CICONTROL_RESET, 1, 0);
513
514 // success!
515 printk("budget_ci: CI interface initialised\n");
516 budget_ci->budget.ci_present = 1;
517
518 // forge a fake CI IRQ so the CAM state is setup correctly
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300519 if (budget_ci->ci_irq) {
520 flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
521 if (budget_ci->slot_status != SLOTSTATUS_NONE)
522 flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
523 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
524 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
526 return 0;
527
528error:
Hartmut Birr2a893de2006-12-03 21:08:08 -0300529 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 return result;
531}
532
533static void ciintf_deinit(struct budget_ci *budget_ci)
534{
535 struct saa7146_dev *saa = budget_ci->budget.dev;
536
537 // disable CI interrupts
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300538 if (budget_ci->ci_irq) {
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300539 SAA7146_IER_DISABLE(saa, MASK_03);
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300540 saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
541 tasklet_kill(&budget_ci->ciintf_irq_tasklet);
542 }
543
544 // reset interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
546 msleep(1);
547 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
548 CICONTROL_RESET, 1, 0);
549
550 // disable TS data stream to CI interface
551 saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
552
553 // release the CA device
554 dvb_ca_en50221_release(&budget_ci->ca);
555
556 // disable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300557 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558}
559
560static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
561{
562 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
563
564 dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
565
566 if (*isr & MASK_06)
David Hardemandd2f3982006-12-02 21:16:05 -0200567 tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568
569 if (*isr & MASK_10)
570 ttpci_budget_irq10_handler(dev, isr);
571
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300572 if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
574}
575
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576static u8 philips_su1278_tt_inittab[] = {
577 0x01, 0x0f,
578 0x02, 0x30,
579 0x03, 0x00,
580 0x04, 0x5b,
581 0x05, 0x85,
582 0x06, 0x02,
583 0x07, 0x00,
584 0x08, 0x02,
585 0x09, 0x00,
586 0x0C, 0x01,
587 0x0D, 0x81,
588 0x0E, 0x44,
589 0x0f, 0x14,
590 0x10, 0x3c,
591 0x11, 0x84,
592 0x12, 0xda,
593 0x13, 0x97,
594 0x14, 0x95,
595 0x15, 0xc9,
596 0x16, 0x19,
597 0x17, 0x8c,
598 0x18, 0x59,
599 0x19, 0xf8,
600 0x1a, 0xfe,
601 0x1c, 0x7f,
602 0x1d, 0x00,
603 0x1e, 0x00,
604 0x1f, 0x50,
605 0x20, 0x00,
606 0x21, 0x00,
607 0x22, 0x00,
608 0x23, 0x00,
609 0x28, 0x00,
610 0x29, 0x28,
611 0x2a, 0x14,
612 0x2b, 0x0f,
613 0x2c, 0x09,
614 0x2d, 0x09,
615 0x31, 0x1f,
616 0x32, 0x19,
617 0x33, 0xfc,
618 0x34, 0x93,
619 0xff, 0xff
620};
621
622static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
623{
624 stv0299_writereg(fe, 0x0e, 0x44);
625 if (srate >= 10000000) {
626 stv0299_writereg(fe, 0x13, 0x97);
627 stv0299_writereg(fe, 0x14, 0x95);
628 stv0299_writereg(fe, 0x15, 0xc9);
629 stv0299_writereg(fe, 0x17, 0x8c);
630 stv0299_writereg(fe, 0x1a, 0xfe);
631 stv0299_writereg(fe, 0x1c, 0x7f);
632 stv0299_writereg(fe, 0x2d, 0x09);
633 } else {
634 stv0299_writereg(fe, 0x13, 0x99);
635 stv0299_writereg(fe, 0x14, 0x8d);
636 stv0299_writereg(fe, 0x15, 0xce);
637 stv0299_writereg(fe, 0x17, 0x43);
638 stv0299_writereg(fe, 0x1a, 0x1d);
639 stv0299_writereg(fe, 0x1c, 0x12);
640 stv0299_writereg(fe, 0x2d, 0x05);
641 }
642 stv0299_writereg(fe, 0x0e, 0x23);
643 stv0299_writereg(fe, 0x0f, 0x94);
644 stv0299_writereg(fe, 0x10, 0x39);
645 stv0299_writereg(fe, 0x15, 0xc9);
646
647 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
648 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
649 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
650
651 return 0;
652}
653
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300654static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,
655 struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656{
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300657 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 u32 div;
659 u8 buf[4];
660 struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
661
662 if ((params->frequency < 950000) || (params->frequency > 2150000))
663 return -EINVAL;
664
665 div = (params->frequency + (500 - 1)) / 500; // round correctly
666 buf[0] = (div >> 8) & 0x7f;
667 buf[1] = div & 0xff;
668 buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
669 buf[3] = 0x20;
670
671 if (params->u.qpsk.symbol_rate < 4000000)
672 buf[3] |= 1;
673
674 if (params->frequency < 1250000)
675 buf[3] |= 0;
676 else if (params->frequency < 1550000)
677 buf[3] |= 0x40;
678 else if (params->frequency < 2050000)
679 buf[3] |= 0x80;
680 else if (params->frequency < 2150000)
681 buf[3] |= 0xC0;
682
Patrick Boettcherdea74862006-05-14 05:01:31 -0300683 if (fe->ops.i2c_gate_ctrl)
684 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300685 if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 return -EIO;
687 return 0;
688}
689
690static struct stv0299_config philips_su1278_tt_config = {
691
692 .demod_address = 0x68,
693 .inittab = philips_su1278_tt_inittab,
694 .mclk = 64000000UL,
695 .invert = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 .skip_reinit = 1,
Oliver Endrissda2c7f62008-04-20 22:13:37 -0300697 .lock_output = STV0299_LOCKOUTPUT_1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 .volt13_op0_op1 = STV0299_VOLT13_OP1,
699 .min_delay_ms = 50,
700 .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701};
702
703
704
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300705static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706{
707 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
708 static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
709 static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700710 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 sizeof(td1316_init) };
712
713 // setup PLL configuration
Patrick Boettcherdea74862006-05-14 05:01:31 -0300714 if (fe->ops.i2c_gate_ctrl)
715 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
717 return -EIO;
718 msleep(1);
719
720 // disable the mc44BC374c (do not check for errors)
721 tuner_msg.addr = 0x65;
722 tuner_msg.buf = disable_mc44BC374c;
723 tuner_msg.len = sizeof(disable_mc44BC374c);
Patrick Boettcherdea74862006-05-14 05:01:31 -0300724 if (fe->ops.i2c_gate_ctrl)
725 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
Patrick Boettcherdea74862006-05-14 05:01:31 -0300727 if (fe->ops.i2c_gate_ctrl)
728 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
730 }
731
732 return 0;
733}
734
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300735static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736{
737 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
738 u8 tuner_buf[4];
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700739 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 -0700740 int tuner_frequency = 0;
741 u8 band, cp, filter;
742
743 // determine charge pump
744 tuner_frequency = params->frequency + 36130000;
745 if (tuner_frequency < 87000000)
746 return -EINVAL;
747 else if (tuner_frequency < 130000000)
748 cp = 3;
749 else if (tuner_frequency < 160000000)
750 cp = 5;
751 else if (tuner_frequency < 200000000)
752 cp = 6;
753 else if (tuner_frequency < 290000000)
754 cp = 3;
755 else if (tuner_frequency < 420000000)
756 cp = 5;
757 else if (tuner_frequency < 480000000)
758 cp = 6;
759 else if (tuner_frequency < 620000000)
760 cp = 3;
761 else if (tuner_frequency < 830000000)
762 cp = 5;
763 else if (tuner_frequency < 895000000)
764 cp = 7;
765 else
766 return -EINVAL;
767
768 // determine band
769 if (params->frequency < 49000000)
770 return -EINVAL;
771 else if (params->frequency < 159000000)
772 band = 1;
773 else if (params->frequency < 444000000)
774 band = 2;
775 else if (params->frequency < 861000000)
776 band = 4;
777 else
778 return -EINVAL;
779
780 // setup PLL filter and TDA9889
781 switch (params->u.ofdm.bandwidth) {
782 case BANDWIDTH_6_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300783 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 filter = 0;
785 break;
786
787 case BANDWIDTH_7_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300788 tda1004x_writereg(fe, 0x0C, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 filter = 0;
790 break;
791
792 case BANDWIDTH_8_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300793 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 filter = 1;
795 break;
796
797 default:
798 return -EINVAL;
799 }
800
801 // calculate divisor
802 // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
803 tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
804
805 // setup tuner buffer
806 tuner_buf[0] = tuner_frequency >> 8;
807 tuner_buf[1] = tuner_frequency & 0xff;
808 tuner_buf[2] = 0xca;
809 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
810
Patrick Boettcherdea74862006-05-14 05:01:31 -0300811 if (fe->ops.i2c_gate_ctrl)
812 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
814 return -EIO;
815
816 msleep(1);
817 return 0;
818}
819
820static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,
821 const struct firmware **fw, char *name)
822{
823 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
824
825 return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);
826}
827
828static struct tda1004x_config philips_tdm1316l_config = {
829
830 .demod_address = 0x8,
831 .invert = 0,
832 .invert_oclk = 0,
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700833 .xtal_freq = TDA10046_XTAL_4M,
834 .agc_config = TDA10046_AGC_DEFAULT,
835 .if_freq = TDA10046_FREQ_3617,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 .request_firmware = philips_tdm1316l_request_firmware,
837};
838
Oliver Endriss6c914492007-02-02 19:12:53 -0300839static struct tda1004x_config philips_tdm1316l_config_invert = {
840
841 .demod_address = 0x8,
842 .invert = 1,
843 .invert_oclk = 0,
844 .xtal_freq = TDA10046_XTAL_4M,
845 .agc_config = TDA10046_AGC_DEFAULT,
846 .if_freq = TDA10046_FREQ_3617,
847 .request_firmware = philips_tdm1316l_request_firmware,
848};
849
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300850static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700851{
852 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
853 u8 tuner_buf[5];
854 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
855 .flags = 0,
856 .buf = tuner_buf,
857 .len = sizeof(tuner_buf) };
858 int tuner_frequency = 0;
859 u8 band, cp, filter;
860
861 // determine charge pump
862 tuner_frequency = params->frequency + 36125000;
863 if (tuner_frequency < 87000000)
864 return -EINVAL;
865 else if (tuner_frequency < 130000000) {
866 cp = 3;
867 band = 1;
868 } else if (tuner_frequency < 160000000) {
869 cp = 5;
870 band = 1;
871 } else if (tuner_frequency < 200000000) {
872 cp = 6;
Oliver Endriss910a7b62007-05-03 13:16:12 -0300873 band = 1;
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700874 } else if (tuner_frequency < 290000000) {
875 cp = 3;
876 band = 2;
877 } else if (tuner_frequency < 420000000) {
878 cp = 5;
879 band = 2;
880 } else if (tuner_frequency < 480000000) {
881 cp = 6;
882 band = 2;
883 } else if (tuner_frequency < 620000000) {
884 cp = 3;
885 band = 4;
886 } else if (tuner_frequency < 830000000) {
887 cp = 5;
888 band = 4;
889 } else if (tuner_frequency < 895000000) {
890 cp = 7;
891 band = 4;
892 } else
893 return -EINVAL;
894
895 // assume PLL filter should always be 8MHz for the moment.
896 filter = 1;
897
898 // calculate divisor
899 tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
900
901 // setup tuner buffer
902 tuner_buf[0] = tuner_frequency >> 8;
903 tuner_buf[1] = tuner_frequency & 0xff;
904 tuner_buf[2] = 0xc8;
905 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
906 tuner_buf[4] = 0x80;
907
Patrick Boettcherdea74862006-05-14 05:01:31 -0300908 if (fe->ops.i2c_gate_ctrl)
909 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700910 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
911 return -EIO;
912
913 msleep(50);
914
Patrick Boettcherdea74862006-05-14 05:01:31 -0300915 if (fe->ops.i2c_gate_ctrl)
916 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700917 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
918 return -EIO;
919
920 msleep(1);
921
922 return 0;
923}
924
925static u8 dvbc_philips_tdm1316l_inittab[] = {
926 0x80, 0x01,
927 0x80, 0x00,
928 0x81, 0x01,
929 0x81, 0x00,
930 0x00, 0x09,
931 0x01, 0x69,
932 0x03, 0x00,
933 0x04, 0x00,
934 0x07, 0x00,
935 0x08, 0x00,
936 0x20, 0x00,
937 0x21, 0x40,
938 0x22, 0x00,
939 0x23, 0x00,
940 0x24, 0x40,
941 0x25, 0x88,
942 0x30, 0xff,
943 0x31, 0x00,
944 0x32, 0xff,
945 0x33, 0x00,
946 0x34, 0x50,
947 0x35, 0x7f,
948 0x36, 0x00,
949 0x37, 0x20,
950 0x38, 0x00,
951 0x40, 0x1c,
952 0x41, 0xff,
953 0x42, 0x29,
954 0x43, 0x20,
955 0x44, 0xff,
956 0x45, 0x00,
957 0x46, 0x00,
958 0x49, 0x04,
959 0x4a, 0x00,
960 0x4b, 0x7b,
961 0x52, 0x30,
962 0x55, 0xae,
963 0x56, 0x47,
964 0x57, 0xe1,
965 0x58, 0x3a,
966 0x5a, 0x1e,
967 0x5b, 0x34,
968 0x60, 0x00,
969 0x63, 0x00,
970 0x64, 0x00,
971 0x65, 0x00,
972 0x66, 0x00,
973 0x67, 0x00,
974 0x68, 0x00,
975 0x69, 0x00,
976 0x6a, 0x02,
977 0x6b, 0x00,
978 0x70, 0xff,
979 0x71, 0x00,
980 0x72, 0x00,
981 0x73, 0x00,
982 0x74, 0x0c,
983 0x80, 0x00,
984 0x81, 0x00,
985 0x82, 0x00,
986 0x83, 0x00,
987 0x84, 0x04,
988 0x85, 0x80,
989 0x86, 0x24,
990 0x87, 0x78,
991 0x88, 0x10,
992 0x89, 0x00,
993 0x90, 0x01,
994 0x91, 0x01,
995 0xa0, 0x04,
996 0xa1, 0x00,
997 0xa2, 0x00,
998 0xb0, 0x91,
999 0xb1, 0x0b,
1000 0xc0, 0x53,
1001 0xc1, 0x70,
1002 0xc2, 0x12,
1003 0xd0, 0x00,
1004 0xd1, 0x00,
1005 0xd2, 0x00,
1006 0xd3, 0x00,
1007 0xd4, 0x00,
1008 0xd5, 0x00,
1009 0xde, 0x00,
1010 0xdf, 0x00,
1011 0x61, 0x38,
1012 0x62, 0x0a,
1013 0x53, 0x13,
1014 0x59, 0x08,
1015 0xff, 0xff,
1016};
1017
1018static struct stv0297_config dvbc_philips_tdm1316l_config = {
1019 .demod_address = 0x1c,
1020 .inittab = dvbc_philips_tdm1316l_inittab,
1021 .invert = 0,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001022 .stop_during_read = 1,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001023};
1024
Sigmund Augdal11417da2008-06-15 17:25:46 -03001025static struct tda10023_config tda10023_config = {
1026 .demod_address = 0xc,
1027 .invert = 0,
1028 .xtal = 16000000,
1029 .pll_m = 11,
1030 .pll_p = 3,
1031 .pll_n = 1,
1032 .deltaf = 0xa511,
1033};
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001034
klaas de waalcf47d872009-03-25 17:53:02 -03001035static struct tda827x_config tda827x_config = {
1036 .config = 0,
1037};
1038
Manu Abrahama55bc842008-10-23 18:32:50 -03001039/* TT S2-3200 DVB-S (STB0899) Inittab */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001040static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001042 { STB0899_DEV_ID , 0x81 },
1043 { STB0899_DISCNTRL1 , 0x32 },
1044 { STB0899_DISCNTRL2 , 0x80 },
1045 { STB0899_DISRX_ST0 , 0x04 },
1046 { STB0899_DISRX_ST1 , 0x00 },
1047 { STB0899_DISPARITY , 0x00 },
1048 { STB0899_DISFIFO , 0x00 },
1049 { STB0899_DISSTATUS , 0x20 },
1050 { STB0899_DISF22 , 0x8c },
1051 { STB0899_DISF22RX , 0x9a },
Manu Abrahamef3052b2008-10-23 18:45:17 -03001052 { STB0899_SYSREG , 0x0b },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001053 { STB0899_ACRPRESC , 0x11 },
1054 { STB0899_ACRDIV1 , 0x0a },
1055 { STB0899_ACRDIV2 , 0x05 },
1056 { STB0899_DACR1 , 0x00 },
1057 { STB0899_DACR2 , 0x00 },
1058 { STB0899_OUTCFG , 0x00 },
1059 { STB0899_MODECFG , 0x00 },
1060 { STB0899_IRQSTATUS_3 , 0x30 },
1061 { STB0899_IRQSTATUS_2 , 0x00 },
1062 { STB0899_IRQSTATUS_1 , 0x00 },
1063 { STB0899_IRQSTATUS_0 , 0x00 },
1064 { STB0899_IRQMSK_3 , 0xf3 },
1065 { STB0899_IRQMSK_2 , 0xfc },
1066 { STB0899_IRQMSK_1 , 0xff },
1067 { STB0899_IRQMSK_0 , 0xff },
1068 { STB0899_IRQCFG , 0x00 },
1069 { STB0899_I2CCFG , 0x88 },
Manu Abraham40e8ce32008-02-03 19:37:02 -03001070 { STB0899_I2CRPT , 0x48 }, /* 12k Pullup, Repeater=16, Stop=disabled */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001071 { STB0899_IOPVALUE5 , 0x00 },
1072 { STB0899_IOPVALUE4 , 0x20 },
1073 { STB0899_IOPVALUE3 , 0xc9 },
1074 { STB0899_IOPVALUE2 , 0x90 },
1075 { STB0899_IOPVALUE1 , 0x40 },
1076 { STB0899_IOPVALUE0 , 0x00 },
1077 { STB0899_GPIO00CFG , 0x82 },
1078 { STB0899_GPIO01CFG , 0x82 },
1079 { STB0899_GPIO02CFG , 0x82 },
1080 { STB0899_GPIO03CFG , 0x82 },
1081 { STB0899_GPIO04CFG , 0x82 },
1082 { STB0899_GPIO05CFG , 0x82 },
1083 { STB0899_GPIO06CFG , 0x82 },
1084 { STB0899_GPIO07CFG , 0x82 },
1085 { STB0899_GPIO08CFG , 0x82 },
1086 { STB0899_GPIO09CFG , 0x82 },
1087 { STB0899_GPIO10CFG , 0x82 },
1088 { STB0899_GPIO11CFG , 0x82 },
1089 { STB0899_GPIO12CFG , 0x82 },
1090 { STB0899_GPIO13CFG , 0x82 },
1091 { STB0899_GPIO14CFG , 0x82 },
1092 { STB0899_GPIO15CFG , 0x82 },
1093 { STB0899_GPIO16CFG , 0x82 },
1094 { STB0899_GPIO17CFG , 0x82 },
1095 { STB0899_GPIO18CFG , 0x82 },
1096 { STB0899_GPIO19CFG , 0x82 },
1097 { STB0899_GPIO20CFG , 0x82 },
1098 { STB0899_SDATCFG , 0xb8 },
1099 { STB0899_SCLTCFG , 0xba },
Manu Abrahama55bc842008-10-23 18:32:50 -03001100 { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */
1101 { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */
1102 { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001103 { STB0899_DIRCLKCFG , 0x82 },
1104 { STB0899_CLKOUT27CFG , 0x7e },
1105 { STB0899_STDBYCFG , 0x82 },
1106 { STB0899_CS0CFG , 0x82 },
1107 { STB0899_CS1CFG , 0x82 },
1108 { STB0899_DISEQCOCFG , 0x20 },
1109 { STB0899_GPIO32CFG , 0x82 },
1110 { STB0899_GPIO33CFG , 0x82 },
1111 { STB0899_GPIO34CFG , 0x82 },
1112 { STB0899_GPIO35CFG , 0x82 },
1113 { STB0899_GPIO36CFG , 0x82 },
1114 { STB0899_GPIO37CFG , 0x82 },
1115 { STB0899_GPIO38CFG , 0x82 },
1116 { STB0899_GPIO39CFG , 0x82 },
Manu Abrahamf2e52cd2007-11-19 16:44:47 -03001117 { STB0899_NCOARSE , 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
Manu Abrahama55bc842008-10-23 18:32:50 -03001118 { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001119 { STB0899_FILTCTRL , 0x00 },
1120 { STB0899_SYSCTRL , 0x00 },
1121 { STB0899_STOPCLK1 , 0x20 },
1122 { STB0899_STOPCLK2 , 0x00 },
1123 { STB0899_INTBUFSTATUS , 0x00 },
1124 { STB0899_INTBUFCTRL , 0x0a },
1125 { 0xffff , 0xff },
1126};
1127
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001128static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = {
1129 { STB0899_DEMOD , 0x00 },
1130 { STB0899_RCOMPC , 0xc9 },
1131 { STB0899_AGC1CN , 0x41 },
1132 { STB0899_AGC1REF , 0x10 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001133 { STB0899_RTC , 0x7a },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001134 { STB0899_TMGCFG , 0x4e },
1135 { STB0899_AGC2REF , 0x34 },
1136 { STB0899_TLSR , 0x84 },
1137 { STB0899_CFD , 0xc7 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001138 { STB0899_ACLC , 0x87 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001139 { STB0899_BCLC , 0x94 },
1140 { STB0899_EQON , 0x41 },
1141 { STB0899_LDT , 0xdd },
1142 { STB0899_LDT2 , 0xc9 },
1143 { STB0899_EQUALREF , 0xb4 },
1144 { STB0899_TMGRAMP , 0x10 },
1145 { STB0899_TMGTHD , 0x30 },
1146 { STB0899_IDCCOMP , 0xfb },
1147 { STB0899_QDCCOMP , 0x03 },
1148 { STB0899_POWERI , 0x3b },
1149 { STB0899_POWERQ , 0x3d },
1150 { STB0899_RCOMP , 0x81 },
1151 { STB0899_AGCIQIN , 0x80 },
1152 { STB0899_AGC2I1 , 0x04 },
1153 { STB0899_AGC2I2 , 0xf5 },
1154 { STB0899_TLIR , 0x25 },
1155 { STB0899_RTF , 0x80 },
1156 { STB0899_DSTATUS , 0x00 },
1157 { STB0899_LDI , 0xca },
1158 { STB0899_CFRM , 0xf1 },
1159 { STB0899_CFRL , 0xf3 },
1160 { STB0899_NIRM , 0x2a },
1161 { STB0899_NIRL , 0x05 },
1162 { STB0899_ISYMB , 0x17 },
1163 { STB0899_QSYMB , 0xfa },
1164 { STB0899_SFRH , 0x2f },
1165 { STB0899_SFRM , 0x68 },
1166 { STB0899_SFRL , 0x40 },
1167 { STB0899_SFRUPH , 0x2f },
1168 { STB0899_SFRUPM , 0x68 },
1169 { STB0899_SFRUPL , 0x40 },
1170 { STB0899_EQUAI1 , 0xfd },
1171 { STB0899_EQUAQ1 , 0x04 },
1172 { STB0899_EQUAI2 , 0x0f },
1173 { STB0899_EQUAQ2 , 0xff },
1174 { STB0899_EQUAI3 , 0xdf },
1175 { STB0899_EQUAQ3 , 0xfa },
1176 { STB0899_EQUAI4 , 0x37 },
1177 { STB0899_EQUAQ4 , 0x0d },
1178 { STB0899_EQUAI5 , 0xbd },
1179 { STB0899_EQUAQ5 , 0xf7 },
1180 { STB0899_DSTATUS2 , 0x00 },
1181 { STB0899_VSTATUS , 0x00 },
1182 { STB0899_VERROR , 0xff },
1183 { STB0899_IQSWAP , 0x2a },
1184 { STB0899_ECNT1M , 0x00 },
1185 { STB0899_ECNT1L , 0x00 },
1186 { STB0899_ECNT2M , 0x00 },
1187 { STB0899_ECNT2L , 0x00 },
1188 { STB0899_ECNT3M , 0x00 },
1189 { STB0899_ECNT3L , 0x00 },
1190 { STB0899_FECAUTO1 , 0x06 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001191 { STB0899_FECM , 0x01 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001192 { STB0899_VTH12 , 0xf0 },
1193 { STB0899_VTH23 , 0xa0 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001194 { STB0899_VTH34 , 0x78 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001195 { STB0899_VTH56 , 0x4e },
1196 { STB0899_VTH67 , 0x48 },
1197 { STB0899_VTH78 , 0x38 },
1198 { STB0899_PRVIT , 0xff },
1199 { STB0899_VITSYNC , 0x19 },
Manu Abrahama55bc842008-10-23 18:32:50 -03001200 { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001201 { STB0899_TSULC , 0x42 },
1202 { STB0899_RSLLC , 0x40 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001203 { STB0899_TSLPL , 0x12 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001204 { STB0899_TSCFGH , 0x0c },
1205 { STB0899_TSCFGM , 0x00 },
1206 { STB0899_TSCFGL , 0x0c },
Manu Abrahamc1426df2009-11-13 18:51:39 -03001207 { STB0899_TSOUT , 0x4d }, /* 0x0d for CAM */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001208 { STB0899_RSSYNCDEL , 0x00 },
1209 { STB0899_TSINHDELH , 0x02 },
1210 { STB0899_TSINHDELM , 0x00 },
1211 { STB0899_TSINHDELL , 0x00 },
1212 { STB0899_TSLLSTKM , 0x00 },
1213 { STB0899_TSLLSTKL , 0x00 },
1214 { STB0899_TSULSTKM , 0x00 },
1215 { STB0899_TSULSTKL , 0xab },
1216 { STB0899_PCKLENUL , 0x00 },
1217 { STB0899_PCKLENLL , 0xcc },
1218 { STB0899_RSPCKLEN , 0xcc },
1219 { STB0899_TSSTATUS , 0x80 },
1220 { STB0899_ERRCTRL1 , 0xb6 },
1221 { STB0899_ERRCTRL2 , 0x96 },
1222 { STB0899_ERRCTRL3 , 0x89 },
1223 { STB0899_DMONMSK1 , 0x27 },
1224 { STB0899_DMONMSK0 , 0x03 },
1225 { STB0899_DEMAPVIT , 0x5c },
1226 { STB0899_PLPARM , 0x1f },
1227 { STB0899_PDELCTRL , 0x48 },
1228 { STB0899_PDELCTRL2 , 0x00 },
1229 { STB0899_BBHCTRL1 , 0x00 },
1230 { STB0899_BBHCTRL2 , 0x00 },
1231 { STB0899_HYSTTHRESH , 0x77 },
1232 { STB0899_MATCSTM , 0x00 },
1233 { STB0899_MATCSTL , 0x00 },
1234 { STB0899_UPLCSTM , 0x00 },
1235 { STB0899_UPLCSTL , 0x00 },
1236 { STB0899_DFLCSTM , 0x00 },
1237 { STB0899_DFLCSTL , 0x00 },
1238 { STB0899_SYNCCST , 0x00 },
1239 { STB0899_SYNCDCSTM , 0x00 },
1240 { STB0899_SYNCDCSTL , 0x00 },
1241 { STB0899_ISI_ENTRY , 0x00 },
1242 { STB0899_ISI_BIT_EN , 0x00 },
1243 { STB0899_MATSTRM , 0x00 },
1244 { STB0899_MATSTRL , 0x00 },
1245 { STB0899_UPLSTRM , 0x00 },
1246 { STB0899_UPLSTRL , 0x00 },
1247 { STB0899_DFLSTRM , 0x00 },
1248 { STB0899_DFLSTRL , 0x00 },
1249 { STB0899_SYNCSTR , 0x00 },
1250 { STB0899_SYNCDSTRM , 0x00 },
1251 { STB0899_SYNCDSTRL , 0x00 },
1252 { STB0899_CFGPDELSTATUS1 , 0x10 },
1253 { STB0899_CFGPDELSTATUS2 , 0x00 },
1254 { STB0899_BBFERRORM , 0x00 },
1255 { STB0899_BBFERRORL , 0x00 },
1256 { STB0899_UPKTERRORM , 0x00 },
1257 { STB0899_UPKTERRORL , 0x00 },
1258 { 0xffff , 0xff },
1259};
1260
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001261static struct stb0899_config tt3200_config = {
1262 .init_dev = tt3200_stb0899_s1_init_1,
Manu Abraham8be969b2008-01-25 18:20:48 -03001263 .init_s2_demod = stb0899_s2_init_2,
Manu Abrahama55bc842008-10-23 18:32:50 -03001264 .init_s1_demod = tt3200_stb0899_s1_init_3,
Manu Abraham8be969b2008-01-25 18:20:48 -03001265 .init_s2_fec = stb0899_s2_init_4,
1266 .init_tst = stb0899_s1_init_5,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001267
Manu Abraham043a68b2008-01-18 14:15:17 -03001268 .postproc = NULL,
1269
Manu Abrahama55bc842008-10-23 18:32:50 -03001270 .demod_address = 0x68,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001271
1272 .xtal_freq = 27000000,
Manu Abrahame99d00c2007-09-25 17:48:59 -03001273 .inversion = IQ_SWAP_ON, /* 1 */
Manu Abrahama55bc842008-10-23 18:32:50 -03001274
Manu Abrahamb91a7cb2008-03-04 19:19:58 -03001275 .lo_clk = 76500000,
1276 .hi_clk = 99000000,
1277
Manu Abraham8be969b2008-01-25 18:20:48 -03001278 .esno_ave = STB0899_DVBS2_ESNO_AVE,
1279 .esno_quant = STB0899_DVBS2_ESNO_QUANT,
1280 .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
1281 .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
1282 .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
1283 .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
1284 .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
1285 .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
1286 .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
Manu Abrahama55bc842008-10-23 18:32:50 -03001287
Manu Abraham8be969b2008-01-25 18:20:48 -03001288 .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
1289 .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
1290 .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
1291 .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
Manu Abrahama55bc842008-10-23 18:32:50 -03001292
1293 .tuner_get_frequency = stb6100_get_frequency,
1294 .tuner_set_frequency = stb6100_set_frequency,
1295 .tuner_set_bandwidth = stb6100_set_bandwidth,
1296 .tuner_get_bandwidth = stb6100_get_bandwidth,
Manu Abraham043a68b2008-01-18 14:15:17 -03001297 .tuner_set_rfsiggain = NULL
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001298};
1299
Mauro Carvalho Chehabffbc5f82009-01-05 01:34:20 -03001300static struct stb6100_config tt3200_stb6100_config = {
Manu Abrahamc14eaed2007-10-04 16:52:51 -03001301 .tuner_address = 0x60,
1302 .refclock = 27000000,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001303};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304
1305static void frontend_init(struct budget_ci *budget_ci)
1306{
1307 switch (budget_ci->budget.dev->pci->subsystem_device) {
1308 case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
1309 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001310 dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001312 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001313 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 break;
1315 }
1316 break;
1317
1318 case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
1319 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001320 dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001322 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 break;
1324 }
1325 break;
1326
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001327 case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
1328 budget_ci->tuner_pll_address = 0x61;
1329 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001330 dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001331 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001332 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001333 break;
1334 }
1335 break;
1336
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001338 budget_ci->tuner_pll_address = 0x63;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001340 dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001342 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1343 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 break;
1345 }
1346 break;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001347
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001348 case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001349 budget_ci->tuner_pll_address = 0x60;
1350 budget_ci->budget.dvb_frontend =
Oliver Endriss6c914492007-02-02 19:12:53 -03001351 dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001352 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001353 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1354 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001355 break;
1356 }
1357 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001358
1359 case 0x1017: // TT S-1500 PCI
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001360 budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001361 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001362 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001363 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
1364
Patrick Boettcherdea74862006-05-14 05:01:31 -03001365 budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001366 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 -03001367 printk("%s: No LNBP21 found!\n", __func__);
Andrew de Quincey2b100e72006-08-08 09:10:11 -03001368 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001369 budget_ci->budget.dvb_frontend = NULL;
1370 }
1371 }
Sigmund Augdal11417da2008-06-15 17:25:46 -03001372 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001373
Sigmund Augdal11417da2008-06-15 17:25:46 -03001374 case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */
1375 budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48);
1376 if (budget_ci->budget.dvb_frontend) {
klaas de waalcf47d872009-03-25 17:53:02 -03001377 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 -03001378 printk(KERN_ERR "%s: No tda827x found!\n", __func__);
1379 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1380 budget_ci->budget.dvb_frontend = NULL;
1381 }
1382 }
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001383 break;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001384
1385 case 0x1019: // TT S2-3200 PCI
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001386 /*
1387 * NOTE! on some STB0899 versions, the internal PLL takes a longer time
1388 * to settle, aka LOCK. On the older revisions of the chip, we don't see
1389 * this, as a result on the newer chips the entire clock tree, will not
1390 * be stable after a freshly POWER 'ed up situation.
1391 * In this case, we should RESET the STB0899 (Active LOW) and wait for
1392 * PLL stabilization.
1393 *
1394 * On the TT S2 3200 and clones, the STB0899 demodulator's RESETB is
1395 * connected to the SAA7146 GPIO, GPIO2, Pin 142
1396 */
1397 /* Reset Demodulator */
Manu Abraham0867f572007-10-15 13:07:16 -03001398 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001399 /* Wait for everything to die */
1400 msleep(50);
1401 /* Pull it up out of Reset state */
Manu Abraham0867f572007-10-15 13:07:16 -03001402 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001403 /* Wait for PLL to stabilize */
1404 msleep(250);
1405 /*
1406 * PLL state should be stable now. Ideally, we should check
1407 * for PLL LOCK status. But well, never mind!
1408 */
Manu Abrahamae9902d2007-10-08 18:51:54 -03001409 budget_ci->budget.dvb_frontend = dvb_attach(stb0899_attach, &tt3200_config, &budget_ci->budget.i2c_adap);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001410 if (budget_ci->budget.dvb_frontend) {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001411 if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {
1412 if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
Harvey Harrison9b4778f2009-01-07 14:42:41 -08001413 printk("%s: No LNBP21 found!\n", __func__);
Manu Abrahamae9902d2007-10-08 18:51:54 -03001414 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001415 budget_ci->budget.dvb_frontend = NULL;
1416 }
1417 } else {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001418 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1419 budget_ci->budget.dvb_frontend = NULL;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001420 }
1421 }
1422 break;
1423
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 }
1425
1426 if (budget_ci->budget.dvb_frontend == NULL) {
Bjorn Helgaas29e66a62008-09-04 17:24:51 -03001427 printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 budget_ci->budget.dev->pci->vendor,
1429 budget_ci->budget.dev->pci->device,
1430 budget_ci->budget.dev->pci->subsystem_vendor,
1431 budget_ci->budget.dev->pci->subsystem_device);
1432 } else {
1433 if (dvb_register_frontend
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001434 (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 printk("budget-ci: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001436 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 budget_ci->budget.dvb_frontend = NULL;
1438 }
1439 }
1440}
1441
1442static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
1443{
1444 struct budget_ci *budget_ci;
1445 int err;
1446
David Hardemanee579bc2006-12-02 21:16:05 -02001447 budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
David Hardeman8cc532e2006-12-02 21:16:05 -02001448 if (!budget_ci) {
1449 err = -ENOMEM;
1450 goto out1;
1451 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452
1453 dprintk(2, "budget_ci: %p\n", budget_ci);
1454
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 dev->ext_priv = budget_ci;
1456
Janne Grunau26dc4d02008-09-21 20:50:11 -03001457 err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE,
1458 adapter_nr);
David Hardeman8cc532e2006-12-02 21:16:05 -02001459 if (err)
1460 goto out2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461
David Hardeman8cc532e2006-12-02 21:16:05 -02001462 err = msp430_ir_init(budget_ci);
1463 if (err)
1464 goto out3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465
1466 ciintf_init(budget_ci);
1467
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001468 budget_ci->budget.dvb_adapter.priv = budget_ci;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 frontend_init(budget_ci);
1470
Oliver Endriss32e4c3a2006-07-18 22:55:23 -03001471 ttpci_budget_init_hooks(&budget_ci->budget);
1472
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 return 0;
David Hardeman8cc532e2006-12-02 21:16:05 -02001474
1475out3:
1476 ttpci_budget_deinit(&budget_ci->budget);
1477out2:
1478 kfree(budget_ci);
1479out1:
1480 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481}
1482
1483static int budget_ci_detach(struct saa7146_dev *dev)
1484{
1485 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
1486 struct saa7146_dev *saa = budget_ci->budget.dev;
1487 int err;
1488
1489 if (budget_ci->budget.ci_present)
1490 ciintf_deinit(budget_ci);
David Hardeman8cc532e2006-12-02 21:16:05 -02001491 msp430_ir_deinit(budget_ci);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001492 if (budget_ci->budget.dvb_frontend) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001494 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001495 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 err = ttpci_budget_deinit(&budget_ci->budget);
1497
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 // disable frontend and CI interface
1499 saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
1500
1501 kfree(budget_ci);
1502
1503 return err;
1504}
1505
1506static struct saa7146_extension budget_extension;
1507
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001508MAKE_BUDGET_INFO(ttbs2, "TT-Budget/S-1500 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
1510MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001511MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001512MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
Sigmund Augdal11417da2008-06-15 17:25:46 -03001513MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001514MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515
1516static struct pci_device_id pci_tbl[] = {
1517 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
1518 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001519 MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001521 MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001522 MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
Sigmund Augdal11417da2008-06-15 17:25:46 -03001523 MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001524 MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 {
1526 .vendor = 0,
1527 }
1528};
1529
1530MODULE_DEVICE_TABLE(pci, pci_tbl);
1531
1532static struct saa7146_extension budget_extension = {
Dave Jones0e367a12006-08-07 13:18:56 -03001533 .name = "budget_ci dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03001534 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535
1536 .module = THIS_MODULE,
1537 .pci_tbl = &pci_tbl[0],
1538 .attach = budget_ci_attach,
1539 .detach = budget_ci_detach,
1540
1541 .irq_mask = MASK_03 | MASK_06 | MASK_10,
1542 .irq_func = budget_ci_irq,
1543};
1544
1545static int __init budget_ci_init(void)
1546{
1547 return saa7146_register_extension(&budget_extension);
1548}
1549
1550static void __exit budget_ci_exit(void)
1551{
1552 saa7146_unregister_extension(&budget_extension);
1553}
1554
1555module_init(budget_ci_init);
1556module_exit(budget_ci_exit);
1557
1558MODULE_LICENSE("GPL");
1559MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
1560MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1561 "budget PCI DVB cards w/ CI-module produced by "
1562 "Siemens, Technotrend, Hauppauge");