?? tuner.c
字號:
buf[2]=0x86; // LOGC buf[3]=0x0f; //reserved buf[4]=0x1f; buf[5]=(lo2n-1) | (lo2a<<5); if(rfin >400*1000*1000) buf[6]=0xe4; else buf[6]=0xf4; // set PKEN per rev 1.2 buf[7]=8+xogc; buf[8]=0xc3; //reserved buf[9]=0x4e; //reserved buf[10]=0xec; //reserved buf[11]=(lo2num&0xff); buf[12]=(lo2num>>8) |0x80; // Lo2RST return 0;}static int mt2032_check_lo_lock(struct i2c_client *c){ int try,lock=0; unsigned char buf[2]; for(try=0;try<10;try++) { buf[0]=0x0e; i2c_master_send(c,buf,1); i2c_master_recv(c,buf,1); dprintk("mt2032 Reg.E=0x%02x\n",buf[0]); lock=buf[0] &0x06; if (lock==6) break; dprintk("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]); udelay(1000); } return lock;}static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock){ unsigned char buf[2]; int tad1; buf[0]=0x0f; i2c_master_send(c,buf,1); i2c_master_recv(c,buf,1); dprintk("mt2032 Reg.F=0x%02x\n",buf[0]); tad1=buf[0]&0x07; if(tad1 ==0) return lock; if(tad1 ==1) return lock; if(tad1==2) { if(sel==0) return lock; else sel--; } else { if(sel<4) sel++; else return lock; } dprintk("mt2032 optimize_vco: sel=%d\n",sel); buf[0]=0x0f; buf[1]=sel; i2c_master_send(c,buf,2); lock=mt2032_check_lo_lock(c); return lock;}static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin, unsigned int if1, unsigned int if2, unsigned int from, unsigned int to){ unsigned char buf[21]; int lint_try,ret,sel,lock=0; struct tuner *t = i2c_get_clientdata(c); dprintk("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",rfin,if1,if2,from,to); buf[0]=0; ret=i2c_master_send(c,buf,1); i2c_master_recv(c,buf,21); buf[0]=0; ret=mt2032_compute_freq(rfin,if1,if2,from,to,&buf[1],&sel,t->xogc); if (ret<0) return; // send only the relevant registers per Rev. 1.2 buf[0]=0; ret=i2c_master_send(c,buf,4); buf[5]=5; ret=i2c_master_send(c,buf+5,4); buf[11]=11; ret=i2c_master_send(c,buf+11,3); if(ret!=3) printk("mt2032_set_if_freq failed with %d\n",ret); // wait for PLLs to lock (per manual), retry LINT if not. for(lint_try=0; lint_try<2; lint_try++) { lock=mt2032_check_lo_lock(c); if(optimize_vco) lock=mt2032_optimize_vco(c,sel,lock); if(lock==6) break; printk("mt2032: re-init PLLs by LINT\n"); buf[0]=7; buf[1]=0x80 +8+t->xogc; // set LINT to re-init PLLs i2c_master_send(c,buf,2); mdelay(10); buf[1]=8+t->xogc; i2c_master_send(c,buf,2); } if (lock!=6) printk("MT2032 Fatal Error: PLLs didn't lock.\n"); buf[0]=2; buf[1]=0x20; // LOGC for optimal phase noise ret=i2c_master_send(c,buf,2); if (ret!=2) printk("mt2032_set_if_freq2 failed with %d\n",ret);}static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq){ struct tuner *t = i2c_get_clientdata(c); int if2,from,to; // signal bandwidth and picture carrier if (t->mode == VIDEO_MODE_NTSC) { from=40750*1000; to=46750*1000; if2=45750*1000; } else { // Pal from=32900*1000; to=39900*1000; if2=38900*1000; } mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */, 1090*1000*1000, if2, from, to);}static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq){ struct tuner *t = i2c_get_clientdata(c); int if2 = t->radio_if2; // per Manual for FM tuning: first if center freq. 1085 MHz mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */, 1085*1000*1000,if2,if2,if2);}// Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001static int mt2032_init(struct i2c_client *c){ struct tuner *t = i2c_get_clientdata(c); unsigned char buf[21]; int ret,xogc,xok=0; // Initialize Registers per spec. buf[1]=2; // Index to register 2 buf[2]=0xff; buf[3]=0x0f; buf[4]=0x1f; ret=i2c_master_send(c,buf+1,4); buf[5]=6; // Index register 6 buf[6]=0xe4; buf[7]=0x8f; buf[8]=0xc3; buf[9]=0x4e; buf[10]=0xec; ret=i2c_master_send(c,buf+5,6); buf[12]=13; // Index register 13 buf[13]=0x32; ret=i2c_master_send(c,buf+12,2); // Adjust XOGC (register 7), wait for XOK xogc=7; do { dprintk("mt2032: xogc = 0x%02x\n",xogc&0x07); mdelay(10); buf[0]=0x0e; i2c_master_send(c,buf,1); i2c_master_recv(c,buf,1); xok=buf[0]&0x01; dprintk("mt2032: xok = 0x%02x\n",xok); if (xok == 1) break; xogc--; dprintk("mt2032: xogc = 0x%02x\n",xogc&0x07); if (xogc == 3) { xogc=4; // min. 4 per spec break; } buf[0]=0x07; buf[1]=0x88 + xogc; ret=i2c_master_send(c,buf,2); if (ret!=2) printk("mt2032_init failed with %d\n",ret); } while (xok != 1 ); t->xogc=xogc; t->tv_freq = mt2032_set_tv_freq; t->radio_freq = mt2032_set_radio_freq; return(1);}static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned int if2){ unsigned int if1=1218*1000*1000; unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b; int ret; unsigned char buf[6]; dprintk("mt2050_set_if_freq freq=%d\n",freq); f_lo1=freq+if1; f_lo1=(f_lo1/1000000)*1000000; f_lo2=f_lo1-freq-if2; f_lo2=(f_lo2/50000)*50000; lo1=f_lo1/4000000; lo2=f_lo2/4000000; f_lo1_modulo= f_lo1-(lo1*4000000); f_lo2_modulo= f_lo2-(lo2*4000000); num1=4*f_lo1_modulo/4000000; num2=4096*(f_lo2_modulo/1000)/4000; // todo spurchecks div1a=(lo1/12)-1; div1b=lo1-(div1a+1)*12; div2a=(lo2/8)-1; div2b=lo2-(div2a+1)*8; dprintk("lo1 lo2 = %d %d\n", lo1, lo2); dprintk("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n",num1,num2,div1a,div1b,div2a,div2b); buf[0]=1; buf[1]= 4*div1b + num1; if(freq<275*1000*1000) buf[1] = buf[1]|0x80; buf[2]=div1a; buf[3]=32*div2b + num2/256; buf[4]=num2-(num2/256)*256; buf[5]=div2a; if(num2!=0) buf[5]=buf[5]|0x40; if(debug) { int i; printk("bufs is: "); for(i=0;i<6;i++) printk("%x ",buf[i]); printk("\n"); } ret=i2c_master_send(c,buf,6); if (ret!=6) printk("mt2050_set_if_freq failed with %d\n",ret);}static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq){ struct tuner *t = i2c_get_clientdata(c); unsigned int if2; if (t->mode == VIDEO_MODE_NTSC) { if2=45750*1000; } else { // Pal if2=38900*1000; } mt2050_set_if_freq(c,freq*62500,if2);}static int mt2050_init(struct i2c_client *c){ struct tuner *t = i2c_get_clientdata(c); unsigned char buf[1]; int ret; buf[0]=6; buf[1]=0x10; ret=i2c_master_send(c,buf,2); // power buf[0]=0x0f; buf[1]=0x0f; ret=i2c_master_send(c,buf,2); // m1lo buf[0]=0x0d; ret=i2c_master_send(c,buf,1); i2c_master_recv(c,buf,1); dprintk("mt2050: sro is %x\n",buf[0]); t->tv_freq = mt2050_set_tv_freq; return 0;}static int microtune_init(struct i2c_client *c){ struct tuner *t = i2c_get_clientdata(c); char *name; unsigned char buf[21]; int company_code; buf[0] = 0; t->tv_freq = NULL; t->radio_freq = NULL; name = "unknown"; i2c_master_send(c,buf,1); i2c_master_recv(c,buf,21); if(debug) { int i; printk(KERN_DEBUG "tuner: MT2032 hexdump:\n"); for(i=0;i<21;i++) { printk(" %02x",buf[i]); if(((i+1)%8)==0) printk(" "); if(((i+1)%16)==0) printk("\n "); } printk("\n "); } company_code = buf[0x11] << 8 | buf[0x12]; printk("tuner: microtune: companycode=%04x part=%02x rev=%02x\n", company_code,buf[0x13],buf[0x14]); if (company_code != 0x4d54) { printk("tuner: microtune: unknown companycode\n"); return 0; } if (buf[0x13] < ARRAY_SIZE(microtune_part) && NULL != microtune_part[buf[0x13]]) name = microtune_part[buf[0x13]]; switch (buf[0x13]) { case MT2032: mt2032_init(c); break; case MT2050: mt2050_init(c); break; default: printk("tuner: microtune %s found, not (yet?) supported, sorry :-/\n", name); return 0; } printk("tuner: microtune %s found, OK\n",name); return 0;}/* ---------------------------------------------------------------------- */static void default_set_tv_freq(struct i2c_client *c, unsigned int freq){ struct tuner *t = i2c_get_clientdata(c); u8 config; u16 div; struct tunertype *tun; unsigned char buffer[4]; int rc; tun=&tuners[t->type]; if (freq < tun->thresh1) config = tun->VHF_L; else if (freq < tun->thresh2) config = tun->VHF_H; else config = tun->UHF; /* tv norm specific stuff for multi-norm tuners */ switch (t->type) { case TUNER_PHILIPS_SECAM: // FI1216MF /* 0x01 -> ??? no change ??? */ /* 0x02 -> PAL BDGHI / SECAM L */ /* 0x04 -> ??? PAL others / SECAM others ??? */ config &= ~0x02; if (t->mode == VIDEO_MODE_SECAM) config |= 0x02; break; case TUNER_TEMIC_4046FM5: config &= ~0x0f; switch (pal[0]) { case 'i': case 'I': config |= TEMIC_SET_PAL_I;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -