summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Cousins <bobc@rockbox.org>2009-11-01 22:58:08 +0000
committerBob Cousins <bobc@rockbox.org>2009-11-01 22:58:08 +0000
commit33040275cfccdc1f1c33e0a9ef3b5a2b88aa3679 (patch)
treeb985669b775e9f482ca1d724f09d8a5cc74cd1cb
parent5d40b9a24a5ffe096691fbc117c718561d4bb30c (diff)
downloadrockbox-33040275cfccdc1f1c33e0a9ef3b5a2b88aa3679.tar.gz
rockbox-33040275cfccdc1f1c33e0a9ef3b5a2b88aa3679.zip
Improvements to mini2440/UDA1341 audio
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23478 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/audio/uda1341.c76
-rw-r--r--firmware/export/uda1341.h35
-rw-r--r--firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c15
3 files changed, 109 insertions, 17 deletions
diff --git a/firmware/drivers/audio/uda1341.c b/firmware/drivers/audio/uda1341.c
index f9d95eff02..0171169942 100644
--- a/firmware/drivers/audio/uda1341.c
+++ b/firmware/drivers/audio/uda1341.c
@@ -33,9 +33,9 @@ const struct sound_settings_info audiohw_settings[] = {
33 [SOUND_VOLUME] = {"dB", 0, 1, -84, 0, -25}, 33 [SOUND_VOLUME] = {"dB", 0, 1, -84, 0, -25},
34 [SOUND_BASS] = {"dB", 0, 2, 0, 24, 0}, 34 [SOUND_BASS] = {"dB", 0, 2, 0, 24, 0},
35 [SOUND_TREBLE] = {"dB", 0, 2, 0, 6, 0}, 35 [SOUND_TREBLE] = {"dB", 0, 2, 0, 6, 0},
36 [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, 36 [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, /* not used */
37 [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, 37 [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, /* not used */
38 [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, 38 [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, /* not used */
39#ifdef HAVE_RECORDING 39#ifdef HAVE_RECORDING
40 [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0}, 40 [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0},
41 [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0}, 41 [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0},
@@ -43,6 +43,17 @@ const struct sound_settings_info audiohw_settings[] = {
43#endif 43#endif
44}; 44};
45 45
46/* convert tenth of dB volume (-600..0) to master volume register value */
47int tenthdb2master(int db)
48{
49 if (db < -600)
50 return 63;
51 else /* 1 dB steps */
52 return -(db / 10) + 1;
53}
54
55static unsigned short uda_regs[NUM_REG_ID];
56
46/****************************************************************************/ 57/****************************************************************************/
47 58
48/* ------------------------------------------------- */ 59/* ------------------------------------------------- */
@@ -59,7 +70,7 @@ const struct sound_settings_info audiohw_settings[] = {
59static void l3_init (void) 70static void l3_init (void)
60{ 71{
61 L3PORT |= L3MODE | L3CLOCK; 72 L3PORT |= L3MODE | L3CLOCK;
62 L3PORT &= L3DATA; 73 L3PORT &= ~L3DATA;
63 74
64 S3C2440_GPIO_CONFIG (GPBCON, 2, GPIO_OUTPUT); /* L3 MODE */ 75 S3C2440_GPIO_CONFIG (GPBCON, 2, GPIO_OUTPUT); /* L3 MODE */
65 S3C2440_GPIO_CONFIG (GPBCON, 3, GPIO_OUTPUT); /* L3 DATA */ 76 S3C2440_GPIO_CONFIG (GPBCON, 3, GPIO_OUTPUT); /* L3 DATA */
@@ -72,8 +83,8 @@ static void l3_init (void)
72 83
73static void bit_delay (void) 84static void bit_delay (void)
74{ 85{
75 int j; 86 volatile int j;
76 for (j=0; j<4; j++) 87 for (j=0; j<5; j++)
77 ; 88 ;
78} 89}
79 90
@@ -86,6 +97,7 @@ static void l3_write_byte (unsigned char data, bool address_mode)
86 L3PORT &= ~L3MODE; 97 L3PORT &= ~L3MODE;
87 else 98 else
88 L3PORT |= L3MODE; 99 L3PORT |= L3MODE;
100 bit_delay();
89 101
90 for (bit=0; bit < 8; bit++) 102 for (bit=0; bit < 8; bit++)
91 { 103 {
@@ -144,41 +156,91 @@ static void udacodec_reset(void)
144 I2S_IFMT_IIS); 156 I2S_IFMT_IIS);
145 udacodec_write (UDA_REG_STATUS, UDA_STATUS_0 | UDA_SYSCLK_256FS | I2S_IFMT_IIS); 157 udacodec_write (UDA_REG_STATUS, UDA_STATUS_0 | UDA_SYSCLK_256FS | I2S_IFMT_IIS);
146 udacodec_write (UDA_REG_STATUS, UDA_STATUS_1 | UDA_POWER_DAC_ON); 158 udacodec_write (UDA_REG_STATUS, UDA_STATUS_1 | UDA_POWER_DAC_ON);
159
160 uda_regs[UDA_REG_ID_CTRL2] = UDA_PEAK_DETECT_POS_AFTER |
161 UDA_DE_EMPHASIS_NONE | UDA_MUTE_OFF | UDA_MODE_SWITCH_FLAT;
162
147} 163}
148 164
149/****************************************************************************/ 165/****************************************************************************/
150 166
151/* Audio API functions */ 167/* Audio API functions */
152 168
169/* This table must match the table in pcm-xxxx.c if using Master mode */
170/* [reserved, master clock rate] */
171static const unsigned char uda_freq_parms[HW_NUM_FREQ][2] =
172{
173 [HW_FREQ_64] = { 0, UDA_SYSCLK_256FS },
174 [HW_FREQ_44] = { 0, UDA_SYSCLK_384FS },
175 [HW_FREQ_22] = { 0, UDA_SYSCLK_256FS },
176 [HW_FREQ_11] = { 0, UDA_SYSCLK_256FS },
177};
178
153void audiohw_init(void) 179void audiohw_init(void)
154{ 180{
155 udacodec_reset(); 181 udacodec_reset();
182
183 audiohw_set_bass (0);
184 audiohw_set_treble (0);
185 audiohw_set_master_vol (26, 26); /* -25 dB */
156} 186}
157 187
188void audiohw_postinit(void)
189{
190}
191
158void audiohw_close(void) 192void audiohw_close(void)
159{ 193{
194 /* DAC, ADC off */
195 udacodec_write (UDA_REG_STATUS, UDA_STATUS_1 | 0);
160} 196}
161 197
162void audiohw_set_bass(int value) 198void audiohw_set_bass(int value)
163{ 199{
200 uda_regs [UDA_REG_ID_CTRL1] &= UDA_BASS_BOOST (UDA_BASS_BOOST_MASK);
201 uda_regs [UDA_REG_ID_CTRL1] |= UDA_BASS_BOOST (value & UDA_BASS_BOOST_MASK);
202
203 udacodec_write (UDA_REG_DATA0, UDA_DATA_CTRL1 | uda_regs [UDA_REG_ID_CTRL1] );
164} 204}
165 205
166void audiohw_set_treble(int value) 206void audiohw_set_treble(int value)
167{ 207{
208 uda_regs [UDA_REG_ID_CTRL1] &= UDA_TREBLE (UDA_TREBLE_MASK);
209 uda_regs [UDA_REG_ID_CTRL1] |= UDA_TREBLE (value & UDA_TREBLE_MASK);
210
211 udacodec_write (UDA_REG_DATA0, UDA_DATA_CTRL1 | uda_regs [UDA_REG_ID_CTRL1] );
168} 212}
169 213
170void audiohw_mute(bool mute) 214void audiohw_mute(bool mute)
171{ 215{
216 if (mute)
217 uda_regs [UDA_REG_ID_CTRL2] |= UDA_MUTE_ON;
218 else
219 uda_regs [UDA_REG_ID_CTRL2] &= ~UDA_MUTE_ON;
220
221 udacodec_write (UDA_REG_DATA0, UDA_DATA_CTRL2 | uda_regs [UDA_REG_ID_CTRL2] );
172} 222}
173 223
174void audiohw_set_prescaler(int val) 224void audiohw_set_prescaler(int val)
175{ 225{
226 (void)val;
176} 227}
177 228
178void audiohw_postinit(void) 229/**
230 * Sets left and right master volume (1(max) to 62(muted))
231 */
232void audiohw_set_master_vol(int vol_l, int vol_r)
179{ 233{
234 uda_regs[UDA_REG_ID_CTRL0] = (vol_l + vol_r) / 2;
235 udacodec_write (UDA_REG_DATA0, UDA_DATA_CTRL0 | uda_regs[UDA_REG_ID_CTRL0]);
180} 236}
181 237
182void audiohw_set_frequency(int fsel) 238void audiohw_set_frequency(int fsel)
183{ 239{
240 if ((unsigned)fsel >= HW_NUM_FREQ)
241 fsel = HW_FREQ_DEFAULT;
242
243 uda_regs[UDA_REG_ID_STATUS_0] = I2S_IFMT_IIS | uda_freq_parms[fsel][1];
244
245 udacodec_write (UDA_REG_STATUS, UDA_STATUS_0 | uda_regs[UDA_REG_ID_STATUS_0]);
184} 246}
diff --git a/firmware/export/uda1341.h b/firmware/export/uda1341.h
index dcbbeef8e5..a43d33a137 100644
--- a/firmware/export/uda1341.h
+++ b/firmware/export/uda1341.h
@@ -26,7 +26,7 @@
26#define VOLUME_MIN -840 26#define VOLUME_MIN -840
27#define VOLUME_MAX 0 27#define VOLUME_MAX 0
28 28
29#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | PRESCALER_CAP) 29#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP)
30 30
31extern int tenthdb2master(int db); 31extern int tenthdb2master(int db);
32extern int tenthdb2mixer(int db); 32extern int tenthdb2mixer(int db);
@@ -34,6 +34,23 @@ extern int tenthdb2mixer(int db);
34extern void audiohw_set_master_vol(int vol_l, int vol_r); 34extern void audiohw_set_master_vol(int vol_l, int vol_r);
35extern void audiohw_set_mixer_vol(int channel1, int channel2); 35extern void audiohw_set_mixer_vol(int channel1, int channel2);
36 36
37/* These are logical register numbers for driver */
38enum uda_register {
39 UDA_REG_ID_STATUS_0,
40 UDA_REG_ID_STATUS_1,
41 UDA_REG_ID_CTRL0,
42 UDA_REG_ID_CTRL1,
43 UDA_REG_ID_CTRL2,
44 UDA_REG_ID_EXT_0,
45 UDA_REG_ID_EXT_1,
46 UDA_REG_ID_EXT_2,
47 UDA_REG_ID_EXT_4,
48 UDA_REG_ID_EXT_5,
49 UDA_REG_ID_EXT_6,
50 NUM_REG_ID
51};
52
53
37/* Address byte */ 54/* Address byte */
38#define UDA1341_ADDR 0x14 55#define UDA1341_ADDR 0x14
39#define UDA_REG_DATA0 0x00 56#define UDA_REG_DATA0 0x00
@@ -67,23 +84,27 @@ extern void audiohw_set_mixer_vol(int channel1, int channel2);
67#define UDA_POWER_DAC_ON (1 << 0) 84#define UDA_POWER_DAC_ON (1 << 0)
68 85
69/* DATA0 */ 86/* DATA0 */
70#define UDA_DATA_CTRL0 (0 << 6) 87#define UDA_DATA_CTRL0 (0 << 6) /* volume */
71#define UDA_DATA_CTRL1 (1 << 6) 88#define UDA_DATA_CTRL1 (1 << 6) /* bass, treble */
72#define UDA_DATA_CTRL2 (2 << 6) 89#define UDA_DATA_CTRL2 (2 << 6) /* peak det pos, de-emp, mute */
73#define UDA_DATA_EXT_ADDR (6 << 5) 90#define UDA_DATA_EXT_ADDR (6 << 5)
74#define UDA_DATA_EXT_DATA (7 << 5) 91#define UDA_DATA_EXT_DATA (7 << 5)
75 92
76#define UDA_VOLUME(x) ((x) << 8) /* 1=0dB, 61=-60dB */ 93#define UDA_VOLUME(x) ((x) << 0) /* 1=0dB, 61=-60dB */
77 94
78#define UDA_BASS_BOOST(x) ((x) << 2) /* see datasheet */ 95#define UDA_BASS_BOOST(x) ((x) << 2) /* see datasheet */
96#define UDA_BASS_BOOST_MASK 0x0F
79#define UDA_TREBLE(x) ((x) << 0) /* see datasheet */ 97#define UDA_TREBLE(x) ((x) << 0) /* see datasheet */
98#define UDA_TREBLE_MASK 0x03
80 99
81#define UDA_PEAK_DETECT_POS (1 << 5) 100#define UDA_PEAK_DETECT_POS_BEFORE (0 << 5)
101#define UDA_PEAK_DETECT_POS_AFTER (1 << 5)
82#define UDA_DE_EMPHASIS_NONE (0 << 3) 102#define UDA_DE_EMPHASIS_NONE (0 << 3)
83#define UDA_DE_EMPHASIS_32 (1 << 3) 103#define UDA_DE_EMPHASIS_32 (1 << 3)
84#define UDA_DE_EMPHASIS_44_1 (2 << 3) 104#define UDA_DE_EMPHASIS_44_1 (2 << 3)
85#define UDA_DE_EMPHASIS_48 (3 << 3) 105#define UDA_DE_EMPHASIS_48 (3 << 3)
86#define UDA_MUTE (1 << 2) 106#define UDA_MUTE_ON (1 << 2)
107#define UDA_MUTE_OFF (0 << 2)
87#define UDA_MODE_SWITCH_FLAT (0 << 0) 108#define UDA_MODE_SWITCH_FLAT (0 << 0)
88#define UDA_MODE_SWITCH_MIN (1 << 0) 109#define UDA_MODE_SWITCH_MIN (1 << 0)
89#define UDA_MODE_SWITCH_MAX (3 << 0) 110#define UDA_MODE_SWITCH_MAX (3 << 0)
diff --git a/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c b/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c
index 237bf264f5..9c898f88d9 100644
--- a/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c
+++ b/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c
@@ -19,6 +19,7 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#include <stdlib.h> 21#include <stdlib.h>
22#include "config.h"
22#include "system.h" 23#include "system.h"
23#include "kernel.h" 24#include "kernel.h"
24#include "logf.h" 25#include "logf.h"
@@ -48,7 +49,7 @@ static struct
48static const unsigned char pcm_freq_parms[HW_NUM_FREQ][2] = 49static const unsigned char pcm_freq_parms[HW_NUM_FREQ][2] =
49{ 50{
50 [HW_FREQ_64] = { 2, IISMOD_MASTER_CLOCK_256FS }, 51 [HW_FREQ_64] = { 2, IISMOD_MASTER_CLOCK_256FS },
51 [HW_FREQ_44] = { 3, IISMOD_MASTER_CLOCK_384FS }, 52 [HW_FREQ_44] = { 2, IISMOD_MASTER_CLOCK_384FS },
52 [HW_FREQ_22] = { 8, IISMOD_MASTER_CLOCK_256FS }, 53 [HW_FREQ_22] = { 8, IISMOD_MASTER_CLOCK_256FS },
53 [HW_FREQ_11] = { 17, IISMOD_MASTER_CLOCK_256FS }, 54 [HW_FREQ_11] = { 17, IISMOD_MASTER_CLOCK_256FS },
54}; 55};
@@ -127,9 +128,12 @@ void pcm_postinit(void)
127void pcm_dma_apply_settings(void) 128void pcm_dma_apply_settings(void)
128{ 129{
129#ifdef HAVE_UDA1341 130#ifdef HAVE_UDA1341
131 unsigned int reg_val;
130 /* set prescaler and master clock rate according to freq */ 132 /* set prescaler and master clock rate according to freq */
131 IISPSR = (pcm_freq_parms [pcm_fsel][0] * IISPSR_PRESCALER_A) | pcm_freq_parms [pcm_fsel][0]; 133 reg_val = (pcm_freq_parms [pcm_fsel][0] << 5) | pcm_freq_parms [pcm_fsel][0];
132 IISMOD |= ~IISMOD_MASTER_CLOCK_384FS | pcm_freq_parms [pcm_fsel][1] ; 134
135 IISMOD = (IISMOD & ~IISMOD_MASTER_CLOCK_384FS) | pcm_freq_parms [pcm_fsel][1] ;
136 IISPSR = reg_val;
133#endif 137#endif
134 138
135 audiohw_set_frequency(pcm_fsel); 139 audiohw_set_frequency(pcm_fsel);
@@ -156,6 +160,11 @@ static void play_start_pcm(void)
156 /* turn off the idle */ 160 /* turn off the idle */
157 IISCON &= ~(1<<3); 161 IISCON &= ~(1<<3);
158 162
163#ifdef HAVE_UDA1341
164 IISMOD = (IISMOD & ~IISMOD_MASTER_CLOCK_384FS) | pcm_freq_parms [pcm_fsel][1] ;
165 IISPSR = (pcm_freq_parms [pcm_fsel][0] << 5) | pcm_freq_parms [pcm_fsel][0];
166#endif
167
159 /* start the IIS */ 168 /* start the IIS */
160 IISCON |= (1<<0); 169 IISCON |= (1<<0);
161} 170}