Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * i2c tv tuner chip device driver
0004  * controls microtune tuners, mt2032 + mt2050 at the moment.
0005  *
0006  * This "mt20xx" module was split apart from the original "tuner" module.
0007  */
0008 #include <linux/delay.h>
0009 #include <linux/i2c.h>
0010 #include <linux/slab.h>
0011 #include <linux/videodev2.h>
0012 #include "tuner-i2c.h"
0013 #include "mt20xx.h"
0014 
0015 static int debug;
0016 module_param(debug, int, 0644);
0017 MODULE_PARM_DESC(debug, "enable verbose debug messages");
0018 
0019 /* ---------------------------------------------------------------------- */
0020 
0021 static unsigned int optimize_vco  = 1;
0022 module_param(optimize_vco,      int, 0644);
0023 
0024 static unsigned int tv_antenna    = 1;
0025 module_param(tv_antenna,        int, 0644);
0026 
0027 static unsigned int radio_antenna;
0028 module_param(radio_antenna,     int, 0644);
0029 
0030 /* ---------------------------------------------------------------------- */
0031 
0032 #define MT2032 0x04
0033 #define MT2030 0x06
0034 #define MT2040 0x07
0035 #define MT2050 0x42
0036 
0037 static char *microtune_part[] = {
0038     [ MT2030 ] = "MT2030",
0039     [ MT2032 ] = "MT2032",
0040     [ MT2040 ] = "MT2040",
0041     [ MT2050 ] = "MT2050",
0042 };
0043 
0044 struct microtune_priv {
0045     struct tuner_i2c_props i2c_props;
0046 
0047     unsigned int xogc;
0048     //unsigned int radio_if2;
0049 
0050     u32 frequency;
0051 };
0052 
0053 static void microtune_release(struct dvb_frontend *fe)
0054 {
0055     kfree(fe->tuner_priv);
0056     fe->tuner_priv = NULL;
0057 }
0058 
0059 static int microtune_get_frequency(struct dvb_frontend *fe, u32 *frequency)
0060 {
0061     struct microtune_priv *priv = fe->tuner_priv;
0062     *frequency = priv->frequency;
0063     return 0;
0064 }
0065 
0066 // IsSpurInBand()?
0067 static int mt2032_spurcheck(struct dvb_frontend *fe,
0068                 int f1, int f2, int spectrum_from,int spectrum_to)
0069 {
0070     struct microtune_priv *priv = fe->tuner_priv;
0071     int n1=1,n2,f;
0072 
0073     f1=f1/1000; //scale to kHz to avoid 32bit overflows
0074     f2=f2/1000;
0075     spectrum_from/=1000;
0076     spectrum_to/=1000;
0077 
0078     tuner_dbg("spurcheck f1=%d f2=%d  from=%d to=%d\n",
0079           f1,f2,spectrum_from,spectrum_to);
0080 
0081     do {
0082         n2=-n1;
0083         f=n1*(f1-f2);
0084         do {
0085         n2--;
0086         f=f-f2;
0087         tuner_dbg("spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f);
0088 
0089         if( (f>spectrum_from) && (f<spectrum_to))
0090             tuner_dbg("mt2032 spurcheck triggered: %d\n",n1);
0091         } while ( (f>(f2-spectrum_to)) || (n2>-5));
0092         n1++;
0093     } while (n1<5);
0094 
0095     return 1;
0096 }
0097 
0098 static int mt2032_compute_freq(struct dvb_frontend *fe,
0099                    unsigned int rfin,
0100                    unsigned int if1, unsigned int if2,
0101                    unsigned int spectrum_from,
0102                    unsigned int spectrum_to,
0103                    unsigned char *buf,
0104                    int *ret_sel,
0105                    unsigned int xogc) //all in Hz
0106 {
0107     struct microtune_priv *priv = fe->tuner_priv;
0108     unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1,
0109         desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq;
0110 
0111     fref= 5250 *1000; //5.25MHz
0112     desired_lo1=rfin+if1;
0113 
0114     lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000);
0115     lo1n=lo1/8;
0116     lo1a=lo1-(lo1n*8);
0117 
0118     s=rfin/1000/1000+1090;
0119 
0120     if(optimize_vco) {
0121         if(s>1890) sel=0;
0122         else if(s>1720) sel=1;
0123         else if(s>1530) sel=2;
0124         else if(s>1370) sel=3;
0125         else sel=4; // >1090
0126     }
0127     else {
0128         if(s>1790) sel=0; // <1958
0129         else if(s>1617) sel=1;
0130         else if(s>1449) sel=2;
0131         else if(s>1291) sel=3;
0132         else sel=4; // >1090
0133     }
0134     *ret_sel=sel;
0135 
0136     lo1freq=(lo1a+8*lo1n)*fref;
0137 
0138     tuner_dbg("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n",
0139           rfin,lo1,lo1n,lo1a,sel,lo1freq);
0140 
0141     desired_lo2=lo1freq-rfin-if2;
0142     lo2=(desired_lo2)/fref;
0143     lo2n=lo2/8;
0144     lo2a=lo2-(lo2n*8);
0145     lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith
0146     lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000;
0147 
0148     tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n",
0149           rfin,lo2,lo2n,lo2a,lo2num,lo2freq);
0150 
0151     if (lo1a > 7 || lo1n < 17 || lo1n > 48 || lo2a > 7 || lo2n < 17 ||
0152             lo2n > 30) {
0153         tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n",
0154                lo1a, lo1n, lo2a,lo2n);
0155         return(-1);
0156     }
0157 
0158     mt2032_spurcheck(fe, lo1freq, desired_lo2,  spectrum_from, spectrum_to);
0159     // should recalculate lo1 (one step up/down)
0160 
0161     // set up MT2032 register map for transfer over i2c
0162     buf[0]=lo1n-1;
0163     buf[1]=lo1a | (sel<<4);
0164     buf[2]=0x86; // LOGC
0165     buf[3]=0x0f; //reserved
0166     buf[4]=0x1f;
0167     buf[5]=(lo2n-1) | (lo2a<<5);
0168     if(rfin >400*1000*1000)
0169         buf[6]=0xe4;
0170     else
0171         buf[6]=0xf4; // set PKEN per rev 1.2
0172     buf[7]=8+xogc;
0173     buf[8]=0xc3; //reserved
0174     buf[9]=0x4e; //reserved
0175     buf[10]=0xec; //reserved
0176     buf[11]=(lo2num&0xff);
0177     buf[12]=(lo2num>>8) |0x80; // Lo2RST
0178 
0179     return 0;
0180 }
0181 
0182 static int mt2032_check_lo_lock(struct dvb_frontend *fe)
0183 {
0184     struct microtune_priv *priv = fe->tuner_priv;
0185     int try,lock=0;
0186     unsigned char buf[2];
0187 
0188     for(try=0;try<10;try++) {
0189         buf[0]=0x0e;
0190         tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
0191         tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
0192         tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]);
0193         lock=buf[0] &0x06;
0194 
0195         if (lock==6)
0196             break;
0197 
0198         tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]);
0199         udelay(1000);
0200     }
0201     return lock;
0202 }
0203 
0204 static int mt2032_optimize_vco(struct dvb_frontend *fe,int sel,int lock)
0205 {
0206     struct microtune_priv *priv = fe->tuner_priv;
0207     unsigned char buf[2];
0208     int tad1;
0209 
0210     buf[0]=0x0f;
0211     tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
0212     tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
0213     tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]);
0214     tad1=buf[0]&0x07;
0215 
0216     if(tad1 ==0) return lock;
0217     if(tad1 ==1) return lock;
0218 
0219     if(tad1==2) {
0220         if(sel==0)
0221             return lock;
0222         else sel--;
0223     }
0224     else {
0225         if(sel<4)
0226             sel++;
0227         else
0228             return lock;
0229     }
0230 
0231     tuner_dbg("mt2032 optimize_vco: sel=%d\n",sel);
0232 
0233     buf[0]=0x0f;
0234     buf[1]=sel;
0235     tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
0236     lock=mt2032_check_lo_lock(fe);
0237     return lock;
0238 }
0239 
0240 
0241 static void mt2032_set_if_freq(struct dvb_frontend *fe, unsigned int rfin,
0242                    unsigned int if1, unsigned int if2,
0243                    unsigned int from, unsigned int to)
0244 {
0245     unsigned char buf[21];
0246     int lint_try,ret,sel,lock=0;
0247     struct microtune_priv *priv = fe->tuner_priv;
0248 
0249     tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",
0250           rfin,if1,if2,from,to);
0251 
0252     buf[0]=0;
0253     ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
0254     tuner_i2c_xfer_recv(&priv->i2c_props,buf,21);
0255 
0256     buf[0]=0;
0257     ret=mt2032_compute_freq(fe,rfin,if1,if2,from,to,&buf[1],&sel,priv->xogc);
0258     if (ret<0)
0259         return;
0260 
0261     // send only the relevant registers per Rev. 1.2
0262     buf[0]=0;
0263     ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,4);
0264     buf[5]=5;
0265     ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,4);
0266     buf[11]=11;
0267     ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+11,3);
0268     if(ret!=3)
0269         tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret);
0270 
0271     // wait for PLLs to lock (per manual), retry LINT if not.
0272     for(lint_try=0; lint_try<2; lint_try++) {
0273         lock=mt2032_check_lo_lock(fe);
0274 
0275         if(optimize_vco)
0276             lock=mt2032_optimize_vco(fe,sel,lock);
0277         if(lock==6) break;
0278 
0279         tuner_dbg("mt2032: re-init PLLs by LINT\n");
0280         buf[0]=7;
0281         buf[1]=0x80 +8+priv->xogc; // set LINT to re-init PLLs
0282         tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
0283         mdelay(10);
0284         buf[1]=8+priv->xogc;
0285         tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
0286     }
0287 
0288     if (lock!=6)
0289         tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n");
0290 
0291     buf[0]=2;
0292     buf[1]=0x20; // LOGC for optimal phase noise
0293     ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
0294     if (ret!=2)
0295         tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
0296 }
0297 
0298 
0299 static int mt2032_set_tv_freq(struct dvb_frontend *fe,
0300                   struct analog_parameters *params)
0301 {
0302     int if2,from,to;
0303 
0304     // signal bandwidth and picture carrier
0305     if (params->std & V4L2_STD_525_60) {
0306         // NTSC
0307         from = 40750*1000;
0308         to   = 46750*1000;
0309         if2  = 45750*1000;
0310     } else {
0311         // PAL
0312         from = 32900*1000;
0313         to   = 39900*1000;
0314         if2  = 38900*1000;
0315     }
0316 
0317     mt2032_set_if_freq(fe, params->frequency*62500,
0318                1090*1000*1000, if2, from, to);
0319 
0320     return 0;
0321 }
0322 
0323 static int mt2032_set_radio_freq(struct dvb_frontend *fe,
0324                  struct analog_parameters *params)
0325 {
0326     struct microtune_priv *priv = fe->tuner_priv;
0327     int if2;
0328 
0329     if (params->std & V4L2_STD_525_60) {
0330         tuner_dbg("pinnacle ntsc\n");
0331         if2 = 41300 * 1000;
0332     } else {
0333         tuner_dbg("pinnacle pal\n");
0334         if2 = 33300 * 1000;
0335     }
0336 
0337     // per Manual for FM tuning: first if center freq. 1085 MHz
0338     mt2032_set_if_freq(fe, params->frequency * 125 / 2,
0339                1085*1000*1000,if2,if2,if2);
0340 
0341     return 0;
0342 }
0343 
0344 static int mt2032_set_params(struct dvb_frontend *fe,
0345                  struct analog_parameters *params)
0346 {
0347     struct microtune_priv *priv = fe->tuner_priv;
0348     int ret = -EINVAL;
0349 
0350     switch (params->mode) {
0351     case V4L2_TUNER_RADIO:
0352         ret = mt2032_set_radio_freq(fe, params);
0353         priv->frequency = params->frequency * 125 / 2;
0354         break;
0355     case V4L2_TUNER_ANALOG_TV:
0356     case V4L2_TUNER_DIGITAL_TV:
0357         ret = mt2032_set_tv_freq(fe, params);
0358         priv->frequency = params->frequency * 62500;
0359         break;
0360     }
0361 
0362     return ret;
0363 }
0364 
0365 static const struct dvb_tuner_ops mt2032_tuner_ops = {
0366     .set_analog_params = mt2032_set_params,
0367     .release           = microtune_release,
0368     .get_frequency     = microtune_get_frequency,
0369 };
0370 
0371 // Initialization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
0372 static int mt2032_init(struct dvb_frontend *fe)
0373 {
0374     struct microtune_priv *priv = fe->tuner_priv;
0375     unsigned char buf[21];
0376     int ret,xogc,xok=0;
0377 
0378     // Initialize Registers per spec.
0379     buf[1]=2; // Index to register 2
0380     buf[2]=0xff;
0381     buf[3]=0x0f;
0382     buf[4]=0x1f;
0383     ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+1,4);
0384 
0385     buf[5]=6; // Index register 6
0386     buf[6]=0xe4;
0387     buf[7]=0x8f;
0388     buf[8]=0xc3;
0389     buf[9]=0x4e;
0390     buf[10]=0xec;
0391     ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,6);
0392 
0393     buf[12]=13;  // Index register 13
0394     buf[13]=0x32;
0395     ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+12,2);
0396 
0397     // Adjust XOGC (register 7), wait for XOK
0398     xogc=7;
0399     do {
0400         tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
0401         mdelay(10);
0402         buf[0]=0x0e;
0403         tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
0404         tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
0405         xok=buf[0]&0x01;
0406         tuner_dbg("mt2032: xok = 0x%02x\n",xok);
0407         if (xok == 1) break;
0408 
0409         xogc--;
0410         tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
0411         if (xogc == 3) {
0412             xogc=4; // min. 4 per spec
0413             break;
0414         }
0415         buf[0]=0x07;
0416         buf[1]=0x88 + xogc;
0417         ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
0418         if (ret!=2)
0419             tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
0420     } while (xok != 1 );
0421     priv->xogc=xogc;
0422 
0423     memcpy(&fe->ops.tuner_ops, &mt2032_tuner_ops, sizeof(struct dvb_tuner_ops));
0424 
0425     return(1);
0426 }
0427 
0428 static void mt2050_set_antenna(struct dvb_frontend *fe, unsigned char antenna)
0429 {
0430     struct microtune_priv *priv = fe->tuner_priv;
0431     unsigned char buf[2];
0432 
0433     buf[0] = 6;
0434     buf[1] = antenna ? 0x11 : 0x10;
0435     tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
0436     tuner_dbg("mt2050: enabled antenna connector %d\n", antenna);
0437 }
0438 
0439 static void mt2050_set_if_freq(struct dvb_frontend *fe,unsigned int freq, unsigned int if2)
0440 {
0441     struct microtune_priv *priv = fe->tuner_priv;
0442     unsigned int if1=1218*1000*1000;
0443     unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b;
0444     int ret;
0445     unsigned char buf[6];
0446 
0447     tuner_dbg("mt2050_set_if_freq freq=%d if1=%d if2=%d\n",
0448           freq,if1,if2);
0449 
0450     f_lo1=freq+if1;
0451     f_lo1=(f_lo1/1000000)*1000000;
0452 
0453     f_lo2=f_lo1-freq-if2;
0454     f_lo2=(f_lo2/50000)*50000;
0455 
0456     lo1=f_lo1/4000000;
0457     lo2=f_lo2/4000000;
0458 
0459     f_lo1_modulo= f_lo1-(lo1*4000000);
0460     f_lo2_modulo= f_lo2-(lo2*4000000);
0461 
0462     num1=4*f_lo1_modulo/4000000;
0463     num2=4096*(f_lo2_modulo/1000)/4000;
0464 
0465     // todo spurchecks
0466 
0467     div1a=(lo1/12)-1;
0468     div1b=lo1-(div1a+1)*12;
0469 
0470     div2a=(lo2/8)-1;
0471     div2b=lo2-(div2a+1)*8;
0472 
0473     if (debug > 1) {
0474         tuner_dbg("lo1 lo2 = %d %d\n", lo1, lo2);
0475         tuner_dbg("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n",
0476               num1,num2,div1a,div1b,div2a,div2b);
0477     }
0478 
0479     buf[0]=1;
0480     buf[1]= 4*div1b + num1;
0481     if(freq<275*1000*1000) buf[1] = buf[1]|0x80;
0482 
0483     buf[2]=div1a;
0484     buf[3]=32*div2b + num2/256;
0485     buf[4]=num2-(num2/256)*256;
0486     buf[5]=div2a;
0487     if(num2!=0) buf[5]=buf[5]|0x40;
0488 
0489     if (debug > 1)
0490         tuner_dbg("bufs is: %*ph\n", 6, buf);
0491 
0492     ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,6);
0493     if (ret!=6)
0494         tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret);
0495 }
0496 
0497 static int mt2050_set_tv_freq(struct dvb_frontend *fe,
0498                   struct analog_parameters *params)
0499 {
0500     unsigned int if2;
0501 
0502     if (params->std & V4L2_STD_525_60) {
0503         // NTSC
0504         if2 = 45750*1000;
0505     } else {
0506         // PAL
0507         if2 = 38900*1000;
0508     }
0509     if (V4L2_TUNER_DIGITAL_TV == params->mode) {
0510         // DVB (pinnacle 300i)
0511         if2 = 36150*1000;
0512     }
0513     mt2050_set_if_freq(fe, params->frequency*62500, if2);
0514     mt2050_set_antenna(fe, tv_antenna);
0515 
0516     return 0;
0517 }
0518 
0519 static int mt2050_set_radio_freq(struct dvb_frontend *fe,
0520                  struct analog_parameters *params)
0521 {
0522     struct microtune_priv *priv = fe->tuner_priv;
0523     int if2;
0524 
0525     if (params->std & V4L2_STD_525_60) {
0526         tuner_dbg("pinnacle ntsc\n");
0527         if2 = 41300 * 1000;
0528     } else {
0529         tuner_dbg("pinnacle pal\n");
0530         if2 = 33300 * 1000;
0531     }
0532 
0533     mt2050_set_if_freq(fe, params->frequency * 125 / 2, if2);
0534     mt2050_set_antenna(fe, radio_antenna);
0535 
0536     return 0;
0537 }
0538 
0539 static int mt2050_set_params(struct dvb_frontend *fe,
0540                  struct analog_parameters *params)
0541 {
0542     struct microtune_priv *priv = fe->tuner_priv;
0543     int ret = -EINVAL;
0544 
0545     switch (params->mode) {
0546     case V4L2_TUNER_RADIO:
0547         ret = mt2050_set_radio_freq(fe, params);
0548         priv->frequency = params->frequency * 125 / 2;
0549         break;
0550     case V4L2_TUNER_ANALOG_TV:
0551     case V4L2_TUNER_DIGITAL_TV:
0552         ret = mt2050_set_tv_freq(fe, params);
0553         priv->frequency = params->frequency * 62500;
0554         break;
0555     }
0556 
0557     return ret;
0558 }
0559 
0560 static const struct dvb_tuner_ops mt2050_tuner_ops = {
0561     .set_analog_params = mt2050_set_params,
0562     .release           = microtune_release,
0563     .get_frequency     = microtune_get_frequency,
0564 };
0565 
0566 static int mt2050_init(struct dvb_frontend *fe)
0567 {
0568     struct microtune_priv *priv = fe->tuner_priv;
0569     unsigned char buf[2];
0570 
0571     buf[0] = 6;
0572     buf[1] = 0x10;
0573     tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); /* power */
0574 
0575     buf[0] = 0x0f;
0576     buf[1] = 0x0f;
0577     tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); /* m1lo */
0578 
0579     buf[0] = 0x0d;
0580     tuner_i2c_xfer_send(&priv->i2c_props, buf, 1);
0581     tuner_i2c_xfer_recv(&priv->i2c_props, buf, 1);
0582 
0583     tuner_dbg("mt2050: sro is %x\n", buf[0]);
0584 
0585     memcpy(&fe->ops.tuner_ops, &mt2050_tuner_ops, sizeof(struct dvb_tuner_ops));
0586 
0587     return 0;
0588 }
0589 
0590 struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
0591                       struct i2c_adapter* i2c_adap,
0592                       u8 i2c_addr)
0593 {
0594     struct microtune_priv *priv = NULL;
0595     char *name;
0596     unsigned char buf[21];
0597     int company_code;
0598 
0599     priv = kzalloc(sizeof(struct microtune_priv), GFP_KERNEL);
0600     if (priv == NULL)
0601         return NULL;
0602     fe->tuner_priv = priv;
0603 
0604     priv->i2c_props.addr = i2c_addr;
0605     priv->i2c_props.adap = i2c_adap;
0606     priv->i2c_props.name = "mt20xx";
0607 
0608     //priv->radio_if2 = 10700 * 1000;   /* 10.7MHz - FM radio */
0609 
0610     memset(buf,0,sizeof(buf));
0611 
0612     name = "unknown";
0613 
0614     tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
0615     tuner_i2c_xfer_recv(&priv->i2c_props,buf,21);
0616     if (debug)
0617         tuner_dbg("MT20xx hexdump: %*ph\n", 21, buf);
0618 
0619     company_code = buf[0x11] << 8 | buf[0x12];
0620     tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n",
0621            company_code,buf[0x13],buf[0x14]);
0622 
0623 
0624     if (buf[0x13] < ARRAY_SIZE(microtune_part) &&
0625         NULL != microtune_part[buf[0x13]])
0626         name = microtune_part[buf[0x13]];
0627     switch (buf[0x13]) {
0628     case MT2032:
0629         mt2032_init(fe);
0630         break;
0631     case MT2050:
0632         mt2050_init(fe);
0633         break;
0634     default:
0635         tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n",
0636                name);
0637         return NULL;
0638     }
0639 
0640     strscpy(fe->ops.tuner_ops.info.name, name,
0641         sizeof(fe->ops.tuner_ops.info.name));
0642     tuner_info("microtune %s found, OK\n",name);
0643     return fe;
0644 }
0645 
0646 EXPORT_SYMBOL_GPL(microtune_attach);
0647 
0648 MODULE_DESCRIPTION("Microtune tuner driver");
0649 MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
0650 MODULE_LICENSE("GPL");