summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_x1000
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2022-01-11 13:58:41 +0000
committerAidan MacDonald <amachronic@protonmail.com>2022-01-29 19:28:03 +0000
commitc1f1d9140407757fab16c418eed09f5517c649d7 (patch)
treeee75be10480d454ea8a8cbd38cb51d29b7019433 /firmware/target/mips/ingenic_x1000
parentbc5a6385949c9f0a17173f3512aa9a6db9175803 (diff)
downloadrockbox-c1f1d9140407757fab16c418eed09f5517c649d7.tar.gz
rockbox-c1f1d9140407757fab16c418eed09f5517c649d7.zip
FiiO M3K: audio recording
Recording works now, although I'm sure there will be a few things that need fine-tuning. A major issue is that writing to the SD card creates noticable interference, which happens on the original firmware too but seems worse under Rockbox. (Since Rockbox waits until RAM fills up before writing data, the interference will only be heard on >50 MiB recordings.) Change-Id: I5561dd9668c3bdd34e92f34ef50848aef8c0b7eb
Diffstat (limited to 'firmware/target/mips/ingenic_x1000')
-rw-r--r--firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c127
1 files changed, 121 insertions, 6 deletions
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c
index f7dced8f54..9374d23a81 100644
--- a/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c
+++ b/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c
@@ -7,7 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2021 Aidan MacDonald 10 * Copyright (C) 2021-2022 Aidan MacDonald
11 * 11 *
12 * This program is free software; you can redistribute it and/or 12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License 13 * modify it under the terms of the GNU General Public License
@@ -20,6 +20,7 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include "audiohw.h" 22#include "audiohw.h"
23#include "audio.h"
23#include "system.h" 24#include "system.h"
24#include "pcm_sampr.h" 25#include "pcm_sampr.h"
25#include "aic-x1000.h" 26#include "aic-x1000.h"
@@ -27,6 +28,11 @@
27#include "gpio-x1000.h" 28#include "gpio-x1000.h"
28#include "logf.h" 29#include "logf.h"
29 30
31static int cur_audio_source = AUDIO_SRC_PLAYBACK;
32static int cur_vol_r = AK4376_MIN_VOLUME;
33static int cur_vol_l = AK4376_MIN_VOLUME;
34static int cur_recvol = 0;
35static int cur_filter_roll_off = 0;
30static int cur_fsel = HW_FREQ_48; 36static int cur_fsel = HW_FREQ_48;
31static int cur_power_mode = SOUND_HIGH_POWER; 37static int cur_power_mode = SOUND_HIGH_POWER;
32 38
@@ -60,29 +66,138 @@ void audiohw_postinit(void)
60 66
61void audiohw_close(void) 67void audiohw_close(void)
62{ 68{
63 ak4376_close(); 69 if(cur_audio_source == AUDIO_SRC_PLAYBACK)
70 ak4376_close();
71 else if(cur_audio_source == AUDIO_SRC_MIC)
72 x1000_icodec_close();
73}
74
75void audio_set_output_source(int source)
76{
77 /* this is a no-op */
78 (void)source;
79}
80
81void audio_input_mux(int source, unsigned flags)
82{
83 (void)flags;
84
85 if(source == cur_audio_source)
86 return;
87
88 /* close whatever codec is currently in use */
89 audiohw_close();
90 aic_enable_i2s_bit_clock(false);
91
92 /* switch to new source */
93 cur_audio_source = source;
94
95 if(source == AUDIO_SRC_PLAYBACK) {
96 /* power on DAC */
97 aic_set_external_codec(true);
98 aic_set_i2s_mode(AIC_I2S_MASTER_MODE);
99 ak4376_open();
100
101 /* apply the old settings */
102 audiohw_set_volume(cur_vol_l, cur_vol_r);
103 audiohw_set_filter_roll_off(cur_filter_roll_off);
104 set_ak_freqmode();
105 } else if(source == AUDIO_SRC_MIC) {
106 aic_set_external_codec(false);
107 aic_set_i2s_mode(AIC_I2S_SLAVE_MODE);
108 /* Note: Sampling frequency is irrelevant here */
109 aic_set_i2s_clock(X1000_CLK_EXCLK, 48000, 0);
110 aic_enable_i2s_bit_clock(true);
111
112 x1000_icodec_open();
113
114 /* configure the mic */
115 x1000_icodec_mic1_enable(true);
116 x1000_icodec_mic1_bias_enable(true);
117 x1000_icodec_mic1_configure(JZCODEC_MIC1_DIFFERENTIAL |
118 JZCODEC_MIC1_BIAS_2_08V);
119
120 /* configure the ADC */
121 x1000_icodec_adc_mic_sel(JZCODEC_MIC_SEL_ANALOG);
122 x1000_icodec_adc_highpass_filter(true);
123 x1000_icodec_adc_frequency(cur_fsel);
124 x1000_icodec_adc_enable(true);
125
126 /* configure the mixer to put mic input in both channels */
127 x1000_icodec_mixer_enable(true);
128 x1000_icodec_write(JZCODEC_MIX2, 0x10);
129
130 /* set gain and unmute */
131 audiohw_set_recvol(cur_recvol, 0, AUDIO_GAIN_MIC);
132 x1000_icodec_adc_mute(false);
133 } else {
134 logf("bad audio input source: %d (flags: %x)", source, flags);
135 }
64} 136}
65 137
66void audiohw_set_volume(int vol_l, int vol_r) 138void audiohw_set_volume(int vol_l, int vol_r)
67{ 139{
68 ak4376_set_volume(vol_l, vol_r); 140 cur_vol_l = vol_l;
141 cur_vol_r = vol_r;
142
143 if(cur_audio_source == AUDIO_SRC_PLAYBACK)
144 ak4376_set_volume(vol_l, vol_r);
69} 145}
70 146
71void audiohw_set_filter_roll_off(int val) 147void audiohw_set_filter_roll_off(int val)
72{ 148{
73 ak4376_set_filter_roll_off(val); 149 cur_filter_roll_off = val;
150
151 if(cur_audio_source == AUDIO_SRC_PLAYBACK)
152 ak4376_set_filter_roll_off(val);
74} 153}
75 154
76void audiohw_set_frequency(int fsel) 155void audiohw_set_frequency(int fsel)
77{ 156{
78 cur_fsel = fsel; 157 cur_fsel = fsel;
79 set_ak_freqmode(); 158
159 if(cur_audio_source == AUDIO_SRC_PLAYBACK)
160 set_ak_freqmode();
161 else
162 x1000_icodec_adc_frequency(fsel);
80} 163}
81 164
82void audiohw_set_power_mode(int mode) 165void audiohw_set_power_mode(int mode)
83{ 166{
84 cur_power_mode = mode; 167 cur_power_mode = mode;
85 set_ak_freqmode(); 168
169 if(cur_audio_source == AUDIO_SRC_PLAYBACK)
170 set_ak_freqmode();
171}
172
173static int round_step_up(int x, int step)
174{
175 int rem = x % step;
176 if(rem > 0)
177 rem -= step;
178 return x - rem;
179}
180
181void audiohw_set_recvol(int left, int right, int type)
182{
183 (void)right;
184
185 if(type == AUDIO_GAIN_MIC) {
186 cur_recvol = left;
187
188 if(cur_audio_source == AUDIO_SRC_MIC) {
189 int mic_gain = round_step_up(left, X1000_ICODEC_MIC_GAIN_STEP);
190 mic_gain = MIN(mic_gain, X1000_ICODEC_MIC_GAIN_MAX);
191 mic_gain = MAX(mic_gain, X1000_ICODEC_MIC_GAIN_MIN);
192
193 int adc_gain = left - mic_gain;
194 adc_gain = MIN(adc_gain, X1000_ICODEC_ADC_GAIN_MAX);
195 adc_gain = MAX(adc_gain, X1000_ICODEC_ADC_GAIN_MIN);
196
197 x1000_icodec_adc_gain(adc_gain);
198 x1000_icodec_mic1_gain(mic_gain);
199 }
200 }
86} 201}
87 202
88void ak4376_set_pdn_pin(int level) 203void ak4376_set_pdn_pin(int level)