Simplify special case function, speedup of about 0.2MHz on both coldfire and pp decod...
[kugel-rb.git] / firmware / drivers / tuner / s1a0903x01.c
blob3a417d73aff30133a74cfad127ab7fe37070d247
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 * 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 ****************************************************************************/
23 #include <stdbool.h>
24 #include <stdlib.h>
25 #include "config.h"
26 #include "kernel.h"
27 #include "tuner.h" /* tuner abstraction interface */
28 #include "fmradio.h" /* physical interface driver */
29 #include "sound.h"
30 #include "mas.h"
31 #include "power.h"
33 #define DEFAULT_IN1 0x100003 /* Mute */
34 #define DEFAULT_IN2 0x140884 /* 5kHz, 7.2MHz crystal */
35 #define PLL_FREQ_STEP 10000
37 static int fm_in1;
38 static int fm_in2;
39 static int fm_present = -1; /* unknown */
41 /* tuner abstraction layer: set something to the tuner */
42 int s1a0903x01_set(int setting, int value)
44 int val = 1;
46 switch(setting)
48 case RADIO_SLEEP:
49 if (!value)
50 { /* wakeup: just unit */
51 fm_in1 = DEFAULT_IN1;
52 fm_in2 = DEFAULT_IN2;
53 fmradio_set(1, fm_in1);
54 fmradio_set(2, fm_in2);
56 /* else we have no sleep mode? */
57 break;
59 case RADIO_FREQUENCY:
61 int pll_cnt;
62 #if CONFIG_CODEC == MAS3587F
63 /* Shift the MAS internal clock away for certain frequencies to
64 * avoid interference. */
65 int pitch = 1000;
67 /* 4th harmonic falls in the FM frequency range */
68 int if_freq = 4 * mas_get_pllfreq();
70 /* shift the mas harmonic >= 300 kHz away using the direction
71 * which needs less shifting. */
72 if (value < if_freq)
74 if (if_freq - value < 300000)
75 pitch = 1003 - (if_freq - value) / 100000;
77 else
79 if (value - if_freq < 300000)
80 pitch = 997 + (value - if_freq) / 100000;
82 sound_set_pitch(pitch);
83 #endif
84 /* We add the standard Intermediate Frequency 10.7MHz
85 ** before calculating the divisor
86 ** The reference frequency is set to 50kHz, and the VCO
87 ** output is prescaled by 2.
90 pll_cnt = (value + 10700000) / (PLL_FREQ_STEP/2) / 2;
92 /* 0x100000 == FM mode
93 ** 0x000002 == Microprocessor controlled Mute
95 fm_in1 = (fm_in1 & 0xfff00007) | (pll_cnt << 3);
96 fmradio_set(1, fm_in1);
97 break;
100 case RADIO_SCAN_FREQUENCY:
101 /* Tune in and delay */
102 s1a0903x01_set(RADIO_FREQUENCY, value);
103 sleep(1);
104 /* Start IF measurement */
105 fm_in1 |= 4;
106 fmradio_set(1, fm_in1);
107 sleep(1);
108 val = s1a0903x01_get(RADIO_TUNED);
109 break;
111 case RADIO_MUTE:
112 fm_in1 = (fm_in1 & 0xfffffffe) | (value?1:0);
113 fmradio_set(1, fm_in1);
114 break;
116 case RADIO_FORCE_MONO:
117 fm_in2 = (fm_in2 & 0xfffffffb) | (value?0:4);
118 fmradio_set(2, fm_in2);
119 break;
120 /* NOTE: These were only zeroed when starting the tuner from OFF
121 but the default values already set them to 0. */
122 #if 0
123 case S1A0903X01_IF_MEASUREMENT:
124 fm_in1 = (fm_in1 & 0xfffffffb) | (value?4:0);
125 fmradio_set(1, fm_in1);
126 break;
128 case S1A0903X01_SENSITIVITY:
129 fm_in2 = (fm_in2 & 0xffff9fff) | ((value & 3) << 13);
130 fmradio_set(2, fm_in2);
131 break;
132 #endif
133 default:
134 val = -1;
137 return val;
140 /* tuner abstraction layer: read something from the tuner */
141 int s1a0903x01_get(int setting)
143 int val = -1;
144 switch(setting)
146 case RADIO_PRESENT:
147 if (fm_present == -1)
149 #ifdef HAVE_TUNER_PWR_CTRL
150 bool fmstatus = tuner_power(true);
151 #endif
152 /* 5kHz, 7.2MHz crystal, test mode 1 */
153 fmradio_set(2, 0x140885);
154 fm_present = (fmradio_read(0) == 0x140885);
155 #ifdef HAVE_TUNER_PWR_CTRL
156 if (!fmstatus)
157 tuner_power(false);
158 #endif
161 val = fm_present;
162 break;
164 case RADIO_TUNED:
165 val = fmradio_read(3);
166 val = abs(10700 - ((val & 0x7ffff) / 8)) < 50; /* convert to kHz */
167 break;
169 case RADIO_STEREO:
170 val = fmradio_read(3);
171 val = ((val & 0x100000) ? true : false);
172 break;
174 return val;