blob: d7e68a639cd836b14e657393d87650112defb2ba [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 *
3 * i2c tv tuner chip device driver
4 * controls microtune tuners, mt2032 + mt2050 at the moment.
5 */
6#include <linux/delay.h>
7#include <linux/i2c.h>
8#include <linux/videodev.h>
9#include <linux/moduleparam.h>
10#include <media/tuner.h>
11
12/* ---------------------------------------------------------------------- */
13
14static unsigned int optimize_vco = 1;
15module_param(optimize_vco, int, 0644);
16
17static unsigned int tv_antenna = 1;
18module_param(tv_antenna, int, 0644);
19
20static unsigned int radio_antenna = 0;
21module_param(radio_antenna, int, 0644);
22
Hans Verkuilfac9e892006-01-09 15:32:40 -020023/* from tuner-core.c */
Hans Verkuilf9195de2006-01-11 19:01:01 -020024extern int tuner_debug;
Hans Verkuilfac9e892006-01-09 15:32:40 -020025
Linus Torvalds1da177e2005-04-16 15:20:36 -070026/* ---------------------------------------------------------------------- */
27
28#define MT2032 0x04
29#define MT2030 0x06
30#define MT2040 0x07
31#define MT2050 0x42
32
33static char *microtune_part[] = {
34 [ MT2030 ] = "MT2030",
35 [ MT2032 ] = "MT2032",
36 [ MT2040 ] = "MT2040",
37 [ MT2050 ] = "MT2050",
38};
39
Michael Krufkyb2083192007-05-29 22:54:06 -030040struct microtune_priv {
41 unsigned int xogc;
42 unsigned int radio_if2;
43};
44
Linus Torvalds1da177e2005-04-16 15:20:36 -070045// IsSpurInBand()?
46static int mt2032_spurcheck(struct i2c_client *c,
47 int f1, int f2, int spectrum_from,int spectrum_to)
48{
49 struct tuner *t = i2c_get_clientdata(c);
50 int n1=1,n2,f;
51
52 f1=f1/1000; //scale to kHz to avoid 32bit overflows
53 f2=f2/1000;
54 spectrum_from/=1000;
55 spectrum_to/=1000;
56
57 tuner_dbg("spurcheck f1=%d f2=%d from=%d to=%d\n",
58 f1,f2,spectrum_from,spectrum_to);
59
60 do {
61 n2=-n1;
62 f=n1*(f1-f2);
63 do {
64 n2--;
65 f=f-f2;
66 tuner_dbg("spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f);
67
68 if( (f>spectrum_from) && (f<spectrum_to))
69 tuner_dbg("mt2032 spurcheck triggered: %d\n",n1);
70 } while ( (f>(f2-spectrum_to)) || (n2>-5));
71 n1++;
72 } while (n1<5);
73
74 return 1;
75}
76
77static int mt2032_compute_freq(struct i2c_client *c,
78 unsigned int rfin,
79 unsigned int if1, unsigned int if2,
80 unsigned int spectrum_from,
81 unsigned int spectrum_to,
82 unsigned char *buf,
83 int *ret_sel,
84 unsigned int xogc) //all in Hz
85{
86 struct tuner *t = i2c_get_clientdata(c);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -080087 unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1,
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq;
89
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -080090 fref= 5250 *1000; //5.25MHz
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 desired_lo1=rfin+if1;
92
93 lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -080094 lo1n=lo1/8;
95 lo1a=lo1-(lo1n*8);
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -080097 s=rfin/1000/1000+1090;
Linus Torvalds1da177e2005-04-16 15:20:36 -070098
99 if(optimize_vco) {
100 if(s>1890) sel=0;
101 else if(s>1720) sel=1;
102 else if(s>1530) sel=2;
103 else if(s>1370) sel=3;
104 else sel=4; // >1090
105 }
106 else {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800107 if(s>1790) sel=0; // <1958
108 else if(s>1617) sel=1;
109 else if(s>1449) sel=2;
110 else if(s>1291) sel=3;
111 else sel=4; // >1090
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 }
113 *ret_sel=sel;
114
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800115 lo1freq=(lo1a+8*lo1n)*fref;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
117 tuner_dbg("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n",
118 rfin,lo1,lo1n,lo1a,sel,lo1freq);
119
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800120 desired_lo2=lo1freq-rfin-if2;
121 lo2=(desired_lo2)/fref;
122 lo2n=lo2/8;
123 lo2a=lo2-(lo2n*8);
124 lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith
125 lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
127 tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n",
128 rfin,lo2,lo2n,lo2a,lo2num,lo2freq);
129
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800130 if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n",
132 lo1a, lo1n, lo2a,lo2n);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800133 return(-1);
134 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135
136 mt2032_spurcheck(c, lo1freq, desired_lo2, spectrum_from, spectrum_to);
137 // should recalculate lo1 (one step up/down)
138
139 // set up MT2032 register map for transfer over i2c
140 buf[0]=lo1n-1;
141 buf[1]=lo1a | (sel<<4);
142 buf[2]=0x86; // LOGC
143 buf[3]=0x0f; //reserved
144 buf[4]=0x1f;
145 buf[5]=(lo2n-1) | (lo2a<<5);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800146 if(rfin >400*1000*1000)
147 buf[6]=0xe4;
148 else
149 buf[6]=0xf4; // set PKEN per rev 1.2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 buf[7]=8+xogc;
151 buf[8]=0xc3; //reserved
152 buf[9]=0x4e; //reserved
153 buf[10]=0xec; //reserved
154 buf[11]=(lo2num&0xff);
155 buf[12]=(lo2num>>8) |0x80; // Lo2RST
156
157 return 0;
158}
159
160static int mt2032_check_lo_lock(struct i2c_client *c)
161{
162 struct tuner *t = i2c_get_clientdata(c);
163 int try,lock=0;
164 unsigned char buf[2];
165
166 for(try=0;try<10;try++) {
167 buf[0]=0x0e;
168 i2c_master_send(c,buf,1);
169 i2c_master_recv(c,buf,1);
170 tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]);
171 lock=buf[0] &0x06;
172
173 if (lock==6)
174 break;
175
176 tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]);
177 udelay(1000);
178 }
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800179 return lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180}
181
182static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock)
183{
184 struct tuner *t = i2c_get_clientdata(c);
185 unsigned char buf[2];
186 int tad1;
187
188 buf[0]=0x0f;
189 i2c_master_send(c,buf,1);
190 i2c_master_recv(c,buf,1);
191 tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]);
192 tad1=buf[0]&0x07;
193
194 if(tad1 ==0) return lock;
195 if(tad1 ==1) return lock;
196
197 if(tad1==2) {
198 if(sel==0)
199 return lock;
200 else sel--;
201 }
202 else {
203 if(sel<4)
204 sel++;
205 else
206 return lock;
207 }
208
209 tuner_dbg("mt2032 optimize_vco: sel=%d\n",sel);
210
211 buf[0]=0x0f;
212 buf[1]=sel;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800213 i2c_master_send(c,buf,2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 lock=mt2032_check_lo_lock(c);
215 return lock;
216}
217
218
219static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin,
220 unsigned int if1, unsigned int if2,
221 unsigned int from, unsigned int to)
222{
223 unsigned char buf[21];
224 int lint_try,ret,sel,lock=0;
225 struct tuner *t = i2c_get_clientdata(c);
Michael Krufkyb2083192007-05-29 22:54:06 -0300226 struct microtune_priv *priv = t->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227
228 tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",
229 rfin,if1,if2,from,to);
230
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800231 buf[0]=0;
232 ret=i2c_master_send(c,buf,1);
233 i2c_master_recv(c,buf,21);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234
235 buf[0]=0;
Michael Krufkyb2083192007-05-29 22:54:06 -0300236 ret=mt2032_compute_freq(c,rfin,if1,if2,from,to,&buf[1],&sel,priv->xogc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 if (ret<0)
238 return;
239
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800240 // send only the relevant registers per Rev. 1.2
241 buf[0]=0;
242 ret=i2c_master_send(c,buf,4);
243 buf[5]=5;
244 ret=i2c_master_send(c,buf+5,4);
245 buf[11]=11;
246 ret=i2c_master_send(c,buf+11,3);
247 if(ret!=3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret);
249
250 // wait for PLLs to lock (per manual), retry LINT if not.
251 for(lint_try=0; lint_try<2; lint_try++) {
252 lock=mt2032_check_lo_lock(c);
253
254 if(optimize_vco)
255 lock=mt2032_optimize_vco(c,sel,lock);
256 if(lock==6) break;
257
258 tuner_dbg("mt2032: re-init PLLs by LINT\n");
259 buf[0]=7;
Michael Krufkyb2083192007-05-29 22:54:06 -0300260 buf[1]=0x80 +8+priv->xogc; // set LINT to re-init PLLs
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 i2c_master_send(c,buf,2);
262 mdelay(10);
Michael Krufkyb2083192007-05-29 22:54:06 -0300263 buf[1]=8+priv->xogc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 i2c_master_send(c,buf,2);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800265 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
267 if (lock!=6)
268 tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n");
269
270 buf[0]=2;
271 buf[1]=0x20; // LOGC for optimal phase noise
272 ret=i2c_master_send(c,buf,2);
273 if (ret!=2)
274 tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
275}
276
277
278static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq)
279{
280 struct tuner *t = i2c_get_clientdata(c);
281 int if2,from,to;
282
283 // signal bandwidth and picture carrier
284 if (t->std & V4L2_STD_525_60) {
285 // NTSC
286 from = 40750*1000;
287 to = 46750*1000;
288 if2 = 45750*1000;
289 } else {
290 // PAL
291 from = 32900*1000;
292 to = 39900*1000;
293 if2 = 38900*1000;
294 }
295
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800296 mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 1090*1000*1000, if2, from, to);
298}
299
300static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq)
301{
302 struct tuner *t = i2c_get_clientdata(c);
Michael Krufkyb2083192007-05-29 22:54:06 -0300303 struct microtune_priv *priv = t->priv;
304 int if2 = priv->radio_if2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
306 // per Manual for FM tuning: first if center freq. 1085 MHz
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800307 mt2032_set_if_freq(c, freq * 1000 / 16,
Mauro Carvalho Chehab586b0ca2005-06-28 20:45:21 -0700308 1085*1000*1000,if2,if2,if2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309}
310
311// Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
312static int mt2032_init(struct i2c_client *c)
313{
314 struct tuner *t = i2c_get_clientdata(c);
Michael Krufkyb2083192007-05-29 22:54:06 -0300315 struct microtune_priv *priv = t->priv;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800316 unsigned char buf[21];
317 int ret,xogc,xok=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318
319 // Initialize Registers per spec.
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800320 buf[1]=2; // Index to register 2
321 buf[2]=0xff;
322 buf[3]=0x0f;
323 buf[4]=0x1f;
324 ret=i2c_master_send(c,buf+1,4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800326 buf[5]=6; // Index register 6
327 buf[6]=0xe4;
328 buf[7]=0x8f;
329 buf[8]=0xc3;
330 buf[9]=0x4e;
331 buf[10]=0xec;
332 ret=i2c_master_send(c,buf+5,6);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800334 buf[12]=13; // Index register 13
335 buf[13]=0x32;
336 ret=i2c_master_send(c,buf+12,2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800338 // Adjust XOGC (register 7), wait for XOK
339 xogc=7;
340 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800342 mdelay(10);
343 buf[0]=0x0e;
344 i2c_master_send(c,buf,1);
345 i2c_master_recv(c,buf,1);
346 xok=buf[0]&0x01;
347 tuner_dbg("mt2032: xok = 0x%02x\n",xok);
348 if (xok == 1) break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800350 xogc--;
351 tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
352 if (xogc == 3) {
353 xogc=4; // min. 4 per spec
354 break;
355 }
356 buf[0]=0x07;
357 buf[1]=0x88 + xogc;
358 ret=i2c_master_send(c,buf,2);
359 if (ret!=2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800361 } while (xok != 1 );
Michael Krufkyb2083192007-05-29 22:54:06 -0300362 priv->xogc=xogc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
Hans Verkuil27487d42006-01-15 15:04:52 -0200364 t->set_tv_freq = mt2032_set_tv_freq;
365 t->set_radio_freq = mt2032_set_radio_freq;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800366 return(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367}
368
369static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna)
370{
371 struct tuner *t = i2c_get_clientdata(c);
Michael Krufky56584c92007-05-29 15:36:37 -0300372 unsigned char buf[2];
373 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
Michael Krufky56584c92007-05-29 15:36:37 -0300375 buf[0] = 6;
376 buf[1] = antenna ? 0x11 : 0x10;
377 ret=i2c_master_send(c,buf,2);
378 tuner_dbg("mt2050: enabled antenna connector %d\n", antenna);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379}
380
381static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned int if2)
382{
383 struct tuner *t = i2c_get_clientdata(c);
384 unsigned int if1=1218*1000*1000;
385 unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b;
386 int ret;
387 unsigned char buf[6];
388
389 tuner_dbg("mt2050_set_if_freq freq=%d if1=%d if2=%d\n",
390 freq,if1,if2);
391
392 f_lo1=freq+if1;
393 f_lo1=(f_lo1/1000000)*1000000;
394
395 f_lo2=f_lo1-freq-if2;
396 f_lo2=(f_lo2/50000)*50000;
397
398 lo1=f_lo1/4000000;
399 lo2=f_lo2/4000000;
400
401 f_lo1_modulo= f_lo1-(lo1*4000000);
402 f_lo2_modulo= f_lo2-(lo2*4000000);
403
404 num1=4*f_lo1_modulo/4000000;
405 num2=4096*(f_lo2_modulo/1000)/4000;
406
407 // todo spurchecks
408
409 div1a=(lo1/12)-1;
410 div1b=lo1-(div1a+1)*12;
411
412 div2a=(lo2/8)-1;
413 div2b=lo2-(div2a+1)*8;
414
Hans Verkuilf9195de2006-01-11 19:01:01 -0200415 if (tuner_debug > 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 tuner_dbg("lo1 lo2 = %d %d\n", lo1, lo2);
417 tuner_dbg("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n",
418 num1,num2,div1a,div1b,div2a,div2b);
419 }
420
421 buf[0]=1;
422 buf[1]= 4*div1b + num1;
423 if(freq<275*1000*1000) buf[1] = buf[1]|0x80;
424
425 buf[2]=div1a;
426 buf[3]=32*div2b + num2/256;
427 buf[4]=num2-(num2/256)*256;
428 buf[5]=div2a;
429 if(num2!=0) buf[5]=buf[5]|0x40;
430
Hans Verkuilf9195de2006-01-11 19:01:01 -0200431 if (tuner_debug > 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 int i;
433 tuner_dbg("bufs is: ");
434 for(i=0;i<6;i++)
435 printk("%x ",buf[i]);
436 printk("\n");
437 }
438
439 ret=i2c_master_send(c,buf,6);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800440 if (ret!=6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret);
442}
443
444static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq)
445{
446 struct tuner *t = i2c_get_clientdata(c);
447 unsigned int if2;
448
449 if (t->std & V4L2_STD_525_60) {
450 // NTSC
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800451 if2 = 45750*1000;
452 } else {
453 // PAL
454 if2 = 38900*1000;
455 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 if (V4L2_TUNER_DIGITAL_TV == t->mode) {
457 // DVB (pinnacle 300i)
458 if2 = 36150*1000;
459 }
460 mt2050_set_if_freq(c, freq*62500, if2);
461 mt2050_set_antenna(c, tv_antenna);
462}
463
464static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq)
465{
466 struct tuner *t = i2c_get_clientdata(c);
Michael Krufkyb2083192007-05-29 22:54:06 -0300467 struct microtune_priv *priv = t->priv;
468 int if2 = priv->radio_if2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
Nickolay V. Shmyreve9d096d2005-11-08 21:38:17 -0800470 mt2050_set_if_freq(c, freq * 1000 / 16, if2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 mt2050_set_antenna(c, radio_antenna);
472}
473
474static int mt2050_init(struct i2c_client *c)
475{
476 struct tuner *t = i2c_get_clientdata(c);
477 unsigned char buf[2];
478 int ret;
479
480 buf[0]=6;
481 buf[1]=0x10;
482 ret=i2c_master_send(c,buf,2); // power
483
484 buf[0]=0x0f;
485 buf[1]=0x0f;
486 ret=i2c_master_send(c,buf,2); // m1lo
487
488 buf[0]=0x0d;
489 ret=i2c_master_send(c,buf,1);
490 i2c_master_recv(c,buf,1);
491
492 tuner_dbg("mt2050: sro is %x\n",buf[0]);
Hans Verkuil27487d42006-01-15 15:04:52 -0200493 t->set_tv_freq = mt2050_set_tv_freq;
494 t->set_radio_freq = mt2050_set_radio_freq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 return 0;
496}
497
498int microtune_init(struct i2c_client *c)
499{
Michael Krufkyb2083192007-05-29 22:54:06 -0300500 struct microtune_priv *priv = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 struct tuner *t = i2c_get_clientdata(c);
502 char *name;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800503 unsigned char buf[21];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 int company_code;
505
Michael Krufkyb2083192007-05-29 22:54:06 -0300506 priv = kzalloc(sizeof(struct microtune_priv), GFP_KERNEL);
507 if (priv == NULL)
508 return -ENOMEM;
509 t->priv = priv;
510
511 priv->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */
512
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 memset(buf,0,sizeof(buf));
Hans Verkuil27487d42006-01-15 15:04:52 -0200514 t->set_tv_freq = NULL;
515 t->set_radio_freq = NULL;
Mauro Carvalho Chehab793cf9e2005-09-09 13:03:37 -0700516 t->standby = NULL;
Hans Verkuil39e8f402006-01-09 15:25:16 -0200517 if (t->std & V4L2_STD_525_60) {
518 tuner_dbg("pinnacle ntsc\n");
Michael Krufkyb2083192007-05-29 22:54:06 -0300519 priv->radio_if2 = 41300 * 1000;
Hans Verkuil39e8f402006-01-09 15:25:16 -0200520 } else {
521 tuner_dbg("pinnacle pal\n");
Michael Krufkyb2083192007-05-29 22:54:06 -0300522 priv->radio_if2 = 33300 * 1000;
Hans Verkuil39e8f402006-01-09 15:25:16 -0200523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 name = "unknown";
525
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800526 i2c_master_send(c,buf,1);
527 i2c_master_recv(c,buf,21);
Hans Verkuilf9195de2006-01-11 19:01:01 -0200528 if (tuner_debug) {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800529 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 tuner_dbg("MT20xx hexdump:");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800531 for(i=0;i<21;i++) {
532 printk(" %02x",buf[i]);
533 if(((i+1)%8)==0) printk(" ");
534 }
535 printk("\n");
536 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 company_code = buf[0x11] << 8 | buf[0x12];
538 tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n",
539 company_code,buf[0x13],buf[0x14]);
540
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541
542 if (buf[0x13] < ARRAY_SIZE(microtune_part) &&
543 NULL != microtune_part[buf[0x13]])
544 name = microtune_part[buf[0x13]];
545 switch (buf[0x13]) {
546 case MT2032:
547 mt2032_init(c);
548 break;
549 case MT2050:
550 mt2050_init(c);
551 break;
552 default:
553 tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n",
554 name);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800555 return 0;
556 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557
558 strlcpy(c->name, name, sizeof(c->name));
559 tuner_info("microtune %s found, OK\n",name);
560 return 0;
561}
562
563/*
564 * Overrides for Emacs so that we follow Linus's tabbing style.
565 * ---------------------------------------------------------------------------
566 * Local variables:
567 * c-basic-offset: 8
568 * End:
569 */