diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c | 127 |
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 | ||
31 | static int cur_audio_source = AUDIO_SRC_PLAYBACK; | ||
32 | static int cur_vol_r = AK4376_MIN_VOLUME; | ||
33 | static int cur_vol_l = AK4376_MIN_VOLUME; | ||
34 | static int cur_recvol = 0; | ||
35 | static int cur_filter_roll_off = 0; | ||
30 | static int cur_fsel = HW_FREQ_48; | 36 | static int cur_fsel = HW_FREQ_48; |
31 | static int cur_power_mode = SOUND_HIGH_POWER; | 37 | static int cur_power_mode = SOUND_HIGH_POWER; |
32 | 38 | ||
@@ -60,29 +66,138 @@ void audiohw_postinit(void) | |||
60 | 66 | ||
61 | void audiohw_close(void) | 67 | void 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 | |||
75 | void audio_set_output_source(int source) | ||
76 | { | ||
77 | /* this is a no-op */ | ||
78 | (void)source; | ||
79 | } | ||
80 | |||
81 | void 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 | ||
66 | void audiohw_set_volume(int vol_l, int vol_r) | 138 | void 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 | ||
71 | void audiohw_set_filter_roll_off(int val) | 147 | void 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 | ||
76 | void audiohw_set_frequency(int fsel) | 155 | void 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 | ||
82 | void audiohw_set_power_mode(int mode) | 165 | void 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 | |||
173 | static 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 | |||
181 | void 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 | ||
88 | void ak4376_set_pdn_pin(int level) | 203 | void ak4376_set_pdn_pin(int level) |