diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/media/dvb/ttpci/budget.c | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'drivers/media/dvb/ttpci/budget.c')
-rw-r--r-- | drivers/media/dvb/ttpci/budget.c | 793 |
1 files changed, 793 insertions, 0 deletions
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c new file mode 100644 index 00000000000..d238fb9371a --- /dev/null +++ b/drivers/media/dvb/ttpci/budget.c | |||
@@ -0,0 +1,793 @@ | |||
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/ | ||
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 | #include "s5h1420.h" | ||
44 | #include "tda10086.h" | ||
45 | #include "tda826x.h" | ||
46 | #include "lnbp21.h" | ||
47 | #include "bsru6.h" | ||
48 | #include "bsbe1.h" | ||
49 | #include "tdhd1.h" | ||
50 | #include "stv6110x.h" | ||
51 | #include "stv090x.h" | ||
52 | #include "isl6423.h" | ||
53 | |||
54 | static int diseqc_method; | ||
55 | module_param(diseqc_method, int, 0444); | ||
56 | MODULE_PARM_DESC(diseqc_method, "Select DiSEqC method for subsystem id 13c2:1003, 0: default, 1: more reliable (for newer revisions only)"); | ||
57 | |||
58 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
59 | |||
60 | static void Set22K (struct budget *budget, int state) | ||
61 | { | ||
62 | struct saa7146_dev *dev=budget->dev; | ||
63 | dprintk(2, "budget: %p\n", budget); | ||
64 | saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO)); | ||
65 | } | ||
66 | |||
67 | /* Diseqc functions only for TT Budget card */ | ||
68 | /* taken from the Skyvision DVB driver by | ||
69 | Ralph Metzler <rjkm@metzlerbros.de> */ | ||
70 | |||
71 | static void DiseqcSendBit (struct budget *budget, int data) | ||
72 | { | ||
73 | struct saa7146_dev *dev=budget->dev; | ||
74 | dprintk(2, "budget: %p\n", budget); | ||
75 | |||
76 | saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); | ||
77 | udelay(data ? 500 : 1000); | ||
78 | saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); | ||
79 | udelay(data ? 1000 : 500); | ||
80 | } | ||
81 | |||
82 | static void DiseqcSendByte (struct budget *budget, int data) | ||
83 | { | ||
84 | int i, par=1, d; | ||
85 | |||
86 | dprintk(2, "budget: %p\n", budget); | ||
87 | |||
88 | for (i=7; i>=0; i--) { | ||
89 | d = (data>>i)&1; | ||
90 | par ^= d; | ||
91 | DiseqcSendBit(budget, d); | ||
92 | } | ||
93 | |||
94 | DiseqcSendBit(budget, par); | ||
95 | } | ||
96 | |||
97 | static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst) | ||
98 | { | ||
99 | struct saa7146_dev *dev=budget->dev; | ||
100 | int i; | ||
101 | |||
102 | dprintk(2, "budget: %p\n", budget); | ||
103 | |||
104 | saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); | ||
105 | mdelay(16); | ||
106 | |||
107 | for (i=0; i<len; i++) | ||
108 | DiseqcSendByte(budget, msg[i]); | ||
109 | |||
110 | mdelay(16); | ||
111 | |||
112 | if (burst!=-1) { | ||
113 | if (burst) | ||
114 | DiseqcSendByte(budget, 0xff); | ||
115 | else { | ||
116 | saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); | ||
117 | mdelay(12); | ||
118 | udelay(500); | ||
119 | saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); | ||
120 | } | ||
121 | msleep(20); | ||
122 | } | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * Routines for the Fujitsu Siemens Activy budget card | ||
129 | * 22 kHz tone and DiSEqC are handled by the frontend. | ||
130 | * Voltage must be set here. | ||
131 | * GPIO 1: LNBP EN, GPIO 2: LNBP VSEL | ||
132 | */ | ||
133 | static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage) | ||
134 | { | ||
135 | struct saa7146_dev *dev=budget->dev; | ||
136 | |||
137 | dprintk(2, "budget: %p\n", budget); | ||
138 | |||
139 | switch (voltage) { | ||
140 | case SEC_VOLTAGE_13: | ||
141 | saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); | ||
142 | saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO); | ||
143 | break; | ||
144 | case SEC_VOLTAGE_18: | ||
145 | saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); | ||
146 | saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); | ||
147 | break; | ||
148 | case SEC_VOLTAGE_OFF: | ||
149 | saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); | ||
150 | break; | ||
151 | default: | ||
152 | return -EINVAL; | ||
153 | } | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static int siemens_budget_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) | ||
159 | { | ||
160 | struct budget* budget = (struct budget*) fe->dvb->priv; | ||
161 | |||
162 | return SetVoltage_Activy (budget, voltage); | ||
163 | } | ||
164 | |||
165 | static int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | ||
166 | { | ||
167 | struct budget* budget = (struct budget*) fe->dvb->priv; | ||
168 | |||
169 | switch (tone) { | ||
170 | case SEC_TONE_ON: | ||
171 | Set22K (budget, 1); | ||
172 | break; | ||
173 | |||
174 | case SEC_TONE_OFF: | ||
175 | Set22K (budget, 0); | ||
176 | break; | ||
177 | |||
178 | default: | ||
179 | return -EINVAL; | ||
180 | } | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) | ||
186 | { | ||
187 | struct budget* budget = (struct budget*) fe->dvb->priv; | ||
188 | |||
189 | SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0); | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) | ||
195 | { | ||
196 | struct budget* budget = (struct budget*) fe->dvb->priv; | ||
197 | |||
198 | SendDiSEqCMsg (budget, 0, NULL, minicmd); | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) | ||
204 | { | ||
205 | struct budget* budget = (struct budget*) fe->dvb->priv; | ||
206 | u8 pwr = 0; | ||
207 | u8 buf[4]; | ||
208 | struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; | ||
209 | u32 div = (params->frequency + 479500) / 125; | ||
210 | |||
211 | if (params->frequency > 2000000) pwr = 3; | ||
212 | else if (params->frequency > 1800000) pwr = 2; | ||
213 | else if (params->frequency > 1600000) pwr = 1; | ||
214 | else if (params->frequency > 1200000) pwr = 0; | ||
215 | else if (params->frequency >= 1100000) pwr = 1; | ||
216 | else pwr = 2; | ||
217 | |||
218 | buf[0] = (div >> 8) & 0x7f; | ||
219 | buf[1] = div & 0xff; | ||
220 | buf[2] = ((div & 0x18000) >> 10) | 0x95; | ||
221 | buf[3] = (pwr << 6) | 0x30; | ||
222 | |||
223 | // NOTE: since we're using a prescaler of 2, we set the | ||
224 | // divisor frequency to 62.5kHz and divide by 125 above | ||
225 | |||
226 | if (fe->ops.i2c_gate_ctrl) | ||
227 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
228 | if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static struct ves1x93_config alps_bsrv2_config = | ||
233 | { | ||
234 | .demod_address = 0x08, | ||
235 | .xin = 90100000UL, | ||
236 | .invert_pwm = 0, | ||
237 | }; | ||
238 | |||
239 | static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) | ||
240 | { | ||
241 | struct budget* budget = (struct budget*) fe->dvb->priv; | ||
242 | u32 div; | ||
243 | u8 data[4]; | ||
244 | struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) }; | ||
245 | |||
246 | div = (params->frequency + 35937500 + 31250) / 62500; | ||
247 | |||
248 | data[0] = (div >> 8) & 0x7f; | ||
249 | data[1] = div & 0xff; | ||
250 | data[2] = 0x85 | ((div >> 10) & 0x60); | ||
251 | data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81); | ||
252 | |||
253 | if (fe->ops.i2c_gate_ctrl) | ||
254 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
255 | if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static struct ves1820_config alps_tdbe2_config = { | ||
260 | .demod_address = 0x09, | ||
261 | .xin = 57840000UL, | ||
262 | .invert = 1, | ||
263 | .selagc = VES1820_SELAGC_SIGNAMPERR, | ||
264 | }; | ||
265 | |||
266 | static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) | ||
267 | { | ||
268 | struct budget *budget = fe->dvb->priv; | ||
269 | u8 *tuner_addr = fe->tuner_priv; | ||
270 | u32 div; | ||
271 | u8 cfg, cpump, band_select; | ||
272 | u8 data[4]; | ||
273 | struct i2c_msg msg = { .flags = 0, .buf = data, .len = sizeof(data) }; | ||
274 | |||
275 | if (tuner_addr) | ||
276 | msg.addr = *tuner_addr; | ||
277 | else | ||
278 | msg.addr = 0x61; | ||
279 | |||
280 | div = (36125000 + params->frequency) / 166666; | ||
281 | |||
282 | cfg = 0x88; | ||
283 | |||
284 | if (params->frequency < 175000000) cpump = 2; | ||
285 | else if (params->frequency < 390000000) cpump = 1; | ||
286 | else if (params->frequency < 470000000) cpump = 2; | ||
287 | else if (params->frequency < 750000000) cpump = 1; | ||
288 | else cpump = 3; | ||
289 | |||
290 | if (params->frequency < 175000000) band_select = 0x0e; | ||
291 | else if (params->frequency < 470000000) band_select = 0x05; | ||
292 | else band_select = 0x03; | ||
293 | |||
294 | data[0] = (div >> 8) & 0x7f; | ||
295 | data[1] = div & 0xff; | ||
296 | data[2] = ((div >> 10) & 0x60) | cfg; | ||
297 | data[3] = (cpump << 6) | band_select; | ||
298 | |||
299 | if (fe->ops.i2c_gate_ctrl) | ||
300 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
301 | if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; | ||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | static struct l64781_config grundig_29504_401_config = { | ||
306 | .demod_address = 0x55, | ||
307 | }; | ||
308 | |||
309 | static struct l64781_config grundig_29504_401_config_activy = { | ||
310 | .demod_address = 0x54, | ||
311 | }; | ||
312 | |||
313 | static u8 tuner_address_grundig_29504_401_activy = 0x60; | ||
314 | |||
315 | static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) | ||
316 | { | ||
317 | struct budget* budget = (struct budget*) fe->dvb->priv; | ||
318 | u32 div; | ||
319 | u8 data[4]; | ||
320 | struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; | ||
321 | |||
322 | div = params->frequency / 125; | ||
323 | data[0] = (div >> 8) & 0x7f; | ||
324 | data[1] = div & 0xff; | ||
325 | data[2] = 0x8e; | ||
326 | data[3] = 0x00; | ||
327 | |||
328 | if (fe->ops.i2c_gate_ctrl) | ||
329 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
330 | if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; | ||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | static struct tda8083_config grundig_29504_451_config = { | ||
335 | .demod_address = 0x68, | ||
336 | }; | ||
337 | |||
338 | static int s5h1420_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) | ||
339 | { | ||
340 | struct budget* budget = (struct budget*) fe->dvb->priv; | ||
341 | u32 div; | ||
342 | u8 data[4]; | ||
343 | struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; | ||
344 | |||
345 | div = params->frequency / 1000; | ||
346 | data[0] = (div >> 8) & 0x7f; | ||
347 | data[1] = div & 0xff; | ||
348 | data[2] = 0xc2; | ||
349 | |||
350 | if (div < 1450) | ||
351 | data[3] = 0x00; | ||
352 | else if (div < 1850) | ||
353 | data[3] = 0x40; | ||
354 | else if (div < 2000) | ||
355 | data[3] = 0x80; | ||
356 | else | ||
357 | data[3] = 0xc0; | ||
358 | |||
359 | if (fe->ops.i2c_gate_ctrl) | ||
360 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
361 | if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; | ||
362 | |||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | static struct s5h1420_config s5h1420_config = { | ||
367 | .demod_address = 0x53, | ||
368 | .invert = 1, | ||
369 | .cdclk_polarity = 1, | ||
370 | }; | ||
371 | |||
372 | static struct tda10086_config tda10086_config = { | ||
373 | .demod_address = 0x0e, | ||
374 | .invert = 0, | ||
375 | .diseqc_tone = 1, | ||
376 | .xtal_freq = TDA10086_XTAL_16M, | ||
377 | }; | ||
378 | |||
379 | static struct stv0299_config alps_bsru6_config_activy = { | ||
380 | .demod_address = 0x68, | ||
381 | .inittab = alps_bsru6_inittab, | ||
382 | .mclk = 88000000UL, | ||
383 | .invert = 1, | ||
384 | .op0_off = 1, | ||
385 | .min_delay_ms = 100, | ||
386 | .set_symbol_rate = alps_bsru6_set_symbol_rate, | ||
387 | }; | ||
388 | |||
389 | static struct stv0299_config alps_bsbe1_config_activy = { | ||
390 | .demod_address = 0x68, | ||
391 | .inittab = alps_bsbe1_inittab, | ||
392 | .mclk = 88000000UL, | ||
393 | .invert = 1, | ||
394 | .op0_off = 1, | ||
395 | .min_delay_ms = 100, | ||
396 | .set_symbol_rate = alps_bsbe1_set_symbol_rate, | ||
397 | }; | ||
398 | |||
399 | static int alps_tdhd1_204_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name) | ||
400 | { | ||
401 | struct budget *budget = (struct budget *)fe->dvb->priv; | ||
402 | |||
403 | return request_firmware(fw, name, &budget->dev->pci->dev); | ||
404 | } | ||
405 | |||
406 | |||
407 | static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg) | ||
408 | { | ||
409 | u8 val; | ||
410 | struct i2c_msg msg[] = { | ||
411 | { .addr = adr, .flags = 0, .buf = ®, .len = 1 }, | ||
412 | { .addr = adr, .flags = I2C_M_RD, .buf = &val, .len = 1 } | ||
413 | }; | ||
414 | |||
415 | return (i2c_transfer(i2c, msg, 2) != 2) ? -EIO : val; | ||
416 | } | ||
417 | |||
418 | static u8 read_pwm(struct budget* budget) | ||
419 | { | ||
420 | u8 b = 0xff; | ||
421 | u8 pwm; | ||
422 | struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 }, | ||
423 | { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} }; | ||
424 | |||
425 | if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff)) | ||
426 | pwm = 0x48; | ||
427 | |||
428 | return pwm; | ||
429 | } | ||
430 | |||
431 | static struct stv090x_config tt1600_stv090x_config = { | ||
432 | .device = STV0903, | ||
433 | .demod_mode = STV090x_SINGLE, | ||
434 | .clk_mode = STV090x_CLK_EXT, | ||
435 | |||
436 | .xtal = 13500000, | ||
437 | .address = 0x68, | ||
438 | |||
439 | .ts1_mode = STV090x_TSMODE_DVBCI, | ||
440 | .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, | ||
441 | |||
442 | .repeater_level = STV090x_RPTLEVEL_16, | ||
443 | |||
444 | .tuner_init = NULL, | ||
445 | .tuner_sleep = NULL, | ||
446 | .tuner_set_mode = NULL, | ||
447 | .tuner_set_frequency = NULL, | ||
448 | .tuner_get_frequency = NULL, | ||
449 | .tuner_set_bandwidth = NULL, | ||
450 | .tuner_get_bandwidth = NULL, | ||
451 | .tuner_set_bbgain = NULL, | ||
452 | .tuner_get_bbgain = NULL, | ||
453 | .tuner_set_refclk = NULL, | ||
454 | .tuner_get_status = NULL, | ||
455 | }; | ||
456 | |||
457 | static struct stv6110x_config tt1600_stv6110x_config = { | ||
458 | .addr = 0x60, | ||
459 | .refclk = 27000000, | ||
460 | .clk_div = 2, | ||
461 | }; | ||
462 | |||
463 | static struct isl6423_config tt1600_isl6423_config = { | ||
464 | .current_max = SEC_CURRENT_515m, | ||
465 | .curlim = SEC_CURRENT_LIM_ON, | ||
466 | .mod_extern = 1, | ||
467 | .addr = 0x08, | ||
468 | }; | ||
469 | |||
470 | static void frontend_init(struct budget *budget) | ||
471 | { | ||
472 | (void)alps_bsbe1_config; /* avoid warning */ | ||
473 | |||
474 | switch(budget->dev->pci->subsystem_device) { | ||
475 | case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659)) | ||
476 | case 0x1013: | ||
477 | // try the ALPS BSRV2 first of all | ||
478 | budget->dvb_frontend = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &budget->i2c_adap); | ||
479 | if (budget->dvb_frontend) { | ||
480 | budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params; | ||
481 | budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd; | ||
482 | budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst; | ||
483 | budget->dvb_frontend->ops.set_tone = budget_set_tone; | ||
484 | break; | ||
485 | } | ||
486 | |||
487 | // try the ALPS BSRU6 now | ||
488 | budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap); | ||
489 | if (budget->dvb_frontend) { | ||
490 | budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; | ||
491 | budget->dvb_frontend->tuner_priv = &budget->i2c_adap; | ||
492 | if (budget->dev->pci->subsystem_device == 0x1003 && diseqc_method == 0) { | ||
493 | budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd; | ||
494 | budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst; | ||
495 | budget->dvb_frontend->ops.set_tone = budget_set_tone; | ||
496 | } | ||
497 | break; | ||
498 | } | ||
499 | break; | ||
500 | |||
501 | case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659)) | ||
502 | |||
503 | budget->dvb_frontend = dvb_attach(ves1820_attach, &alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget)); | ||
504 | if (budget->dvb_frontend) { | ||
505 | budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params; | ||
506 | break; | ||
507 | } | ||
508 | break; | ||
509 | |||
510 | case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060)) | ||
511 | |||
512 | budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config, &budget->i2c_adap); | ||
513 | if (budget->dvb_frontend) { | ||
514 | budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params; | ||
515 | budget->dvb_frontend->tuner_priv = NULL; | ||
516 | break; | ||
517 | } | ||
518 | break; | ||
519 | |||
520 | case 0x4f60: /* Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/tsa5059) */ | ||
521 | { | ||
522 | int subtype = i2c_readreg(&budget->i2c_adap, 0x50, 0x67); | ||
523 | |||
524 | if (subtype < 0) | ||
525 | break; | ||
526 | /* fixme: find a better way to identify the card */ | ||
527 | if (subtype < 0x36) { | ||
528 | /* assume ALPS BSRU6 */ | ||
529 | budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config_activy, &budget->i2c_adap); | ||
530 | if (budget->dvb_frontend) { | ||
531 | printk(KERN_INFO "budget: tuner ALPS BSRU6 detected\n"); | ||
532 | budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; | ||
533 | budget->dvb_frontend->tuner_priv = &budget->i2c_adap; | ||
534 | budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage; | ||
535 | budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL; | ||
536 | break; | ||
537 | } | ||
538 | } else { | ||
539 | /* assume ALPS BSBE1 */ | ||
540 | /* reset tuner */ | ||
541 | saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTLO); | ||
542 | msleep(50); | ||
543 | saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTHI); | ||
544 | msleep(250); | ||
545 | budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config_activy, &budget->i2c_adap); | ||
546 | if (budget->dvb_frontend) { | ||
547 | printk(KERN_INFO "budget: tuner ALPS BSBE1 detected\n"); | ||
548 | budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params; | ||
549 | budget->dvb_frontend->tuner_priv = &budget->i2c_adap; | ||
550 | budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage; | ||
551 | budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL; | ||
552 | break; | ||
553 | } | ||
554 | } | ||
555 | break; | ||
556 | } | ||
557 | |||
558 | case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522)) | ||
559 | budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap); | ||
560 | if (budget->dvb_frontend) { | ||
561 | budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params; | ||
562 | budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage; | ||
563 | budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL; | ||
564 | } | ||
565 | break; | ||
566 | |||
567 | case 0x5f60: /* Fujitsu Siemens Activy Budget-T PCI rev AL (tda10046/ALPS TDHD1-204A) */ | ||
568 | budget->dvb_frontend = dvb_attach(tda10046_attach, &alps_tdhd1_204a_config, &budget->i2c_adap); | ||
569 | if (budget->dvb_frontend) { | ||
570 | budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdhd1_204a_tuner_set_params; | ||
571 | budget->dvb_frontend->tuner_priv = &budget->i2c_adap; | ||
572 | } | ||
573 | break; | ||
574 | |||
575 | case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */ | ||
576 | budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap); | ||
577 | if (budget->dvb_frontend) { | ||
578 | budget->dvb_frontend->tuner_priv = &tuner_address_grundig_29504_401_activy; | ||
579 | budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params; | ||
580 | } | ||
581 | break; | ||
582 | |||
583 | case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260)) | ||
584 | budget->dvb_frontend = dvb_attach(s5h1420_attach, &s5h1420_config, &budget->i2c_adap); | ||
585 | if (budget->dvb_frontend) { | ||
586 | budget->dvb_frontend->ops.tuner_ops.set_params = s5h1420_tuner_set_params; | ||
587 | if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) { | ||
588 | printk("%s: No LNBP21 found!\n", __func__); | ||
589 | goto error_out; | ||
590 | } | ||
591 | break; | ||
592 | } | ||
593 | |||
594 | case 0x1018: // TT Budget-S-1401 (philips tda10086/philips tda8262) | ||
595 | // gpio2 is connected to CLB - reset it + leave it high | ||
596 | saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO); | ||
597 | msleep(1); | ||
598 | saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI); | ||
599 | msleep(1); | ||
600 | |||
601 | budget->dvb_frontend = dvb_attach(tda10086_attach, &tda10086_config, &budget->i2c_adap); | ||
602 | if (budget->dvb_frontend) { | ||
603 | if (dvb_attach(tda826x_attach, budget->dvb_frontend, 0x60, &budget->i2c_adap, 0) == NULL) | ||
604 | printk("%s: No tda826x found!\n", __func__); | ||
605 | if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) { | ||
606 | printk("%s: No LNBP21 found!\n", __func__); | ||
607 | goto error_out; | ||
608 | } | ||
609 | break; | ||
610 | } | ||
611 | |||
612 | case 0x101c: { /* TT S2-1600 */ | ||
613 | struct stv6110x_devctl *ctl; | ||
614 | saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO); | ||
615 | msleep(50); | ||
616 | saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI); | ||
617 | msleep(250); | ||
618 | |||
619 | budget->dvb_frontend = dvb_attach(stv090x_attach, | ||
620 | &tt1600_stv090x_config, | ||
621 | &budget->i2c_adap, | ||
622 | STV090x_DEMODULATOR_0); | ||
623 | |||
624 | if (budget->dvb_frontend) { | ||
625 | |||
626 | ctl = dvb_attach(stv6110x_attach, | ||
627 | budget->dvb_frontend, | ||
628 | &tt1600_stv6110x_config, | ||
629 | &budget->i2c_adap); | ||
630 | |||
631 | if (ctl) { | ||
632 | tt1600_stv090x_config.tuner_init = ctl->tuner_init; | ||
633 | tt1600_stv090x_config.tuner_sleep = ctl->tuner_sleep; | ||
634 | tt1600_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; | ||
635 | tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; | ||
636 | tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; | ||
637 | tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; | ||
638 | tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; | ||
639 | tt1600_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; | ||
640 | tt1600_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; | ||
641 | tt1600_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; | ||
642 | tt1600_stv090x_config.tuner_get_status = ctl->tuner_get_status; | ||
643 | |||
644 | /* call the init function once to initialize | ||
645 | tuner's clock output divider and demod's | ||
646 | master clock */ | ||
647 | if (budget->dvb_frontend->ops.init) | ||
648 | budget->dvb_frontend->ops.init(budget->dvb_frontend); | ||
649 | |||
650 | if (dvb_attach(isl6423_attach, | ||
651 | budget->dvb_frontend, | ||
652 | &budget->i2c_adap, | ||
653 | &tt1600_isl6423_config) == NULL) { | ||
654 | printk(KERN_ERR "%s: No Intersil ISL6423 found!\n", __func__); | ||
655 | goto error_out; | ||
656 | } | ||
657 | } else { | ||
658 | printk(KERN_ERR "%s: No STV6110(A) Silicon Tuner found!\n", __func__); | ||
659 | goto error_out; | ||
660 | } | ||
661 | } | ||
662 | } | ||
663 | break; | ||
664 | } | ||
665 | |||
666 | if (budget->dvb_frontend == NULL) { | ||
667 | printk("budget: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n", | ||
668 | budget->dev->pci->vendor, | ||
669 | budget->dev->pci->device, | ||
670 | budget->dev->pci->subsystem_vendor, | ||
671 | budget->dev->pci->subsystem_device); | ||
672 | } else { | ||
673 | if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) | ||
674 | goto error_out; | ||
675 | } | ||
676 | return; | ||
677 | |||
678 | error_out: | ||
679 | printk("budget: Frontend registration failed!\n"); | ||
680 | dvb_frontend_detach(budget->dvb_frontend); | ||
681 | budget->dvb_frontend = NULL; | ||
682 | return; | ||
683 | } | ||
684 | |||
685 | static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) | ||
686 | { | ||
687 | struct budget *budget = NULL; | ||
688 | int err; | ||
689 | |||
690 | budget = kmalloc(sizeof(struct budget), GFP_KERNEL); | ||
691 | if( NULL == budget ) { | ||
692 | return -ENOMEM; | ||
693 | } | ||
694 | |||
695 | dprintk(2, "dev:%p, info:%p, budget:%p\n", dev, info, budget); | ||
696 | |||
697 | dev->ext_priv = budget; | ||
698 | |||
699 | err = ttpci_budget_init(budget, dev, info, THIS_MODULE, adapter_nr); | ||
700 | if (err) { | ||
701 | printk("==> failed\n"); | ||
702 | kfree (budget); | ||
703 | return err; | ||
704 | } | ||
705 | |||
706 | budget->dvb_adapter.priv = budget; | ||
707 | frontend_init(budget); | ||
708 | |||
709 | ttpci_budget_init_hooks(budget); | ||
710 | |||
711 | return 0; | ||
712 | } | ||
713 | |||
714 | static int budget_detach (struct saa7146_dev* dev) | ||
715 | { | ||
716 | struct budget *budget = (struct budget*) dev->ext_priv; | ||
717 | int err; | ||
718 | |||
719 | if (budget->dvb_frontend) { | ||
720 | dvb_unregister_frontend(budget->dvb_frontend); | ||
721 | dvb_frontend_detach(budget->dvb_frontend); | ||
722 | } | ||
723 | |||
724 | err = ttpci_budget_deinit (budget); | ||
725 | |||
726 | kfree (budget); | ||
727 | dev->ext_priv = NULL; | ||
728 | |||
729 | return err; | ||
730 | } | ||
731 | |||
732 | static struct saa7146_extension budget_extension; | ||
733 | |||
734 | MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT); | ||
735 | MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT); | ||
736 | MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT); | ||
737 | MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC); | ||
738 | MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT); | ||
739 | MAKE_BUDGET_INFO(tt1600, "TT-Budget S2-1600 PCI", BUDGET_TT); | ||
740 | MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY); | ||
741 | MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY); | ||
742 | MAKE_BUDGET_INFO(fsact, "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY); | ||
743 | MAKE_BUDGET_INFO(fsact1, "Fujitsu Siemens Activy Budget-T PCI (rev AL/ALPS TDHD1-204A)", BUDGET_FS_ACTIVY); | ||
744 | |||
745 | static struct pci_device_id pci_tbl[] = { | ||
746 | MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003), | ||
747 | MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004), | ||
748 | MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005), | ||
749 | MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013), | ||
750 | MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1016), | ||
751 | MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018), | ||
752 | MAKE_EXTENSION_PCI(tt1600, 0x13c2, 0x101c), | ||
753 | MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60), | ||
754 | MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61), | ||
755 | MAKE_EXTENSION_PCI(fsact1, 0x1131, 0x5f60), | ||
756 | MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61), | ||
757 | { | ||
758 | .vendor = 0, | ||
759 | } | ||
760 | }; | ||
761 | |||
762 | MODULE_DEVICE_TABLE(pci, pci_tbl); | ||
763 | |||
764 | static struct saa7146_extension budget_extension = { | ||
765 | .name = "budget dvb", | ||
766 | .flags = SAA7146_USE_I2C_IRQ, | ||
767 | |||
768 | .module = THIS_MODULE, | ||
769 | .pci_tbl = pci_tbl, | ||
770 | .attach = budget_attach, | ||
771 | .detach = budget_detach, | ||
772 | |||
773 | .irq_mask = MASK_10, | ||
774 | .irq_func = ttpci_budget_irq10_handler, | ||
775 | }; | ||
776 | |||
777 | static int __init budget_init(void) | ||
778 | { | ||
779 | return saa7146_register_extension(&budget_extension); | ||
780 | } | ||
781 | |||
782 | static void __exit budget_exit(void) | ||
783 | { | ||
784 | saa7146_unregister_extension(&budget_extension); | ||
785 | } | ||
786 | |||
787 | module_init(budget_init); | ||
788 | module_exit(budget_exit); | ||
789 | |||
790 | MODULE_LICENSE("GPL"); | ||
791 | MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others"); | ||
792 | MODULE_DESCRIPTION("driver for the SAA7146 based so-called " | ||
793 | "budget PCI DVB cards by Siemens, Technotrend, Hauppauge"); | ||