1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Tuner "middleware" for Samsung S1A0903X01 chip
11 * Copyright (C) 2003 Linus Nielsen Feltzing
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
27 #include "tuner.h" /* tuner abstraction interface */
28 #include "fmradio.h" /* physical interface driver */
32 #define DEFAULT_IN1 0x100003 /* Mute */
33 #define DEFAULT_IN2 0x140884 /* 5kHz, 7.2MHz crystal */
34 #define PLL_FREQ_STEP 10000
38 static int fm_present
= -1; /* unknown */
40 /* tuner abstraction layer: set something to the tuner */
41 int s1a0903x01_set(int setting
, int value
)
49 { /* wakeup: just unit */
52 fmradio_set(1, fm_in1
);
53 fmradio_set(2, fm_in2
);
55 /* else we have no sleep mode? */
61 #if CONFIG_CODEC == MAS3587F
62 /* Shift the MAS internal clock away for certain frequencies to
63 * avoid interference. */
66 /* 4th harmonic falls in the FM frequency range */
67 int if_freq
= 4 * mpeg_get_mas_pllfreq();
69 /* shift the mas harmonic >= 300 kHz away using the direction
70 * which needs less shifting. */
73 if (if_freq
- value
< 300000)
74 pitch
= 1003 - (if_freq
- value
) / 100000;
78 if (value
- if_freq
< 300000)
79 pitch
= 997 + (value
- if_freq
) / 100000;
81 sound_set_pitch(pitch
);
83 /* We add the standard Intermediate Frequency 10.7MHz
84 ** before calculating the divisor
85 ** The reference frequency is set to 50kHz, and the VCO
86 ** output is prescaled by 2.
89 pll_cnt
= (value
+ 10700000) / (PLL_FREQ_STEP
/2) / 2;
91 /* 0x100000 == FM mode
92 ** 0x000002 == Microprocessor controlled Mute
94 fm_in1
= (fm_in1
& 0xfff00007) | (pll_cnt
<< 3);
95 fmradio_set(1, fm_in1
);
99 case RADIO_SCAN_FREQUENCY
:
100 /* Tune in and delay */
101 s1a0903x01_set(RADIO_FREQUENCY
, value
);
103 /* Start IF measurement */
105 fmradio_set(1, fm_in1
);
107 val
= s1a0903x01_get(RADIO_TUNED
);
111 fm_in1
= (fm_in1
& 0xfffffffe) | (value
?1:0);
112 fmradio_set(1, fm_in1
);
115 case RADIO_FORCE_MONO
:
116 fm_in2
= (fm_in2
& 0xfffffffb) | (value
?0:4);
117 fmradio_set(2, fm_in2
);
119 /* NOTE: These were only zeroed when starting the tuner from OFF
120 but the default values already set them to 0. */
122 case S1A0903X01_IF_MEASUREMENT
:
123 fm_in1
= (fm_in1
& 0xfffffffb) | (value
?4:0);
124 fmradio_set(1, fm_in1
);
127 case S1A0903X01_SENSITIVITY
:
128 fm_in2
= (fm_in2
& 0xffff9fff) | ((value
& 3) << 13);
129 fmradio_set(2, fm_in2
);
139 /* tuner abstraction layer: read something from the tuner */
140 int s1a0903x01_get(int setting
)
146 if (fm_present
== -1)
148 #ifdef HAVE_TUNER_PWR_CTRL
149 bool fmstatus
= tuner_power(true);
151 /* 5kHz, 7.2MHz crystal, test mode 1 */
152 fmradio_set(2, 0x140885);
153 fm_present
= (fmradio_read(0) == 0x140885);
154 #ifdef HAVE_TUNER_PWR_CTRL
164 val
= fmradio_read(3);
165 val
= abs(10700 - ((val
& 0x7ffff) / 8)) < 50; /* convert to kHz */
169 val
= fmradio_read(3);
170 val
= ((val
& 0x100000) ? true : false);