summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES5
-rw-r--r--firmware/drivers/audio/as3514.c309
-rw-r--r--firmware/export/audio.h3
-rw-r--r--firmware/export/audiohw.h3
-rw-r--r--firmware/export/config-e200.h15
-rw-r--r--firmware/export/pcm_sampr.h15
-rw-r--r--firmware/sound.c2
-rw-r--r--firmware/target/arm/pcm-pp.c202
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/ata-e200.c11
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/audio-e200.c103
10 files changed, 534 insertions, 134 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index fdb457cbed..70bd12e0d5 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -296,7 +296,9 @@ target/arm/system-pp502x.c
296target/arm/crt0-pp-bl.S 296target/arm/crt0-pp-bl.S
297#else 297#else
298target/arm/pcm-pp.c 298target/arm/pcm-pp.c
299#ifndef SANSA_E200
299target/arm/audio-pp.c 300target/arm/audio-pp.c
301#endif /* SANSA_E200 */
300target/arm/crt0-pp.S 302target/arm/crt0-pp.S
301#endif 303#endif
302#elif CONFIG_CPU == PNX0101 304#elif CONFIG_CPU == PNX0101
@@ -375,6 +377,9 @@ target/arm/usb-pp.c
375target/arm/sandisk/sansa-e200/button-e200.c 377target/arm/sandisk/sansa-e200/button-e200.c
376target/arm/sandisk/sansa-e200/power-e200.c 378target/arm/sandisk/sansa-e200/power-e200.c
377target/arm/i2s-pp.c 379target/arm/i2s-pp.c
380#ifndef BOOTLOADER
381target/arm/sandisk/sansa-e200/audio-e200.c
382#endif /* BOOTLOADER */
378#endif /* SIMULATOR */ 383#endif /* SIMULATOR */
379#endif /* SANSA_E200 */ 384#endif /* SANSA_E200 */
380 385
diff --git a/firmware/drivers/audio/as3514.c b/firmware/drivers/audio/as3514.c
index 3c11caa4c7..982bbe16d3 100644
--- a/firmware/drivers/audio/as3514.c
+++ b/firmware/drivers/audio/as3514.c
@@ -22,46 +22,76 @@
22#include "cpu.h" 22#include "cpu.h"
23#include "debug.h" 23#include "debug.h"
24#include "system.h" 24#include "system.h"
25#include "audio.h"
25 26
26#include "audiohw.h" 27#include "audiohw.h"
27#include "i2s.h" 28#include "i2s.h"
28#include "i2c-pp.h" 29#include "i2c-pp.h"
29 30
30const struct sound_settings_info audiohw_settings[] = { 31const struct sound_settings_info audiohw_settings[] = {
31 [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25}, 32 [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25},
32 /* HAVE_SW_TONE_CONTROLS */ 33 /* HAVE_SW_TONE_CONTROLS */
33 [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0}, 34 [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0},
34 [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0}, 35 [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0},
35 [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, 36 [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0},
36 [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, 37 [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0},
37 [SOUND_STEREO_WIDTH] = {"%", 0, 1, 0, 255, 100}, 38 [SOUND_STEREO_WIDTH] = {"%", 0, 1, 0, 255, 100},
39 [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 39, 23},
40 [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 31, 23},
41 [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 31, 23},
38}; 42};
39 43
40/* Shadow registers */ 44/* Shadow registers */
41int as3514_regs[0x1E]; /* last audio register: PLLMODE 0x1d */ 45struct as3514_info
46{
47 int vol_r; /* Cached volume level (R) */
48 int vol_l; /* Cached volume level (L) */
49 unsigned int regs[0x1e]; /* last audio register: PLLMODE 0x1d */
50} as3514;
51
52enum
53{
54 SOURCE_DAC = 0,
55 SOURCE_MIC1,
56 SOURCE_LINE_IN1,
57 SOURCE_LINE_IN1_ANALOG
58};
59
60static unsigned int source = SOURCE_DAC;
42 61
43/* 62/*
44 * little helper method to set register values. 63 * little helper method to set register values.
45 * With the help of as3514_regs, we minimize i2c 64 * With the help of as3514.regs, we minimize i2c
46 * traffic. 65 * traffic.
47 */ 66 */
48static void as3514_write(int reg, int value) 67static void as3514_write(unsigned int reg, unsigned int value)
49{ 68{
50 if (pp_i2c_send(AS3514_I2C_ADDR, reg, value) != 2) 69 if (pp_i2c_send(AS3514_I2C_ADDR, reg, value) != 2)
51 { 70 {
52 DEBUGF("as3514 error reg=0x%x", reg); 71 DEBUGF("as3514 error reg=0x%02x", reg);
53 } 72 }
54 73
55 if ((unsigned int)reg < sizeof(as3514_regs) / sizeof(int)) 74 if (reg < ARRAYLEN(as3514.regs))
56 { 75 {
57 as3514_regs[reg] = value; 76 as3514.regs[reg] = value;
58 } 77 }
59 else 78 else
60 { 79 {
61 DEBUGF("as3514 error reg=0x%x", reg); 80 DEBUGF("as3514 error reg=0x%02x", reg);
62 } 81 }
63} 82}
64 83
84/* Helpers to set/clear bits */
85static void as3514_write_or(unsigned int reg, unsigned int bits)
86{
87 as3514_write(reg, as3514.regs[reg] | bits);
88}
89
90static void as3514_write_and(unsigned int reg, unsigned int bits)
91{
92 as3514_write(reg, as3514.regs[reg] & bits);
93}
94
65/* convert tenth of dB volume to master volume register value */ 95/* convert tenth of dB volume to master volume register value */
66int tenthdb2master(int db) 96int tenthdb2master(int db)
67{ 97{
@@ -75,6 +105,26 @@ int tenthdb2master(int db)
75 } 105 }
76} 106}
77 107
108int sound_val2phys(int setting, int value)
109{
110 int result;
111
112 switch(setting)
113 {
114 case SOUND_LEFT_GAIN:
115 case SOUND_RIGHT_GAIN:
116 case SOUND_MIC_GAIN:
117 result = (value - 23) * 15;
118 break;
119
120 default:
121 result = value;
122 break;
123 }
124
125 return result;
126}
127
78void audiohw_reset(void); 128void audiohw_reset(void);
79 129
80/* 130/*
@@ -110,20 +160,33 @@ int audiohw_init(void)
110 i2s_reset(); 160 i2s_reset();
111 161
112 /* Set ADC off, mixer on, DAC on, line out off, line in off, mic off */ 162 /* Set ADC off, mixer on, DAC on, line out off, line in off, mic off */
113 as3514_write(AUDIOSET1, 0x64); /* Turn on SUM, DAC, LineIn 1 */ 163
114 as3514_write(AUDIOSET3, 0x5); /* Set HPCM off, ZCU off*/ 164 /* Turn on SUM, DAC */
115 as3514_write(HPH_OUT_R, 0xc0 | 0x16); /* set vol and set speaker over-current to 0 */ 165 as3514_write(AUDIOSET1, (1 << 6) | (1 << 5));
116 as3514_write(HPH_OUT_L, 0x16); /* set default vol for headphone */ 166
117#if 0 167 /* Set HPCM off, ZCU off*/
118 as3514_write(LINE_IN1_R, 0x36); /* unmute lineIn 1 and set gain */ 168 as3514_write(AUDIOSET3, (1 << 2) | (1 << 0));
119 as3514_write(LINE_IN1_L, 0x36); /* unmute lineIn 1 and set gain */ 169
120#endif 170 /* set vol and set speaker over-current to 0 */
171 as3514_write(HPH_OUT_R, (0x3 << 6) | 0x16);
172 /* set default vol for headphone */
173 as3514_write(HPH_OUT_L, 0x16);
174
175 /* LRCK 24-48kHz */
121 as3514_write(PLLMODE, 0x00); 176 as3514_write(PLLMODE, 0x00);
122 177
178 /* DAC_Mute_off */
179 as3514_write_or(DAC_L, (1 << 6));
180
181 /* M1_Sup_off */
182 as3514_write_or(MIC1_L, (1 << 7));
183 /* M2_Sup_off */
184 as3514_write_or(MIC2_L, (1 << 7));
185
123 /* read all reg values */ 186 /* read all reg values */
124 for (i = 0; i < sizeof(as3514_regs) / sizeof(int); i++) 187 for (i = 0; i < ARRAYLEN(as3514.regs); i++)
125 { 188 {
126 as3514_regs[i] = i2c_readbyte(AS3514_I2C_ADDR, i); 189 as3514.regs[i] = i2c_readbyte(AS3514_I2C_ADDR, i);
127 } 190 }
128 191
129 return 0; 192 return 0;
@@ -136,75 +199,80 @@ void audiohw_postinit(void)
136/* Silently enable / disable audio output */ 199/* Silently enable / disable audio output */
137void audiohw_enable_output(bool enable) 200void audiohw_enable_output(bool enable)
138{ 201{
139 int curr; 202 if (enable) {
140 curr = as3514_regs[HPH_OUT_L];
141
142 if (enable)
143 {
144 /* reset the I2S controller into known state */ 203 /* reset the I2S controller into known state */
145 i2s_reset(); 204 i2s_reset();
146 205
147 as3514_write(HPH_OUT_L, curr | 0x40); /* power on */ 206 as3514_write_or(HPH_OUT_L, (1 << 6)); /* power on */
148 audiohw_mute(0); 207 audiohw_mute(0);
149 } else { 208 } else {
150 audiohw_mute(1); 209 audiohw_mute(1);
151 as3514_write(HPH_OUT_L, curr & ~(0x40)); /* power off */ 210 as3514_write_and(HPH_OUT_L, ~(1 << 6)); /* power off */
152 } 211 }
153} 212}
154 213
155int audiohw_set_master_vol(int vol_l, int vol_r) 214int audiohw_set_master_vol(int vol_l, int vol_r)
156{ 215{
157 int hph_r = as3514_regs[HPH_OUT_R] & ~0x1f; 216 unsigned int hph_r = as3514.regs[HPH_OUT_R] & ~0x1f;
158 int hph_l = as3514_regs[HPH_OUT_L] & ~0x1f; 217 unsigned int hph_l = as3514.regs[HPH_OUT_L] & ~0x1f;
159 218 unsigned int mix_l, mix_r;
160 /* we are controling dac volume instead of headphone volume, 219 unsigned int mix_reg_r, mix_reg_l;
161 as the volume is bigger. 220
162 HDP: 1.07 dB gain 221 /* keep track of current setting */
163 DAC: 6 dB gain 222 as3514.vol_l = vol_l;
164 */ 223 as3514.vol_r = vol_r;
165 if(vol_r <= 0x16) 224
166 { 225 if (source == SOURCE_LINE_IN1_ANALOG) {
167 as3514_write(DAC_R, vol_r); 226 mix_reg_r = LINE_IN1_R;
168 as3514_write(HPH_OUT_R, hph_r); /* set 0 */ 227 mix_reg_l = LINE_IN1_L;
169 } 228 } else {
170 else 229 mix_reg_r = DAC_R;
171 { 230 mix_reg_l = DAC_L;
172 as3514_write(DAC_R, 0x16);
173 as3514_write(HPH_OUT_R, hph_r + (vol_r - 0x16));
174 } 231 }
175 232
176 if(vol_l <= 0x16) 233 mix_r = as3514.regs[mix_reg_r] & ~0x1f;
177 { 234 mix_l = as3514.regs[mix_reg_l] & ~0x1f;
178 as3514_write(DAC_L, 0x40 + vol_l); 235
179 as3514_write(HPH_OUT_L, hph_l); /* set 0 */ 236 /* we combine the mixer channel volume range with the headphone volume
237 range */
238 if (vol_r <= 0x16) {
239 mix_r |= vol_r;
240 /* hph_r - set 0 */
241 } else {
242 mix_r |= 0x16;
243 hph_r += vol_r - 0x16;
180 } 244 }
181 else 245
182 { 246 if (vol_l <= 0x16) {
183 as3514_write(DAC_L, 0x40 + 0x16); 247 mix_l |= vol_l;
184 as3514_write(HPH_OUT_L, hph_l + (vol_l - 0x16)); 248 /* hph_l - set 0 */
249 } else {
250 mix_l |= 0x16;
251 hph_l += vol_l - 0x16;
185 } 252 }
186 253
254 as3514_write(mix_reg_r, mix_r);
255 as3514_write(mix_reg_l, mix_l);
256 as3514_write(HPH_OUT_R, hph_r);
257 as3514_write(HPH_OUT_L, hph_l);
258
187 return 0; 259 return 0;
188} 260}
189 261
190int audiohw_set_lineout_vol(int vol_l, int vol_r) 262int audiohw_set_lineout_vol(int vol_l, int vol_r)
191{ 263{
192 as3514_write(LINE_OUT_R, vol_r); 264 as3514_write(LINE_OUT_R, vol_r);
193 as3514_write(LINE_OUT_L, 0x40 | vol_l); 265 as3514_write(LINE_OUT_L, (1 << 6) | vol_l);
194 266
195 return 0; 267 return 0;
196} 268}
197 269
198int audiohw_mute(int mute) 270int audiohw_mute(int mute)
199{ 271{
200 int curr; 272 if (mute) {
201 curr = as3514_regs[HPH_OUT_L]; 273 as3514_write_or(HPH_OUT_L, (1 << 7));
202
203 if (mute)
204 {
205 as3514_write(HPH_OUT_L, curr | 0x80);
206 } else { 274 } else {
207 as3514_write(HPH_OUT_L, curr & ~(0x80)); 275 as3514_write_and(HPH_OUT_L, ~(1 << 7));
208 } 276 }
209 277
210 return 0; 278 return 0;
@@ -214,7 +282,7 @@ int audiohw_mute(int mute)
214void audiohw_close(void) 282void audiohw_close(void)
215{ 283{
216 /* mute headphones */ 284 /* mute headphones */
217 audiohw_mute(1); 285 audiohw_mute(true);
218 286
219 /* turn off everything */ 287 /* turn off everything */
220 as3514_write(AUDIOSET1, 0x0); 288 as3514_write(AUDIOSET1, 0x0);
@@ -227,21 +295,124 @@ void audiohw_set_sample_rate(int sampling_control)
227 295
228void audiohw_enable_recording(bool source_mic) 296void audiohw_enable_recording(bool source_mic)
229{ 297{
230 (void)source_mic; 298 if (source_mic) {
299 source = SOURCE_MIC1;
300
301 /* Sync mixer volumes before switching inputs */
302 audiohw_set_master_vol(as3514.vol_l, as3514.vol_r);
303
304 /* ADCmux = Stereo Microphone */
305 as3514_write_and(ADC_R, ~(0x3 << 6));
306 /* MIC1_on, LIN1_off */
307 as3514_write(AUDIOSET1,
308 (as3514.regs[AUDIOSET1] & ~(1 << 2)) | (1 << 0));
309 /* M1_AGC_off */
310 as3514_write_and(MIC1_R, ~(1 << 7));
311 } else {
312 source = SOURCE_LINE_IN1;
313
314 audiohw_set_master_vol(as3514.vol_l, as3514.vol_r);
315
316 /* ADCmux = Line_IN1 */
317 as3514_write(ADC_R,
318 (as3514.regs[ADC_R] & ~(0x3 << 6)) | (0x1 << 6));
319 /* MIC1_off, LIN1_on */
320 as3514_write(AUDIOSET1,
321 (as3514.regs[AUDIOSET1] & ~(1 << 0)) | (1 << 2));
322 }
323
324 /* ADC_Mute_off */
325 as3514_write_or(ADC_L, (1 << 6));
326 /* ADC_on */
327 as3514_write_or(AUDIOSET1, (1 << 7));
231} 328}
232 329
233void audiohw_disable_recording(void) 330void audiohw_disable_recording(void)
234{ 331{
332 source = SOURCE_DAC;
333
334 /* ADC_Mute_on */
335 as3514_write_and(ADC_L, ~(1 << 6));
336
337 /* ADC_off, LIN1_off, MIC_off */
338 as3514_write_and(AUDIOSET1, ~((1 << 7) | (1 << 2) | (1 << 0)));
339
340 audiohw_set_master_vol(as3514.vol_l, as3514.vol_r);
235} 341}
236 342
343/**
344 * Set recording volume
345 *
346 * Line in : 0 .. 23 .. 31 =>
347 Volume -34.5 .. +00.0 .. +12.0 dB
348 * Mic (left): 0 .. 23 .. 39 =>
349 * Volume -34.5 .. +00.0 .. +24.0 dB
350 *
351 */
237void audiohw_set_recvol(int left, int right, int type) 352void audiohw_set_recvol(int left, int right, int type)
238{ 353{
239 (void)left; 354 switch (type)
240 (void)right; 355 {
241 (void)type; 356 case AUDIO_GAIN_MIC:
357 {
358 /* Combine MIC gains seamlessly with ADC levels */
359 unsigned int mic1_r = as3514.regs[MIC1_R] & ~(0x3 << 5);
360
361 if (left >= 36) {
362 /* M1_Gain = +40db, ADR_Vol = +7.5dB .. +12.0 dB =>
363 +19.5 dB .. +24.0 dB */
364 left -= 8;
365 mic1_r |= (0x2 << 5);
366 } else if (left >= 32) {
367 /* M1_Gain = +34db, ADR_Vol = +7.5dB .. +12.0 dB =>
368 +13.5 dB .. +18.0 dB */
369 left -= 4;
370 mic1_r |= (0x1 << 5);
371 }
372 /* M1_Gain = +28db, ADR_Vol = -34.5dB .. +12.0 dB =>
373 -34.5 dB .. +12.0 dB */
374
375 right = left;
376
377 as3514_write(MIC1_R, mic1_r);
378 break;
379 }
380 case AUDIO_GAIN_LINEIN:
381 break;
382 default:
383 return;
384 }
385
386 as3514_write(ADC_R, (as3514.regs[ADC_R] & ~0x1f) | right);
387 as3514_write(ADC_L, (as3514.regs[ADC_L] & ~0x1f) | left);
242} 388}
243 389
390/**
391 * Enable line in 1 analog monitoring
392 *
393 */
244void audiohw_set_monitor(int enable) 394void audiohw_set_monitor(int enable)
245{ 395{
246 (void)enable; 396 /* LI1R_Mute_on - default */
397 unsigned int line_in1_r = as3514.regs[LINE_IN1_R] & ~(1 << 5);
398 /* LI1L_Mute_on - default */
399 unsigned int line_in1_l = as3514.regs[LINE_IN1_L] & ~(1 << 5);
400 /* LIN1_off - default */
401 unsigned int audioset1 = as3514.regs[AUDIOSET1] & ~(1 << 2);
402
403 if (enable) {
404 source = SOURCE_LINE_IN1_ANALOG;
405 audiohw_set_master_vol(as3514.vol_l, as3514.vol_r);
406
407 /* LI1R_Mute_off */
408 line_in1_r |= (1 << 5);
409 /* LI1L_Mute_off */
410 line_in1_l |= (1 << 5);
411 /* LIN1_on */
412 audioset1 |= (1 << 2);
413 }
414
415 as3514_write(AUDIOSET1, audioset1);
416 as3514_write(LINE_IN1_R, line_in1_r);
417 as3514_write(LINE_IN1_L, line_in1_l);
247} 418}
diff --git a/firmware/export/audio.h b/firmware/export/audio.h
index a0da846215..a79a734e29 100644
--- a/firmware/export/audio.h
+++ b/firmware/export/audio.h
@@ -139,6 +139,9 @@ enum audio_sources
139 AUDIO_SRC_DEFAULT = AUDIO_SRC_PLAYBACK 139 AUDIO_SRC_DEFAULT = AUDIO_SRC_PLAYBACK
140}; 140};
141 141
142extern int audio_channels;
143extern int audio_output_source;
144
142#ifdef HAVE_RECORDING 145#ifdef HAVE_RECORDING
143/* Recordable source implies it has the input as well */ 146/* Recordable source implies it has the input as well */
144 147
diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h
index 3838b007d0..65a2466dfc 100644
--- a/firmware/export/audiohw.h
+++ b/firmware/export/audiohw.h
@@ -58,7 +58,8 @@ enum {
58 SOUND_SUPERBASS, 58 SOUND_SUPERBASS,
59#endif 59#endif
60#if CONFIG_CODEC == MAS3587F || defined(HAVE_UDA1380) || defined(HAVE_TLV320)\ 60#if CONFIG_CODEC == MAS3587F || defined(HAVE_UDA1380) || defined(HAVE_TLV320)\
61 || defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731) 61 || defined(HAVE_WM8975) || defined(HAVE_WM8758) || defined(HAVE_WM8731) \
62 || defined(HAVE_AS3514)
62 SOUND_LEFT_GAIN, 63 SOUND_LEFT_GAIN,
63 SOUND_RIGHT_GAIN, 64 SOUND_RIGHT_GAIN,
64 SOUND_MIC_GAIN, 65 SOUND_MIC_GAIN,
diff --git a/firmware/export/config-e200.h b/firmware/export/config-e200.h
index 9d4fb1ccef..001c89b7d7 100644
--- a/firmware/export/config-e200.h
+++ b/firmware/export/config-e200.h
@@ -7,11 +7,22 @@
7#define MODEL_NUMBER 16 7#define MODEL_NUMBER 16
8#define MODEL_NAME "Sandisk Sansa e200" 8#define MODEL_NAME "Sandisk Sansa e200"
9 9
10#define HW_SAMPR_CAPS (SAMPR_CAP_44)
11
10/* define this if you have recording possibility */ 12/* define this if you have recording possibility */
11/*#define HAVE_RECORDING*/ /* TODO: add support for this */ 13#define HAVE_RECORDING
14
15#define DEFAULT_REC_MIC_GAIN 23
16#define DEFAULT_REC_LEFT_GAIN 23
17#define DEFAULT_REC_RIGHT_GAIN 23
18
19#define REC_SAMPR_CAPS (SAMPR_CAP_22)
20#define REC_FREQ_DEFAULT REC_FREQ_22 /* Default is not 44.1kHz */
21#define REC_SAMPR_DEFAULT SAMPR_22
22
12/* Define bitmask of input sources - recordable bitmask can be defined 23/* Define bitmask of input sources - recordable bitmask can be defined
13 explicitly if different */ 24 explicitly if different */
14/* #define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_FMRADIO) */ 25#define INPUT_SRC_CAPS (SRC_CAP_MIC)
15 26
16/* define this if you have a bitmap LCD display */ 27/* define this if you have a bitmap LCD display */
17#define HAVE_LCD_BITMAP 28#define HAVE_LCD_BITMAP
diff --git a/firmware/export/pcm_sampr.h b/firmware/export/pcm_sampr.h
index 27a300d645..b27050ec60 100644
--- a/firmware/export/pcm_sampr.h
+++ b/firmware/export/pcm_sampr.h
@@ -292,18 +292,13 @@ enum rec_freq_indexes
292#define REC_HAVE_8_(...) 292#define REC_HAVE_8_(...)
293#endif 293#endif
294 REC_NUM_FREQ, 294 REC_NUM_FREQ,
295 /* This should always come out I reckon */
296 REC_FREQ_DEFAULT = REC_FREQ_44,
297 /* Get the minimum bitcount needed to save the range of values */
298 REC_FREQ_CFG_NUM_BITS = (REC_NUM_FREQ > 8 ?
299 4 : (REC_NUM_FREQ > 4 ?
300 3 : (REC_NUM_FREQ > 2 ?
301 2 : 1
302 )
303 )
304 ),
305}; /* enum rec_freq_indexes */ 295}; /* enum rec_freq_indexes */
306 296
297/* Default to 44.1kHz if not otherwise specified */
298#ifndef REC_FREQ_DEFAULT
299#define REC_FREQ_DEFAULT REC_FREQ_44
300#endif
301
307#define REC_FREQ_CFG_VAL_LIST &REC_HAVE_96_(",96") REC_HAVE_88_(",88") \ 302#define REC_FREQ_CFG_VAL_LIST &REC_HAVE_96_(",96") REC_HAVE_88_(",88") \
308 REC_HAVE_64_(",64") REC_HAVE_48_(",48") \ 303 REC_HAVE_64_(",64") REC_HAVE_48_(",48") \
309 REC_HAVE_44_(",44") REC_HAVE_32_(",32") \ 304 REC_HAVE_44_(",44") REC_HAVE_32_(",32") \
diff --git a/firmware/sound.c b/firmware/sound.c
index 9e4481c3c6..0ccf1df260 100644
--- a/firmware/sound.c
+++ b/firmware/sound.c
@@ -743,6 +743,7 @@ void sound_set(int setting, int value)
743 sound_set_val(value); 743 sound_set_val(value);
744} 744}
745 745
746#ifndef HAVE_AS3514
746int sound_val2phys(int setting, int value) 747int sound_val2phys(int setting, int value)
747{ 748{
748#if CONFIG_CODEC == MAS3587F 749#if CONFIG_CODEC == MAS3587F
@@ -804,6 +805,7 @@ int sound_val2phys(int setting, int value)
804 return value; 805 return value;
805#endif 806#endif
806} 807}
808#endif /* HAVE_AS3514 */
807 809
808#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) 810#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
809#ifndef SIMULATOR 811#ifndef SIMULATOR
diff --git a/firmware/target/arm/pcm-pp.c b/firmware/target/arm/pcm-pp.c
index 41bd92bd0d..9027ff13b3 100644
--- a/firmware/target/arm/pcm-pp.c
+++ b/firmware/target/arm/pcm-pp.c
@@ -160,7 +160,7 @@ void fiq(void)
160{ 160{
161 /* Clear interrupt */ 161 /* Clear interrupt */
162#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 162#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
163 IISCONFIG &= ~0x2; 163 IISCONFIG &= ~(1 << 1);
164#elif CONFIG_CPU == PP5002 164#elif CONFIG_CPU == PP5002
165 inl(0xcf001040); 165 inl(0xcf001040);
166 IISFIFO_CFG &= ~(1<<9); 166 IISFIFO_CFG &= ~(1<<9);
@@ -171,7 +171,7 @@ void fiq(void)
171 if (FIFO_FREE_COUNT < 2) { 171 if (FIFO_FREE_COUNT < 2) {
172 /* Enable interrupt */ 172 /* Enable interrupt */
173#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 173#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
174 IISCONFIG |= 0x2; 174 IISCONFIG |= (1 << 1);
175#elif CONFIG_CPU == PP5002 175#elif CONFIG_CPU == PP5002
176 IISFIFO_CFG |= (1<<9); 176 IISFIFO_CFG |= (1<<9);
177#endif 177#endif
@@ -221,7 +221,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
221 221
222 /* Enable playback FIFO */ 222 /* Enable playback FIFO */
223#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 223#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
224 IISCONFIG |= 0x20000000; 224 IISCONFIG |= (1 << 29);
225#elif CONFIG_CPU == PP5002 225#elif CONFIG_CPU == PP5002
226 IISCONFIG |= 0x4; 226 IISCONFIG |= 0x4;
227#endif 227#endif
@@ -232,7 +232,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
232 if (FIFO_FREE_COUNT < 2) { 232 if (FIFO_FREE_COUNT < 2) {
233 /* Enable interrupt */ 233 /* Enable interrupt */
234#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 234#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
235 IISCONFIG |= 0x2; 235 IISCONFIG |= (1 << 1);
236#elif CONFIG_CPU == PP5002 236#elif CONFIG_CPU == PP5002
237 IISFIFO_CFG |= (1<<9); 237 IISFIFO_CFG |= (1<<9);
238#endif 238#endif
@@ -257,13 +257,8 @@ void pcm_play_dma_stop(void)
257 pcm_paused = false; 257 pcm_paused = false;
258 258
259#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 259#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
260 260 /* Disable playback FIFO and interrupt */
261 /* Disable playback FIFO */ 261 IISCONFIG &= ~((1 << 29) | (1 << 1));
262 IISCONFIG &= ~0x20000000;
263
264 /* Disable the interrupt */
265 IISCONFIG &= ~0x2;
266
267#elif CONFIG_CPU == PP5002 262#elif CONFIG_CPU == PP5002
268 263
269 /* Disable playback FIFO */ 264 /* Disable playback FIFO */
@@ -279,10 +274,8 @@ void pcm_play_dma_stop(void)
279void pcm_play_pause_pause(void) 274void pcm_play_pause_pause(void)
280{ 275{
281#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 276#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
282 /* Disable the interrupt */ 277 /* Disable playback FIFO and interrupt */
283 IISCONFIG &= ~0x2; 278 IISCONFIG &= ~((1 << 29) | (1 << 1));
284 /* Disable playback FIFO */
285 IISCONFIG &= ~0x20000000;
286#elif CONFIG_CPU == PP5002 279#elif CONFIG_CPU == PP5002
287 /* Disable the interrupt */ 280 /* Disable the interrupt */
288 IISFIFO_CFG &= ~(1<<9); 281 IISFIFO_CFG &= ~(1<<9);
@@ -301,7 +294,7 @@ void pcm_play_pause_unpause(void)
301 294
302 /* Enable playback FIFO */ 295 /* Enable playback FIFO */
303#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 296#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
304 IISCONFIG |= 0x20000000; 297 IISCONFIG |= (1 << 29);
305#elif CONFIG_CPU == PP5002 298#elif CONFIG_CPU == PP5002
306 IISCONFIG |= 0x4; 299 IISCONFIG |= 0x4;
307#endif 300#endif
@@ -312,7 +305,7 @@ void pcm_play_pause_unpause(void)
312 if (FIFO_FREE_COUNT < 2) { 305 if (FIFO_FREE_COUNT < 2) {
313 /* Enable interrupt */ 306 /* Enable interrupt */
314#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 307#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
315 IISCONFIG |= 0x2; 308 IISCONFIG |= (1 << 1);
316#elif CONFIG_CPU == PP5002 309#elif CONFIG_CPU == PP5002
317 IISFIFO_CFG |= (1<<9); 310 IISFIFO_CFG |= (1<<9);
318#endif 311#endif
@@ -369,6 +362,79 @@ void pcm_postinit(void)
369 ** Recording DMA transfer 362 ** Recording DMA transfer
370 **/ 363 **/
371#ifdef HAVE_RECORDING 364#ifdef HAVE_RECORDING
365
366#ifdef HAVE_AS3514
367void fiq_record(void) ICODE_ATTR __attribute__((naked));
368void fiq_record(void)
369{
370 register pcm_more_callback_type2 more_ready;
371 register int32_t value1, value2;
372
373 asm volatile ("stmfd sp!, {r0-r7, ip, lr} \n"); /* Store context */
374
375 IISCONFIG &= ~(1 << 0);
376
377 if (audio_channels == 2) {
378 /* RX is stereo */
379 while (p_size > 0) {
380 if (FIFO_FREE_COUNT < 2) {
381 /* enable interrupt */
382 IISCONFIG |= (1 << 0);
383 goto fiq_record_exit;
384 }
385
386 /* Discard every other sample since ADC clock is 1/2 LRCK */
387 value1 = IISFIFO_RD;
388 value2 = IISFIFO_RD;
389
390 *(int32_t *)p = value1;
391 p += 2;
392 p_size -= 4;
393
394 /* TODO: Figure out how to do IIS loopback */
395 if (audio_output_source != AUDIO_SRC_PLAYBACK) {
396 IISFIFO_WR = value1;
397 IISFIFO_WR = value1;
398 }
399 }
400 }
401 else {
402 /* RX is left channel mono */
403 while (p_size > 0) {
404 if (FIFO_FREE_COUNT < 2) {
405 /* enable interrupt */
406 IISCONFIG |= (1 << 0);
407 goto fiq_record_exit;
408 }
409
410 /* Discard every other sample since ADC clock is 1/2 LRCK */
411 value1 = IISFIFO_RD;
412 value2 = IISFIFO_RD;
413 *p++ = value1;
414 *p++ = value1;
415 p_size -= 4;
416
417 if (audio_output_source != AUDIO_SRC_PLAYBACK) {
418 value1 = *((int32_t *)p - 1);
419 IISFIFO_WR = value1;
420 IISFIFO_WR = value1;
421 }
422 }
423 }
424
425 more_ready = pcm_callback_more_ready;
426
427 if (more_ready == NULL || more_ready(0) < 0) {
428 /* Finished recording */
429 pcm_rec_dma_stop();
430 }
431
432fiq_record_exit:
433 asm volatile("ldmfd sp!, {r0-r7, ip, lr} \n" /* Restore context */
434 "subs pc, lr, #4 \n"); /* Return from FIQ */
435}
436
437#else
372static short peak_l, peak_r IBSS_ATTR; 438static short peak_l, peak_r IBSS_ATTR;
373 439
374void fiq_record(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ"))); 440void fiq_record(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ")));
@@ -380,7 +446,7 @@ void fiq_record(void)
380 446
381 /* Clear interrupt */ 447 /* Clear interrupt */
382#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 448#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
383 IISCONFIG &= ~0x01; 449 IISCONFIG &= ~(1 << 0);
384#elif CONFIG_CPU == PP5002 450#elif CONFIG_CPU == PP5002
385 /* TODO */ 451 /* TODO */
386#endif 452#endif
@@ -389,12 +455,13 @@ void fiq_record(void)
389 if (FIFO_FREE_COUNT < 2) { 455 if (FIFO_FREE_COUNT < 2) {
390 /* enable interrupt */ 456 /* enable interrupt */
391#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 457#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
392 IISCONFIG |= 0x01; 458 IISCONFIG |= (1 << 0);
393#elif CONFIG_CPU == PP5002 459#elif CONFIG_CPU == PP5002
394 /* TODO */ 460 /* TODO */
395#endif 461#endif
396 return; 462 return;
397 } 463 }
464
398 value = (unsigned short)(IISFIFO_RD >> 16); 465 value = (unsigned short)(IISFIFO_RD >> 16);
399 if (value > peak_l) peak_l = value; 466 if (value > peak_l) peak_l = value;
400 else if (-value > peak_l) peak_l = -value; 467 else if (-value > peak_l) peak_l = -value;
@@ -424,16 +491,18 @@ void fiq_record(void)
424 pcm_rec_dma_stop(); 491 pcm_rec_dma_stop();
425} 492}
426 493
494#endif /* HAVE_AS3514 */
495
427/* Continue transferring data in */ 496/* Continue transferring data in */
428void pcm_record_more(void *start, size_t size) 497void pcm_record_more(void *start, size_t size)
429{ 498{
430 rec_peak_addr = (unsigned long *)start; /* Start peaking at dest */ 499 rec_peak_addr = start; /* Start peaking at dest */
431 p = start; 500 p = start; /* Start of RX buffer */
432 p_size = size; /* Bytes to transfer */ 501 p_size = size; /* Bytes to transfer */
433#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 502#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024
434 IISCONFIG |= 0x01; 503 IISCONFIG |= (1 << 0);
435#elif CONFIG_CPU == PP5002 504#elif CONFIG_CPU == PP5002
436 /* TODO */ 505 /* TODO */
437#endif 506#endif
438} 507}
439 508
@@ -441,11 +510,14 @@ void pcm_rec_dma_stop(void)
441{ 510{
442 logf("pcm_rec_dma_stop"); 511 logf("pcm_rec_dma_stop");
443 512
444 /* disable fifo */
445 IISCONFIG &= ~0x10000000;
446
447 disable_fiq(); 513 disable_fiq();
448 514
515 /* clear interrupt, disable fifo */
516 IISCONFIG &= ~((1 << 28) | (1 << 0));
517
518 /* clear rx fifo */
519 IISFIFO_CFG |= (1 << 12);
520
449 pcm_recording = false; 521 pcm_recording = false;
450} 522}
451 523
@@ -455,7 +527,10 @@ void pcm_rec_dma_start(void *addr, size_t size)
455 527
456 pcm_recording = true; 528 pcm_recording = true;
457 529
530#ifndef HAVE_AS3514
458 peak_l = peak_r = 0; 531 peak_l = peak_r = 0;
532#endif
533
459 p_size = size; 534 p_size = size;
460 p = addr; 535 p = addr;
461 536
@@ -463,11 +538,8 @@ void pcm_rec_dma_start(void *addr, size_t size)
463 CPU_INT_PRIORITY |= I2S_MASK; 538 CPU_INT_PRIORITY |= I2S_MASK;
464 CPU_INT_EN = I2S_MASK; 539 CPU_INT_EN = I2S_MASK;
465 540
466 /* interrupt on full fifo */ 541 /* interrupt on full fifo, enable record fifo */
467 IISCONFIG |= 0x1; 542 IISCONFIG |= (1 << 28) | (1 << 0);
468
469 /* enable record fifo */
470 IISCONFIG |= 0x10000000;
471 543
472 set_fiq_handler(fiq_record); 544 set_fiq_handler(fiq_record);
473 enable_fiq(); 545 enable_fiq();
@@ -476,18 +548,7 @@ void pcm_rec_dma_start(void *addr, size_t size)
476void pcm_close_recording(void) 548void pcm_close_recording(void)
477{ 549{
478 logf("pcm_close_recording"); 550 logf("pcm_close_recording");
479
480 pcm_rec_dma_stop(); 551 pcm_rec_dma_stop();
481
482#if (CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024)
483 disable_fiq();
484
485 /* disable fifo */
486 IISCONFIG &= ~0x10000000;
487
488 /* Clear interrupt */
489 IISCONFIG &= ~0x01;
490#endif
491} /* pcm_close_recording */ 552} /* pcm_close_recording */
492 553
493void pcm_init_recording(void) 554void pcm_init_recording(void)
@@ -505,7 +566,7 @@ void pcm_init_recording(void)
505 GPIOA_OUTPUT_VAL &= ~0x4; 566 GPIOA_OUTPUT_VAL &= ~0x4;
506#endif 567#endif
507 /* Setup the recording FIQ handler */ 568 /* Setup the recording FIQ handler */
508 *((unsigned int*)(15*4)) = (unsigned int)&fiq_record; 569 set_fiq_handler(fiq_record);
509#endif 570#endif
510 571
511 pcm_rec_dma_stop(); 572 pcm_rec_dma_stop();
@@ -513,10 +574,57 @@ void pcm_init_recording(void)
513 574
514void pcm_calculate_rec_peaks(int *left, int *right) 575void pcm_calculate_rec_peaks(int *left, int *right)
515{ 576{
516 *left = rec_peak_left; 577#ifdef HAVE_AS3514
517 *right = rec_peak_right; 578 if (pcm_recording)
579 {
580 unsigned long *start = rec_peak_addr;
581 unsigned long *end = (unsigned long *)p;
582
583 if (start < end)
584 {
585 unsigned long *addr = start;
586 long peak_l = 0, peak_r = 0;
587 long peaksq_l = 0, peaksq_r = 0;
588
589 do
590 {
591 long value = *addr;
592 long ch, chsq;
593
594 ch = (int16_t)value;
595 chsq = ch*ch;
596 if (chsq > peaksq_l)
597 peak_l = ch, peaksq_l = chsq;
598
599 ch = value >> 16;
600 chsq = ch*ch;
601 if (chsq > peaksq_r)
602 peak_r = ch, peaksq_r = chsq;
603
604 addr += 4;
605 }
606 while (addr < end);
607
608 if (start == rec_peak_addr)
609 rec_peak_addr = end;
610
611 rec_peak_left = abs(peak_l);
612 rec_peak_right = abs(peak_r);
613 }
614 }
615 else
616 {
617 rec_peak_left = rec_peak_right = 0;
618 }
619#endif /* HAVE_AS3514 */
620
621 if (left)
622 *left = rec_peak_left;
623
624 if (right)
625 *right = rec_peak_right;
518} 626}
519#endif 627#endif /* HAVE_RECORDING */
520 628
521/* 629/*
522 * This function goes directly into the DMA buffer to calculate the left and 630 * This function goes directly into the DMA buffer to calculate the left and
diff --git a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
index 29fe0d9109..10c13cdb2e 100644
--- a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
+++ b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
@@ -223,6 +223,7 @@ void sd_wait_for_state(tSDCardInfo* card, unsigned int state)
223 while(((response >> 9) & 0xf) != state) 223 while(((response >> 9) & 0xf) != state)
224 { 224 {
225 sd_send_command(SEND_STATUS, (card->rca) << 16, 1); 225 sd_send_command(SEND_STATUS, (card->rca) << 16, 1);
226 priority_yield();
226 sd_read_response(&response, 1); 227 sd_read_response(&response, 1);
227 /* TODO: Add a timeout and error handling */ 228 /* TODO: Add a timeout and error handling */
228 } 229 }
@@ -442,7 +443,7 @@ void sd_init_device(void)
442 dataptr += (FIFO_SIZE*2); /* Advance one chunk of 16 words */ 443 dataptr += (FIFO_SIZE*2); /* Advance one chunk of 16 words */
443 } 444 }
444 } 445 }
445 mutex_init(&sd_mtx); 446 spinlock_init(&sd_mtx);
446} 447}
447 448
448/* API Functions */ 449/* API Functions */
@@ -472,7 +473,7 @@ int ata_read_sectors(IF_MV2(int drive,)
472#ifdef HAVE_MULTIVOLUME 473#ifdef HAVE_MULTIVOLUME
473 (void)drive; /* unused for now */ 474 (void)drive; /* unused for now */
474#endif 475#endif
475 mutex_lock(&sd_mtx); 476 spinlock_lock(&sd_mtx);
476 477
477 last_disk_activity = current_tick; 478 last_disk_activity = current_tick;
478 spinup_start = current_tick; 479 spinup_start = current_tick;
@@ -530,7 +531,7 @@ int ata_read_sectors(IF_MV2(int drive,)
530 ata_led(false); 531 ata_led(false);
531 ata_enable(false); 532 ata_enable(false);
532 533
533 mutex_unlock(&sd_mtx); 534 spinlock_unlock(&sd_mtx);
534 535
535 return ret; 536 return ret;
536} 537}
@@ -551,7 +552,7 @@ int ata_write_sectors(IF_MV2(int drive,)
551 long timeout; 552 long timeout;
552 tSDCardInfo *card = &card_info[current_card]; 553 tSDCardInfo *card = &card_info[current_card];
553 554
554 mutex_lock(&sd_mtx); 555 spinlock_lock(&sd_mtx);
555 ata_enable(true); 556 ata_enable(true);
556 ata_led(true); 557 ata_led(true);
557 if(current_card == 0) 558 if(current_card == 0)
@@ -607,7 +608,7 @@ retry:
607 sd_wait_for_state(card, TRAN); 608 sd_wait_for_state(card, TRAN);
608 ata_led(false); 609 ata_led(false);
609 ata_enable(false); 610 ata_enable(false);
610 mutex_unlock(&sd_mtx); 611 spinlock_unlock(&sd_mtx);
611 612
612 return ret; 613 return ret;
613} 614}
diff --git a/firmware/target/arm/sandisk/sansa-e200/audio-e200.c b/firmware/target/arm/sandisk/sansa-e200/audio-e200.c
new file mode 100644
index 0000000000..a3f3284b98
--- /dev/null
+++ b/firmware/target/arm/sandisk/sansa-e200/audio-e200.c
@@ -0,0 +1,103 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Michael Sevakis
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "system.h"
20#include "cpu.h"
21#include "audio.h"
22#include "sound.h"
23
24int audio_channels = 2;
25int audio_output_source = AUDIO_SRC_PLAYBACK;
26
27void audio_set_output_source(int source)
28{
29 int oldmode = set_fiq_status(FIQ_DISABLED);
30
31 if ((unsigned)source >= AUDIO_NUM_SOURCES)
32 source = AUDIO_SRC_PLAYBACK;
33
34 audio_output_source = source;
35
36 if (source != AUDIO_SRC_PLAYBACK)
37 IISCONFIG |= (1 << 29);
38
39 set_fiq_status(oldmode);
40} /* audio_set_output_source */
41
42void audio_set_source(int source, unsigned flags)
43{
44 static int last_source = AUDIO_SRC_PLAYBACK;
45#if 0
46 static bool last_recording = false;
47 bool recording = flags & SRCF_RECORDING;
48#endif
49 (void)flags;
50
51 switch (source)
52 {
53 default: /* playback - no recording */
54 source = AUDIO_SRC_PLAYBACK;
55 case AUDIO_SRC_PLAYBACK:
56 audio_channels = 2;
57 if (source != last_source)
58 {
59 audiohw_set_monitor(false);
60 audiohw_disable_recording();
61 }
62 break;
63
64 case AUDIO_SRC_MIC: /* recording only */
65 audio_channels = 1;
66 if (source != last_source)
67 {
68 audiohw_set_monitor(false);
69 audiohw_enable_recording(true); /* source mic */
70 }
71 break;
72
73#if 0
74 case AUDIO_SRC_FMRADIO: /* recording and playback */
75 audio_channels = 2;
76
77 if (!recording)
78 audiohw_set_recvol(23, 23, AUDIO_GAIN_LINEIN);
79
80 if (source == last_source && recording == last_recording)
81 break;
82
83 last_recording = recording;
84
85 if (recording)
86 {
87 audiohw_set_monitor(false);
88 audiohw_enable_recording(false);
89 }
90 else
91 {
92 audiohw_disable_recording();
93 audiohw_set_monitor(true); /* line 1 analog audio path */
94 }
95
96 break;
97#endif
98 } /* end switch */
99
100 last_source = source;
101} /* audio_set_source */
102
103