1016a45b2Smrg
2016a45b2Smrg#ifdef HAVE_XORG_CONFIG_H
3016a45b2Smrg#include <xorg-config.h>
4016a45b2Smrg#endif
5016a45b2Smrg
6016a45b2Smrg#include <unistd.h>
7016a45b2Smrg#include <stdlib.h>
8016a45b2Smrg#include <string.h>
9016a45b2Smrg#include <math.h>
10016a45b2Smrg
11016a45b2Smrg#include "xf86.h"
12016a45b2Smrg#include "xf86i2c.h"
13016a45b2Smrg#include "fi1236.h"
14016a45b2Smrg#include "tda9885.h"
15016a45b2Smrg#include "i2c_def.h"
16016a45b2Smrg
17016a45b2Smrg#define NUM_TUNERS    8
18016a45b2Smrg
19016a45b2Smrgconst FI1236_parameters tuner_parms[NUM_TUNERS] =
20016a45b2Smrg{
21016a45b2Smrg    /* 0 - FI1236 */
22016a45b2Smrg    { 733 ,884 ,12820 ,2516 ,7220 ,0xA2 ,0x94, 0x34, 0x8e },
23016a45b2Smrg    /* !!!based on documentation - it should be:
24016a45b2Smrg    {733 ,16*55.25 ,16*801.25 ,16*160 ,16*454 ,0xA0 ,0x90, 0x30, 0x8e},*/
25016a45b2Smrg
26016a45b2Smrg    /* 1 - FI1216 */
27016a45b2Smrg    { 623 ,16*48.75 ,16*855.25 ,16*170 ,16*450 ,0xA0 ,0x90, 0x30, 0x8e },
28016a45b2Smrg    /* 2 - TEMIC FN5AL */
29016a45b2Smrg    { 623 ,16*45.75 ,16*855.25 ,16*169 ,16*454 ,0xA0 ,0x90, 0x30, 0x8e },
30016a45b2Smrg    /* 3 - MT2032.. */
31016a45b2Smrg    { 733 ,768 ,13760 , 0 , 0 , 0 , 0,  0, 0 },
32016a45b2Smrg    /* 4 - FI1246 */
33016a45b2Smrg    { 623 ,16*45.75 ,16*855.25 ,16*170 ,16*450 ,0xA0 ,0x90, 0x30, 0x8e },
34016a45b2Smrg    /* 5 - FI1256 */
35016a45b2Smrg    { 623 ,16*49.75 ,16*863.25 ,16*170 ,16*450 ,0xA0 ,0x90, 0x30, 0x8e },
36016a45b2Smrg    /* 6 - FI1236W */
37016a45b2Smrg    /*{ 733 ,884 ,12820 ,2516 ,7220 ,0x1 ,0x2, 0x4, 0x8e },*/
38016a45b2Smrg    { 732, 16*55.25, 16*801.25, 16*160, 16*442, 0x1, 0x2, 0x4, 0x8e },
39016a45b2Smrg	 /* 7 - FM1216ME */
40016a45b2Smrg    { 623 ,16*48.25 ,16*863.25 ,16*158.00 ,16*442.00 ,0x1 ,0x2, 0x4, 0x8e }
41016a45b2Smrg};
42016a45b2Smrg
43016a45b2Smrg
44016a45b2SmrgFI1236Ptr Detect_FI1236(I2CBusPtr b, I2CSlaveAddr addr)
45016a45b2Smrg{
46016a45b2Smrg   FI1236Ptr f;
47016a45b2Smrg   I2CByte a;
48016a45b2Smrg
49016a45b2Smrg   f = calloc(1,sizeof(FI1236Rec));
50016a45b2Smrg   if(f == NULL) return NULL;
51016a45b2Smrg   f->d.DevName = strdup("FI12xx Tuner");
52016a45b2Smrg   f->d.SlaveAddr = addr;
53016a45b2Smrg   f->d.pI2CBus = b;
54016a45b2Smrg   f->d.NextDev = NULL;
55016a45b2Smrg   f->d.StartTimeout = b->StartTimeout;
56016a45b2Smrg   f->d.BitTimeout = b->BitTimeout;
57016a45b2Smrg   f->d.AcknTimeout = b->AcknTimeout;
58016a45b2Smrg   f->d.ByteTimeout = b->ByteTimeout;
59016a45b2Smrg   f->type=TUNER_TYPE_FI1236;
60016a45b2Smrg   f->afc_timer_installed=FALSE;
61016a45b2Smrg   f->last_afc_hint=TUNER_OFF;
62016a45b2Smrg   f->video_if=45.7812;
63016a45b2Smrg
64016a45b2Smrg   if(!I2C_WriteRead(&(f->d), NULL, 0, &a, 1))
65016a45b2Smrg   {
66016a45b2Smrg   	free(f);
67016a45b2Smrg	return NULL;
68016a45b2Smrg    }
69016a45b2Smrg    FI1236_set_tuner_type(f, TUNER_TYPE_FI1236);
70016a45b2Smrg    if(!I2CDevInit(&(f->d)))
71016a45b2Smrg    {
72016a45b2Smrg       free(f);
73016a45b2Smrg       return NULL;
74016a45b2Smrg    }
75016a45b2Smrg    return f;
76016a45b2Smrg}
77016a45b2Smrg
78016a45b2Smrgstatic void MT2032_dump_parameters(FI1236Ptr f, MT2032_parameters *m)
79016a45b2Smrg{
80016a45b2Smrgxf86DrvMsg(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",
81016a45b2Smrg	m->f_rf, m->f_if1, m->f_if2, m->f_ref, m->f_ifbw, m->f_step);
82016a45b2Smrg
83016a45b2Smrgxf86DrvMsg(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",
84016a45b2Smrg	m->f_lo1, m->f_lo2, m->LO1I, m->LO2I, m->SEL, m->STEP, m->NUM);
85016a45b2Smrg}
86016a45b2Smrg
87016a45b2Smrg
88016a45b2Smrgstatic void MT2032_getid(FI1236Ptr f)
89016a45b2Smrg{
90016a45b2SmrgCARD8 out[4];
91016a45b2SmrgCARD8 in;
92016a45b2Smrg
93016a45b2Smrgin=0x11;
94016a45b2SmrgI2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 4);
95016a45b2Smrgxf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: Company code 0x%02x%02x, part code 0x%02x, revision code 0x%02x\n",
96016a45b2Smrg	out[0], out[1], out[2], out[3]);
97016a45b2Smrg
98016a45b2Smrg}
99016a45b2Smrg
100016a45b2Smrg/* might be buggy */
101016a45b2Smrg#if 0
102016a45b2Smrgstatic void MT2032_shutdown(FI1236Ptr f)
103016a45b2Smrg{
104016a45b2SmrgCARD8 data[10];
105016a45b2Smrg
106016a45b2Smrgdata[0]=0x00; /* start with register 0x00 */
107016a45b2Smrgdata[1]=0x1A;
108016a45b2Smrgdata[2]=0x44;
109016a45b2Smrgdata[3]=0x20;
110016a45b2Smrg
111016a45b2SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0);
112016a45b2Smrg
113016a45b2Smrgdata[0]=0x05; /* now start with register 0x05 */
114016a45b2Smrgdata[1]=0xD7;
115016a45b2Smrgdata[2]=0x14;
116016a45b2Smrgdata[3]=0x05;
117016a45b2SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0);
118016a45b2Smrg
119016a45b2Smrgdata[0]=0x0B; /* now start with register 0x05 */
120016a45b2Smrgdata[1]=0x8F;
121016a45b2Smrgdata[2]=0x07;
122016a45b2Smrgdata[3]=0x43;
123016a45b2SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0);
124016a45b2Smrg
125016a45b2Smrgusleep(15000);
126016a45b2Smrg}
127016a45b2Smrg#endif
128016a45b2Smrg
129016a45b2Smrgstatic void MT2032_dump_status(FI1236Ptr f);
130016a45b2Smrg
131016a45b2Smrgstatic void MT2032_init(FI1236Ptr f)
132016a45b2Smrg{
133016a45b2SmrgCARD8 data[10];
134016a45b2SmrgCARD8 value;
135016a45b2SmrgCARD8 xogc = 0x00;
136016a45b2Smrg
137016a45b2SmrgMT2032_getid(f);
138016a45b2Smrg
139016a45b2Smrgdata[0]=0x02; /* start with register 0x02 */
140016a45b2Smrgdata[1]=0xFF;
141016a45b2Smrgdata[2]=0x0F;
142016a45b2Smrgdata[3]=0x1F;
143016a45b2Smrg
144016a45b2SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0);
145016a45b2Smrg
146016a45b2Smrgdata[0]=0x06; /* now start with register 0x06 */
147016a45b2Smrgdata[1]=0xE4;
148016a45b2Smrgdata[2]=0x8F;
149016a45b2Smrgdata[3]=0xC3;
150016a45b2Smrgdata[4]=0x4E;
151016a45b2Smrgdata[5]=0xEC;
152016a45b2SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 6, NULL, 0);
153016a45b2Smrg
154016a45b2Smrgdata[0]=0x0d; /* now start with register 0x0d */
155016a45b2Smrgdata[1]=0x32;
156016a45b2SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0);
157016a45b2Smrg
158016a45b2Smrgwhile(1) {
159016a45b2Smrg	usleep(15000); /* wait 15 milliseconds */
160016a45b2Smrg
161016a45b2Smrg	data[0]=0x0e; /* register number 7, status */
162016a45b2Smrg	value=0xFF;
163016a45b2Smrg	if(!I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1))
164016a45b2Smrg		xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to read XOK\n");
165016a45b2Smrg	xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: XOK=%d\n", value & 0x01);
166016a45b2Smrg	if(value & 1) break;
167016a45b2Smrg
168016a45b2Smrg	data[0]=0x07;
169016a45b2Smrg	if(!I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1))
170016a45b2Smrg		xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to read XOGC\n");
171016a45b2Smrg
172016a45b2Smrg	xogc=value & 0x7;
173016a45b2Smrg	if(xogc==4){
174016a45b2Smrg		break; /* XOGC has reached 4.. stop */
175016a45b2Smrg		}
176016a45b2Smrg	xogc--;
177016a45b2Smrg	xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: try XOGC=%d\n", xogc);
178016a45b2Smrg	usleep(15000);
179016a45b2Smrg	data[0]=0x07; /* register number 7, control byte 2 */
180016a45b2Smrg	data[1]=0x08 | xogc;
181016a45b2Smrg	I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0);
182016a45b2Smrg	}
183016a45b2Smrgf->xogc=xogc;
184016a45b2Smrg/* wait before continuing */
185016a45b2Smrgusleep(15000); /* wait 50 milliseconds */
186016a45b2SmrgMT2032_dump_status(f);
187016a45b2Smrg}
188016a45b2Smrg
189016a45b2Smrgstatic int MT2032_no_spur_in_band(MT2032_parameters *m)
190016a45b2Smrg{
191016a45b2Smrgint n_max, n1, n2;
192016a45b2Smrgdouble f_test;
193016a45b2Smrgn_max=5;
194016a45b2Smrgn1=1;
195016a45b2Smrgwhile(1){
196016a45b2Smrg	n2=-n1;
197016a45b2Smrg	f_test=n1*(m->f_lo1-m->f_lo2);
198016a45b2Smrg	while(1){
199016a45b2Smrg		n2--;
200016a45b2Smrg		f_test=f_test-m->f_lo2;
201016a45b2Smrg		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);
202016a45b2Smrg		xf86DrvMsg(0, X_INFO, "d_f=%g f_ifbw=%g\n",fabs(fabs(f_test)-m->f_if2), m->f_ifbw);
203016a45b2Smrg		if((fabs(fabs(f_test)-m->f_if2)*2.0)<=m->f_ifbw)return 0;
204016a45b2Smrg		if(n2<=-n_max)break;
205016a45b2Smrg  		/* this line in the manual is bogus. I say it is faster
206016a45b2Smrg		and more correct to go over all harmonics.. */
207016a45b2Smrg		#if 0
208016a45b2Smrg		if(f_test<(m->f_lo2-m->f_if2-m->f_ifbw))break;
209016a45b2Smrg		#endif
210016a45b2Smrg		}
211016a45b2Smrg	n1++;
212016a45b2Smrg	if(n1>=n_max)return 1;
213016a45b2Smrg	}
214016a45b2Smrg
215016a45b2Smrg}
216016a45b2Smrg
217016a45b2Smrgstatic 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)
218016a45b2Smrg{
219016a45b2Smrgint n;
220016a45b2Smrgm->f_rf=f_rf;
221016a45b2Smrgm->f_if1=f_if1;
222016a45b2Smrgm->f_if2=f_if2;
223016a45b2Smrgm->f_ref=f_ref;
224016a45b2Smrgm->f_ifbw=f_ifbw;
225016a45b2Smrgm->f_step=f_step;
226016a45b2Smrg
227016a45b2Smrgm->f_lo1=f_rf+f_if1;
228016a45b2Smrgm->LO1I=lrint(m->f_lo1/f_ref);
229016a45b2Smrgm->f_lo1=f_ref*m->LO1I;
230016a45b2Smrg
231016a45b2Smrgm->f_lo2=m->f_lo1-f_rf-f_if2;
232016a45b2Smrg
233016a45b2Smrg/* check for spurs */
234016a45b2Smrgn=1;
235016a45b2Smrgwhile(n<3){
236016a45b2Smrg	if(MT2032_no_spur_in_band(m))break;
237016a45b2Smrg	if(m->f_lo1<(f_rf+f_if1)){
238016a45b2Smrg		m->LO1I+=n;
239016a45b2Smrg		} else {
240016a45b2Smrg		m->LO1I-=n;
241016a45b2Smrg		}
242016a45b2Smrg	m->f_lo1=m->LO1I*f_ref;
243016a45b2Smrg	m->f_lo2=m->f_lo1-f_rf-f_if2;
244016a45b2Smrg	n++;
245016a45b2Smrg	}
246016a45b2Smrg/* xf86DrvMsg(0, X_INFO, "MT2032: n=%d\n", n); */
247016a45b2Smrg/* select VCO */
248016a45b2Smrg
249016a45b2Smrg/* m->f_lo1>1100.0 */
250016a45b2Smrgif(m->f_lo1<1370.0)m->SEL=4;
251016a45b2Smrg	else
252016a45b2Smrgif(m->f_lo1<1530.0)m->SEL=3;
253016a45b2Smrg	else
254016a45b2Smrgif(m->f_lo1<1720.0)m->SEL=2;
255016a45b2Smrg	else
256016a45b2Smrgif(m->f_lo1<1890.0)m->SEL=1;
257016a45b2Smrg	else  /* m->f_lo1 < 1958.0 */
258016a45b2Smrg	m->SEL=0;
259016a45b2Smrg
260016a45b2Smrg/* calculate the rest of the registers */
261016a45b2Smrgm->LO2I=floor(m->f_lo2/f_ref);
262016a45b2Smrgm->STEP=floor(3780.0*f_step/f_ref);
263016a45b2Smrgm->NUM=floor(3780.0*(m->f_lo2/f_ref-m->LO2I));
264016a45b2Smrgm->NUM=m->STEP*lrint((1.0*m->NUM)/(1.0*m->STEP));
265016a45b2Smrg}
266016a45b2Smrg
267016a45b2Smrgstatic int MT2032_wait_for_lock(FI1236Ptr f)
268016a45b2Smrg{
269016a45b2Smrgint n;
270016a45b2SmrgCARD8 data[10];
271016a45b2SmrgCARD8 value;
272016a45b2Smrg
273016a45b2Smrgn=12;
274016a45b2Smrgwhile(1){
275016a45b2Smrg	data[0]=0x0e; /* register number 7, status */
276016a45b2Smrg	I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1);
277016a45b2Smrg/*	xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: LO1LK=%d LO2LK=%d\n", (value & 0x04)>>2, (value & 0x02)>>1); */
278016a45b2Smrg	if((value & 6)==6) break;
279016a45b2Smrg	usleep(1500);
280016a45b2Smrg	n--;
281016a45b2Smrg	if(n<0)break;
282016a45b2Smrg	}
283016a45b2Smrgif(n<0){
284016a45b2Smrg	xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to set frequency\n");
285016a45b2Smrg	return 0;
286016a45b2Smrg	}
287016a45b2Smrgreturn 1;
288016a45b2Smrg}
289016a45b2Smrg
290016a45b2Smrgstatic void MT2032_implement_settings(FI1236Ptr f, MT2032_parameters *m)
291016a45b2Smrg{
292016a45b2SmrgCARD8 data[10];
293016a45b2SmrgCARD8 value;
294016a45b2Smrg
295016a45b2Smrgdata[0]=0x00;     /* start with register 0x00 */
296016a45b2Smrgdata[1]=(m->LO1I>>3)-1;
297016a45b2Smrgdata[2]=(m->SEL<<4)|(m->LO1I & 0x7);
298016a45b2Smrgdata[3]=0x86;
299016a45b2SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0);
300016a45b2Smrg
301016a45b2Smrgdata[0]=0x05;     /* start with register 0x05 */
302016a45b2Smrgdata[1]=((m->LO2I & 0x7)<<5)|((m->LO2I>>3)-1);
303016a45b2Smrgif(m->f_rf<400.0)data[2]=0xe4;
304016a45b2Smrg	else data[2]=0xf4;
305016a45b2SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 3, NULL, 0);
306016a45b2Smrg
307016a45b2Smrgdata[0]=0x07; /* register number 7, control byte 2 */
308016a45b2SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1);
309016a45b2Smrgxf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: using XOGC=%d\n", (value & 0x07));
310016a45b2Smrgdata[1]=8 | (value & 0x7);
311016a45b2SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0);
312016a45b2Smrg
313016a45b2Smrgdata[0]=0x0b;   /* start with register 0x0b */
314016a45b2Smrgdata[1]=m->NUM & 0xff;
315016a45b2Smrgdata[2]=(1<<7)|((m->NUM >> 8) & 0x0f);
316016a45b2SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 3, NULL, 0);
317016a45b2Smrg
318016a45b2SmrgMT2032_wait_for_lock(f);
319016a45b2Smrg}
320016a45b2Smrg
321016a45b2Smrgstatic void MT2032_optimize_VCO(FI1236Ptr f, MT2032_parameters *m)
322016a45b2Smrg{
323016a45b2SmrgCARD8 data[10];
324016a45b2SmrgCARD8 value;
325016a45b2SmrgCARD8 TAD1;
326016a45b2Smrg
327016a45b2Smrgdata[0]=0x0f; /* register number 7, status */
328016a45b2SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1);
329016a45b2SmrgTAD1=value & 0x07;
330016a45b2Smrgxf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: TAD1=%d SEL=%d\n", TAD1, m->SEL);
331016a45b2Smrgif(TAD1 < 2)return;
332016a45b2Smrgif(TAD1==2){
333016a45b2Smrg	if(m->SEL==0)return;
334016a45b2Smrg	m->SEL--;
335016a45b2Smrg	} else {
336016a45b2Smrg	if(m->SEL>=4)return;
337016a45b2Smrg	m->SEL++;
338016a45b2Smrg	}
339016a45b2Smrgdata[0]=0x01;  /* start with register 1 */
340016a45b2Smrgdata[1]=(m->SEL<<4)|(m->LO1I & 0x7);
341016a45b2SmrgI2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0);
342016a45b2Smrg
343016a45b2Smrg}
344016a45b2Smrg
345016a45b2Smrgstatic int FI1236_get_afc_hint(FI1236Ptr f)
346016a45b2Smrg{
347016a45b2Smrg	CARD8 out;
348016a45b2Smrg	CARD8 AFC;
349016a45b2Smrg
350016a45b2Smrg	if ((f->type == TUNER_TYPE_FM1216ME) || (f->type == TUNER_TYPE_FI1236W))
351016a45b2Smrg	{
352016a45b2Smrg		TDA9885Ptr t = (TDA9885Ptr)f->afc_source;
353016a45b2Smrg		if (t == NULL)
354016a45b2Smrg			return TUNER_OFF;
355016a45b2Smrg
356016a45b2Smrg		tda9885_getstatus(t);
357016a45b2Smrg		tda9885_dumpstatus(t);
358016a45b2Smrg		AFC = t->afc_status & 0x0f;
359016a45b2Smrg
360016a45b2Smrg		xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: FI1236_get_afc_hint: %i\n", AFC);
361016a45b2Smrg		if (AFC == 0) return TUNER_TUNED;
362016a45b2Smrg		else if (AFC <= 0x07)return TUNER_JUST_BELOW;
363016a45b2Smrg		else if (AFC < 0x0f )return TUNER_JUST_ABOVE;
364016a45b2Smrg		else if (AFC == 0x0f)return TUNER_TUNED;
365016a45b2Smrg	}
366016a45b2Smrg	else
367016a45b2Smrg	{
368016a45b2Smrg		I2C_WriteRead(&(f->d), NULL, 0, &out, 1);
369016a45b2Smrg		AFC=out & 0x7;
370016a45b2Smrg		xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: FI1236_get_afc_hint: %i\n", AFC);
371016a45b2Smrg		if(AFC==2)return TUNER_TUNED;
372016a45b2Smrg		if(AFC==3)return TUNER_JUST_BELOW;
373016a45b2Smrg		if(AFC==1)return TUNER_JUST_ABOVE;
374016a45b2Smrg		return TUNER_OFF;
375016a45b2Smrg	}
376016a45b2Smrg	return TUNER_OFF;
377016a45b2Smrg}
378016a45b2Smrg
379016a45b2Smrgstatic int MT2032_get_afc_hint(FI1236Ptr f)
380016a45b2Smrg{
381016a45b2SmrgCARD8 in;
382016a45b2SmrgCARD8 out[2];
383016a45b2SmrgCARD8 AFC;
384016a45b2Smrgin=0x0e;
385016a45b2SmrgI2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 2);
386016a45b2SmrgAFC=(out[0]>>4) & 0x7;
387016a45b2Smrg#if 0
388016a45b2Smrgxf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC=%d TAD1=%d TAD2=%d\n", AFC, out[1] & 0x7, (out[1]>>4)& 0x07);
389016a45b2Smrg#endif
390016a45b2Smrgif(AFC==2)return TUNER_TUNED;
391016a45b2Smrgif(AFC==3)return TUNER_JUST_BELOW;
392016a45b2Smrgif(AFC==1)return TUNER_JUST_ABOVE;
393016a45b2Smrgreturn TUNER_OFF;
394016a45b2Smrg}
395016a45b2Smrg
396016a45b2Smrg/* this function is for external use only */
397016a45b2Smrgint TUNER_get_afc_hint(FI1236Ptr f)
398016a45b2Smrg{
399016a45b2Smrgif(f->afc_timer_installed)return TUNER_STILL_TUNING;
400016a45b2Smrgreturn f->last_afc_hint;
401016a45b2Smrg}
402016a45b2Smrg
403016a45b2Smrgstatic void MT2032_dump_status(FI1236Ptr f)
404016a45b2Smrg{
405016a45b2SmrgCARD8 in;
406016a45b2SmrgCARD8 out[2];
407016a45b2SmrgCARD8 AFC;
408016a45b2SmrgCARD8 LDONrb;
409016a45b2SmrgCARD8 LO1LK, LO2LK, XOK;
410016a45b2SmrgCARD8 TAD2, TAD1;
411016a45b2Smrg
412016a45b2Smrgin=0x0e;
413016a45b2SmrgI2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 2);
414016a45b2SmrgXOK=out[0] & 1;
415016a45b2SmrgLO1LK=(out[0]>>2) &1;
416016a45b2SmrgLO2LK=(out[0]>>1) &1;
417016a45b2SmrgLDONrb=(out[0]>>3) &1;
418016a45b2Smrg
419016a45b2SmrgAFC=(out[0]>>4) & 0x7;
420016a45b2Smrg
421016a45b2SmrgTAD1=(out[1] & 0x7);
422016a45b2SmrgTAD2=(out[1]>>4) & 0x7;
423016a45b2Smrg
424016a45b2Smrgxf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: status: XOK=%d LO1LK=%d LO2LK=%d LDONrb=%d AFC=%d TAD1=%d TAD2=%d\n",
425016a45b2Smrg	XOK, LO1LK, LO2LK, LDONrb, AFC, TAD1, TAD2);
426016a45b2Smrgxf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: status: OSCILLATOR:%s PLL1:%s PLL2:%s\n",
427016a45b2Smrg	XOK ? "ok":"off", LO1LK ? "locked" : "off" , LO2LK ? "locked" : "off");
428016a45b2Smrg
429016a45b2Smrg}
430016a45b2Smrg
431016a45b2Smrgstatic void MT2032_tune(FI1236Ptr f, double freq, double step)
432016a45b2Smrg{
433016a45b2SmrgMT2032_parameters m;
434016a45b2SmrgCARD8 data[10];
435016a45b2Smrgint i;
436016a45b2Smrg/* NTSC IF is 44mhz.. but 733/16=45.8125 and all TDAXXXX docs mention
437016a45b2Smrg     45.75, 39, 58.75 and 30. */
438016a45b2Smrg#if 0
439016a45b2SmrgMT2032_calculate_register_settings(&m, freq, 1090.0, 45.125, 5.25, 6.0, step);
440016a45b2SmrgMT2032_calculate_register_settings(&m, freq, 1090.0, 45.74, 5.25, 6.0, step);
441016a45b2Smrg#endif
442016a45b2SmrgMT2032_calculate_register_settings(&m, freq, 1090.0, f->video_if, 5.25, 3.0, step);
443016a45b2SmrgMT2032_dump_parameters(f, &m);
444016a45b2SmrgMT2032_implement_settings(f, &m);
445016a45b2Smrg/* MT2032_dump_parameters(f, &m); */
446016a45b2Smrgfor(i=0;i<3;i++){
447016a45b2Smrg	MT2032_optimize_VCO(f, &m);
448016a45b2Smrg	if(MT2032_wait_for_lock(f)){
449016a45b2Smrg		data[0]=0x02;  /* LO Gain control register 0x02 */
450016a45b2Smrg		data[1]=0x20;
451016a45b2Smrg		I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0);
452016a45b2Smrg		return;
453016a45b2Smrg		}
454016a45b2Smrg	data[0]=0x07;
455016a45b2Smrg	data[1]=0x88|f->xogc;
456016a45b2Smrg	I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0);
457016a45b2Smrg	usleep(15000);
458016a45b2Smrg	data[1]=0x08|f->xogc;
459016a45b2Smrg	I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0);
460016a45b2Smrg	}
461016a45b2Smrgxf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to set frequency\n");
462016a45b2Smrg}
463016a45b2Smrg
464016a45b2Smrgvoid FI1236_set_tuner_type(FI1236Ptr f, int type)
465016a45b2Smrg{
466016a45b2Smrgf->type=type;
467016a45b2Smrgif(type>=NUM_TUNERS)type = NUM_TUNERS-1;
468016a45b2Smrgif(type<0)type = 0;
469016a45b2Smrgmemcpy(&(f->parm), &(tuner_parms[type]), sizeof(FI1236_parameters));
470016a45b2Smrgf->original_frequency=f->parm.min_freq;
471016a45b2Smrgf->afc_delta=0;
472016a45b2Smrgif(type==TUNER_TYPE_MT2032){
473016a45b2Smrg	MT2032_init(f);
474016a45b2Smrg	return;
475016a45b2Smrg	}
476016a45b2Smrg}
477016a45b2Smrg
478016a45b2Smrg
479016a45b2Smrgstatic CARD32 AFC_TimerCallback(OsTimerPtr timer, CARD32 time, pointer data){
480016a45b2SmrgFI1236Ptr f=(FI1236Ptr)data;
481016a45b2Smrgif(FI1236_AFC(f))return 150;
482016a45b2Smrg	else {
483016a45b2Smrg	f->afc_timer_installed=FALSE;
484016a45b2Smrg	f->afc_count=0;
485016a45b2Smrg	return 0;
486016a45b2Smrg	}
487016a45b2Smrg}
488016a45b2Smrg
489016a45b2Smrgvoid FI1236_tune(FI1236Ptr f, CARD32 frequency)
490016a45b2Smrg{
491016a45b2Smrg    CARD16 divider;
492016a45b2Smrg	 CARD8 data;
493016a45b2Smrg
494016a45b2Smrg    if(frequency < f->parm.min_freq) frequency = f->parm.min_freq;
495016a45b2Smrg    if(frequency > f->parm.max_freq) frequency = f->parm.max_freq;
496016a45b2Smrg
497016a45b2Smrg    divider = (f->parm.fcar+(CARD16)frequency) & 0x7fff;
498016a45b2Smrg    f->tuner_data.div1 = (CARD8)((divider>>8)&0x7f);
499016a45b2Smrg    f->tuner_data.div2 = (CARD8)(divider & 0xff);
500016a45b2Smrg    f->tuner_data.control = f->parm.control;
501016a45b2Smrg
502016a45b2Smrg    if(frequency < f->parm.threshold1)
503016a45b2Smrg    {
504016a45b2Smrg        f->tuner_data.band = f->parm.band_low;
505016a45b2Smrg    }
506016a45b2Smrg    else if (frequency < f->parm.threshold2)
507016a45b2Smrg    {
508016a45b2Smrg        f->tuner_data.band = f->parm.band_mid;
509016a45b2Smrg    }
510016a45b2Smrg    else
511016a45b2Smrg    {
512016a45b2Smrg        f->tuner_data.band = f->parm.band_high;
513016a45b2Smrg    }
514016a45b2Smrg
515016a45b2Smrg	 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Setting tuner band to %d\n", f->tuner_data.band);
516016a45b2Smrg
517016a45b2Smrg    xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Setting tuner frequency to %d\n", (int)frequency);
518016a45b2Smrg
519016a45b2Smrg	 if ((f->type == TUNER_TYPE_FM1216ME) || (f->type == TUNER_TYPE_FI1236W))
520016a45b2Smrg	 {
521016a45b2Smrg				f->tuner_data.aux = 0x20;
522016a45b2Smrg				I2C_WriteRead(&(f->d), (I2CByte *)&(f->tuner_data), 5, NULL, 0);
523016a45b2Smrg				I2C_WriteRead(&(f->d), NULL, 0, &data, 1);
524016a45b2Smrg				xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Tuner status %x\n", data);
525016a45b2Smrg
526016a45b2Smrg	 }
527016a45b2Smrg	 else
528016a45b2Smrg				I2C_WriteRead(&(f->d), (I2CByte *)&(f->tuner_data), 4, NULL, 0);
529016a45b2Smrg}
530016a45b2Smrg
531016a45b2Smrgvoid TUNER_set_frequency(FI1236Ptr f, CARD32 frequency)
532016a45b2Smrg{
533016a45b2Smrg    if(frequency < f->parm.min_freq) frequency = f->parm.min_freq;
534016a45b2Smrg    if(frequency > f->parm.max_freq) frequency = f->parm.max_freq;
535016a45b2Smrg
536016a45b2Smrg    f->afc_delta=0;
537016a45b2Smrg    f->original_frequency=frequency;
538016a45b2Smrg
539016a45b2Smrg    if(f->type==TUNER_TYPE_MT2032)
540016a45b2Smrg        {
541016a45b2Smrg    	MT2032_tune(f, (1.0*frequency)/16.0, 0.0625);
542016a45b2Smrg	} else
543016a45b2Smrg	{
544016a45b2Smrg	FI1236_tune(f, frequency);
545016a45b2Smrg	}
546016a45b2Smrg
547016a45b2Smrg    if(!f->afc_timer_installed)
548016a45b2Smrg        {
549016a45b2Smrg     	f->afc_timer_installed=TRUE;
550016a45b2Smrg/*     	RegisterBlockAndWakeupHandlers(FI1236_BlockHandler, AFCWakeup, f); */
551016a45b2Smrg	TimerSet(NULL, 0, 300, AFC_TimerCallback, f);
552016a45b2Smrg	}
553016a45b2Smrg
554016a45b2Smrg}
555016a45b2Smrg
556016a45b2Smrg
557016a45b2Smrgint FI1236_AFC(FI1236Ptr f)
558016a45b2Smrg{
559016a45b2Smrg    #if 0
560016a45b2Smrg    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);
561016a45b2Smrg    #endif
562016a45b2Smrg    f->afc_count++;
563016a45b2Smrg    if(f->type==TUNER_TYPE_MT2032)
564016a45b2Smrg        {
565016a45b2Smrg    	f->last_afc_hint=MT2032_get_afc_hint(f);
566016a45b2Smrg        xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: afc_hint=%d\n", f->last_afc_hint);
567016a45b2Smrg	if(f->last_afc_hint==TUNER_TUNED)return 0;
568016a45b2Smrg	if(f->afc_count>3)f->last_afc_hint=TUNER_OFF;
569016a45b2Smrg	if(f->last_afc_hint==TUNER_OFF)
570016a45b2Smrg	        {
571016a45b2Smrg		f->afc_delta=0;
572016a45b2Smrg		} else
573016a45b2Smrg		f->afc_delta+=f->last_afc_hint;
574016a45b2Smrg        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);
575016a45b2Smrg    	MT2032_tune(f, (1.0*f->original_frequency+0.5*f->afc_delta)/16.0, 0.03125);
576016a45b2Smrg	if(f->last_afc_hint==TUNER_OFF)return 0;
577016a45b2Smrg	return 1; /* call me again */
578016a45b2Smrg	} else
579016a45b2Smrg	{
580016a45b2Smrg    	f->last_afc_hint=FI1236_get_afc_hint(f);
581016a45b2Smrg	if(f->last_afc_hint==TUNER_TUNED)
582016a45b2Smrg	{
583016a45b2Smrg			  xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: TUNER_TUNNED\n");
584016a45b2Smrg			  return 0;
585016a45b2Smrg	}
586016a45b2Smrg	if(f->afc_count>3)f->last_afc_hint=TUNER_OFF;
587016a45b2Smrg	if(f->last_afc_hint==TUNER_OFF)
588016a45b2Smrg	        {
589016a45b2Smrg		f->afc_delta=0;
590016a45b2Smrg		} else
591016a45b2Smrg		f->afc_delta+=f->last_afc_hint;
592016a45b2Smrg        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);
593016a45b2Smrg	FI1236_tune(f, f->original_frequency+f->afc_delta);
594016a45b2Smrg	if(f->last_afc_hint==TUNER_OFF)return 0;
595016a45b2Smrg	return 1; /* call me again */
596016a45b2Smrg	}
597016a45b2Smrg    return 0; /* done */
598016a45b2Smrg}
599016a45b2Smrg
600016a45b2Smrgvoid fi1236_dump_status(FI1236Ptr f)
601016a45b2Smrg{
602016a45b2Smrgif(f->type==TUNER_TYPE_MT2032){
603016a45b2Smrg	MT2032_dump_status(f);
604016a45b2Smrg	}
605016a45b2Smrg}
606