diff options
Diffstat (limited to 'linux/drivers/media/dvb/frontends/mt2060.c')
-rw-r--r-- | linux/drivers/media/dvb/frontends/mt2060.c | 153 |
1 files changed, 93 insertions, 60 deletions
diff --git a/linux/drivers/media/dvb/frontends/mt2060.c b/linux/drivers/media/dvb/frontends/mt2060.c index 4d8efe1ae..728bc2cd5 100644 --- a/linux/drivers/media/dvb/frontends/mt2060.c +++ b/linux/drivers/media/dvb/frontends/mt2060.c @@ -25,6 +25,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/delay.h> #include <linux/dvb/frontend.h> #include "mt2060.h" #include "mt2060_priv.h" @@ -55,7 +56,8 @@ static int mt2060_writereg(struct mt2060_state *state, u8 reg, u8 val) { u8 buf[2]; struct i2c_msg msg = { - .addr = state->config->i2c_address, .flags = 0, .buf = buf, .len = 2 }; + .addr = state->config->i2c_address, .flags = 0, .buf = buf, .len = 2 + }; buf[0]=reg; buf[1]=val; @@ -70,7 +72,8 @@ static int mt2060_writereg(struct mt2060_state *state, u8 reg, u8 val) static int mt2060_writeregs(struct mt2060_state *state,u8 *buf, u8 len) { struct i2c_msg msg = { - .addr = state->config->i2c_address, .flags = 0, .buf = buf, .len = len }; + .addr = state->config->i2c_address, .flags = 0, .buf = buf, .len = len + }; if (i2c_transfer(state->i2c, &msg, 1) != 1) { printk(KERN_WARNING "mt2060 I2C write failed (len=%i)\n",(int)len); return -EREMOTEIO; @@ -117,13 +120,13 @@ static int mt2060_spurcalc(u32 lo1,u32 lo2,u32 if2) int I,J; int dia,diamin,diff; diamin=1000000; - for (I=1;I<10;I++) { - J=((2*I*lo1)/lo2+1)/2; - diff=I*(int)lo1-J*(int)lo2; - if (diff<0) diff=-diff; - dia=(diff-(int)if2); - if (dia<0) dia=-dia; - if (diamin>dia) diamin=dia; + for (I = 1; I < 10; I++) { + J = ((2*I*lo1)/lo2+1)/2; + diff = I*(int)lo1-J*(int)lo2; + if (diff < 0) diff=-diff; + dia = (diff-(int)if2); + if (dia < 0) dia=-dia; + if (diamin > dia) diamin=dia; } return diamin; } @@ -139,20 +142,22 @@ static int mt2060_spurcheck(u32 lo1,u32 lo2,u32 if2) J=1000; Spur=mt2060_spurcalc(lo1,lo2,if2); - if (Spur<BANDWIDTH) { + if (Spur < BANDWIDTH) { /* Potential spurs detected */ dprintk("Spurs before : f_lo1: %d f_lo2: %d (kHz)", (int)lo1,(int)lo2); I=1000; - Sp1=mt2060_spurcalc(lo1+I,lo2+I,if2); - Sp2=mt2060_spurcalc(lo1-I,lo2-I,if2); + Sp1 = mt2060_spurcalc(lo1+I,lo2+I,if2); + Sp2 = mt2060_spurcalc(lo1-I,lo2-I,if2); - if (Sp1<Sp2) { J=-J; I=-I; Spur=Sp2; } - else Spur=Sp1; + if (Sp1 < Sp2) { + J=-J; I=-I; Spur=Sp2; + } else + Spur=Sp1; - while (Spur<BANDWIDTH) { - I+=J; - Spur=mt2060_spurcalc(lo1+I,lo2+I,if2); + while (Spur < BANDWIDTH) { + I += J; + Spur = mt2060_spurcalc(lo1+I,lo2+I,if2); } dprintk("Spurs after : f_lo1: %d f_lo2: %d (kHz)", (int)(lo1+I),(int)(lo2+I)); @@ -167,52 +172,51 @@ static int mt2060_spurcheck(u32 lo1,u32 lo2,u32 if2) int mt2060_set(struct mt2060_state *state, struct dvb_frontend_parameters *fep) { + int ret=0; u32 freq; - int lnaband; + u8 lnaband; u32 f_lo1,f_lo2; u32 div1,num1,div2,num2; u8 b[8]; - int ret=0; - freq=fep->frequency / 1000; // Hz -> kHz + freq = fep->frequency / 1000; // Hz -> kHz - f_lo1=freq + IF1; - f_lo1=(f_lo1/250)*250; - f_lo2=f_lo1 - freq - IF2; - f_lo2=(f_lo2/50)*50; + f_lo1 = freq + IF1; + f_lo1 = (f_lo1/250)*250; + f_lo2 = f_lo1 - freq - IF2; + f_lo2 = (f_lo2/50)*50; #ifdef MT2060_SPURCHECK // LO-related spurs detection and correction - num1=mt2060_spurcheck(f_lo1,f_lo2,IF2); - f_lo1+=num1; - f_lo2+=num1; + num1 = mt2060_spurcheck(f_lo1,f_lo2,IF2); + f_lo1 += num1; + f_lo2 += num1; #endif //Frequency LO1 = 16MHz * (DIV1 + NUM1/64 ) - div1=f_lo1 / FREF; - num1=(64 * (f_lo1 % FREF) )/FREF; + div1 = f_lo1 / FREF; + num1 = (64 * (f_lo1 % FREF) )/FREF; // Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 ) - div2=f_lo2 / FREF; - num2=(16384 * (f_lo2 % FREF) /FREF +1)/2; - - if (freq<=95 *1000) lnaband=0xB0; else - if (freq<=180*1000) lnaband=0xA0; else - if (freq<=260*1000) lnaband=0x90; else - if (freq<=335*1000) lnaband=0x80; else - if (freq<=425*1000) lnaband=0x70; else - if (freq<=480*1000) lnaband=0x60; else - if (freq<=570*1000) lnaband=0x50; else - if (freq<=645*1000) lnaband=0x40; else - if (freq<=730*1000) lnaband=0x30; else - if (freq<=810*1000) lnaband=0x20; else - lnaband=0x10; - - b[0]=REG_LO1C1; - b[1]=lnaband | ((num1 >>2) & 0x0F); - b[2]=div1; - b[3]=(num2 & 0x0F) | ((num1 & 3) << 4); - b[4]=num2 >> 4; - b[5]=((num2 >>12) & 1) | (div2 << 1); + div2 = f_lo2 / FREF; + num2 = (16384 * (f_lo2 % FREF) /FREF +1)/2; + + if (freq <= 95000) lnaband = 0xB0; else + if (freq <= 180000) lnaband = 0xA0; else + if (freq <= 260000) lnaband = 0x90; else + if (freq <= 335000) lnaband = 0x80; else + if (freq <= 425000) lnaband = 0x70; else + if (freq <= 480000) lnaband = 0x60; else + if (freq <= 570000) lnaband = 0x50; else + if (freq <= 645000) lnaband = 0x40; else + if (freq <= 730000) lnaband = 0x30; else + if (freq <= 810000) lnaband = 0x20; else lnaband = 0x10; + + b[0] = REG_LO1C1; + b[1] = lnaband | ((num1 >>2) & 0x0F); + b[2] = div1; + b[3] = (num2 & 0x0F) | ((num1 & 3) << 4); + b[4] = num2 >> 4; + b[5] = ((num2 >>12) & 1) | (div2 << 1); dprintk("PLL freq: %d f_lo1: %d f_lo2: %d (kHz)",(int)freq,(int)f_lo1,(int)f_lo2); dprintk("PLL div1: %d num1: %d div2: %d num2: %d",(int)div1,(int)num1,(int)div2,(int)num2); @@ -223,10 +227,45 @@ int mt2060_set(struct mt2060_state *state, struct dvb_frontend_parameters *fep) } EXPORT_SYMBOL(mt2060_set); +/* from usbsnoop.log */ +static void mt2060_calibrate(struct mt2060_state *state) +{ + u8 b = 0; + int i = 0; + do { + b |= (1 << 6); // FM1SS; + mt2060_writereg(state, REG_LO2C1,b); + msleep(25); + + if (i == 0) { + b |= (1 << 7); // FM1CA; + mt2060_writereg(state, REG_LO2C1,b); + b &= ~(1 << 7); // FM1CA; + msleep(25); + } + + b &= ~(1 << 6); // FM1SS + mt2060_writereg(state, REG_LO2C1,b); + + msleep(25); + i++; + } while (i < 9); + + i = 0; + while (i++ < 10 && mt2060_readreg(state, REG_MISC_STAT, &b) == 0 && (b & (1 << 6)) == 0) + msleep(25); + + if (i < 10) { + mt2060_readreg(state, REG_FM_FREQ, &state->fmfreq); // now find out, what is fmreq used for :) + dprintk("calibration was successful: %d",state->fmfreq); + } else + dprintk("FMCAL timed out"); +} + /* This functions tries to identify a MT2060 tuner by reading the PART/REV register. This is hasty. */ int mt2060_attach(struct mt2060_state *state, struct mt2060_config *config, struct i2c_adapter *i2c) { - u8 id; + u8 id = 0; memset(state,0,sizeof(struct mt2060_state)); state->config = config; @@ -235,19 +274,13 @@ int mt2060_attach(struct mt2060_state *state, struct mt2060_config *config, stru if (mt2060_readreg(state,REG_PART_REV,&id) != 0) return -ENODEV; - if (id!=PART_REV) - return -ENODEV; - - if (mt2060_writereg(state,REG_PART_REV,0) != 0) + if (id != PART_REV) return -ENODEV; - if (mt2060_readreg(state,REG_PART_REV,&id) != 0) - return -ENODEV; + printk(KERN_INFO "MT2060: successfully identified\n"); - if (id!=PART_REV) - return -ENODEV; + mt2060_calibrate(state); - printk(KERN_INFO "MT2060: Identified Microtune MT2060 chip\n"); return 0; } EXPORT_SYMBOL(mt2060_attach); |