diff options
author | Andrew de Quincey <adq_dvb@lidskialf.net> | 2006-08-08 08:10:10 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-09-26 10:53:30 -0400 |
commit | 6bca3580c3303451b65afc98276edf40628dffe0 (patch) | |
tree | 95e9e6dd94ebaa2b286b6119e627306dc20ee470 | |
parent | 2cd885aa0f35e9329292e5be2a6c9d424bba5531 (diff) |
V4L/DVB (4396): Add drivers for tda10086 + tda826x chips
TDA10086 is a new DVB-S demodulator
TDA826x is a DVB-S Silicon Tuner
Signed-off-by: Andrew de Quincey <adq_dvb@lidskialf.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r-- | drivers/media/dvb/frontends/Kconfig | 16 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/tda10086.c | 740 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/tda10086.h | 41 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/tda826x.c | 160 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/tda826x.h | 40 |
6 files changed, 999 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index db978555b1eb..5cf96c2e605a 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig | |||
@@ -46,6 +46,13 @@ config DVB_S5H1420 | |||
46 | help | 46 | help |
47 | A DVB-S tuner module. Say Y when you want to support this frontend. | 47 | A DVB-S tuner module. Say Y when you want to support this frontend. |
48 | 48 | ||
49 | config DVB_TDA10086 | ||
50 | tristate "Philips TDA10086 based" | ||
51 | depends on DVB_CORE | ||
52 | default m if DVB_FE_CUSTOMISE | ||
53 | help | ||
54 | A DVB-S tuner module. Say Y when you want to support this frontend. | ||
55 | |||
49 | comment "DVB-T (terrestrial) frontends" | 56 | comment "DVB-T (terrestrial) frontends" |
50 | depends on DVB_CORE | 57 | depends on DVB_CORE |
51 | 58 | ||
@@ -216,6 +223,15 @@ config DVB_LGDT330X | |||
216 | An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want | 223 | An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want |
217 | to support this frontend. | 224 | to support this frontend. |
218 | 225 | ||
226 | comment "Tuners/PLL support" | ||
227 | depends on DVB_CORE | ||
228 | |||
229 | config DVB_TDA826X | ||
230 | tristate "Philips TDA826X silicon tuner" | ||
231 | depends on DVB_CORE | ||
232 | default m if DVB_FE_CUSTOMISE | ||
233 | help | ||
234 | A DVB-S silicon tuner module. Say Y when you want to support this tuner. | ||
219 | 235 | ||
220 | comment "Miscellaneous devices" | 236 | comment "Miscellaneous devices" |
221 | depends on DVB_CORE | 237 | depends on DVB_CORE |
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 0e4880b6db14..646aa6d1487d 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
@@ -33,3 +33,5 @@ obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o | |||
33 | obj-$(CONFIG_DVB_CX24123) += cx24123.o | 33 | obj-$(CONFIG_DVB_CX24123) += cx24123.o |
34 | obj-$(CONFIG_DVB_LNBP21) += lnbp21.o | 34 | obj-$(CONFIG_DVB_LNBP21) += lnbp21.o |
35 | obj-$(CONFIG_DVB_ISL6421) += isl6421.o | 35 | obj-$(CONFIG_DVB_ISL6421) += isl6421.o |
36 | obj-$(CONFIG_DVB_TDA10086) += tda10086.o | ||
37 | obj-$(CONFIG_DVB_TDA826X) += tda826x.o | ||
diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c new file mode 100644 index 000000000000..5d18eba5c649 --- /dev/null +++ b/drivers/media/dvb/frontends/tda10086.c | |||
@@ -0,0 +1,740 @@ | |||
1 | /* | ||
2 | Driver for Philips tda10086 DVBS Demodulator | ||
3 | |||
4 | (c) 2006 Andrew de Quincey | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | |||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | */ | ||
22 | |||
23 | #include <linux/init.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/moduleparam.h> | ||
26 | #include <linux/device.h> | ||
27 | #include <linux/jiffies.h> | ||
28 | #include <linux/string.h> | ||
29 | #include <linux/slab.h> | ||
30 | |||
31 | #include "dvb_frontend.h" | ||
32 | #include "tda10086.h" | ||
33 | |||
34 | #define SACLK 96000000 | ||
35 | |||
36 | struct tda10086_state { | ||
37 | struct i2c_adapter* i2c; | ||
38 | const struct tda10086_config* config; | ||
39 | struct dvb_frontend frontend; | ||
40 | |||
41 | /* private demod data */ | ||
42 | u32 frequency; | ||
43 | u32 symbol_rate; | ||
44 | }; | ||
45 | |||
46 | static int debug = 1; | ||
47 | #define dprintk(args...) \ | ||
48 | do { \ | ||
49 | if (debug) printk(KERN_DEBUG "tda10086: " args); \ | ||
50 | } while (0) | ||
51 | |||
52 | static int tda10086_write_byte(struct tda10086_state *state, int reg, int data) | ||
53 | { | ||
54 | int ret; | ||
55 | u8 b0[] = { reg, data }; | ||
56 | struct i2c_msg msg = { .flags = 0, .buf = b0, .len = 2 }; | ||
57 | |||
58 | msg.addr = state->config->demod_address; | ||
59 | ret = i2c_transfer(state->i2c, &msg, 1); | ||
60 | |||
61 | if (ret != 1) | ||
62 | dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n", | ||
63 | __FUNCTION__, reg, data, ret); | ||
64 | |||
65 | return (ret != 1) ? ret : 0; | ||
66 | } | ||
67 | |||
68 | static int tda10086_read_byte(struct tda10086_state *state, int reg) | ||
69 | { | ||
70 | int ret; | ||
71 | u8 b0[] = { reg }; | ||
72 | u8 b1[] = { 0 }; | ||
73 | struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 }, | ||
74 | { .flags = I2C_M_RD, .buf = b1, .len = 1 }}; | ||
75 | |||
76 | msg[0].addr = state->config->demod_address; | ||
77 | msg[1].addr = state->config->demod_address; | ||
78 | ret = i2c_transfer(state->i2c, msg, 2); | ||
79 | |||
80 | if (ret != 2) { | ||
81 | dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg, | ||
82 | ret); | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | return b1[0]; | ||
87 | } | ||
88 | |||
89 | static int tda10086_write_mask(struct tda10086_state *state, int reg, int mask, int data) | ||
90 | { | ||
91 | int val; | ||
92 | |||
93 | // read a byte and check | ||
94 | val = tda10086_read_byte(state, reg); | ||
95 | if (val < 0) | ||
96 | return val; | ||
97 | |||
98 | // mask if off | ||
99 | val = val & ~mask; | ||
100 | val |= data & 0xff; | ||
101 | |||
102 | // write it out again | ||
103 | return tda10086_write_byte(state, reg, val); | ||
104 | } | ||
105 | |||
106 | static int tda10086_init(struct dvb_frontend* fe) | ||
107 | { | ||
108 | struct tda10086_state* state = fe->demodulator_priv; | ||
109 | |||
110 | dprintk ("%s\n", __FUNCTION__); | ||
111 | |||
112 | // reset | ||
113 | tda10086_write_byte(state, 0x00, 0x00); | ||
114 | msleep(10); | ||
115 | |||
116 | // misc setup | ||
117 | tda10086_write_byte(state, 0x01, 0x94); | ||
118 | tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP | ||
119 | tda10086_write_byte(state, 0x03, 0x64); | ||
120 | tda10086_write_byte(state, 0x04, 0x43); | ||
121 | tda10086_write_byte(state, 0x0c, 0x0c); | ||
122 | tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold | ||
123 | tda10086_write_byte(state, 0x20, 0x89); // misc | ||
124 | tda10086_write_byte(state, 0x30, 0x04); // acquisition period length | ||
125 | tda10086_write_byte(state, 0x32, 0x00); // irq off | ||
126 | tda10086_write_byte(state, 0x31, 0x56); // setup AFC | ||
127 | |||
128 | // setup PLL (assumes 16Mhz XIN) | ||
129 | tda10086_write_byte(state, 0x55, 0x2c); // misc PLL setup | ||
130 | tda10086_write_byte(state, 0x3a, 0x0b); // M=12 | ||
131 | tda10086_write_byte(state, 0x3b, 0x01); // P=2 | ||
132 | tda10086_write_mask(state, 0x55, 0x20, 0x00); // powerup PLL | ||
133 | |||
134 | // setup TS interface | ||
135 | tda10086_write_byte(state, 0x11, 0x81); | ||
136 | tda10086_write_byte(state, 0x12, 0x81); | ||
137 | tda10086_write_byte(state, 0x19, 0x40); // parallel mode A + MSBFIRST | ||
138 | tda10086_write_byte(state, 0x56, 0x80); // powerdown WPLL - unused in the mode we use | ||
139 | tda10086_write_byte(state, 0x57, 0x08); // bypass WPLL - unused in the mode we use | ||
140 | tda10086_write_byte(state, 0x10, 0x2a); | ||
141 | |||
142 | // setup ADC | ||
143 | tda10086_write_byte(state, 0x58, 0x61); // ADC setup | ||
144 | tda10086_write_mask(state, 0x58, 0x01, 0x00); // powerup ADC | ||
145 | |||
146 | // setup AGC | ||
147 | tda10086_write_byte(state, 0x05, 0x0B); | ||
148 | tda10086_write_byte(state, 0x37, 0x63); | ||
149 | tda10086_write_byte(state, 0x3f, 0x03); // NOTE: flydvb uses 0x0a and varies it | ||
150 | tda10086_write_byte(state, 0x40, 0x64); | ||
151 | tda10086_write_byte(state, 0x41, 0x4f); | ||
152 | tda10086_write_byte(state, 0x42, 0x43); | ||
153 | |||
154 | // setup viterbi | ||
155 | tda10086_write_byte(state, 0x1a, 0x11); // VBER 10^6, DVB, QPSK | ||
156 | |||
157 | // setup carrier recovery | ||
158 | tda10086_write_byte(state, 0x3d, 0x80); | ||
159 | |||
160 | // setup SEC | ||
161 | tda10086_write_byte(state, 0x36, 0x00); // all SEC off | ||
162 | tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000))); // } tone frequency | ||
163 | tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8); // } | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static void tda10086_diseqc_wait(struct tda10086_state *state) | ||
169 | { | ||
170 | unsigned long timeout = jiffies + msecs_to_jiffies(200); | ||
171 | while (!(tda10086_read_byte(state, 0x50) & 0x01)) { | ||
172 | if(time_after(jiffies, timeout)) { | ||
173 | printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__); | ||
174 | break; | ||
175 | } | ||
176 | msleep(10); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | ||
181 | { | ||
182 | struct tda10086_state* state = fe->demodulator_priv; | ||
183 | |||
184 | dprintk ("%s\n", __FUNCTION__); | ||
185 | |||
186 | switch(tone) { | ||
187 | case SEC_TONE_OFF: | ||
188 | tda10086_write_byte(state, 0x36, 0x00); | ||
189 | break; | ||
190 | |||
191 | case SEC_TONE_ON: | ||
192 | tda10086_write_byte(state, 0x36, 0x01); | ||
193 | break; | ||
194 | } | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static int tda10086_send_master_cmd (struct dvb_frontend* fe, | ||
200 | struct dvb_diseqc_master_cmd* cmd) | ||
201 | { | ||
202 | struct tda10086_state* state = fe->demodulator_priv; | ||
203 | int i; | ||
204 | u8 oldval; | ||
205 | |||
206 | dprintk ("%s\n", __FUNCTION__); | ||
207 | |||
208 | if (cmd->msg_len > 6) | ||
209 | return -EINVAL; | ||
210 | oldval = tda10086_read_byte(state, 0x36); | ||
211 | |||
212 | for(i=0; i< cmd->msg_len; i++) { | ||
213 | tda10086_write_byte(state, 0x48+i, cmd->msg[i]); | ||
214 | } | ||
215 | tda10086_write_byte(state, 0x36, 0x08 | ((cmd->msg_len + 1) << 4)); | ||
216 | |||
217 | tda10086_diseqc_wait(state); | ||
218 | |||
219 | tda10086_write_byte(state, 0x36, oldval); | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) | ||
225 | { | ||
226 | struct tda10086_state* state = fe->demodulator_priv; | ||
227 | u8 oldval = tda10086_read_byte(state, 0x36); | ||
228 | |||
229 | dprintk ("%s\n", __FUNCTION__); | ||
230 | |||
231 | switch(minicmd) { | ||
232 | case SEC_MINI_A: | ||
233 | tda10086_write_byte(state, 0x36, 0x04); | ||
234 | break; | ||
235 | |||
236 | case SEC_MINI_B: | ||
237 | tda10086_write_byte(state, 0x36, 0x06); | ||
238 | break; | ||
239 | } | ||
240 | |||
241 | tda10086_diseqc_wait(state); | ||
242 | |||
243 | tda10086_write_byte(state, 0x36, oldval); | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static int tda10086_set_inversion(struct tda10086_state *state, | ||
249 | struct dvb_frontend_parameters *fe_params) | ||
250 | { | ||
251 | u8 invval = 0x80; | ||
252 | |||
253 | dprintk ("%s %i %i\n", __FUNCTION__, fe_params->inversion, state->config->invert); | ||
254 | |||
255 | switch(fe_params->inversion) { | ||
256 | case INVERSION_OFF: | ||
257 | if (state->config->invert) | ||
258 | invval = 0x40; | ||
259 | break; | ||
260 | case INVERSION_ON: | ||
261 | if (!state->config->invert) | ||
262 | invval = 0x40; | ||
263 | break; | ||
264 | case INVERSION_AUTO: | ||
265 | invval = 0x00; | ||
266 | break; | ||
267 | } | ||
268 | tda10086_write_mask(state, 0x0c, 0xc0, invval); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int tda10086_set_symbol_rate(struct tda10086_state *state, | ||
274 | struct dvb_frontend_parameters *fe_params) | ||
275 | { | ||
276 | u8 dfn = 0; | ||
277 | u8 afs = 0; | ||
278 | u8 byp = 0; | ||
279 | u8 reg37 = 0x43; | ||
280 | u8 reg42 = 0x43; | ||
281 | u64 big; | ||
282 | u32 tmp; | ||
283 | u32 bdr; | ||
284 | u32 bdri; | ||
285 | u32 symbol_rate = fe_params->u.qpsk.symbol_rate; | ||
286 | |||
287 | dprintk ("%s %i\n", __FUNCTION__, symbol_rate); | ||
288 | |||
289 | // setup the decimation and anti-aliasing filters.. | ||
290 | if (symbol_rate < (u32) (SACLK * 0.0137)) { | ||
291 | dfn=4; | ||
292 | afs=1; | ||
293 | } else if (symbol_rate < (u32) (SACLK * 0.0208)) { | ||
294 | dfn=4; | ||
295 | afs=0; | ||
296 | } else if (symbol_rate < (u32) (SACLK * 0.0270)) { | ||
297 | dfn=3; | ||
298 | afs=1; | ||
299 | } else if (symbol_rate < (u32) (SACLK * 0.0416)) { | ||
300 | dfn=3; | ||
301 | afs=0; | ||
302 | } else if (symbol_rate < (u32) (SACLK * 0.0550)) { | ||
303 | dfn=2; | ||
304 | afs=1; | ||
305 | } else if (symbol_rate < (u32) (SACLK * 0.0833)) { | ||
306 | dfn=2; | ||
307 | afs=0; | ||
308 | } else if (symbol_rate < (u32) (SACLK * 0.1100)) { | ||
309 | dfn=1; | ||
310 | afs=1; | ||
311 | } else if (symbol_rate < (u32) (SACLK * 0.1666)) { | ||
312 | dfn=1; | ||
313 | afs=0; | ||
314 | } else if (symbol_rate < (u32) (SACLK * 0.2200)) { | ||
315 | dfn=0; | ||
316 | afs=1; | ||
317 | } else if (symbol_rate < (u32) (SACLK * 0.3333)) { | ||
318 | dfn=0; | ||
319 | afs=0; | ||
320 | } else { | ||
321 | reg37 = 0x63; | ||
322 | reg42 = 0x4f; | ||
323 | byp=1; | ||
324 | } | ||
325 | |||
326 | // calculate BDR | ||
327 | big = (1ULL<<21) * ((u64) symbol_rate/1000ULL) * (1ULL<<dfn); | ||
328 | big += ((SACLK/1000ULL)-1ULL); | ||
329 | do_div(big, (SACLK/1000ULL)); | ||
330 | bdr = big & 0xfffff; | ||
331 | |||
332 | // calculate BDRI | ||
333 | tmp = (1<<dfn)*(symbol_rate/1000); | ||
334 | bdri = ((32 * (SACLK/1000)) + (tmp-1)) / tmp; | ||
335 | |||
336 | tda10086_write_byte(state, 0x21, (afs << 7) | dfn); | ||
337 | tda10086_write_mask(state, 0x20, 0x08, byp << 3); | ||
338 | tda10086_write_byte(state, 0x06, bdr); | ||
339 | tda10086_write_byte(state, 0x07, bdr >> 8); | ||
340 | tda10086_write_byte(state, 0x08, bdr >> 16); | ||
341 | tda10086_write_byte(state, 0x09, bdri); | ||
342 | tda10086_write_byte(state, 0x37, reg37); | ||
343 | tda10086_write_byte(state, 0x42, reg42); | ||
344 | |||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | static int tda10086_set_fec(struct tda10086_state *state, | ||
349 | struct dvb_frontend_parameters *fe_params) | ||
350 | { | ||
351 | u8 fecval; | ||
352 | |||
353 | dprintk ("%s %i\n", __FUNCTION__, fe_params->u.qpsk.fec_inner); | ||
354 | |||
355 | switch(fe_params->u.qpsk.fec_inner) { | ||
356 | case FEC_1_2: | ||
357 | fecval = 0x00; | ||
358 | break; | ||
359 | case FEC_2_3: | ||
360 | fecval = 0x01; | ||
361 | break; | ||
362 | case FEC_3_4: | ||
363 | fecval = 0x02; | ||
364 | break; | ||
365 | case FEC_4_5: | ||
366 | fecval = 0x03; | ||
367 | break; | ||
368 | case FEC_5_6: | ||
369 | fecval = 0x04; | ||
370 | break; | ||
371 | case FEC_6_7: | ||
372 | fecval = 0x05; | ||
373 | break; | ||
374 | case FEC_7_8: | ||
375 | fecval = 0x06; | ||
376 | break; | ||
377 | case FEC_8_9: | ||
378 | fecval = 0x07; | ||
379 | break; | ||
380 | case FEC_AUTO: | ||
381 | fecval = 0x08; | ||
382 | break; | ||
383 | default: | ||
384 | return -1; | ||
385 | } | ||
386 | tda10086_write_byte(state, 0x0d, fecval); | ||
387 | |||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | static int tda10086_set_frontend(struct dvb_frontend* fe, | ||
392 | struct dvb_frontend_parameters *fe_params) | ||
393 | { | ||
394 | struct tda10086_state *state = fe->demodulator_priv; | ||
395 | int ret; | ||
396 | u32 freq = 0; | ||
397 | int freqoff; | ||
398 | |||
399 | dprintk ("%s\n", __FUNCTION__); | ||
400 | |||
401 | // set params | ||
402 | if (fe->ops.tuner_ops.set_params) { | ||
403 | fe->ops.tuner_ops.set_params(fe, fe_params); | ||
404 | if (fe->ops.i2c_gate_ctrl) | ||
405 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
406 | |||
407 | if (fe->ops.tuner_ops.get_frequency) | ||
408 | fe->ops.tuner_ops.get_frequency(fe, &freq); | ||
409 | if (fe->ops.i2c_gate_ctrl) | ||
410 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
411 | } | ||
412 | |||
413 | // calcluate the frequency offset (in *Hz* not kHz) | ||
414 | freqoff = fe_params->frequency - freq; | ||
415 | freqoff = ((1<<16) * freqoff) / (SACLK/1000); | ||
416 | tda10086_write_byte(state, 0x3d, 0x80 | ((freqoff >> 8) & 0x7f)); | ||
417 | tda10086_write_byte(state, 0x3e, freqoff); | ||
418 | |||
419 | if ((ret = tda10086_set_inversion(state, fe_params)) < 0) | ||
420 | return ret; | ||
421 | if ((ret = tda10086_set_symbol_rate(state, fe_params)) < 0) | ||
422 | return ret; | ||
423 | if ((ret = tda10086_set_fec(state, fe_params)) < 0) | ||
424 | return ret; | ||
425 | |||
426 | // soft reset + disable TS output until lock | ||
427 | tda10086_write_mask(state, 0x10, 0x40, 0x40); | ||
428 | tda10086_write_mask(state, 0x00, 0x01, 0x00); | ||
429 | |||
430 | state->symbol_rate = fe_params->u.qpsk.symbol_rate; | ||
431 | state->frequency = fe_params->frequency; | ||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params) | ||
436 | { | ||
437 | struct tda10086_state* state = fe->demodulator_priv; | ||
438 | u8 val; | ||
439 | int tmp; | ||
440 | u64 tmp64; | ||
441 | |||
442 | dprintk ("%s\n", __FUNCTION__); | ||
443 | |||
444 | // calculate the updated frequency (note: we convert from Hz->kHz) | ||
445 | tmp64 = tda10086_read_byte(state, 0x52); | ||
446 | tmp64 |= (tda10086_read_byte(state, 0x51) << 8); | ||
447 | if (tmp64 & 0x8000) | ||
448 | tmp64 |= 0xffffffffffff0000ULL; | ||
449 | tmp64 = (tmp64 * (SACLK/1000ULL)); | ||
450 | do_div(tmp64, (1ULL<<15) * (1ULL<<1)); | ||
451 | fe_params->frequency = (int) state->frequency + (int) tmp64; | ||
452 | |||
453 | // the inversion | ||
454 | val = tda10086_read_byte(state, 0x0c); | ||
455 | if (val & 0x80) { | ||
456 | switch(val & 0x40) { | ||
457 | case 0x00: | ||
458 | fe_params->inversion = INVERSION_OFF; | ||
459 | if (state->config->invert) | ||
460 | fe_params->inversion = INVERSION_ON; | ||
461 | break; | ||
462 | default: | ||
463 | fe_params->inversion = INVERSION_ON; | ||
464 | if (state->config->invert) | ||
465 | fe_params->inversion = INVERSION_OFF; | ||
466 | break; | ||
467 | } | ||
468 | } else { | ||
469 | tda10086_read_byte(state, 0x0f); | ||
470 | switch(val & 0x02) { | ||
471 | case 0x00: | ||
472 | fe_params->inversion = INVERSION_OFF; | ||
473 | if (state->config->invert) | ||
474 | fe_params->inversion = INVERSION_ON; | ||
475 | break; | ||
476 | default: | ||
477 | fe_params->inversion = INVERSION_ON; | ||
478 | if (state->config->invert) | ||
479 | fe_params->inversion = INVERSION_OFF; | ||
480 | break; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | // calculate the updated symbol rate | ||
485 | tmp = tda10086_read_byte(state, 0x1d); | ||
486 | if (tmp & 0x80) | ||
487 | tmp |= 0xffffff00; | ||
488 | tmp = (tmp * 480 * (1<<1)) / 128; | ||
489 | tmp = ((state->symbol_rate/1000) * tmp) / (1000000/1000); | ||
490 | fe_params->u.qpsk.symbol_rate = state->symbol_rate + tmp; | ||
491 | |||
492 | // the FEC | ||
493 | val = (tda10086_read_byte(state, 0x0d) & 0x70) >> 4; | ||
494 | switch(val) { | ||
495 | case 0x00: | ||
496 | fe_params->u.qpsk.fec_inner = FEC_1_2; | ||
497 | break; | ||
498 | case 0x01: | ||
499 | fe_params->u.qpsk.fec_inner = FEC_2_3; | ||
500 | break; | ||
501 | case 0x02: | ||
502 | fe_params->u.qpsk.fec_inner = FEC_3_4; | ||
503 | break; | ||
504 | case 0x03: | ||
505 | fe_params->u.qpsk.fec_inner = FEC_4_5; | ||
506 | break; | ||
507 | case 0x04: | ||
508 | fe_params->u.qpsk.fec_inner = FEC_5_6; | ||
509 | break; | ||
510 | case 0x05: | ||
511 | fe_params->u.qpsk.fec_inner = FEC_6_7; | ||
512 | break; | ||
513 | case 0x06: | ||
514 | fe_params->u.qpsk.fec_inner = FEC_7_8; | ||
515 | break; | ||
516 | case 0x07: | ||
517 | fe_params->u.qpsk.fec_inner = FEC_8_9; | ||
518 | break; | ||
519 | } | ||
520 | |||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status) | ||
525 | { | ||
526 | struct tda10086_state* state = fe->demodulator_priv; | ||
527 | u8 val; | ||
528 | |||
529 | dprintk ("%s\n", __FUNCTION__); | ||
530 | |||
531 | val = tda10086_read_byte(state, 0x0e); | ||
532 | *fe_status = 0; | ||
533 | if (val & 0x01) | ||
534 | *fe_status |= FE_HAS_SIGNAL; | ||
535 | if (val & 0x02) | ||
536 | *fe_status |= FE_HAS_CARRIER; | ||
537 | if (val & 0x04) | ||
538 | *fe_status |= FE_HAS_VITERBI; | ||
539 | if (val & 0x08) | ||
540 | *fe_status |= FE_HAS_SYNC; | ||
541 | if (val & 0x10) | ||
542 | *fe_status |= FE_HAS_LOCK; | ||
543 | |||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal) | ||
548 | { | ||
549 | struct tda10086_state* state = fe->demodulator_priv; | ||
550 | u8 _str; | ||
551 | |||
552 | dprintk ("%s\n", __FUNCTION__); | ||
553 | |||
554 | _str = tda10086_read_byte(state, 0x43); | ||
555 | *signal = (_str << 8) | _str; | ||
556 | |||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr) | ||
561 | { | ||
562 | struct tda10086_state* state = fe->demodulator_priv; | ||
563 | u8 _snr; | ||
564 | |||
565 | dprintk ("%s\n", __FUNCTION__); | ||
566 | |||
567 | _snr = tda10086_read_byte(state, 0x1c); | ||
568 | *snr = (_snr << 8) | _snr; | ||
569 | |||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | static int tda10086_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | ||
574 | { | ||
575 | struct tda10086_state* state = fe->demodulator_priv; | ||
576 | |||
577 | dprintk ("%s\n", __FUNCTION__); | ||
578 | |||
579 | // read it | ||
580 | *ucblocks = tda10086_read_byte(state, 0x18) & 0x7f; | ||
581 | |||
582 | // reset counter | ||
583 | tda10086_write_byte(state, 0x18, 0x00); | ||
584 | tda10086_write_byte(state, 0x18, 0x80); | ||
585 | |||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | static int tda10086_read_ber(struct dvb_frontend* fe, u32* ber) | ||
590 | { | ||
591 | struct tda10086_state* state = fe->demodulator_priv; | ||
592 | |||
593 | dprintk ("%s\n", __FUNCTION__); | ||
594 | |||
595 | // read it | ||
596 | *ber = 0; | ||
597 | *ber |= tda10086_read_byte(state, 0x15); | ||
598 | *ber |= tda10086_read_byte(state, 0x16) << 8; | ||
599 | *ber |= (tda10086_read_byte(state, 0x17) & 0xf) << 16; | ||
600 | |||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | static int tda10086_sleep(struct dvb_frontend* fe) | ||
605 | { | ||
606 | struct tda10086_state* state = fe->demodulator_priv; | ||
607 | |||
608 | dprintk ("%s\n", __FUNCTION__); | ||
609 | |||
610 | tda10086_write_mask(state, 0x00, 0x08, 0x08); | ||
611 | |||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) | ||
616 | { | ||
617 | struct tda10086_state* state = fe->demodulator_priv; | ||
618 | |||
619 | dprintk ("%s\n", __FUNCTION__); | ||
620 | |||
621 | if (enable) { | ||
622 | tda10086_write_mask(state, 0x00, 0x10, 0x10); | ||
623 | } else { | ||
624 | tda10086_write_mask(state, 0x00, 0x10, 0x00); | ||
625 | } | ||
626 | |||
627 | return 0; | ||
628 | } | ||
629 | |||
630 | static int tda10086_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) | ||
631 | { | ||
632 | if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) { | ||
633 | fesettings->min_delay_ms = 50; | ||
634 | fesettings->step_size = 2000; | ||
635 | fesettings->max_drift = 8000; | ||
636 | } else if (fesettings->parameters.u.qpsk.symbol_rate > 12000000) { | ||
637 | fesettings->min_delay_ms = 100; | ||
638 | fesettings->step_size = 1500; | ||
639 | fesettings->max_drift = 9000; | ||
640 | } else if (fesettings->parameters.u.qpsk.symbol_rate > 8000000) { | ||
641 | fesettings->min_delay_ms = 100; | ||
642 | fesettings->step_size = 1000; | ||
643 | fesettings->max_drift = 8000; | ||
644 | } else if (fesettings->parameters.u.qpsk.symbol_rate > 4000000) { | ||
645 | fesettings->min_delay_ms = 100; | ||
646 | fesettings->step_size = 500; | ||
647 | fesettings->max_drift = 7000; | ||
648 | } else if (fesettings->parameters.u.qpsk.symbol_rate > 2000000) { | ||
649 | fesettings->min_delay_ms = 200; | ||
650 | fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000); | ||
651 | fesettings->max_drift = 14 * fesettings->step_size; | ||
652 | } else { | ||
653 | fesettings->min_delay_ms = 200; | ||
654 | fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000); | ||
655 | fesettings->max_drift = 18 * fesettings->step_size; | ||
656 | } | ||
657 | |||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | static void tda10086_release(struct dvb_frontend* fe) | ||
662 | { | ||
663 | struct tda10086_state *state = fe->demodulator_priv; | ||
664 | tda10086_sleep(fe); | ||
665 | kfree(state); | ||
666 | } | ||
667 | |||
668 | static struct dvb_frontend_ops tda10086_ops = { | ||
669 | |||
670 | .info = { | ||
671 | .name = "Philips TDA10086 DVB-S", | ||
672 | .type = FE_QPSK, | ||
673 | .frequency_min = 950000, | ||
674 | .frequency_max = 2150000, | ||
675 | .frequency_stepsize = 125, /* kHz for QPSK frontends */ | ||
676 | .symbol_rate_min = 1000000, | ||
677 | .symbol_rate_max = 45000000, | ||
678 | .caps = FE_CAN_INVERSION_AUTO | | ||
679 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
680 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
681 | FE_CAN_QPSK | ||
682 | }, | ||
683 | |||
684 | .release = tda10086_release, | ||
685 | |||
686 | .init = tda10086_init, | ||
687 | .sleep = tda10086_sleep, | ||
688 | .i2c_gate_ctrl = tda10086_i2c_gate_ctrl, | ||
689 | |||
690 | .set_frontend = tda10086_set_frontend, | ||
691 | .get_frontend = tda10086_get_frontend, | ||
692 | .get_tune_settings = tda10086_get_tune_settings, | ||
693 | |||
694 | .read_status = tda10086_read_status, | ||
695 | .read_ber = tda10086_read_ber, | ||
696 | .read_signal_strength = tda10086_read_signal_strength, | ||
697 | .read_snr = tda10086_read_snr, | ||
698 | .read_ucblocks = tda10086_read_ucblocks, | ||
699 | |||
700 | .diseqc_send_master_cmd = tda10086_send_master_cmd, | ||
701 | .diseqc_send_burst = tda10086_send_burst, | ||
702 | .set_tone = tda10086_set_tone, | ||
703 | }; | ||
704 | |||
705 | struct dvb_frontend* tda10086_attach(const struct tda10086_config* config, | ||
706 | struct i2c_adapter* i2c) | ||
707 | { | ||
708 | struct tda10086_state *state; | ||
709 | |||
710 | dprintk ("%s\n", __FUNCTION__); | ||
711 | |||
712 | /* allocate memory for the internal state */ | ||
713 | state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL); | ||
714 | if (!state) | ||
715 | return NULL; | ||
716 | |||
717 | /* setup the state */ | ||
718 | state->config = config; | ||
719 | state->i2c = i2c; | ||
720 | |||
721 | /* check if the demod is there */ | ||
722 | if (tda10086_read_byte(state, 0x1e) != 0xe1) { | ||
723 | kfree(state); | ||
724 | return NULL; | ||
725 | } | ||
726 | |||
727 | /* create dvb_frontend */ | ||
728 | memcpy(&state->frontend.ops, &tda10086_ops, sizeof(struct dvb_frontend_ops)); | ||
729 | state->frontend.demodulator_priv = state; | ||
730 | return &state->frontend; | ||
731 | } | ||
732 | |||
733 | module_param(debug, int, 0644); | ||
734 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | ||
735 | |||
736 | MODULE_DESCRIPTION("Philips TDA10086 DVB-S Demodulator"); | ||
737 | MODULE_AUTHOR("Andrew de Quincey"); | ||
738 | MODULE_LICENSE("GPL"); | ||
739 | |||
740 | EXPORT_SYMBOL(tda10086_attach); | ||
diff --git a/drivers/media/dvb/frontends/tda10086.h b/drivers/media/dvb/frontends/tda10086.h new file mode 100644 index 000000000000..e8061db11123 --- /dev/null +++ b/drivers/media/dvb/frontends/tda10086.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | Driver for Philips tda10086 DVBS Frontend | ||
3 | |||
4 | (c) 2006 Andrew de Quincey | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | |||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | */ | ||
22 | |||
23 | #ifndef TDA10086_H | ||
24 | #define TDA10086_H | ||
25 | |||
26 | #include <linux/dvb/frontend.h> | ||
27 | #include <linux/firmware.h> | ||
28 | |||
29 | struct tda10086_config | ||
30 | { | ||
31 | /* the demodulator's i2c address */ | ||
32 | u8 demod_address; | ||
33 | |||
34 | /* does the "inversion" need inverted? */ | ||
35 | u8 invert; | ||
36 | }; | ||
37 | |||
38 | extern struct dvb_frontend* tda10086_attach(const struct tda10086_config* config, | ||
39 | struct i2c_adapter* i2c); | ||
40 | |||
41 | #endif // TDA10086_H | ||
diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c new file mode 100644 index 000000000000..2921eb82fb6f --- /dev/null +++ b/drivers/media/dvb/frontends/tda826x.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | Driver for Philips tda8262/tda8263 DVBS Silicon tuners | ||
3 | |||
4 | (c) 2006 Andrew de Quincey | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | |||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/dvb/frontend.h> | ||
25 | #include <asm/types.h> | ||
26 | |||
27 | #include "tda826x.h" | ||
28 | |||
29 | struct tda826x_priv { | ||
30 | /* i2c details */ | ||
31 | int i2c_address; | ||
32 | struct i2c_adapter *i2c; | ||
33 | u8 has_loopthrough:1; | ||
34 | u32 frequency; | ||
35 | }; | ||
36 | |||
37 | static int tda826x_release(struct dvb_frontend *fe) | ||
38 | { | ||
39 | if (fe->tuner_priv) | ||
40 | kfree(fe->tuner_priv); | ||
41 | fe->tuner_priv = NULL; | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static int tda826x_sleep(struct dvb_frontend *fe) | ||
46 | { | ||
47 | struct tda826x_priv *priv = fe->tuner_priv; | ||
48 | int ret; | ||
49 | u8 buf [] = { 0x00, 0x8d }; | ||
50 | struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 2 }; | ||
51 | |||
52 | if (!priv->has_loopthrough) | ||
53 | buf[1] = 0xad; | ||
54 | |||
55 | if (fe->ops.i2c_gate_ctrl) | ||
56 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
57 | if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) { | ||
58 | printk("%s: i2c error\n", __FUNCTION__); | ||
59 | } | ||
60 | if (fe->ops.i2c_gate_ctrl) | ||
61 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
62 | printk("%s:\n", __FUNCTION__); | ||
63 | |||
64 | return (ret == 1) ? 0 : ret; | ||
65 | } | ||
66 | |||
67 | static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | ||
68 | { | ||
69 | struct tda826x_priv *priv = fe->tuner_priv; | ||
70 | int ret; | ||
71 | u32 div; | ||
72 | u8 buf [11]; | ||
73 | struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 11 }; | ||
74 | |||
75 | div = (params->frequency + (1000-1)) / 1000; | ||
76 | |||
77 | buf[0] = 0x00; // subaddress | ||
78 | buf[1] = 0x09; // powerdown RSSI + the magic value 1 | ||
79 | if (!priv->has_loopthrough) | ||
80 | buf[1] |= 0x20; // power down loopthrough if not needed | ||
81 | buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO | ||
82 | buf[3] = div >> 7; | ||
83 | buf[4] = div << 1; | ||
84 | buf[5] = 0xff; // basedband filter to max | ||
85 | buf[6] = 0xfe; // gains at max + no RF attenuation | ||
86 | buf[7] = 0x83; // charge pumps at high, tests off | ||
87 | buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports. | ||
88 | buf[9] = 0x1a; // normal caltime + recommended values for SELTH + SELVTL | ||
89 | buf[10] = 0xd4; // recommended value 13 for BBIAS + unknown bit set on | ||
90 | |||
91 | if (fe->ops.i2c_gate_ctrl) | ||
92 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
93 | if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) { | ||
94 | printk("%s: i2c error\n", __FUNCTION__); | ||
95 | } | ||
96 | if (fe->ops.i2c_gate_ctrl) | ||
97 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
98 | |||
99 | priv->frequency = div * 1000; | ||
100 | printk("%s:\n", __FUNCTION__); | ||
101 | |||
102 | return (ret == 1) ? 0 : ret; | ||
103 | } | ||
104 | |||
105 | static int tda826x_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
106 | { | ||
107 | struct tda826x_priv *priv = fe->tuner_priv; | ||
108 | *frequency = priv->frequency; | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static struct dvb_tuner_ops tda826x_tuner_ops = { | ||
113 | .release = tda826x_release, | ||
114 | .sleep = tda826x_sleep, | ||
115 | .set_params = tda826x_set_params, | ||
116 | .get_frequency = tda826x_get_frequency, | ||
117 | }; | ||
118 | |||
119 | struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c, int has_loopthrough) | ||
120 | { | ||
121 | struct tda826x_priv *priv = NULL; | ||
122 | u8 b1 [] = { 0, 0 }; | ||
123 | struct i2c_msg msg [] = { { .addr = addr, .flags = 0, .buf = NULL, .len = 0 }, | ||
124 | { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } }; | ||
125 | int ret; | ||
126 | |||
127 | if (fe->ops.i2c_gate_ctrl) | ||
128 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
129 | ret = i2c_transfer (i2c, msg, 2); | ||
130 | if (fe->ops.i2c_gate_ctrl) | ||
131 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
132 | |||
133 | if (ret != 2) | ||
134 | return NULL; | ||
135 | if (!(b1[1] & 0x80)) | ||
136 | return NULL; | ||
137 | |||
138 | priv = kzalloc(sizeof(struct tda826x_priv), GFP_KERNEL); | ||
139 | if (priv == NULL) | ||
140 | return NULL; | ||
141 | |||
142 | priv->i2c_address = addr; | ||
143 | priv->i2c = i2c; | ||
144 | priv->has_loopthrough = has_loopthrough; | ||
145 | |||
146 | memcpy(&fe->ops.tuner_ops, &tda826x_tuner_ops, sizeof(struct dvb_tuner_ops)); | ||
147 | strncpy(fe->ops.tuner_ops.info.name, "Philips TDA826X", 128); | ||
148 | fe->ops.tuner_ops.info.frequency_min = 950000; | ||
149 | fe->ops.tuner_ops.info.frequency_min = 2175000; | ||
150 | |||
151 | fe->tuner_priv = priv; | ||
152 | printk("%s:\n", __FUNCTION__); | ||
153 | |||
154 | return fe; | ||
155 | } | ||
156 | EXPORT_SYMBOL(tda826x_attach); | ||
157 | |||
158 | MODULE_DESCRIPTION("DVB TDA826x driver"); | ||
159 | MODULE_AUTHOR("Andrew de Quincey"); | ||
160 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/tda826x.h b/drivers/media/dvb/frontends/tda826x.h new file mode 100644 index 000000000000..3307607632b0 --- /dev/null +++ b/drivers/media/dvb/frontends/tda826x.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | Driver for Philips tda8262/tda8263 DVBS Silicon tuners | ||
3 | |||
4 | (c) 2006 Andrew de Quincey | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | |||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | */ | ||
22 | |||
23 | #ifndef __DVB_TDA826X_H__ | ||
24 | #define __DVB_TDA826X_H__ | ||
25 | |||
26 | #include <linux/i2c.h> | ||
27 | #include "dvb_frontend.h" | ||
28 | |||
29 | /** | ||
30 | * Attach a tda826x tuner to the supplied frontend structure. | ||
31 | * | ||
32 | * @param fe Frontend to attach to. | ||
33 | * @param addr i2c address of the tuner. | ||
34 | * @param i2c i2c adapter to use. | ||
35 | * @param has_loopthrough Set to 1 if the card has a loopthrough RF connector. | ||
36 | * @return FE pointer on success, NULL on failure. | ||
37 | */ | ||
38 | extern struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c, int has_loopthrough); | ||
39 | |||
40 | #endif | ||