summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx233/audioout-imx233.c
diff options
context:
space:
mode:
authorAmaury Pouly <pamaury@rockbox.org>2011-10-18 22:06:05 +0000
committerAmaury Pouly <pamaury@rockbox.org>2011-10-18 22:06:05 +0000
commit7b70e5a8fae7ce8b0f9c74403c1efcc414297e35 (patch)
treeb07bffc5da4c952f0ff26a654579a245ad8acbe0 /firmware/target/arm/imx233/audioout-imx233.c
parent96f0464796639e241074a98b0a5dd7f07305d142 (diff)
downloadrockbox-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.c179
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
26void 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
53void imx233_audioout_postinit(void)
54{
55 /* start converting audio */
56 __REG_SET(HW_AUDIOOUT_CTRL) = HW_AUDIOOUT_CTRL__RUN;
57}
58
59void 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 */
82void 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
95void 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
113void 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 */
173void 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}