| 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | // |
| 3 | // es8323.c -- es8323 ALSA SoC audio driver |
| 4 | // |
| 5 | // Copyright 2024 Rockchip Electronics Co. Ltd. |
| 6 | // Copyright 2024 Everest Semiconductor Co.,Ltd. |
| 7 | // Copyright 2024 Loongson Technology Co.,Ltd. |
| 8 | // |
| 9 | // Author: Mark Brown <broonie@kernel.org> |
| 10 | // Jianqun Xu <jay.xu@rock-chips.com> |
| 11 | // Nickey Yang <nickey.yang@rock-chips.com> |
| 12 | // Further cleanup and restructuring by: |
| 13 | // Binbin Zhou <zhoubinbin@loongson.cn> |
| 14 | |
| 15 | #include <linux/module.h> |
| 16 | #include <linux/acpi.h> |
| 17 | #include <linux/clk.h> |
| 18 | #include <linux/delay.h> |
| 19 | #include <linux/i2c.h> |
| 20 | #include <linux/mod_devicetable.h> |
| 21 | #include <linux/regmap.h> |
| 22 | #include <sound/pcm.h> |
| 23 | #include <sound/pcm_params.h> |
| 24 | #include <sound/soc.h> |
| 25 | #include <sound/soc-dapm.h> |
| 26 | #include <sound/tlv.h> |
| 27 | |
| 28 | #include "es8323.h" |
| 29 | |
| 30 | struct es8323_priv { |
| 31 | unsigned int sysclk; |
| 32 | struct clk *mclk; |
| 33 | struct regmap *regmap; |
| 34 | struct snd_pcm_hw_constraint_list *sysclk_constraints; |
| 35 | struct snd_soc_component *component; |
| 36 | }; |
| 37 | |
| 38 | /* es8323 register cache */ |
| 39 | static const struct reg_default es8323_reg_defaults[] = { |
| 40 | { ES8323_CONTROL1, 0x06 }, |
| 41 | { ES8323_CONTROL2, 0x1c }, |
| 42 | { ES8323_CHIPPOWER, 0xc3 }, |
| 43 | { ES8323_ADCPOWER, 0xfc }, |
| 44 | { ES8323_DACPOWER, 0xc0 }, |
| 45 | { ES8323_CHIPLOPOW1, 0x00 }, |
| 46 | { ES8323_CHIPLOPOW2, 0x00 }, |
| 47 | { ES8323_ANAVOLMANAG, 0x7c }, |
| 48 | { ES8323_MASTERMODE, 0x80 }, |
| 49 | { ES8323_ADCCONTROL1, 0x00 }, |
| 50 | { ES8323_ADCCONTROL2, 0x00 }, |
| 51 | { ES8323_ADCCONTROL3, 0x06 }, |
| 52 | { ES8323_ADCCONTROL4, 0x00 }, |
| 53 | { ES8323_ADCCONTROL5, 0x06 }, |
| 54 | { ES8323_ADCCONTROL6, 0x30 }, |
| 55 | { ES8323_ADC_MUTE, 0x30 }, |
| 56 | { ES8323_LADC_VOL, 0xc0 }, |
| 57 | { ES8323_RADC_VOL, 0xc0 }, |
| 58 | { ES8323_ADCCONTROL10, 0x38 }, |
| 59 | { ES8323_ADCCONTROL11, 0xb0 }, |
| 60 | { ES8323_ADCCONTROL12, 0x32 }, |
| 61 | { ES8323_ADCCONTROL13, 0x06 }, |
| 62 | { ES8323_ADCCONTROL14, 0x00 }, |
| 63 | { ES8323_DACCONTROL1, 0x00 }, |
| 64 | { ES8323_DACCONTROL2, 0x06 }, |
| 65 | { ES8323_DAC_MUTE, 0x30 }, |
| 66 | { ES8323_LDAC_VOL, 0xc0 }, |
| 67 | { ES8323_RDAC_VOL, 0xc0 }, |
| 68 | { ES8323_DACCONTROL6, 0x08 }, |
| 69 | { ES8323_DACCONTROL7, 0x06 }, |
| 70 | { ES8323_DACCONTROL8, 0x1f }, |
| 71 | { ES8323_DACCONTROL9, 0xf7 }, |
| 72 | { ES8323_DACCONTROL10, 0xfd }, |
| 73 | { ES8323_DACCONTROL11, 0xff }, |
| 74 | { ES8323_DACCONTROL12, 0x1f }, |
| 75 | { ES8323_DACCONTROL13, 0xf7 }, |
| 76 | { ES8323_DACCONTROL14, 0xfd }, |
| 77 | { ES8323_DACCONTROL15, 0xff }, |
| 78 | { ES8323_DACCONTROL16, 0x00 }, |
| 79 | { ES8323_DACCONTROL17, 0x38 }, |
| 80 | { ES8323_DACCONTROL18, 0x38 }, |
| 81 | { ES8323_DACCONTROL19, 0x38 }, |
| 82 | { ES8323_DACCONTROL20, 0x38 }, |
| 83 | { ES8323_DACCONTROL21, 0x38 }, |
| 84 | { ES8323_DACCONTROL22, 0x38 }, |
| 85 | { ES8323_DACCONTROL23, 0x00 }, |
| 86 | { ES8323_LOUT1_VOL, 0x00 }, |
| 87 | { ES8323_ROUT1_VOL, 0x00 }, |
| 88 | }; |
| 89 | |
| 90 | static const char *const es8323_stereo_3d_texts[] = { "No 3D " , "Level 1" , "Level 2" , "Level 3" , |
| 91 | "Level 4" , "Level 5" , "Level 6" , "Level 7" }; |
| 92 | static SOC_ENUM_SINGLE_DECL(es8323_stereo_3d_enum, ES8323_DACCONTROL7, 2, es8323_stereo_3d_texts); |
| 93 | |
| 94 | static const char *const es8323_alc_func_texts[] = { "Off" , "Right" , "Left" , "Stereo" }; |
| 95 | static SOC_ENUM_SINGLE_DECL(es8323_alc_function_enum, |
| 96 | ES8323_ADCCONTROL10, 6, es8323_alc_func_texts); |
| 97 | |
| 98 | static const char *const es8323_ng_type_texts[] = { "Constant PGA Gain" , "Mute ADC Output" }; |
| 99 | static SOC_ENUM_SINGLE_DECL(es8323_alc_ng_type_enum, ES8323_ADCCONTROL14, 1, es8323_ng_type_texts); |
| 100 | |
| 101 | static const char *const es8323_deemph_texts[] = { "None" , "32Khz" , "44.1Khz" , "48Khz" }; |
| 102 | static SOC_ENUM_SINGLE_DECL(es8323_playback_deemphasis_enum, |
| 103 | ES8323_DACCONTROL6, 6, es8323_deemph_texts); |
| 104 | |
| 105 | static const char *const es8323_adcpol_texts[] = { "Normal" , "L Invert" , |
| 106 | "R Invert" , "L + R Invert" }; |
| 107 | static SOC_ENUM_SINGLE_DECL(es8323_capture_polarity_enum, |
| 108 | ES8323_ADCCONTROL6, 6, es8323_adcpol_texts); |
| 109 | |
| 110 | static const DECLARE_TLV_DB_SCALE(es8323_adc_tlv, -9600, 50, 1); |
| 111 | static const DECLARE_TLV_DB_SCALE(es8323_dac_tlv, -9600, 50, 1); |
| 112 | static const DECLARE_TLV_DB_SCALE(es8323_out_tlv, -4500, 150, 0); |
| 113 | static const DECLARE_TLV_DB_SCALE(es8323_bypass_tlv, 0, 300, 0); |
| 114 | static const DECLARE_TLV_DB_SCALE(es8323_bypass_tlv2, -15, 300, 0); |
| 115 | |
| 116 | static const struct snd_kcontrol_new es8323_snd_controls[] = { |
| 117 | SOC_ENUM("3D Mode" , es8323_stereo_3d_enum), |
| 118 | SOC_ENUM("ALC Capture Function" , es8323_alc_function_enum), |
| 119 | SOC_ENUM("ALC Capture NG Type" , es8323_alc_ng_type_enum), |
| 120 | SOC_ENUM("Playback De-emphasis" , es8323_playback_deemphasis_enum), |
| 121 | SOC_ENUM("Capture Polarity" , es8323_capture_polarity_enum), |
| 122 | SOC_SINGLE("ALC Capture ZC Switch" , ES8323_ADCCONTROL13, 6, 1, 0), |
| 123 | SOC_SINGLE("ALC Capture Decay Time" , ES8323_ADCCONTROL12, 4, 15, 0), |
| 124 | SOC_SINGLE("ALC Capture Attack Time" , ES8323_ADCCONTROL12, 0, 15, 0), |
| 125 | SOC_SINGLE("ALC Capture NG Threshold" , ES8323_ADCCONTROL14, 3, 31, 0), |
| 126 | SOC_SINGLE("ALC Capture NG Switch" , ES8323_ADCCONTROL14, 0, 1, 0), |
| 127 | SOC_SINGLE("ZC Timeout Switch" , ES8323_ADCCONTROL13, 6, 1, 0), |
| 128 | SOC_SINGLE("Capture Mute Switch" , ES8323_ADC_MUTE, 2, 1, 0), |
| 129 | SOC_SINGLE_TLV("Left Channel Capture Volume" , ES8323_ADCCONTROL1, 4, 8, |
| 130 | 0, es8323_bypass_tlv), |
| 131 | SOC_SINGLE_TLV("Right Channel Capture Volume" , ES8323_ADCCONTROL1, 0, |
| 132 | 8, 0, es8323_bypass_tlv), |
| 133 | SOC_SINGLE_TLV("Left Mixer Left Bypass Volume" , ES8323_DACCONTROL17, 3, |
| 134 | 7, 1, es8323_bypass_tlv2), |
| 135 | SOC_SINGLE_TLV("Right Mixer Right Bypass Volume" , ES8323_DACCONTROL20, |
| 136 | 3, 7, 1, es8323_bypass_tlv2), |
| 137 | SOC_DOUBLE_R_TLV("PCM Volume" , ES8323_LDAC_VOL, ES8323_RDAC_VOL, |
| 138 | 0, 192, 1, es8323_dac_tlv), |
| 139 | SOC_DOUBLE_R_TLV("Capture Digital Volume" , ES8323_LADC_VOL, |
| 140 | ES8323_RADC_VOL, 0, 192, 1, es8323_adc_tlv), |
| 141 | SOC_DOUBLE_R_TLV("Output 1 Playback Volume" , ES8323_LOUT1_VOL, |
| 142 | ES8323_ROUT1_VOL, 0, 33, 0, es8323_out_tlv), |
| 143 | SOC_DOUBLE_R_TLV("Output 2 Playback Volume" , ES8323_LOUT2_VOL, |
| 144 | ES8323_ROUT2_VOL, 0, 33, 0, es8323_out_tlv), |
| 145 | }; |
| 146 | |
| 147 | /* Left DAC Route */ |
| 148 | static const char *const es8323_pga_sell[] = { "Line 1L" , "Line 2L" , "NC" , "DifferentialL" }; |
| 149 | static SOC_ENUM_SINGLE_DECL(es8323_left_dac_enum, ES8323_ADCCONTROL2, 6, es8323_pga_sell); |
| 150 | static const struct snd_kcontrol_new es8323_left_dac_mux_controls = |
| 151 | SOC_DAPM_ENUM("Left DAC Route" , es8323_left_dac_enum); |
| 152 | |
| 153 | /* Right DAC Route */ |
| 154 | static const char *const es8323_pga_selr[] = { "Line 1R" , "Line 2R" , "NC" , "DifferentialR" }; |
| 155 | static SOC_ENUM_SINGLE_DECL(es8323_right_dac_enum, ES8323_ADCCONTROL2, 4, es8323_pga_selr); |
| 156 | static const struct snd_kcontrol_new es8323_right_dac_mux_controls = |
| 157 | SOC_DAPM_ENUM("Right DAC Route" , es8323_right_dac_enum); |
| 158 | |
| 159 | /* Left Line Mux */ |
| 160 | static const char *const es8323_lin_sell[] = { "Line 1L" , "Line 2L" , "NC" , "MicL" }; |
| 161 | static SOC_ENUM_SINGLE_DECL(es8323_llin_enum, ES8323_DACCONTROL16, 3, es8323_lin_sell); |
| 162 | static const struct snd_kcontrol_new es8323_left_line_controls = |
| 163 | SOC_DAPM_ENUM("LLIN Mux" , es8323_llin_enum); |
| 164 | |
| 165 | /* Right Line Mux */ |
| 166 | static const char *const es8323_lin_selr[] = { "Line 1R" , "Line 2R" , "NC" , "MicR" }; |
| 167 | static SOC_ENUM_SINGLE_DECL(es8323_rlin_enum, ES8323_DACCONTROL16, 0, es8323_lin_selr); |
| 168 | static const struct snd_kcontrol_new es8323_right_line_controls = |
| 169 | SOC_DAPM_ENUM("RLIN Mux" , es8323_rlin_enum); |
| 170 | |
| 171 | /* Differential Mux */ |
| 172 | static const char *const es8323_diffmux_sel[] = { "Line 1" , "Line 2" }; |
| 173 | static SOC_ENUM_SINGLE_DECL(es8323_diffmux_enum, ES8323_ADCCONTROL3, 7, es8323_diffmux_sel); |
| 174 | static const struct snd_kcontrol_new es8323_diffmux_controls = |
| 175 | SOC_DAPM_ENUM("Route2" , es8323_diffmux_enum); |
| 176 | |
| 177 | /* Mono ADC Mux */ |
| 178 | static const char *const es8323_mono_adc_mux[] = { "Stereo" , "Mono (Left)" , "Mono (Right)" }; |
| 179 | static SOC_ENUM_SINGLE_DECL(es8323_mono_adc_mux_enum, ES8323_ADCCONTROL3, 3, es8323_mono_adc_mux); |
| 180 | static const struct snd_kcontrol_new es8323_mono_adc_mux_controls = |
| 181 | SOC_DAPM_ENUM("Mono Mux" , es8323_mono_adc_mux_enum); |
| 182 | |
| 183 | /* Left Mixer */ |
| 184 | static const struct snd_kcontrol_new es8323_left_mixer_controls[] = { |
| 185 | SOC_DAPM_SINGLE("Left Playback Switch" , ES8323_DACCONTROL17, 7, 1, 0), |
| 186 | SOC_DAPM_SINGLE("Left Bypass Switch" , ES8323_DACCONTROL17, 6, 1, 0), |
| 187 | }; |
| 188 | |
| 189 | /* Right Mixer */ |
| 190 | static const struct snd_kcontrol_new es8323_right_mixer_controls[] = { |
| 191 | SOC_DAPM_SINGLE("Right Playback Switch" , ES8323_DACCONTROL20, 7, 1, 0), |
| 192 | SOC_DAPM_SINGLE("Right Bypass Switch" , ES8323_DACCONTROL20, 6, 1, 0), |
| 193 | }; |
| 194 | |
| 195 | static const struct snd_soc_dapm_widget es8323_dapm_widgets[] = { |
| 196 | SND_SOC_DAPM_INPUT("LINPUT1" ), |
| 197 | SND_SOC_DAPM_INPUT("LINPUT2" ), |
| 198 | SND_SOC_DAPM_INPUT("RINPUT1" ), |
| 199 | SND_SOC_DAPM_INPUT("RINPUT2" ), |
| 200 | |
| 201 | SND_SOC_DAPM_MICBIAS("Mic Bias" , SND_SOC_NOPM, 3, 1), |
| 202 | |
| 203 | /* Muxes */ |
| 204 | SND_SOC_DAPM_MUX("Left PGA Mux" , SND_SOC_NOPM, 0, 0, &es8323_left_dac_mux_controls), |
| 205 | SND_SOC_DAPM_MUX("Right PGA Mux" , SND_SOC_NOPM, 0, 0, &es8323_right_dac_mux_controls), |
| 206 | SND_SOC_DAPM_MUX("Differential Mux" , SND_SOC_NOPM, 0, 0, &es8323_diffmux_controls), |
| 207 | SND_SOC_DAPM_MUX("Left ADC Mux" , SND_SOC_NOPM, 0, 0, &es8323_mono_adc_mux_controls), |
| 208 | SND_SOC_DAPM_MUX("Right ADC Mux" , SND_SOC_NOPM, 0, 0, &es8323_mono_adc_mux_controls), |
| 209 | SND_SOC_DAPM_MUX("Left Line Mux" , SND_SOC_NOPM, 0, 0, &es8323_left_line_controls), |
| 210 | SND_SOC_DAPM_MUX("Right Line Mux" , SND_SOC_NOPM, 0, 0, &es8323_right_line_controls), |
| 211 | |
| 212 | SND_SOC_DAPM_ADC("Right ADC" , "Right Capture" , SND_SOC_NOPM, 4, 1), |
| 213 | SND_SOC_DAPM_ADC("Left ADC" , "Left Capture" , SND_SOC_NOPM, 5, 1), |
| 214 | SND_SOC_DAPM_DAC("Right DAC" , "Right Playback" , ES8323_DACPOWER, 6, 1), |
| 215 | SND_SOC_DAPM_DAC("Left DAC" , "Left Playback" , ES8323_DACPOWER, 7, 1), |
| 216 | |
| 217 | SND_SOC_DAPM_MIXER("Left Mixer" , SND_SOC_NOPM, 0, 0, |
| 218 | &es8323_left_mixer_controls[0], |
| 219 | ARRAY_SIZE(es8323_left_mixer_controls)), |
| 220 | SND_SOC_DAPM_MIXER("Right Mixer" , SND_SOC_NOPM, 0, 0, |
| 221 | &es8323_right_mixer_controls[0], |
| 222 | ARRAY_SIZE(es8323_right_mixer_controls)), |
| 223 | |
| 224 | SND_SOC_DAPM_PGA("Right ADC Power" , SND_SOC_NOPM, 6, 1, NULL, 0), |
| 225 | SND_SOC_DAPM_PGA("Left ADC Power" , SND_SOC_NOPM, 7, 1, NULL, 0), |
| 226 | SND_SOC_DAPM_PGA("Right Out 2" , ES8323_DACPOWER, 2, 0, NULL, 0), |
| 227 | SND_SOC_DAPM_PGA("Left Out 2" , ES8323_DACPOWER, 3, 0, NULL, 0), |
| 228 | SND_SOC_DAPM_PGA("Right Out 1" , ES8323_DACPOWER, 4, 0, NULL, 0), |
| 229 | SND_SOC_DAPM_PGA("Left Out 1" , ES8323_DACPOWER, 5, 0, NULL, 0), |
| 230 | SND_SOC_DAPM_PGA("LAMP" , ES8323_ADCCONTROL1, 4, 0, NULL, 0), |
| 231 | SND_SOC_DAPM_PGA("RAMP" , ES8323_ADCCONTROL1, 0, 0, NULL, 0), |
| 232 | |
| 233 | SND_SOC_DAPM_OUTPUT("LOUT1" ), |
| 234 | SND_SOC_DAPM_OUTPUT("ROUT1" ), |
| 235 | SND_SOC_DAPM_OUTPUT("LOUT2" ), |
| 236 | SND_SOC_DAPM_OUTPUT("ROUT2" ), |
| 237 | SND_SOC_DAPM_OUTPUT("VREF" ), |
| 238 | }; |
| 239 | |
| 240 | static const struct snd_soc_dapm_route es8323_dapm_routes[] = { |
| 241 | /*12.22*/ |
| 242 | {"Left PGA Mux" , "Line 1L" , "LINPUT1" }, |
| 243 | {"Left PGA Mux" , "Line 2L" , "LINPUT2" }, |
| 244 | {"Left PGA Mux" , "DifferentialL" , "Differential Mux" }, |
| 245 | |
| 246 | {"Right PGA Mux" , "Line 1R" , "RINPUT1" }, |
| 247 | {"Right PGA Mux" , "Line 2R" , "RINPUT2" }, |
| 248 | {"Right PGA Mux" , "DifferentialR" , "Differential Mux" }, |
| 249 | |
| 250 | {"Differential Mux" , "Line 1" , "LINPUT1" }, |
| 251 | {"Differential Mux" , "Line 1" , "RINPUT1" }, |
| 252 | {"Differential Mux" , "Line 2" , "LINPUT2" }, |
| 253 | {"Differential Mux" , "Line 2" , "RINPUT2" }, |
| 254 | |
| 255 | {"Left ADC Mux" , "Stereo" , "Right PGA Mux" }, |
| 256 | {"Left ADC Mux" , "Stereo" , "Left PGA Mux" }, |
| 257 | {"Left ADC Mux" , "Mono (Left)" , "Left PGA Mux" }, |
| 258 | |
| 259 | {"Right ADC Mux" , "Stereo" , "Left PGA Mux" }, |
| 260 | {"Right ADC Mux" , "Stereo" , "Right PGA Mux" }, |
| 261 | {"Right ADC Mux" , "Mono (Right)" , "Right PGA Mux" }, |
| 262 | |
| 263 | {"Left ADC Power" , NULL, "Left ADC Mux" }, |
| 264 | {"Right ADC Power" , NULL, "Right ADC Mux" }, |
| 265 | {"Left ADC" , NULL, "Left ADC Power" }, |
| 266 | {"Right ADC" , NULL, "Right ADC Power" }, |
| 267 | |
| 268 | {"Left Line Mux" , "Line 1L" , "LINPUT1" }, |
| 269 | {"Left Line Mux" , "Line 2L" , "LINPUT2" }, |
| 270 | {"Left Line Mux" , "MicL" , "Left PGA Mux" }, |
| 271 | |
| 272 | {"Right Line Mux" , "Line 1R" , "RINPUT1" }, |
| 273 | {"Right Line Mux" , "Line 2R" , "RINPUT2" }, |
| 274 | {"Right Line Mux" , "MicR" , "Right PGA Mux" }, |
| 275 | |
| 276 | {"Left Mixer" , "Left Playback Switch" , "Left DAC" }, |
| 277 | {"Left Mixer" , "Left Bypass Switch" , "Left Line Mux" }, |
| 278 | |
| 279 | {"Right Mixer" , "Right Playback Switch" , "Right DAC" }, |
| 280 | {"Right Mixer" , "Right Bypass Switch" , "Right Line Mux" }, |
| 281 | |
| 282 | {"Left Out 1" , NULL, "Left Mixer" }, |
| 283 | {"LOUT1" , NULL, "Left Out 1" }, |
| 284 | {"Right Out 1" , NULL, "Right Mixer" }, |
| 285 | {"ROUT1" , NULL, "Right Out 1" }, |
| 286 | |
| 287 | {"Left Out 2" , NULL, "Left Mixer" }, |
| 288 | {"LOUT2" , NULL, "Left Out 2" }, |
| 289 | {"Right Out 2" , NULL, "Right Mixer" }, |
| 290 | {"ROUT2" , NULL, "Right Out 2" }, |
| 291 | }; |
| 292 | |
| 293 | struct coeff_div { |
| 294 | u32 mclk; |
| 295 | u32 rate; |
| 296 | u16 fs; |
| 297 | u8 sr:4; |
| 298 | u8 usb:1; |
| 299 | }; |
| 300 | |
| 301 | /* codec hifi mclk clock divider coefficients */ |
| 302 | static const struct coeff_div es8323_coeff_div[] = { |
| 303 | /* 8k */ |
| 304 | {12288000, 8000, 1536, 0xa, 0x0}, |
| 305 | {11289600, 8000, 1408, 0x9, 0x0}, |
| 306 | {18432000, 8000, 2304, 0xc, 0x0}, |
| 307 | {16934400, 8000, 2112, 0xb, 0x0}, |
| 308 | {12000000, 8000, 1500, 0xb, 0x1}, |
| 309 | |
| 310 | /* 11.025k */ |
| 311 | {11289600, 11025, 1024, 0x7, 0x0}, |
| 312 | {16934400, 11025, 1536, 0xa, 0x0}, |
| 313 | {12000000, 11025, 1088, 0x9, 0x1}, |
| 314 | |
| 315 | /* 16k */ |
| 316 | {12288000, 16000, 768, 0x6, 0x0}, |
| 317 | {18432000, 16000, 1152, 0x8, 0x0}, |
| 318 | {12000000, 16000, 750, 0x7, 0x1}, |
| 319 | |
| 320 | /* 22.05k */ |
| 321 | {11289600, 22050, 512, 0x4, 0x0}, |
| 322 | {16934400, 22050, 768, 0x6, 0x0}, |
| 323 | {12000000, 22050, 544, 0x6, 0x1}, |
| 324 | |
| 325 | /* 32k */ |
| 326 | {12288000, 32000, 384, 0x3, 0x0}, |
| 327 | {18432000, 32000, 576, 0x5, 0x0}, |
| 328 | {12000000, 32000, 375, 0x4, 0x1}, |
| 329 | |
| 330 | /* 44.1k */ |
| 331 | {11289600, 44100, 256, 0x2, 0x0}, |
| 332 | {16934400, 44100, 384, 0x3, 0x0}, |
| 333 | {12000000, 44100, 272, 0x3, 0x1}, |
| 334 | |
| 335 | /* 48k */ |
| 336 | {12288000, 48000, 256, 0x2, 0x0}, |
| 337 | {18432000, 48000, 384, 0x3, 0x0}, |
| 338 | {12000000, 48000, 250, 0x2, 0x1}, |
| 339 | |
| 340 | /* 88.2k */ |
| 341 | {11289600, 88200, 128, 0x0, 0x0}, |
| 342 | {16934400, 88200, 192, 0x1, 0x0}, |
| 343 | {12000000, 88200, 136, 0x1, 0x1}, |
| 344 | |
| 345 | /* 96k */ |
| 346 | {12288000, 96000, 128, 0x0, 0x0}, |
| 347 | {18432000, 96000, 192, 0x1, 0x0}, |
| 348 | {12000000, 96000, 125, 0x0, 0x1}, |
| 349 | }; |
| 350 | |
| 351 | static unsigned int rates_12288[] = { |
| 352 | 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000, |
| 353 | }; |
| 354 | |
| 355 | static struct snd_pcm_hw_constraint_list constraints_12288 = { |
| 356 | .count = ARRAY_SIZE(rates_12288), |
| 357 | .list = rates_12288, |
| 358 | }; |
| 359 | |
| 360 | static unsigned int rates_112896[] = { |
| 361 | 8000, 11025, 22050, 44100, |
| 362 | }; |
| 363 | |
| 364 | static struct snd_pcm_hw_constraint_list constraints_112896 = { |
| 365 | .count = ARRAY_SIZE(rates_112896), |
| 366 | .list = rates_112896, |
| 367 | }; |
| 368 | |
| 369 | static unsigned int rates_12[] = { |
| 370 | 8000, 11025, 12000, 16000, 22050, 24000, |
| 371 | 32000, 44100, 48000, 48000, 88235, 96000, |
| 372 | }; |
| 373 | |
| 374 | static struct snd_pcm_hw_constraint_list constraints_12 = { |
| 375 | .count = ARRAY_SIZE(rates_12), |
| 376 | .list = rates_12, |
| 377 | }; |
| 378 | |
| 379 | static inline int get_coeff(int mclk, int rate) |
| 380 | { |
| 381 | int i; |
| 382 | |
| 383 | for (i = 0; i < ARRAY_SIZE(es8323_coeff_div); i++) { |
| 384 | if (es8323_coeff_div[i].rate == rate && |
| 385 | es8323_coeff_div[i].mclk == mclk) |
| 386 | return i; |
| 387 | } |
| 388 | |
| 389 | return -EINVAL; |
| 390 | } |
| 391 | |
| 392 | static int es8323_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
| 393 | int clk_id, unsigned int freq, int dir) |
| 394 | { |
| 395 | struct snd_soc_component *component = codec_dai->component; |
| 396 | struct es8323_priv *es8323 = snd_soc_component_get_drvdata(c: component); |
| 397 | |
| 398 | switch (freq) { |
| 399 | case 11289600: |
| 400 | case 18432000: |
| 401 | case 22579200: |
| 402 | case 36864000: |
| 403 | es8323->sysclk_constraints = &constraints_112896; |
| 404 | break; |
| 405 | case 12288000: |
| 406 | case 16934400: |
| 407 | case 24576000: |
| 408 | case 33868800: |
| 409 | es8323->sysclk_constraints = &constraints_12288; |
| 410 | break; |
| 411 | case 12000000: |
| 412 | case 24000000: |
| 413 | es8323->sysclk_constraints = &constraints_12; |
| 414 | break; |
| 415 | default: |
| 416 | return -EINVAL; |
| 417 | } |
| 418 | |
| 419 | es8323->sysclk = freq; |
| 420 | return 0; |
| 421 | } |
| 422 | |
| 423 | static int es8323_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) |
| 424 | { |
| 425 | struct snd_soc_component *component = codec_dai->component; |
| 426 | u8 iface = snd_soc_component_read(component, ES8323_MASTERMODE); |
| 427 | u8 adciface = snd_soc_component_read(component, ES8323_ADC_IFACE); |
| 428 | u8 daciface = snd_soc_component_read(component, ES8323_DAC_IFACE); |
| 429 | |
| 430 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
| 431 | case SND_SOC_DAIFMT_BC_FP: |
| 432 | iface |= 0x80; |
| 433 | break; |
| 434 | case SND_SOC_DAIFMT_BC_FC: |
| 435 | iface &= 0x7f; |
| 436 | break; |
| 437 | default: |
| 438 | return -EINVAL; |
| 439 | } |
| 440 | |
| 441 | /* interface format */ |
| 442 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
| 443 | case SND_SOC_DAIFMT_I2S: |
| 444 | adciface &= 0xfc; |
| 445 | daciface &= 0xf8; |
| 446 | break; |
| 447 | case SND_SOC_DAIFMT_LEFT_J: |
| 448 | adciface &= 0xfd; |
| 449 | daciface &= 0xf9; |
| 450 | break; |
| 451 | case SND_SOC_DAIFMT_RIGHT_J: |
| 452 | adciface &= 0xfe; |
| 453 | daciface &= 0xfa; |
| 454 | break; |
| 455 | case SND_SOC_DAIFMT_DSP_A: |
| 456 | case SND_SOC_DAIFMT_DSP_B: |
| 457 | adciface &= 0xff; |
| 458 | daciface &= 0xfb; |
| 459 | break; |
| 460 | default: |
| 461 | return -EINVAL; |
| 462 | } |
| 463 | |
| 464 | /* clock inversion */ |
| 465 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
| 466 | case SND_SOC_DAIFMT_NB_NF: |
| 467 | iface &= 0xdf; |
| 468 | adciface &= 0xdf; |
| 469 | daciface &= 0xbf; |
| 470 | break; |
| 471 | case SND_SOC_DAIFMT_IB_IF: |
| 472 | iface |= 0x20; |
| 473 | adciface |= 0x20; |
| 474 | daciface |= 0x40; |
| 475 | break; |
| 476 | case SND_SOC_DAIFMT_IB_NF: |
| 477 | iface |= 0x20; |
| 478 | adciface &= 0xdf; |
| 479 | daciface &= 0xbf; |
| 480 | break; |
| 481 | case SND_SOC_DAIFMT_NB_IF: |
| 482 | iface &= 0xdf; |
| 483 | adciface |= 0x20; |
| 484 | daciface |= 0x40; |
| 485 | break; |
| 486 | default: |
| 487 | return -EINVAL; |
| 488 | } |
| 489 | |
| 490 | snd_soc_component_write(component, ES8323_MASTERMODE, val: iface); |
| 491 | snd_soc_component_write(component, ES8323_ADC_IFACE, val: adciface); |
| 492 | snd_soc_component_write(component, ES8323_DAC_IFACE, val: daciface); |
| 493 | |
| 494 | return 0; |
| 495 | } |
| 496 | |
| 497 | static int es8323_pcm_startup(struct snd_pcm_substream *substream, |
| 498 | struct snd_soc_dai *dai) |
| 499 | { |
| 500 | struct snd_soc_component *component = dai->component; |
| 501 | struct es8323_priv *es8323 = snd_soc_component_get_drvdata(c: component); |
| 502 | |
| 503 | if (es8323->sysclk) { |
| 504 | snd_pcm_hw_constraint_list(runtime: substream->runtime, cond: 0, |
| 505 | SNDRV_PCM_HW_PARAM_RATE, |
| 506 | l: es8323->sysclk_constraints); |
| 507 | } |
| 508 | |
| 509 | return 0; |
| 510 | } |
| 511 | |
| 512 | static int es8323_pcm_hw_params(struct snd_pcm_substream *substream, |
| 513 | struct snd_pcm_hw_params *params, |
| 514 | struct snd_soc_dai *dai) |
| 515 | { |
| 516 | struct snd_soc_component *component = dai->component; |
| 517 | struct es8323_priv *es8323 = snd_soc_component_get_drvdata(c: component); |
| 518 | u16 srate = snd_soc_component_read(component, ES8323_MASTERMODE) & 0x80; |
| 519 | u16 adciface = snd_soc_component_read(component, ES8323_ADC_IFACE) & 0xe3; |
| 520 | u16 daciface = snd_soc_component_read(component, ES8323_DAC_IFACE) & 0xc7; |
| 521 | int coeff; |
| 522 | |
| 523 | coeff = get_coeff(mclk: es8323->sysclk, rate: params_rate(p: params)); |
| 524 | if (coeff < 0) { |
| 525 | coeff = get_coeff(mclk: es8323->sysclk / 2, rate: params_rate(p: params)); |
| 526 | srate |= 0x40; |
| 527 | } |
| 528 | |
| 529 | if (coeff < 0) { |
| 530 | dev_err(component->dev, |
| 531 | "Unable to configure sample rate %dHz with %dHz MCLK\n" , |
| 532 | params_rate(params), es8323->sysclk); |
| 533 | return coeff; |
| 534 | } |
| 535 | |
| 536 | /* bit size */ |
| 537 | switch (params_format(p: params)) { |
| 538 | case SNDRV_PCM_FORMAT_S16_LE: |
| 539 | adciface |= 0xc; |
| 540 | daciface |= 0x18; |
| 541 | break; |
| 542 | case SNDRV_PCM_FORMAT_S20_3LE: |
| 543 | adciface |= 0x4; |
| 544 | daciface |= 0x8; |
| 545 | break; |
| 546 | case SNDRV_PCM_FORMAT_S24_LE: |
| 547 | break; |
| 548 | case SNDRV_PCM_FORMAT_S32_LE: |
| 549 | adciface |= 0x10; |
| 550 | daciface |= 0x20; |
| 551 | break; |
| 552 | } |
| 553 | |
| 554 | snd_soc_component_write(component, ES8323_DAC_IFACE, val: daciface); |
| 555 | snd_soc_component_write(component, ES8323_ADC_IFACE, val: adciface); |
| 556 | |
| 557 | snd_soc_component_write(component, ES8323_MASTERMODE, val: srate); |
| 558 | snd_soc_component_write(component, ES8323_ADCCONTROL5, |
| 559 | val: es8323_coeff_div[coeff].sr | |
| 560 | (es8323_coeff_div[coeff].usb) << 4); |
| 561 | snd_soc_component_write(component, ES8323_DACCONTROL2, |
| 562 | val: es8323_coeff_div[coeff].sr | |
| 563 | (es8323_coeff_div[coeff].usb) << 4); |
| 564 | |
| 565 | snd_soc_component_write(component, ES8323_DACPOWER, val: 0x3c); |
| 566 | |
| 567 | return 0; |
| 568 | } |
| 569 | |
| 570 | static int es8323_mute_stream(struct snd_soc_dai *dai, int mute, int stream) |
| 571 | { |
| 572 | struct snd_soc_component *component = dai->component; |
| 573 | u32 val = mute ? 0x6 : 0x2; |
| 574 | |
| 575 | snd_soc_component_write(component, ES8323_DAC_MUTE, val); |
| 576 | |
| 577 | return 0; |
| 578 | } |
| 579 | |
| 580 | static const struct snd_soc_dai_ops es8323_ops = { |
| 581 | .startup = es8323_pcm_startup, |
| 582 | .hw_params = es8323_pcm_hw_params, |
| 583 | .set_fmt = es8323_set_dai_fmt, |
| 584 | .set_sysclk = es8323_set_dai_sysclk, |
| 585 | .mute_stream = es8323_mute_stream, |
| 586 | }; |
| 587 | |
| 588 | #define ES8323_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
| 589 | SNDRV_PCM_FMTBIT_S24_LE) |
| 590 | |
| 591 | static struct snd_soc_dai_driver es8323_dai = { |
| 592 | .name = "ES8323 HiFi" , |
| 593 | .playback = { |
| 594 | .stream_name = "Playback" , |
| 595 | .channels_min = 1, |
| 596 | .channels_max = 2, |
| 597 | .rates = SNDRV_PCM_RATE_8000_96000, |
| 598 | .formats = ES8323_FORMATS, |
| 599 | }, |
| 600 | .capture = { |
| 601 | .stream_name = "Capture" , |
| 602 | .channels_min = 1, |
| 603 | .channels_max = 2, |
| 604 | .rates = SNDRV_PCM_RATE_8000_96000, |
| 605 | .formats = ES8323_FORMATS, |
| 606 | }, |
| 607 | .ops = &es8323_ops, |
| 608 | .symmetric_rate = 1, |
| 609 | }; |
| 610 | |
| 611 | static int es8323_probe(struct snd_soc_component *component) |
| 612 | { |
| 613 | struct es8323_priv *es8323 = snd_soc_component_get_drvdata(c: component); |
| 614 | int ret; |
| 615 | |
| 616 | es8323->component = component; |
| 617 | |
| 618 | es8323->mclk = devm_clk_get_optional(dev: component->dev, id: "mclk" ); |
| 619 | if (IS_ERR(ptr: es8323->mclk)) { |
| 620 | dev_err(component->dev, "unable to get mclk\n" ); |
| 621 | return PTR_ERR(ptr: es8323->mclk); |
| 622 | } |
| 623 | |
| 624 | if (!es8323->mclk) |
| 625 | dev_warn(component->dev, "assuming static mclk\n" ); |
| 626 | |
| 627 | ret = clk_prepare_enable(clk: es8323->mclk); |
| 628 | if (ret) { |
| 629 | dev_err(component->dev, "unable to enable mclk\n" ); |
| 630 | return ret; |
| 631 | } |
| 632 | |
| 633 | snd_soc_component_write(component, ES8323_CONTROL2, val: 0x60); |
| 634 | snd_soc_component_write(component, ES8323_CHIPPOWER, val: 0x00); |
| 635 | |
| 636 | return 0; |
| 637 | } |
| 638 | |
| 639 | static int es8323_set_bias_level(struct snd_soc_component *component, |
| 640 | enum snd_soc_bias_level level) |
| 641 | { |
| 642 | struct es8323_priv *es8323 = snd_soc_component_get_drvdata(c: component); |
| 643 | int ret; |
| 644 | |
| 645 | switch (level) { |
| 646 | case SND_SOC_BIAS_ON: |
| 647 | ret = clk_prepare_enable(clk: es8323->mclk); |
| 648 | if (ret) |
| 649 | return ret; |
| 650 | |
| 651 | snd_soc_component_write(component, ES8323_CHIPPOWER, val: 0xf0); |
| 652 | usleep_range(min: 18000, max: 20000); |
| 653 | snd_soc_component_write(component, ES8323_DACPOWER, val: 0x3c); |
| 654 | snd_soc_component_write(component, ES8323_ANAVOLMANAG, val: 0x7c); |
| 655 | snd_soc_component_write(component, ES8323_CHIPLOPOW1, val: 0x00); |
| 656 | snd_soc_component_write(component, ES8323_CHIPLOPOW2, val: 0x00); |
| 657 | snd_soc_component_write(component, ES8323_CHIPPOWER, val: 0x00); |
| 658 | snd_soc_component_write(component, ES8323_ADCPOWER, val: 0x09); |
| 659 | snd_soc_component_write(component, ES8323_ADCCONTROL14, val: 0x00); |
| 660 | break; |
| 661 | case SND_SOC_BIAS_PREPARE: |
| 662 | break; |
| 663 | case SND_SOC_BIAS_STANDBY: |
| 664 | snd_soc_component_write(component, ES8323_ANAVOLMANAG, val: 0x7c); |
| 665 | snd_soc_component_write(component, ES8323_CHIPLOPOW1, val: 0x00); |
| 666 | snd_soc_component_write(component, ES8323_CHIPLOPOW2, val: 0x00); |
| 667 | snd_soc_component_write(component, ES8323_CHIPPOWER, val: 0x00); |
| 668 | snd_soc_component_write(component, ES8323_ADCPOWER, val: 0x59); |
| 669 | break; |
| 670 | case SND_SOC_BIAS_OFF: |
| 671 | clk_disable_unprepare(clk: es8323->mclk); |
| 672 | snd_soc_component_write(component, ES8323_ADCPOWER, val: 0xff); |
| 673 | snd_soc_component_write(component, ES8323_DACPOWER, val: 0xC0); |
| 674 | snd_soc_component_write(component, ES8323_CHIPLOPOW1, val: 0xff); |
| 675 | snd_soc_component_write(component, ES8323_CHIPLOPOW2, val: 0xff); |
| 676 | snd_soc_component_write(component, ES8323_CHIPPOWER, val: 0xff); |
| 677 | snd_soc_component_write(component, ES8323_ANAVOLMANAG, val: 0x7b); |
| 678 | break; |
| 679 | } |
| 680 | |
| 681 | return 0; |
| 682 | } |
| 683 | |
| 684 | static void es8323_remove(struct snd_soc_component *component) |
| 685 | { |
| 686 | struct es8323_priv *es8323 = snd_soc_component_get_drvdata(c: component); |
| 687 | |
| 688 | clk_disable_unprepare(clk: es8323->mclk); |
| 689 | es8323_set_bias_level(component, level: SND_SOC_BIAS_OFF); |
| 690 | } |
| 691 | |
| 692 | static int es8323_suspend(struct snd_soc_component *component) |
| 693 | { |
| 694 | struct es8323_priv *es8323 = snd_soc_component_get_drvdata(c: component); |
| 695 | |
| 696 | regcache_cache_only(map: es8323->regmap, enable: true); |
| 697 | regcache_mark_dirty(map: es8323->regmap); |
| 698 | |
| 699 | return 0; |
| 700 | } |
| 701 | |
| 702 | static int es8323_resume(struct snd_soc_component *component) |
| 703 | { |
| 704 | struct es8323_priv *es8323 = snd_soc_component_get_drvdata(c: component); |
| 705 | |
| 706 | regcache_cache_only(map: es8323->regmap, enable: false); |
| 707 | regcache_sync(map: es8323->regmap); |
| 708 | |
| 709 | return 0; |
| 710 | } |
| 711 | |
| 712 | static const struct snd_soc_component_driver soc_component_dev_es8323 = { |
| 713 | .probe = es8323_probe, |
| 714 | .remove = es8323_remove, |
| 715 | .suspend = es8323_suspend, |
| 716 | .resume = es8323_resume, |
| 717 | .set_bias_level = es8323_set_bias_level, |
| 718 | .controls = es8323_snd_controls, |
| 719 | .num_controls = ARRAY_SIZE(es8323_snd_controls), |
| 720 | .dapm_widgets = es8323_dapm_widgets, |
| 721 | .num_dapm_widgets = ARRAY_SIZE(es8323_dapm_widgets), |
| 722 | .dapm_routes = es8323_dapm_routes, |
| 723 | .num_dapm_routes = ARRAY_SIZE(es8323_dapm_routes), |
| 724 | .use_pmdown_time = 1, |
| 725 | .endianness = 1, |
| 726 | }; |
| 727 | |
| 728 | static const struct regmap_config es8323_regmap = { |
| 729 | .reg_bits = 8, |
| 730 | .val_bits = 8, |
| 731 | .use_single_read = true, |
| 732 | .use_single_write = true, |
| 733 | .max_register = 0x53, |
| 734 | .reg_defaults = es8323_reg_defaults, |
| 735 | .num_reg_defaults = ARRAY_SIZE(es8323_reg_defaults), |
| 736 | .cache_type = REGCACHE_MAPLE, |
| 737 | }; |
| 738 | |
| 739 | static int es8323_i2c_probe(struct i2c_client *i2c_client) |
| 740 | { |
| 741 | struct es8323_priv *es8323; |
| 742 | struct device *dev = &i2c_client->dev; |
| 743 | |
| 744 | es8323 = devm_kzalloc(dev, size: sizeof(*es8323), GFP_KERNEL); |
| 745 | if (!es8323) |
| 746 | return -ENOMEM; |
| 747 | |
| 748 | i2c_set_clientdata(client: i2c_client, data: es8323); |
| 749 | |
| 750 | es8323->regmap = devm_regmap_init_i2c(i2c_client, &es8323_regmap); |
| 751 | if (IS_ERR(ptr: es8323->regmap)) |
| 752 | return PTR_ERR(ptr: es8323->regmap); |
| 753 | |
| 754 | return devm_snd_soc_register_component(dev, |
| 755 | component_driver: &soc_component_dev_es8323, |
| 756 | dai_drv: &es8323_dai, num_dai: 1); |
| 757 | } |
| 758 | |
| 759 | static const struct i2c_device_id es8323_i2c_id[] = { |
| 760 | { "es8323" }, |
| 761 | { } |
| 762 | }; |
| 763 | MODULE_DEVICE_TABLE(i2c, es8323_i2c_id); |
| 764 | |
| 765 | static const struct acpi_device_id es8323_acpi_match[] = { |
| 766 | { "ESSX8323" , 0 }, |
| 767 | { } |
| 768 | }; |
| 769 | MODULE_DEVICE_TABLE(acpi, es8323_acpi_match); |
| 770 | |
| 771 | static const struct of_device_id es8323_of_match[] = { |
| 772 | { .compatible = "everest,es8323" }, |
| 773 | { } |
| 774 | }; |
| 775 | MODULE_DEVICE_TABLE(of, es8323_of_match); |
| 776 | |
| 777 | static struct i2c_driver es8323_i2c_driver = { |
| 778 | .driver = { |
| 779 | .name = "ES8323" , |
| 780 | .acpi_match_table = es8323_acpi_match, |
| 781 | .of_match_table = es8323_of_match, |
| 782 | }, |
| 783 | .probe = es8323_i2c_probe, |
| 784 | .id_table = es8323_i2c_id, |
| 785 | }; |
| 786 | module_i2c_driver(es8323_i2c_driver); |
| 787 | |
| 788 | MODULE_DESCRIPTION("Everest Semi ES8323 ALSA SoC Codec Driver" ); |
| 789 | MODULE_AUTHOR("Mark Brown <broonie@kernel.org>" ); |
| 790 | MODULE_AUTHOR("Binbin Zhou <zhoubinbin@loongson.cn>" ); |
| 791 | MODULE_LICENSE("GPL" ); |
| 792 | |