diff options
Diffstat (limited to 'firmware/drivers/as3514.c')
-rw-r--r-- | firmware/drivers/as3514.c | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/firmware/drivers/as3514.c b/firmware/drivers/as3514.c new file mode 100644 index 0000000000..23d53a634e --- /dev/null +++ b/firmware/drivers/as3514.c | |||
@@ -0,0 +1,229 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Driver for AS3514 audio codec | ||
11 | * | ||
12 | * Copyright (c) 2007 Daniel Ankers | ||
13 | * | ||
14 | * All files in this archive are subject to the GNU General Public License. | ||
15 | * See the file COPYING in the source tree root for full license agreement. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include "lcd.h" | ||
22 | #include "cpu.h" | ||
23 | #include "kernel.h" | ||
24 | #include "thread.h" | ||
25 | #include "power.h" | ||
26 | #include "debug.h" | ||
27 | #include "system.h" | ||
28 | #include "sprintf.h" | ||
29 | #include "button.h" | ||
30 | #include "string.h" | ||
31 | #include "file.h" | ||
32 | #include "buffer.h" | ||
33 | #include "audio.h" | ||
34 | #include "backlight.h" | ||
35 | |||
36 | #include "as3514.h" | ||
37 | #include "i2s.h" | ||
38 | #include "i2c-pp.h" | ||
39 | |||
40 | /* convert tenth of dB volume to master volume register value */ | ||
41 | int tenthdb2master(int db) | ||
42 | { | ||
43 | /* +1..07 to -45.43dB in 1.5dB steps == 32 levels = 5 bits */ | ||
44 | /* 11111 == +1.07dB (0x1f) = 31) */ | ||
45 | /* 11110 == -0.43dB (0x1e) = 30) */ | ||
46 | /* 00001 == -43.93dB (0x01) */ | ||
47 | /* 00000 == -45.43dB (0x00) */ | ||
48 | |||
49 | if (db < VOLUME_MIN) { | ||
50 | return 0x0; | ||
51 | } else if (db >= VOLUME_MAX) { | ||
52 | return 0x1f; | ||
53 | } else { | ||
54 | return((db-VOLUME_MIN)/15); /* VOLUME_MIN is negative */ | ||
55 | } | ||
56 | } | ||
57 | |||
58 | /* convert tenth of dB volume (-405..60) to mixer volume register value */ | ||
59 | int tenthdb2mixer(int db) | ||
60 | { | ||
61 | /* FIXME: Make this sensible */ | ||
62 | if (db < -405) { | ||
63 | return 0x0; | ||
64 | } else if (db >= 60) { | ||
65 | return 0x1f; | ||
66 | } else { | ||
67 | return((db+405)/15); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | void audiohw_reset(void); | ||
72 | |||
73 | /* | ||
74 | * Initialise the PP I2C and I2S. | ||
75 | */ | ||
76 | int audiohw_init(void) { | ||
77 | /* reset I2C */ | ||
78 | i2c_init(); | ||
79 | |||
80 | /* normal outputs for CDI and I2S pin groups */ | ||
81 | DEV_INIT &= ~0x300; | ||
82 | |||
83 | /*mini2?*/ | ||
84 | outl(inl(0x70000010) & ~0x3000000, 0x70000010); | ||
85 | /*mini2?*/ | ||
86 | |||
87 | /* device reset */ | ||
88 | DEV_RS |= 0x800; | ||
89 | DEV_RS &=~0x800; | ||
90 | |||
91 | /* device enable */ | ||
92 | DEV_EN |= 0x807; | ||
93 | |||
94 | /* enable external dev clock clocks */ | ||
95 | DEV_EN |= 0x2; | ||
96 | |||
97 | /* external dev clock to 24MHz */ | ||
98 | outl(inl(0x70000018) & ~0xc, 0x70000018); | ||
99 | |||
100 | i2s_reset(); | ||
101 | |||
102 | /* Set ADC off, mixer on, DAC on, line out off, line in off, mic off */ | ||
103 | pp_i2c_send(AS3514_I2C_ADDR, AUDIOSET1, 0x60); /* Turn on DAC and mixer */ | ||
104 | pp_i2c_send(AS3514_I2C_ADDR, PLLMODE, 0x04); | ||
105 | pp_i2c_send(AS3514_I2C_ADDR, DAC_L, 0x50); /* DAC mute off, -16.5dB gain */ | ||
106 | pp_i2c_send(AS3514_I2C_ADDR, DAC_R, 0x10); /* DAC -16.5dB gain to prevent overloading | ||
107 | the headphone amp */ | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | void audiohw_postinit(void) | ||
112 | { | ||
113 | } | ||
114 | |||
115 | /* Silently enable / disable audio output */ | ||
116 | void audiohw_enable_output(bool enable) | ||
117 | { | ||
118 | if (enable) | ||
119 | { | ||
120 | /* reset the I2S controller into known state */ | ||
121 | i2s_reset(); | ||
122 | |||
123 | pp_i2c_send(AS3514_I2C_ADDR, HPH_OUT_L, 0xc0); /* Mute on, power on */ | ||
124 | audiohw_mute(0); | ||
125 | } else { | ||
126 | audiohw_mute(1); | ||
127 | pp_i2c_send(AS3514_I2C_ADDR, HPH_OUT_L, 0x80); /* Mute on, power off */ | ||
128 | } | ||
129 | } | ||
130 | |||
131 | int audiohw_set_master_vol(int vol_l, int vol_r) | ||
132 | { | ||
133 | vol_l &= 0x1f; | ||
134 | vol_r &= 0x1f; | ||
135 | pp_i2c_send(AS3514_I2C_ADDR, HPH_OUT_R, 0x40 | vol_r); | ||
136 | pp_i2c_send(AS3514_I2C_ADDR, HPH_OUT_L, 0x40 | vol_l); | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | int audiohw_set_lineout_vol(int vol_l, int vol_r) | ||
142 | { | ||
143 | pp_i2c_send(AS3514_I2C_ADDR, LINE_OUT_R, 0x40 | vol_r); | ||
144 | pp_i2c_send(AS3514_I2C_ADDR, LINE_OUT_L, 0x40 | vol_l); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | int audiohw_set_mixer_vol(int channel1, int channel2) | ||
150 | { | ||
151 | (void)channel1; | ||
152 | (void)channel2; | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | /* We are using Linear bass control */ | ||
158 | void audiohw_set_bass(int value) | ||
159 | { | ||
160 | (void)value; | ||
161 | } | ||
162 | |||
163 | void audiohw_set_treble(int value) | ||
164 | { | ||
165 | (void)value; | ||
166 | } | ||
167 | |||
168 | int audiohw_mute(int mute) | ||
169 | { | ||
170 | int curr; | ||
171 | |||
172 | curr = i2c_readbyte(AS3514_I2C_ADDR, HPH_OUT_L); | ||
173 | if (mute) | ||
174 | { | ||
175 | pp_i2c_send(AS3514_I2C_ADDR, HPH_OUT_L, curr | 0x80); | ||
176 | } else { | ||
177 | pp_i2c_send(AS3514_I2C_ADDR, HPH_OUT_L, curr & ~(0x80)); | ||
178 | } | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | /* Nice shutdown of WM8758 codec */ | ||
184 | void audiohw_close(void) | ||
185 | { | ||
186 | audiohw_mute(1); | ||
187 | } | ||
188 | |||
189 | /* Change the order of the noise shaper, 5th order is recommended above 32kHz */ | ||
190 | void audiohw_set_nsorder(int order) | ||
191 | { | ||
192 | (void)order; | ||
193 | } | ||
194 | |||
195 | void audiohw_set_sample_rate(int sampling_control) | ||
196 | { | ||
197 | (void)sampling_control; | ||
198 | /* TODO: Implement this by adjusting the I2S Master clock */ | ||
199 | } | ||
200 | |||
201 | void audiohw_enable_recording(bool source_mic) | ||
202 | { | ||
203 | (void)source_mic; | ||
204 | /* TODO */ | ||
205 | } | ||
206 | |||
207 | void audiohw_disable_recording(void) { | ||
208 | /* TODO */ | ||
209 | } | ||
210 | |||
211 | void audiohw_set_recvol(int left, int right, int type) { | ||
212 | |||
213 | (void)left; | ||
214 | (void)right; | ||
215 | (void)type; | ||
216 | } | ||
217 | |||
218 | void audiohw_set_monitor(int enable) { | ||
219 | |||
220 | (void)enable; | ||
221 | } | ||
222 | |||
223 | void audiohw_set_equalizer_band(int band, int freq, int bw, int gain) | ||
224 | { | ||
225 | (void)band; | ||
226 | (void)freq; | ||
227 | (void)bw; | ||
228 | (void)gain; | ||
229 | } | ||