summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2010-06-26 10:07:17 +0000
committerMichael Sevakis <jethead71@rockbox.org>2010-06-26 10:07:17 +0000
commitb15a523870d6aa45b38b92547053beb986b92d9a (patch)
tree8b75fe5f13a3418186cb11c01062ad415490036b /firmware
parentac622c6d673c708d48527db8a189401422a5d03c (diff)
downloadrockbox-b15a523870d6aa45b38b92547053beb986b92d9a.tar.gz
rockbox-b15a523870d6aa45b38b92547053beb986b92d9a.zip
e200v1/c200v1: Implement limited samplerate switching. Rates 24kHz and below are being a bear as far as minor crackling at higher amplitude-- leave them out for the time being since no solution is currently evident. 48, 44, 32 (rec rates 24, 22, 16) seem perfectly fine. I'm betting c200 is ok to include because it uses the same setup as e200.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27139 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/audio/as3514.c9
-rw-r--r--firmware/drivers/audio/sdl.c4
-rw-r--r--firmware/export/as3514.h1
-rw-r--r--firmware/export/config/sansac200.h4
-rw-r--r--firmware/export/config/sansae200.h9
-rw-r--r--firmware/export/pcm.h13
-rw-r--r--firmware/export/pcm_sampr.h20
-rw-r--r--firmware/pcm.c20
-rw-r--r--firmware/target/arm/i2s-pp.c6
-rw-r--r--firmware/target/arm/sandisk/audio-c200_e200.c83
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
328void audiohw_set_frequency(int fsel) 328void 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)
162void audiohw_set_depth_3d(int value) 162void audiohw_set_depth_3d(int value)
163 { (void)value; } 163 { (void)value; }
164#endif 164#endif
165#if defined(HAVE_SAMPR_TYPE_REC)
166unsigned 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)
166int mas_codec_readreg(int reg) 170int 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
29extern void audiohw_set_master_vol(int vol_l, int vol_r); 29extern void audiohw_set_master_vol(int vol_l, int vol_r);
30extern void audiohw_set_lineout_vol(int vol_l, int vol_r); 30extern void audiohw_set_lineout_vol(int vol_l, int vol_r);
31extern 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);
55typedef void (*pcm_rec_callback_type)(int status, void **start, size_t *size); 55typedef 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
63unsigned int pcm_sampr_type_rec_to_play(unsigned int samplerate);
64#endif
65#endif /* CONFIG_SAMPR_TYPES */
66
60void pcm_set_frequency(unsigned int samplerate); 67void pcm_set_frequency(unsigned int samplerate);
61/* apply settings to hardware immediately */ 68/* apply settings to hardware immediately */
62void pcm_apply_settings(void); 69void 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
312extern const unsigned long rec_freq_sampr[REC_NUM_FREQ]; 312extern 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
323unsigned 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
33void i2s_reset(void) 37void 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
26int audio_channels = 2; 27int audio_channels = 2;
27int audio_output_source = AUDIO_SRC_PLAYBACK; 28int 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
98void 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
167unsigned 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}