Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: Add ak4619 codec support

Add support for the Asahi Kasei AK4619 audio codec.

[Kuninori cleanuped and adjusted to upstream code]

Signed-off-by: Khanh Le <khanh.le.xr@renesas.com>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://msgid.link/r/87iky5wxvr.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Khanh Le and committed by
Mark Brown
ca73d314 9f774c75

+919
+5
sound/soc/codecs/Kconfig
··· 45 45 imply SND_SOC_AK4535 46 46 imply SND_SOC_AK4554 47 47 imply SND_SOC_AK4613 48 + imply SND_SOC_AK4619 48 49 imply SND_SOC_AK4641 49 50 imply SND_SOC_AK4642 50 51 imply SND_SOC_AK4671 ··· 598 597 config SND_SOC_AK4613 599 598 tristate "AKM AK4613 CODEC" 600 599 depends on I2C 600 + 601 + config SND_SOC_AK4619 602 + tristate "AKM AK4619 CODEC" 603 + depends on I2C 601 604 602 605 config SND_SOC_AK4641 603 606 tristate
+2
sound/soc/codecs/Makefile
··· 39 39 snd-soc-ak4535-y := ak4535.o 40 40 snd-soc-ak4554-y := ak4554.o 41 41 snd-soc-ak4613-y := ak4613.o 42 + snd-soc-ak4619-y := ak4619.o 42 43 snd-soc-ak4641-y := ak4641.o 43 44 snd-soc-ak4642-y := ak4642.o 44 45 snd-soc-ak4671-y := ak4671.o ··· 440 439 obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o 441 440 obj-$(CONFIG_SND_SOC_AK4554) += snd-soc-ak4554.o 442 441 obj-$(CONFIG_SND_SOC_AK4613) += snd-soc-ak4613.o 442 + obj-$(CONFIG_SND_SOC_AK4619) += snd-soc-ak4619.o 443 443 obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o 444 444 obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o 445 445 obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
+912
sound/soc/codecs/ak4619.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * ak4619.c -- Asahi Kasei ALSA SoC Audio driver 4 + * 5 + * Copyright (C) 2023 Renesas Electronics Corporation 6 + * Khanh Le <khanh.le.xr@renesas.com> 7 + * 8 + * Based on ak4613.c by Kuninori Morimoto 9 + * Based on da7213.c by Adam Thomson 10 + * Based on ak4641.c by Harald Welte 11 + */ 12 + 13 + #include <linux/clk.h> 14 + #include <linux/gpio/consumer.h> 15 + #include <linux/i2c.h> 16 + #include <linux/slab.h> 17 + #include <linux/of_device.h> 18 + #include <linux/module.h> 19 + #include <linux/regmap.h> 20 + #include <sound/soc.h> 21 + #include <sound/pcm.h> 22 + #include <sound/pcm_params.h> 23 + #include <sound/tlv.h> 24 + 25 + /* 26 + * Registers 27 + */ 28 + 29 + #define PWR_MGMT 0x00 /* Power Management */ 30 + #define AU_IFF1 0x01 /* Audio I/F Format */ 31 + #define AU_IFF2 0x02 /* Audio I/F Format (Extended) */ 32 + #define SYS_CLK 0x03 /* System Clock Setting */ 33 + #define MIC_AMP1 0x04 /* MIC AMP Gain 1 */ 34 + #define MIC_AMP2 0x05 /* MIC AMP Gain 2 */ 35 + #define LADC1 0x06 /* ADC1 Lch Digital Volume */ 36 + #define RADC1 0x07 /* ADC1 Rch Digital Volume */ 37 + #define LADC2 0x08 /* ADC2 Lch Digital Volume */ 38 + #define RADC2 0x09 /* ADC2 Rch Digital Volume */ 39 + #define ADC_DF 0x0a /* ADC Digital Filter Setting */ 40 + #define ADC_AI 0x0b /* ADC Analog Input Setting */ 41 + #define ADC_MHPF 0x0D /* ADC Mute & HPF Control */ 42 + #define LDAC1 0x0E /* DAC1 Lch Digital Volume */ 43 + #define RDAC1 0x0F /* DAC1 Rch Digital Volume */ 44 + #define LDAC2 0x10 /* DAC2 Lch Digital Volume */ 45 + #define RDAC2 0x11 /* DAC2 Rch Digital Volume */ 46 + #define DAC_IS 0x12 /* DAC Input Select Setting */ 47 + #define DAC_DEMP 0x13 /* DAC De-Emphasis Setting */ 48 + #define DAC_MF 0x14 /* DAC Mute & Filter Setting */ 49 + 50 + /* 51 + * Bit fields 52 + */ 53 + 54 + /* Power Management */ 55 + #define PMAD2 BIT(5) 56 + #define PMAD1 BIT(4) 57 + #define PMDA2 BIT(2) 58 + #define PMDA1 BIT(1) 59 + #define RSTN BIT(0) 60 + 61 + /* Audio_I/F Format */ 62 + #define DCF_STEREO_I2S (0x0 << 4) 63 + #define DCF_STEREO_MSB (0x5 << 4) 64 + #define DCF_PCM_SF (0x6 << 4) 65 + #define DCF_PCM_LF (0x7 << 4) 66 + #define DSL_32 (0x3 << 2) 67 + #define DCF_MASK (0x7 << 4) 68 + #define DSL_MASK (0x3 << 2) 69 + #define BCKP BIT(1) 70 + 71 + /* Audio_I/F Format (Extended) */ 72 + #define DIDL_24 (0x0 << 2) 73 + #define DIDL_20 (0x1 << 2) 74 + #define DIDL_16 (0x2 << 2) 75 + #define DIDL_32 (0x3 << 2) 76 + #define DODL_24 (0x0 << 0) 77 + #define DODL_20 (0x1 << 0) 78 + #define DODL_16 (0x2 << 0) 79 + #define DIDL_MASK (0x3 << 2) 80 + #define DODL_MASK (0x3 << 0) 81 + #define SLOT BIT(4) 82 + 83 + /* System Clock Setting */ 84 + #define FS_MASK 0x7 85 + 86 + /* MIC AMP Gain */ 87 + #define MGNL_SHIFT 4 88 + #define MGNR_SHIFT 0 89 + #define MGN_MAX 0xB 90 + 91 + /* ADC Digital Volume */ 92 + #define VOLAD_SHIFT 0 93 + #define VOLAD_MAX 0xFF 94 + 95 + /* ADC Digital Filter Setting */ 96 + #define AD1SL_SHIFT 0 97 + #define AD2SL_SHIFT 4 98 + 99 + /* Analog Input Select */ 100 + #define AD1LSEL_SHIFT 6 101 + #define AD1RSEL_SHIFT 4 102 + #define AD2LSEL_SHIFT 2 103 + #define AD2RSEL_SHIFT 0 104 + 105 + /* ADC Mute & HPF Control */ 106 + #define ATSPAD_SHIFT 7 107 + #define AD1MUTE_SHIFT 5 108 + #define AD2MUTE_SHIFT 6 109 + #define AD1MUTE_MAX 1 110 + #define AD2MUTE_MAX 1 111 + #define AD1MUTE_EN BIT(5) 112 + #define AD2MUTE_EN BIT(6) 113 + #define AD1HPFN_SHIFT 1 114 + #define AD1HPFN_MAX 1 115 + #define AD2HPFN_SHIFT 2 116 + #define AD2HPFN_MAX 1 117 + 118 + /* DAC Digital Volume */ 119 + #define VOLDA_SHIFT 0 120 + #define VOLDA_MAX 0xFF 121 + 122 + /* DAC Input Select Setting */ 123 + #define DAC1SEL_SHIFT 0 124 + #define DAC2SEL_SHIFT 2 125 + 126 + /* DAC De-Emphasis Setting */ 127 + #define DEM1_32000 (0x3 << 0) 128 + #define DEM1_44100 (0x0 << 0) 129 + #define DEM1_48000 (0x2 << 0) 130 + #define DEM1_OFF (0x1 << 0) 131 + #define DEM2_32000 (0x3 << 2) 132 + #define DEM2_44100 (0x0 << 2) 133 + #define DEM2_48000 (0x2 << 2) 134 + #define DEM2_OFF (0x1 << 2) 135 + #define DEM1_MASK (0x3 << 0) 136 + #define DEM2_MASK (0x3 << 2) 137 + #define DEM1_SHIFT 0 138 + #define DEM2_SHIFT 2 139 + 140 + /* DAC Mute & Filter Setting */ 141 + #define DA1MUTE_SHIFT 4 142 + #define DA1MUTE_MAX 1 143 + #define DA2MUTE_SHIFT 5 144 + #define DA2MUTE_MAX 1 145 + #define DA1MUTE_EN BIT(4) 146 + #define DA2MUTE_EN BIT(5) 147 + #define ATSPDA_SHIFT 7 148 + #define DA1SL_SHIFT 0 149 + #define DA2SL_SHIFT 2 150 + 151 + /* Codec private data */ 152 + struct ak4619_priv { 153 + struct regmap *regmap; 154 + struct snd_pcm_hw_constraint_list constraint; 155 + int deemph_en; 156 + unsigned int playback_rate; 157 + unsigned int sysclk; 158 + }; 159 + 160 + /* 161 + * DAC Volume 162 + * 163 + * max : 0x00 : +12.0 dB 164 + * ( 0.5 dB step ) 165 + * min : 0xFE : -115.0 dB 166 + * mute: 0xFF 167 + */ 168 + static const DECLARE_TLV_DB_SCALE(dac_tlv, -11550, 50, 1); 169 + 170 + /* 171 + * MIC Volume 172 + * 173 + * max : 0x0B : +27.0 dB 174 + * ( 3 dB step ) 175 + * min: 0x00 : -6.0 dB 176 + */ 177 + static const DECLARE_TLV_DB_SCALE(mic_tlv, -600, 300, 0); 178 + 179 + /* 180 + * ADC Volume 181 + * 182 + * max : 0x00 : +24.0 dB 183 + * ( 0.5 dB step ) 184 + * min : 0xFE : -103.0 dB 185 + * mute: 0xFF 186 + */ 187 + static const DECLARE_TLV_DB_SCALE(adc_tlv, -10350, 50, 1); 188 + 189 + /* ADC & DAC Volume Level Transition Time select */ 190 + static const char * const ak4619_vol_trans_txt[] = { 191 + "4/fs", "16/fs" 192 + }; 193 + 194 + static SOC_ENUM_SINGLE_DECL(ak4619_adc_vol_trans, ADC_MHPF, ATSPAD_SHIFT, ak4619_vol_trans_txt); 195 + static SOC_ENUM_SINGLE_DECL(ak4619_dac_vol_trans, DAC_MF, ATSPDA_SHIFT, ak4619_vol_trans_txt); 196 + 197 + /* ADC Digital Filter select */ 198 + static const char * const ak4619_adc_digi_fil_txt[] = { 199 + "Sharp Roll-Off Filter", 200 + "Slow Roll-Off Filter", 201 + "Short Delay Sharp Roll-Off Filter", 202 + "Short Delay Slow Roll-Off Filter", 203 + "Voice Filter" 204 + }; 205 + 206 + static SOC_ENUM_SINGLE_DECL(ak4619_adc_1_digi_fil, ADC_DF, AD1SL_SHIFT, ak4619_adc_digi_fil_txt); 207 + static SOC_ENUM_SINGLE_DECL(ak4619_adc_2_digi_fil, ADC_DF, AD2SL_SHIFT, ak4619_adc_digi_fil_txt); 208 + 209 + /* DAC De-Emphasis Filter select */ 210 + static const char * const ak4619_dac_de_emp_txt[] = { 211 + "44.1kHz", "OFF", "48kHz", "32kHz" 212 + }; 213 + 214 + static SOC_ENUM_SINGLE_DECL(ak4619_dac_1_de_emp, DAC_DEMP, DEM1_SHIFT, ak4619_dac_de_emp_txt); 215 + static SOC_ENUM_SINGLE_DECL(ak4619_dac_2_de_emp, DAC_DEMP, DEM2_SHIFT, ak4619_dac_de_emp_txt); 216 + 217 + /* DAC Digital Filter select */ 218 + static const char * const ak4619_dac_digi_fil_txt[] = { 219 + "Sharp Roll-Off Filter", 220 + "Slow Roll-Off Filter", 221 + "Short Delay Sharp Roll-Off Filter", 222 + "Short Delay Slow Roll-Off Filter" 223 + }; 224 + 225 + static SOC_ENUM_SINGLE_DECL(ak4619_dac_1_digi_fil, DAC_MF, DA1SL_SHIFT, ak4619_dac_digi_fil_txt); 226 + static SOC_ENUM_SINGLE_DECL(ak4619_dac_2_digi_fil, DAC_MF, DA2SL_SHIFT, ak4619_dac_digi_fil_txt); 227 + 228 + /* 229 + * Control functions 230 + */ 231 + 232 + static void ak4619_set_deemph(struct snd_soc_component *component) 233 + { 234 + struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component); 235 + u8 dem = 0; 236 + 237 + if (!ak4619->deemph_en) 238 + return; 239 + 240 + switch (ak4619->playback_rate) { 241 + case 32000: 242 + dem |= DEM1_32000 | DEM2_32000; 243 + break; 244 + case 44100: 245 + dem |= DEM1_44100 | DEM2_44100; 246 + break; 247 + case 48000: 248 + dem |= DEM1_48000 | DEM2_48000; 249 + break; 250 + default: 251 + dem |= DEM1_OFF | DEM2_OFF; 252 + break; 253 + } 254 + snd_soc_component_update_bits(component, DAC_DEMP, DEM1_MASK | DEM2_MASK, dem); 255 + } 256 + 257 + static int ak4619_put_deemph(struct snd_kcontrol *kcontrol, 258 + struct snd_ctl_elem_value *ucontrol) 259 + { 260 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 261 + struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component); 262 + int deemph_en = ucontrol->value.integer.value[0]; 263 + int ret = 0; 264 + 265 + switch (deemph_en) { 266 + case 0: 267 + case 1: 268 + break; 269 + default: 270 + return -EINVAL; 271 + } 272 + 273 + if (ak4619->deemph_en != deemph_en) 274 + ret = 1; /* The value changed */ 275 + 276 + ak4619->deemph_en = deemph_en; 277 + ak4619_set_deemph(component); 278 + 279 + return ret; 280 + } 281 + 282 + static int ak4619_get_deemph(struct snd_kcontrol *kcontrol, 283 + struct snd_ctl_elem_value *ucontrol) 284 + { 285 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 286 + struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component); 287 + 288 + ucontrol->value.integer.value[0] = ak4619->deemph_en; 289 + 290 + return 0; 291 + }; 292 + 293 + /* 294 + * KControls 295 + */ 296 + static const struct snd_kcontrol_new ak4619_snd_controls[] = { 297 + 298 + /* Volume controls */ 299 + SOC_DOUBLE_R_TLV("DAC 1 Volume", LDAC1, RDAC1, VOLDA_SHIFT, VOLDA_MAX, 1, dac_tlv), 300 + SOC_DOUBLE_R_TLV("DAC 2 Volume", LDAC2, RDAC2, VOLDA_SHIFT, VOLDA_MAX, 1, dac_tlv), 301 + SOC_DOUBLE_R_TLV("ADC 1 Volume", LADC1, RADC1, VOLAD_SHIFT, VOLAD_MAX, 1, adc_tlv), 302 + SOC_DOUBLE_R_TLV("ADC 2 Volume", LADC2, RADC2, VOLAD_SHIFT, VOLAD_MAX, 1, adc_tlv), 303 + 304 + SOC_DOUBLE_TLV("Mic 1 Volume", MIC_AMP1, MGNL_SHIFT, MGNR_SHIFT, MGN_MAX, 0, mic_tlv), 305 + SOC_DOUBLE_TLV("Mic 2 Volume", MIC_AMP2, MGNL_SHIFT, MGNR_SHIFT, MGN_MAX, 0, mic_tlv), 306 + 307 + /* Volume Level Transition Time controls */ 308 + SOC_ENUM("ADC Volume Level Transition Time", ak4619_adc_vol_trans), 309 + SOC_ENUM("DAC Volume Level Transition Time", ak4619_dac_vol_trans), 310 + 311 + /* Mute controls */ 312 + SOC_SINGLE("DAC 1 Switch", DAC_MF, DA1MUTE_SHIFT, DA1MUTE_MAX, 1), 313 + SOC_SINGLE("DAC 2 Switch", DAC_MF, DA2MUTE_SHIFT, DA2MUTE_MAX, 1), 314 + 315 + SOC_SINGLE("ADC 1 Switch", ADC_MHPF, AD1MUTE_SHIFT, AD1MUTE_MAX, 1), 316 + SOC_SINGLE("ADC 2 Switch", ADC_MHPF, AD2MUTE_SHIFT, AD2MUTE_MAX, 1), 317 + 318 + /* Filter controls */ 319 + SOC_ENUM("ADC 1 Digital Filter", ak4619_adc_1_digi_fil), 320 + SOC_ENUM("ADC 2 Digital Filter", ak4619_adc_2_digi_fil), 321 + 322 + SOC_SINGLE("ADC 1 HPF", ADC_MHPF, AD1HPFN_SHIFT, AD1HPFN_MAX, 1), 323 + SOC_SINGLE("ADC 2 HPF", ADC_MHPF, AD2HPFN_SHIFT, AD2HPFN_MAX, 1), 324 + 325 + SOC_ENUM("DAC 1 De-Emphasis Filter", ak4619_dac_1_de_emp), 326 + SOC_ENUM("DAC 2 De-Emphasis Filter", ak4619_dac_2_de_emp), 327 + 328 + SOC_ENUM("DAC 1 Digital Filter", ak4619_dac_1_digi_fil), 329 + SOC_ENUM("DAC 2 Digital Filter", ak4619_dac_2_digi_fil), 330 + 331 + SOC_SINGLE_BOOL_EXT("Playback De-Emphasis Switch", 0, ak4619_get_deemph, ak4619_put_deemph), 332 + }; 333 + 334 + /* 335 + * DAPM 336 + */ 337 + 338 + /* Analog input mode */ 339 + static const char * const ak4619_analog_in_txt[] = { 340 + "Differential", "Single-Ended1", "Single-Ended2", "Pseudo Differential" 341 + }; 342 + 343 + static SOC_ENUM_SINGLE_DECL(ak4619_ad_1_left_in, ADC_AI, AD1LSEL_SHIFT, ak4619_analog_in_txt); 344 + static SOC_ENUM_SINGLE_DECL(ak4619_ad_1_right_in, ADC_AI, AD1RSEL_SHIFT, ak4619_analog_in_txt); 345 + static SOC_ENUM_SINGLE_DECL(ak4619_ad_2_left_in, ADC_AI, AD2LSEL_SHIFT, ak4619_analog_in_txt); 346 + static SOC_ENUM_SINGLE_DECL(ak4619_ad_2_right_in, ADC_AI, AD2RSEL_SHIFT, ak4619_analog_in_txt); 347 + 348 + static const struct snd_kcontrol_new ak4619_ad_1_left_in_mux = 349 + SOC_DAPM_ENUM("Analog Input 1 Left MUX", ak4619_ad_1_left_in); 350 + static const struct snd_kcontrol_new ak4619_ad_1_right_in_mux = 351 + SOC_DAPM_ENUM("Analog Input 1 Right MUX", ak4619_ad_1_right_in); 352 + static const struct snd_kcontrol_new ak4619_ad_2_left_in_mux = 353 + SOC_DAPM_ENUM("Analog Input 2 Left MUX", ak4619_ad_2_left_in); 354 + static const struct snd_kcontrol_new ak4619_ad_2_right_in_mux = 355 + SOC_DAPM_ENUM("Analog Input 2 Right MUX", ak4619_ad_2_right_in); 356 + 357 + /* DAC source mux */ 358 + static const char * const ak4619_dac_in_txt[] = { 359 + "SDIN1", "SDIN2", "SDOUT1", "SDOUT2" 360 + }; 361 + 362 + static SOC_ENUM_SINGLE_DECL(ak4619_dac_1_in, DAC_IS, DAC1SEL_SHIFT, ak4619_dac_in_txt); 363 + static SOC_ENUM_SINGLE_DECL(ak4619_dac_2_in, DAC_IS, DAC2SEL_SHIFT, ak4619_dac_in_txt); 364 + 365 + static const struct snd_kcontrol_new ak4619_dac_1_in_mux = 366 + SOC_DAPM_ENUM("DAC 1 Source MUX", ak4619_dac_1_in); 367 + static const struct snd_kcontrol_new ak4619_dac_2_in_mux = 368 + SOC_DAPM_ENUM("DAC 2 Source MUX", ak4619_dac_2_in); 369 + 370 + static const struct snd_soc_dapm_widget ak4619_dapm_widgets[] = { 371 + 372 + /* DACs */ 373 + SND_SOC_DAPM_DAC("DAC1", NULL, PWR_MGMT, 1, 0), 374 + SND_SOC_DAPM_DAC("DAC2", NULL, PWR_MGMT, 2, 0), 375 + 376 + /* ADCs */ 377 + SND_SOC_DAPM_ADC("ADC1", NULL, PWR_MGMT, 4, 0), 378 + SND_SOC_DAPM_ADC("ADC2", NULL, PWR_MGMT, 5, 0), 379 + 380 + /* Outputs */ 381 + SND_SOC_DAPM_OUTPUT("AOUT1L"), 382 + SND_SOC_DAPM_OUTPUT("AOUT2L"), 383 + 384 + SND_SOC_DAPM_OUTPUT("AOUT1R"), 385 + SND_SOC_DAPM_OUTPUT("AOUT2R"), 386 + 387 + /* Inputs */ 388 + SND_SOC_DAPM_INPUT("AIN1L"), 389 + SND_SOC_DAPM_INPUT("AIN2L"), 390 + SND_SOC_DAPM_INPUT("AIN4L"), 391 + SND_SOC_DAPM_INPUT("AIN5L"), 392 + 393 + SND_SOC_DAPM_INPUT("AIN1R"), 394 + SND_SOC_DAPM_INPUT("AIN2R"), 395 + SND_SOC_DAPM_INPUT("AIN4R"), 396 + SND_SOC_DAPM_INPUT("AIN5R"), 397 + 398 + SND_SOC_DAPM_INPUT("MIC1L"), 399 + SND_SOC_DAPM_INPUT("MIC1R"), 400 + SND_SOC_DAPM_INPUT("MIC2L"), 401 + SND_SOC_DAPM_INPUT("MIC2R"), 402 + 403 + /* DAI */ 404 + SND_SOC_DAPM_AIF_IN("SDIN1", "Playback", 0, SND_SOC_NOPM, 0, 0), 405 + SND_SOC_DAPM_AIF_IN("SDIN2", "Playback", 0, SND_SOC_NOPM, 0, 0), 406 + SND_SOC_DAPM_AIF_OUT("SDOUT1", "Capture", 0, SND_SOC_NOPM, 0, 0), 407 + SND_SOC_DAPM_AIF_OUT("SDOUT2", "Capture", 0, SND_SOC_NOPM, 0, 0), 408 + 409 + /* MUXs for Mic PGA source selection */ 410 + SND_SOC_DAPM_MUX("Analog Input 1 Left MUX", SND_SOC_NOPM, 0, 0, &ak4619_ad_1_left_in_mux), 411 + SND_SOC_DAPM_MUX("Analog Input 1 Right MUX", SND_SOC_NOPM, 0, 0, &ak4619_ad_1_right_in_mux), 412 + SND_SOC_DAPM_MUX("Analog Input 2 Left MUX", SND_SOC_NOPM, 0, 0, &ak4619_ad_2_left_in_mux), 413 + SND_SOC_DAPM_MUX("Analog Input 2 Right MUX", SND_SOC_NOPM, 0, 0, &ak4619_ad_2_right_in_mux), 414 + 415 + /* MUXs for DAC source selection */ 416 + SND_SOC_DAPM_MUX("DAC 1 Source MUX", SND_SOC_NOPM, 0, 0, &ak4619_dac_1_in_mux), 417 + SND_SOC_DAPM_MUX("DAC 2 Source MUX", SND_SOC_NOPM, 0, 0, &ak4619_dac_2_in_mux), 418 + }; 419 + 420 + static const struct snd_soc_dapm_route ak4619_intercon[] = { 421 + /* Dest Connecting Widget Source */ 422 + 423 + /* Output path */ 424 + {"AOUT1L", NULL, "DAC1"}, 425 + {"AOUT2L", NULL, "DAC2"}, 426 + 427 + {"AOUT1R", NULL, "DAC1"}, 428 + {"AOUT2R", NULL, "DAC2"}, 429 + 430 + {"DAC1", NULL, "DAC 1 Source MUX"}, 431 + {"DAC2", NULL, "DAC 2 Source MUX"}, 432 + 433 + {"DAC 1 Source MUX", "SDIN1", "SDIN1"}, 434 + {"DAC 1 Source MUX", "SDIN2", "SDIN2"}, 435 + {"DAC 1 Source MUX", "SDOUT1", "SDOUT1"}, 436 + {"DAC 1 Source MUX", "SDOUT2", "SDOUT2"}, 437 + 438 + {"DAC 2 Source MUX", "SDIN1", "SDIN1"}, 439 + {"DAC 2 Source MUX", "SDIN2", "SDIN2"}, 440 + {"DAC 2 Source MUX", "SDOUT1", "SDOUT1"}, 441 + {"DAC 2 Source MUX", "SDOUT2", "SDOUT2"}, 442 + 443 + /* Input path */ 444 + {"SDOUT1", NULL, "ADC1"}, 445 + {"SDOUT2", NULL, "ADC2"}, 446 + 447 + {"ADC1", NULL, "Analog Input 1 Left MUX"}, 448 + {"ADC1", NULL, "Analog Input 1 Right MUX"}, 449 + 450 + {"ADC2", NULL, "Analog Input 2 Left MUX"}, 451 + {"ADC2", NULL, "Analog Input 2 Right MUX"}, 452 + 453 + {"Analog Input 1 Left MUX", "Differential", "MIC1L"}, 454 + {"Analog Input 1 Left MUX", "Single-Ended1", "MIC1L"}, 455 + {"Analog Input 1 Left MUX", "Single-Ended2", "MIC1L"}, 456 + {"Analog Input 1 Left MUX", "Pseudo Differential", "MIC1L"}, 457 + 458 + {"Analog Input 1 Right MUX", "Differential", "MIC1R"}, 459 + {"Analog Input 1 Right MUX", "Single-Ended1", "MIC1R"}, 460 + {"Analog Input 1 Right MUX", "Single-Ended2", "MIC1R"}, 461 + {"Analog Input 1 Right MUX", "Pseudo Differential", "MIC1R"}, 462 + 463 + {"Analog Input 2 Left MUX", "Differential", "MIC2L"}, 464 + {"Analog Input 2 Left MUX", "Single-Ended1", "MIC2L"}, 465 + {"Analog Input 2 Left MUX", "Single-Ended2", "MIC2L"}, 466 + {"Analog Input 2 Left MUX", "Pseudo Differential", "MIC2L"}, 467 + 468 + {"Analog Input 2 Right MUX", "Differential", "MIC2R"}, 469 + {"Analog Input 2 Right MUX", "Single-Ended1", "MIC2R"}, 470 + {"Analog Input 2 Right MUX", "Single-Ended2", "MIC2R"}, 471 + {"Analog Input 2 Right MUX", "Pseudo Differential", "MIC2R"}, 472 + 473 + {"MIC1L", NULL, "AIN1L"}, 474 + {"MIC1L", NULL, "AIN2L"}, 475 + 476 + {"MIC1R", NULL, "AIN1R"}, 477 + {"MIC1R", NULL, "AIN2R"}, 478 + 479 + {"MIC2L", NULL, "AIN4L"}, 480 + {"MIC2L", NULL, "AIN5L"}, 481 + 482 + {"MIC2R", NULL, "AIN4R"}, 483 + {"MIC2R", NULL, "AIN5R"}, 484 + }; 485 + 486 + static const struct reg_default ak4619_reg_defaults[] = { 487 + { PWR_MGMT, 0x00 }, 488 + { AU_IFF1, 0x0C }, 489 + { AU_IFF2, 0x0C }, 490 + { SYS_CLK, 0x00 }, 491 + { MIC_AMP1, 0x22 }, 492 + { MIC_AMP2, 0x22 }, 493 + { LADC1, 0x30 }, 494 + { RADC1, 0x30 }, 495 + { LADC2, 0x30 }, 496 + { RADC2, 0x30 }, 497 + { ADC_DF, 0x00 }, 498 + { ADC_AI, 0x00 }, 499 + { ADC_MHPF, 0x00 }, 500 + { LDAC1, 0x18 }, 501 + { RDAC1, 0x18 }, 502 + { LDAC2, 0x18 }, 503 + { RDAC2, 0x18 }, 504 + { DAC_IS, 0x04 }, 505 + { DAC_DEMP, 0x05 }, 506 + { DAC_MF, 0x0A }, 507 + }; 508 + 509 + static int ak4619_set_bias_level(struct snd_soc_component *component, 510 + enum snd_soc_bias_level level) 511 + { 512 + u8 pwr_ctrl = 0; 513 + 514 + switch (level) { 515 + case SND_SOC_BIAS_ON: 516 + pwr_ctrl |= RSTN; 517 + fallthrough; 518 + case SND_SOC_BIAS_PREPARE: 519 + pwr_ctrl |= PMAD1 | PMAD2 | PMDA1 | PMDA2; 520 + fallthrough; 521 + case SND_SOC_BIAS_STANDBY: 522 + case SND_SOC_BIAS_OFF: 523 + default: 524 + break; 525 + } 526 + 527 + snd_soc_component_write(component, PWR_MGMT, pwr_ctrl); 528 + 529 + return 0; 530 + } 531 + 532 + static int ak4619_dai_hw_params(struct snd_pcm_substream *substream, 533 + struct snd_pcm_hw_params *params, 534 + struct snd_soc_dai *dai) 535 + { 536 + struct snd_soc_component *component = dai->component; 537 + struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component); 538 + unsigned int width; 539 + unsigned int rate; 540 + unsigned int fs; 541 + bool is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 542 + u8 dai_ctrl = 0; 543 + u8 clk_mode = 0; 544 + 545 + width = params_width(params); 546 + switch (width) { 547 + case 16: 548 + dai_ctrl |= is_play ? DIDL_16 : DODL_16; 549 + break; 550 + case 20: 551 + dai_ctrl |= is_play ? DIDL_20 : DODL_20; 552 + break; 553 + case 24: 554 + dai_ctrl |= is_play ? DIDL_24 : DODL_24; 555 + break; 556 + case 32: 557 + if (is_play) 558 + dai_ctrl |= DIDL_32; 559 + else 560 + return -EINVAL; 561 + break; 562 + default: 563 + return -EINVAL; 564 + } 565 + 566 + rate = params_rate(params); 567 + if (rate) 568 + fs = ak4619->sysclk / rate; 569 + else 570 + return -EINVAL; 571 + 572 + switch (rate) { 573 + case 8000: 574 + case 11025: 575 + case 12000: 576 + case 16000: 577 + case 22050: 578 + case 24000: 579 + case 32000: 580 + case 44100: 581 + case 48000: 582 + switch (fs) { 583 + case 256: 584 + clk_mode |= (0x0 << 0); 585 + break; 586 + case 384: 587 + clk_mode |= (0x2 << 0); 588 + break; 589 + case 512: 590 + clk_mode |= (0x3 << 0); 591 + break; 592 + default: 593 + return -EINVAL; 594 + } 595 + break; 596 + case 64000: 597 + case 88200: 598 + case 96000: 599 + if (fs == 256) 600 + clk_mode |= (0x1 << 0); 601 + else 602 + return -EINVAL; 603 + break; 604 + case 176400: 605 + case 192000: 606 + if (fs == 128) 607 + clk_mode |= (0x4 << 0); 608 + else 609 + return -EINVAL; 610 + break; 611 + default: 612 + return -EINVAL; 613 + } 614 + 615 + snd_soc_component_update_bits(component, SYS_CLK, FS_MASK, clk_mode); 616 + snd_soc_component_update_bits(component, AU_IFF2, 617 + is_play ? DIDL_MASK : DODL_MASK, dai_ctrl); 618 + 619 + if (is_play) { 620 + ak4619->playback_rate = rate; 621 + ak4619_set_deemph(component); 622 + } 623 + 624 + return 0; 625 + } 626 + 627 + static int ak4619_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 628 + { 629 + struct snd_soc_component *component = dai->component; 630 + u8 dai_fmt1 = 0; 631 + u8 dai_fmt2 = 0; 632 + 633 + /* Set clock normal/inverted */ 634 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 635 + case SND_SOC_DAIFMT_NB_NF: 636 + break; 637 + case SND_SOC_DAIFMT_IB_NF: 638 + dai_fmt1 |= BCKP; 639 + break; 640 + case SND_SOC_DAIFMT_NB_IF: 641 + case SND_SOC_DAIFMT_IB_IF: 642 + default: 643 + return -EINVAL; 644 + } 645 + 646 + /* Only Stereo modes are supported */ 647 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 648 + case SND_SOC_DAIFMT_I2S: 649 + dai_fmt1 |= DCF_STEREO_I2S; 650 + break; 651 + case SND_SOC_DAIFMT_LEFT_J: 652 + dai_fmt1 |= DCF_STEREO_MSB; 653 + break; 654 + case SND_SOC_DAIFMT_DSP_A: /* L data MSB after FRM LRC */ 655 + dai_fmt1 |= DCF_PCM_SF; 656 + dai_fmt2 |= SLOT; 657 + break; 658 + case SND_SOC_DAIFMT_DSP_B: /* L data MSB during FRM LRC */ 659 + dai_fmt1 |= DCF_PCM_LF; 660 + dai_fmt2 |= SLOT; 661 + break; 662 + default: 663 + return -EINVAL; 664 + } 665 + 666 + /* Only slave mode is support */ 667 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 668 + case SND_SOC_DAIFMT_CBC_CFC: 669 + break; 670 + default: 671 + return -EINVAL; 672 + } 673 + 674 + /* By default only 64 BICK per LRCLK is supported */ 675 + dai_fmt1 |= DSL_32; 676 + 677 + snd_soc_component_update_bits(component, AU_IFF1, DCF_MASK | 678 + DSL_MASK | BCKP, dai_fmt1); 679 + snd_soc_component_update_bits(component, AU_IFF2, SLOT, dai_fmt2); 680 + 681 + return 0; 682 + } 683 + 684 + static int ak4619_dai_set_sysclk(struct snd_soc_dai *codec_dai, 685 + int clk_id, unsigned int freq, int dir) 686 + { 687 + struct snd_soc_component *component = codec_dai->component; 688 + struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component); 689 + 690 + ak4619->sysclk = freq; 691 + 692 + return 0; 693 + } 694 + 695 + static int ak4619_dai_mute(struct snd_soc_dai *dai, int mute, int direction) 696 + { 697 + struct snd_soc_component *component = dai->component; 698 + 699 + snd_soc_component_update_bits(component, DAC_MF, DA1MUTE_EN, mute ? DA1MUTE_EN : 0); 700 + snd_soc_component_update_bits(component, DAC_MF, DA2MUTE_EN, mute ? DA2MUTE_EN : 0); 701 + 702 + return 0; 703 + } 704 + 705 + static void ak4619_hw_constraints(struct ak4619_priv *ak4619, 706 + struct snd_pcm_runtime *runtime) 707 + { 708 + struct snd_pcm_hw_constraint_list *constraint = &ak4619->constraint; 709 + int ak4619_rate_mask = 0; 710 + unsigned int fs; 711 + int i; 712 + static const unsigned int ak4619_sr[] = { 713 + 8000, 714 + 11025, 715 + 12000, 716 + 16000, 717 + 22050, 718 + 24000, 719 + 32000, 720 + 44100, 721 + 48000, 722 + 64000, 723 + 88200, 724 + 96000, 725 + 176400, 726 + 192000, 727 + }; 728 + 729 + /* 730 + * [8kHz - 48kHz] : 256fs, 384fs or 512fs 731 + * [64kHz - 96kHz] : 256fs 732 + * [176.4kHz, 192kHz] : 128fs 733 + */ 734 + 735 + for (i = 0; i < ARRAY_SIZE(ak4619_sr); i++) { 736 + fs = ak4619->sysclk / ak4619_sr[i]; 737 + 738 + switch (fs) { 739 + case 512: 740 + case 384: 741 + case 256: 742 + ak4619_rate_mask |= (1 << i); 743 + break; 744 + case 128: 745 + switch (i) { 746 + case (ARRAY_SIZE(ak4619_sr) - 1): 747 + case (ARRAY_SIZE(ak4619_sr) - 2): 748 + ak4619_rate_mask |= (1 << i); 749 + break; 750 + default: 751 + break; 752 + } 753 + break; 754 + default: 755 + break; 756 + } 757 + }; 758 + 759 + constraint->list = ak4619_sr; 760 + constraint->mask = ak4619_rate_mask; 761 + constraint->count = ARRAY_SIZE(ak4619_sr); 762 + 763 + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, constraint); 764 + }; 765 + 766 + #define PLAYBACK_MODE 0 767 + #define CAPTURE_MODE 1 768 + 769 + static int ak4619_dai_startup(struct snd_pcm_substream *substream, 770 + struct snd_soc_dai *dai) 771 + { 772 + struct snd_soc_component *component = dai->component; 773 + struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component); 774 + 775 + ak4619_hw_constraints(ak4619, substream->runtime); 776 + 777 + return 0; 778 + } 779 + 780 + static u64 ak4619_dai_formats[] = { 781 + /* 782 + * Select below from Sound Card, not here 783 + * SND_SOC_DAIFMT_CBC_CFC 784 + * SND_SOC_DAIFMT_CBP_CFP 785 + */ 786 + 787 + /* First Priority */ 788 + SND_SOC_POSSIBLE_DAIFMT_I2S | 789 + SND_SOC_POSSIBLE_DAIFMT_LEFT_J, 790 + 791 + /* Second Priority */ 792 + SND_SOC_POSSIBLE_DAIFMT_DSP_A | 793 + SND_SOC_POSSIBLE_DAIFMT_DSP_B, 794 + }; 795 + 796 + static const struct snd_soc_dai_ops ak4619_dai_ops = { 797 + .startup = ak4619_dai_startup, 798 + .set_sysclk = ak4619_dai_set_sysclk, 799 + .set_fmt = ak4619_dai_set_fmt, 800 + .hw_params = ak4619_dai_hw_params, 801 + .mute_stream = ak4619_dai_mute, 802 + .auto_selectable_formats = ak4619_dai_formats, 803 + .num_auto_selectable_formats = ARRAY_SIZE(ak4619_dai_formats), 804 + }; 805 + 806 + static const struct snd_soc_component_driver soc_component_dev_ak4619 = { 807 + .set_bias_level = ak4619_set_bias_level, 808 + .controls = ak4619_snd_controls, 809 + .num_controls = ARRAY_SIZE(ak4619_snd_controls), 810 + .dapm_widgets = ak4619_dapm_widgets, 811 + .num_dapm_widgets = ARRAY_SIZE(ak4619_dapm_widgets), 812 + .dapm_routes = ak4619_intercon, 813 + .num_dapm_routes = ARRAY_SIZE(ak4619_intercon), 814 + .idle_bias_on = 1, 815 + .endianness = 1, 816 + }; 817 + 818 + static const struct regmap_config ak4619_regmap_cfg = { 819 + .reg_bits = 8, 820 + .val_bits = 8, 821 + .max_register = 0x14, 822 + .reg_defaults = ak4619_reg_defaults, 823 + .num_reg_defaults = ARRAY_SIZE(ak4619_reg_defaults), 824 + .cache_type = REGCACHE_MAPLE, 825 + }; 826 + 827 + static const struct of_device_id ak4619_of_match[] = { 828 + { .compatible = "asahi-kasei,ak4619", .data = &ak4619_regmap_cfg }, 829 + {}, 830 + }; 831 + MODULE_DEVICE_TABLE(of, ak4619_of_match); 832 + 833 + static const struct i2c_device_id ak4619_i2c_id[] = { 834 + { "ak4619", (kernel_ulong_t)&ak4619_regmap_cfg }, 835 + { } 836 + }; 837 + MODULE_DEVICE_TABLE(i2c, ak4619_i2c_id); 838 + 839 + #define AK4619_RATES SNDRV_PCM_RATE_8000_192000 840 + 841 + #define AK4619_DAC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ 842 + SNDRV_PCM_FMTBIT_S20_LE |\ 843 + SNDRV_PCM_FMTBIT_S24_LE |\ 844 + SNDRV_PCM_FMTBIT_S32_LE) 845 + 846 + #define AK4619_ADC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ 847 + SNDRV_PCM_FMTBIT_S20_LE |\ 848 + SNDRV_PCM_FMTBIT_S24_LE) 849 + 850 + static struct snd_soc_dai_driver ak4619_dai = { 851 + .name = "ak4619-hifi", 852 + .playback = { 853 + .stream_name = "Playback", 854 + .channels_min = 1, 855 + .channels_max = 2, 856 + .rates = AK4619_RATES, 857 + .formats = AK4619_DAC_FORMATS, 858 + }, 859 + .capture = { 860 + .stream_name = "Capture", 861 + .channels_min = 1, 862 + .channels_max = 2, 863 + .rates = AK4619_RATES, 864 + .formats = AK4619_ADC_FORMATS, 865 + }, 866 + .ops = &ak4619_dai_ops, 867 + .symmetric_rate = 1, 868 + }; 869 + 870 + static int ak4619_i2c_probe(struct i2c_client *i2c) 871 + { 872 + struct device *dev = &i2c->dev; 873 + struct ak4619_priv *ak4619; 874 + int ret; 875 + 876 + ak4619 = devm_kzalloc(dev, sizeof(*ak4619), GFP_KERNEL); 877 + if (!ak4619) 878 + return -ENOMEM; 879 + 880 + i2c_set_clientdata(i2c, ak4619); 881 + 882 + ak4619->regmap = devm_regmap_init_i2c(i2c, &ak4619_regmap_cfg); 883 + if (IS_ERR(ak4619->regmap)) { 884 + ret = PTR_ERR(ak4619->regmap); 885 + dev_err(dev, "regmap_init() failed: %d\n", ret); 886 + return ret; 887 + } 888 + 889 + ret = devm_snd_soc_register_component(dev, &soc_component_dev_ak4619, 890 + &ak4619_dai, 1); 891 + if (ret < 0) { 892 + dev_err(dev, "Failed to register ak4619 component: %d\n", 893 + ret); 894 + return ret; 895 + } 896 + 897 + return 0; 898 + } 899 + 900 + static struct i2c_driver ak4619_i2c_driver = { 901 + .driver = { 902 + .name = "ak4619-codec", 903 + .of_match_table = ak4619_of_match, 904 + }, 905 + .probe = ak4619_i2c_probe, 906 + .id_table = ak4619_i2c_id, 907 + }; 908 + module_i2c_driver(ak4619_i2c_driver); 909 + 910 + MODULE_DESCRIPTION("SoC AK4619 driver"); 911 + MODULE_AUTHOR("Khanh Le <khanh.le.xr@renesas.com>"); 912 + MODULE_LICENSE("GPL v2");