1706f2543Smrg
2706f2543Smrg#ifdef HAVE_XORG_CONFIG_H
3706f2543Smrg#include <xorg-config.h>
4706f2543Smrg#endif
5706f2543Smrg
6706f2543Smrg#include <unistd.h>
7706f2543Smrg#include <stdlib.h>
8706f2543Smrg#include <string.h>
9706f2543Smrg#include <math.h>
10706f2543Smrg
11706f2543Smrg#include "xf86.h"
12706f2543Smrg#include "xf86i2c.h"
13706f2543Smrg#include "fi1236.h"
14706f2543Smrg#include "tda9885.h"
15706f2543Smrg#include "i2c_def.h"
16706f2543Smrg
17706f2543Smrg#define NUM_TUNERS    8
18706f2543Smrg
19706f2543Smrgconst FI1236_parameters tuner_parms[NUM_TUNERS] =
20706f2543Smrg{
21706f2543Smrg    /* 0 - FI1236 */
22706f2543Smrg    { 733 ,884 ,12820 ,2516 ,7220 ,0xA2 ,0x94, 0x34, 0x8e },
23706f2543Smrg    /* !!!based on documentation - it should be:
24706f2543Smrg    {733 ,16*55.25 ,16*801.25 ,16*160 ,16*454 ,0xA0 ,0x90, 0x30, 0x8e},*/
25706f2543Smrg
26706f2543Smrg    /* 1 - FI1216 */
27706f2543Smrg    { 623 ,16*48.75 ,16*855.25 ,16*170 ,16*450 ,0xA0 ,0x90, 0x30, 0x8e },
28706f2543Smrg    /* 2 - TEMIC FN5AL */
29706f2543Smrg    { 623 ,16*45.75 ,16*855.25 ,16*169 ,16*454 ,0xA0 ,0x90, 0x30, 0x8e },
30706f2543Smrg    /* 3 - MT2032.. */
31706f2543Smrg    { 733 ,768 ,13760 , 0 , 0 , 0 , 0,  0, 0 },
32706f2543Smrg    /* 4 - FI1246 */
33706f2543Smrg    { 623 ,16*45.75 ,16*855.25 ,16*170 ,16*450 ,0xA0 ,0x90, 0x30, 0x8e },
34706f2543Smrg    /* 5 - FI1256 */
35706f2543Smrg    { 623 ,16*49.75 ,16*863.25 ,16*170 ,16*450 ,0xA0 ,0x90, 0x30, 0x8e },
36706f2543Smrg    /* 6 - FI1236W */
37706f2543Smrg    /*{ 733 ,884 ,12820 ,2516 ,7220 ,0x1 ,0x2, 0x4, 0x8e },*/
38706f2543Smrg    { 732, 16*55.25, 16*801.25, 16*160, 16*442, 0x1, 0x2, 0x4, 0x8e },
39706f2543Smrg	 /* 7 - FM1216ME */
40706f2543Smrg    { 623 ,16*48.25 ,16*863.25 ,16*158.00 ,16*442.00 ,0x1 ,0x2, 0x4, 0x8e }
41706f2543Smrg};
42706f2543Smrg
43706f2543Smrg
44706f2543SmrgFI1236Ptr Detect_FI1236(I2CBusPtr b, I2CSlaveAddr addr)
45706f2543Smrg{
46706f2543Smrg   FI1236Ptr f;
47706f2543Smrg   I2CByte a;
48706f2543Smrg
49706f2543Smrg   f = calloc(1,sizeof(FI1236Rec));
50706f2543Smrg   if(f == NULL) return NULL;
51706f2543Smrg   f->d.DevName = strdup("FI12xx Tuner");
52706f2543Smrg   f->d.SlaveAddr = addr;
53706f2543Smrg   f->d.pI2CBus = b;
54706f2543Smrg   f->d.NextDev = NULL;
55706f2543Smrg   f->d.StartTimeout = b->StartTimeout;
56706f2543Smrg   f->d.BitTimeout = b->BitTimeout;
57706f2543Smrg   f->d.AcknTimeout = b->AcknTimeout;
58706f2543Smrg   f->d.ByteTimeout = b->ByteTimeout;
59706f2543Smrg   f->type=TUNER_TYPE_FI1236;
60706f2543Smrg   f->afc_timer_installed=FALSE;
61706f2543Smrg   f->last_afc_hint=TUNER_OFF;
62706f2543Smrg   f->video_if=45.7812;
63706f2543Smrg
64706f2543Smrg   if(!I2C_WriteRead(&(f->d), NULL, 0, &a, 1))
65706f2543Smrg   {
66706f2543Smrg   	free(f);
67706f2543Smrg	return NULL;
68706f2543Smrg    }
69706f2543Smrg    FI1236_set_tuner_type(f, TUNER_TYPE_FI1236);
70706f2543Smrg    if(!I2CDevInit(&(f->d)))
71706f2543Smrg    {
72706f2543Smrg       free(f);
73706f2543Smrg       return NULL;
74706f2543Smrg    }
75706f2543Smrg    return f;
76706f2543Smrg}
77706f2543Smrg
78706f2543Smrgstatic void MT2032_dump_parameters(FI1236Ptr f, MT2032_parameters *m)
79706f2543Smrg{
80706f2543Smrgxf86DrvMsg(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",
81706f2543Smrg	m->f_rf, m->f_if1, m->f_if2, m->f_ref, m->f_ifbw, m->f_step);
82706f2543Smrg
83706f2543Smrgxf86DrvMsg(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",
84706f2543Smrg	m->f_lo1, m->f_lo2, m->LO1I, m->LO2I, m->SEL, m->STEP, m->NUM);
85706f2543Smrg}
86706f2543Smrg
87706f2543Smrg
88706f2543Smrgstatic void MT2032_getid(FI1236Ptr f)
89706f2543Smrg{
90706f2543SmrgCARD8 out[4];
91706f2543SmrgCARD8 in;
92706f2543Smrg
93706f2543Smrgin=0x11;
94706f2543SmrgI2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 4);
95706f2543Smrgxf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: Company code 0x%02x%02x, part code 0x%02x, revision code 0x%02x\n",
96706f2543Smrg	out[0], out[1], out[2], out[3]);
97706f2543Smrg
98706f2543Smrg}
99706f2543Smrg
100706f2543Smrg/* might be buggy */
101706f2543Smrg#if 0
102706f2543Smrgstatic void MT2032_shutdown(FI1236Ptr f)
103706f2543Smrg{
104706f2543SmrgCARD8 data[10];
105706f2543Smrg
106706f2543Smrgdata[0]=0x00; /* start with register 0x00 */
107706f2543Smrgdata[1]=0x1A;
108706f2543Smrgdata[2]=0x44;
109706f2543Smrgdata[3]=0x20;
110706f2543Smrg
111706f2543SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0);
112706f2543Smrg
113706f2543Smrgdata[0]=0x05; /* now start with register 0x05 */
114706f2543Smrgdata[1]=0xD7;
115706f2543Smrgdata[2]=0x14;
116706f2543Smrgdata[3]=0x05;
117706f2543SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0);
118706f2543Smrg
119706f2543Smrgdata[0]=0x0B; /* now start with register 0x05 */
120706f2543Smrgdata[1]=0x8F;
121706f2543Smrgdata[2]=0x07;
122706f2543Smrgdata[3]=0x43;
123706f2543SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0);
124706f2543Smrg
125706f2543Smrgusleep(15000);
126706f2543Smrg}
127706f2543Smrg#endif
128706f2543Smrg
129706f2543Smrgstatic void MT2032_dump_status(FI1236Ptr f);
130706f2543Smrg
131706f2543Smrgstatic void MT2032_init(FI1236Ptr f)
132706f2543Smrg{
133706f2543SmrgCARD8 data[10];
134706f2543SmrgCARD8 value;
135706f2543SmrgCARD8 xogc = 0x00;
136706f2543Smrg
137706f2543SmrgMT2032_getid(f);
138706f2543Smrg
139706f2543Smrgdata[0]=0x02; /* start with register 0x02 */
140706f2543Smrgdata[1]=0xFF;
141706f2543Smrgdata[2]=0x0F;
142706f2543Smrgdata[3]=0x1F;
143706f2543Smrg
144706f2543SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0);
145706f2543Smrg
146706f2543Smrgdata[0]=0x06; /* now start with register 0x06 */
147706f2543Smrgdata[1]=0xE4;
148706f2543Smrgdata[2]=0x8F;
149706f2543Smrgdata[3]=0xC3;
150706f2543Smrgdata[4]=0x4E;
151706f2543Smrgdata[5]=0xEC;
152706f2543SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 6, NULL, 0);
153706f2543Smrg
154706f2543Smrgdata[0]=0x0d; /* now start with register 0x0d */
155706f2543Smrgdata[1]=0x32;
156706f2543SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0);
157706f2543Smrg
158706f2543Smrgwhile(1) {
159706f2543Smrg	usleep(15000); /* wait 15 milliseconds */
160706f2543Smrg
161706f2543Smrg	data[0]=0x0e; /* register number 7, status */
162706f2543Smrg	value=0xFF;
163706f2543Smrg	if(!I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1))
164706f2543Smrg		xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to read XOK\n");
165706f2543Smrg	xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: XOK=%d\n", value & 0x01);
166706f2543Smrg	if(value & 1) break;
167706f2543Smrg
168706f2543Smrg	data[0]=0x07;
169706f2543Smrg	if(!I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1))
170706f2543Smrg		xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to read XOGC\n");
171706f2543Smrg
172706f2543Smrg	xogc=value & 0x7;
173706f2543Smrg	if(xogc==4){
174706f2543Smrg		break; /* XOGC has reached 4.. stop */
175706f2543Smrg		}
176706f2543Smrg	xogc--;
177706f2543Smrg	xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: try XOGC=%d\n", xogc);
178706f2543Smrg	usleep(15000);
179706f2543Smrg	data[0]=0x07; /* register number 7, control byte 2 */
180706f2543Smrg	data[1]=0x08 | xogc;
181706f2543Smrg	I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0);
182706f2543Smrg	}
183706f2543Smrgf->xogc=xogc;
184706f2543Smrg/* wait before continuing */
185706f2543Smrgusleep(15000); /* wait 50 milliseconds */
186706f2543SmrgMT2032_dump_status(f);
187706f2543Smrg}
188706f2543Smrg
189706f2543Smrgstatic int MT2032_no_spur_in_band(MT2032_parameters *m)
190706f2543Smrg{
191706f2543Smrgint n_max, n1, n2;
192706f2543Smrgdouble f_test;
193706f2543Smrgn_max=5;
194706f2543Smrgn1=1;
195706f2543Smrgwhile(1){
196706f2543Smrg	n2=-n1;
197706f2543Smrg	f_test=n1*(m->f_lo1-m->f_lo2);
198706f2543Smrg	while(1){
199706f2543Smrg		n2--;
200706f2543Smrg		f_test=f_test-m->f_lo2;
201706f2543Smrg		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);
202706f2543Smrg		xf86DrvMsg(0, X_INFO, "d_f=%g f_ifbw=%g\n",fabs(fabs(f_test)-m->f_if2), m->f_ifbw);
203706f2543Smrg		if((fabs(fabs(f_test)-m->f_if2)*2.0)<=m->f_ifbw)return 0;
204706f2543Smrg		if(n2<=-n_max)break;
205706f2543Smrg  		/* this line in the manual is bogus. I say it is faster
206706f2543Smrg		and more correct to go over all harmonics.. */
207706f2543Smrg		#if 0
208706f2543Smrg		if(f_test<(m->f_lo2-m->f_if2-m->f_ifbw))break;
209706f2543Smrg		#endif
210706f2543Smrg		}
211706f2543Smrg	n1++;
212706f2543Smrg	if(n1>=n_max)return 1;
213706f2543Smrg	}
214706f2543Smrg
215706f2543Smrg}
216706f2543Smrg
217706f2543Smrgstatic 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)
218706f2543Smrg{
219706f2543Smrgint n;
220706f2543Smrgm->f_rf=f_rf;
221706f2543Smrgm->f_if1=f_if1;
222706f2543Smrgm->f_if2=f_if2;
223706f2543Smrgm->f_ref=f_ref;
224706f2543Smrgm->f_ifbw=f_ifbw;
225706f2543Smrgm->f_step=f_step;
226706f2543Smrg
227706f2543Smrgm->f_lo1=f_rf+f_if1;
228706f2543Smrgm->LO1I=lrint(m->f_lo1/f_ref);
229706f2543Smrgm->f_lo1=f_ref*m->LO1I;
230706f2543Smrg
231706f2543Smrgm->f_lo2=m->f_lo1-f_rf-f_if2;
232706f2543Smrg
233706f2543Smrg/* check for spurs */
234706f2543Smrgn=1;
235706f2543Smrgwhile(n<3){
236706f2543Smrg	if(MT2032_no_spur_in_band(m))break;
237706f2543Smrg	if(m->f_lo1<(f_rf+f_if1)){
238706f2543Smrg		m->LO1I+=n;
239706f2543Smrg		} else {
240706f2543Smrg		m->LO1I-=n;
241706f2543Smrg		}
242706f2543Smrg	m->f_lo1=m->LO1I*f_ref;
243706f2543Smrg	m->f_lo2=m->f_lo1-f_rf-f_if2;
244706f2543Smrg	n++;
245706f2543Smrg	}
246706f2543Smrg/* xf86DrvMsg(0, X_INFO, "MT2032: n=%d\n", n); */
247706f2543Smrg/* select VCO */
248706f2543Smrg
249706f2543Smrg/* m->f_lo1>1100.0 */
250706f2543Smrgif(m->f_lo1<1370.0)m->SEL=4;
251706f2543Smrg	else
252706f2543Smrgif(m->f_lo1<1530.0)m->SEL=3;
253706f2543Smrg	else
254706f2543Smrgif(m->f_lo1<1720.0)m->SEL=2;
255706f2543Smrg	else
256706f2543Smrgif(m->f_lo1<1890.0)m->SEL=1;
257706f2543Smrg	else  /* m->f_lo1 < 1958.0 */
258706f2543Smrg	m->SEL=0;
259706f2543Smrg
260706f2543Smrg/* calculate the rest of the registers */
261706f2543Smrgm->LO2I=floor(m->f_lo2/f_ref);
262706f2543Smrgm->STEP=floor(3780.0*f_step/f_ref);
263706f2543Smrgm->NUM=floor(3780.0*(m->f_lo2/f_ref-m->LO2I));
264706f2543Smrgm->NUM=m->STEP*lrint((1.0*m->NUM)/(1.0*m->STEP));
265706f2543Smrg}
266706f2543Smrg
267706f2543Smrgstatic int MT2032_wait_for_lock(FI1236Ptr f)
268706f2543Smrg{
269706f2543Smrgint n;
270706f2543SmrgCARD8 data[10];
271706f2543SmrgCARD8 value;
272706f2543Smrg
273706f2543Smrgn=12;
274706f2543Smrgwhile(1){
275706f2543Smrg	data[0]=0x0e; /* register number 7, status */
276706f2543Smrg	I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1);
277706f2543Smrg/*	xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: LO1LK=%d LO2LK=%d\n", (value & 0x04)>>2, (value & 0x02)>>1); */
278706f2543Smrg	if((value & 6)==6) break;
279706f2543Smrg	usleep(1500);
280706f2543Smrg	n--;
281706f2543Smrg	if(n<0)break;
282706f2543Smrg	}
283706f2543Smrgif(n<0){
284706f2543Smrg	xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to set frequency\n");
285706f2543Smrg	return 0;
286706f2543Smrg	}
287706f2543Smrgreturn 1;
288706f2543Smrg}
289706f2543Smrg
290706f2543Smrgstatic void MT2032_implement_settings(FI1236Ptr f, MT2032_parameters *m)
291706f2543Smrg{
292706f2543SmrgCARD8 data[10];
293706f2543SmrgCARD8 value;
294706f2543Smrg
295706f2543Smrgdata[0]=0x00;     /* start with register 0x00 */
296706f2543Smrgdata[1]=(m->LO1I>>3)-1;
297706f2543Smrgdata[2]=(m->SEL<<4)|(m->LO1I & 0x7);
298706f2543Smrgdata[3]=0x86;
299706f2543SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0);
300706f2543Smrg
301706f2543Smrgdata[0]=0x05;     /* start with register 0x05 */
302706f2543Smrgdata[1]=((m->LO2I & 0x7)<<5)|((m->LO2I>>3)-1);
303706f2543Smrgif(m->f_rf<400.0)data[2]=0xe4;
304706f2543Smrg	else data[2]=0xf4;
305706f2543SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 3, NULL, 0);
306706f2543Smrg
307706f2543Smrgdata[0]=0x07; /* register number 7, control byte 2 */
308706f2543SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1);
309706f2543Smrgxf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: using XOGC=%d\n", (value & 0x07));
310706f2543Smrgdata[1]=8 | (value & 0x7);
311706f2543SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0);
312706f2543Smrg
313706f2543Smrgdata[0]=0x0b;   /* start with register 0x0b */
314706f2543Smrgdata[1]=m->NUM & 0xff;
315706f2543Smrgdata[2]=(1<<7)|((m->NUM >> 8) & 0x0f);
316706f2543SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 3, NULL, 0);
317706f2543Smrg
318706f2543SmrgMT2032_wait_for_lock(f);
319706f2543Smrg}
320706f2543Smrg
321706f2543Smrgstatic void MT2032_optimize_VCO(FI1236Ptr f, MT2032_parameters *m)
322706f2543Smrg{
323706f2543SmrgCARD8 data[10];
324706f2543SmrgCARD8 value;
325706f2543SmrgCARD8 TAD1;
326706f2543Smrg
327706f2543Smrgdata[0]=0x0f; /* register number 7, status */
328706f2543SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1);
329706f2543SmrgTAD1=value & 0x07;
330706f2543Smrgxf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: TAD1=%d SEL=%d\n", TAD1, m->SEL);
331706f2543Smrgif(TAD1 < 2)return;
332706f2543Smrgif(TAD1==2){
333706f2543Smrg	if(m->SEL==0)return;
334706f2543Smrg	m->SEL--;
335706f2543Smrg	} else {
336706f2543Smrg	if(m->SEL>=4)return;
337706f2543Smrg	m->SEL++;
338706f2543Smrg	}
339706f2543Smrgdata[0]=0x01;  /* start with register 1 */
340706f2543Smrgdata[1]=(m->SEL<<4)|(m->LO1I & 0x7);
341706f2543SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0);
342706f2543Smrg
343706f2543Smrg}
344706f2543Smrg
345706f2543Smrgstatic int FI1236_get_afc_hint(FI1236Ptr f)
346706f2543Smrg{
347706f2543Smrg	CARD8 out;
348706f2543Smrg	CARD8 AFC;
349706f2543Smrg
350706f2543Smrg	if ((f->type == TUNER_TYPE_FM1216ME) || (f->type == TUNER_TYPE_FI1236W))
351706f2543Smrg	{
352706f2543Smrg		TDA9885Ptr t = (TDA9885Ptr)f->afc_source;
353706f2543Smrg		if (t == NULL)
354706f2543Smrg			return TUNER_OFF;
355706f2543Smrg
356706f2543Smrg		tda9885_getstatus(t);
357706f2543Smrg		tda9885_dumpstatus(t);
358706f2543Smrg		AFC = t->afc_status & 0x0f;
359706f2543Smrg
360706f2543Smrg		xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: FI1236_get_afc_hint: %i\n", AFC);
361706f2543Smrg		if (AFC == 0) return TUNER_TUNED;
362706f2543Smrg		else if (AFC <= 0x07)return TUNER_JUST_BELOW;
363706f2543Smrg		else if (AFC < 0x0f )return TUNER_JUST_ABOVE;
364706f2543Smrg		else if (AFC == 0x0f)return TUNER_TUNED;
365706f2543Smrg	}
366706f2543Smrg	else
367706f2543Smrg	{
368706f2543Smrg		I2C_WriteRead(&(f->d), NULL, 0, &out, 1);
369706f2543Smrg		AFC=out & 0x7;
370706f2543Smrg		xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: FI1236_get_afc_hint: %i\n", AFC);
371706f2543Smrg		if(AFC==2)return TUNER_TUNED;
372706f2543Smrg		if(AFC==3)return TUNER_JUST_BELOW;
373706f2543Smrg		if(AFC==1)return TUNER_JUST_ABOVE;
374706f2543Smrg		return TUNER_OFF;
375706f2543Smrg	}
376706f2543Smrg	return TUNER_OFF;
377706f2543Smrg}
378706f2543Smrg
379706f2543Smrgstatic int MT2032_get_afc_hint(FI1236Ptr f)
380706f2543Smrg{
381706f2543SmrgCARD8 in;
382706f2543SmrgCARD8 out[2];
383706f2543SmrgCARD8 AFC;
384706f2543Smrgin=0x0e;
385706f2543SmrgI2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 2);
386706f2543SmrgAFC=(out[0]>>4) & 0x7;
387706f2543Smrg#if 0
388706f2543Smrgxf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC=%d TAD1=%d TAD2=%d\n", AFC, out[1] & 0x7, (out[1]>>4)& 0x07);
389706f2543Smrg#endif
390706f2543Smrgif(AFC==2)return TUNER_TUNED;
391706f2543Smrgif(AFC==3)return TUNER_JUST_BELOW;
392706f2543Smrgif(AFC==1)return TUNER_JUST_ABOVE;
393706f2543Smrgreturn TUNER_OFF;
394706f2543Smrg}
395706f2543Smrg
396706f2543Smrg/* this function is for external use only */
397706f2543Smrgint TUNER_get_afc_hint(FI1236Ptr f)
398706f2543Smrg{
399706f2543Smrgif(f->afc_timer_installed)return TUNER_STILL_TUNING;
400706f2543Smrgreturn f->last_afc_hint;
401706f2543Smrg}
402706f2543Smrg
403706f2543Smrgstatic void MT2032_dump_status(FI1236Ptr f)
404706f2543Smrg{
405706f2543SmrgCARD8 in;
406706f2543SmrgCARD8 out[2];
407706f2543SmrgCARD8 AFC;
408706f2543SmrgCARD8 LDONrb;
409706f2543SmrgCARD8 LO1LK, LO2LK, XOK;
410706f2543SmrgCARD8 TAD2, TAD1;
411706f2543Smrg
412706f2543Smrgin=0x0e;
413706f2543SmrgI2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 2);
414706f2543SmrgXOK=out[0] & 1;
415706f2543SmrgLO1LK=(out[0]>>2) &1;
416706f2543SmrgLO2LK=(out[0]>>1) &1;
417706f2543SmrgLDONrb=(out[0]>>3) &1;
418706f2543Smrg
419706f2543SmrgAFC=(out[0]>>4) & 0x7;
420706f2543Smrg
421706f2543SmrgTAD1=(out[1] & 0x7);
422706f2543SmrgTAD2=(out[1]>>4) & 0x7;
423706f2543Smrg
424706f2543Smrgxf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: status: XOK=%d LO1LK=%d LO2LK=%d LDONrb=%d AFC=%d TAD1=%d TAD2=%d\n",
425706f2543Smrg	XOK, LO1LK, LO2LK, LDONrb, AFC, TAD1, TAD2);
426706f2543Smrgxf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: status: OSCILLATOR:%s PLL1:%s PLL2:%s\n",
427706f2543Smrg	XOK ? "ok":"off", LO1LK ? "locked" : "off" , LO2LK ? "locked" : "off");
428706f2543Smrg
429706f2543Smrg}
430706f2543Smrg
431706f2543Smrgstatic void MT2032_tune(FI1236Ptr f, double freq, double step)
432706f2543Smrg{
433706f2543SmrgMT2032_parameters m;
434706f2543SmrgCARD8 data[10];
435706f2543Smrgint i;
436706f2543Smrg/* NTSC IF is 44mhz.. but 733/16=45.8125 and all TDAXXXX docs mention
437706f2543Smrg     45.75, 39, 58.75 and 30. */
438706f2543Smrg#if 0
439706f2543SmrgMT2032_calculate_register_settings(&m, freq, 1090.0, 45.125, 5.25, 6.0, step);
440706f2543SmrgMT2032_calculate_register_settings(&m, freq, 1090.0, 45.74, 5.25, 6.0, step);
441706f2543Smrg#endif
442706f2543SmrgMT2032_calculate_register_settings(&m, freq, 1090.0, f->video_if, 5.25, 3.0, step);
443706f2543SmrgMT2032_dump_parameters(f, &m);
444706f2543SmrgMT2032_implement_settings(f, &m);
445706f2543Smrg/* MT2032_dump_parameters(f, &m); */
446706f2543Smrgfor(i=0;i<3;i++){
447706f2543Smrg	MT2032_optimize_VCO(f, &m);
448706f2543Smrg	if(MT2032_wait_for_lock(f)){
449706f2543Smrg		data[0]=0x02;  /* LO Gain control register 0x02 */
450706f2543Smrg		data[1]=0x20;
451706f2543Smrg		I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0);
452706f2543Smrg		return;
453706f2543Smrg		}
454706f2543Smrg	data[0]=0x07;
455706f2543Smrg	data[1]=0x88|f->xogc;
456706f2543Smrg	I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0);
457706f2543Smrg	usleep(15000);
458706f2543Smrg	data[1]=0x08|f->xogc;
459706f2543Smrg	I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0);
460706f2543Smrg	}
461706f2543Smrgxf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to set frequency\n");
462706f2543Smrg}
463706f2543Smrg
464706f2543Smrgvoid FI1236_set_tuner_type(FI1236Ptr f, int type)
465706f2543Smrg{
466706f2543Smrgf->type=type;
467706f2543Smrgif(type>=NUM_TUNERS)type = NUM_TUNERS-1;
468706f2543Smrgif(type<0)type = 0;
469706f2543Smrgmemcpy(&(f->parm), &(tuner_parms[type]), sizeof(FI1236_parameters));
470706f2543Smrgf->original_frequency=f->parm.min_freq;
471706f2543Smrgf->afc_delta=0;
472706f2543Smrgif(type==TUNER_TYPE_MT2032){
473706f2543Smrg	MT2032_init(f);
474706f2543Smrg	return;
475706f2543Smrg	}
476706f2543Smrg}
477706f2543Smrg
478706f2543Smrg
479706f2543Smrgstatic CARD32 AFC_TimerCallback(OsTimerPtr timer, CARD32 time, pointer data){
480706f2543SmrgFI1236Ptr f=(FI1236Ptr)data;
481706f2543Smrgif(FI1236_AFC(f))return 150;
482706f2543Smrg	else {
483706f2543Smrg	f->afc_timer_installed=FALSE;
484706f2543Smrg	f->afc_count=0;
485706f2543Smrg	return 0;
486706f2543Smrg	}
487706f2543Smrg}
488706f2543Smrg
489706f2543Smrgvoid FI1236_tune(FI1236Ptr f, CARD32 frequency)
490706f2543Smrg{
491706f2543Smrg    CARD16 divider;
492706f2543Smrg	 CARD8 data;
493706f2543Smrg
494706f2543Smrg    if(frequency < f->parm.min_freq) frequency = f->parm.min_freq;
495706f2543Smrg    if(frequency > f->parm.max_freq) frequency = f->parm.max_freq;
496706f2543Smrg
497706f2543Smrg    divider = (f->parm.fcar+(CARD16)frequency) & 0x7fff;
498706f2543Smrg    f->tuner_data.div1 = (CARD8)((divider>>8)&0x7f);
499706f2543Smrg    f->tuner_data.div2 = (CARD8)(divider & 0xff);
500706f2543Smrg    f->tuner_data.control = f->parm.control;
501706f2543Smrg
502706f2543Smrg    if(frequency < f->parm.threshold1)
503706f2543Smrg    {
504706f2543Smrg        f->tuner_data.band = f->parm.band_low;
505706f2543Smrg    }
506706f2543Smrg    else if (frequency < f->parm.threshold2)
507706f2543Smrg    {
508706f2543Smrg        f->tuner_data.band = f->parm.band_mid;
509706f2543Smrg    }
510706f2543Smrg    else
511706f2543Smrg    {
512706f2543Smrg        f->tuner_data.band = f->parm.band_high;
513706f2543Smrg    }
514706f2543Smrg
515706f2543Smrg	 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Setting tuner band to %d\n", f->tuner_data.band);
516706f2543Smrg
517706f2543Smrg    xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Setting tuner frequency to %d\n", (int)frequency);
518706f2543Smrg
519706f2543Smrg	 if ((f->type == TUNER_TYPE_FM1216ME) || (f->type == TUNER_TYPE_FI1236W))
520706f2543Smrg	 {
521706f2543Smrg				f->tuner_data.aux = 0x20;
522706f2543Smrg				I2C_WriteRead(&(f->d), (I2CByte *)&(f->tuner_data), 5, NULL, 0);
523706f2543Smrg				I2C_WriteRead(&(f->d), NULL, 0, &data, 1);
524706f2543Smrg				xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Tuner status %x\n", data);
525706f2543Smrg
526706f2543Smrg	 }
527706f2543Smrg	 else
528706f2543Smrg				I2C_WriteRead(&(f->d), (I2CByte *)&(f->tuner_data), 4, NULL, 0);
529706f2543Smrg}
530706f2543Smrg
531706f2543Smrgvoid TUNER_set_frequency(FI1236Ptr f, CARD32 frequency)
532706f2543Smrg{
533706f2543Smrg    if(frequency < f->parm.min_freq) frequency = f->parm.min_freq;
534706f2543Smrg    if(frequency > f->parm.max_freq) frequency = f->parm.max_freq;
535706f2543Smrg
536706f2543Smrg    f->afc_delta=0;
537706f2543Smrg    f->original_frequency=frequency;
538706f2543Smrg
539706f2543Smrg    if(f->type==TUNER_TYPE_MT2032)
540706f2543Smrg        {
541706f2543Smrg    	MT2032_tune(f, (1.0*frequency)/16.0, 0.0625);
542706f2543Smrg	} else
543706f2543Smrg	{
544706f2543Smrg	FI1236_tune(f, frequency);
545706f2543Smrg	}
546706f2543Smrg
547706f2543Smrg    if(!f->afc_timer_installed)
548706f2543Smrg        {
549706f2543Smrg     	f->afc_timer_installed=TRUE;
550706f2543Smrg/*     	RegisterBlockAndWakeupHandlers(FI1236_BlockHandler, AFCWakeup, f); */
551706f2543Smrg	TimerSet(NULL, 0, 300, AFC_TimerCallback, f);
552706f2543Smrg	}
553706f2543Smrg
554706f2543Smrg}
555706f2543Smrg
556706f2543Smrg
557706f2543Smrgint FI1236_AFC(FI1236Ptr f)
558706f2543Smrg{
559706f2543Smrg    #if 0
560706f2543Smrg    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);
561706f2543Smrg    #endif
562706f2543Smrg    f->afc_count++;
563706f2543Smrg    if(f->type==TUNER_TYPE_MT2032)
564706f2543Smrg        {
565706f2543Smrg    	f->last_afc_hint=MT2032_get_afc_hint(f);
566706f2543Smrg        xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: afc_hint=%d\n", f->last_afc_hint);
567706f2543Smrg	if(f->last_afc_hint==TUNER_TUNED)return 0;
568706f2543Smrg	if(f->afc_count>3)f->last_afc_hint=TUNER_OFF;
569706f2543Smrg	if(f->last_afc_hint==TUNER_OFF)
570706f2543Smrg	        {
571706f2543Smrg		f->afc_delta=0;
572706f2543Smrg		} else
573706f2543Smrg		f->afc_delta+=f->last_afc_hint;
574706f2543Smrg        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);
575706f2543Smrg    	MT2032_tune(f, (1.0*f->original_frequency+0.5*f->afc_delta)/16.0, 0.03125);
576706f2543Smrg	if(f->last_afc_hint==TUNER_OFF)return 0;
577706f2543Smrg	return 1; /* call me again */
578706f2543Smrg	} else
579706f2543Smrg	{
580706f2543Smrg    	f->last_afc_hint=FI1236_get_afc_hint(f);
581706f2543Smrg	if(f->last_afc_hint==TUNER_TUNED)
582706f2543Smrg	{
583706f2543Smrg			  xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: TUNER_TUNNED\n");
584706f2543Smrg			  return 0;
585706f2543Smrg	}
586706f2543Smrg	if(f->afc_count>3)f->last_afc_hint=TUNER_OFF;
587706f2543Smrg	if(f->last_afc_hint==TUNER_OFF)
588706f2543Smrg	        {
589706f2543Smrg		f->afc_delta=0;
590706f2543Smrg		} else
591706f2543Smrg		f->afc_delta+=f->last_afc_hint;
592706f2543Smrg        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);
593706f2543Smrg	FI1236_tune(f, f->original_frequency+f->afc_delta);
594706f2543Smrg	if(f->last_afc_hint==TUNER_OFF)return 0;
595706f2543Smrg	return 1; /* call me again */
596706f2543Smrg	}
597706f2543Smrg    return 0; /* done */
598706f2543Smrg}
599706f2543Smrg
600706f2543Smrgvoid fi1236_dump_status(FI1236Ptr f)
601706f2543Smrg{
602706f2543Smrgif(f->type==TUNER_TYPE_MT2032){
603706f2543Smrg	MT2032_dump_status(f);
604706f2543Smrg	}
605706f2543Smrg}
606