diff options
author | marha <marha@users.sourceforge.net> | 2009-06-28 22:07:26 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2009-06-28 22:07:26 +0000 |
commit | 3562e78743202e43aec8727005182a2558117eca (patch) | |
tree | 8f9113a77d12470c5c851a2a8e4cb02e89df7d43 /xorg-server/hw/xfree86/i2c/fi1236.c | |
download | vcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.gz vcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.bz2 vcxsrv-3562e78743202e43aec8727005182a2558117eca.zip |
Checked in the following released items:
xkeyboard-config-1.4.tar.gz
ttf-bitstream-vera-1.10.tar.gz
font-alias-1.0.1.tar.gz
font-sun-misc-1.0.0.tar.gz
font-sun-misc-1.0.0.tar.gz
font-sony-misc-1.0.0.tar.gz
font-schumacher-misc-1.0.0.tar.gz
font-mutt-misc-1.0.0.tar.gz
font-misc-misc-1.0.0.tar.gz
font-misc-meltho-1.0.0.tar.gz
font-micro-misc-1.0.0.tar.gz
font-jis-misc-1.0.0.tar.gz
font-isas-misc-1.0.0.tar.gz
font-dec-misc-1.0.0.tar.gz
font-daewoo-misc-1.0.0.tar.gz
font-cursor-misc-1.0.0.tar.gz
font-arabic-misc-1.0.0.tar.gz
font-winitzki-cyrillic-1.0.0.tar.gz
font-misc-cyrillic-1.0.0.tar.gz
font-cronyx-cyrillic-1.0.0.tar.gz
font-screen-cyrillic-1.0.1.tar.gz
font-xfree86-type1-1.0.1.tar.gz
font-adobe-utopia-type1-1.0.1.tar.gz
font-ibm-type1-1.0.0.tar.gz
font-bitstream-type1-1.0.0.tar.gz
font-bitstream-speedo-1.0.0.tar.gz
font-bh-ttf-1.0.0.tar.gz
font-bh-type1-1.0.0.tar.gz
font-bitstream-100dpi-1.0.0.tar.gz
font-bh-lucidatypewriter-100dpi-1.0.0.tar.gz
font-bh-100dpi-1.0.0.tar.gz
font-adobe-utopia-100dpi-1.0.1.tar.gz
font-adobe-100dpi-1.0.0.tar.gz
font-util-1.0.1.tar.gz
font-bitstream-75dpi-1.0.0.tar.gz
font-bh-lucidatypewriter-75dpi-1.0.0.tar.gz
font-adobe-utopia-75dpi-1.0.1.tar.gz
font-bh-75dpi-1.0.0.tar.gz
bdftopcf-1.0.1.tar.gz
font-adobe-75dpi-1.0.0.tar.gz
mkfontscale-1.0.6.tar.gz
openssl-0.9.8k.tar.gz
bigreqsproto-1.0.2.tar.gz
xtrans-1.2.2.tar.gz
resourceproto-1.0.2.tar.gz
inputproto-1.4.4.tar.gz
compositeproto-0.4.tar.gz
damageproto-1.1.0.tar.gz
zlib-1.2.3.tar.gz
xkbcomp-1.0.5.tar.gz
freetype-2.3.9.tar.gz
pthreads-w32-2-8-0-release.tar.gz
pixman-0.12.0.tar.gz
kbproto-1.0.3.tar.gz
evieext-1.0.2.tar.gz
fixesproto-4.0.tar.gz
recordproto-1.13.2.tar.gz
randrproto-1.2.2.tar.gz
scrnsaverproto-1.1.0.tar.gz
renderproto-0.9.3.tar.gz
xcmiscproto-1.1.2.tar.gz
fontsproto-2.0.2.tar.gz
xextproto-7.0.3.tar.gz
xproto-7.0.14.tar.gz
libXdmcp-1.0.2.tar.gz
libxkbfile-1.0.5.tar.gz
libfontenc-1.0.4.tar.gz
libXfont-1.3.4.tar.gz
libX11-1.1.5.tar.gz
libXau-1.0.4.tar.gz
libxcb-1.1.tar.gz
xorg-server-1.5.3.tar.gz
Diffstat (limited to 'xorg-server/hw/xfree86/i2c/fi1236.c')
-rw-r--r-- | xorg-server/hw/xfree86/i2c/fi1236.c | 609 |
1 files changed, 609 insertions, 0 deletions
diff --git a/xorg-server/hw/xfree86/i2c/fi1236.c b/xorg-server/hw/xfree86/i2c/fi1236.c new file mode 100644 index 000000000..110563ed9 --- /dev/null +++ b/xorg-server/hw/xfree86/i2c/fi1236.c @@ -0,0 +1,609 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "xf86.h" +#include "xf86i2c.h" +#include "fi1236.h" +#include "tda9885.h" +#include "i2c_def.h" + +#define NUM_TUNERS 8 + +const FI1236_parameters tuner_parms[NUM_TUNERS] = +{ + /* 0 - FI1236 */ + { 733 ,884 ,12820 ,2516 ,7220 ,0xA2 ,0x94, 0x34, 0x8e }, + /* !!!based on documentation - it should be: + {733 ,16*55.25 ,16*801.25 ,16*160 ,16*454 ,0xA0 ,0x90, 0x30, 0x8e},*/ + + /* 1 - FI1216 */ + { 623 ,16*48.75 ,16*855.25 ,16*170 ,16*450 ,0xA0 ,0x90, 0x30, 0x8e }, + /* 2 - TEMIC FN5AL */ + { 623 ,16*45.75 ,16*855.25 ,16*169 ,16*454 ,0xA0 ,0x90, 0x30, 0x8e }, + /* 3 - MT2032.. */ + { 733 ,768 ,13760 , 0 , 0 , 0 , 0, 0, 0 }, + /* 4 - FI1246 */ + { 623 ,16*45.75 ,16*855.25 ,16*170 ,16*450 ,0xA0 ,0x90, 0x30, 0x8e }, + /* 5 - FI1256 */ + { 623 ,16*49.75 ,16*863.25 ,16*170 ,16*450 ,0xA0 ,0x90, 0x30, 0x8e }, + /* 6 - FI1236W */ + /*{ 733 ,884 ,12820 ,2516 ,7220 ,0x1 ,0x2, 0x4, 0x8e },*/ + { 732, 16*55.25, 16*801.25, 16*160, 16*442, 0x1, 0x2, 0x4, 0x8e }, + /* 7 - FM1216ME */ + { 623 ,16*48.25 ,16*863.25 ,16*158.00 ,16*442.00 ,0x1 ,0x2, 0x4, 0x8e } +}; + + +FI1236Ptr Detect_FI1236(I2CBusPtr b, I2CSlaveAddr addr) +{ + FI1236Ptr f; + I2CByte a; + + f = xcalloc(1,sizeof(FI1236Rec)); + if(f == NULL) return NULL; + f->d.DevName = strdup("FI12xx Tuner"); + f->d.SlaveAddr = addr; + f->d.pI2CBus = b; + f->d.NextDev = NULL; + f->d.StartTimeout = b->StartTimeout; + f->d.BitTimeout = b->BitTimeout; + f->d.AcknTimeout = b->AcknTimeout; + f->d.ByteTimeout = b->ByteTimeout; + f->type=TUNER_TYPE_FI1236; + f->afc_timer_installed=FALSE; + f->last_afc_hint=TUNER_OFF; + f->video_if=45.7812; + + if(!I2C_WriteRead(&(f->d), NULL, 0, &a, 1)) + { + free(f); + return NULL; + } + FI1236_set_tuner_type(f, TUNER_TYPE_FI1236); + if(!I2CDevInit(&(f->d))) + { + free(f); + return NULL; + } + return f; +} + +static void MT2032_dump_parameters(FI1236Ptr f, MT2032_parameters *m) +{ +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: input f_rf=%g f_if1=%g f_if2=%g f_ref=%g f_ifbw=%g f_step=%g\n", + m->f_rf, m->f_if1, m->f_if2, m->f_ref, m->f_ifbw, m->f_step); + +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: computed f_lo1=%g f_lo2=%g LO1I=%d LO2I=%d SEL=%d STEP=%d NUM=%d\n", + m->f_lo1, m->f_lo2, m->LO1I, m->LO2I, m->SEL, m->STEP, m->NUM); +} + + +static void MT2032_getid(FI1236Ptr f) +{ +CARD8 out[4]; +CARD8 in; + +in=0x11; +I2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 4); +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: Company code 0x%02x%02x, part code 0x%02x, revision code 0x%02x\n", + out[0], out[1], out[2], out[3]); + +} + +/* might be buggy */ +#if 0 +static void MT2032_shutdown(FI1236Ptr f) +{ +CARD8 data[10]; + +data[0]=0x00; /* start with register 0x00 */ +data[1]=0x1A; +data[2]=0x44; +data[3]=0x20; + +I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); + +data[0]=0x05; /* now start with register 0x05 */ +data[1]=0xD7; +data[2]=0x14; +data[3]=0x05; +I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); + +data[0]=0x0B; /* now start with register 0x05 */ +data[1]=0x8F; +data[2]=0x07; +data[3]=0x43; +I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); + +usleep(15000); +} +#endif + +static void MT2032_dump_status(FI1236Ptr f); + +static void MT2032_init(FI1236Ptr f) +{ +CARD8 data[10]; +CARD8 value; +CARD8 xogc = 0x00; + +MT2032_getid(f); + +data[0]=0x02; /* start with register 0x02 */ +data[1]=0xFF; +data[2]=0x0F; +data[3]=0x1F; + +I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); + +data[0]=0x06; /* now start with register 0x06 */ +data[1]=0xE4; +data[2]=0x8F; +data[3]=0xC3; +data[4]=0x4E; +data[5]=0xEC; +I2C_WriteRead(&(f->d), (I2CByte *)data, 6, NULL, 0); + +data[0]=0x0d; /* now start with register 0x0d */ +data[1]=0x32; +I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + +while(1) { + usleep(15000); /* wait 15 milliseconds */ + + data[0]=0x0e; /* register number 7, status */ + value=0xFF; + if(!I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1)) + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to read XOK\n"); + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: XOK=%d\n", value & 0x01); + if(value & 1) break; + + data[0]=0x07; + if(!I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1)) + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to read XOGC\n"); + + xogc=value & 0x7; + if(xogc==4){ + break; /* XOGC has reached 4.. stop */ + } + xogc--; + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: try XOGC=%d\n", xogc); + usleep(15000); + data[0]=0x07; /* register number 7, control byte 2 */ + data[1]=0x08 | xogc; + I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + } +f->xogc=xogc; +/* wait before continuing */ +usleep(15000); /* wait 50 milliseconds */ +MT2032_dump_status(f); +} + +static int MT2032_no_spur_in_band(MT2032_parameters *m) +{ +int n_max, n1, n2; +double f_test; +n_max=5; +n1=1; +while(1){ + n2=-n1; + f_test=n1*(m->f_lo1-m->f_lo2); + while(1){ + n2--; + f_test=f_test-m->f_lo2; + xf86DrvMsg(0, X_INFO, "testing f_test=%g n1=%d n2=%d f_lo1=%g f_lo2=%g f_if2=%g\n", f_test, n1, n2, m->f_lo1, m->f_lo2, m->f_if2); + xf86DrvMsg(0, X_INFO, "d_f=%g f_ifbw=%g\n",fabs(fabs(f_test)-m->f_if2), m->f_ifbw); + if((fabs(fabs(f_test)-m->f_if2)*2.0)<=m->f_ifbw)return 0; + if(n2<=-n_max)break; + /* this line in the manual is bogus. I say it is faster + and more correct to go over all harmonics.. */ + #if 0 + if(f_test<(m->f_lo2-m->f_if2-m->f_ifbw))break; + #endif + } + n1++; + if(n1>=n_max)return 1; + } + +} + +static void MT2032_calculate_register_settings(MT2032_parameters *m, double f_rf, double f_if1, double f_if2, double f_ref, double f_ifbw, double f_step) +{ +int n; +m->f_rf=f_rf; +m->f_if1=f_if1; +m->f_if2=f_if2; +m->f_ref=f_ref; +m->f_ifbw=f_ifbw; +m->f_step=f_step; + +m->f_lo1=f_rf+f_if1; +m->LO1I=(int)floor((m->f_lo1/f_ref)+0.5); +m->f_lo1=f_ref*m->LO1I; + +m->f_lo2=m->f_lo1-f_rf-f_if2; + +/* check for spurs */ +n=1; +while(n<3){ + if(MT2032_no_spur_in_band(m))break; + if(m->f_lo1<(f_rf+f_if1)){ + m->LO1I+=n; + } else { + m->LO1I-=n; + } + m->f_lo1=m->LO1I*f_ref; + m->f_lo2=m->f_lo1-f_rf-f_if2; + n++; + } +/* xf86DrvMsg(0, X_INFO, "MT2032: n=%d\n", n); */ +/* select VCO */ + +/* m->f_lo1>1100.0 */ +if(m->f_lo1<1370.0)m->SEL=4; + else +if(m->f_lo1<1530.0)m->SEL=3; + else +if(m->f_lo1<1720.0)m->SEL=2; + else +if(m->f_lo1<1890.0)m->SEL=1; + else /* m->f_lo1 < 1958.0 */ + m->SEL=0; + +/* calculate the rest of the registers */ +m->LO2I=(int)floor(m->f_lo2/f_ref); +m->STEP=(int)floor(3780.0*f_step/f_ref); +m->NUM=(int)floor(3780.0*(m->f_lo2/f_ref-m->LO2I)); +m->NUM=m->STEP*(int)floor((1.0*m->NUM)/(1.0*m->STEP)+0.5); +} + +static int MT2032_wait_for_lock(FI1236Ptr f) +{ +int n; +CARD8 data[10]; +CARD8 value; + +n=12; +while(1){ + data[0]=0x0e; /* register number 7, status */ + I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1); +/* xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: LO1LK=%d LO2LK=%d\n", (value & 0x04)>>2, (value & 0x02)>>1); */ + if((value & 6)==6) break; + usleep(1500); + n--; + if(n<0)break; + } +if(n<0){ + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to set frequency\n"); + return 0; + } +return 1; +} + +static void MT2032_implement_settings(FI1236Ptr f, MT2032_parameters *m) +{ +CARD8 data[10]; +CARD8 value; + +data[0]=0x00; /* start with register 0x00 */ +data[1]=(m->LO1I>>3)-1; +data[2]=(m->SEL<<4)|(m->LO1I & 0x7); +data[3]=0x86; +I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); + +data[0]=0x05; /* start with register 0x05 */ +data[1]=((m->LO2I & 0x7)<<5)|((m->LO2I>>3)-1); +if(m->f_rf<400.0)data[2]=0xe4; + else data[2]=0xf4; +I2C_WriteRead(&(f->d), (I2CByte *)data, 3, NULL, 0); + +data[0]=0x07; /* register number 7, control byte 2 */ +I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1); +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: using XOGC=%d\n", (value & 0x07)); +data[1]=8 | (value & 0x7); +I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + +data[0]=0x0b; /* start with register 0x0b */ +data[1]=m->NUM & 0xff; +data[2]=(1<<7)|((m->NUM >> 8) & 0x0f); +I2C_WriteRead(&(f->d), (I2CByte *)data, 3, NULL, 0); + +MT2032_wait_for_lock(f); +} + +static void MT2032_optimize_VCO(FI1236Ptr f, MT2032_parameters *m) +{ +CARD8 data[10]; +CARD8 value; +CARD8 TAD1; + +data[0]=0x0f; /* register number 7, status */ +I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1); +TAD1=value & 0x07; +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: TAD1=%d SEL=%d\n", TAD1, m->SEL); +if(TAD1 < 2)return; +if(TAD1==2){ + if(m->SEL==0)return; + m->SEL--; + } else { + if(m->SEL>=4)return; + m->SEL++; + } +data[0]=0x01; /* start with register 1 */ +data[1]=(m->SEL<<4)|(m->LO1I & 0x7); +I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + +} + +static int FI1236_get_afc_hint(FI1236Ptr f) +{ + CARD8 out; + CARD8 AFC; + + if ((f->type == TUNER_TYPE_FM1216ME) || (f->type == TUNER_TYPE_FI1236W)) + { + TDA9885Ptr t = (TDA9885Ptr)f->afc_source; + if (t == NULL) + return TUNER_OFF; + + tda9885_getstatus(t); + tda9885_dumpstatus(t); + AFC = t->afc_status & 0x0f; + + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: FI1236_get_afc_hint: %i\n", AFC); + if (AFC == 0) return TUNER_TUNED; + else if (AFC <= 0x07)return TUNER_JUST_BELOW; + else if (AFC < 0x0f )return TUNER_JUST_ABOVE; + else if (AFC == 0x0f)return TUNER_TUNED; + } + else + { + I2C_WriteRead(&(f->d), NULL, 0, &out, 1); + AFC=out & 0x7; + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: FI1236_get_afc_hint: %i\n", AFC); + if(AFC==2)return TUNER_TUNED; + if(AFC==3)return TUNER_JUST_BELOW; + if(AFC==1)return TUNER_JUST_ABOVE; + return TUNER_OFF; + } + return TUNER_OFF; +} + +static int MT2032_get_afc_hint(FI1236Ptr f) +{ +CARD8 in; +CARD8 out[2]; +CARD8 AFC; +in=0x0e; +I2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 2); +AFC=(out[0]>>4) & 0x7; +#if 0 +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC=%d TAD1=%d TAD2=%d\n", AFC, out[1] & 0x7, (out[1]>>4)& 0x07); +#endif +if(AFC==2)return TUNER_TUNED; +if(AFC==3)return TUNER_JUST_BELOW; +if(AFC==1)return TUNER_JUST_ABOVE; +return TUNER_OFF; +} + +/* this function is for external use only */ +int TUNER_get_afc_hint(FI1236Ptr f) +{ +if(f->afc_timer_installed)return TUNER_STILL_TUNING; +return f->last_afc_hint; +if(f->type==TUNER_TYPE_MT2032) + return MT2032_get_afc_hint(f); + else + return FI1236_get_afc_hint(f); +} + +static void MT2032_dump_status(FI1236Ptr f) +{ +CARD8 in; +CARD8 out[2]; +CARD8 AFC; +CARD8 LDONrb; +CARD8 LO1LK, LO2LK, XOK; +CARD8 TAD2, TAD1; + +in=0x0e; +I2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 2); +XOK=out[0] & 1; +LO1LK=(out[0]>>2) &1; +LO2LK=(out[0]>>1) &1; +LDONrb=(out[0]>>3) &1; + +AFC=(out[0]>>4) & 0x7; + +TAD1=(out[1] & 0x7); +TAD2=(out[1]>>4) & 0x7; + +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: status: XOK=%d LO1LK=%d LO2LK=%d LDONrb=%d AFC=%d TAD1=%d TAD2=%d\n", + XOK, LO1LK, LO2LK, LDONrb, AFC, TAD1, TAD2); +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: status: OSCILLATOR:%s PLL1:%s PLL2:%s\n", + XOK ? "ok":"off", LO1LK ? "locked" : "off" , LO2LK ? "locked" : "off"); + +} + +static void MT2032_tune(FI1236Ptr f, double freq, double step) +{ +MT2032_parameters m; +CARD8 data[10]; +int i; +/* NTSC IF is 44mhz.. but 733/16=45.8125 and all TDAXXXX docs mention + 45.75, 39, 58.75 and 30. */ +#if 0 +MT2032_calculate_register_settings(&m, freq, 1090.0, 45.125, 5.25, 6.0, step); +MT2032_calculate_register_settings(&m, freq, 1090.0, 45.74, 5.25, 6.0, step); +#endif +MT2032_calculate_register_settings(&m, freq, 1090.0, f->video_if, 5.25, 3.0, step); +MT2032_dump_parameters(f, &m); +MT2032_implement_settings(f, &m); +/* MT2032_dump_parameters(f, &m); */ +for(i=0;i<3;i++){ + MT2032_optimize_VCO(f, &m); + if(MT2032_wait_for_lock(f)){ + data[0]=0x02; /* LO Gain control register 0x02 */ + data[1]=0x20; + I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + return; + } + data[0]=0x07; + data[1]=0x88|f->xogc; + I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + usleep(15000); + data[1]=0x08|f->xogc; + I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + } +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to set frequency\n"); +} + +void FI1236_set_tuner_type(FI1236Ptr f, int type) +{ +f->type=type; +if(type>=NUM_TUNERS)type = NUM_TUNERS-1; +if(type<0)type = 0; +memcpy(&(f->parm), &(tuner_parms[type]), sizeof(FI1236_parameters)); +f->original_frequency=f->parm.min_freq; +f->afc_delta=0; +if(type==TUNER_TYPE_MT2032){ + MT2032_init(f); + return; + } +} + + +static CARD32 AFC_TimerCallback(OsTimerPtr timer, CARD32 time, pointer data){ +FI1236Ptr f=(FI1236Ptr)data; +if(FI1236_AFC(f))return 150; + else { + f->afc_timer_installed=FALSE; + f->afc_count=0; + return 0; + } +} + +void FI1236_tune(FI1236Ptr f, CARD32 frequency) +{ + CARD16 divider; + CARD8 data; + + if(frequency < f->parm.min_freq) frequency = f->parm.min_freq; + if(frequency > f->parm.max_freq) frequency = f->parm.max_freq; + + divider = (f->parm.fcar+(CARD16)frequency) & 0x7fff; + f->tuner_data.div1 = (CARD8)((divider>>8)&0x7f); + f->tuner_data.div2 = (CARD8)(divider & 0xff); + f->tuner_data.control = f->parm.control; + + if(frequency < f->parm.threshold1) + { + f->tuner_data.band = f->parm.band_low; + } + else if (frequency < f->parm.threshold2) + { + f->tuner_data.band = f->parm.band_mid; + } + else + { + f->tuner_data.band = f->parm.band_high; + } + + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Setting tuner band to %d\n", f->tuner_data.band); + + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Setting tuner frequency to %d\n", (int)frequency); + + if ((f->type == TUNER_TYPE_FM1216ME) || (f->type == TUNER_TYPE_FI1236W)) + { + f->tuner_data.aux = 0x20; + I2C_WriteRead(&(f->d), (I2CByte *)&(f->tuner_data), 5, NULL, 0); + I2C_WriteRead(&(f->d), NULL, 0, &data, 1); + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Tuner status %x\n", data); + + } + else + I2C_WriteRead(&(f->d), (I2CByte *)&(f->tuner_data), 4, NULL, 0); +} + +void TUNER_set_frequency(FI1236Ptr f, CARD32 frequency) +{ + if(frequency < f->parm.min_freq) frequency = f->parm.min_freq; + if(frequency > f->parm.max_freq) frequency = f->parm.max_freq; + + f->afc_delta=0; + f->original_frequency=frequency; + + if(f->type==TUNER_TYPE_MT2032) + { + MT2032_tune(f, (1.0*frequency)/16.0, 0.0625); + } else + { + FI1236_tune(f, frequency); + } + + if(!f->afc_timer_installed) + { + f->afc_timer_installed=TRUE; +/* RegisterBlockAndWakeupHandlers(FI1236_BlockHandler, AFCWakeup, f); */ + TimerSet(NULL, 0, 300, AFC_TimerCallback, f); + } + +} + + +int FI1236_AFC(FI1236Ptr f) +{ + #if 0 + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: f=%p f->count=%d f->original_frequency=%d f->afc_delta=%d\n", f, f->afc_count, f->original_frequency, f->afc_delta); + #endif + f->afc_count++; + if(f->type==TUNER_TYPE_MT2032) + { + f->last_afc_hint=MT2032_get_afc_hint(f); + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: afc_hint=%d\n", f->last_afc_hint); + if(f->last_afc_hint==TUNER_TUNED)return 0; + if(f->afc_count>3)f->last_afc_hint=TUNER_OFF; + if(f->last_afc_hint==TUNER_OFF) + { + f->afc_delta=0; + } else + f->afc_delta+=f->last_afc_hint; + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: Setting tuner frequency to %g\n", (0.5*(2*f->original_frequency+f->afc_delta))/16.0); + MT2032_tune(f, (1.0*f->original_frequency+0.5*f->afc_delta)/16.0, 0.03125); + if(f->last_afc_hint==TUNER_OFF)return 0; + return 1; /* call me again */ + } else + { + f->last_afc_hint=FI1236_get_afc_hint(f); + if(f->last_afc_hint==TUNER_TUNED) + { + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: TUNER_TUNNED\n"); + return 0; + } + if(f->afc_count>3)f->last_afc_hint=TUNER_OFF; + if(f->last_afc_hint==TUNER_OFF) + { + f->afc_delta=0; + } else + f->afc_delta+=f->last_afc_hint; + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: Setting tuner frequency to %g\n", (0.5*(2*f->original_frequency+f->afc_delta))/16.0); + FI1236_tune(f, f->original_frequency+f->afc_delta); + if(f->last_afc_hint==TUNER_OFF)return 0; + return 1; /* call me again */ + } + return 0; /* done */ +} + +void fi1236_dump_status(FI1236Ptr f) +{ +if(f->type==TUNER_TYPE_MT2032){ + MT2032_dump_status(f); + } +} |