Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / i2c / fi1236.c
CommitLineData
a09e091a
JB
1#ifdef HAVE_XORG_CONFIG_H
2#include <xorg-config.h>
3#endif
4
5#include <unistd.h>
6#include <stdlib.h>
7#include <string.h>
8#include <math.h>
9
10#include "xf86.h"
11#include "xf86i2c.h"
12#include "fi1236.h"
13#include "tda9885.h"
14#include "i2c_def.h"
15
16#define NUM_TUNERS 8
17
18const FI1236_parameters tuner_parms[NUM_TUNERS] = {
19 /* 0 - FI1236 */
20 {733, 884, 12820, 2516, 7220, 0xA2, 0x94, 0x34, 0x8e},
21 /* !!!based on documentation - it should be:
22 {733, 16*55.25, 16*801.25, 16*160, 16*454, 0xA0, 0x90, 0x30, 0x8e}, */
23
24 /* 1 - FI1216 */
25 {623, 16 * 48.75, 16 * 855.25, 16 * 170, 16 * 450, 0xA0, 0x90, 0x30, 0x8e},
26 /* 2 - TEMIC FN5AL */
27 {623, 16 * 45.75, 16 * 855.25, 16 * 169, 16 * 454, 0xA0, 0x90, 0x30, 0x8e},
28 /* 3 - MT2032.. */
29 {733, 768, 13760, 0, 0, 0, 0, 0, 0},
30 /* 4 - FI1246 */
31 {623, 16 * 45.75, 16 * 855.25, 16 * 170, 16 * 450, 0xA0, 0x90, 0x30, 0x8e},
32 /* 5 - FI1256 */
33 {623, 16 * 49.75, 16 * 863.25, 16 * 170, 16 * 450, 0xA0, 0x90, 0x30, 0x8e},
34 /* 6 - FI1236W */
35 /*{ 733, 884, 12820, 2516, 7220, 0x1, 0x2, 0x4, 0x8e }, */
36 {732, 16 * 55.25, 16 * 801.25, 16 * 160, 16 * 442, 0x1, 0x2, 0x4, 0x8e},
37 /* 7 - FM1216ME */
38 {623, 16 * 48.25, 16 * 863.25, 16 * 158.00, 16 * 442.00, 0x1, 0x2, 0x4, 0x8e}
39};
40
41FI1236Ptr
42Detect_FI1236(I2CBusPtr b, I2CSlaveAddr addr)
43{
44 FI1236Ptr f;
45 I2CByte a;
46
47 f = calloc(1, sizeof(FI1236Rec));
48 if (f == NULL)
49 return NULL;
50 f->d.DevName = strdup("FI12xx Tuner");
51 f->d.SlaveAddr = addr;
52 f->d.pI2CBus = b;
53 f->d.NextDev = NULL;
54 f->d.StartTimeout = b->StartTimeout;
55 f->d.BitTimeout = b->BitTimeout;
56 f->d.AcknTimeout = b->AcknTimeout;
57 f->d.ByteTimeout = b->ByteTimeout;
58 f->type = TUNER_TYPE_FI1236;
59 f->afc_timer_installed = FALSE;
60 f->last_afc_hint = TUNER_OFF;
61 f->video_if = 45.7812;
62
63 if (!I2C_WriteRead(&(f->d), NULL, 0, &a, 1)) {
64 free(f);
65 return NULL;
66 }
67 FI1236_set_tuner_type(f, TUNER_TYPE_FI1236);
68 if (!I2CDevInit(&(f->d))) {
69 free(f);
70 return NULL;
71 }
72 return f;
73}
74
75static void
76MT2032_dump_parameters(FI1236Ptr f, MT2032_parameters * m)
77{
78 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
79 "MT2032: input f_rf=%g f_if1=%g f_if2=%g f_ref=%g f_ifbw=%g f_step=%g\n",
80 m->f_rf, m->f_if1, m->f_if2, m->f_ref, m->f_ifbw, m->f_step);
81
82 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
83 "MT2032: computed f_lo1=%g f_lo2=%g LO1I=%d LO2I=%d SEL=%d STEP=%d NUM=%d\n",
84 m->f_lo1, m->f_lo2, m->LO1I, m->LO2I, m->SEL, m->STEP, m->NUM);
85}
86
87static void
88MT2032_getid(FI1236Ptr f)
89{
90 CARD8 out[4];
91 CARD8 in;
92
93 in = 0x11;
94 I2C_WriteRead(&(f->d), (I2CByte *) &in, 1, out, 4);
95 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
96 "MT2032: Company code 0x%02x%02x, part code 0x%02x, revision code 0x%02x\n",
97 out[0], out[1], out[2], out[3]);
98
99}
100
101/* might be buggy */
102#if 0
103static void
104MT2032_shutdown(FI1236Ptr f)
105{
106 CARD8 data[10];
107
108 data[0] = 0x00; /* start with register 0x00 */
109 data[1] = 0x1A;
110 data[2] = 0x44;
111 data[3] = 0x20;
112
113 I2C_WriteRead(&(f->d), (I2CByte *) data, 4, NULL, 0);
114
115 data[0] = 0x05; /* now start with register 0x05 */
116 data[1] = 0xD7;
117 data[2] = 0x14;
118 data[3] = 0x05;
119 I2C_WriteRead(&(f->d), (I2CByte *) data, 4, NULL, 0);
120
121 data[0] = 0x0B; /* now start with register 0x05 */
122 data[1] = 0x8F;
123 data[2] = 0x07;
124 data[3] = 0x43;
125 I2C_WriteRead(&(f->d), (I2CByte *) data, 4, NULL, 0);
126
127 usleep(15000);
128}
129#endif
130
131static void MT2032_dump_status(FI1236Ptr f);
132
133static void
134MT2032_init(FI1236Ptr f)
135{
136 CARD8 data[10];
137 CARD8 value;
138 CARD8 xogc = 0x00;
139
140 MT2032_getid(f);
141
142 data[0] = 0x02; /* start with register 0x02 */
143 data[1] = 0xFF;
144 data[2] = 0x0F;
145 data[3] = 0x1F;
146
147 I2C_WriteRead(&(f->d), (I2CByte *) data, 4, NULL, 0);
148
149 data[0] = 0x06; /* now start with register 0x06 */
150 data[1] = 0xE4;
151 data[2] = 0x8F;
152 data[3] = 0xC3;
153 data[4] = 0x4E;
154 data[5] = 0xEC;
155 I2C_WriteRead(&(f->d), (I2CByte *) data, 6, NULL, 0);
156
157 data[0] = 0x0d; /* now start with register 0x0d */
158 data[1] = 0x32;
159 I2C_WriteRead(&(f->d), (I2CByte *) data, 2, NULL, 0);
160
161 while (1) {
162 usleep(15000); /* wait 15 milliseconds */
163
164 data[0] = 0x0e; /* register number 7, status */
165 value = 0xFF;
166 if (!I2C_WriteRead(&(f->d), (I2CByte *) data, 1, &value, 1))
167 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
168 "MT2032: failed to read XOK\n");
169 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
170 "MT2032: XOK=%d\n", value & 0x01);
171 if (value & 1)
172 break;
173
174 data[0] = 0x07;
175 if (!I2C_WriteRead(&(f->d), (I2CByte *) data, 1, &value, 1))
176 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
177 "MT2032: failed to read XOGC\n");
178
179 xogc = value & 0x7;
180 if (xogc == 4)
181 break; /* XOGC has reached 4.. stop */
182 xogc--;
183 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
184 "MT2032: try XOGC=%d\n", xogc);
185 usleep(15000);
186 data[0] = 0x07; /* register number 7, control byte 2 */
187 data[1] = 0x08 | xogc;
188 I2C_WriteRead(&(f->d), (I2CByte *) data, 2, NULL, 0);
189 }
190 f->xogc = xogc;
191 /* wait before continuing */
192 usleep(15000); /* wait 50 milliseconds */
193 MT2032_dump_status(f);
194}
195
196static int
197MT2032_no_spur_in_band(MT2032_parameters * m)
198{
199 int n_max, n1, n2;
200 double f_test;
201
202 n_max = 5;
203 n1 = 1;
204 while (1) {
205 n2 = -n1;
206 f_test = n1 * (m->f_lo1 - m->f_lo2);
207 while (1) {
208 n2--;
209 f_test = f_test - m->f_lo2;
210 xf86DrvMsg(0, X_INFO,
211 "testing f_test=%g n1=%d n2=%d f_lo1=%g f_lo2=%g f_if2=%g\n",
212 f_test, n1, n2, m->f_lo1, m->f_lo2, m->f_if2);
213 xf86DrvMsg(0, X_INFO, "d_f=%g f_ifbw=%g\n",
214 fabs(fabs(f_test) - m->f_if2), m->f_ifbw);
215 if ((fabs(fabs(f_test) - m->f_if2) * 2.0) <= m->f_ifbw)
216 return 0;
217 if (n2 <= -n_max)
218 break;
219 /* this line in the manual is bogus. I say it is faster
220 and more correct to go over all harmonics.. */
221#if 0
222 if (f_test < (m->f_lo2 - m->f_if2 - m->f_ifbw))
223 break;
224#endif
225 }
226 n1++;
227 if (n1 >= n_max)
228 return 1;
229 }
230
231}
232
233static void
234MT2032_calculate_register_settings(MT2032_parameters * m, double f_rf,
235 double f_if1, double f_if2, double f_ref,
236 double f_ifbw, double f_step)
237{
238 int n;
239
240 m->f_rf = f_rf;
241 m->f_if1 = f_if1;
242 m->f_if2 = f_if2;
243 m->f_ref = f_ref;
244 m->f_ifbw = f_ifbw;
245 m->f_step = f_step;
246
247 m->f_lo1 = f_rf + f_if1;
248 m->LO1I = lrint(m->f_lo1 / f_ref);
249 m->f_lo1 = f_ref * m->LO1I;
250
251 m->f_lo2 = m->f_lo1 - f_rf - f_if2;
252
253 /* check for spurs */
254 n = 1;
255 while (n < 3) {
256 if (MT2032_no_spur_in_band(m))
257 break;
258
259 if (m->f_lo1 < (f_rf + f_if1))
260 m->LO1I += n;
261 else
262 m->LO1I -= n;
263
264 m->f_lo1 = m->LO1I * f_ref;
265 m->f_lo2 = m->f_lo1 - f_rf - f_if2;
266 n++;
267 }
268 /* xf86DrvMsg(0, X_INFO, "MT2032: n=%d\n", n); */
269 /* select VCO */
270
271 /* m->f_lo1>1100.0 */
272 if (m->f_lo1 < 1370.0)
273 m->SEL = 4;
274 else if (m->f_lo1 < 1530.0)
275 m->SEL = 3;
276 else if (m->f_lo1 < 1720.0)
277 m->SEL = 2;
278 else if (m->f_lo1 < 1890.0)
279 m->SEL = 1;
280 else /* m->f_lo1 < 1958.0 */
281 m->SEL = 0;
282
283 /* calculate the rest of the registers */
284 m->LO2I = floor(m->f_lo2 / f_ref);
285 m->STEP = floor(3780.0 * f_step / f_ref);
286 m->NUM = floor(3780.0 * (m->f_lo2 / f_ref - m->LO2I));
287 m->NUM = m->STEP * lrint((1.0 * m->NUM) / (1.0 * m->STEP));
288}
289
290static int
291MT2032_wait_for_lock(FI1236Ptr f)
292{
293 int n;
294 CARD8 data[10];
295 CARD8 value;
296
297 n = 12;
298 while (1) {
299 data[0] = 0x0e; /* register number 7, status */
300 I2C_WriteRead(&(f->d), (I2CByte *) data, 1, &value, 1);
301 /* xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
302 "MT2032: LO1LK=%d LO2LK=%d\n",
303 (value & 0x04)>>2, (value & 0x02)>>1); */
304 if ((value & 6) == 6)
305 break;
306 usleep(1500);
307 n--;
308 if (n < 0)
309 break;
310 }
311 if (n < 0) {
312 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
313 "MT2032: failed to set frequency\n");
314 return 0;
315 }
316 return 1;
317}
318
319static void
320MT2032_implement_settings(FI1236Ptr f, MT2032_parameters * m)
321{
322 CARD8 data[10];
323 CARD8 value;
324
325 data[0] = 0x00; /* start with register 0x00 */
326 data[1] = (m->LO1I >> 3) - 1;
327 data[2] = (m->SEL << 4) | (m->LO1I & 0x7);
328 data[3] = 0x86;
329 I2C_WriteRead(&(f->d), (I2CByte *) data, 4, NULL, 0);
330
331 data[0] = 0x05; /* start with register 0x05 */
332 data[1] = ((m->LO2I & 0x7) << 5) | ((m->LO2I >> 3) - 1);
333 if (m->f_rf < 400.0)
334 data[2] = 0xe4;
335 else
336 data[2] = 0xf4;
337 I2C_WriteRead(&(f->d), (I2CByte *) data, 3, NULL, 0);
338
339 data[0] = 0x07; /* register number 7, control byte 2 */
340 I2C_WriteRead(&(f->d), (I2CByte *) data, 1, &value, 1);
341 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
342 "MT2032: using XOGC=%d\n", (value & 0x07));
343 data[1] = 8 | (value & 0x7);
344 I2C_WriteRead(&(f->d), (I2CByte *) data, 2, NULL, 0);
345
346 data[0] = 0x0b; /* start with register 0x0b */
347 data[1] = m->NUM & 0xff;
348 data[2] = (1 << 7) | ((m->NUM >> 8) & 0x0f);
349 I2C_WriteRead(&(f->d), (I2CByte *) data, 3, NULL, 0);
350
351 MT2032_wait_for_lock(f);
352}
353
354static void
355MT2032_optimize_VCO(FI1236Ptr f, MT2032_parameters * m)
356{
357 CARD8 data[10];
358 CARD8 value;
359 CARD8 TAD1;
360
361 data[0] = 0x0f; /* register number 7, status */
362 I2C_WriteRead(&(f->d), (I2CByte *) data, 1, &value, 1);
363 TAD1 = value & 0x07;
364 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
365 "MT2032: TAD1=%d SEL=%d\n", TAD1, m->SEL);
366 if (TAD1 < 2)
367 return;
368 if (TAD1 == 2) {
369 if (m->SEL == 0)
370 return;
371 m->SEL--;
372 }
373 else {
374 if (m->SEL >= 4)
375 return;
376 m->SEL++;
377 }
378 data[0] = 0x01; /* start with register 1 */
379 data[1] = (m->SEL << 4) | (m->LO1I & 0x7);
380 I2C_WriteRead(&(f->d), (I2CByte *) data, 2, NULL, 0);
381
382}
383
384static int
385FI1236_get_afc_hint(FI1236Ptr f)
386{
387 CARD8 out;
388 CARD8 AFC;
389
390 if ((f->type == TUNER_TYPE_FM1216ME) || (f->type == TUNER_TYPE_FI1236W)) {
391 TDA9885Ptr t = (TDA9885Ptr) f->afc_source;
392
393 if (t == NULL)
394 return TUNER_OFF;
395
396 tda9885_getstatus(t);
397 tda9885_dumpstatus(t);
398 AFC = t->afc_status & 0x0f;
399
400 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
401 "AFC: FI1236_get_afc_hint: %i\n", AFC);
402 if (AFC == 0)
403 return TUNER_TUNED;
404 else if (AFC <= 0x07)
405 return TUNER_JUST_BELOW;
406 else if (AFC < 0x0f)
407 return TUNER_JUST_ABOVE;
408 else if (AFC == 0x0f)
409 return TUNER_TUNED;
410 }
411 else {
412 I2C_WriteRead(&(f->d), NULL, 0, &out, 1);
413 AFC = out & 0x7;
414 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
415 "AFC: FI1236_get_afc_hint: %i\n", AFC);
416 if (AFC == 2)
417 return TUNER_TUNED;
418 if (AFC == 3)
419 return TUNER_JUST_BELOW;
420 if (AFC == 1)
421 return TUNER_JUST_ABOVE;
422 return TUNER_OFF;
423 }
424 return TUNER_OFF;
425}
426
427static int
428MT2032_get_afc_hint(FI1236Ptr f)
429{
430 CARD8 in;
431 CARD8 out[2];
432 CARD8 AFC;
433
434 in = 0x0e;
435 I2C_WriteRead(&(f->d), (I2CByte *) &in, 1, out, 2);
436 AFC = (out[0] >> 4) & 0x7;
437#if 0
438 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC=%d TAD1=%d TAD2=%d\n",
439 AFC, out[1] & 0x7, (out[1] >> 4) & 0x07);
440#endif
441 if (AFC == 2)
442 return TUNER_TUNED;
443 if (AFC == 3)
444 return TUNER_JUST_BELOW;
445 if (AFC == 1)
446 return TUNER_JUST_ABOVE;
447 return TUNER_OFF;
448}
449
450/* this function is for external use only */
451int
452TUNER_get_afc_hint(FI1236Ptr f)
453{
454 if (f->afc_timer_installed)
455 return TUNER_STILL_TUNING;
456 return f->last_afc_hint;
457}
458
459static void
460MT2032_dump_status(FI1236Ptr f)
461{
462 CARD8 in;
463 CARD8 out[2];
464 CARD8 AFC;
465 CARD8 LDONrb;
466 CARD8 LO1LK, LO2LK, XOK;
467 CARD8 TAD2, TAD1;
468
469 in = 0x0e;
470 I2C_WriteRead(&(f->d), (I2CByte *) &in, 1, out, 2);
471 XOK = out[0] & 1;
472 LO1LK = (out[0] >> 2) & 1;
473 LO2LK = (out[0] >> 1) & 1;
474 LDONrb = (out[0] >> 3) & 1;
475
476 AFC = (out[0] >> 4) & 0x7;
477
478 TAD1 = (out[1] & 0x7);
479 TAD2 = (out[1] >> 4) & 0x7;
480
481 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
482 "MT2032: status: XOK=%d LO1LK=%d LO2LK=%d LDONrb=%d AFC=%d TAD1=%d TAD2=%d\n",
483 XOK, LO1LK, LO2LK, LDONrb, AFC, TAD1, TAD2);
484 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
485 "MT2032: status: OSCILLATOR:%s PLL1:%s PLL2:%s\n",
486 XOK ? "ok" : "off",
487 LO1LK ? "locked" : "off", LO2LK ? "locked" : "off");
488
489}
490
491static void
492MT2032_tune(FI1236Ptr f, double freq, double step)
493{
494 MT2032_parameters m;
495 CARD8 data[10];
496 int i;
497
498 /* NTSC IF is 44mhz.. but 733/16=45.8125 and all TDAXXXX docs mention
499 45.75, 39, 58.75 and 30. */
500#if 0
501 MT2032_calculate_register_settings(&m, freq, 1090.0, 45.125, 5.25, 6.0,
502 step);
503 MT2032_calculate_register_settings(&m, freq, 1090.0, 45.74, 5.25, 6.0,
504 step);
505#endif
506 MT2032_calculate_register_settings(&m, freq, 1090.0, f->video_if, 5.25, 3.0,
507 step);
508 MT2032_dump_parameters(f, &m);
509 MT2032_implement_settings(f, &m);
510 /* MT2032_dump_parameters(f, &m); */
511 for (i = 0; i < 3; i++) {
512 MT2032_optimize_VCO(f, &m);
513 if (MT2032_wait_for_lock(f)) {
514 data[0] = 0x02; /* LO Gain control register 0x02 */
515 data[1] = 0x20;
516 I2C_WriteRead(&(f->d), (I2CByte *) data, 2, NULL, 0);
517 return;
518 }
519 data[0] = 0x07;
520 data[1] = 0x88 | f->xogc;
521 I2C_WriteRead(&(f->d), (I2CByte *) data, 2, NULL, 0);
522 usleep(15000);
523 data[1] = 0x08 | f->xogc;
524 I2C_WriteRead(&(f->d), (I2CByte *) data, 2, NULL, 0);
525 }
526 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
527 "MT2032: failed to set frequency\n");
528}
529
530void
531FI1236_set_tuner_type(FI1236Ptr f, int type)
532{
533 f->type = type;
534 if (type >= NUM_TUNERS)
535 type = NUM_TUNERS - 1;
536 if (type < 0)
537 type = 0;
538 memcpy(&(f->parm), &(tuner_parms[type]), sizeof(FI1236_parameters));
539 f->original_frequency = f->parm.min_freq;
540 f->afc_delta = 0;
541 if (type == TUNER_TYPE_MT2032) {
542 MT2032_init(f);
543 return;
544 }
545}
546
547static CARD32
548AFC_TimerCallback(OsTimerPtr timer, CARD32 time, pointer data)
549{
550 FI1236Ptr f = (FI1236Ptr) data;
551
552 if (FI1236_AFC(f))
553 return 150;
554 else {
555 f->afc_timer_installed = FALSE;
556 f->afc_count = 0;
557 return 0;
558 }
559}
560
561void
562FI1236_tune(FI1236Ptr f, CARD32 frequency)
563{
564 CARD16 divider;
565 CARD8 data;
566
567 if (frequency < f->parm.min_freq)
568 frequency = f->parm.min_freq;
569 if (frequency > f->parm.max_freq)
570 frequency = f->parm.max_freq;
571
572 divider = (f->parm.fcar + (CARD16) frequency) & 0x7fff;
573 f->tuner_data.div1 = (CARD8) ((divider >> 8) & 0x7f);
574 f->tuner_data.div2 = (CARD8) (divider & 0xff);
575 f->tuner_data.control = f->parm.control;
576
577 if (frequency < f->parm.threshold1)
578 f->tuner_data.band = f->parm.band_low;
579 else if (frequency < f->parm.threshold2)
580 f->tuner_data.band = f->parm.band_mid;
581 else
582 f->tuner_data.band = f->parm.band_high;
583
584 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
585 "Setting tuner band to %d\n", f->tuner_data.band);
586
587 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
588 "Setting tuner frequency to %d\n", (int) frequency);
589
590 if ((f->type == TUNER_TYPE_FM1216ME) || (f->type == TUNER_TYPE_FI1236W)) {
591 f->tuner_data.aux = 0x20;
592 I2C_WriteRead(&(f->d), (I2CByte *) &(f->tuner_data), 5, NULL, 0);
593 I2C_WriteRead(&(f->d), NULL, 0, &data, 1);
594 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Tuner status %x\n", data);
595 }
596 else
597 I2C_WriteRead(&(f->d), (I2CByte *) &(f->tuner_data), 4, NULL, 0);
598}
599
600void
601TUNER_set_frequency(FI1236Ptr f, CARD32 frequency)
602{
603 if (frequency < f->parm.min_freq)
604 frequency = f->parm.min_freq;
605 if (frequency > f->parm.max_freq)
606 frequency = f->parm.max_freq;
607
608 f->afc_delta = 0;
609 f->original_frequency = frequency;
610
611 if (f->type == TUNER_TYPE_MT2032)
612 MT2032_tune(f, (1.0 * frequency) / 16.0, 0.0625);
613 else
614 FI1236_tune(f, frequency);
615
616 if (!f->afc_timer_installed) {
617 f->afc_timer_installed = TRUE;
618/* RegisterBlockAndWakeupHandlers(FI1236_BlockHandler, AFCWakeup, f); */
619 TimerSet(NULL, 0, 300, AFC_TimerCallback, f);
620 }
621
622}
623
624int
625FI1236_AFC(FI1236Ptr f)
626{
627#if 0
628 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
629 "AFC: f=%p f->count=%d f->original_frequency=%d f->afc_delta=%d\n",
630 f, f->afc_count, f->original_frequency, f->afc_delta);
631#endif
632 f->afc_count++;
633 if (f->type == TUNER_TYPE_MT2032) {
634 f->last_afc_hint = MT2032_get_afc_hint(f);
635 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
636 "AFC: afc_hint=%d\n", f->last_afc_hint);
637 if (f->last_afc_hint == TUNER_TUNED)
638 return 0;
639 if (f->afc_count > 3)
640 f->last_afc_hint = TUNER_OFF;
641 if (f->last_afc_hint == TUNER_OFF)
642 f->afc_delta = 0;
643 else
644 f->afc_delta += f->last_afc_hint;
645
646 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
647 "AFC: Setting tuner frequency to %g\n",
648 (0.5 * (2 * f->original_frequency + f->afc_delta)) / 16.0);
649 MT2032_tune(f,
650 (1.0 * f->original_frequency + 0.5 * f->afc_delta) / 16.0,
651 0.03125);
652 if (f->last_afc_hint == TUNER_OFF)
653 return 0;
654 return 1; /* call me again */
655 }
656 else {
657 f->last_afc_hint = FI1236_get_afc_hint(f);
658 if (f->last_afc_hint == TUNER_TUNED) {
659 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: TUNER_TUNNED\n");
660 return 0;
661 }
662 if (f->afc_count > 3)
663 f->last_afc_hint = TUNER_OFF;
664
665 if (f->last_afc_hint == TUNER_OFF)
666 f->afc_delta = 0;
667 else
668 f->afc_delta += f->last_afc_hint;
669
670 xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO,
671 "AFC: Setting tuner frequency to %g\n",
672 (0.5 * (2 * f->original_frequency + f->afc_delta)) / 16.0);
673 FI1236_tune(f, f->original_frequency + f->afc_delta);
674 if (f->last_afc_hint == TUNER_OFF)
675 return 0;
676 return 1; /* call me again */
677 }
678 return 0; /* done */
679}
680
681void
682fi1236_dump_status(FI1236Ptr f)
683{
684 if (f->type == TUNER_TYPE_MT2032)
685 MT2032_dump_status(f);
686}