blob: bcbc5d41a0feb0d8a907672786dc043cad5c9320 [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 Hardeman2520fff2006-12-02 21:16:05 -020038#include <media/ir-common.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
David Härdemanecba77f2006-10-27 20:56:51 -030057/*
58 * Regarding DEBIADDR_IR:
59 * Some CI modules hang if random addresses are read.
60 * Using address 0x4000 for the IR read means that we
61 * use the same address as for CI version, which should
62 * be a safe default.
63 */
64#define DEBIADDR_IR 0x4000
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#define DEBIADDR_CICONTROL 0x0000
66#define DEBIADDR_CIVERSION 0x4000
67#define DEBIADDR_IO 0x1000
68#define DEBIADDR_ATTR 0x3000
69
70#define CICONTROL_RESET 0x01
71#define CICONTROL_ENABLETS 0x02
72#define CICONTROL_CAMDETECT 0x08
73
74#define DEBICICTL 0x00420000
75#define DEBICICAM 0x02420000
76
77#define SLOTSTATUS_NONE 1
78#define SLOTSTATUS_PRESENT 2
79#define SLOTSTATUS_RESET 4
80#define SLOTSTATUS_READY 8
81#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
82
David Härdeman145859c2007-04-27 12:31:22 -030083/*
84 * Milliseconds during which a key is regarded as pressed.
85 * If an identical command arrives within this time, the timer will start over.
David Hardeman2520fff2006-12-02 21:16:05 -020086 */
David Härdeman145859c2007-04-27 12:31:22 -030087#define IR_KEYPRESS_TIMEOUT 250
David Hardeman2520fff2006-12-02 21:16:05 -020088
David Hardeman64741b72006-12-02 21:16:05 -020089/* RC5 device wildcard */
90#define IR_DEVICE_ANY 255
91
David Hardeman64741b72006-12-02 21:16:05 -020092static int rc5_device = -1;
93module_param(rc5_device, int, 0644);
94MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
95
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030096static int ir_debug;
David Hardemanb5471a22006-12-02 21:16:05 -020097module_param(ir_debug, int, 0644);
98MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
99
Janne Grunau26dc4d02008-09-21 20:50:11 -0300100DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
101
David Hardemandd2f3982006-12-02 21:16:05 -0200102struct budget_ci_ir {
103 struct input_dev *dev;
104 struct tasklet_struct msp430_irq_tasklet;
David Härdeman145859c2007-04-27 12:31:22 -0300105 struct timer_list timer_keyup;
David Hardemandd2f3982006-12-02 21:16:05 -0200106 char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
David Hardeman5cc8ae02006-12-02 21:16:05 -0200107 char phys[32];
David Hardeman2520fff2006-12-02 21:16:05 -0200108 struct ir_input_state state;
David Hardeman64741b72006-12-02 21:16:05 -0200109 int rc5_device;
David Härdeman145859c2007-04-27 12:31:22 -0300110 u32 last_raw;
111 u32 ir_key;
112 bool have_command;
David Hardemandd2f3982006-12-02 21:16:05 -0200113};
114
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115struct budget_ci {
116 struct budget budget;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 struct tasklet_struct ciintf_irq_tasklet;
118 int slot_status;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300119 int ci_irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 struct dvb_ca_en50221 ca;
David Hardemandd2f3982006-12-02 21:16:05 -0200121 struct budget_ci_ir ir;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700122 u8 tuner_pll_address; /* used for philips_tdm1316l configs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123};
124
David Hardeman2520fff2006-12-02 21:16:05 -0200125static void msp430_ir_keyup(unsigned long data)
126{
127 struct budget_ci_ir *ir = (struct budget_ci_ir *) data;
128 ir_input_nokey(ir->dev, &ir->state);
129}
130
131static void msp430_ir_interrupt(unsigned long data)
132{
133 struct budget_ci *budget_ci = (struct budget_ci *) data;
134 struct input_dev *dev = budget_ci->ir.dev;
David Hardeman2520fff2006-12-02 21:16:05 -0200135 u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
David Härdeman145859c2007-04-27 12:31:22 -0300136 u32 raw;
David Hardeman2520fff2006-12-02 21:16:05 -0200137
David Hardeman64741b72006-12-02 21:16:05 -0200138 /*
139 * The msp430 chip can generate two different bytes, command and device
140 *
141 * type1: X1CCCCCC, C = command bits (0 - 63)
142 * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
143 *
David Härdeman59327a42007-02-13 09:39:58 -0300144 * Each signal from the remote control can generate one or more command
145 * bytes and one or more device bytes. For the repeated bytes, the
146 * highest bit (X) is set. The first command byte is always generated
147 * before the first device byte. Other than that, no specific order
David Härdeman145859c2007-04-27 12:31:22 -0300148 * seems to apply. To make life interesting, bytes can also be lost.
David Härdeman59327a42007-02-13 09:39:58 -0300149 *
150 * Only when we have a command and device byte, a keypress is
151 * generated.
David Hardeman64741b72006-12-02 21:16:05 -0200152 */
153
David Härdeman59327a42007-02-13 09:39:58 -0300154 if (ir_debug)
155 printk("budget_ci: received byte 0x%02x\n", command);
156
David Härdeman145859c2007-04-27 12:31:22 -0300157 /* Remove repeat bit, we use every command */
158 command = command & 0x7f;
David Härdeman59327a42007-02-13 09:39:58 -0300159
David Hardeman64741b72006-12-02 21:16:05 -0200160 /* Is this a RC5 command byte? */
David Hardeman2520fff2006-12-02 21:16:05 -0200161 if (command & 0x40) {
David Härdeman145859c2007-04-27 12:31:22 -0300162 budget_ci->ir.have_command = true;
163 budget_ci->ir.ir_key = command & 0x3f;
David Hardeman64741b72006-12-02 21:16:05 -0200164 return;
David Hardeman2520fff2006-12-02 21:16:05 -0200165 }
David Hardeman64741b72006-12-02 21:16:05 -0200166
167 /* It's a RC5 device byte */
David Härdeman145859c2007-04-27 12:31:22 -0300168 if (!budget_ci->ir.have_command)
David Härdeman59327a42007-02-13 09:39:58 -0300169 return;
David Härdeman145859c2007-04-27 12:31:22 -0300170 budget_ci->ir.have_command = false;
David Hardeman64741b72006-12-02 21:16:05 -0200171
David Härdeman145859c2007-04-27 12:31:22 -0300172 if (budget_ci->ir.rc5_device != IR_DEVICE_ANY &&
173 budget_ci->ir.rc5_device != (command & 0x1f))
David Hardeman64741b72006-12-02 21:16:05 -0200174 return;
175
David Härdeman145859c2007-04-27 12:31:22 -0300176 /* Is this a repeated key sequence? (same device, command, toggle) */
177 raw = budget_ci->ir.ir_key | (command << 8);
178 if (budget_ci->ir.last_raw != raw || !timer_pending(&budget_ci->ir.timer_keyup)) {
David Hardeman59236d42006-12-02 21:16:06 -0200179 ir_input_nokey(dev, &budget_ci->ir.state);
David Härdeman145859c2007-04-27 12:31:22 -0300180 ir_input_keydown(dev, &budget_ci->ir.state,
181 budget_ci->ir.ir_key, raw);
182 budget_ci->ir.last_raw = raw;
David Hardeman59236d42006-12-02 21:16:06 -0200183 }
David Härdeman145859c2007-04-27 12:31:22 -0300184
185 mod_timer(&budget_ci->ir.timer_keyup, jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT));
David Hardeman2520fff2006-12-02 21:16:05 -0200186}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188static int msp430_ir_init(struct budget_ci *budget_ci)
189{
190 struct saa7146_dev *saa = budget_ci->budget.dev;
David Hardemandd2f3982006-12-02 21:16:05 -0200191 struct input_dev *input_dev = budget_ci->ir.dev;
David Hardeman8cc532e2006-12-02 21:16:05 -0200192 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
David Hardemandd2f3982006-12-02 21:16:05 -0200194 budget_ci->ir.dev = input_dev = input_allocate_device();
David Hardeman8cc532e2006-12-02 21:16:05 -0200195 if (!input_dev) {
David Hardemanee579bc2006-12-02 21:16:05 -0200196 printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
David Hardeman8cc532e2006-12-02 21:16:05 -0200197 error = -ENOMEM;
198 goto out1;
199 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
David Hardemandd2f3982006-12-02 21:16:05 -0200201 snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
202 "Budget-CI dvb ir receiver %s", saa->name);
David Hardeman5cc8ae02006-12-02 21:16:05 -0200203 snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
204 "pci-%s/ir0", pci_name(saa->pci));
205
David Hardemandd2f3982006-12-02 21:16:05 -0200206 input_dev->name = budget_ci->ir.name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207
David Hardeman5cc8ae02006-12-02 21:16:05 -0200208 input_dev->phys = budget_ci->ir.phys;
209 input_dev->id.bustype = BUS_PCI;
210 input_dev->id.version = 1;
211 if (saa->pci->subsystem_vendor) {
212 input_dev->id.vendor = saa->pci->subsystem_vendor;
213 input_dev->id.product = saa->pci->subsystem_device;
214 } else {
215 input_dev->id.vendor = saa->pci->vendor;
216 input_dev->id.product = saa->pci->device;
217 }
Dmitry Torokhov2c8a3a32007-07-16 09:28:15 -0300218 input_dev->dev.parent = &saa->pci->dev;
David Hardeman5cc8ae02006-12-02 21:16:05 -0200219
David Hardeman64741b72006-12-02 21:16:05 -0200220 /* Select keymap and address */
David Hardeman2520fff2006-12-02 21:16:05 -0200221 switch (budget_ci->budget.dev->pci->subsystem_device) {
222 case 0x100c:
223 case 0x100f:
David Hardeman2520fff2006-12-02 21:16:05 -0200224 case 0x1011:
225 case 0x1012:
David Hardeman2520fff2006-12-02 21:16:05 -0200226 /* The hauppauge keymap is a superset of these remotes */
227 ir_input_init(input_dev, &budget_ci->ir.state,
228 IR_TYPE_RC5, ir_codes_hauppauge_new);
David Hardeman64741b72006-12-02 21:16:05 -0200229
230 if (rc5_device < 0)
231 budget_ci->ir.rc5_device = 0x1f;
232 else
233 budget_ci->ir.rc5_device = rc5_device;
David Hardeman2520fff2006-12-02 21:16:05 -0200234 break;
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300235 case 0x1010:
Oliver Endrissf64899c2007-09-17 22:17:12 -0300236 case 0x1017:
Oliver Endrissbbfc4c22008-06-19 23:36:45 -0300237 case 0x101a:
Ville-Pekka Vainioae1942c2007-01-12 14:06:21 -0300238 /* for the Technotrend 1500 bundled remote */
239 ir_input_init(input_dev, &budget_ci->ir.state,
240 IR_TYPE_RC5, ir_codes_tt_1500);
241
242 if (rc5_device < 0)
243 budget_ci->ir.rc5_device = IR_DEVICE_ANY;
244 else
245 budget_ci->ir.rc5_device = rc5_device;
246 break;
David Hardeman2520fff2006-12-02 21:16:05 -0200247 default:
248 /* unknown remote */
249 ir_input_init(input_dev, &budget_ci->ir.state,
250 IR_TYPE_RC5, ir_codes_budget_ci_old);
David Hardeman64741b72006-12-02 21:16:05 -0200251
252 if (rc5_device < 0)
253 budget_ci->ir.rc5_device = IR_DEVICE_ANY;
254 else
255 budget_ci->ir.rc5_device = rc5_device;
David Hardeman2520fff2006-12-02 21:16:05 -0200256 break;
257 }
258
David Härdeman145859c2007-04-27 12:31:22 -0300259 /* initialise the key-up timeout handler */
260 init_timer(&budget_ci->ir.timer_keyup);
261 budget_ci->ir.timer_keyup.function = msp430_ir_keyup;
262 budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir;
263 budget_ci->ir.last_raw = 0xffff; /* An impossible value */
David Hardeman8cc532e2006-12-02 21:16:05 -0200264 error = input_register_device(input_dev);
265 if (error) {
266 printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
267 goto out2;
Dmitry Torokhovb07b4782006-11-20 10:23:04 -0300268 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
David Härdeman145859c2007-04-27 12:31:22 -0300270 /* note: these must be after input_register_device */
271 input_dev->rep[REP_DELAY] = 400;
272 input_dev->rep[REP_PERIOD] = 250;
273
David Hardeman8cc532e2006-12-02 21:16:05 -0200274 tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
275 (unsigned long) budget_ci);
276
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300277 SAA7146_IER_ENABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
279
280 return 0;
David Hardeman8cc532e2006-12-02 21:16:05 -0200281
282out2:
283 input_free_device(input_dev);
284out1:
285 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286}
287
288static void msp430_ir_deinit(struct budget_ci *budget_ci)
289{
290 struct saa7146_dev *saa = budget_ci->budget.dev;
David Hardemandd2f3982006-12-02 21:16:05 -0200291 struct input_dev *dev = budget_ci->ir.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300293 SAA7146_IER_DISABLE(saa, MASK_06);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
David Hardeman8cc532e2006-12-02 21:16:05 -0200295 tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
David Härdeman145859c2007-04-27 12:31:22 -0300297 del_timer_sync(&dev->timer);
298 ir_input_nokey(dev, &budget_ci->ir.state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
300 input_unregister_device(dev);
301}
302
303static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
304{
305 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
306
307 if (slot != 0)
308 return -EINVAL;
309
310 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
311 DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);
312}
313
314static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
315{
316 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
317
318 if (slot != 0)
319 return -EINVAL;
320
321 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
322 DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);
323}
324
325static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
326{
327 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
328
329 if (slot != 0)
330 return -EINVAL;
331
332 return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
333 DEBIADDR_IO | (address & 3), 1, 1, 0);
334}
335
336static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
337{
338 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
339
340 if (slot != 0)
341 return -EINVAL;
342
343 return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
344 DEBIADDR_IO | (address & 3), 1, value, 1, 0);
345}
346
347static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
348{
349 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
350 struct saa7146_dev *saa = budget_ci->budget.dev;
351
352 if (slot != 0)
353 return -EINVAL;
354
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300355 if (budget_ci->ci_irq) {
356 // trigger on RISING edge during reset so we know when READY is re-asserted
357 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
358 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 budget_ci->slot_status = SLOTSTATUS_RESET;
360 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
361 msleep(1);
362 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
363 CICONTROL_RESET, 1, 0);
364
365 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
366 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
367 return 0;
368}
369
370static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
371{
372 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
373 struct saa7146_dev *saa = budget_ci->budget.dev;
374
375 if (slot != 0)
376 return -EINVAL;
377
378 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
379 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
380 return 0;
381}
382
383static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
384{
385 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
386 struct saa7146_dev *saa = budget_ci->budget.dev;
387 int tmp;
388
389 if (slot != 0)
390 return -EINVAL;
391
392 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
393
394 tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
395 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
396 tmp | CICONTROL_ENABLETS, 1, 0);
397
398 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
399 return 0;
400}
401
402static void ciintf_interrupt(unsigned long data)
403{
404 struct budget_ci *budget_ci = (struct budget_ci *) data;
405 struct saa7146_dev *saa = budget_ci->budget.dev;
406 unsigned int flags;
407
408 // ensure we don't get spurious IRQs during initialisation
409 if (!budget_ci->budget.ci_present)
410 return;
411
412 // read the CAM status
413 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
414 if (flags & CICONTROL_CAMDETECT) {
415
416 // GPIO should be set to trigger on falling edge if a CAM is present
417 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
418
419 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
420 // CAM insertion IRQ
421 budget_ci->slot_status = SLOTSTATUS_PRESENT;
422 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
423 DVB_CA_EN50221_CAMCHANGE_INSERTED);
424
425 } else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
426 // CAM ready (reset completed)
427 budget_ci->slot_status = SLOTSTATUS_READY;
428 dvb_ca_en50221_camready_irq(&budget_ci->ca, 0);
429
430 } else if (budget_ci->slot_status & SLOTSTATUS_READY) {
431 // FR/DA IRQ
432 dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);
433 }
434 } else {
435
436 // trigger on rising edge if a CAM is not present - when a CAM is inserted, we
437 // only want to get the IRQ when it sets READY. If we trigger on the falling edge,
438 // the CAM might not actually be ready yet.
439 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
440
441 // generate a CAM removal IRQ if we haven't already
442 if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
443 // CAM removal IRQ
444 budget_ci->slot_status = SLOTSTATUS_NONE;
445 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
446 DVB_CA_EN50221_CAMCHANGE_REMOVED);
447 }
448 }
449}
450
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300451static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
452{
453 struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
454 unsigned int flags;
455
456 // ensure we don't get spurious IRQs during initialisation
457 if (!budget_ci->budget.ci_present)
458 return -EINVAL;
459
460 // read the CAM status
461 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
462 if (flags & CICONTROL_CAMDETECT) {
463 // mark it as present if it wasn't before
464 if (budget_ci->slot_status & SLOTSTATUS_NONE) {
465 budget_ci->slot_status = SLOTSTATUS_PRESENT;
466 }
467
468 // during a RESET, we check if we can read from IO memory to see when CAM is ready
469 if (budget_ci->slot_status & SLOTSTATUS_RESET) {
470 if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
471 budget_ci->slot_status = SLOTSTATUS_READY;
472 }
473 }
474 } else {
475 budget_ci->slot_status = SLOTSTATUS_NONE;
476 }
477
478 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
479 if (budget_ci->slot_status & SLOTSTATUS_READY) {
480 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
481 }
482 return DVB_CA_EN50221_POLL_CAM_PRESENT;
483 }
484
485 return 0;
486}
487
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488static int ciintf_init(struct budget_ci *budget_ci)
489{
490 struct saa7146_dev *saa = budget_ci->budget.dev;
491 int flags;
492 int result;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300493 int ci_version;
494 int ca_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495
496 memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
497
498 // enable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300499 saa7146_write(saa, MC1, MASK_27 | MASK_11);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500
501 // test if it is there
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300502 ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
503 if ((ci_version & 0xa0) != 0xa0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 result = -ENODEV;
505 goto error;
506 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300507
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 // determine whether a CAM is present or not
509 flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
510 budget_ci->slot_status = SLOTSTATUS_NONE;
511 if (flags & CICONTROL_CAMDETECT)
512 budget_ci->slot_status = SLOTSTATUS_PRESENT;
513
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300514 // version 0xa2 of the CI firmware doesn't generate interrupts
515 if (ci_version == 0xa2) {
516 ca_flags = 0;
517 budget_ci->ci_irq = 0;
518 } else {
519 ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
520 DVB_CA_EN50221_FLAG_IRQ_FR |
521 DVB_CA_EN50221_FLAG_IRQ_DA;
522 budget_ci->ci_irq = 1;
523 }
524
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 // register CI interface
526 budget_ci->ca.owner = THIS_MODULE;
527 budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
528 budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
529 budget_ci->ca.read_cam_control = ciintf_read_cam_control;
530 budget_ci->ca.write_cam_control = ciintf_write_cam_control;
531 budget_ci->ca.slot_reset = ciintf_slot_reset;
532 budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
533 budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300534 budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 budget_ci->ca.data = budget_ci;
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700536 if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 &budget_ci->ca,
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300538 ca_flags, 1)) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 printk("budget_ci: CI interface detected, but initialisation failed.\n");
540 goto error;
541 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300542
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 // Setup CI slot IRQ
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300544 if (budget_ci->ci_irq) {
545 tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
546 if (budget_ci->slot_status != SLOTSTATUS_NONE) {
547 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
548 } else {
549 saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
550 }
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300551 SAA7146_IER_ENABLE(saa, MASK_03);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 }
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300553
554 // enable interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
556 CICONTROL_RESET, 1, 0);
557
558 // success!
559 printk("budget_ci: CI interface initialised\n");
560 budget_ci->budget.ci_present = 1;
561
562 // forge a fake CI IRQ so the CAM state is setup correctly
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300563 if (budget_ci->ci_irq) {
564 flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
565 if (budget_ci->slot_status != SLOTSTATUS_NONE)
566 flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
567 dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
568 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
570 return 0;
571
572error:
Hartmut Birr2a893de2006-12-03 21:08:08 -0300573 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 return result;
575}
576
577static void ciintf_deinit(struct budget_ci *budget_ci)
578{
579 struct saa7146_dev *saa = budget_ci->budget.dev;
580
581 // disable CI interrupts
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300582 if (budget_ci->ci_irq) {
Hartmut Birr97a2cf02006-12-03 10:49:47 -0300583 SAA7146_IER_DISABLE(saa, MASK_03);
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300584 saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
585 tasklet_kill(&budget_ci->ciintf_irq_tasklet);
586 }
587
588 // reset interface
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
590 msleep(1);
591 ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
592 CICONTROL_RESET, 1, 0);
593
594 // disable TS data stream to CI interface
595 saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
596
597 // release the CA device
598 dvb_ca_en50221_release(&budget_ci->ca);
599
600 // disable DEBI pins
Hartmut Birr2a893de2006-12-03 21:08:08 -0300601 saa7146_write(saa, MC1, MASK_27);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602}
603
604static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
605{
606 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
607
608 dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
609
610 if (*isr & MASK_06)
David Hardemandd2f3982006-12-02 21:16:05 -0200611 tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
613 if (*isr & MASK_10)
614 ttpci_budget_irq10_handler(dev, isr);
615
Andrew de Quincey96b194c2006-04-05 14:09:45 -0300616 if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
618}
619
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620static u8 philips_su1278_tt_inittab[] = {
621 0x01, 0x0f,
622 0x02, 0x30,
623 0x03, 0x00,
624 0x04, 0x5b,
625 0x05, 0x85,
626 0x06, 0x02,
627 0x07, 0x00,
628 0x08, 0x02,
629 0x09, 0x00,
630 0x0C, 0x01,
631 0x0D, 0x81,
632 0x0E, 0x44,
633 0x0f, 0x14,
634 0x10, 0x3c,
635 0x11, 0x84,
636 0x12, 0xda,
637 0x13, 0x97,
638 0x14, 0x95,
639 0x15, 0xc9,
640 0x16, 0x19,
641 0x17, 0x8c,
642 0x18, 0x59,
643 0x19, 0xf8,
644 0x1a, 0xfe,
645 0x1c, 0x7f,
646 0x1d, 0x00,
647 0x1e, 0x00,
648 0x1f, 0x50,
649 0x20, 0x00,
650 0x21, 0x00,
651 0x22, 0x00,
652 0x23, 0x00,
653 0x28, 0x00,
654 0x29, 0x28,
655 0x2a, 0x14,
656 0x2b, 0x0f,
657 0x2c, 0x09,
658 0x2d, 0x09,
659 0x31, 0x1f,
660 0x32, 0x19,
661 0x33, 0xfc,
662 0x34, 0x93,
663 0xff, 0xff
664};
665
666static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
667{
668 stv0299_writereg(fe, 0x0e, 0x44);
669 if (srate >= 10000000) {
670 stv0299_writereg(fe, 0x13, 0x97);
671 stv0299_writereg(fe, 0x14, 0x95);
672 stv0299_writereg(fe, 0x15, 0xc9);
673 stv0299_writereg(fe, 0x17, 0x8c);
674 stv0299_writereg(fe, 0x1a, 0xfe);
675 stv0299_writereg(fe, 0x1c, 0x7f);
676 stv0299_writereg(fe, 0x2d, 0x09);
677 } else {
678 stv0299_writereg(fe, 0x13, 0x99);
679 stv0299_writereg(fe, 0x14, 0x8d);
680 stv0299_writereg(fe, 0x15, 0xce);
681 stv0299_writereg(fe, 0x17, 0x43);
682 stv0299_writereg(fe, 0x1a, 0x1d);
683 stv0299_writereg(fe, 0x1c, 0x12);
684 stv0299_writereg(fe, 0x2d, 0x05);
685 }
686 stv0299_writereg(fe, 0x0e, 0x23);
687 stv0299_writereg(fe, 0x0f, 0x94);
688 stv0299_writereg(fe, 0x10, 0x39);
689 stv0299_writereg(fe, 0x15, 0xc9);
690
691 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
692 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
693 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
694
695 return 0;
696}
697
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300698static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,
699 struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700{
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300701 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 u32 div;
703 u8 buf[4];
704 struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
705
706 if ((params->frequency < 950000) || (params->frequency > 2150000))
707 return -EINVAL;
708
709 div = (params->frequency + (500 - 1)) / 500; // round correctly
710 buf[0] = (div >> 8) & 0x7f;
711 buf[1] = div & 0xff;
712 buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
713 buf[3] = 0x20;
714
715 if (params->u.qpsk.symbol_rate < 4000000)
716 buf[3] |= 1;
717
718 if (params->frequency < 1250000)
719 buf[3] |= 0;
720 else if (params->frequency < 1550000)
721 buf[3] |= 0x40;
722 else if (params->frequency < 2050000)
723 buf[3] |= 0x80;
724 else if (params->frequency < 2150000)
725 buf[3] |= 0xC0;
726
Patrick Boettcherdea74862006-05-14 05:01:31 -0300727 if (fe->ops.i2c_gate_ctrl)
728 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300729 if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 return -EIO;
731 return 0;
732}
733
734static struct stv0299_config philips_su1278_tt_config = {
735
736 .demod_address = 0x68,
737 .inittab = philips_su1278_tt_inittab,
738 .mclk = 64000000UL,
739 .invert = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 .skip_reinit = 1,
Oliver Endrissda2c7f62008-04-20 22:13:37 -0300741 .lock_output = STV0299_LOCKOUTPUT_1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 .volt13_op0_op1 = STV0299_VOLT13_OP1,
743 .min_delay_ms = 50,
744 .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745};
746
747
748
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300749static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750{
751 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
752 static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
753 static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700754 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 sizeof(td1316_init) };
756
757 // setup PLL configuration
Patrick Boettcherdea74862006-05-14 05:01:31 -0300758 if (fe->ops.i2c_gate_ctrl)
759 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
761 return -EIO;
762 msleep(1);
763
764 // disable the mc44BC374c (do not check for errors)
765 tuner_msg.addr = 0x65;
766 tuner_msg.buf = disable_mc44BC374c;
767 tuner_msg.len = sizeof(disable_mc44BC374c);
Patrick Boettcherdea74862006-05-14 05:01:31 -0300768 if (fe->ops.i2c_gate_ctrl)
769 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
Patrick Boettcherdea74862006-05-14 05:01:31 -0300771 if (fe->ops.i2c_gate_ctrl)
772 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
774 }
775
776 return 0;
777}
778
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300779static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780{
781 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
782 u8 tuner_buf[4];
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -0700783 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 -0700784 int tuner_frequency = 0;
785 u8 band, cp, filter;
786
787 // determine charge pump
788 tuner_frequency = params->frequency + 36130000;
789 if (tuner_frequency < 87000000)
790 return -EINVAL;
791 else if (tuner_frequency < 130000000)
792 cp = 3;
793 else if (tuner_frequency < 160000000)
794 cp = 5;
795 else if (tuner_frequency < 200000000)
796 cp = 6;
797 else if (tuner_frequency < 290000000)
798 cp = 3;
799 else if (tuner_frequency < 420000000)
800 cp = 5;
801 else if (tuner_frequency < 480000000)
802 cp = 6;
803 else if (tuner_frequency < 620000000)
804 cp = 3;
805 else if (tuner_frequency < 830000000)
806 cp = 5;
807 else if (tuner_frequency < 895000000)
808 cp = 7;
809 else
810 return -EINVAL;
811
812 // determine band
813 if (params->frequency < 49000000)
814 return -EINVAL;
815 else if (params->frequency < 159000000)
816 band = 1;
817 else if (params->frequency < 444000000)
818 band = 2;
819 else if (params->frequency < 861000000)
820 band = 4;
821 else
822 return -EINVAL;
823
824 // setup PLL filter and TDA9889
825 switch (params->u.ofdm.bandwidth) {
826 case BANDWIDTH_6_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300827 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 filter = 0;
829 break;
830
831 case BANDWIDTH_7_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300832 tda1004x_writereg(fe, 0x0C, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 filter = 0;
834 break;
835
836 case BANDWIDTH_8_MHZ:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300837 tda1004x_writereg(fe, 0x0C, 0x14);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 filter = 1;
839 break;
840
841 default:
842 return -EINVAL;
843 }
844
845 // calculate divisor
846 // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
847 tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
848
849 // setup tuner buffer
850 tuner_buf[0] = tuner_frequency >> 8;
851 tuner_buf[1] = tuner_frequency & 0xff;
852 tuner_buf[2] = 0xca;
853 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
854
Patrick Boettcherdea74862006-05-14 05:01:31 -0300855 if (fe->ops.i2c_gate_ctrl)
856 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
858 return -EIO;
859
860 msleep(1);
861 return 0;
862}
863
864static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,
865 const struct firmware **fw, char *name)
866{
867 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
868
869 return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);
870}
871
872static struct tda1004x_config philips_tdm1316l_config = {
873
874 .demod_address = 0x8,
875 .invert = 0,
876 .invert_oclk = 0,
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700877 .xtal_freq = TDA10046_XTAL_4M,
878 .agc_config = TDA10046_AGC_DEFAULT,
879 .if_freq = TDA10046_FREQ_3617,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 .request_firmware = philips_tdm1316l_request_firmware,
881};
882
Oliver Endriss6c914492007-02-02 19:12:53 -0300883static struct tda1004x_config philips_tdm1316l_config_invert = {
884
885 .demod_address = 0x8,
886 .invert = 1,
887 .invert_oclk = 0,
888 .xtal_freq = TDA10046_XTAL_4M,
889 .agc_config = TDA10046_AGC_DEFAULT,
890 .if_freq = TDA10046_FREQ_3617,
891 .request_firmware = philips_tdm1316l_request_firmware,
892};
893
Andrew de Quincey0f591d42006-04-18 17:47:11 -0300894static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700895{
896 struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
897 u8 tuner_buf[5];
898 struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
899 .flags = 0,
900 .buf = tuner_buf,
901 .len = sizeof(tuner_buf) };
902 int tuner_frequency = 0;
903 u8 band, cp, filter;
904
905 // determine charge pump
906 tuner_frequency = params->frequency + 36125000;
907 if (tuner_frequency < 87000000)
908 return -EINVAL;
909 else if (tuner_frequency < 130000000) {
910 cp = 3;
911 band = 1;
912 } else if (tuner_frequency < 160000000) {
913 cp = 5;
914 band = 1;
915 } else if (tuner_frequency < 200000000) {
916 cp = 6;
Oliver Endriss910a7b62007-05-03 13:16:12 -0300917 band = 1;
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700918 } else if (tuner_frequency < 290000000) {
919 cp = 3;
920 band = 2;
921 } else if (tuner_frequency < 420000000) {
922 cp = 5;
923 band = 2;
924 } else if (tuner_frequency < 480000000) {
925 cp = 6;
926 band = 2;
927 } else if (tuner_frequency < 620000000) {
928 cp = 3;
929 band = 4;
930 } else if (tuner_frequency < 830000000) {
931 cp = 5;
932 band = 4;
933 } else if (tuner_frequency < 895000000) {
934 cp = 7;
935 band = 4;
936 } else
937 return -EINVAL;
938
939 // assume PLL filter should always be 8MHz for the moment.
940 filter = 1;
941
942 // calculate divisor
943 tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
944
945 // setup tuner buffer
946 tuner_buf[0] = tuner_frequency >> 8;
947 tuner_buf[1] = tuner_frequency & 0xff;
948 tuner_buf[2] = 0xc8;
949 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
950 tuner_buf[4] = 0x80;
951
Patrick Boettcherdea74862006-05-14 05:01:31 -0300952 if (fe->ops.i2c_gate_ctrl)
953 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700954 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
955 return -EIO;
956
957 msleep(50);
958
Patrick Boettcherdea74862006-05-14 05:01:31 -0300959 if (fe->ops.i2c_gate_ctrl)
960 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700961 if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
962 return -EIO;
963
964 msleep(1);
965
966 return 0;
967}
968
969static u8 dvbc_philips_tdm1316l_inittab[] = {
970 0x80, 0x01,
971 0x80, 0x00,
972 0x81, 0x01,
973 0x81, 0x00,
974 0x00, 0x09,
975 0x01, 0x69,
976 0x03, 0x00,
977 0x04, 0x00,
978 0x07, 0x00,
979 0x08, 0x00,
980 0x20, 0x00,
981 0x21, 0x40,
982 0x22, 0x00,
983 0x23, 0x00,
984 0x24, 0x40,
985 0x25, 0x88,
986 0x30, 0xff,
987 0x31, 0x00,
988 0x32, 0xff,
989 0x33, 0x00,
990 0x34, 0x50,
991 0x35, 0x7f,
992 0x36, 0x00,
993 0x37, 0x20,
994 0x38, 0x00,
995 0x40, 0x1c,
996 0x41, 0xff,
997 0x42, 0x29,
998 0x43, 0x20,
999 0x44, 0xff,
1000 0x45, 0x00,
1001 0x46, 0x00,
1002 0x49, 0x04,
1003 0x4a, 0x00,
1004 0x4b, 0x7b,
1005 0x52, 0x30,
1006 0x55, 0xae,
1007 0x56, 0x47,
1008 0x57, 0xe1,
1009 0x58, 0x3a,
1010 0x5a, 0x1e,
1011 0x5b, 0x34,
1012 0x60, 0x00,
1013 0x63, 0x00,
1014 0x64, 0x00,
1015 0x65, 0x00,
1016 0x66, 0x00,
1017 0x67, 0x00,
1018 0x68, 0x00,
1019 0x69, 0x00,
1020 0x6a, 0x02,
1021 0x6b, 0x00,
1022 0x70, 0xff,
1023 0x71, 0x00,
1024 0x72, 0x00,
1025 0x73, 0x00,
1026 0x74, 0x0c,
1027 0x80, 0x00,
1028 0x81, 0x00,
1029 0x82, 0x00,
1030 0x83, 0x00,
1031 0x84, 0x04,
1032 0x85, 0x80,
1033 0x86, 0x24,
1034 0x87, 0x78,
1035 0x88, 0x10,
1036 0x89, 0x00,
1037 0x90, 0x01,
1038 0x91, 0x01,
1039 0xa0, 0x04,
1040 0xa1, 0x00,
1041 0xa2, 0x00,
1042 0xb0, 0x91,
1043 0xb1, 0x0b,
1044 0xc0, 0x53,
1045 0xc1, 0x70,
1046 0xc2, 0x12,
1047 0xd0, 0x00,
1048 0xd1, 0x00,
1049 0xd2, 0x00,
1050 0xd3, 0x00,
1051 0xd4, 0x00,
1052 0xd5, 0x00,
1053 0xde, 0x00,
1054 0xdf, 0x00,
1055 0x61, 0x38,
1056 0x62, 0x0a,
1057 0x53, 0x13,
1058 0x59, 0x08,
1059 0xff, 0xff,
1060};
1061
1062static struct stv0297_config dvbc_philips_tdm1316l_config = {
1063 .demod_address = 0x1c,
1064 .inittab = dvbc_philips_tdm1316l_inittab,
1065 .invert = 0,
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001066 .stop_during_read = 1,
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001067};
1068
Sigmund Augdal11417da2008-06-15 17:25:46 -03001069static struct tda10023_config tda10023_config = {
1070 .demod_address = 0xc,
1071 .invert = 0,
1072 .xtal = 16000000,
1073 .pll_m = 11,
1074 .pll_p = 3,
1075 .pll_n = 1,
1076 .deltaf = 0xa511,
1077};
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001078
Manu Abrahama55bc842008-10-23 18:32:50 -03001079/* TT S2-3200 DVB-S (STB0899) Inittab */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001080static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001082 { STB0899_DEV_ID , 0x81 },
1083 { STB0899_DISCNTRL1 , 0x32 },
1084 { STB0899_DISCNTRL2 , 0x80 },
1085 { STB0899_DISRX_ST0 , 0x04 },
1086 { STB0899_DISRX_ST1 , 0x00 },
1087 { STB0899_DISPARITY , 0x00 },
1088 { STB0899_DISFIFO , 0x00 },
1089 { STB0899_DISSTATUS , 0x20 },
1090 { STB0899_DISF22 , 0x8c },
1091 { STB0899_DISF22RX , 0x9a },
Manu Abrahamef3052b2008-10-23 18:45:17 -03001092 { STB0899_SYSREG , 0x0b },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001093 { STB0899_ACRPRESC , 0x11 },
1094 { STB0899_ACRDIV1 , 0x0a },
1095 { STB0899_ACRDIV2 , 0x05 },
1096 { STB0899_DACR1 , 0x00 },
1097 { STB0899_DACR2 , 0x00 },
1098 { STB0899_OUTCFG , 0x00 },
1099 { STB0899_MODECFG , 0x00 },
1100 { STB0899_IRQSTATUS_3 , 0x30 },
1101 { STB0899_IRQSTATUS_2 , 0x00 },
1102 { STB0899_IRQSTATUS_1 , 0x00 },
1103 { STB0899_IRQSTATUS_0 , 0x00 },
1104 { STB0899_IRQMSK_3 , 0xf3 },
1105 { STB0899_IRQMSK_2 , 0xfc },
1106 { STB0899_IRQMSK_1 , 0xff },
1107 { STB0899_IRQMSK_0 , 0xff },
1108 { STB0899_IRQCFG , 0x00 },
1109 { STB0899_I2CCFG , 0x88 },
Manu Abraham40e8ce32008-02-03 19:37:02 -03001110 { STB0899_I2CRPT , 0x48 }, /* 12k Pullup, Repeater=16, Stop=disabled */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001111 { STB0899_IOPVALUE5 , 0x00 },
1112 { STB0899_IOPVALUE4 , 0x20 },
1113 { STB0899_IOPVALUE3 , 0xc9 },
1114 { STB0899_IOPVALUE2 , 0x90 },
1115 { STB0899_IOPVALUE1 , 0x40 },
1116 { STB0899_IOPVALUE0 , 0x00 },
1117 { STB0899_GPIO00CFG , 0x82 },
1118 { STB0899_GPIO01CFG , 0x82 },
1119 { STB0899_GPIO02CFG , 0x82 },
1120 { STB0899_GPIO03CFG , 0x82 },
1121 { STB0899_GPIO04CFG , 0x82 },
1122 { STB0899_GPIO05CFG , 0x82 },
1123 { STB0899_GPIO06CFG , 0x82 },
1124 { STB0899_GPIO07CFG , 0x82 },
1125 { STB0899_GPIO08CFG , 0x82 },
1126 { STB0899_GPIO09CFG , 0x82 },
1127 { STB0899_GPIO10CFG , 0x82 },
1128 { STB0899_GPIO11CFG , 0x82 },
1129 { STB0899_GPIO12CFG , 0x82 },
1130 { STB0899_GPIO13CFG , 0x82 },
1131 { STB0899_GPIO14CFG , 0x82 },
1132 { STB0899_GPIO15CFG , 0x82 },
1133 { STB0899_GPIO16CFG , 0x82 },
1134 { STB0899_GPIO17CFG , 0x82 },
1135 { STB0899_GPIO18CFG , 0x82 },
1136 { STB0899_GPIO19CFG , 0x82 },
1137 { STB0899_GPIO20CFG , 0x82 },
1138 { STB0899_SDATCFG , 0xb8 },
1139 { STB0899_SCLTCFG , 0xba },
Manu Abrahama55bc842008-10-23 18:32:50 -03001140 { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */
1141 { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */
1142 { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001143 { STB0899_DIRCLKCFG , 0x82 },
1144 { STB0899_CLKOUT27CFG , 0x7e },
1145 { STB0899_STDBYCFG , 0x82 },
1146 { STB0899_CS0CFG , 0x82 },
1147 { STB0899_CS1CFG , 0x82 },
1148 { STB0899_DISEQCOCFG , 0x20 },
1149 { STB0899_GPIO32CFG , 0x82 },
1150 { STB0899_GPIO33CFG , 0x82 },
1151 { STB0899_GPIO34CFG , 0x82 },
1152 { STB0899_GPIO35CFG , 0x82 },
1153 { STB0899_GPIO36CFG , 0x82 },
1154 { STB0899_GPIO37CFG , 0x82 },
1155 { STB0899_GPIO38CFG , 0x82 },
1156 { STB0899_GPIO39CFG , 0x82 },
Manu Abrahamf2e52cd2007-11-19 16:44:47 -03001157 { STB0899_NCOARSE , 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
Manu Abrahama55bc842008-10-23 18:32:50 -03001158 { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001159 { STB0899_FILTCTRL , 0x00 },
1160 { STB0899_SYSCTRL , 0x00 },
1161 { STB0899_STOPCLK1 , 0x20 },
1162 { STB0899_STOPCLK2 , 0x00 },
1163 { STB0899_INTBUFSTATUS , 0x00 },
1164 { STB0899_INTBUFCTRL , 0x0a },
1165 { 0xffff , 0xff },
1166};
1167
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001168static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = {
1169 { STB0899_DEMOD , 0x00 },
1170 { STB0899_RCOMPC , 0xc9 },
1171 { STB0899_AGC1CN , 0x41 },
1172 { STB0899_AGC1REF , 0x10 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001173 { STB0899_RTC , 0x7a },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001174 { STB0899_TMGCFG , 0x4e },
1175 { STB0899_AGC2REF , 0x34 },
1176 { STB0899_TLSR , 0x84 },
1177 { STB0899_CFD , 0xc7 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001178 { STB0899_ACLC , 0x87 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001179 { STB0899_BCLC , 0x94 },
1180 { STB0899_EQON , 0x41 },
1181 { STB0899_LDT , 0xdd },
1182 { STB0899_LDT2 , 0xc9 },
1183 { STB0899_EQUALREF , 0xb4 },
1184 { STB0899_TMGRAMP , 0x10 },
1185 { STB0899_TMGTHD , 0x30 },
1186 { STB0899_IDCCOMP , 0xfb },
1187 { STB0899_QDCCOMP , 0x03 },
1188 { STB0899_POWERI , 0x3b },
1189 { STB0899_POWERQ , 0x3d },
1190 { STB0899_RCOMP , 0x81 },
1191 { STB0899_AGCIQIN , 0x80 },
1192 { STB0899_AGC2I1 , 0x04 },
1193 { STB0899_AGC2I2 , 0xf5 },
1194 { STB0899_TLIR , 0x25 },
1195 { STB0899_RTF , 0x80 },
1196 { STB0899_DSTATUS , 0x00 },
1197 { STB0899_LDI , 0xca },
1198 { STB0899_CFRM , 0xf1 },
1199 { STB0899_CFRL , 0xf3 },
1200 { STB0899_NIRM , 0x2a },
1201 { STB0899_NIRL , 0x05 },
1202 { STB0899_ISYMB , 0x17 },
1203 { STB0899_QSYMB , 0xfa },
1204 { STB0899_SFRH , 0x2f },
1205 { STB0899_SFRM , 0x68 },
1206 { STB0899_SFRL , 0x40 },
1207 { STB0899_SFRUPH , 0x2f },
1208 { STB0899_SFRUPM , 0x68 },
1209 { STB0899_SFRUPL , 0x40 },
1210 { STB0899_EQUAI1 , 0xfd },
1211 { STB0899_EQUAQ1 , 0x04 },
1212 { STB0899_EQUAI2 , 0x0f },
1213 { STB0899_EQUAQ2 , 0xff },
1214 { STB0899_EQUAI3 , 0xdf },
1215 { STB0899_EQUAQ3 , 0xfa },
1216 { STB0899_EQUAI4 , 0x37 },
1217 { STB0899_EQUAQ4 , 0x0d },
1218 { STB0899_EQUAI5 , 0xbd },
1219 { STB0899_EQUAQ5 , 0xf7 },
1220 { STB0899_DSTATUS2 , 0x00 },
1221 { STB0899_VSTATUS , 0x00 },
1222 { STB0899_VERROR , 0xff },
1223 { STB0899_IQSWAP , 0x2a },
1224 { STB0899_ECNT1M , 0x00 },
1225 { STB0899_ECNT1L , 0x00 },
1226 { STB0899_ECNT2M , 0x00 },
1227 { STB0899_ECNT2L , 0x00 },
1228 { STB0899_ECNT3M , 0x00 },
1229 { STB0899_ECNT3L , 0x00 },
1230 { STB0899_FECAUTO1 , 0x06 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001231 { STB0899_FECM , 0x01 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001232 { STB0899_VTH12 , 0xf0 },
1233 { STB0899_VTH23 , 0xa0 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001234 { STB0899_VTH34 , 0x78 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001235 { STB0899_VTH56 , 0x4e },
1236 { STB0899_VTH67 , 0x48 },
1237 { STB0899_VTH78 , 0x38 },
1238 { STB0899_PRVIT , 0xff },
1239 { STB0899_VITSYNC , 0x19 },
Manu Abrahama55bc842008-10-23 18:32:50 -03001240 { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001241 { STB0899_TSULC , 0x42 },
1242 { STB0899_RSLLC , 0x40 },
Mauro Carvalho Chehabf34253d2008-11-10 18:56:20 -03001243 { STB0899_TSLPL , 0x12 },
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001244 { STB0899_TSCFGH , 0x0c },
1245 { STB0899_TSCFGM , 0x00 },
1246 { STB0899_TSCFGL , 0x0c },
Manu Abraham6ea223c2007-09-24 19:58:24 -03001247 { STB0899_TSOUT , 0x0d }, /* 0x0d for CAM */
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001248 { STB0899_RSSYNCDEL , 0x00 },
1249 { STB0899_TSINHDELH , 0x02 },
1250 { STB0899_TSINHDELM , 0x00 },
1251 { STB0899_TSINHDELL , 0x00 },
1252 { STB0899_TSLLSTKM , 0x00 },
1253 { STB0899_TSLLSTKL , 0x00 },
1254 { STB0899_TSULSTKM , 0x00 },
1255 { STB0899_TSULSTKL , 0xab },
1256 { STB0899_PCKLENUL , 0x00 },
1257 { STB0899_PCKLENLL , 0xcc },
1258 { STB0899_RSPCKLEN , 0xcc },
1259 { STB0899_TSSTATUS , 0x80 },
1260 { STB0899_ERRCTRL1 , 0xb6 },
1261 { STB0899_ERRCTRL2 , 0x96 },
1262 { STB0899_ERRCTRL3 , 0x89 },
1263 { STB0899_DMONMSK1 , 0x27 },
1264 { STB0899_DMONMSK0 , 0x03 },
1265 { STB0899_DEMAPVIT , 0x5c },
1266 { STB0899_PLPARM , 0x1f },
1267 { STB0899_PDELCTRL , 0x48 },
1268 { STB0899_PDELCTRL2 , 0x00 },
1269 { STB0899_BBHCTRL1 , 0x00 },
1270 { STB0899_BBHCTRL2 , 0x00 },
1271 { STB0899_HYSTTHRESH , 0x77 },
1272 { STB0899_MATCSTM , 0x00 },
1273 { STB0899_MATCSTL , 0x00 },
1274 { STB0899_UPLCSTM , 0x00 },
1275 { STB0899_UPLCSTL , 0x00 },
1276 { STB0899_DFLCSTM , 0x00 },
1277 { STB0899_DFLCSTL , 0x00 },
1278 { STB0899_SYNCCST , 0x00 },
1279 { STB0899_SYNCDCSTM , 0x00 },
1280 { STB0899_SYNCDCSTL , 0x00 },
1281 { STB0899_ISI_ENTRY , 0x00 },
1282 { STB0899_ISI_BIT_EN , 0x00 },
1283 { STB0899_MATSTRM , 0x00 },
1284 { STB0899_MATSTRL , 0x00 },
1285 { STB0899_UPLSTRM , 0x00 },
1286 { STB0899_UPLSTRL , 0x00 },
1287 { STB0899_DFLSTRM , 0x00 },
1288 { STB0899_DFLSTRL , 0x00 },
1289 { STB0899_SYNCSTR , 0x00 },
1290 { STB0899_SYNCDSTRM , 0x00 },
1291 { STB0899_SYNCDSTRL , 0x00 },
1292 { STB0899_CFGPDELSTATUS1 , 0x10 },
1293 { STB0899_CFGPDELSTATUS2 , 0x00 },
1294 { STB0899_BBFERRORM , 0x00 },
1295 { STB0899_BBFERRORL , 0x00 },
1296 { STB0899_UPKTERRORM , 0x00 },
1297 { STB0899_UPKTERRORL , 0x00 },
1298 { 0xffff , 0xff },
1299};
1300
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001301static struct stb0899_config tt3200_config = {
1302 .init_dev = tt3200_stb0899_s1_init_1,
Manu Abraham8be969b2008-01-25 18:20:48 -03001303 .init_s2_demod = stb0899_s2_init_2,
Manu Abrahama55bc842008-10-23 18:32:50 -03001304 .init_s1_demod = tt3200_stb0899_s1_init_3,
Manu Abraham8be969b2008-01-25 18:20:48 -03001305 .init_s2_fec = stb0899_s2_init_4,
1306 .init_tst = stb0899_s1_init_5,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001307
Manu Abraham043a68b2008-01-18 14:15:17 -03001308 .postproc = NULL,
1309
Manu Abrahama55bc842008-10-23 18:32:50 -03001310 .demod_address = 0x68,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001311
1312 .xtal_freq = 27000000,
Manu Abrahame99d00c2007-09-25 17:48:59 -03001313 .inversion = IQ_SWAP_ON, /* 1 */
Manu Abrahama55bc842008-10-23 18:32:50 -03001314
Manu Abrahamb91a7cb2008-03-04 19:19:58 -03001315 .lo_clk = 76500000,
1316 .hi_clk = 99000000,
1317
Manu Abraham8be969b2008-01-25 18:20:48 -03001318 .esno_ave = STB0899_DVBS2_ESNO_AVE,
1319 .esno_quant = STB0899_DVBS2_ESNO_QUANT,
1320 .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
1321 .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
1322 .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
1323 .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
1324 .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
1325 .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
1326 .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
Manu Abrahama55bc842008-10-23 18:32:50 -03001327
Manu Abraham8be969b2008-01-25 18:20:48 -03001328 .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
1329 .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
1330 .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
1331 .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
Manu Abrahama55bc842008-10-23 18:32:50 -03001332
1333 .tuner_get_frequency = stb6100_get_frequency,
1334 .tuner_set_frequency = stb6100_set_frequency,
1335 .tuner_set_bandwidth = stb6100_set_bandwidth,
1336 .tuner_get_bandwidth = stb6100_get_bandwidth,
Manu Abraham043a68b2008-01-18 14:15:17 -03001337 .tuner_set_rfsiggain = NULL
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001338};
1339
Mauro Carvalho Chehabffbc5f82009-01-05 01:34:20 -03001340static struct stb6100_config tt3200_stb6100_config = {
Manu Abrahamc14eaed2007-10-04 16:52:51 -03001341 .tuner_address = 0x60,
1342 .refclock = 27000000,
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001343};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344
1345static void frontend_init(struct budget_ci *budget_ci)
1346{
1347 switch (budget_ci->budget.dev->pci->subsystem_device) {
1348 case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
1349 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001350 dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001352 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001353 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 break;
1355 }
1356 break;
1357
1358 case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
1359 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001360 dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001362 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 break;
1364 }
1365 break;
1366
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001367 case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
1368 budget_ci->tuner_pll_address = 0x61;
1369 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001370 dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001371 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001372 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001373 break;
1374 }
1375 break;
1376
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001378 budget_ci->tuner_pll_address = 0x63;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 budget_ci->budget.dvb_frontend =
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001380 dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001382 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1383 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 break;
1385 }
1386 break;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001387
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001388 case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001389 budget_ci->tuner_pll_address = 0x60;
1390 budget_ci->budget.dvb_frontend =
Oliver Endriss6c914492007-02-02 19:12:53 -03001391 dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001392 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001393 budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1394 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001395 break;
1396 }
1397 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001398
1399 case 0x1017: // TT S-1500 PCI
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001400 budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001401 if (budget_ci->budget.dvb_frontend) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001402 budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
Andrew de Quincey0f591d42006-04-18 17:47:11 -03001403 budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
1404
Patrick Boettcherdea74862006-05-14 05:01:31 -03001405 budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001406 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 -03001407 printk("%s: No LNBP21 found!\n", __func__);
Andrew de Quincey2b100e72006-08-08 09:10:11 -03001408 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001409 budget_ci->budget.dvb_frontend = NULL;
1410 }
1411 }
Sigmund Augdal11417da2008-06-15 17:25:46 -03001412 break;
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001413
Sigmund Augdal11417da2008-06-15 17:25:46 -03001414 case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */
1415 budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48);
1416 if (budget_ci->budget.dvb_frontend) {
1417 if (dvb_attach(tda827x_attach, budget_ci->budget.dvb_frontend, 0x61, &budget_ci->budget.i2c_adap, NULL) == NULL) {
1418 printk(KERN_ERR "%s: No tda827x found!\n", __func__);
1419 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1420 budget_ci->budget.dvb_frontend = NULL;
1421 }
1422 }
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001423 break;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001424
1425 case 0x1019: // TT S2-3200 PCI
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001426 /*
1427 * NOTE! on some STB0899 versions, the internal PLL takes a longer time
1428 * to settle, aka LOCK. On the older revisions of the chip, we don't see
1429 * this, as a result on the newer chips the entire clock tree, will not
1430 * be stable after a freshly POWER 'ed up situation.
1431 * In this case, we should RESET the STB0899 (Active LOW) and wait for
1432 * PLL stabilization.
1433 *
1434 * On the TT S2 3200 and clones, the STB0899 demodulator's RESETB is
1435 * connected to the SAA7146 GPIO, GPIO2, Pin 142
1436 */
1437 /* Reset Demodulator */
Manu Abraham0867f572007-10-15 13:07:16 -03001438 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001439 /* Wait for everything to die */
1440 msleep(50);
1441 /* Pull it up out of Reset state */
Manu Abraham0867f572007-10-15 13:07:16 -03001442 saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI);
Manu Abraham6efb0ff2007-10-15 12:08:20 -03001443 /* Wait for PLL to stabilize */
1444 msleep(250);
1445 /*
1446 * PLL state should be stable now. Ideally, we should check
1447 * for PLL LOCK status. But well, never mind!
1448 */
Manu Abrahamae9902d2007-10-08 18:51:54 -03001449 budget_ci->budget.dvb_frontend = dvb_attach(stb0899_attach, &tt3200_config, &budget_ci->budget.i2c_adap);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001450 if (budget_ci->budget.dvb_frontend) {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001451 if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {
1452 if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
Harvey Harrison9b4778f2009-01-07 14:42:41 -08001453 printk("%s: No LNBP21 found!\n", __func__);
Manu Abrahamae9902d2007-10-08 18:51:54 -03001454 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001455 budget_ci->budget.dvb_frontend = NULL;
1456 }
1457 } else {
Manu Abrahamae9902d2007-10-08 18:51:54 -03001458 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1459 budget_ci->budget.dvb_frontend = NULL;
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001460 }
1461 }
1462 break;
1463
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 }
1465
1466 if (budget_ci->budget.dvb_frontend == NULL) {
Bjorn Helgaas29e66a62008-09-04 17:24:51 -03001467 printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 budget_ci->budget.dev->pci->vendor,
1469 budget_ci->budget.dev->pci->device,
1470 budget_ci->budget.dev->pci->subsystem_vendor,
1471 budget_ci->budget.dev->pci->subsystem_device);
1472 } else {
1473 if (dvb_register_frontend
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001474 (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 printk("budget-ci: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001476 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 budget_ci->budget.dvb_frontend = NULL;
1478 }
1479 }
1480}
1481
1482static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
1483{
1484 struct budget_ci *budget_ci;
1485 int err;
1486
David Hardemanee579bc2006-12-02 21:16:05 -02001487 budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
David Hardeman8cc532e2006-12-02 21:16:05 -02001488 if (!budget_ci) {
1489 err = -ENOMEM;
1490 goto out1;
1491 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492
1493 dprintk(2, "budget_ci: %p\n", budget_ci);
1494
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 dev->ext_priv = budget_ci;
1496
Janne Grunau26dc4d02008-09-21 20:50:11 -03001497 err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE,
1498 adapter_nr);
David Hardeman8cc532e2006-12-02 21:16:05 -02001499 if (err)
1500 goto out2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501
David Hardeman8cc532e2006-12-02 21:16:05 -02001502 err = msp430_ir_init(budget_ci);
1503 if (err)
1504 goto out3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505
1506 ciintf_init(budget_ci);
1507
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001508 budget_ci->budget.dvb_adapter.priv = budget_ci;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 frontend_init(budget_ci);
1510
Oliver Endriss32e4c3a2006-07-18 22:55:23 -03001511 ttpci_budget_init_hooks(&budget_ci->budget);
1512
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 return 0;
David Hardeman8cc532e2006-12-02 21:16:05 -02001514
1515out3:
1516 ttpci_budget_deinit(&budget_ci->budget);
1517out2:
1518 kfree(budget_ci);
1519out1:
1520 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521}
1522
1523static int budget_ci_detach(struct saa7146_dev *dev)
1524{
1525 struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
1526 struct saa7146_dev *saa = budget_ci->budget.dev;
1527 int err;
1528
1529 if (budget_ci->budget.ci_present)
1530 ciintf_deinit(budget_ci);
David Hardeman8cc532e2006-12-02 21:16:05 -02001531 msp430_ir_deinit(budget_ci);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001532 if (budget_ci->budget.dvb_frontend) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001534 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001535 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 err = ttpci_budget_deinit(&budget_ci->budget);
1537
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 // disable frontend and CI interface
1539 saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
1540
1541 kfree(budget_ci);
1542
1543 return err;
1544}
1545
1546static struct saa7146_extension budget_extension;
1547
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001548MAKE_BUDGET_INFO(ttbs2, "TT-Budget/S-1500 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
1550MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001551MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001552MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
Sigmund Augdal11417da2008-06-15 17:25:46 -03001553MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001554MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
1556static struct pci_device_id pci_tbl[] = {
1557 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
1558 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
Andrew de Quinceydc27a162005-09-09 13:03:07 -07001559 MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
Andrew de Quinceydd2bbb12005-07-07 17:57:54 -07001561 MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
Perceval Anichini8cc2e372006-02-28 09:52:44 -03001562 MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
Sigmund Augdal11417da2008-06-15 17:25:46 -03001563 MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
Marko Schluessler9e0dc662008-10-23 18:16:40 -03001564 MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 {
1566 .vendor = 0,
1567 }
1568};
1569
1570MODULE_DEVICE_TABLE(pci, pci_tbl);
1571
1572static struct saa7146_extension budget_extension = {
Dave Jones0e367a12006-08-07 13:18:56 -03001573 .name = "budget_ci dvb",
Oliver Endriss00c4cc62006-11-01 13:09:51 -03001574 .flags = SAA7146_USE_I2C_IRQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575
1576 .module = THIS_MODULE,
1577 .pci_tbl = &pci_tbl[0],
1578 .attach = budget_ci_attach,
1579 .detach = budget_ci_detach,
1580
1581 .irq_mask = MASK_03 | MASK_06 | MASK_10,
1582 .irq_func = budget_ci_irq,
1583};
1584
1585static int __init budget_ci_init(void)
1586{
1587 return saa7146_register_extension(&budget_extension);
1588}
1589
1590static void __exit budget_ci_exit(void)
1591{
1592 saa7146_unregister_extension(&budget_extension);
1593}
1594
1595module_init(budget_ci_init);
1596module_exit(budget_ci_exit);
1597
1598MODULE_LICENSE("GPL");
1599MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
1600MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1601 "budget PCI DVB cards w/ CI-module produced by "
1602 "Siemens, Technotrend, Hauppauge");