diff options
author | Michael Krufky <mkrufky@linuxtv.org> | 2007-04-27 11:31:14 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-04-27 14:43:35 -0400 |
commit | 8ce47dad8e2b9fcb899a67e6537337fa9c18c1f5 (patch) | |
tree | 8482515d25ebc98bf7ac74e47b78f576f23b753f /drivers/media/dvb/frontends/tda827x.c | |
parent | 7c7fea669d77048b3013567dfb4c9171d536da05 (diff) |
V4L/DVB (5317): Create tda827x dvb tuner module
The patch moves the tda827x dvb tuning code to a separate module
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Hartmut Hackmann <hartmut.hackmann@t-online.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/dvb/frontends/tda827x.c')
-rw-r--r-- | drivers/media/dvb/frontends/tda827x.c | 476 |
1 files changed, 476 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/tda827x.c b/drivers/media/dvb/frontends/tda827x.c new file mode 100644 index 000000000000..cff2d1fa4094 --- /dev/null +++ b/drivers/media/dvb/frontends/tda827x.c | |||
@@ -0,0 +1,476 @@ | |||
1 | /* | ||
2 | * | ||
3 | * (c) 2005 Hartmut Hackmann | ||
4 | * (c) 2007 Michael Krufky | ||
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 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/dvb/frontend.h> | ||
23 | #include <asm/types.h> | ||
24 | |||
25 | #include "tda827x.h" | ||
26 | |||
27 | static int debug = 0; | ||
28 | #define dprintk(args...) \ | ||
29 | do { \ | ||
30 | if (debug) printk(KERN_DEBUG "tda827x: " args); \ | ||
31 | } while (0) | ||
32 | |||
33 | struct tda827x_priv { | ||
34 | int i2c_addr; | ||
35 | struct i2c_adapter *i2c_adap; | ||
36 | struct tda827x_config *cfg; | ||
37 | u32 frequency; | ||
38 | u32 bandwidth; | ||
39 | }; | ||
40 | |||
41 | struct tda827x_data { | ||
42 | u32 lomax; | ||
43 | u8 spd; | ||
44 | u8 bs; | ||
45 | u8 bp; | ||
46 | u8 cp; | ||
47 | u8 gc3; | ||
48 | u8 div1p5; | ||
49 | }; | ||
50 | |||
51 | static const struct tda827x_data tda827x_dvbt[] = { | ||
52 | { .lomax = 62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, | ||
53 | { .lomax = 66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, | ||
54 | { .lomax = 76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, | ||
55 | { .lomax = 84000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, | ||
56 | { .lomax = 93000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
57 | { .lomax = 98000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
58 | { .lomax = 109000000, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
59 | { .lomax = 123000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, | ||
60 | { .lomax = 133000000, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, | ||
61 | { .lomax = 151000000, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
62 | { .lomax = 154000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
63 | { .lomax = 181000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0}, | ||
64 | { .lomax = 185000000, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
65 | { .lomax = 217000000, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
66 | { .lomax = 244000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, | ||
67 | { .lomax = 265000000, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, | ||
68 | { .lomax = 302000000, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
69 | { .lomax = 324000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
70 | { .lomax = 370000000, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
71 | { .lomax = 454000000, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
72 | { .lomax = 493000000, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, | ||
73 | { .lomax = 530000000, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, | ||
74 | { .lomax = 554000000, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
75 | { .lomax = 604000000, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, | ||
76 | { .lomax = 696000000, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, | ||
77 | { .lomax = 740000000, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, | ||
78 | { .lomax = 820000000, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, | ||
79 | { .lomax = 865000000, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, | ||
80 | { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} | ||
81 | }; | ||
82 | |||
83 | static int tda827xo_set_params(struct dvb_frontend *fe, | ||
84 | struct dvb_frontend_parameters *params) | ||
85 | { | ||
86 | struct tda827x_priv *priv = fe->tuner_priv; | ||
87 | u8 buf[14]; | ||
88 | |||
89 | struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, | ||
90 | .buf = buf, .len = sizeof(buf) }; | ||
91 | int i, tuner_freq, if_freq; | ||
92 | u32 N; | ||
93 | |||
94 | switch (params->u.ofdm.bandwidth) { | ||
95 | case BANDWIDTH_6_MHZ: | ||
96 | if_freq = 4000000; | ||
97 | break; | ||
98 | case BANDWIDTH_7_MHZ: | ||
99 | if_freq = 4500000; | ||
100 | break; | ||
101 | default: /* 8 MHz or Auto */ | ||
102 | if_freq = 5000000; | ||
103 | break; | ||
104 | } | ||
105 | tuner_freq = params->frequency + if_freq; | ||
106 | |||
107 | i = 0; | ||
108 | while (tda827x_dvbt[i].lomax < tuner_freq) { | ||
109 | if(tda827x_dvbt[i + 1].lomax == 0) | ||
110 | break; | ||
111 | i++; | ||
112 | } | ||
113 | |||
114 | N = ((tuner_freq + 125000) / 250000) << (tda827x_dvbt[i].spd + 2); | ||
115 | buf[0] = 0; | ||
116 | buf[1] = (N>>8) | 0x40; | ||
117 | buf[2] = N & 0xff; | ||
118 | buf[3] = 0; | ||
119 | buf[4] = 0x52; | ||
120 | buf[5] = (tda827x_dvbt[i].spd << 6) + (tda827x_dvbt[i].div1p5 << 5) + | ||
121 | (tda827x_dvbt[i].bs << 3) + tda827x_dvbt[i].bp; | ||
122 | buf[6] = (tda827x_dvbt[i].gc3 << 4) + 0x8f; | ||
123 | buf[7] = 0xbf; | ||
124 | buf[8] = 0x2a; | ||
125 | buf[9] = 0x05; | ||
126 | buf[10] = 0xff; | ||
127 | buf[11] = 0x00; | ||
128 | buf[12] = 0x00; | ||
129 | buf[13] = 0x40; | ||
130 | |||
131 | msg.len = 14; | ||
132 | if (fe->ops.i2c_gate_ctrl) | ||
133 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
134 | if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) { | ||
135 | printk("%s: could not write to tuner at addr: 0x%02x\n", | ||
136 | __FUNCTION__, priv->i2c_addr << 1); | ||
137 | return -EIO; | ||
138 | } | ||
139 | msleep(500); | ||
140 | /* correct CP value */ | ||
141 | buf[0] = 0x30; | ||
142 | buf[1] = 0x50 + tda827x_dvbt[i].cp; | ||
143 | msg.len = 2; | ||
144 | |||
145 | if (fe->ops.i2c_gate_ctrl) | ||
146 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
147 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
148 | |||
149 | priv->frequency = tuner_freq - if_freq; // FIXME | ||
150 | priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static int tda827xo_sleep(struct dvb_frontend *fe) | ||
156 | { | ||
157 | struct tda827x_priv *priv = fe->tuner_priv; | ||
158 | static u8 buf[] = { 0x30, 0xd0 }; | ||
159 | struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, | ||
160 | .buf = buf, .len = sizeof(buf) }; | ||
161 | |||
162 | if (fe->ops.i2c_gate_ctrl) | ||
163 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
164 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
165 | |||
166 | if (priv->cfg && priv->cfg->sleep) | ||
167 | priv->cfg->sleep(fe); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | /* ------------------------------------------------------------------ */ | ||
173 | |||
174 | struct tda827xa_data { | ||
175 | u32 lomax; | ||
176 | u8 svco; | ||
177 | u8 spd; | ||
178 | u8 scr; | ||
179 | u8 sbs; | ||
180 | u8 gc3; | ||
181 | }; | ||
182 | |||
183 | static const struct tda827xa_data tda827xa_dvbt[] = { | ||
184 | { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1}, | ||
185 | { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, | ||
186 | { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, | ||
187 | { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, | ||
188 | { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1}, | ||
189 | { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, | ||
190 | { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, | ||
191 | { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, | ||
192 | { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, | ||
193 | { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, | ||
194 | { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, | ||
195 | { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, | ||
196 | { .lomax = 290000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, | ||
197 | { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, | ||
198 | { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, | ||
199 | { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, | ||
200 | { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, | ||
201 | { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1}, | ||
202 | { .lomax = 550000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, | ||
203 | { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, | ||
204 | { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, | ||
205 | { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, | ||
206 | { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, | ||
207 | { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, | ||
208 | { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, | ||
209 | { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0}, | ||
210 | { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} | ||
211 | }; | ||
212 | |||
213 | static int tda827xa_set_params(struct dvb_frontend *fe, | ||
214 | struct dvb_frontend_parameters *params) | ||
215 | { | ||
216 | struct tda827x_priv *priv = fe->tuner_priv; | ||
217 | u8 buf[10]; | ||
218 | |||
219 | struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, | ||
220 | .buf = buf, .len = sizeof(buf) }; | ||
221 | |||
222 | int i, tuner_freq, if_freq; | ||
223 | u32 N; | ||
224 | |||
225 | if (priv->cfg && priv->cfg->lna_gain) | ||
226 | priv->cfg->lna_gain(fe, 1); | ||
227 | msleep(20); | ||
228 | |||
229 | switch (params->u.ofdm.bandwidth) { | ||
230 | case BANDWIDTH_6_MHZ: | ||
231 | if_freq = 4000000; | ||
232 | break; | ||
233 | case BANDWIDTH_7_MHZ: | ||
234 | if_freq = 4500000; | ||
235 | break; | ||
236 | default: /* 8 MHz or Auto */ | ||
237 | if_freq = 5000000; | ||
238 | break; | ||
239 | } | ||
240 | tuner_freq = params->frequency + if_freq; | ||
241 | |||
242 | i = 0; | ||
243 | while (tda827xa_dvbt[i].lomax < tuner_freq) { | ||
244 | if(tda827xa_dvbt[i + 1].lomax == 0) | ||
245 | break; | ||
246 | i++; | ||
247 | } | ||
248 | |||
249 | N = ((tuner_freq + 31250) / 62500) << tda827xa_dvbt[i].spd; | ||
250 | buf[0] = 0; // subaddress | ||
251 | buf[1] = N >> 8; | ||
252 | buf[2] = N & 0xff; | ||
253 | buf[3] = 0; | ||
254 | buf[4] = 0x16; | ||
255 | buf[5] = (tda827xa_dvbt[i].spd << 5) + (tda827xa_dvbt[i].svco << 3) + | ||
256 | tda827xa_dvbt[i].sbs; | ||
257 | buf[6] = 0x4b + (tda827xa_dvbt[i].gc3 << 4); | ||
258 | buf[7] = 0x1c; | ||
259 | buf[8] = 0x06; | ||
260 | buf[9] = 0x24; | ||
261 | buf[10] = 0x00; | ||
262 | msg.len = 11; | ||
263 | if (fe->ops.i2c_gate_ctrl) | ||
264 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
265 | if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) { | ||
266 | printk("%s: could not write to tuner at addr: 0x%02x\n", | ||
267 | __FUNCTION__, priv->i2c_addr << 1); | ||
268 | return -EIO; | ||
269 | } | ||
270 | buf[0] = 0x90; | ||
271 | buf[1] = 0xff; | ||
272 | buf[2] = 0x60; | ||
273 | buf[3] = 0x00; | ||
274 | buf[4] = 0x59; // lpsel, for 6MHz + 2 | ||
275 | msg.len = 5; | ||
276 | if (fe->ops.i2c_gate_ctrl) | ||
277 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
278 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
279 | |||
280 | buf[0] = 0xa0; | ||
281 | buf[1] = 0x40; | ||
282 | msg.len = 2; | ||
283 | if (fe->ops.i2c_gate_ctrl) | ||
284 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
285 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
286 | |||
287 | msleep(11); | ||
288 | msg.flags = I2C_M_RD; | ||
289 | if (fe->ops.i2c_gate_ctrl) | ||
290 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
291 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
292 | msg.flags = 0; | ||
293 | |||
294 | buf[1] >>= 4; | ||
295 | dprintk("tda8275a AGC2 gain is: %d\n", buf[1]); | ||
296 | if ((buf[1]) < 2) { | ||
297 | if (priv->cfg && priv->cfg->lna_gain) | ||
298 | priv->cfg->lna_gain(fe, 0); | ||
299 | buf[0] = 0x60; | ||
300 | buf[1] = 0x0c; | ||
301 | if (fe->ops.i2c_gate_ctrl) | ||
302 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
303 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
304 | } | ||
305 | |||
306 | buf[0] = 0xc0; | ||
307 | buf[1] = 0x99; // lpsel, for 6MHz + 2 | ||
308 | if (fe->ops.i2c_gate_ctrl) | ||
309 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
310 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
311 | |||
312 | buf[0] = 0x60; | ||
313 | buf[1] = 0x3c; | ||
314 | if (fe->ops.i2c_gate_ctrl) | ||
315 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
316 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
317 | |||
318 | /* correct CP value */ | ||
319 | buf[0] = 0x30; | ||
320 | buf[1] = 0x10 + tda827xa_dvbt[i].scr; | ||
321 | if (fe->ops.i2c_gate_ctrl) | ||
322 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
323 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
324 | |||
325 | msleep(163); | ||
326 | buf[0] = 0xc0; | ||
327 | buf[1] = 0x39; // lpsel, for 6MHz + 2 | ||
328 | if (fe->ops.i2c_gate_ctrl) | ||
329 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
330 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
331 | |||
332 | msleep(3); | ||
333 | /* freeze AGC1 */ | ||
334 | buf[0] = 0x50; | ||
335 | buf[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4); | ||
336 | if (fe->ops.i2c_gate_ctrl) | ||
337 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
338 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
339 | |||
340 | priv->frequency = tuner_freq - if_freq; // FIXME | ||
341 | priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; | ||
342 | |||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | static int tda827xa_sleep(struct dvb_frontend *fe) | ||
347 | { | ||
348 | struct tda827x_priv *priv = fe->tuner_priv; | ||
349 | static u8 buf[] = { 0x30, 0x90 }; | ||
350 | struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, | ||
351 | .buf = buf, .len = sizeof(buf) }; | ||
352 | |||
353 | if (fe->ops.i2c_gate_ctrl) | ||
354 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
355 | |||
356 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
357 | |||
358 | if (fe->ops.i2c_gate_ctrl) | ||
359 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
360 | |||
361 | if (priv->cfg && priv->cfg->sleep) | ||
362 | priv->cfg->sleep(fe); | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static int tda827x_release(struct dvb_frontend *fe) | ||
368 | { | ||
369 | kfree(fe->tuner_priv); | ||
370 | fe->tuner_priv = NULL; | ||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static int tda827x_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
375 | { | ||
376 | struct tda827x_priv *priv = fe->tuner_priv; | ||
377 | *frequency = priv->frequency; | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) | ||
382 | { | ||
383 | struct tda827x_priv *priv = fe->tuner_priv; | ||
384 | *bandwidth = priv->bandwidth; | ||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | static int tda827x_init(struct dvb_frontend *fe) | ||
389 | { | ||
390 | struct tda827x_priv *priv = fe->tuner_priv; | ||
391 | |||
392 | if (priv->cfg && priv->cfg->init) | ||
393 | priv->cfg->init(fe); | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | |||
399 | static struct dvb_tuner_ops tda827xo_tuner_ops = { | ||
400 | .info = { | ||
401 | .name = "Philips TDA827X", | ||
402 | }, | ||
403 | .release = tda827x_release, | ||
404 | .init = tda827x_init, | ||
405 | .sleep = tda827xo_sleep, | ||
406 | .set_params = tda827xo_set_params, | ||
407 | .get_frequency = tda827x_get_frequency, | ||
408 | .get_bandwidth = tda827x_get_bandwidth, | ||
409 | }; | ||
410 | |||
411 | static struct dvb_tuner_ops tda827xa_tuner_ops = { | ||
412 | .info = { | ||
413 | .name = "Philips TDA827XA", | ||
414 | }, | ||
415 | .release = tda827x_release, | ||
416 | .init = tda827x_init, | ||
417 | .sleep = tda827xa_sleep, | ||
418 | .set_params = tda827xa_set_params, | ||
419 | .get_frequency = tda827x_get_frequency, | ||
420 | .get_bandwidth = tda827x_get_bandwidth, | ||
421 | }; | ||
422 | |||
423 | struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr, | ||
424 | struct i2c_adapter *i2c, | ||
425 | struct tda827x_config *cfg) | ||
426 | { | ||
427 | struct tda827x_priv *priv = NULL; | ||
428 | u8 data; | ||
429 | struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, | ||
430 | .buf = &data, .len = 1 }; | ||
431 | dprintk("%s:\n", __FUNCTION__); | ||
432 | |||
433 | if (fe->ops.i2c_gate_ctrl) | ||
434 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
435 | |||
436 | if (i2c_transfer(i2c, &msg, 1) != 1) { | ||
437 | printk("%s: could not read from tuner at addr: 0x%02x\n", | ||
438 | __FUNCTION__, addr << 1); | ||
439 | return NULL; | ||
440 | } | ||
441 | |||
442 | priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL); | ||
443 | if (priv == NULL) | ||
444 | return NULL; | ||
445 | |||
446 | priv->i2c_addr = addr; | ||
447 | priv->i2c_adap = i2c; | ||
448 | priv->cfg = cfg; | ||
449 | if ((data & 0x3c) == 0) { | ||
450 | dprintk("tda827x tuner found\n"); | ||
451 | memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops)); | ||
452 | } else { | ||
453 | dprintk("tda827xa tuner found\n"); | ||
454 | memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops)); | ||
455 | } | ||
456 | fe->tuner_priv = priv; | ||
457 | |||
458 | return fe; | ||
459 | } | ||
460 | EXPORT_SYMBOL(tda827x_attach); | ||
461 | |||
462 | module_param(debug, int, 0644); | ||
463 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | ||
464 | |||
465 | MODULE_DESCRIPTION("DVB TDA827x driver"); | ||
466 | MODULE_AUTHOR("Hartmut Hackmann"); | ||
467 | MODULE_AUTHOR("Michael Krufky"); | ||
468 | MODULE_LICENSE("GPL"); | ||
469 | |||
470 | /* | ||
471 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
472 | * --------------------------------------------------------------------------- | ||
473 | * Local variables: | ||
474 | * c-basic-offset: 8 | ||
475 | * End: | ||
476 | */ | ||