summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c')
-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)