diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/media/video/mt20xx.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/video/mt20xx.c')
-rw-r--r-- | drivers/media/video/mt20xx.c | 558 |
1 files changed, 558 insertions, 0 deletions
diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c new file mode 100644 index 000000000000..95ad17b7f38e --- /dev/null +++ b/drivers/media/video/mt20xx.c | |||
@@ -0,0 +1,558 @@ | |||
1 | /* | ||
2 | * $Id: mt20xx.c,v 1.4 2005/03/04 09:24:56 kraxel Exp $ | ||
3 | * | ||
4 | * i2c tv tuner chip device driver | ||
5 | * controls microtune tuners, mt2032 + mt2050 at the moment. | ||
6 | */ | ||
7 | #include <linux/delay.h> | ||
8 | #include <linux/i2c.h> | ||
9 | #include <linux/videodev.h> | ||
10 | #include <linux/moduleparam.h> | ||
11 | #include <media/tuner.h> | ||
12 | |||
13 | /* ---------------------------------------------------------------------- */ | ||
14 | |||
15 | static unsigned int optimize_vco = 1; | ||
16 | module_param(optimize_vco, int, 0644); | ||
17 | |||
18 | static unsigned int tv_antenna = 1; | ||
19 | module_param(tv_antenna, int, 0644); | ||
20 | |||
21 | static unsigned int radio_antenna = 0; | ||
22 | module_param(radio_antenna, int, 0644); | ||
23 | |||
24 | /* ---------------------------------------------------------------------- */ | ||
25 | |||
26 | #define MT2032 0x04 | ||
27 | #define MT2030 0x06 | ||
28 | #define MT2040 0x07 | ||
29 | #define MT2050 0x42 | ||
30 | |||
31 | static char *microtune_part[] = { | ||
32 | [ MT2030 ] = "MT2030", | ||
33 | [ MT2032 ] = "MT2032", | ||
34 | [ MT2040 ] = "MT2040", | ||
35 | [ MT2050 ] = "MT2050", | ||
36 | }; | ||
37 | |||
38 | // IsSpurInBand()? | ||
39 | static int mt2032_spurcheck(struct i2c_client *c, | ||
40 | int f1, int f2, int spectrum_from,int spectrum_to) | ||
41 | { | ||
42 | struct tuner *t = i2c_get_clientdata(c); | ||
43 | int n1=1,n2,f; | ||
44 | |||
45 | f1=f1/1000; //scale to kHz to avoid 32bit overflows | ||
46 | f2=f2/1000; | ||
47 | spectrum_from/=1000; | ||
48 | spectrum_to/=1000; | ||
49 | |||
50 | tuner_dbg("spurcheck f1=%d f2=%d from=%d to=%d\n", | ||
51 | f1,f2,spectrum_from,spectrum_to); | ||
52 | |||
53 | do { | ||
54 | n2=-n1; | ||
55 | f=n1*(f1-f2); | ||
56 | do { | ||
57 | n2--; | ||
58 | f=f-f2; | ||
59 | tuner_dbg("spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f); | ||
60 | |||
61 | if( (f>spectrum_from) && (f<spectrum_to)) | ||
62 | tuner_dbg("mt2032 spurcheck triggered: %d\n",n1); | ||
63 | } while ( (f>(f2-spectrum_to)) || (n2>-5)); | ||
64 | n1++; | ||
65 | } while (n1<5); | ||
66 | |||
67 | return 1; | ||
68 | } | ||
69 | |||
70 | static int mt2032_compute_freq(struct i2c_client *c, | ||
71 | unsigned int rfin, | ||
72 | unsigned int if1, unsigned int if2, | ||
73 | unsigned int spectrum_from, | ||
74 | unsigned int spectrum_to, | ||
75 | unsigned char *buf, | ||
76 | int *ret_sel, | ||
77 | unsigned int xogc) //all in Hz | ||
78 | { | ||
79 | struct tuner *t = i2c_get_clientdata(c); | ||
80 | unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1, | ||
81 | desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq; | ||
82 | |||
83 | fref= 5250 *1000; //5.25MHz | ||
84 | desired_lo1=rfin+if1; | ||
85 | |||
86 | lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000); | ||
87 | lo1n=lo1/8; | ||
88 | lo1a=lo1-(lo1n*8); | ||
89 | |||
90 | s=rfin/1000/1000+1090; | ||
91 | |||
92 | if(optimize_vco) { | ||
93 | if(s>1890) sel=0; | ||
94 | else if(s>1720) sel=1; | ||
95 | else if(s>1530) sel=2; | ||
96 | else if(s>1370) sel=3; | ||
97 | else sel=4; // >1090 | ||
98 | } | ||
99 | else { | ||
100 | if(s>1790) sel=0; // <1958 | ||
101 | else if(s>1617) sel=1; | ||
102 | else if(s>1449) sel=2; | ||
103 | else if(s>1291) sel=3; | ||
104 | else sel=4; // >1090 | ||
105 | } | ||
106 | *ret_sel=sel; | ||
107 | |||
108 | lo1freq=(lo1a+8*lo1n)*fref; | ||
109 | |||
110 | tuner_dbg("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n", | ||
111 | rfin,lo1,lo1n,lo1a,sel,lo1freq); | ||
112 | |||
113 | desired_lo2=lo1freq-rfin-if2; | ||
114 | lo2=(desired_lo2)/fref; | ||
115 | lo2n=lo2/8; | ||
116 | lo2a=lo2-(lo2n*8); | ||
117 | lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith | ||
118 | lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000; | ||
119 | |||
120 | tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n", | ||
121 | rfin,lo2,lo2n,lo2a,lo2num,lo2freq); | ||
122 | |||
123 | if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) { | ||
124 | tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n", | ||
125 | lo1a, lo1n, lo2a,lo2n); | ||
126 | return(-1); | ||
127 | } | ||
128 | |||
129 | mt2032_spurcheck(c, lo1freq, desired_lo2, spectrum_from, spectrum_to); | ||
130 | // should recalculate lo1 (one step up/down) | ||
131 | |||
132 | // set up MT2032 register map for transfer over i2c | ||
133 | buf[0]=lo1n-1; | ||
134 | buf[1]=lo1a | (sel<<4); | ||
135 | buf[2]=0x86; // LOGC | ||
136 | buf[3]=0x0f; //reserved | ||
137 | buf[4]=0x1f; | ||
138 | buf[5]=(lo2n-1) | (lo2a<<5); | ||
139 | if(rfin >400*1000*1000) | ||
140 | buf[6]=0xe4; | ||
141 | else | ||
142 | buf[6]=0xf4; // set PKEN per rev 1.2 | ||
143 | buf[7]=8+xogc; | ||
144 | buf[8]=0xc3; //reserved | ||
145 | buf[9]=0x4e; //reserved | ||
146 | buf[10]=0xec; //reserved | ||
147 | buf[11]=(lo2num&0xff); | ||
148 | buf[12]=(lo2num>>8) |0x80; // Lo2RST | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int mt2032_check_lo_lock(struct i2c_client *c) | ||
154 | { | ||
155 | struct tuner *t = i2c_get_clientdata(c); | ||
156 | int try,lock=0; | ||
157 | unsigned char buf[2]; | ||
158 | |||
159 | for(try=0;try<10;try++) { | ||
160 | buf[0]=0x0e; | ||
161 | i2c_master_send(c,buf,1); | ||
162 | i2c_master_recv(c,buf,1); | ||
163 | tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]); | ||
164 | lock=buf[0] &0x06; | ||
165 | |||
166 | if (lock==6) | ||
167 | break; | ||
168 | |||
169 | tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]); | ||
170 | udelay(1000); | ||
171 | } | ||
172 | return lock; | ||
173 | } | ||
174 | |||
175 | static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock) | ||
176 | { | ||
177 | struct tuner *t = i2c_get_clientdata(c); | ||
178 | unsigned char buf[2]; | ||
179 | int tad1; | ||
180 | |||
181 | buf[0]=0x0f; | ||
182 | i2c_master_send(c,buf,1); | ||
183 | i2c_master_recv(c,buf,1); | ||
184 | tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]); | ||
185 | tad1=buf[0]&0x07; | ||
186 | |||
187 | if(tad1 ==0) return lock; | ||
188 | if(tad1 ==1) return lock; | ||
189 | |||
190 | if(tad1==2) { | ||
191 | if(sel==0) | ||
192 | return lock; | ||
193 | else sel--; | ||
194 | } | ||
195 | else { | ||
196 | if(sel<4) | ||
197 | sel++; | ||
198 | else | ||
199 | return lock; | ||
200 | } | ||
201 | |||
202 | tuner_dbg("mt2032 optimize_vco: sel=%d\n",sel); | ||
203 | |||
204 | buf[0]=0x0f; | ||
205 | buf[1]=sel; | ||
206 | i2c_master_send(c,buf,2); | ||
207 | lock=mt2032_check_lo_lock(c); | ||
208 | return lock; | ||
209 | } | ||
210 | |||
211 | |||
212 | static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin, | ||
213 | unsigned int if1, unsigned int if2, | ||
214 | unsigned int from, unsigned int to) | ||
215 | { | ||
216 | unsigned char buf[21]; | ||
217 | int lint_try,ret,sel,lock=0; | ||
218 | struct tuner *t = i2c_get_clientdata(c); | ||
219 | |||
220 | tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n", | ||
221 | rfin,if1,if2,from,to); | ||
222 | |||
223 | buf[0]=0; | ||
224 | ret=i2c_master_send(c,buf,1); | ||
225 | i2c_master_recv(c,buf,21); | ||
226 | |||
227 | buf[0]=0; | ||
228 | ret=mt2032_compute_freq(c,rfin,if1,if2,from,to,&buf[1],&sel,t->xogc); | ||
229 | if (ret<0) | ||
230 | return; | ||
231 | |||
232 | // send only the relevant registers per Rev. 1.2 | ||
233 | buf[0]=0; | ||
234 | ret=i2c_master_send(c,buf,4); | ||
235 | buf[5]=5; | ||
236 | ret=i2c_master_send(c,buf+5,4); | ||
237 | buf[11]=11; | ||
238 | ret=i2c_master_send(c,buf+11,3); | ||
239 | if(ret!=3) | ||
240 | tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret); | ||
241 | |||
242 | // wait for PLLs to lock (per manual), retry LINT if not. | ||
243 | for(lint_try=0; lint_try<2; lint_try++) { | ||
244 | lock=mt2032_check_lo_lock(c); | ||
245 | |||
246 | if(optimize_vco) | ||
247 | lock=mt2032_optimize_vco(c,sel,lock); | ||
248 | if(lock==6) break; | ||
249 | |||
250 | tuner_dbg("mt2032: re-init PLLs by LINT\n"); | ||
251 | buf[0]=7; | ||
252 | buf[1]=0x80 +8+t->xogc; // set LINT to re-init PLLs | ||
253 | i2c_master_send(c,buf,2); | ||
254 | mdelay(10); | ||
255 | buf[1]=8+t->xogc; | ||
256 | i2c_master_send(c,buf,2); | ||
257 | } | ||
258 | |||
259 | if (lock!=6) | ||
260 | tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n"); | ||
261 | |||
262 | buf[0]=2; | ||
263 | buf[1]=0x20; // LOGC for optimal phase noise | ||
264 | ret=i2c_master_send(c,buf,2); | ||
265 | if (ret!=2) | ||
266 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); | ||
267 | } | ||
268 | |||
269 | |||
270 | static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq) | ||
271 | { | ||
272 | struct tuner *t = i2c_get_clientdata(c); | ||
273 | int if2,from,to; | ||
274 | |||
275 | // signal bandwidth and picture carrier | ||
276 | if (t->std & V4L2_STD_525_60) { | ||
277 | // NTSC | ||
278 | from = 40750*1000; | ||
279 | to = 46750*1000; | ||
280 | if2 = 45750*1000; | ||
281 | } else { | ||
282 | // PAL | ||
283 | from = 32900*1000; | ||
284 | to = 39900*1000; | ||
285 | if2 = 38900*1000; | ||
286 | } | ||
287 | |||
288 | mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */, | ||
289 | 1090*1000*1000, if2, from, to); | ||
290 | } | ||
291 | |||
292 | static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq) | ||
293 | { | ||
294 | struct tuner *t = i2c_get_clientdata(c); | ||
295 | int if2 = t->radio_if2; | ||
296 | |||
297 | // per Manual for FM tuning: first if center freq. 1085 MHz | ||
298 | mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */, | ||
299 | 1085*1000*1000,if2,if2,if2); | ||
300 | } | ||
301 | |||
302 | // Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001 | ||
303 | static int mt2032_init(struct i2c_client *c) | ||
304 | { | ||
305 | struct tuner *t = i2c_get_clientdata(c); | ||
306 | unsigned char buf[21]; | ||
307 | int ret,xogc,xok=0; | ||
308 | |||
309 | // Initialize Registers per spec. | ||
310 | buf[1]=2; // Index to register 2 | ||
311 | buf[2]=0xff; | ||
312 | buf[3]=0x0f; | ||
313 | buf[4]=0x1f; | ||
314 | ret=i2c_master_send(c,buf+1,4); | ||
315 | |||
316 | buf[5]=6; // Index register 6 | ||
317 | buf[6]=0xe4; | ||
318 | buf[7]=0x8f; | ||
319 | buf[8]=0xc3; | ||
320 | buf[9]=0x4e; | ||
321 | buf[10]=0xec; | ||
322 | ret=i2c_master_send(c,buf+5,6); | ||
323 | |||
324 | buf[12]=13; // Index register 13 | ||
325 | buf[13]=0x32; | ||
326 | ret=i2c_master_send(c,buf+12,2); | ||
327 | |||
328 | // Adjust XOGC (register 7), wait for XOK | ||
329 | xogc=7; | ||
330 | do { | ||
331 | tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); | ||
332 | mdelay(10); | ||
333 | buf[0]=0x0e; | ||
334 | i2c_master_send(c,buf,1); | ||
335 | i2c_master_recv(c,buf,1); | ||
336 | xok=buf[0]&0x01; | ||
337 | tuner_dbg("mt2032: xok = 0x%02x\n",xok); | ||
338 | if (xok == 1) break; | ||
339 | |||
340 | xogc--; | ||
341 | tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); | ||
342 | if (xogc == 3) { | ||
343 | xogc=4; // min. 4 per spec | ||
344 | break; | ||
345 | } | ||
346 | buf[0]=0x07; | ||
347 | buf[1]=0x88 + xogc; | ||
348 | ret=i2c_master_send(c,buf,2); | ||
349 | if (ret!=2) | ||
350 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); | ||
351 | } while (xok != 1 ); | ||
352 | t->xogc=xogc; | ||
353 | |||
354 | t->tv_freq = mt2032_set_tv_freq; | ||
355 | t->radio_freq = mt2032_set_radio_freq; | ||
356 | return(1); | ||
357 | } | ||
358 | |||
359 | static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna) | ||
360 | { | ||
361 | struct tuner *t = i2c_get_clientdata(c); | ||
362 | unsigned char buf[2]; | ||
363 | int ret; | ||
364 | |||
365 | buf[0] = 6; | ||
366 | buf[1] = antenna ? 0x11 : 0x10; | ||
367 | ret=i2c_master_send(c,buf,2); | ||
368 | tuner_dbg("mt2050: enabled antenna connector %d\n", antenna); | ||
369 | } | ||
370 | |||
371 | static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned int if2) | ||
372 | { | ||
373 | struct tuner *t = i2c_get_clientdata(c); | ||
374 | unsigned int if1=1218*1000*1000; | ||
375 | unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b; | ||
376 | int ret; | ||
377 | unsigned char buf[6]; | ||
378 | |||
379 | tuner_dbg("mt2050_set_if_freq freq=%d if1=%d if2=%d\n", | ||
380 | freq,if1,if2); | ||
381 | |||
382 | f_lo1=freq+if1; | ||
383 | f_lo1=(f_lo1/1000000)*1000000; | ||
384 | |||
385 | f_lo2=f_lo1-freq-if2; | ||
386 | f_lo2=(f_lo2/50000)*50000; | ||
387 | |||
388 | lo1=f_lo1/4000000; | ||
389 | lo2=f_lo2/4000000; | ||
390 | |||
391 | f_lo1_modulo= f_lo1-(lo1*4000000); | ||
392 | f_lo2_modulo= f_lo2-(lo2*4000000); | ||
393 | |||
394 | num1=4*f_lo1_modulo/4000000; | ||
395 | num2=4096*(f_lo2_modulo/1000)/4000; | ||
396 | |||
397 | // todo spurchecks | ||
398 | |||
399 | div1a=(lo1/12)-1; | ||
400 | div1b=lo1-(div1a+1)*12; | ||
401 | |||
402 | div2a=(lo2/8)-1; | ||
403 | div2b=lo2-(div2a+1)*8; | ||
404 | |||
405 | if (tuner_debug > 1) { | ||
406 | tuner_dbg("lo1 lo2 = %d %d\n", lo1, lo2); | ||
407 | tuner_dbg("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n", | ||
408 | num1,num2,div1a,div1b,div2a,div2b); | ||
409 | } | ||
410 | |||
411 | buf[0]=1; | ||
412 | buf[1]= 4*div1b + num1; | ||
413 | if(freq<275*1000*1000) buf[1] = buf[1]|0x80; | ||
414 | |||
415 | buf[2]=div1a; | ||
416 | buf[3]=32*div2b + num2/256; | ||
417 | buf[4]=num2-(num2/256)*256; | ||
418 | buf[5]=div2a; | ||
419 | if(num2!=0) buf[5]=buf[5]|0x40; | ||
420 | |||
421 | if (tuner_debug > 1) { | ||
422 | int i; | ||
423 | tuner_dbg("bufs is: "); | ||
424 | for(i=0;i<6;i++) | ||
425 | printk("%x ",buf[i]); | ||
426 | printk("\n"); | ||
427 | } | ||
428 | |||
429 | ret=i2c_master_send(c,buf,6); | ||
430 | if (ret!=6) | ||
431 | tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret); | ||
432 | } | ||
433 | |||
434 | static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq) | ||
435 | { | ||
436 | struct tuner *t = i2c_get_clientdata(c); | ||
437 | unsigned int if2; | ||
438 | |||
439 | if (t->std & V4L2_STD_525_60) { | ||
440 | // NTSC | ||
441 | if2 = 45750*1000; | ||
442 | } else { | ||
443 | // PAL | ||
444 | if2 = 38900*1000; | ||
445 | } | ||
446 | if (V4L2_TUNER_DIGITAL_TV == t->mode) { | ||
447 | // DVB (pinnacle 300i) | ||
448 | if2 = 36150*1000; | ||
449 | } | ||
450 | mt2050_set_if_freq(c, freq*62500, if2); | ||
451 | mt2050_set_antenna(c, tv_antenna); | ||
452 | } | ||
453 | |||
454 | static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq) | ||
455 | { | ||
456 | struct tuner *t = i2c_get_clientdata(c); | ||
457 | int if2 = t->radio_if2; | ||
458 | |||
459 | mt2050_set_if_freq(c, freq*62500, if2); | ||
460 | mt2050_set_antenna(c, radio_antenna); | ||
461 | } | ||
462 | |||
463 | static int mt2050_init(struct i2c_client *c) | ||
464 | { | ||
465 | struct tuner *t = i2c_get_clientdata(c); | ||
466 | unsigned char buf[2]; | ||
467 | int ret; | ||
468 | |||
469 | buf[0]=6; | ||
470 | buf[1]=0x10; | ||
471 | ret=i2c_master_send(c,buf,2); // power | ||
472 | |||
473 | buf[0]=0x0f; | ||
474 | buf[1]=0x0f; | ||
475 | ret=i2c_master_send(c,buf,2); // m1lo | ||
476 | |||
477 | buf[0]=0x0d; | ||
478 | ret=i2c_master_send(c,buf,1); | ||
479 | i2c_master_recv(c,buf,1); | ||
480 | |||
481 | tuner_dbg("mt2050: sro is %x\n",buf[0]); | ||
482 | t->tv_freq = mt2050_set_tv_freq; | ||
483 | t->radio_freq = mt2050_set_radio_freq; | ||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | int microtune_init(struct i2c_client *c) | ||
488 | { | ||
489 | struct tuner *t = i2c_get_clientdata(c); | ||
490 | char *name; | ||
491 | unsigned char buf[21]; | ||
492 | int company_code; | ||
493 | |||
494 | memset(buf,0,sizeof(buf)); | ||
495 | t->tv_freq = NULL; | ||
496 | t->radio_freq = NULL; | ||
497 | name = "unknown"; | ||
498 | |||
499 | i2c_master_send(c,buf,1); | ||
500 | i2c_master_recv(c,buf,21); | ||
501 | if (tuner_debug) { | ||
502 | int i; | ||
503 | tuner_dbg("MT20xx hexdump:"); | ||
504 | for(i=0;i<21;i++) { | ||
505 | printk(" %02x",buf[i]); | ||
506 | if(((i+1)%8)==0) printk(" "); | ||
507 | } | ||
508 | printk("\n"); | ||
509 | } | ||
510 | company_code = buf[0x11] << 8 | buf[0x12]; | ||
511 | tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n", | ||
512 | company_code,buf[0x13],buf[0x14]); | ||
513 | |||
514 | #if 0 | ||
515 | /* seems to cause more problems than it solves ... */ | ||
516 | switch (company_code) { | ||
517 | case 0x30bf: | ||
518 | case 0x3cbf: | ||
519 | case 0x3dbf: | ||
520 | case 0x4d54: | ||
521 | case 0x8e81: | ||
522 | case 0x8e91: | ||
523 | /* ok (?) */ | ||
524 | break; | ||
525 | default: | ||
526 | tuner_warn("tuner: microtune: unknown companycode\n"); | ||
527 | return 0; | ||
528 | } | ||
529 | #endif | ||
530 | |||
531 | if (buf[0x13] < ARRAY_SIZE(microtune_part) && | ||
532 | NULL != microtune_part[buf[0x13]]) | ||
533 | name = microtune_part[buf[0x13]]; | ||
534 | switch (buf[0x13]) { | ||
535 | case MT2032: | ||
536 | mt2032_init(c); | ||
537 | break; | ||
538 | case MT2050: | ||
539 | mt2050_init(c); | ||
540 | break; | ||
541 | default: | ||
542 | tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n", | ||
543 | name); | ||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | strlcpy(c->name, name, sizeof(c->name)); | ||
548 | tuner_info("microtune %s found, OK\n",name); | ||
549 | return 0; | ||
550 | } | ||
551 | |||
552 | /* | ||
553 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
554 | * --------------------------------------------------------------------------- | ||
555 | * Local variables: | ||
556 | * c-basic-offset: 8 | ||
557 | * End: | ||
558 | */ | ||