move handling of shared manuals (like h100 series) to a new setting in rbutil.ini...
[Rockbox.git] / firmware / tuner_samsung.c
blob82934d716063b0aecc742ffe265b627bc94a48fa
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 * Tuner "middleware" for Samsung S1A0903X01 chip
11 * Copyright (C) 2003 Linus Nielsen Feltzing
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
21 #include <stdbool.h>
22 #include <stdlib.h>
23 #include "config.h"
24 #include "kernel.h"
25 #include "tuner.h" /* tuner abstraction interface */
26 #include "fmradio.h" /* physical interface driver */
27 #include "mpeg.h"
28 #include "sound.h"
30 #define DEFAULT_IN1 0x100003 /* Mute */
31 #define DEFAULT_IN2 0x140884 /* 5kHz, 7.2MHz crystal */
32 #define PLL_FREQ_STEP 10000
34 static int fm_in1;
35 static int fm_in2;
37 /* tuner abstraction layer: set something to the tuner */
38 int samsung_set(int setting, int value)
40 int val = 1;
42 switch(setting)
44 case RADIO_SLEEP:
45 if (!value)
46 { /* wakeup: just unit */
47 fm_in1 = DEFAULT_IN1;
48 fm_in2 = DEFAULT_IN2;
49 fmradio_set(1, fm_in1);
50 fmradio_set(2, fm_in2);
52 /* else we have no sleep mode? */
53 break;
55 case RADIO_FREQUENCY:
57 int pll_cnt;
58 #if CONFIG_CODEC == MAS3587F
59 /* Shift the MAS internal clock away for certain frequencies to
60 * avoid interference. */
61 int pitch = 1000;
63 /* 4th harmonic falls in the FM frequency range */
64 int if_freq = 4 * mpeg_get_mas_pllfreq();
66 /* shift the mas harmonic >= 300 kHz away using the direction
67 * which needs less shifting. */
68 if (value < if_freq)
70 if (if_freq - value < 300000)
71 pitch = 1003 - (if_freq - value) / 100000;
73 else
75 if (value - if_freq < 300000)
76 pitch = 997 + (value - if_freq) / 100000;
78 sound_set_pitch(pitch);
79 #endif
80 /* We add the standard Intermediate Frequency 10.7MHz
81 ** before calculating the divisor
82 ** The reference frequency is set to 50kHz, and the VCO
83 ** output is prescaled by 2.
86 pll_cnt = (value + 10700000) / (PLL_FREQ_STEP/2) / 2;
88 /* 0x100000 == FM mode
89 ** 0x000002 == Microprocessor controlled Mute
91 fm_in1 = (fm_in1 & 0xfff00007) | (pll_cnt << 3);
92 fmradio_set(1, fm_in1);
93 break;
96 case RADIO_SCAN_FREQUENCY:
97 /* Tune in and delay */
98 samsung_set(RADIO_FREQUENCY, value);
99 sleep(1);
100 /* Start IF measurement */
101 samsung_set(RADIO_IF_MEASUREMENT, 1);
102 sleep(1);
103 val = samsung_get(RADIO_TUNED);
104 break;
106 case RADIO_MUTE:
107 fm_in1 = (fm_in1 & 0xfffffffe) | (value?1:0);
108 fmradio_set(1, fm_in1);
109 break;
111 case RADIO_IF_MEASUREMENT:
112 fm_in1 = (fm_in1 & 0xfffffffb) | (value?4:0);
113 fmradio_set(1, fm_in1);
114 break;
116 case RADIO_SENSITIVITY:
117 fm_in2 = (fm_in2 & 0xffff9fff) | ((value & 3) << 13);
118 fmradio_set(2, fm_in2);
119 break;
121 case RADIO_FORCE_MONO:
122 fm_in2 = (fm_in2 & 0xfffffffb) | (value?0:4);
123 fmradio_set(2, fm_in2);
124 break;
125 default:
126 val = -1;
129 return val;
132 /* tuner abstraction layer: read something from the tuner */
133 int samsung_get(int setting)
135 int val = -1;
136 switch(setting)
138 case RADIO_PRESENT:
139 fmradio_set(2, 0x140885); /* 5kHz, 7.2MHz crystal, test mode 1 */
140 val = (fmradio_read(0) == 0x140885);
141 break;
143 case RADIO_TUNED:
144 val = fmradio_read(3);
145 val = abs(10700 - ((val & 0x7ffff) / 8)) < 50; /* convert to kHz */
146 break;
148 case RADIO_STEREO:
149 val = fmradio_read(3);
150 val = ((val & 0x100000) ? true : false);
152 return val;