diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/drivers/audio/as3514.c | 9 | ||||
-rw-r--r-- | firmware/drivers/audio/sdl.c | 4 | ||||
-rw-r--r-- | firmware/export/as3514.h | 1 | ||||
-rw-r--r-- | firmware/export/config/sansac200.h | 4 | ||||
-rw-r--r-- | firmware/export/config/sansae200.h | 9 | ||||
-rw-r--r-- | firmware/export/pcm.h | 13 | ||||
-rw-r--r-- | firmware/export/pcm_sampr.h | 20 | ||||
-rw-r--r-- | firmware/pcm.c | 20 | ||||
-rw-r--r-- | firmware/target/arm/i2s-pp.c | 6 | ||||
-rw-r--r-- | firmware/target/arm/sandisk/audio-c200_e200.c | 83 |
10 files changed, 160 insertions, 9 deletions
diff --git a/firmware/drivers/audio/as3514.c b/firmware/drivers/audio/as3514.c index 34dc9ad29f..957aba8dbb 100644 --- a/firmware/drivers/audio/as3514.c +++ b/firmware/drivers/audio/as3514.c | |||
@@ -327,6 +327,15 @@ void audiohw_close(void) | |||
327 | 327 | ||
328 | void audiohw_set_frequency(int fsel) | 328 | void audiohw_set_frequency(int fsel) |
329 | { | 329 | { |
330 | #if defined(SANSA_E200) || defined(SANSA_C200) | ||
331 | if ((unsigned)fsel >= HW_NUM_FREQ) | ||
332 | fsel = HW_FREQ_DEFAULT; | ||
333 | |||
334 | as3514_write(AS3514_PLLMODE, hw_freq_sampr[fsel] < 24000 ? | ||
335 | PLLMODE_LRCK_8_23 : PLLMODE_LRCK_24_48); | ||
336 | |||
337 | audiohw_set_sampr_dividers(fsel); | ||
338 | #endif | ||
330 | (void)fsel; | 339 | (void)fsel; |
331 | } | 340 | } |
332 | 341 | ||
diff --git a/firmware/drivers/audio/sdl.c b/firmware/drivers/audio/sdl.c index c063192873..f4c622d7a6 100644 --- a/firmware/drivers/audio/sdl.c +++ b/firmware/drivers/audio/sdl.c | |||
@@ -162,6 +162,10 @@ void audiohw_set_eq_band_width(unsigned int band, int value) | |||
162 | void audiohw_set_depth_3d(int value) | 162 | void audiohw_set_depth_3d(int value) |
163 | { (void)value; } | 163 | { (void)value; } |
164 | #endif | 164 | #endif |
165 | #if defined(HAVE_SAMPR_TYPE_REC) | ||
166 | unsigned int pcm_sampr_type_rec_to_play(int samplerate) | ||
167 | { return samplerate; } | ||
168 | #endif | ||
165 | #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) | 169 | #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) |
166 | int mas_codec_readreg(int reg) | 170 | int mas_codec_readreg(int reg) |
167 | { | 171 | { |
diff --git a/firmware/export/as3514.h b/firmware/export/as3514.h index ffcf9186e7..de975ce3c6 100644 --- a/firmware/export/as3514.h +++ b/firmware/export/as3514.h | |||
@@ -28,6 +28,7 @@ extern int tenthdb2master(int db); | |||
28 | 28 | ||
29 | extern void audiohw_set_master_vol(int vol_l, int vol_r); | 29 | extern void audiohw_set_master_vol(int vol_l, int vol_r); |
30 | extern void audiohw_set_lineout_vol(int vol_l, int vol_r); | 30 | extern void audiohw_set_lineout_vol(int vol_l, int vol_r); |
31 | extern void audiohw_set_sampr_dividers(int fsel); | ||
31 | 32 | ||
32 | /* Register Descriptions */ | 33 | /* Register Descriptions */ |
33 | 34 | ||
diff --git a/firmware/export/config/sansac200.h b/firmware/export/config/sansac200.h index 5905b6a3f9..6c05ba5a1c 100644 --- a/firmware/export/config/sansac200.h +++ b/firmware/export/config/sansac200.h | |||
@@ -7,12 +7,12 @@ | |||
7 | #define MODEL_NUMBER 20 | 7 | #define MODEL_NUMBER 20 |
8 | #define MODEL_NAME "Sandisk Sansa c200 series" | 8 | #define MODEL_NAME "Sandisk Sansa c200 series" |
9 | 9 | ||
10 | #define HW_SAMPR_CAPS (SAMPR_CAP_44) | 10 | #define HW_SAMPR_CAPS (SAMPR_CAP_48 | SAMPR_CAP_44 | SAMPR_CAP_32) |
11 | 11 | ||
12 | /* define this if you have recording possibility */ | 12 | /* define this if you have recording possibility */ |
13 | #define HAVE_RECORDING | 13 | #define HAVE_RECORDING |
14 | 14 | ||
15 | #define REC_SAMPR_CAPS (SAMPR_CAP_22) | 15 | #define REC_SAMPR_CAPS (SAMPR_CAP_24 | SAMPR_CAP_22 | SAMPR_CAP_16) |
16 | #define REC_FREQ_DEFAULT REC_FREQ_22 /* Default is not 44.1kHz */ | 16 | #define REC_FREQ_DEFAULT REC_FREQ_22 /* Default is not 44.1kHz */ |
17 | #define REC_SAMPR_DEFAULT SAMPR_22 | 17 | #define REC_SAMPR_DEFAULT SAMPR_22 |
18 | 18 | ||
diff --git a/firmware/export/config/sansae200.h b/firmware/export/config/sansae200.h index 8f4f3235dc..501e9eac37 100644 --- a/firmware/export/config/sansae200.h +++ b/firmware/export/config/sansae200.h | |||
@@ -7,15 +7,20 @@ | |||
7 | #define MODEL_NUMBER 16 | 7 | #define MODEL_NUMBER 16 |
8 | #define MODEL_NAME "Sandisk Sansa e200 series" | 8 | #define MODEL_NAME "Sandisk Sansa e200 series" |
9 | 9 | ||
10 | #define HW_SAMPR_CAPS (SAMPR_CAP_44) | 10 | #define HW_SAMPR_CAPS (SAMPR_CAP_48 | SAMPR_CAP_44 | SAMPR_CAP_32) |
11 | 11 | ||
12 | /* define this if you have recording possibility */ | 12 | /* define this if you have recording possibility */ |
13 | #define HAVE_RECORDING | 13 | #define HAVE_RECORDING |
14 | 14 | ||
15 | #define REC_SAMPR_CAPS (SAMPR_CAP_22) | 15 | #define REC_SAMPR_CAPS (SAMPR_CAP_24 | SAMPR_CAP_22 | SAMPR_CAP_16) |
16 | #define REC_FREQ_DEFAULT REC_FREQ_22 /* Default is not 44.1kHz */ | 16 | #define REC_FREQ_DEFAULT REC_FREQ_22 /* Default is not 44.1kHz */ |
17 | #define REC_SAMPR_DEFAULT SAMPR_22 | 17 | #define REC_SAMPR_DEFAULT SAMPR_22 |
18 | 18 | ||
19 | /* because the samplerates don't match at each point, we must be able to | ||
20 | * tell PCM which set of rates to use. not needed if recording rates are | ||
21 | * a simple subset of playback rates and are equal values. */ | ||
22 | #define CONFIG_SAMPR_TYPES | ||
23 | |||
19 | /* Define bitmask of input sources - recordable bitmask can be defined | 24 | /* Define bitmask of input sources - recordable bitmask can be defined |
20 | explicitly if different */ | 25 | explicitly if different */ |
21 | #define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_FMRADIO) | 26 | #define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_FMRADIO) |
diff --git a/firmware/export/pcm.h b/firmware/export/pcm.h index 02fa04cb7e..e388e29f0c 100644 --- a/firmware/export/pcm.h +++ b/firmware/export/pcm.h | |||
@@ -54,9 +54,16 @@ typedef void (*pcm_play_callback_type)(unsigned char **start, | |||
54 | size_t *size); | 54 | size_t *size); |
55 | typedef void (*pcm_rec_callback_type)(int status, void **start, size_t *size); | 55 | typedef void (*pcm_rec_callback_type)(int status, void **start, size_t *size); |
56 | 56 | ||
57 | /* set the pcm frequency - use values in hw_sampr_list | 57 | /* set the pcm frequency - use values in hw_sampr_list |
58 | * use -1 for the default frequency | 58 | * when CONFIG_SAMPR_TYPES is #defined, or-in SAMPR_TYPE_* fields with |
59 | */ | 59 | * frequency value. SAMPR_TYPE_PLAY is 0 and the default if none is |
60 | * specified. */ | ||
61 | #ifdef CONFIG_SAMPR_TYPES | ||
62 | #ifdef SAMPR_TYPE_REC | ||
63 | unsigned int pcm_sampr_type_rec_to_play(unsigned int samplerate); | ||
64 | #endif | ||
65 | #endif /* CONFIG_SAMPR_TYPES */ | ||
66 | |||
60 | void pcm_set_frequency(unsigned int samplerate); | 67 | void pcm_set_frequency(unsigned int samplerate); |
61 | /* apply settings to hardware immediately */ | 68 | /* apply settings to hardware immediately */ |
62 | void pcm_apply_settings(void); | 69 | void pcm_apply_settings(void); |
diff --git a/firmware/export/pcm_sampr.h b/firmware/export/pcm_sampr.h index 2204b9c059..54db8a1dfb 100644 --- a/firmware/export/pcm_sampr.h +++ b/firmware/export/pcm_sampr.h | |||
@@ -312,4 +312,24 @@ enum rec_freq_indexes | |||
312 | extern const unsigned long rec_freq_sampr[REC_NUM_FREQ]; | 312 | extern const unsigned long rec_freq_sampr[REC_NUM_FREQ]; |
313 | #endif /* HAVE_RECORDING */ | 313 | #endif /* HAVE_RECORDING */ |
314 | 314 | ||
315 | #ifdef CONFIG_SAMPR_TYPES | ||
316 | |||
317 | #define SAMPR_TYPE_MASK (0xff << 24) | ||
318 | #define SAMPR_TYPE_PLAY (0x00 << 24) | ||
319 | #ifdef HAVE_RECORDING | ||
320 | #define SAMPR_TYPE_REC (0x01 << 24) | ||
321 | #endif | ||
322 | |||
323 | unsigned int sampr_type_rec_to_play(unsigned int samplerate); | ||
324 | |||
325 | #else /* ndef CONFIG_SAMPR_TYPES */ | ||
326 | |||
327 | /* Types are ignored and == 0 */ | ||
328 | #define SAMPR_TYPE_PLAY 0 | ||
329 | #ifdef HAVE_RECORDING | ||
330 | #define SAMPR_TYPE_REC 0 | ||
331 | #endif | ||
332 | |||
333 | #endif /* CONFIG_SAMPR_TYPES */ | ||
334 | |||
315 | #endif /* PCM_SAMPR_H */ | 335 | #endif /* PCM_SAMPR_H */ |
diff --git a/firmware/pcm.c b/firmware/pcm.c index 8080823077..72fe23cb16 100644 --- a/firmware/pcm.c +++ b/firmware/pcm.c | |||
@@ -361,8 +361,24 @@ void pcm_set_frequency(unsigned int samplerate) | |||
361 | { | 361 | { |
362 | logf("pcm_set_frequency"); | 362 | logf("pcm_set_frequency"); |
363 | 363 | ||
364 | int index = round_value_to_list32(samplerate, hw_freq_sampr, | 364 | int index; |
365 | HW_NUM_FREQ, false); | 365 | |
366 | #ifdef CONFIG_SAMPR_TYPES | ||
367 | unsigned int type = samplerate & SAMPR_TYPE_MASK; | ||
368 | samplerate &= ~SAMPR_TYPE_MASK; | ||
369 | |||
370 | #ifdef SAMPR_TYPE_REC | ||
371 | /* For now, supported targets have direct conversion when configured with | ||
372 | * CONFIG_SAMPR_TYPES. | ||
373 | * Some hypothetical target with independent rates would need slightly | ||
374 | * different handling throughout this source. */ | ||
375 | if (type == SAMPR_TYPE_REC) | ||
376 | samplerate = pcm_sampr_type_rec_to_play(samplerate); | ||
377 | #endif | ||
378 | #endif /* CONFIG_SAMPR_TYPES */ | ||
379 | |||
380 | index = round_value_to_list32(samplerate, hw_freq_sampr, | ||
381 | HW_NUM_FREQ, false); | ||
366 | 382 | ||
367 | if (samplerate != hw_freq_sampr[index]) | 383 | if (samplerate != hw_freq_sampr[index]) |
368 | index = HW_FREQ_DEFAULT; /* Invalid = default */ | 384 | index = HW_FREQ_DEFAULT; /* Invalid = default */ |
diff --git a/firmware/target/arm/i2s-pp.c b/firmware/target/arm/i2s-pp.c index c9d66d53ae..83f39515c4 100644 --- a/firmware/target/arm/i2s-pp.c +++ b/firmware/target/arm/i2s-pp.c | |||
@@ -28,6 +28,10 @@ | |||
28 | #include "system.h" | 28 | #include "system.h" |
29 | #include "cpu.h" | 29 | #include "cpu.h" |
30 | #include "i2s.h" | 30 | #include "i2s.h" |
31 | #if defined (SANSA_E200) || defined (SANSA_C200) | ||
32 | #include "audiohw.h" | ||
33 | #include "pcm_sampr.h" | ||
34 | #endif | ||
31 | 35 | ||
32 | #if CONFIG_CPU == PP5002 | 36 | #if CONFIG_CPU == PP5002 |
33 | void i2s_reset(void) | 37 | void i2s_reset(void) |
@@ -70,6 +74,8 @@ void i2s_reset(void) | |||
70 | IISCLK = (IISCLK & ~0x1ff) | 31; | 74 | IISCLK = (IISCLK & ~0x1ff) | 31; |
71 | IISDIV = (IISDIV & ~0xc0000000) | (2 << 30); | 75 | IISDIV = (IISDIV & ~0xc0000000) | (2 << 30); |
72 | IISDIV = (IISDIV & ~0x3f) | 16; | 76 | IISDIV = (IISDIV & ~0x3f) | 16; |
77 | #elif defined (SANSA_E200) || defined (SANSA_C200) | ||
78 | audiohw_set_sampr_dividers(HW_FREQ_DEFAULT); | ||
73 | #else | 79 | #else |
74 | IISCLK = (IISCLK & ~0x1ff) | 33; | 80 | IISCLK = (IISCLK & ~0x1ff) | 33; |
75 | IISDIV = 7; | 81 | IISDIV = 7; |
diff --git a/firmware/target/arm/sandisk/audio-c200_e200.c b/firmware/target/arm/sandisk/audio-c200_e200.c index 1d78e71541..0037bac58b 100644 --- a/firmware/target/arm/sandisk/audio-c200_e200.c +++ b/firmware/target/arm/sandisk/audio-c200_e200.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "cpu.h" | 22 | #include "cpu.h" |
23 | #include "audio.h" | 23 | #include "audio.h" |
24 | #include "sound.h" | 24 | #include "sound.h" |
25 | #include "general.h" | ||
25 | 26 | ||
26 | int audio_channels = 2; | 27 | int audio_channels = 2; |
27 | int audio_output_source = AUDIO_SRC_PLAYBACK; | 28 | int audio_output_source = AUDIO_SRC_PLAYBACK; |
@@ -92,3 +93,85 @@ void audio_input_mux(int source, unsigned flags) | |||
92 | 93 | ||
93 | last_source = source; | 94 | last_source = source; |
94 | } /* audio_input_mux */ | 95 | } /* audio_input_mux */ |
96 | |||
97 | |||
98 | void audiohw_set_sampr_dividers(int fsel) | ||
99 | { | ||
100 | /* Seems to predivide 24MHz by 2 for a source clock of 12MHz. Maybe | ||
101 | * there's a way to set that? */ | ||
102 | static const struct | ||
103 | { | ||
104 | unsigned char iisclk; | ||
105 | unsigned char iisdiv; | ||
106 | } regvals[HW_NUM_FREQ] = | ||
107 | { | ||
108 | /* 8kHz - 24kHz work well but there seems to be a minor crackling | ||
109 | * issue for playback at times and all possibilities were checked | ||
110 | * for the divisors without any positive change. | ||
111 | * 32kHz - 48kHz seem fine all around. */ | ||
112 | #if 0 | ||
113 | [HW_FREQ_8] = /* CLK / 1500 (8000Hz) */ | ||
114 | { | ||
115 | .iisclk = 24, | ||
116 | .iisdiv = 59, | ||
117 | }, | ||
118 | [HW_FREQ_11] = /* CLK / 1088 (~11029.41Hz) */ | ||
119 | { | ||
120 | .iisclk = 33, | ||
121 | .iisdiv = 31, | ||
122 | }, | ||
123 | [HW_FREQ_12] = /* CLK / 1000 (120000Hz) */ | ||
124 | { | ||
125 | .iisclk = 49, | ||
126 | .iisdiv = 19, | ||
127 | }, | ||
128 | [HW_FREQ_16] = /* CLK / 750 (16000Hz) */ | ||
129 | { | ||
130 | .iisclk = 24, | ||
131 | .iisdiv = 29, | ||
132 | }, | ||
133 | [HW_FREQ_22] = /* CLK / 544 (~22058.82Hz) */ | ||
134 | { | ||
135 | .iisclk = 33, | ||
136 | .iisdiv = 15, | ||
137 | }, | ||
138 | [HW_FREQ_24] = /* CLK / 500 (24000Hz) */ | ||
139 | { | ||
140 | .iisclk = 49, | ||
141 | .iisdiv = 9, | ||
142 | }, | ||
143 | #endif | ||
144 | [HW_FREQ_32] = /* CLK / 375 (32000Hz) */ | ||
145 | { | ||
146 | .iisclk = 24, | ||
147 | .iisdiv = 14, | ||
148 | }, | ||
149 | [HW_FREQ_44] = /* CLK / 272 (~44117.68Hz) */ | ||
150 | { | ||
151 | .iisclk = 33, | ||
152 | .iisdiv = 7, | ||
153 | }, | ||
154 | [HW_FREQ_48] = /* CLK / 250 (48000Hz) */ | ||
155 | { | ||
156 | .iisclk = 49, | ||
157 | .iisdiv = 4, | ||
158 | }, | ||
159 | /* going a bit higher would be nice to get 64kHz play, 32kHz rec, but a | ||
160 | * close enough division isn't obtainable unless CLK can be changed */ | ||
161 | }; | ||
162 | |||
163 | IISCLK = (IISCLK & ~0x17ff) | regvals[fsel].iisclk; | ||
164 | IISDIV = (IISDIV & ~0xc000003f) | regvals[fsel].iisdiv; | ||
165 | } | ||
166 | |||
167 | unsigned int pcm_sampr_type_rec_to_play(unsigned int samplerate) | ||
168 | { | ||
169 | /* Check if the samplerate is in the list of recordable rates. | ||
170 | * Fail to default if not */ | ||
171 | int index = round_value_to_list32(samplerate, rec_freq_sampr, | ||
172 | REC_NUM_FREQ, false); | ||
173 | if (samplerate != rec_freq_sampr[index]) | ||
174 | return HW_SAMPR_DEFAULT; | ||
175 | |||
176 | return samplerate * 2; /* Recording rates are 1/2 the codec clock */ | ||
177 | } | ||