diff options
author | Amaury Pouly <pamaury@rockbox.org> | 2011-10-18 22:06:05 +0000 |
---|---|---|
committer | Amaury Pouly <pamaury@rockbox.org> | 2011-10-18 22:06:05 +0000 |
commit | 7b70e5a8fae7ce8b0f9c74403c1efcc414297e35 (patch) | |
tree | b07bffc5da4c952f0ff26a654579a245ad8acbe0 /firmware/target/arm/imx233/audioout-imx233.c | |
parent | 96f0464796639e241074a98b0a5dd7f07305d142 (diff) | |
download | rockbox-7b70e5a8fae7ce8b0f9c74403c1efcc414297e35.tar.gz rockbox-7b70e5a8fae7ce8b0f9c74403c1efcc414297e35.zip |
imx233/fuze+: implement audioout functions (init, volume, frequency); add stubs for audioin
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30798 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/imx233/audioout-imx233.c')
-rw-r--r-- | firmware/target/arm/imx233/audioout-imx233.c | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/firmware/target/arm/imx233/audioout-imx233.c b/firmware/target/arm/imx233/audioout-imx233.c new file mode 100644 index 0000000000..0a48a909e8 --- /dev/null +++ b/firmware/target/arm/imx233/audioout-imx233.c | |||
@@ -0,0 +1,179 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2011 by Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
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 "audioout-imx233.h" | ||
22 | #include "clkctrl-imx233.h" | ||
23 | #include "rtc-imx233.h" | ||
24 | #include "pcm_sampr.h" | ||
25 | |||
26 | void imx233_audioout_preinit(void) | ||
27 | { | ||
28 | /* Enable AUDIOOUT block */ | ||
29 | imx233_reset_block(&HW_AUDIOOUT_CTRL); | ||
30 | /* Enable digital filter clock */ | ||
31 | imx233_enable_xtal_clock(XTAL_FILT, true); | ||
32 | /* Enable DAC */ | ||
33 | __REG_CLR(HW_AUDIOOUT_ANACLKCTRL) = HW_AUDIOOUT_ANACLKCTRL__CLKGATE; | ||
34 | /* Set capless mode */ | ||
35 | __REG_CLR(HW_AUDIOOUT_PWRDN) = HW_AUDIOOUT_PWRDN__CAPLESS; | ||
36 | /* Set word-length to 16-bit */ | ||
37 | __REG_SET(HW_AUDIOOUT_CTRL) = HW_AUDIOOUT_CTRL__WORD_LENGTH; | ||
38 | /* Power up DAC */ | ||
39 | __REG_CLR(HW_AUDIOOUT_PWRDN) = HW_AUDIOOUT_PWRDN__DAC; | ||
40 | /* Hold HP to ground to avoid pop, then release and power up HP */ | ||
41 | __REG_SET(HW_AUDIOOUT_ANACTRL) = HW_AUDIOOUT_ANACTRL__HP_HOLD_GND; | ||
42 | __REG_SET(HW_RTC_PERSISTENT0) = HW_RTC_PERSISTENT0__SPARE__RELEASE_GND; | ||
43 | __REG_CLR(HW_AUDIOOUT_PWRDN) = HW_AUDIOOUT_PWRDN__HEADPHONE; | ||
44 | /* Set HP mode to AB */ | ||
45 | __REG_SET(HW_AUDIOOUT_ANACTRL) = HW_AUDIOOUT_ANACTRL__HP_CLASSAB; | ||
46 | /* Stop holding to ground */ | ||
47 | __REG_CLR(HW_AUDIOOUT_ANACTRL) = HW_AUDIOOUT_ANACTRL__HP_HOLD_GND; | ||
48 | /* Set dmawait count to 31 (see errata, workaround random stop) */ | ||
49 | __REG_CLR(HW_AUDIOOUT_CTRL) = HW_AUDIOOUT_CTRL__DMAWAIT_COUNT_BM; | ||
50 | __REG_SET(HW_AUDIOOUT_CTRL) = 31 << HW_AUDIOOUT_CTRL__DMAWAIT_COUNT_BP; | ||
51 | } | ||
52 | |||
53 | void imx233_audioout_postinit(void) | ||
54 | { | ||
55 | /* start converting audio */ | ||
56 | __REG_SET(HW_AUDIOOUT_CTRL) = HW_AUDIOOUT_CTRL__RUN; | ||
57 | } | ||
58 | |||
59 | void imx233_audioout_close(void) | ||
60 | { | ||
61 | /* Switch to class A */ | ||
62 | __REG_CLR(HW_AUDIOOUT_ANACTRL) = HW_AUDIOOUT_ANACTRL__HP_CLASSAB; | ||
63 | /* Hold HP to ground */ | ||
64 | __REG_SET(HW_AUDIOOUT_ANACTRL) = HW_AUDIOOUT_ANACTRL__HP_HOLD_GND; | ||
65 | /* Mute HP and power down */ | ||
66 | __REG_SET(HW_AUDIOOUT_HPVOL) = HW_AUDIOOUT_HPVOL__MUTE; | ||
67 | /* Power down HP */ | ||
68 | __REG_SET(HW_AUDIOOUT_PWRDN) = HW_AUDIOOUT_PWRDN__HEADPHONE; | ||
69 | /* Mute DAC */ | ||
70 | __REG_SET(HW_AUDIOOUT_DACVOLUME) = HW_AUDIOOUT_DACVOLUME__MUTE_LEFT | ||
71 | | HW_AUDIOOUT_DACVOLUME__MUTE_RIGHT; | ||
72 | /* Power down DAC */ | ||
73 | __REG_SET(HW_AUDIOOUT_PWRDN) = HW_AUDIOOUT_PWRDN__DAC; | ||
74 | /* Gate off DAC */ | ||
75 | __REG_SET(HW_AUDIOOUT_ANACLKCTRL) = HW_AUDIOOUT_ANACLKCTRL__CLKGATE; | ||
76 | /* Disable digital filter clock */ | ||
77 | imx233_enable_xtal_clock(XTAL_FILT, false); | ||
78 | /* will also gate off the module */ | ||
79 | __REG_CLR(HW_AUDIOOUT_CTRL) = HW_AUDIOOUT_CTRL__RUN; | ||
80 | } | ||
81 | /* volume in half dB */ | ||
82 | void imx233_audioout_set_dac_vol(int vol_l, int vol_r) | ||
83 | { | ||
84 | /* minimum is -100dB and max is 0dB */ | ||
85 | vol_l = MAX(-200, MIN(vol_l, 0)); | ||
86 | vol_r = MAX(-200, MIN(vol_r, 0)); | ||
87 | /* unmute, enable zero cross and set volume. | ||
88 | * 0xff is 0dB */ | ||
89 | HW_AUDIOOUT_DACVOLUME = | ||
90 | (0xff + vol_l) << HW_AUDIOOUT_DACVOLUME__VOLUME_LEFT_BP | | ||
91 | (0xff + vol_r) << HW_AUDIOOUT_DACVOLUME__VOLUME_RIGHT_BP | | ||
92 | HW_AUDIOOUT_DACVOLUME__EN_ZCD; | ||
93 | } | ||
94 | |||
95 | void imx233_audioout_set_hp_vol(int vol_l, int vol_r) | ||
96 | { | ||
97 | uint32_t select = (HW_AUDIOOUT_HPVOL & HW_AUDIOOUT_HPVOL__SELECT); | ||
98 | /* minimum is -57.5dB and max is 6dB in DAC mode | ||
99 | * and -51.5dB / 12dB in Line1 mode */ | ||
100 | int min = select ? -103 : -115; | ||
101 | int max = select ? 24 : 12; | ||
102 | |||
103 | vol_l = MAX(min, MIN(vol_l, max)); | ||
104 | vol_r = MAX(min, MIN(vol_r, max)); | ||
105 | /* unmute, enable zero cross and set volume. Keep select value. */ | ||
106 | HW_AUDIOOUT_HPVOL = | ||
107 | (max - vol_l) << HW_AUDIOOUT_HPVOL__VOL_LEFT_BP | | ||
108 | (max - vol_r) << HW_AUDIOOUT_HPVOL__VOL_RIGHT_BP | | ||
109 | select | | ||
110 | HW_AUDIOOUT_HPVOL__EN_MSTR_ZCD; | ||
111 | } | ||
112 | |||
113 | void imx233_audioout_set_freq(int fsel) | ||
114 | { | ||
115 | static struct | ||
116 | { | ||
117 | int base_mult; | ||
118 | int src_hold; | ||
119 | int src_int; | ||
120 | int src_frac; | ||
121 | }dacssr[HW_NUM_FREQ] = | ||
122 | { | ||
123 | HW_HAVE_8_([HW_FREQ_8] = { 0x1, 0x3, 0x17, 0xe00 } ,) | ||
124 | HW_HAVE_11_([HW_FREQ_11] = { 0x1, 0x3, 0x11, 0x37 } ,) | ||
125 | HW_HAVE_12_([HW_FREQ_12] = { 0x1, 0x3, 0xf, 0x13ff },) | ||
126 | HW_HAVE_16_([HW_FREQ_16] = { 0x1, 0x1, 0x17, 0xe00},) | ||
127 | HW_HAVE_22_([HW_FREQ_22] = { 0x1, 0x1, 0x11, 0x37 },) | ||
128 | HW_HAVE_24_([HW_FREQ_24] = { 0x1, 0x1, 0xf, 0x13ff },) | ||
129 | HW_HAVE_32_([HW_FREQ_32] = { 0x1, 0x0, 0x17, 0xe00},) | ||
130 | HW_HAVE_44_([HW_FREQ_44] = { 0x1, 0x0, 0x11, 0x37 },) | ||
131 | HW_HAVE_48_([HW_FREQ_48] = { 0x1, 0x0, 0xf, 0x13ff },) | ||
132 | HW_HAVE_64_([HW_FREQ_64] = { 0x2, 0x0, 0x17, 0xe00},) | ||
133 | HW_HAVE_88_([HW_FREQ_88] = { 0x2, 0x0, 0x11, 0x37 },) | ||
134 | HW_HAVE_96_([HW_FREQ_96] = { 0x2, 0x0, 0xf, 0x13ff },) | ||
135 | }; | ||
136 | |||
137 | HW_AUDIOOUT_DACSRR = | ||
138 | dacssr[fsel].src_frac << HW_AUDIOOUT_DACSRR__SRC_FRAC_BP | | ||
139 | dacssr[fsel].src_int << HW_AUDIOOUT_DACSRR__SRC_INT_BP | | ||
140 | dacssr[fsel].src_hold << HW_AUDIOOUT_DACSRR__SRC_HOLD_BP | | ||
141 | dacssr[fsel].base_mult << HW_AUDIOOUT_DACSRR__BASEMULT_BP; | ||
142 | |||
143 | #if 0 | ||
144 | /* Select base_mult and src_hold depending on the audio range: | ||
145 | * 0 < f <= 12000 --> base_mult = 1, src_hold = 3 (div by 4) | ||
146 | * 12000 < f <= 24000 --> base_mult = 1, src_hold = 1 (div by 2) | ||
147 | * 24000 < f <= 48000 --> base_mult = 1, src_hold = 0 (div by 1) | ||
148 | * 48000 < f <= 96000 --> base_mult = 2, src_hold = 0 (mul by 2) | ||
149 | * 96000 < f <= ..... --> base_mult = 4, src_hold = 0 (mul by 4) */ | ||
150 | int base_mult = 1; | ||
151 | int src_hold = 0; | ||
152 | if(f > 96000) | ||
153 | base_mult = 4; | ||
154 | else if(f > 48000) | ||
155 | base_mult = 2; | ||
156 | else if(f <= 12000) | ||
157 | src_hold = 3; | ||
158 | else if(f <= 24000) | ||
159 | src_hold = 1; | ||
160 | /* compute the divisor (a tricky to keep to do it with 32-bit words only) */ | ||
161 | int src_int = (750000 * base_mult) / (f * (src_hold + 1)); | ||
162 | int src_frac = ((750000 * base_mult - src_int * f * (src_hold + 1)) << 13) / (f * (src_hold + 1)); | ||
163 | |||
164 | HW_AUDIOOUT_DACSRR = | ||
165 | src_frac << HW_AUDIOOUT_DACSRR__SRC_FRAC_BP | | ||
166 | src_int << HW_AUDIOOUT_DACSRR__SRC_INT_BP | | ||
167 | src_hold << HW_AUDIOOUT_DACSRR__SRC_HOLD_BP | | ||
168 | base_mult << HW_AUDIOOUT_DACSRR__BASEMULT_BP; | ||
169 | #endif | ||
170 | } | ||
171 | |||
172 | /* select between DAC and Line1 */ | ||
173 | void imx233_audiout_select_hp_input(bool line1) | ||
174 | { | ||
175 | if(line1) | ||
176 | __REG_SET(HW_AUDIOOUT_HPVOL) = HW_AUDIOOUT_HPVOL__SELECT; | ||
177 | else | ||
178 | __REG_CLR(HW_AUDIOOUT_HPVOL) = HW_AUDIOOUT_HPVOL__SELECT; | ||
179 | } | ||