blob: 6163cb03b8f418e9859263be98d668881ad97482 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * budget-av.c: driver for the SAA7146 based Budget DVB cards
3 * with analog video in
4 *
5 * Compiled from various sources by Michael Hunold <michael@mihu.de>
6 *
7 * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
8 * Andrew de Quincey <adq_dvb@lidskialf.net>
9 *
10 * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
11 *
12 * Copyright (C) 1999-2002 Ralph Metzler
13 * & Marcus Metzler for convergence integrated media GmbH
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
31 *
32 *
33 * the project's page is at http://www.linuxtv.org/dvb/
34 */
35
36#include "budget.h"
37#include "stv0299.h"
38#include "tda10021.h"
39#include "tda1004x.h"
Regis Prevotf8bf1342006-01-11 23:31:53 -020040#include "dvb-pll.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <media/saa7146_vv.h>
42#include <linux/module.h>
43#include <linux/errno.h>
44#include <linux/slab.h>
45#include <linux/interrupt.h>
46#include <linux/input.h>
47#include <linux/spinlock.h>
48
49#include "dvb_ca_en50221.h"
50
51#define DEBICICAM 0x02420000
52
Andrew de Quincey5c1208b2006-05-22 10:32:02 -030053#define SLOTSTATUS_NONE 1
54#define SLOTSTATUS_PRESENT 2
55#define SLOTSTATUS_RESET 4
56#define SLOTSTATUS_READY 8
57#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
58
Linus Torvalds1da177e2005-04-16 15:20:36 -070059struct budget_av {
60 struct budget budget;
61 struct video_device *vd;
62 int cur_input;
63 int has_saa7113;
64 struct tasklet_struct ciintf_irq_tasklet;
65 int slot_status;
66 struct dvb_ca_en50221 ca;
Andrew de Quincey5c1208b2006-05-22 10:32:02 -030067 u8 reinitialise_demod:1;
68 u8 tda10021_poclkp:1;
69 u8 tda10021_ts_enabled;
70 int (*tda10021_set_frontend)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
Linus Torvalds1da177e2005-04-16 15:20:36 -070071};
72
Andrew de Quincey5c1208b2006-05-22 10:32:02 -030073static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot);
74
75
Andrew de Quincey86f40cc2006-03-30 15:53:35 -030076/* GPIO Connections:
77 * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*!
78 * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory
79 * 2 - CI Card Enable (Active Low)
80 * 3 - CI Card Detect
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -070081 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070082
83/****************************************************************************
84 * INITIALIZATION
85 ****************************************************************************/
86
87static u8 i2c_readreg(struct i2c_adapter *i2c, u8 id, u8 reg)
88{
89 u8 mm1[] = { 0x00 };
90 u8 mm2[] = { 0x00 };
91 struct i2c_msg msgs[2];
92
93 msgs[0].flags = 0;
94 msgs[1].flags = I2C_M_RD;
95 msgs[0].addr = msgs[1].addr = id / 2;
96 mm1[0] = reg;
97 msgs[0].len = 1;
98 msgs[1].len = 1;
99 msgs[0].buf = mm1;
100 msgs[1].buf = mm2;
101
102 i2c_transfer(i2c, msgs, 2);
103
104 return mm2[0];
105}
106
107static int i2c_readregs(struct i2c_adapter *i2c, u8 id, u8 reg, u8 * buf, u8 len)
108{
109 u8 mm1[] = { reg };
110 struct i2c_msg msgs[2] = {
111 {.addr = id / 2,.flags = 0,.buf = mm1,.len = 1},
112 {.addr = id / 2,.flags = I2C_M_RD,.buf = buf,.len = len}
113 };
114
115 if (i2c_transfer(i2c, msgs, 2) != 2)
116 return -EIO;
117
118 return 0;
119}
120
121static int i2c_writereg(struct i2c_adapter *i2c, u8 id, u8 reg, u8 val)
122{
123 u8 msg[2] = { reg, val };
124 struct i2c_msg msgs;
125
126 msgs.flags = 0;
127 msgs.addr = id / 2;
128 msgs.len = 2;
129 msgs.buf = msg;
130 return i2c_transfer(i2c, &msgs, 1);
131}
132
133static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
134{
135 struct budget_av *budget_av = (struct budget_av *) ca->data;
136 int result;
137
138 if (slot != 0)
139 return -EINVAL;
140
141 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
142 udelay(1);
143
Andrew de Quincey2d0235d2006-01-09 15:25:05 -0200144 result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300145 if (result == -ETIMEDOUT) {
146 ciintf_slot_shutdown(ca, slot);
147 printk(KERN_INFO "budget-av: cam ejected 1\n");
148 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 return result;
150}
151
152static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
153{
154 struct budget_av *budget_av = (struct budget_av *) ca->data;
155 int result;
156
157 if (slot != 0)
158 return -EINVAL;
159
160 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
161 udelay(1);
162
Andrew de Quincey2d0235d2006-01-09 15:25:05 -0200163 result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300164 if (result == -ETIMEDOUT) {
165 ciintf_slot_shutdown(ca, slot);
166 printk(KERN_INFO "budget-av: cam ejected 2\n");
167 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 return result;
169}
170
171static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
172{
173 struct budget_av *budget_av = (struct budget_av *) ca->data;
174 int result;
175
176 if (slot != 0)
177 return -EINVAL;
178
179 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
180 udelay(1);
181
182 result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300183 if ((result == -ETIMEDOUT) || ((result == 0xff) && ((address & 3) < 2))) {
184 ciintf_slot_shutdown(ca, slot);
185 printk(KERN_INFO "budget-av: cam ejected 3\n");
186 return -ETIMEDOUT;
187 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 return result;
189}
190
191static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
192{
193 struct budget_av *budget_av = (struct budget_av *) ca->data;
194 int result;
195
196 if (slot != 0)
197 return -EINVAL;
198
199 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
200 udelay(1);
201
202 result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300203 if (result == -ETIMEDOUT) {
204 ciintf_slot_shutdown(ca, slot);
205 printk(KERN_INFO "budget-av: cam ejected 5\n");
206 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 return result;
208}
209
210static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
211{
212 struct budget_av *budget_av = (struct budget_av *) ca->data;
213 struct saa7146_dev *saa = budget_av->budget.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214
215 if (slot != 0)
216 return -EINVAL;
217
218 dprintk(1, "ciintf_slot_reset\n");
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300219 budget_av->slot_status = SLOTSTATUS_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -0700221 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -0700223 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
224 msleep(2);
225 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); /* Vcc on */
226 msleep(20); /* 20 ms Vcc settling time */
227
228 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300229 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
230 msleep(20);
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -0700231
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300232 /* reinitialise the frontend if necessary */
233 if (budget_av->reinitialise_demod)
234 dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300236 /* set tda10021 back to original clock configuration on reset */
237 if (budget_av->tda10021_poclkp) {
238 tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
239 budget_av->tda10021_ts_enabled = 0;
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -0700240 }
241
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 return 0;
243}
244
245static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
246{
247 struct budget_av *budget_av = (struct budget_av *) ca->data;
248 struct saa7146_dev *saa = budget_av->budget.dev;
249
250 if (slot != 0)
251 return -EINVAL;
252
253 dprintk(1, "ciintf_slot_shutdown\n");
254
255 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300256 budget_av->slot_status = SLOTSTATUS_NONE;
257
258 /* set tda10021 back to original clock configuration when cam removed */
259 if (budget_av->tda10021_poclkp) {
260 tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
261 budget_av->tda10021_ts_enabled = 0;
262 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 return 0;
264}
265
266static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
267{
268 struct budget_av *budget_av = (struct budget_av *) ca->data;
269 struct saa7146_dev *saa = budget_av->budget.dev;
270
271 if (slot != 0)
272 return -EINVAL;
273
274 dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status);
275
276 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300277
278 /* tda10021 seems to need a different TS clock config when data is routed to the CAM */
279 if (budget_av->tda10021_poclkp) {
280 tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
281 budget_av->tda10021_ts_enabled = 1;
282 }
283
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 return 0;
285}
286
287static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
288{
289 struct budget_av *budget_av = (struct budget_av *) ca->data;
290 struct saa7146_dev *saa = budget_av->budget.dev;
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300291 int result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292
293 if (slot != 0)
294 return -EINVAL;
295
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300296 /* test the card detect line - needs to be done carefully
297 * since it never goes high for some CAMs on this interface (e.g. topuptv) */
298 if (budget_av->slot_status == SLOTSTATUS_NONE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
300 udelay(1);
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300301 if (saa7146_read(saa, PSR) & MASK_06) {
302 if (budget_av->slot_status == SLOTSTATUS_NONE) {
303 budget_av->slot_status = SLOTSTATUS_PRESENT;
304 printk(KERN_INFO "budget-av: cam inserted A\n");
Andrew de Quincey2d0235d2006-01-09 15:25:05 -0200305 }
306 }
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300307 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
308 }
Andrew de Quincey2d0235d2006-01-09 15:25:05 -0200309
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300310 /* We also try and read from IO memory to work round the above detection bug. If
311 * there is no CAM, we will get a timeout. Only done if there is no cam
312 * present, since this test actually breaks some cams :(
313 *
314 * if the CI interface is not open, we also do the above test since we
315 * don't care if the cam has problems - we'll be resetting it on open() anyway */
316 if ((budget_av->slot_status == SLOTSTATUS_NONE) || (!open)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300318 result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1);
319 if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) {
320 budget_av->slot_status = SLOTSTATUS_PRESENT;
321 printk(KERN_INFO "budget-av: cam inserted B\n");
322 } else if (result < 0) {
323 if (budget_av->slot_status != SLOTSTATUS_NONE) {
324 ciintf_slot_shutdown(ca, slot);
325 printk(KERN_INFO "budget-av: cam ejected 5\n");
326 return 0;
327 }
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -0700328 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 }
330
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300331 /* read from attribute memory in reset/ready state to know when the CAM is ready */
332 if (budget_av->slot_status == SLOTSTATUS_RESET) {
333 result = ciintf_read_attribute_mem(ca, slot, 0);
334 if (result == 0x1d) {
335 budget_av->slot_status = SLOTSTATUS_READY;
336 }
337 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300339 /* work out correct return code */
340 if (budget_av->slot_status != SLOTSTATUS_NONE) {
341 if (budget_av->slot_status & SLOTSTATUS_READY) {
342 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
343 }
344 return DVB_CA_EN50221_POLL_CAM_PRESENT;
345 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 return 0;
347}
348
349static int ciintf_init(struct budget_av *budget_av)
350{
351 struct saa7146_dev *saa = budget_av->budget.dev;
352 int result;
353
354 memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221));
355
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -0700356 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
357 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO);
359 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
360
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 /* Enable DEBI pins */
362 saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
363
364 /* register CI interface */
365 budget_av->ca.owner = THIS_MODULE;
366 budget_av->ca.read_attribute_mem = ciintf_read_attribute_mem;
367 budget_av->ca.write_attribute_mem = ciintf_write_attribute_mem;
368 budget_av->ca.read_cam_control = ciintf_read_cam_control;
369 budget_av->ca.write_cam_control = ciintf_write_cam_control;
370 budget_av->ca.slot_reset = ciintf_slot_reset;
371 budget_av->ca.slot_shutdown = ciintf_slot_shutdown;
372 budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
373 budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
374 budget_av->ca.data = budget_av;
Andrew de Quincey5c1208b2006-05-22 10:32:02 -0300375 budget_av->budget.ci_present = 1;
376 budget_av->slot_status = SLOTSTATUS_NONE;
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -0700377
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -0700378 if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 &budget_av->ca, 0, 1)) != 0) {
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -0700380 printk(KERN_ERR "budget-av: ci initialisation failed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 goto error;
382 }
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -0700383
384 printk(KERN_INFO "budget-av: ci interface initialised.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 return 0;
386
387error:
388 saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
389 return result;
390}
391
392static void ciintf_deinit(struct budget_av *budget_av)
393{
394 struct saa7146_dev *saa = budget_av->budget.dev;
395
396 saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
397 saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
398 saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
399 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
400
401 /* release the CA device */
402 dvb_ca_en50221_release(&budget_av->ca);
403
404 /* disable DEBI pins */
405 saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
406}
407
408
409static const u8 saa7113_tab[] = {
410 0x01, 0x08,
411 0x02, 0xc0,
412 0x03, 0x33,
413 0x04, 0x00,
414 0x05, 0x00,
415 0x06, 0xeb,
416 0x07, 0xe0,
417 0x08, 0x28,
418 0x09, 0x00,
419 0x0a, 0x80,
420 0x0b, 0x47,
421 0x0c, 0x40,
422 0x0d, 0x00,
423 0x0e, 0x01,
424 0x0f, 0x44,
425
426 0x10, 0x08,
427 0x11, 0x0c,
428 0x12, 0x7b,
429 0x13, 0x00,
430 0x15, 0x00, 0x16, 0x00, 0x17, 0x00,
431
432 0x57, 0xff,
433 0x40, 0x82, 0x58, 0x00, 0x59, 0x54, 0x5a, 0x07,
434 0x5b, 0x83, 0x5e, 0x00,
435 0xff
436};
437
438static int saa7113_init(struct budget_av *budget_av)
439{
440 struct budget *budget = &budget_av->budget;
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -0700441 struct saa7146_dev *saa = budget->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 const u8 *data = saa7113_tab;
443
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -0700444 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
445 msleep(200);
446
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 if (i2c_writereg(&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) {
448 dprintk(1, "saa7113 not found on KNC card\n");
449 return -ENODEV;
450 }
451
452 dprintk(1, "saa7113 detected and initializing\n");
453
454 while (*data != 0xff) {
455 i2c_writereg(&budget->i2c_adap, 0x4a, *data, *(data + 1));
456 data += 2;
457 }
458
459 dprintk(1, "saa7113 status=%02x\n", i2c_readreg(&budget->i2c_adap, 0x4a, 0x1f));
460
461 return 0;
462}
463
464static int saa7113_setinput(struct budget_av *budget_av, int input)
465{
466 struct budget *budget = &budget_av->budget;
467
468 if (1 != budget_av->has_saa7113)
469 return -ENODEV;
470
471 if (input == 1) {
472 i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc7);
473 i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x80);
474 } else if (input == 0) {
475 i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc0);
476 i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x00);
477 } else
478 return -EINVAL;
479
480 budget_av->cur_input = input;
481 return 0;
482}
483
484
485static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
486{
487 u8 aclk = 0;
488 u8 bclk = 0;
489 u8 m1;
490
491 aclk = 0xb5;
492 if (srate < 2000000)
493 bclk = 0x86;
494 else if (srate < 5000000)
495 bclk = 0x89;
496 else if (srate < 15000000)
497 bclk = 0x8f;
498 else if (srate < 45000000)
499 bclk = 0x95;
500
501 m1 = 0x14;
502 if (srate < 4000000)
503 m1 = 0x10;
504
505 stv0299_writereg(fe, 0x13, aclk);
506 stv0299_writereg(fe, 0x14, bclk);
507 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
508 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
509 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
510 stv0299_writereg(fe, 0x0f, 0x80 | m1);
511
512 return 0;
513}
514
Andrew de Quinceye87d41c2006-04-18 17:47:11 -0300515static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe,
516 struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 u32 div;
519 u8 buf[4];
Andrew de Quinceye87d41c2006-04-18 17:47:11 -0300520 struct budget *budget = (struct budget *) fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
522
523 if ((params->frequency < 950000) || (params->frequency > 2150000))
524 return -EINVAL;
525
526 div = (params->frequency + (125 - 1)) / 125; // round correctly
527 buf[0] = (div >> 8) & 0x7f;
528 buf[1] = div & 0xff;
529 buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
530 buf[3] = 0x20;
531
532 if (params->u.qpsk.symbol_rate < 4000000)
533 buf[3] |= 1;
534
535 if (params->frequency < 1250000)
536 buf[3] |= 0;
537 else if (params->frequency < 1550000)
538 buf[3] |= 0x40;
539 else if (params->frequency < 2050000)
540 buf[3] |= 0x80;
541 else if (params->frequency < 2150000)
542 buf[3] |= 0xC0;
543
Patrick Boettcherdea74862006-05-14 05:01:31 -0300544 if (fe->ops.i2c_gate_ctrl)
545 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceye87d41c2006-04-18 17:47:11 -0300546 if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 return -EIO;
548 return 0;
549}
550
Andrew de Quinceyeffa7912006-01-09 15:25:09 -0200551#define MIN2(a,b) ((a) < (b) ? (a) : (b))
552#define MIN3(a,b,c) MIN2(MIN2(a,b),c)
553
Andrew de Quinceye87d41c2006-04-18 17:47:11 -0300554static int philips_su1278sh2_tua6100_tuner_set_params(struct dvb_frontend *fe,
555 struct dvb_frontend_parameters *params)
Andrew de Quinceyeffa7912006-01-09 15:25:09 -0200556{
557 u8 reg0 [2] = { 0x00, 0x00 };
558 u8 reg1 [4] = { 0x01, 0x00, 0x00, 0x00 };
559 u8 reg2 [3] = { 0x02, 0x00, 0x00 };
560 int _fband;
561 int first_ZF;
562 int R, A, N, P, M;
563 struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = NULL,.len = 0 };
564 int freq = params->frequency;
Andrew de Quinceye87d41c2006-04-18 17:47:11 -0300565 struct budget *budget = (struct budget *) fe->dvb->priv;
Andrew de Quinceyeffa7912006-01-09 15:25:09 -0200566
567 first_ZF = (freq) / 1000;
568
569 if (abs(MIN2(abs(first_ZF-1190),abs(first_ZF-1790))) <
570 abs(MIN3(abs(first_ZF-1202),abs(first_ZF-1542),abs(first_ZF-1890))))
571 _fband = 2;
572 else
573 _fband = 3;
574
575 if (_fband == 2) {
576 if (((first_ZF >= 950) && (first_ZF < 1350)) ||
577 ((first_ZF >= 1430) && (first_ZF < 1950)))
578 reg0[1] = 0x07;
579 else if (((first_ZF >= 1350) && (first_ZF < 1430)) ||
580 ((first_ZF >= 1950) && (first_ZF < 2150)))
581 reg0[1] = 0x0B;
582 }
583
584 if(_fband == 3) {
585 if (((first_ZF >= 950) && (first_ZF < 1350)) ||
586 ((first_ZF >= 1455) && (first_ZF < 1950)))
587 reg0[1] = 0x07;
588 else if (((first_ZF >= 1350) && (first_ZF < 1420)) ||
589 ((first_ZF >= 1950) && (first_ZF < 2150)))
590 reg0[1] = 0x0B;
591 else if ((first_ZF >= 1420) && (first_ZF < 1455))
592 reg0[1] = 0x0F;
593 }
594
595 if (first_ZF > 1525)
596 reg1[1] |= 0x80;
597 else
598 reg1[1] &= 0x7F;
599
600 if (_fband == 2) {
601 if (first_ZF > 1430) { /* 1430MHZ */
602 reg1[1] &= 0xCF; /* N2 */
603 reg2[1] &= 0xCF; /* R2 */
604 reg2[1] |= 0x10;
605 } else {
606 reg1[1] &= 0xCF; /* N2 */
607 reg1[1] |= 0x20;
608 reg2[1] &= 0xCF; /* R2 */
609 reg2[1] |= 0x10;
610 }
611 }
612
613 if (_fband == 3) {
614 if ((first_ZF >= 1455) &&
615 (first_ZF < 1630)) {
616 reg1[1] &= 0xCF; /* N2 */
617 reg1[1] |= 0x20;
618 reg2[1] &= 0xCF; /* R2 */
619 } else {
620 if (first_ZF < 1455) {
621 reg1[1] &= 0xCF; /* N2 */
622 reg1[1] |= 0x20;
623 reg2[1] &= 0xCF; /* R2 */
624 reg2[1] |= 0x10;
625 } else {
626 if (first_ZF >= 1630) {
627 reg1[1] &= 0xCF; /* N2 */
628 reg2[1] &= 0xCF; /* R2 */
629 reg2[1] |= 0x10;
630 }
631 }
632 }
633 }
634
635 /* set ports, enable P0 for symbol rates > 4Ms/s */
636 if (params->u.qpsk.symbol_rate >= 4000000)
637 reg1[1] |= 0x0c;
638 else
639 reg1[1] |= 0x04;
640
641 reg2[1] |= 0x0c;
642
643 R = 64;
644 A = 64;
645 P = 64; //32
646
647 M = (freq * R) / 4; /* in Mhz */
648 N = (M - A * 1000) / (P * 1000);
649
650 reg1[1] |= (N >> 9) & 0x03;
651 reg1[2] = (N >> 1) & 0xff;
652 reg1[3] = (N << 7) & 0x80;
653
654 reg2[1] |= (R >> 8) & 0x03;
655 reg2[2] = R & 0xFF; /* R */
656
657 reg1[3] |= A & 0x7f; /* A */
658
659 if (P == 64)
660 reg1[1] |= 0x40; /* Prescaler 64/65 */
661
662 reg0[1] |= 0x03;
663
664 /* already enabled - do not reenable i2c repeater or TX fails */
Patrick Boettcherdea74862006-05-14 05:01:31 -0300665 if (fe->ops.i2c_gate_ctrl)
666 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceyeffa7912006-01-09 15:25:09 -0200667 msg.buf = reg0;
668 msg.len = sizeof(reg0);
Andrew de Quinceye87d41c2006-04-18 17:47:11 -0300669 if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
Andrew de Quinceyeffa7912006-01-09 15:25:09 -0200670 return -EIO;
671
Patrick Boettcherdea74862006-05-14 05:01:31 -0300672 if (fe->ops.i2c_gate_ctrl)
673 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceyeffa7912006-01-09 15:25:09 -0200674 msg.buf = reg1;
675 msg.len = sizeof(reg1);
Andrew de Quinceye87d41c2006-04-18 17:47:11 -0300676 if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
Andrew de Quinceyeffa7912006-01-09 15:25:09 -0200677 return -EIO;
678
Patrick Boettcherdea74862006-05-14 05:01:31 -0300679 if (fe->ops.i2c_gate_ctrl)
680 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceyeffa7912006-01-09 15:25:09 -0200681 msg.buf = reg2;
682 msg.len = sizeof(reg2);
Andrew de Quinceye87d41c2006-04-18 17:47:11 -0300683 if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
Andrew de Quinceyeffa7912006-01-09 15:25:09 -0200684 return -EIO;
685
686 return 0;
687}
688
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689static u8 typhoon_cinergy1200s_inittab[] = {
690 0x01, 0x15,
691 0x02, 0x30,
692 0x03, 0x00,
693 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
694 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
695 0x06, 0x40, /* DAC not used, set to high impendance mode */
696 0x07, 0x00, /* DAC LSB */
697 0x08, 0x40, /* DiSEqC off */
698 0x09, 0x00, /* FIFO */
699 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
700 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
701 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
702 0x10, 0x3f, // AGC2 0x3d
703 0x11, 0x84,
Oliver Endrissff29d062005-11-08 21:35:43 -0800704 0x12, 0xb9,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 0x15, 0xc9, // lock detector threshold
706 0x16, 0x00,
707 0x17, 0x00,
708 0x18, 0x00,
709 0x19, 0x00,
710 0x1a, 0x00,
711 0x1f, 0x50,
712 0x20, 0x00,
713 0x21, 0x00,
714 0x22, 0x00,
715 0x23, 0x00,
716 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
717 0x29, 0x1e, // 1/2 threshold
718 0x2a, 0x14, // 2/3 threshold
719 0x2b, 0x0f, // 3/4 threshold
720 0x2c, 0x09, // 5/6 threshold
721 0x2d, 0x05, // 7/8 threshold
722 0x2e, 0x01,
723 0x31, 0x1f, // test all FECs
724 0x32, 0x19, // viterbi and synchro search
725 0x33, 0xfc, // rs control
726 0x34, 0x93, // error control
727 0x0f, 0x92,
728 0xff, 0xff
729};
730
731static struct stv0299_config typhoon_config = {
732 .demod_address = 0x68,
733 .inittab = typhoon_cinergy1200s_inittab,
734 .mclk = 88000000UL,
735 .invert = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 .skip_reinit = 0,
737 .lock_output = STV0229_LOCKOUTPUT_1,
738 .volt13_op0_op1 = STV0299_VOLT13_OP0,
739 .min_delay_ms = 100,
740 .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741};
742
743
744static struct stv0299_config cinergy_1200s_config = {
745 .demod_address = 0x68,
746 .inittab = typhoon_cinergy1200s_inittab,
747 .mclk = 88000000UL,
748 .invert = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 .skip_reinit = 0,
750 .lock_output = STV0229_LOCKOUTPUT_0,
751 .volt13_op0_op1 = STV0299_VOLT13_OP0,
752 .min_delay_ms = 100,
753 .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754};
755
Andrew de Quinceyeffa7912006-01-09 15:25:09 -0200756static struct stv0299_config cinergy_1200s_1894_0010_config = {
757 .demod_address = 0x68,
758 .inittab = typhoon_cinergy1200s_inittab,
759 .mclk = 88000000UL,
760 .invert = 1,
761 .skip_reinit = 0,
762 .lock_output = STV0229_LOCKOUTPUT_1,
763 .volt13_op0_op1 = STV0299_VOLT13_OP0,
764 .min_delay_ms = 100,
765 .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
Andrew de Quinceyeffa7912006-01-09 15:25:09 -0200766};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
Andrew de Quinceye87d41c2006-04-18 17:47:11 -0300768static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769{
770 struct budget *budget = (struct budget *) fe->dvb->priv;
771 u8 buf[4];
772 struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
773
774#define TUNER_MUL 62500
775
776 u32 div = (params->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL;
777
778 buf[0] = (div >> 8) & 0x7f;
779 buf[1] = div & 0xff;
Johannes Stezenbacheef57642005-07-07 17:57:58 -0700780 buf[2] = 0x86;
781 buf[3] = (params->frequency < 150000000 ? 0x01 :
782 params->frequency < 445000000 ? 0x02 : 0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783
Patrick Boettcherdea74862006-05-14 05:01:31 -0300784 if (fe->ops.i2c_gate_ctrl)
785 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
787 return -EIO;
788 return 0;
789}
790
791static struct tda10021_config philips_cu1216_config = {
792 .demod_address = 0x0c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793};
794
795
796
797
Andrew de Quinceye87d41c2006-04-18 17:47:11 -0300798static int philips_tu1216_tuner_init(struct dvb_frontend *fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799{
800 struct budget *budget = (struct budget *) fe->dvb->priv;
801 static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
802 struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
803
804 // setup PLL configuration
Patrick Boettcherdea74862006-05-14 05:01:31 -0300805 if (fe->ops.i2c_gate_ctrl)
806 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
808 return -EIO;
809 msleep(1);
810
811 return 0;
812}
813
Andrew de Quinceye87d41c2006-04-18 17:47:11 -0300814static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815{
816 struct budget *budget = (struct budget *) fe->dvb->priv;
817 u8 tuner_buf[4];
818 struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len =
819 sizeof(tuner_buf) };
820 int tuner_frequency = 0;
821 u8 band, cp, filter;
822
823 // determine charge pump
824 tuner_frequency = params->frequency + 36166000;
825 if (tuner_frequency < 87000000)
826 return -EINVAL;
827 else if (tuner_frequency < 130000000)
828 cp = 3;
829 else if (tuner_frequency < 160000000)
830 cp = 5;
831 else if (tuner_frequency < 200000000)
832 cp = 6;
833 else if (tuner_frequency < 290000000)
834 cp = 3;
835 else if (tuner_frequency < 420000000)
836 cp = 5;
837 else if (tuner_frequency < 480000000)
838 cp = 6;
839 else if (tuner_frequency < 620000000)
840 cp = 3;
841 else if (tuner_frequency < 830000000)
842 cp = 5;
843 else if (tuner_frequency < 895000000)
844 cp = 7;
845 else
846 return -EINVAL;
847
848 // determine band
849 if (params->frequency < 49000000)
850 return -EINVAL;
851 else if (params->frequency < 161000000)
852 band = 1;
853 else if (params->frequency < 444000000)
854 band = 2;
855 else if (params->frequency < 861000000)
856 band = 4;
857 else
858 return -EINVAL;
859
860 // setup PLL filter
861 switch (params->u.ofdm.bandwidth) {
862 case BANDWIDTH_6_MHZ:
863 filter = 0;
864 break;
865
866 case BANDWIDTH_7_MHZ:
867 filter = 0;
868 break;
869
870 case BANDWIDTH_8_MHZ:
871 filter = 1;
872 break;
873
874 default:
875 return -EINVAL;
876 }
877
878 // calculate divisor
879 // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
880 tuner_frequency = (((params->frequency / 1000) * 6) + 217496) / 1000;
881
882 // setup tuner buffer
883 tuner_buf[0] = (tuner_frequency >> 8) & 0x7f;
884 tuner_buf[1] = tuner_frequency & 0xff;
885 tuner_buf[2] = 0xca;
886 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
887
Patrick Boettcherdea74862006-05-14 05:01:31 -0300888 if (fe->ops.i2c_gate_ctrl)
889 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
891 return -EIO;
892
893 msleep(1);
894 return 0;
895}
896
897static int philips_tu1216_request_firmware(struct dvb_frontend *fe,
898 const struct firmware **fw, char *name)
899{
900 struct budget *budget = (struct budget *) fe->dvb->priv;
901
902 return request_firmware(fw, name, &budget->dev->pci->dev);
903}
904
905static struct tda1004x_config philips_tu1216_config = {
906
907 .demod_address = 0x8,
908 .invert = 1,
909 .invert_oclk = 1,
Hartmut Hackmannecb60de2005-07-07 17:57:40 -0700910 .xtal_freq = TDA10046_XTAL_4M,
911 .agc_config = TDA10046_AGC_DEFAULT,
912 .if_freq = TDA10046_FREQ_3617,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 .request_firmware = philips_tu1216_request_firmware,
914};
915
Regis Prevotf8bf1342006-01-11 23:31:53 -0200916static u8 philips_sd1878_inittab[] = {
917 0x01, 0x15,
918 0x02, 0x30,
919 0x03, 0x00,
920 0x04, 0x7d,
921 0x05, 0x35,
922 0x06, 0x40,
923 0x07, 0x00,
924 0x08, 0x43,
925 0x09, 0x02,
926 0x0C, 0x51,
927 0x0D, 0x82,
928 0x0E, 0x23,
929 0x10, 0x3f,
930 0x11, 0x84,
931 0x12, 0xb9,
932 0x15, 0xc9,
933 0x16, 0x19,
934 0x17, 0x8c,
935 0x18, 0x59,
936 0x19, 0xf8,
937 0x1a, 0xfe,
938 0x1c, 0x7f,
939 0x1d, 0x00,
940 0x1e, 0x00,
941 0x1f, 0x50,
942 0x20, 0x00,
943 0x21, 0x00,
944 0x22, 0x00,
945 0x23, 0x00,
946 0x28, 0x00,
947 0x29, 0x28,
948 0x2a, 0x14,
949 0x2b, 0x0f,
950 0x2c, 0x09,
951 0x2d, 0x09,
952 0x31, 0x1f,
953 0x32, 0x19,
954 0x33, 0xfc,
955 0x34, 0x93,
956 0xff, 0xff
957};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958
Andrew de Quinceye87d41c2006-04-18 17:47:11 -0300959static int philips_sd1878_tda8261_tuner_set_params(struct dvb_frontend *fe,
960 struct dvb_frontend_parameters *params)
Regis Prevotf8bf1342006-01-11 23:31:53 -0200961{
962 u8 buf[4];
963 int rc;
964 struct i2c_msg tuner_msg = {.addr=0x60,.flags=0,.buf=buf,.len=sizeof(buf)};
Andrew de Quinceye87d41c2006-04-18 17:47:11 -0300965 struct budget *budget = (struct budget *) fe->dvb->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966
Regis Prevotf8bf1342006-01-11 23:31:53 -0200967 if((params->frequency < 950000) || (params->frequency > 2150000))
968 return -EINVAL;
969
970 rc=dvb_pll_configure(&dvb_pll_philips_sd1878_tda8261, buf,
971 params->frequency, 0);
972 if(rc < 0) return rc;
973
Patrick Boettcherdea74862006-05-14 05:01:31 -0300974 if (fe->ops.i2c_gate_ctrl)
975 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quinceye87d41c2006-04-18 17:47:11 -0300976 if(i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
Regis Prevotf8bf1342006-01-11 23:31:53 -0200977 return -EIO;
978
979 return 0;
980}
981
982static int philips_sd1878_ci_set_symbol_rate(struct dvb_frontend *fe,
983 u32 srate, u32 ratio)
984{
985 u8 aclk = 0;
986 u8 bclk = 0;
987 u8 m1;
988
989 aclk = 0xb5;
990 if (srate < 2000000)
991 bclk = 0x86;
992 else if (srate < 5000000)
993 bclk = 0x89;
994 else if (srate < 15000000)
995 bclk = 0x8f;
996 else if (srate < 45000000)
997 bclk = 0x95;
998
999 m1 = 0x14;
1000 if (srate < 4000000)
1001 m1 = 0x10;
1002
1003 stv0299_writereg(fe, 0x0e, 0x23);
1004 stv0299_writereg(fe, 0x0f, 0x94);
1005 stv0299_writereg(fe, 0x10, 0x39);
1006 stv0299_writereg(fe, 0x13, aclk);
1007 stv0299_writereg(fe, 0x14, bclk);
1008 stv0299_writereg(fe, 0x15, 0xc9);
1009 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
1010 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
1011 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
1012 stv0299_writereg(fe, 0x0f, 0x80 | m1);
1013
1014 return 0;
1015}
1016
1017static struct stv0299_config philips_sd1878_config = {
1018 .demod_address = 0x68,
Andrew de Quincey5c1208b2006-05-22 10:32:02 -03001019 .inittab = philips_sd1878_inittab,
Regis Prevotf8bf1342006-01-11 23:31:53 -02001020 .mclk = 88000000UL,
1021 .invert = 0,
1022 .skip_reinit = 0,
1023 .lock_output = STV0229_LOCKOUTPUT_1,
1024 .volt13_op0_op1 = STV0299_VOLT13_OP0,
1025 .min_delay_ms = 100,
1026 .set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
Regis Prevotf8bf1342006-01-11 23:31:53 -02001027};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
1029static u8 read_pwm(struct budget_av *budget_av)
1030{
1031 u8 b = 0xff;
1032 u8 pwm;
1033 struct i2c_msg msg[] = { {.addr = 0x50,.flags = 0,.buf = &b,.len = 1},
1034 {.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1}
1035 };
1036
1037 if ((i2c_transfer(&budget_av->budget.i2c_adap, msg, 2) != 2)
1038 || (pwm == 0xff))
1039 pwm = 0x48;
1040
1041 return pwm;
1042}
1043
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001044#define SUBID_DVBS_KNC1 0x0010
1045#define SUBID_DVBS_KNC1_PLUS 0x0011
1046#define SUBID_DVBS_TYPHOON 0x4f56
1047#define SUBID_DVBS_CINERGY1200 0x1154
Regis Prevotf8bf1342006-01-11 23:31:53 -02001048#define SUBID_DVBS_CYNERGY1200N 0x1155
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001049
Regis Prevotf8bf1342006-01-11 23:31:53 -02001050#define SUBID_DVBS_TV_STAR 0x0014
1051#define SUBID_DVBS_TV_STAR_CI 0x0016
Lothar Englisch60110ce2006-06-06 16:13:46 -03001052#define SUBID_DVBS_EASYWATCH_1 0x001a
Thilo Berger36f4f332006-02-27 00:09:08 -03001053#define SUBID_DVBS_EASYWATCH 0x001e
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001054#define SUBID_DVBC_KNC1 0x0020
1055#define SUBID_DVBC_KNC1_PLUS 0x0021
1056#define SUBID_DVBC_CINERGY1200 0x1156
1057
1058#define SUBID_DVBT_KNC1_PLUS 0x0031
1059#define SUBID_DVBT_KNC1 0x0030
1060#define SUBID_DVBT_CINERGY1200 0x1157
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061
Andrew de Quincey5c1208b2006-05-22 10:32:02 -03001062
1063static int tda10021_set_frontend(struct dvb_frontend *fe,
1064 struct dvb_frontend_parameters *p)
1065{
1066 struct budget_av* budget_av = fe->dvb->priv;
1067 int result;
1068
1069 result = budget_av->tda10021_set_frontend(fe, p);
1070 if (budget_av->tda10021_ts_enabled) {
1071 tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
1072 } else {
1073 tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
1074 }
1075
1076 return result;
1077}
1078
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079static void frontend_init(struct budget_av *budget_av)
1080{
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001081 struct saa7146_dev * saa = budget_av->budget.dev;
1082 struct dvb_frontend * fe = NULL;
1083
Andrew de Quincey473f5422006-04-13 17:29:07 -03001084 /* Enable / PowerON Frontend */
1085 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
1086
1087 /* additional setup necessary for the PLUS cards */
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001088 switch (saa->pci->subsystem_device) {
1089 case SUBID_DVBS_KNC1_PLUS:
1090 case SUBID_DVBC_KNC1_PLUS:
1091 case SUBID_DVBT_KNC1_PLUS:
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001092 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 break;
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001094 }
1095
1096 switch (saa->pci->subsystem_device) {
1097
1098 case SUBID_DVBS_KNC1:
Lothar Englisch60110ce2006-06-06 16:13:46 -03001099 case SUBID_DVBS_EASYWATCH_1:
Andrew de Quinceyeffa7912006-01-09 15:25:09 -02001100 if (saa->pci->subsystem_vendor == 0x1894) {
1101 fe = stv0299_attach(&cinergy_1200s_1894_0010_config,
1102 &budget_av->budget.i2c_adap);
Andrew de Quinceye87d41c2006-04-18 17:47:11 -03001103 if (fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001104 fe->ops.tuner_ops.set_params = philips_su1278sh2_tua6100_tuner_set_params;
Andrew de Quinceye87d41c2006-04-18 17:47:11 -03001105 }
Andrew de Quinceyeffa7912006-01-09 15:25:09 -02001106 } else {
1107 fe = stv0299_attach(&typhoon_config,
1108 &budget_av->budget.i2c_adap);
Andrew de Quinceye87d41c2006-04-18 17:47:11 -03001109 if (fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001110 fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
Andrew de Quinceye87d41c2006-04-18 17:47:11 -03001111 }
Andrew de Quinceyeffa7912006-01-09 15:25:09 -02001112 }
1113 break;
1114
Regis Prevotf8bf1342006-01-11 23:31:53 -02001115 case SUBID_DVBS_TV_STAR:
1116 case SUBID_DVBS_TV_STAR_CI:
1117 case SUBID_DVBS_CYNERGY1200N:
Thilo Berger36f4f332006-02-27 00:09:08 -03001118 case SUBID_DVBS_EASYWATCH:
Regis Prevotf8bf1342006-01-11 23:31:53 -02001119 fe = stv0299_attach(&philips_sd1878_config,
1120 &budget_av->budget.i2c_adap);
Andrew de Quinceye87d41c2006-04-18 17:47:11 -03001121 if (fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001122 fe->ops.tuner_ops.set_params = philips_sd1878_tda8261_tuner_set_params;
Andrew de Quinceye87d41c2006-04-18 17:47:11 -03001123 }
Regis Prevotf8bf1342006-01-11 23:31:53 -02001124 break;
1125
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001126 case SUBID_DVBS_KNC1_PLUS:
1127 case SUBID_DVBS_TYPHOON:
1128 fe = stv0299_attach(&typhoon_config,
1129 &budget_av->budget.i2c_adap);
Andrew de Quinceye87d41c2006-04-18 17:47:11 -03001130 if (fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001131 fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
Andrew de Quinceye87d41c2006-04-18 17:47:11 -03001132 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 break;
1134
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001135 case SUBID_DVBS_CINERGY1200:
1136 fe = stv0299_attach(&cinergy_1200s_config,
1137 &budget_av->budget.i2c_adap);
Andrew de Quinceye87d41c2006-04-18 17:47:11 -03001138 if (fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001139 fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
Andrew de Quinceye87d41c2006-04-18 17:47:11 -03001140 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 break;
1142
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001143 case SUBID_DVBC_KNC1:
1144 case SUBID_DVBC_KNC1_PLUS:
Andrew de Quincey5c1208b2006-05-22 10:32:02 -03001145 case SUBID_DVBC_CINERGY1200:
1146 budget_av->reinitialise_demod = 1;
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001147 fe = tda10021_attach(&philips_cu1216_config,
1148 &budget_av->budget.i2c_adap,
1149 read_pwm(budget_av));
Andrew de Quinceye87d41c2006-04-18 17:47:11 -03001150 if (fe) {
Andrew de Quincey5c1208b2006-05-22 10:32:02 -03001151 budget_av->tda10021_poclkp = 1;
Patrick Boettcherdea74862006-05-14 05:01:31 -03001152 budget_av->tda10021_set_frontend = fe->ops.set_frontend;
1153 fe->ops.set_frontend = tda10021_set_frontend;
1154 fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
Andrew de Quinceye87d41c2006-04-18 17:47:11 -03001155 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 break;
1157
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001158 case SUBID_DVBT_KNC1:
1159 case SUBID_DVBT_KNC1_PLUS:
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001160 case SUBID_DVBT_CINERGY1200:
Andrew de Quincey5c1208b2006-05-22 10:32:02 -03001161 budget_av->reinitialise_demod = 1;
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001162 fe = tda10046_attach(&philips_tu1216_config,
1163 &budget_av->budget.i2c_adap);
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03001164 if (fe) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001165 fe->ops.tuner_ops.init = philips_tu1216_tuner_init;
1166 fe->ops.tuner_ops.set_params = philips_tu1216_tuner_set_params;
Andrew de Quincey6b3ccab2006-04-20 12:01:47 -03001167 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 break;
1169 }
1170
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001171 if (fe == NULL) {
1172 printk(KERN_ERR "budget-av: A frontend driver was not found "
1173 "for device %04x/%04x subsystem %04x/%04x\n",
1174 saa->pci->vendor,
1175 saa->pci->device,
1176 saa->pci->subsystem_vendor,
1177 saa->pci->subsystem_device);
1178 return;
1179 }
1180
1181 budget_av->budget.dvb_frontend = fe;
1182
1183 if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
1184 budget_av->budget.dvb_frontend)) {
1185 printk(KERN_ERR "budget-av: Frontend registration failed!\n");
Patrick Boettcherdea74862006-05-14 05:01:31 -03001186 if (budget_av->budget.dvb_frontend->ops.release)
1187 budget_av->budget.dvb_frontend->ops.release(budget_av->budget.dvb_frontend);
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001188 budget_av->budget.dvb_frontend = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 }
1190}
1191
1192
1193static void budget_av_irq(struct saa7146_dev *dev, u32 * isr)
1194{
1195 struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
1196
1197 dprintk(8, "dev: %p, budget_av: %p\n", dev, budget_av);
1198
1199 if (*isr & MASK_10)
1200 ttpci_budget_irq10_handler(dev, isr);
1201}
1202
1203static int budget_av_detach(struct saa7146_dev *dev)
1204{
1205 struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
1206 int err;
1207
1208 dprintk(2, "dev: %p\n", dev);
1209
1210 if (1 == budget_av->has_saa7113) {
1211 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
1212
1213 msleep(200);
1214
1215 saa7146_unregister_device(&budget_av->vd, dev);
1216 }
1217
1218 if (budget_av->budget.ci_present)
1219 ciintf_deinit(budget_av);
1220
1221 if (budget_av->budget.dvb_frontend != NULL)
1222 dvb_unregister_frontend(budget_av->budget.dvb_frontend);
1223 err = ttpci_budget_deinit(&budget_av->budget);
1224
1225 kfree(budget_av);
1226
1227 return err;
1228}
1229
1230static struct saa7146_ext_vv vv_data;
1231
1232static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
1233{
1234 struct budget_av *budget_av;
1235 u8 *mac;
1236 int err;
1237
1238 dprintk(2, "dev: %p\n", dev);
1239
Panagiotis Issaris74081872006-01-11 19:40:56 -02001240 if (!(budget_av = kzalloc(sizeof(struct budget_av), GFP_KERNEL)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 return -ENOMEM;
1242
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001243 budget_av->has_saa7113 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 budget_av->budget.ci_present = 0;
1245
1246 dev->ext_priv = budget_av;
1247
1248 if ((err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE))) {
1249 kfree(budget_av);
1250 return err;
1251 }
1252
1253 /* knc1 initialization */
1254 saa7146_write(dev, DD1_STREAM_B, 0x04000000);
1255 saa7146_write(dev, DD1_INIT, 0x07000600);
1256 saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
1257
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001258 if (saa7113_init(budget_av) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 budget_av->has_saa7113 = 1;
1260
1261 if (0 != saa7146_vv_init(dev, &vv_data)) {
1262 /* fixme: proper cleanup here */
1263 ERR(("cannot init vv subsystem.\n"));
1264 return err;
1265 }
1266
1267 if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
1268 /* fixme: proper cleanup here */
1269 ERR(("cannot register capture v4l2 device.\n"));
1270 return err;
1271 }
1272
1273 /* beware: this modifies dev->vv ... */
1274 saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A,
1275 SAA7146_HPS_SYNC_PORT_A);
1276
1277 saa7113_setinput(budget_av, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 }
1279
1280 /* fixme: find some sane values here... */
1281 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
1282
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001283 mac = budget_av->budget.dvb_adapter.proposed_mac;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001285 printk(KERN_ERR "KNC1-%d: Could not read MAC from KNC1 card\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001286 budget_av->budget.dvb_adapter.num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 memset(mac, 0, 6);
1288 } else {
Johannes Stezenbachb82a96a2005-05-16 21:54:49 -07001289 printk(KERN_INFO "KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001290 budget_av->budget.dvb_adapter.num,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
1292 }
1293
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001294 budget_av->budget.dvb_adapter.priv = budget_av;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 frontend_init(budget_av);
1296
Andrew de Quincey71a8dff2006-04-06 09:42:46 -03001297 if (!budget_av->has_saa7113) {
1298 ciintf_init(budget_av);
1299 }
1300
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 return 0;
1302}
1303
1304#define KNC1_INPUTS 2
1305static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
1306 {0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
1307 {1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
1308};
1309
1310static struct saa7146_extension_ioctls ioctls[] = {
1311 {VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE},
1312 {VIDIOC_G_INPUT, SAA7146_EXCLUSIVE},
1313 {VIDIOC_S_INPUT, SAA7146_EXCLUSIVE},
1314 {0, 0}
1315};
1316
1317static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
1318{
1319 struct saa7146_dev *dev = fh->dev;
1320 struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
1321
1322 switch (cmd) {
1323 case VIDIOC_ENUMINPUT:{
1324 struct v4l2_input *i = arg;
1325
1326 dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
1327 if (i->index < 0 || i->index >= KNC1_INPUTS) {
1328 return -EINVAL;
1329 }
1330 memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
1331 return 0;
1332 }
1333 case VIDIOC_G_INPUT:{
1334 int *input = (int *) arg;
1335
1336 *input = budget_av->cur_input;
1337
1338 dprintk(1, "VIDIOC_G_INPUT %d.\n", *input);
1339 return 0;
1340 }
1341 case VIDIOC_S_INPUT:{
1342 int input = *(int *) arg;
1343 dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
1344 return saa7113_setinput(budget_av, input);
1345 }
1346 default:
1347 return -ENOIOCTLCMD;
1348 }
1349 return 0;
1350}
1351
1352static struct saa7146_standard standard[] = {
1353 {.name = "PAL",.id = V4L2_STD_PAL,
1354 .v_offset = 0x17,.v_field = 288,
1355 .h_offset = 0x14,.h_pixels = 680,
1356 .v_max_out = 576,.h_max_out = 768 },
1357
1358 {.name = "NTSC",.id = V4L2_STD_NTSC,
1359 .v_offset = 0x16,.v_field = 240,
1360 .h_offset = 0x06,.h_pixels = 708,
1361 .v_max_out = 480,.h_max_out = 640, },
1362};
1363
1364static struct saa7146_ext_vv vv_data = {
1365 .inputs = 2,
1366 .capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
1367 .flags = 0,
1368 .stds = &standard[0],
1369 .num_stds = sizeof(standard) / sizeof(struct saa7146_standard),
1370 .ioctls = &ioctls[0],
1371 .ioctl = av_ioctl,
1372};
1373
1374static struct saa7146_extension budget_extension;
1375
1376MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
1377MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
1378MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
Regis Prevotf8bf1342006-01-11 23:31:53 -02001379MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
Thilo Berger36f4f332006-02-27 00:09:08 -03001380MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR);
Lothar Englisch60110ce2006-06-06 16:13:46 -03001381MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S);
Johannes Stezenbach2d4f2c22005-05-16 21:54:23 -07001382MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
1383MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
1384MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
Regis Prevotf8bf1342006-01-11 23:31:53 -02001386MAKE_BUDGET_INFO(cin1200sn, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C);
1388MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
1389
1390static struct pci_device_id pci_tbl[] = {
1391 MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
Johannes Stezenbach2d4f2c22005-05-16 21:54:23 -07001392 MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
Andrew de Quinceyeffa7912006-01-09 15:25:09 -02001393 MAKE_EXTENSION_PCI(knc1s, 0x1894, 0x0010),
Johannes Stezenbach2d4f2c22005-05-16 21:54:23 -07001394 MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
Regis Prevotf8bf1342006-01-11 23:31:53 -02001395 MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
1396 MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
Thilo Berger36f4f332006-02-27 00:09:08 -03001397 MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
Lothar Englisch60110ce2006-06-06 16:13:46 -03001398 MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
Johannes Stezenbach2d4f2c22005-05-16 21:54:23 -07001400 MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
Johannes Stezenbach2d4f2c22005-05-16 21:54:23 -07001402 MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154),
Regis Prevotf8bf1342006-01-11 23:31:53 -02001404 MAKE_EXTENSION_PCI(cin1200sn, 0x153b, 0x1155),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),
1406 MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),
1407 {
1408 .vendor = 0,
1409 }
1410};
1411
1412MODULE_DEVICE_TABLE(pci, pci_tbl);
1413
1414static struct saa7146_extension budget_extension = {
Julian Scheel27b05fd2005-07-12 13:58:39 -07001415 .name = "budget_av",
Oliver Endriss69459f32005-12-01 00:51:48 -08001416 .flags = SAA7146_I2C_SHORT_DELAY,
1417
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 .pci_tbl = pci_tbl,
1419
1420 .module = THIS_MODULE,
1421 .attach = budget_av_attach,
1422 .detach = budget_av_detach,
1423
1424 .irq_mask = MASK_10,
1425 .irq_func = budget_av_irq,
1426};
1427
1428static int __init budget_av_init(void)
1429{
1430 return saa7146_register_extension(&budget_extension);
1431}
1432
1433static void __exit budget_av_exit(void)
1434{
1435 saa7146_unregister_extension(&budget_extension);
1436}
1437
1438module_init(budget_av_init);
1439module_exit(budget_av_exit);
1440
1441MODULE_LICENSE("GPL");
1442MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
1443MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1444 "budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)");