aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/ttpci/budget.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/media/dvb/ttpci/budget.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/media/dvb/ttpci/budget.c')
-rw-r--r--drivers/media/dvb/ttpci/budget.c573
1 files changed, 573 insertions, 0 deletions
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
new file mode 100644
index 000000000000..5e6a10f4ad95
--- /dev/null
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -0,0 +1,573 @@
1/*
2 * budget.c: driver for the SAA7146 based Budget DVB cards
3 *
4 * Compiled from various sources by Michael Hunold <michael@mihu.de>
5 *
6 * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
7 *
8 * Copyright (C) 1999-2002 Ralph Metzler
9 * & Marcus Metzler for convergence integrated media GmbH
10 *
11 * 26feb2004 Support for FS Activy Card (Grundig tuner) by
12 * Michael Dreher <michael@5dot1.de>,
13 * Oliver Endriss <o.endriss@gmx.de> and
14 * Andreas 'randy' Weinberger
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
20 *
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
32 *
33 *
34 * the project's page is at http://www.linuxtv.org/dvb/
35 */
36
37#include "budget.h"
38#include "stv0299.h"
39#include "ves1x93.h"
40#include "ves1820.h"
41#include "l64781.h"
42#include "tda8083.h"
43
44static void Set22K (struct budget *budget, int state)
45{
46 struct saa7146_dev *dev=budget->dev;
47 dprintk(2, "budget: %p\n", budget);
48 saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO));
49}
50
51/* Diseqc functions only for TT Budget card */
52/* taken from the Skyvision DVB driver by
53 Ralph Metzler <rjkm@metzlerbros.de> */
54
55static void DiseqcSendBit (struct budget *budget, int data)
56{
57 struct saa7146_dev *dev=budget->dev;
58 dprintk(2, "budget: %p\n", budget);
59
60 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
61 udelay(data ? 500 : 1000);
62 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
63 udelay(data ? 1000 : 500);
64}
65
66static void DiseqcSendByte (struct budget *budget, int data)
67{
68 int i, par=1, d;
69
70 dprintk(2, "budget: %p\n", budget);
71
72 for (i=7; i>=0; i--) {
73 d = (data>>i)&1;
74 par ^= d;
75 DiseqcSendBit(budget, d);
76 }
77
78 DiseqcSendBit(budget, par);
79}
80
81static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst)
82{
83 struct saa7146_dev *dev=budget->dev;
84 int i;
85
86 dprintk(2, "budget: %p\n", budget);
87
88 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
89 mdelay(16);
90
91 for (i=0; i<len; i++)
92 DiseqcSendByte(budget, msg[i]);
93
94 mdelay(16);
95
96 if (burst!=-1) {
97 if (burst)
98 DiseqcSendByte(budget, 0xff);
99 else {
100 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
101 udelay(12500);
102 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
103 }
104 msleep(20);
105 }
106
107 return 0;
108}
109
110/*
111 * Routines for the Fujitsu Siemens Activy budget card
112 * 22 kHz tone and DiSEqC are handled by the frontend.
113 * Voltage must be set here.
114 */
115static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
116{
117 struct saa7146_dev *dev=budget->dev;
118
119 dprintk(2, "budget: %p\n", budget);
120
121 switch (voltage) {
122 case SEC_VOLTAGE_13:
123 saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
124 break;
125 case SEC_VOLTAGE_18:
126 saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
127 break;
128 default:
129 return -EINVAL;
130 }
131
132 return 0;
133}
134
135static int siemens_budget_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
136{
137 struct budget* budget = (struct budget*) fe->dvb->priv;
138
139 return SetVoltage_Activy (budget, voltage);
140}
141
142static int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
143{
144 struct budget* budget = (struct budget*) fe->dvb->priv;
145
146 switch (tone) {
147 case SEC_TONE_ON:
148 Set22K (budget, 1);
149 break;
150
151 case SEC_TONE_OFF:
152 Set22K (budget, 0);
153 break;
154
155 default:
156 return -EINVAL;
157 }
158
159 return 0;
160}
161
162static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
163{
164 struct budget* budget = (struct budget*) fe->dvb->priv;
165
166 SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
167
168 return 0;
169}
170
171static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
172{
173 struct budget* budget = (struct budget*) fe->dvb->priv;
174
175 SendDiSEqCMsg (budget, 0, NULL, minicmd);
176
177 return 0;
178}
179
180static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
181{
182 struct budget* budget = (struct budget*) fe->dvb->priv;
183 u8 pwr = 0;
184 u8 buf[4];
185 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
186 u32 div = (params->frequency + 479500) / 125;
187
188 if (params->frequency > 2000000) pwr = 3;
189 else if (params->frequency > 1800000) pwr = 2;
190 else if (params->frequency > 1600000) pwr = 1;
191 else if (params->frequency > 1200000) pwr = 0;
192 else if (params->frequency >= 1100000) pwr = 1;
193 else pwr = 2;
194
195 buf[0] = (div >> 8) & 0x7f;
196 buf[1] = div & 0xff;
197 buf[2] = ((div & 0x18000) >> 10) | 0x95;
198 buf[3] = (pwr << 6) | 0x30;
199
200 // NOTE: since we're using a prescaler of 2, we set the
201 // divisor frequency to 62.5kHz and divide by 125 above
202
203 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
204 return 0;
205}
206
207static struct ves1x93_config alps_bsrv2_config =
208{
209 .demod_address = 0x08,
210 .xin = 90100000UL,
211 .invert_pwm = 0,
212 .pll_set = alps_bsrv2_pll_set,
213};
214
215static u8 alps_bsru6_inittab[] = {
216 0x01, 0x15,
217 0x02, 0x00,
218 0x03, 0x00,
219 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
220 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
221 0x06, 0x40, /* DAC not used, set to high impendance mode */
222 0x07, 0x00, /* DAC LSB */
223 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
224 0x09, 0x00, /* FIFO */
225 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
226 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
227 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
228 0x10, 0x3f, // AGC2 0x3d
229 0x11, 0x84,
230 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
231 0x15, 0xc9, // lock detector threshold
232 0x16, 0x00,
233 0x17, 0x00,
234 0x18, 0x00,
235 0x19, 0x00,
236 0x1a, 0x00,
237 0x1f, 0x50,
238 0x20, 0x00,
239 0x21, 0x00,
240 0x22, 0x00,
241 0x23, 0x00,
242 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
243 0x29, 0x1e, // 1/2 threshold
244 0x2a, 0x14, // 2/3 threshold
245 0x2b, 0x0f, // 3/4 threshold
246 0x2c, 0x09, // 5/6 threshold
247 0x2d, 0x05, // 7/8 threshold
248 0x2e, 0x01,
249 0x31, 0x1f, // test all FECs
250 0x32, 0x19, // viterbi and synchro search
251 0x33, 0xfc, // rs control
252 0x34, 0x93, // error control
253 0x0f, 0x52,
254 0xff, 0xff
255};
256
257static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
258{
259 u8 aclk = 0;
260 u8 bclk = 0;
261
262 if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
263 else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
264 else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
265 else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
266 else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
267 else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
268
269 stv0299_writereg (fe, 0x13, aclk);
270 stv0299_writereg (fe, 0x14, bclk);
271 stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff);
272 stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff);
273 stv0299_writereg (fe, 0x21, (ratio ) & 0xf0);
274
275 return 0;
276}
277
278static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
279{
280 struct budget* budget = (struct budget*) fe->dvb->priv;
281 u8 data[4];
282 u32 div;
283 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
284
285 if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL;
286
287 div = (params->frequency + (125 - 1)) / 125; // round correctly
288 data[0] = (div >> 8) & 0x7f;
289 data[1] = div & 0xff;
290 data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
291 data[3] = 0xC4;
292
293 if (params->frequency > 1530000) data[3] = 0xc0;
294
295 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
296 return 0;
297}
298
299static struct stv0299_config alps_bsru6_config = {
300
301 .demod_address = 0x68,
302 .inittab = alps_bsru6_inittab,
303 .mclk = 88000000UL,
304 .invert = 1,
305 .enhanced_tuning = 0,
306 .skip_reinit = 0,
307 .lock_output = STV0229_LOCKOUTPUT_1,
308 .volt13_op0_op1 = STV0299_VOLT13_OP1,
309 .min_delay_ms = 100,
310 .set_symbol_rate = alps_bsru6_set_symbol_rate,
311 .pll_set = alps_bsru6_pll_set,
312};
313
314static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
315{
316 struct budget* budget = (struct budget*) fe->dvb->priv;
317 u32 div;
318 u8 data[4];
319 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
320
321 div = (params->frequency + 35937500 + 31250) / 62500;
322
323 data[0] = (div >> 8) & 0x7f;
324 data[1] = div & 0xff;
325 data[2] = 0x85 | ((div >> 10) & 0x60);
326 data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
327
328 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
329 return 0;
330}
331
332static struct ves1820_config alps_tdbe2_config = {
333 .demod_address = 0x09,
334 .xin = 57840000UL,
335 .invert = 1,
336 .selagc = VES1820_SELAGC_SIGNAMPERR,
337 .pll_set = alps_tdbe2_pll_set,
338};
339
340static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
341{
342 struct budget* budget = (struct budget*) fe->dvb->priv;
343 u32 div;
344 u8 cfg, cpump, band_select;
345 u8 data[4];
346 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
347
348 div = (36125000 + params->frequency) / 166666;
349
350 cfg = 0x88;
351
352 if (params->frequency < 175000000) cpump = 2;
353 else if (params->frequency < 390000000) cpump = 1;
354 else if (params->frequency < 470000000) cpump = 2;
355 else if (params->frequency < 750000000) cpump = 1;
356 else cpump = 3;
357
358 if (params->frequency < 175000000) band_select = 0x0e;
359 else if (params->frequency < 470000000) band_select = 0x05;
360 else band_select = 0x03;
361
362 data[0] = (div >> 8) & 0x7f;
363 data[1] = div & 0xff;
364 data[2] = ((div >> 10) & 0x60) | cfg;
365 data[3] = (cpump << 6) | band_select;
366
367 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
368 return 0;
369}
370
371static struct l64781_config grundig_29504_401_config = {
372 .demod_address = 0x55,
373 .pll_set = grundig_29504_401_pll_set,
374};
375
376static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
377{
378 struct budget* budget = (struct budget*) fe->dvb->priv;
379 u32 div;
380 u8 data[4];
381 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
382
383 div = params->frequency / 125;
384 data[0] = (div >> 8) & 0x7f;
385 data[1] = div & 0xff;
386 data[2] = 0x8e;
387 data[3] = 0x00;
388
389 if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
390 return 0;
391}
392
393static struct tda8083_config grundig_29504_451_config = {
394 .demod_address = 0x68,
395 .pll_set = grundig_29504_451_pll_set,
396};
397
398static u8 read_pwm(struct budget* budget)
399{
400 u8 b = 0xff;
401 u8 pwm;
402 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
403 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
404
405 if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
406 pwm = 0x48;
407
408 return pwm;
409}
410
411static void frontend_init(struct budget *budget)
412{
413 switch(budget->dev->pci->subsystem_device) {
414 case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
415 case 0x1013:
416 // try the ALPS BSRV2 first of all
417 budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
418 if (budget->dvb_frontend) {
419 budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
420 budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
421 budget->dvb_frontend->ops->set_tone = budget_set_tone;
422 break;
423 }
424
425 // try the ALPS BSRU6 now
426 budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
427 if (budget->dvb_frontend) {
428 budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
429 budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
430 budget->dvb_frontend->ops->set_tone = budget_set_tone;
431 break;
432 }
433 break;
434
435 case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
436
437 budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
438 if (budget->dvb_frontend) break;
439 break;
440
441 case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
442
443 budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap);
444 if (budget->dvb_frontend) break;
445 break;
446
447 case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059))
448 budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
449 if (budget->dvb_frontend) {
450 budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
451 break;
452 }
453 break;
454
455 case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
456 budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
457 if (budget->dvb_frontend) {
458 budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
459 break;
460 }
461 break;
462 }
463
464 if (budget->dvb_frontend == NULL) {
465 printk("budget: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
466 budget->dev->pci->vendor,
467 budget->dev->pci->device,
468 budget->dev->pci->subsystem_vendor,
469 budget->dev->pci->subsystem_device);
470 } else {
471 if (dvb_register_frontend(budget->dvb_adapter, budget->dvb_frontend)) {
472 printk("budget: Frontend registration failed!\n");
473 if (budget->dvb_frontend->ops->release)
474 budget->dvb_frontend->ops->release(budget->dvb_frontend);
475 budget->dvb_frontend = NULL;
476 }
477 }
478}
479
480static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
481{
482 struct budget *budget = NULL;
483 int err;
484
485 budget = kmalloc(sizeof(struct budget), GFP_KERNEL);
486 if( NULL == budget ) {
487 return -ENOMEM;
488 }
489
490 dprintk(2, "dev:%p, info:%p, budget:%p\n", dev, info, budget);
491
492 dev->ext_priv = budget;
493
494 if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
495 printk("==> failed\n");
496 kfree (budget);
497 return err;
498 }
499
500 budget->dvb_adapter->priv = budget;
501 frontend_init(budget);
502
503 return 0;
504}
505
506static int budget_detach (struct saa7146_dev* dev)
507{
508 struct budget *budget = (struct budget*) dev->ext_priv;
509 int err;
510
511 if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend);
512
513 err = ttpci_budget_deinit (budget);
514
515 kfree (budget);
516 dev->ext_priv = NULL;
517
518 return err;
519}
520
521static struct saa7146_extension budget_extension;
522
523MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT);
524MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT);
525MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
526MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC);
527MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
528MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
529
530static struct pci_device_id pci_tbl[] = {
531 MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003),
532 MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004),
533 MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005),
534 MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
535 MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
536 MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
537 {
538 .vendor = 0,
539 }
540};
541
542MODULE_DEVICE_TABLE(pci, pci_tbl);
543
544static struct saa7146_extension budget_extension = {
545 .name = "budget dvb\0",
546 .flags = 0,
547
548 .module = THIS_MODULE,
549 .pci_tbl = pci_tbl,
550 .attach = budget_attach,
551 .detach = budget_detach,
552
553 .irq_mask = MASK_10,
554 .irq_func = ttpci_budget_irq10_handler,
555};
556
557static int __init budget_init(void)
558{
559 return saa7146_register_extension(&budget_extension);
560}
561
562static void __exit budget_exit(void)
563{
564 saa7146_unregister_extension(&budget_extension);
565}
566
567module_init(budget_init);
568module_exit(budget_exit);
569
570MODULE_LICENSE("GPL");
571MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
572MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
573 "budget PCI DVB cards by Siemens, Technotrend, Hauppauge");