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

ASoC: rt5514: add rt5514 codec driver

This is the initial codec driver for rt5514. The codec includes a low power
DSP for voice wake up. The register address is incremental by 4 in the DSP
memory map. In order to recover the codec settings in the codec mode and
manipulate the DSP mode for voice wake up, we use the multi-level register
map. One is for ALSA API in codec mode that can be recovered by cache
before recording. Another is for DSP related settings that can be accessed
with 32bit address of the DSP in the application of voice wake up.

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Oder Chiou and committed by
Mark Brown
4a6180ea 92e963f5

+1267
+25
Documentation/devicetree/bindings/sound/rt5514.txt
··· 1 + RT5514 audio CODEC 2 + 3 + This device supports I2C only. 4 + 5 + Required properties: 6 + 7 + - compatible : "realtek,rt5514". 8 + 9 + - reg : The I2C address of the device. 10 + 11 + Pins on the device (for linking into audio routes) for RT5514: 12 + 13 + * DMIC1L 14 + * DMIC1R 15 + * DMIC2L 16 + * DMIC2R 17 + * AMICL 18 + * AMICR 19 + 20 + Example: 21 + 22 + codec: rt5514@57 { 23 + compatible = "realtek,rt5514"; 24 + reg = <0x57>; 25 + };
+6
sound/soc/codecs/Kconfig
··· 95 95 select SND_SOC_PCM512x_SPI if SPI_MASTER 96 96 select SND_SOC_RT286 if I2C 97 97 select SND_SOC_RT298 if I2C 98 + select SND_SOC_RT5514 if I2C 98 99 select SND_SOC_RT5616 if I2C 99 100 select SND_SOC_RT5631 if I2C 100 101 select SND_SOC_RT5640 if I2C ··· 566 565 567 566 config SND_SOC_RL6231 568 567 tristate 568 + default y if SND_SOC_RT5514=y 569 569 default y if SND_SOC_RT5616=y 570 570 default y if SND_SOC_RT5640=y 571 571 default y if SND_SOC_RT5645=y ··· 574 572 default y if SND_SOC_RT5659=y 575 573 default y if SND_SOC_RT5670=y 576 574 default y if SND_SOC_RT5677=y 575 + default m if SND_SOC_RT5514=m 577 576 default m if SND_SOC_RT5616=m 578 577 default m if SND_SOC_RT5640=m 579 578 default m if SND_SOC_RT5645=m ··· 597 594 config SND_SOC_RT298 598 595 tristate 599 596 depends on I2C 597 + 598 + config SND_SOC_RT5514 599 + tristate 600 600 601 601 config SND_SOC_RT5616 602 602 tristate
+2
sound/soc/codecs/Makefile
··· 92 92 snd-soc-rl6347a-objs := rl6347a.o 93 93 snd-soc-rt286-objs := rt286.o 94 94 snd-soc-rt298-objs := rt298.o 95 + snd-soc-rt5514-objs := rt5514.o 95 96 snd-soc-rt5616-objs := rt5616.o 96 97 snd-soc-rt5631-objs := rt5631.o 97 98 snd-soc-rt5640-objs := rt5640.o ··· 297 296 obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o 298 297 obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o 299 298 obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o 299 + obj-$(CONFIG_SND_SOC_RT5514) += snd-soc-rt5514.o 300 300 obj-$(CONFIG_SND_SOC_RT5616) += snd-soc-rt5616.o 301 301 obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o 302 302 obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
+982
sound/soc/codecs/rt5514.c
··· 1 + /* 2 + * rt5514.c -- RT5514 ALSA SoC audio codec driver 3 + * 4 + * Copyright 2015 Realtek Semiconductor Corp. 5 + * Author: Oder Chiou <oder_chiou@realtek.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/fs.h> 13 + #include <linux/module.h> 14 + #include <linux/moduleparam.h> 15 + #include <linux/init.h> 16 + #include <linux/delay.h> 17 + #include <linux/pm.h> 18 + #include <linux/regmap.h> 19 + #include <linux/i2c.h> 20 + #include <linux/platform_device.h> 21 + #include <linux/firmware.h> 22 + #include <linux/gpio.h> 23 + #include <sound/core.h> 24 + #include <sound/pcm.h> 25 + #include <sound/pcm_params.h> 26 + #include <sound/soc.h> 27 + #include <sound/soc-dapm.h> 28 + #include <sound/initval.h> 29 + #include <sound/tlv.h> 30 + 31 + #include "rl6231.h" 32 + #include "rt5514.h" 33 + 34 + static const struct reg_sequence rt5514_i2c_patch[] = { 35 + {0x1800101c, 0x00000000}, 36 + {0x18001100, 0x0000031f}, 37 + {0x18001104, 0x00000007}, 38 + {0x18001108, 0x00000000}, 39 + {0x1800110c, 0x00000000}, 40 + {0x18001110, 0x00000000}, 41 + {0x18001114, 0x00000001}, 42 + {0x18001118, 0x00000000}, 43 + {0x18002f08, 0x00000006}, 44 + {0x18002f00, 0x00055149}, 45 + {0x18002f00, 0x0005514b}, 46 + {0x18002f00, 0x00055149}, 47 + {0xfafafafa, 0x00000001}, 48 + {0x18002f10, 0x00000001}, 49 + {0x18002f10, 0x00000000}, 50 + {0x18002f10, 0x00000001}, 51 + {0xfafafafa, 0x00000001}, 52 + {0x18002000, 0x000010ec}, 53 + {0xfafafafa, 0x00000000}, 54 + }; 55 + 56 + static const struct reg_sequence rt5514_patch[] = { 57 + {RT5514_DIG_IO_CTRL, 0x00000040}, 58 + {RT5514_CLK_CTRL1, 0x38020041}, 59 + {RT5514_SRC_CTRL, 0x44000eee}, 60 + {RT5514_ANA_CTRL_LDO10, 0x00028604}, 61 + {RT5514_ANA_CTRL_ADCFED, 0x00000800}, 62 + }; 63 + 64 + static const struct reg_default rt5514_reg[] = { 65 + {RT5514_RESET, 0x00000000}, 66 + {RT5514_PWR_ANA1, 0x00808880}, 67 + {RT5514_PWR_ANA2, 0x00220000}, 68 + {RT5514_I2S_CTRL1, 0x00000330}, 69 + {RT5514_I2S_CTRL2, 0x20000000}, 70 + {RT5514_VAD_CTRL6, 0xc00007d2}, 71 + {RT5514_EXT_VAD_CTRL, 0x80000080}, 72 + {RT5514_DIG_IO_CTRL, 0x00000040}, 73 + {RT5514_PAD_CTRL1, 0x00804000}, 74 + {RT5514_DMIC_DATA_CTRL, 0x00000005}, 75 + {RT5514_DIG_SOURCE_CTRL, 0x00000002}, 76 + {RT5514_SRC_CTRL, 0x44000eee}, 77 + {RT5514_DOWNFILTER2_CTRL1, 0x0000882f}, 78 + {RT5514_PLL_SOURCE_CTRL, 0x00000004}, 79 + {RT5514_CLK_CTRL1, 0x38020041}, 80 + {RT5514_CLK_CTRL2, 0x00000000}, 81 + {RT5514_PLL3_CALIB_CTRL1, 0x00400200}, 82 + {RT5514_PLL3_CALIB_CTRL5, 0x40220012}, 83 + {RT5514_DELAY_BUF_CTRL1, 0x7fff006a}, 84 + {RT5514_DELAY_BUF_CTRL3, 0x00000000}, 85 + {RT5514_DOWNFILTER0_CTRL1, 0x00020c2f}, 86 + {RT5514_DOWNFILTER0_CTRL2, 0x00020c2f}, 87 + {RT5514_DOWNFILTER0_CTRL3, 0x00000362}, 88 + {RT5514_DOWNFILTER1_CTRL1, 0x00020c2f}, 89 + {RT5514_DOWNFILTER1_CTRL2, 0x00020c2f}, 90 + {RT5514_DOWNFILTER1_CTRL3, 0x00000362}, 91 + {RT5514_ANA_CTRL_LDO10, 0x00028604}, 92 + {RT5514_ANA_CTRL_LDO18_16, 0x02000345}, 93 + {RT5514_ANA_CTRL_ADC12, 0x0000a2a8}, 94 + {RT5514_ANA_CTRL_ADC21, 0x00001180}, 95 + {RT5514_ANA_CTRL_ADC22, 0x0000aaa8}, 96 + {RT5514_ANA_CTRL_ADC23, 0x00151427}, 97 + {RT5514_ANA_CTRL_MICBST, 0x00002000}, 98 + {RT5514_ANA_CTRL_ADCFED, 0x00000800}, 99 + {RT5514_ANA_CTRL_INBUF, 0x00000143}, 100 + {RT5514_ANA_CTRL_VREF, 0x00008d50}, 101 + {RT5514_ANA_CTRL_PLL3, 0x0000000e}, 102 + {RT5514_ANA_CTRL_PLL1_1, 0x00000000}, 103 + {RT5514_ANA_CTRL_PLL1_2, 0x00030220}, 104 + {RT5514_DMIC_LP_CTRL, 0x00000000}, 105 + {RT5514_MISC_CTRL_DSP, 0x00000000}, 106 + {RT5514_DSP_CTRL1, 0x00055149}, 107 + {RT5514_DSP_CTRL3, 0x00000006}, 108 + {RT5514_DSP_CTRL4, 0x00000001}, 109 + {RT5514_VENDOR_ID1, 0x00000001}, 110 + {RT5514_VENDOR_ID2, 0x10ec5514}, 111 + }; 112 + 113 + static bool rt5514_volatile_register(struct device *dev, unsigned int reg) 114 + { 115 + switch (reg) { 116 + case RT5514_VENDOR_ID1: 117 + case RT5514_VENDOR_ID2: 118 + return true; 119 + 120 + default: 121 + return false; 122 + } 123 + } 124 + 125 + static bool rt5514_readable_register(struct device *dev, unsigned int reg) 126 + { 127 + switch (reg) { 128 + case RT5514_RESET: 129 + case RT5514_PWR_ANA1: 130 + case RT5514_PWR_ANA2: 131 + case RT5514_I2S_CTRL1: 132 + case RT5514_I2S_CTRL2: 133 + case RT5514_VAD_CTRL6: 134 + case RT5514_EXT_VAD_CTRL: 135 + case RT5514_DIG_IO_CTRL: 136 + case RT5514_PAD_CTRL1: 137 + case RT5514_DMIC_DATA_CTRL: 138 + case RT5514_DIG_SOURCE_CTRL: 139 + case RT5514_SRC_CTRL: 140 + case RT5514_DOWNFILTER2_CTRL1: 141 + case RT5514_PLL_SOURCE_CTRL: 142 + case RT5514_CLK_CTRL1: 143 + case RT5514_CLK_CTRL2: 144 + case RT5514_PLL3_CALIB_CTRL1: 145 + case RT5514_PLL3_CALIB_CTRL5: 146 + case RT5514_DELAY_BUF_CTRL1: 147 + case RT5514_DELAY_BUF_CTRL3: 148 + case RT5514_DOWNFILTER0_CTRL1: 149 + case RT5514_DOWNFILTER0_CTRL2: 150 + case RT5514_DOWNFILTER0_CTRL3: 151 + case RT5514_DOWNFILTER1_CTRL1: 152 + case RT5514_DOWNFILTER1_CTRL2: 153 + case RT5514_DOWNFILTER1_CTRL3: 154 + case RT5514_ANA_CTRL_LDO10: 155 + case RT5514_ANA_CTRL_LDO18_16: 156 + case RT5514_ANA_CTRL_ADC12: 157 + case RT5514_ANA_CTRL_ADC21: 158 + case RT5514_ANA_CTRL_ADC22: 159 + case RT5514_ANA_CTRL_ADC23: 160 + case RT5514_ANA_CTRL_MICBST: 161 + case RT5514_ANA_CTRL_ADCFED: 162 + case RT5514_ANA_CTRL_INBUF: 163 + case RT5514_ANA_CTRL_VREF: 164 + case RT5514_ANA_CTRL_PLL3: 165 + case RT5514_ANA_CTRL_PLL1_1: 166 + case RT5514_ANA_CTRL_PLL1_2: 167 + case RT5514_DMIC_LP_CTRL: 168 + case RT5514_MISC_CTRL_DSP: 169 + case RT5514_DSP_CTRL1: 170 + case RT5514_DSP_CTRL3: 171 + case RT5514_DSP_CTRL4: 172 + case RT5514_VENDOR_ID1: 173 + case RT5514_VENDOR_ID2: 174 + return true; 175 + 176 + default: 177 + return false; 178 + } 179 + } 180 + 181 + static bool rt5514_i2c_readable_register(struct device *dev, 182 + unsigned int reg) 183 + { 184 + switch (reg) { 185 + case RT5514_DSP_MAPPING | RT5514_RESET: 186 + case RT5514_DSP_MAPPING | RT5514_PWR_ANA1: 187 + case RT5514_DSP_MAPPING | RT5514_PWR_ANA2: 188 + case RT5514_DSP_MAPPING | RT5514_I2S_CTRL1: 189 + case RT5514_DSP_MAPPING | RT5514_I2S_CTRL2: 190 + case RT5514_DSP_MAPPING | RT5514_VAD_CTRL6: 191 + case RT5514_DSP_MAPPING | RT5514_EXT_VAD_CTRL: 192 + case RT5514_DSP_MAPPING | RT5514_DIG_IO_CTRL: 193 + case RT5514_DSP_MAPPING | RT5514_PAD_CTRL1: 194 + case RT5514_DSP_MAPPING | RT5514_DMIC_DATA_CTRL: 195 + case RT5514_DSP_MAPPING | RT5514_DIG_SOURCE_CTRL: 196 + case RT5514_DSP_MAPPING | RT5514_SRC_CTRL: 197 + case RT5514_DSP_MAPPING | RT5514_DOWNFILTER2_CTRL1: 198 + case RT5514_DSP_MAPPING | RT5514_PLL_SOURCE_CTRL: 199 + case RT5514_DSP_MAPPING | RT5514_CLK_CTRL1: 200 + case RT5514_DSP_MAPPING | RT5514_CLK_CTRL2: 201 + case RT5514_DSP_MAPPING | RT5514_PLL3_CALIB_CTRL1: 202 + case RT5514_DSP_MAPPING | RT5514_PLL3_CALIB_CTRL5: 203 + case RT5514_DSP_MAPPING | RT5514_DELAY_BUF_CTRL1: 204 + case RT5514_DSP_MAPPING | RT5514_DELAY_BUF_CTRL3: 205 + case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL1: 206 + case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL2: 207 + case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL3: 208 + case RT5514_DSP_MAPPING | RT5514_DOWNFILTER1_CTRL1: 209 + case RT5514_DSP_MAPPING | RT5514_DOWNFILTER1_CTRL2: 210 + case RT5514_DSP_MAPPING | RT5514_DOWNFILTER1_CTRL3: 211 + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_LDO10: 212 + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_LDO18_16: 213 + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADC12: 214 + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADC21: 215 + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADC22: 216 + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADC23: 217 + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_MICBST: 218 + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADCFED: 219 + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_INBUF: 220 + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_VREF: 221 + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_PLL3: 222 + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_PLL1_1: 223 + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_PLL1_2: 224 + case RT5514_DSP_MAPPING | RT5514_DMIC_LP_CTRL: 225 + case RT5514_DSP_MAPPING | RT5514_MISC_CTRL_DSP: 226 + case RT5514_DSP_MAPPING | RT5514_DSP_CTRL1: 227 + case RT5514_DSP_MAPPING | RT5514_DSP_CTRL3: 228 + case RT5514_DSP_MAPPING | RT5514_DSP_CTRL4: 229 + case RT5514_DSP_MAPPING | RT5514_VENDOR_ID1: 230 + case RT5514_DSP_MAPPING | RT5514_VENDOR_ID2: 231 + return true; 232 + 233 + default: 234 + return false; 235 + } 236 + } 237 + 238 + /* {-3, 0, +3, +4.5, +7.5, +9.5, +12, +14, +17} dB */ 239 + static const DECLARE_TLV_DB_RANGE(bst_tlv, 240 + 0, 2, TLV_DB_SCALE_ITEM(-300, 300, 0), 241 + 3, 3, TLV_DB_SCALE_ITEM(450, 0, 0), 242 + 4, 4, TLV_DB_SCALE_ITEM(750, 0, 0), 243 + 5, 5, TLV_DB_SCALE_ITEM(950, 0, 0), 244 + 6, 6, TLV_DB_SCALE_ITEM(1200, 0, 0), 245 + 7, 7, TLV_DB_SCALE_ITEM(1400, 0, 0), 246 + 8, 8, TLV_DB_SCALE_ITEM(1700, 0, 0) 247 + ); 248 + 249 + static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); 250 + 251 + static const struct snd_kcontrol_new rt5514_snd_controls[] = { 252 + SOC_DOUBLE_TLV("MIC Boost Volume", RT5514_ANA_CTRL_MICBST, 253 + RT5514_SEL_BSTL_SFT, RT5514_SEL_BSTR_SFT, 8, 0, bst_tlv), 254 + SOC_DOUBLE_R_TLV("ADC1 Capture Volume", RT5514_DOWNFILTER0_CTRL1, 255 + RT5514_DOWNFILTER0_CTRL2, RT5514_AD_GAIN_SFT, 127, 0, 256 + adc_vol_tlv), 257 + SOC_DOUBLE_R_TLV("ADC2 Capture Volume", RT5514_DOWNFILTER1_CTRL1, 258 + RT5514_DOWNFILTER1_CTRL2, RT5514_AD_GAIN_SFT, 127, 0, 259 + adc_vol_tlv), 260 + }; 261 + 262 + /* ADC Mixer*/ 263 + static const struct snd_kcontrol_new rt5514_sto1_adc_l_mix[] = { 264 + SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER0_CTRL1, 265 + RT5514_AD_DMIC_MIX_BIT, 1, 1), 266 + SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER0_CTRL1, 267 + RT5514_AD_AD_MIX_BIT, 1, 1), 268 + }; 269 + 270 + static const struct snd_kcontrol_new rt5514_sto1_adc_r_mix[] = { 271 + SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER0_CTRL2, 272 + RT5514_AD_DMIC_MIX_BIT, 1, 1), 273 + SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER0_CTRL2, 274 + RT5514_AD_AD_MIX_BIT, 1, 1), 275 + }; 276 + 277 + static const struct snd_kcontrol_new rt5514_sto2_adc_l_mix[] = { 278 + SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER1_CTRL1, 279 + RT5514_AD_DMIC_MIX_BIT, 1, 1), 280 + SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER1_CTRL1, 281 + RT5514_AD_AD_MIX_BIT, 1, 1), 282 + }; 283 + 284 + static const struct snd_kcontrol_new rt5514_sto2_adc_r_mix[] = { 285 + SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER1_CTRL2, 286 + RT5514_AD_DMIC_MIX_BIT, 1, 1), 287 + SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER1_CTRL2, 288 + RT5514_AD_AD_MIX_BIT, 1, 1), 289 + }; 290 + 291 + /* DMIC Source */ 292 + static const char * const rt5514_dmic_src[] = { 293 + "DMIC1", "DMIC2" 294 + }; 295 + 296 + static const SOC_ENUM_SINGLE_DECL( 297 + rt5514_stereo1_dmic_enum, RT5514_DIG_SOURCE_CTRL, 298 + RT5514_AD0_DMIC_INPUT_SEL_SFT, rt5514_dmic_src); 299 + 300 + static const struct snd_kcontrol_new rt5514_sto1_dmic_mux = 301 + SOC_DAPM_ENUM("Stereo1 DMIC Source", rt5514_stereo1_dmic_enum); 302 + 303 + static const SOC_ENUM_SINGLE_DECL( 304 + rt5514_stereo2_dmic_enum, RT5514_DIG_SOURCE_CTRL, 305 + RT5514_AD1_DMIC_INPUT_SEL_SFT, rt5514_dmic_src); 306 + 307 + static const struct snd_kcontrol_new rt5514_sto2_dmic_mux = 308 + SOC_DAPM_ENUM("Stereo2 DMIC Source", rt5514_stereo2_dmic_enum); 309 + 310 + /** 311 + * rt5514_calc_dmic_clk - Calculate the frequency divider parameter of dmic. 312 + * 313 + * @rate: base clock rate. 314 + * 315 + * Choose divider parameter that gives the highest possible DMIC frequency in 316 + * 1MHz - 3MHz range. 317 + */ 318 + static int rt5514_calc_dmic_clk(struct snd_soc_codec *codec, int rate) 319 + { 320 + int div[] = {2, 3, 4, 8, 12, 16, 24, 32}; 321 + int i; 322 + 323 + if (rate < 1000000 * div[0]) { 324 + pr_warn("Base clock rate %d is too low\n", rate); 325 + return -EINVAL; 326 + } 327 + 328 + for (i = 0; i < ARRAY_SIZE(div); i++) { 329 + /* find divider that gives DMIC frequency below 3.072MHz */ 330 + if (3072000 * div[i] >= rate) 331 + return i; 332 + } 333 + 334 + dev_warn(codec->dev, "Base clock rate %d is too high\n", rate); 335 + return -EINVAL; 336 + } 337 + 338 + static int rt5514_set_dmic_clk(struct snd_soc_dapm_widget *w, 339 + struct snd_kcontrol *kcontrol, int event) 340 + { 341 + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 342 + struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 343 + int idx; 344 + 345 + idx = rt5514_calc_dmic_clk(codec, rt5514->sysclk); 346 + if (idx < 0) 347 + dev_err(codec->dev, "Failed to set DMIC clock\n"); 348 + else 349 + regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL1, 350 + RT5514_CLK_DMIC_OUT_SEL_MASK, 351 + idx << RT5514_CLK_DMIC_OUT_SEL_SFT); 352 + 353 + return idx; 354 + } 355 + 356 + static int rt5514_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, 357 + struct snd_soc_dapm_widget *sink) 358 + { 359 + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); 360 + struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 361 + 362 + if (rt5514->sysclk_src == RT5514_SCLK_S_PLL1) 363 + return 1; 364 + else 365 + return 0; 366 + } 367 + 368 + static const struct snd_soc_dapm_widget rt5514_dapm_widgets[] = { 369 + /* Input Lines */ 370 + SND_SOC_DAPM_INPUT("DMIC1L"), 371 + SND_SOC_DAPM_INPUT("DMIC1R"), 372 + SND_SOC_DAPM_INPUT("DMIC2L"), 373 + SND_SOC_DAPM_INPUT("DMIC2R"), 374 + 375 + SND_SOC_DAPM_INPUT("AMICL"), 376 + SND_SOC_DAPM_INPUT("AMICR"), 377 + 378 + SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0), 379 + SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0), 380 + 381 + SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0, 382 + rt5514_set_dmic_clk, SND_SOC_DAPM_PRE_PMU), 383 + 384 + SND_SOC_DAPM_SUPPLY("ADC CLK", RT5514_CLK_CTRL1, 385 + RT5514_CLK_AD_ANA1_EN_BIT, 0, NULL, 0), 386 + 387 + SND_SOC_DAPM_SUPPLY("LDO18 IN", RT5514_PWR_ANA1, 388 + RT5514_POW_LDO18_IN_BIT, 0, NULL, 0), 389 + SND_SOC_DAPM_SUPPLY("LDO18 ADC", RT5514_PWR_ANA1, 390 + RT5514_POW_LDO18_ADC_BIT, 0, NULL, 0), 391 + SND_SOC_DAPM_SUPPLY("LDO21", RT5514_PWR_ANA1, RT5514_POW_LDO21_BIT, 0, 392 + NULL, 0), 393 + SND_SOC_DAPM_SUPPLY("BG LDO18 IN", RT5514_PWR_ANA1, 394 + RT5514_POW_BG_LDO18_IN_BIT, 0, NULL, 0), 395 + SND_SOC_DAPM_SUPPLY("BG LDO21", RT5514_PWR_ANA1, 396 + RT5514_POW_BG_LDO21_BIT, 0, NULL, 0), 397 + SND_SOC_DAPM_SUPPLY("BG MBIAS", RT5514_PWR_ANA2, 398 + RT5514_POW_BG_MBIAS_BIT, 0, NULL, 0), 399 + SND_SOC_DAPM_SUPPLY("MBIAS", RT5514_PWR_ANA2, RT5514_POW_MBIAS_BIT, 0, 400 + NULL, 0), 401 + SND_SOC_DAPM_SUPPLY("VREF2", RT5514_PWR_ANA2, RT5514_POW_VREF2_BIT, 0, 402 + NULL, 0), 403 + SND_SOC_DAPM_SUPPLY("VREF1", RT5514_PWR_ANA2, RT5514_POW_VREF1_BIT, 0, 404 + NULL, 0), 405 + SND_SOC_DAPM_SUPPLY("ADC Power", SND_SOC_NOPM, 0, 0, NULL, 0), 406 + 407 + 408 + SND_SOC_DAPM_SUPPLY("LDO16L", RT5514_PWR_ANA2, RT5514_POWL_LDO16_BIT, 0, 409 + NULL, 0), 410 + SND_SOC_DAPM_SUPPLY("ADC1L", RT5514_PWR_ANA2, RT5514_POW_ADC1_L_BIT, 0, 411 + NULL, 0), 412 + SND_SOC_DAPM_SUPPLY("BSTL2", RT5514_PWR_ANA2, RT5514_POW2_BSTL_BIT, 0, 413 + NULL, 0), 414 + SND_SOC_DAPM_SUPPLY("BSTL", RT5514_PWR_ANA2, RT5514_POW_BSTL_BIT, 0, 415 + NULL, 0), 416 + SND_SOC_DAPM_SUPPLY("ADCFEDL", RT5514_PWR_ANA2, RT5514_POW_ADCFEDL_BIT, 417 + 0, NULL, 0), 418 + SND_SOC_DAPM_SUPPLY("ADCL Power", SND_SOC_NOPM, 0, 0, NULL, 0), 419 + 420 + SND_SOC_DAPM_SUPPLY("LDO16R", RT5514_PWR_ANA2, RT5514_POWR_LDO16_BIT, 0, 421 + NULL, 0), 422 + SND_SOC_DAPM_SUPPLY("ADC1R", RT5514_PWR_ANA2, RT5514_POW_ADC1_R_BIT, 0, 423 + NULL, 0), 424 + SND_SOC_DAPM_SUPPLY("BSTR2", RT5514_PWR_ANA2, RT5514_POW2_BSTR_BIT, 0, 425 + NULL, 0), 426 + SND_SOC_DAPM_SUPPLY("BSTR", RT5514_PWR_ANA2, RT5514_POW_BSTR_BIT, 0, 427 + NULL, 0), 428 + SND_SOC_DAPM_SUPPLY("ADCFEDR", RT5514_PWR_ANA2, RT5514_POW_ADCFEDR_BIT, 429 + 0, NULL, 0), 430 + SND_SOC_DAPM_SUPPLY("ADCR Power", SND_SOC_NOPM, 0, 0, NULL, 0), 431 + 432 + SND_SOC_DAPM_SUPPLY("PLL1 LDO ENABLE", RT5514_ANA_CTRL_PLL1_2, 433 + RT5514_EN_LDO_PLL1_BIT, 0, NULL, 0), 434 + SND_SOC_DAPM_SUPPLY("PLL1 LDO", RT5514_PWR_ANA2, 435 + RT5514_POW_PLL1_LDO_BIT, 0, NULL, 0), 436 + SND_SOC_DAPM_SUPPLY("PLL1", RT5514_PWR_ANA2, RT5514_POW_PLL1_BIT, 0, 437 + NULL, 0), 438 + 439 + /* ADC Mux */ 440 + SND_SOC_DAPM_MUX("Stereo1 DMIC Mux", SND_SOC_NOPM, 0, 0, 441 + &rt5514_sto1_dmic_mux), 442 + SND_SOC_DAPM_MUX("Stereo2 DMIC Mux", SND_SOC_NOPM, 0, 0, 443 + &rt5514_sto2_dmic_mux), 444 + 445 + /* ADC Mixer */ 446 + SND_SOC_DAPM_SUPPLY("adc stereo1 filter", RT5514_CLK_CTRL1, 447 + RT5514_CLK_AD0_EN_BIT, 0, NULL, 0), 448 + SND_SOC_DAPM_SUPPLY("adc stereo2 filter", RT5514_CLK_CTRL1, 449 + RT5514_CLK_AD1_EN_BIT, 0, NULL, 0), 450 + 451 + SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", SND_SOC_NOPM, 0, 0, 452 + rt5514_sto1_adc_l_mix, ARRAY_SIZE(rt5514_sto1_adc_l_mix)), 453 + SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", SND_SOC_NOPM, 0, 0, 454 + rt5514_sto1_adc_r_mix, ARRAY_SIZE(rt5514_sto1_adc_r_mix)), 455 + SND_SOC_DAPM_MIXER("Sto2 ADC MIXL", SND_SOC_NOPM, 0, 0, 456 + rt5514_sto2_adc_l_mix, ARRAY_SIZE(rt5514_sto2_adc_l_mix)), 457 + SND_SOC_DAPM_MIXER("Sto2 ADC MIXR", SND_SOC_NOPM, 0, 0, 458 + rt5514_sto2_adc_r_mix, ARRAY_SIZE(rt5514_sto2_adc_r_mix)), 459 + 460 + SND_SOC_DAPM_ADC("Stereo1 ADC MIXL", NULL, RT5514_DOWNFILTER0_CTRL1, 461 + RT5514_AD_AD_MUTE_BIT, 1), 462 + SND_SOC_DAPM_ADC("Stereo1 ADC MIXR", NULL, RT5514_DOWNFILTER0_CTRL2, 463 + RT5514_AD_AD_MUTE_BIT, 1), 464 + SND_SOC_DAPM_ADC("Stereo2 ADC MIXL", NULL, RT5514_DOWNFILTER1_CTRL1, 465 + RT5514_AD_AD_MUTE_BIT, 1), 466 + SND_SOC_DAPM_ADC("Stereo2 ADC MIXR", NULL, RT5514_DOWNFILTER1_CTRL2, 467 + RT5514_AD_AD_MUTE_BIT, 1), 468 + 469 + /* ADC PGA */ 470 + SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), 471 + SND_SOC_DAPM_PGA("Stereo2 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), 472 + 473 + /* Audio Interface */ 474 + SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), 475 + }; 476 + 477 + static const struct snd_soc_dapm_route rt5514_dapm_routes[] = { 478 + { "DMIC1", NULL, "DMIC1L" }, 479 + { "DMIC1", NULL, "DMIC1R" }, 480 + { "DMIC2", NULL, "DMIC2L" }, 481 + { "DMIC2", NULL, "DMIC2R" }, 482 + 483 + { "DMIC1L", NULL, "DMIC CLK" }, 484 + { "DMIC1R", NULL, "DMIC CLK" }, 485 + { "DMIC2L", NULL, "DMIC CLK" }, 486 + { "DMIC2R", NULL, "DMIC CLK" }, 487 + 488 + { "Stereo1 DMIC Mux", "DMIC1", "DMIC1" }, 489 + { "Stereo1 DMIC Mux", "DMIC2", "DMIC2" }, 490 + 491 + { "Sto1 ADC MIXL", "DMIC Switch", "Stereo1 DMIC Mux" }, 492 + { "Sto1 ADC MIXL", "ADC Switch", "AMICL" }, 493 + { "Sto1 ADC MIXR", "DMIC Switch", "Stereo1 DMIC Mux" }, 494 + { "Sto1 ADC MIXR", "ADC Switch", "AMICR" }, 495 + 496 + { "ADC Power", NULL, "LDO18 IN" }, 497 + { "ADC Power", NULL, "LDO18 ADC" }, 498 + { "ADC Power", NULL, "LDO21" }, 499 + { "ADC Power", NULL, "BG LDO18 IN" }, 500 + { "ADC Power", NULL, "BG LDO21" }, 501 + { "ADC Power", NULL, "BG MBIAS" }, 502 + { "ADC Power", NULL, "MBIAS" }, 503 + { "ADC Power", NULL, "VREF2" }, 504 + { "ADC Power", NULL, "VREF1" }, 505 + 506 + { "ADCL Power", NULL, "LDO16L" }, 507 + { "ADCL Power", NULL, "ADC1L" }, 508 + { "ADCL Power", NULL, "BSTL2" }, 509 + { "ADCL Power", NULL, "BSTL" }, 510 + { "ADCL Power", NULL, "ADCFEDL" }, 511 + 512 + { "ADCR Power", NULL, "LDO16R" }, 513 + { "ADCR Power", NULL, "ADC1R" }, 514 + { "ADCR Power", NULL, "BSTR2" }, 515 + { "ADCR Power", NULL, "BSTR" }, 516 + { "ADCR Power", NULL, "ADCFEDR" }, 517 + 518 + { "AMICL", NULL, "ADC CLK" }, 519 + { "AMICL", NULL, "ADC Power" }, 520 + { "AMICL", NULL, "ADCL Power" }, 521 + { "AMICR", NULL, "ADC CLK" }, 522 + { "AMICR", NULL, "ADC Power" }, 523 + { "AMICR", NULL, "ADCR Power" }, 524 + 525 + { "PLL1 LDO", NULL, "PLL1 LDO ENABLE" }, 526 + { "PLL1", NULL, "PLL1 LDO" }, 527 + 528 + { "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" }, 529 + { "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" }, 530 + 531 + { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXL" }, 532 + { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR" }, 533 + { "Stereo1 ADC MIX", NULL, "adc stereo1 filter" }, 534 + { "adc stereo1 filter", NULL, "PLL1", rt5514_is_sys_clk_from_pll }, 535 + 536 + { "Stereo2 DMIC Mux", "DMIC1", "DMIC1" }, 537 + { "Stereo2 DMIC Mux", "DMIC2", "DMIC2" }, 538 + 539 + { "Sto2 ADC MIXL", "DMIC Switch", "Stereo2 DMIC Mux" }, 540 + { "Sto2 ADC MIXL", "ADC Switch", "AMICL" }, 541 + { "Sto2 ADC MIXR", "DMIC Switch", "Stereo2 DMIC Mux" }, 542 + { "Sto2 ADC MIXR", "ADC Switch", "AMICR" }, 543 + 544 + { "Stereo2 ADC MIXL", NULL, "Sto2 ADC MIXL" }, 545 + { "Stereo2 ADC MIXR", NULL, "Sto2 ADC MIXR" }, 546 + 547 + { "Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXL" }, 548 + { "Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXR" }, 549 + { "Stereo2 ADC MIX", NULL, "adc stereo2 filter" }, 550 + { "adc stereo2 filter", NULL, "PLL1", rt5514_is_sys_clk_from_pll }, 551 + 552 + { "AIF1TX", NULL, "Stereo1 ADC MIX"}, 553 + { "AIF1TX", NULL, "Stereo2 ADC MIX"}, 554 + }; 555 + 556 + static int rt5514_hw_params(struct snd_pcm_substream *substream, 557 + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 558 + { 559 + struct snd_soc_codec *codec = dai->codec; 560 + struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 561 + int pre_div, bclk_ms, frame_size; 562 + unsigned int val_len = 0; 563 + 564 + rt5514->lrck = params_rate(params); 565 + pre_div = rl6231_get_clk_info(rt5514->sysclk, rt5514->lrck); 566 + if (pre_div < 0) { 567 + dev_err(codec->dev, "Unsupported clock setting\n"); 568 + return -EINVAL; 569 + } 570 + 571 + frame_size = snd_soc_params_to_frame_size(params); 572 + if (frame_size < 0) { 573 + dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size); 574 + return -EINVAL; 575 + } 576 + 577 + bclk_ms = frame_size > 32; 578 + rt5514->bclk = rt5514->lrck * (32 << bclk_ms); 579 + 580 + dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n", 581 + rt5514->bclk, rt5514->lrck); 582 + dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", 583 + bclk_ms, pre_div, dai->id); 584 + 585 + switch (params_format(params)) { 586 + case SNDRV_PCM_FORMAT_S16_LE: 587 + break; 588 + case SNDRV_PCM_FORMAT_S20_3LE: 589 + val_len = RT5514_I2S_DL_20; 590 + break; 591 + case SNDRV_PCM_FORMAT_S24_LE: 592 + val_len = RT5514_I2S_DL_24; 593 + break; 594 + case SNDRV_PCM_FORMAT_S8: 595 + val_len = RT5514_I2S_DL_8; 596 + break; 597 + default: 598 + return -EINVAL; 599 + } 600 + 601 + regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, RT5514_I2S_DL_MASK, 602 + val_len); 603 + regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, 604 + RT5514_CLK_SYS_DIV_OUT_MASK | RT5514_SEL_ADC_OSR_MASK, 605 + pre_div << RT5514_CLK_SYS_DIV_OUT_SFT | 606 + pre_div << RT5514_SEL_ADC_OSR_SFT); 607 + 608 + return 0; 609 + } 610 + 611 + static int rt5514_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 612 + { 613 + struct snd_soc_codec *codec = dai->codec; 614 + struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 615 + unsigned int reg_val = 0; 616 + 617 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 618 + case SND_SOC_DAIFMT_NB_NF: 619 + break; 620 + 621 + case SND_SOC_DAIFMT_NB_IF: 622 + reg_val |= RT5514_I2S_LR_INV; 623 + break; 624 + 625 + case SND_SOC_DAIFMT_IB_NF: 626 + reg_val |= RT5514_I2S_BP_INV; 627 + break; 628 + 629 + case SND_SOC_DAIFMT_IB_IF: 630 + reg_val |= RT5514_I2S_BP_INV | RT5514_I2S_LR_INV; 631 + break; 632 + 633 + default: 634 + return -EINVAL; 635 + } 636 + 637 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 638 + case SND_SOC_DAIFMT_I2S: 639 + break; 640 + 641 + case SND_SOC_DAIFMT_LEFT_J: 642 + reg_val |= RT5514_I2S_DF_LEFT; 643 + break; 644 + 645 + case SND_SOC_DAIFMT_DSP_A: 646 + reg_val |= RT5514_I2S_DF_PCM_A; 647 + break; 648 + 649 + case SND_SOC_DAIFMT_DSP_B: 650 + reg_val |= RT5514_I2S_DF_PCM_B; 651 + break; 652 + 653 + default: 654 + return -EINVAL; 655 + } 656 + 657 + regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, 658 + RT5514_I2S_DF_MASK | RT5514_I2S_BP_MASK | RT5514_I2S_LR_MASK, 659 + reg_val); 660 + 661 + return 0; 662 + } 663 + 664 + static int rt5514_set_dai_sysclk(struct snd_soc_dai *dai, 665 + int clk_id, unsigned int freq, int dir) 666 + { 667 + struct snd_soc_codec *codec = dai->codec; 668 + struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 669 + unsigned int reg_val = 0; 670 + 671 + if (freq == rt5514->sysclk && clk_id == rt5514->sysclk_src) 672 + return 0; 673 + 674 + switch (clk_id) { 675 + case RT5514_SCLK_S_MCLK: 676 + reg_val |= RT5514_CLK_SYS_PRE_SEL_MCLK; 677 + break; 678 + 679 + case RT5514_SCLK_S_PLL1: 680 + reg_val |= RT5514_CLK_SYS_PRE_SEL_PLL; 681 + break; 682 + 683 + default: 684 + dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id); 685 + return -EINVAL; 686 + } 687 + 688 + regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, 689 + RT5514_CLK_SYS_PRE_SEL_MASK, reg_val); 690 + 691 + rt5514->sysclk = freq; 692 + rt5514->sysclk_src = clk_id; 693 + 694 + dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); 695 + 696 + return 0; 697 + } 698 + 699 + static int rt5514_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, 700 + unsigned int freq_in, unsigned int freq_out) 701 + { 702 + struct snd_soc_codec *codec = dai->codec; 703 + struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 704 + struct rl6231_pll_code pll_code; 705 + int ret; 706 + 707 + if (!freq_in || !freq_out) { 708 + dev_dbg(codec->dev, "PLL disabled\n"); 709 + 710 + rt5514->pll_in = 0; 711 + rt5514->pll_out = 0; 712 + regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, 713 + RT5514_CLK_SYS_PRE_SEL_MASK, 714 + RT5514_CLK_SYS_PRE_SEL_MCLK); 715 + 716 + return 0; 717 + } 718 + 719 + if (source == rt5514->pll_src && freq_in == rt5514->pll_in && 720 + freq_out == rt5514->pll_out) 721 + return 0; 722 + 723 + switch (source) { 724 + case RT5514_PLL1_S_MCLK: 725 + regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 726 + RT5514_PLL_1_SEL_MASK, RT5514_PLL_1_SEL_MCLK); 727 + break; 728 + 729 + case RT5514_PLL1_S_BCLK: 730 + regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 731 + RT5514_PLL_1_SEL_MASK, RT5514_PLL_1_SEL_SCLK); 732 + break; 733 + 734 + default: 735 + dev_err(codec->dev, "Unknown PLL source %d\n", source); 736 + return -EINVAL; 737 + } 738 + 739 + ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); 740 + if (ret < 0) { 741 + dev_err(codec->dev, "Unsupport input clock %d\n", freq_in); 742 + return ret; 743 + } 744 + 745 + dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n", 746 + pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), 747 + pll_code.n_code, pll_code.k_code); 748 + 749 + regmap_write(rt5514->regmap, RT5514_ANA_CTRL_PLL1_1, 750 + pll_code.k_code << RT5514_PLL_K_SFT | 751 + pll_code.n_code << RT5514_PLL_N_SFT | 752 + (pll_code.m_bp ? 0 : pll_code.m_code) << RT5514_PLL_M_SFT); 753 + regmap_update_bits(rt5514->regmap, RT5514_ANA_CTRL_PLL1_2, 754 + RT5514_PLL_M_BP, pll_code.m_bp << RT5514_PLL_M_BP_SFT); 755 + 756 + rt5514->pll_in = freq_in; 757 + rt5514->pll_out = freq_out; 758 + rt5514->pll_src = source; 759 + 760 + return 0; 761 + } 762 + 763 + static int rt5514_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 764 + unsigned int rx_mask, int slots, int slot_width) 765 + { 766 + struct snd_soc_codec *codec = dai->codec; 767 + struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 768 + unsigned int val = 0; 769 + 770 + if (rx_mask || tx_mask) 771 + val |= RT5514_TDM_MODE; 772 + 773 + if (slots == 4) 774 + val |= RT5514_TDMSLOT_SEL_RX_4CH | RT5514_TDMSLOT_SEL_TX_4CH; 775 + 776 + 777 + switch (slot_width) { 778 + case 20: 779 + val |= RT5514_CH_LEN_RX_20 | RT5514_CH_LEN_TX_20; 780 + break; 781 + 782 + case 24: 783 + val |= RT5514_CH_LEN_RX_24 | RT5514_CH_LEN_TX_24; 784 + break; 785 + 786 + case 32: 787 + val |= RT5514_CH_LEN_RX_32 | RT5514_CH_LEN_TX_32; 788 + break; 789 + 790 + case 16: 791 + default: 792 + break; 793 + } 794 + 795 + regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, RT5514_TDM_MODE | 796 + RT5514_TDMSLOT_SEL_RX_MASK | RT5514_TDMSLOT_SEL_TX_MASK | 797 + RT5514_CH_LEN_RX_MASK | RT5514_CH_LEN_TX_MASK, val); 798 + 799 + return 0; 800 + } 801 + 802 + static int rt5514_probe(struct snd_soc_codec *codec) 803 + { 804 + struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 805 + 806 + rt5514->codec = codec; 807 + 808 + return 0; 809 + } 810 + 811 + static int rt5514_i2c_read(void *context, unsigned int reg, unsigned int *val) 812 + { 813 + struct i2c_client *client = context; 814 + struct rt5514_priv *rt5514 = i2c_get_clientdata(client); 815 + 816 + regmap_read(rt5514->i2c_regmap, reg | RT5514_DSP_MAPPING, val); 817 + 818 + return 0; 819 + } 820 + 821 + static int rt5514_i2c_write(void *context, unsigned int reg, unsigned int val) 822 + { 823 + struct i2c_client *client = context; 824 + struct rt5514_priv *rt5514 = i2c_get_clientdata(client); 825 + 826 + regmap_write(rt5514->i2c_regmap, reg | RT5514_DSP_MAPPING, val); 827 + 828 + return 0; 829 + } 830 + 831 + #define RT5514_STEREO_RATES SNDRV_PCM_RATE_8000_192000 832 + #define RT5514_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 833 + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) 834 + 835 + struct snd_soc_dai_ops rt5514_aif_dai_ops = { 836 + .hw_params = rt5514_hw_params, 837 + .set_fmt = rt5514_set_dai_fmt, 838 + .set_sysclk = rt5514_set_dai_sysclk, 839 + .set_pll = rt5514_set_dai_pll, 840 + .set_tdm_slot = rt5514_set_tdm_slot, 841 + }; 842 + 843 + struct snd_soc_dai_driver rt5514_dai[] = { 844 + { 845 + .name = "rt5514-aif1", 846 + .id = 0, 847 + .capture = { 848 + .stream_name = "AIF1 Capture", 849 + .channels_min = 1, 850 + .channels_max = 4, 851 + .rates = RT5514_STEREO_RATES, 852 + .formats = RT5514_FORMATS, 853 + }, 854 + .ops = &rt5514_aif_dai_ops, 855 + } 856 + }; 857 + 858 + static struct snd_soc_codec_driver soc_codec_dev_rt5514 = { 859 + .probe = rt5514_probe, 860 + .idle_bias_off = true, 861 + .controls = rt5514_snd_controls, 862 + .num_controls = ARRAY_SIZE(rt5514_snd_controls), 863 + .dapm_widgets = rt5514_dapm_widgets, 864 + .num_dapm_widgets = ARRAY_SIZE(rt5514_dapm_widgets), 865 + .dapm_routes = rt5514_dapm_routes, 866 + .num_dapm_routes = ARRAY_SIZE(rt5514_dapm_routes), 867 + }; 868 + 869 + static const struct regmap_config rt5514_i2c_regmap = { 870 + .name = "i2c", 871 + .reg_bits = 32, 872 + .val_bits = 32, 873 + 874 + .max_register = RT5514_DSP_MAPPING | RT5514_VENDOR_ID2, 875 + .readable_reg = rt5514_i2c_readable_register, 876 + 877 + .cache_type = REGCACHE_NONE, 878 + }; 879 + 880 + static const struct regmap_config rt5514_regmap = { 881 + .reg_bits = 16, 882 + .val_bits = 32, 883 + 884 + .max_register = RT5514_VENDOR_ID2, 885 + .volatile_reg = rt5514_volatile_register, 886 + .readable_reg = rt5514_readable_register, 887 + .reg_read = rt5514_i2c_read, 888 + .reg_write = rt5514_i2c_write, 889 + 890 + .cache_type = REGCACHE_RBTREE, 891 + .reg_defaults = rt5514_reg, 892 + .num_reg_defaults = ARRAY_SIZE(rt5514_reg), 893 + .use_single_rw = true, 894 + }; 895 + 896 + static const struct i2c_device_id rt5514_i2c_id[] = { 897 + { "rt5514", 0 }, 898 + { } 899 + }; 900 + MODULE_DEVICE_TABLE(i2c, rt5514_i2c_id); 901 + 902 + #if defined(CONFIG_OF) 903 + static const struct of_device_id rt5514_of_match[] = { 904 + { .compatible = "realtek,rt5514", }, 905 + {}, 906 + }; 907 + MODULE_DEVICE_TABLE(of, rt5514_of_match); 908 + #endif 909 + 910 + static int rt5514_i2c_probe(struct i2c_client *i2c, 911 + const struct i2c_device_id *id) 912 + { 913 + struct rt5514_priv *rt5514; 914 + int ret; 915 + unsigned int val; 916 + 917 + rt5514 = devm_kzalloc(&i2c->dev, sizeof(struct rt5514_priv), 918 + GFP_KERNEL); 919 + if (rt5514 == NULL) 920 + return -ENOMEM; 921 + 922 + i2c_set_clientdata(i2c, rt5514); 923 + 924 + rt5514->i2c_regmap = devm_regmap_init_i2c(i2c, &rt5514_i2c_regmap); 925 + if (IS_ERR(rt5514->i2c_regmap)) { 926 + ret = PTR_ERR(rt5514->i2c_regmap); 927 + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 928 + ret); 929 + return ret; 930 + } 931 + 932 + rt5514->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt5514_regmap); 933 + if (IS_ERR(rt5514->regmap)) { 934 + ret = PTR_ERR(rt5514->regmap); 935 + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 936 + ret); 937 + return ret; 938 + } 939 + 940 + regmap_read(rt5514->regmap, RT5514_VENDOR_ID2, &val); 941 + if (val != RT5514_DEVICE_ID) { 942 + dev_err(&i2c->dev, 943 + "Device with ID register %x is not rt5514\n", val); 944 + return -ENODEV; 945 + } 946 + 947 + ret = regmap_register_patch(rt5514->i2c_regmap, rt5514_i2c_patch, 948 + ARRAY_SIZE(rt5514_i2c_patch)); 949 + if (ret != 0) 950 + dev_warn(&i2c->dev, "Failed to apply i2c_regmap patch: %d\n", 951 + ret); 952 + 953 + ret = regmap_register_patch(rt5514->regmap, rt5514_patch, 954 + ARRAY_SIZE(rt5514_patch)); 955 + if (ret != 0) 956 + dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); 957 + 958 + return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5514, 959 + rt5514_dai, ARRAY_SIZE(rt5514_dai)); 960 + } 961 + 962 + static int rt5514_i2c_remove(struct i2c_client *i2c) 963 + { 964 + snd_soc_unregister_codec(&i2c->dev); 965 + 966 + return 0; 967 + } 968 + 969 + struct i2c_driver rt5514_i2c_driver = { 970 + .driver = { 971 + .name = "rt5514", 972 + .of_match_table = of_match_ptr(rt5514_of_match), 973 + }, 974 + .probe = rt5514_i2c_probe, 975 + .remove = rt5514_i2c_remove, 976 + .id_table = rt5514_i2c_id, 977 + }; 978 + module_i2c_driver(rt5514_i2c_driver); 979 + 980 + MODULE_DESCRIPTION("ASoC RT5514 driver"); 981 + MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); 982 + MODULE_LICENSE("GPL v2");
+252
sound/soc/codecs/rt5514.h
··· 1 + /* 2 + * rt5514.h -- RT5514 ALSA SoC audio driver 3 + * 4 + * Copyright 2015 Realtek Microelectronics 5 + * Author: Oder Chiou <oder_chiou@realtek.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + 12 + #ifndef __RT5514_H__ 13 + #define __RT5514_H__ 14 + 15 + #define RT5514_DEVICE_ID 0x10ec5514 16 + 17 + #define RT5514_RESET 0x2000 18 + #define RT5514_PWR_ANA1 0x2004 19 + #define RT5514_PWR_ANA2 0x2008 20 + #define RT5514_I2S_CTRL1 0x2010 21 + #define RT5514_I2S_CTRL2 0x2014 22 + #define RT5514_VAD_CTRL6 0x2030 23 + #define RT5514_EXT_VAD_CTRL 0x206c 24 + #define RT5514_DIG_IO_CTRL 0x2070 25 + #define RT5514_PAD_CTRL1 0x2080 26 + #define RT5514_DMIC_DATA_CTRL 0x20a0 27 + #define RT5514_DIG_SOURCE_CTRL 0x20a4 28 + #define RT5514_SRC_CTRL 0x20ac 29 + #define RT5514_DOWNFILTER2_CTRL1 0x20d0 30 + #define RT5514_PLL_SOURCE_CTRL 0x2100 31 + #define RT5514_CLK_CTRL1 0x2104 32 + #define RT5514_CLK_CTRL2 0x2108 33 + #define RT5514_PLL3_CALIB_CTRL1 0x2110 34 + #define RT5514_PLL3_CALIB_CTRL5 0x2124 35 + #define RT5514_DELAY_BUF_CTRL1 0x2140 36 + #define RT5514_DELAY_BUF_CTRL3 0x2148 37 + #define RT5514_DOWNFILTER0_CTRL1 0x2190 38 + #define RT5514_DOWNFILTER0_CTRL2 0x2194 39 + #define RT5514_DOWNFILTER0_CTRL3 0x2198 40 + #define RT5514_DOWNFILTER1_CTRL1 0x21a0 41 + #define RT5514_DOWNFILTER1_CTRL2 0x21a4 42 + #define RT5514_DOWNFILTER1_CTRL3 0x21a8 43 + #define RT5514_ANA_CTRL_LDO10 0x2200 44 + #define RT5514_ANA_CTRL_LDO18_16 0x2204 45 + #define RT5514_ANA_CTRL_ADC12 0x2210 46 + #define RT5514_ANA_CTRL_ADC21 0x2214 47 + #define RT5514_ANA_CTRL_ADC22 0x2218 48 + #define RT5514_ANA_CTRL_ADC23 0x221c 49 + #define RT5514_ANA_CTRL_MICBST 0x2220 50 + #define RT5514_ANA_CTRL_ADCFED 0x2224 51 + #define RT5514_ANA_CTRL_INBUF 0x2228 52 + #define RT5514_ANA_CTRL_VREF 0x222c 53 + #define RT5514_ANA_CTRL_PLL3 0x2240 54 + #define RT5514_ANA_CTRL_PLL1_1 0x2260 55 + #define RT5514_ANA_CTRL_PLL1_2 0x2264 56 + #define RT5514_DMIC_LP_CTRL 0x2e00 57 + #define RT5514_MISC_CTRL_DSP 0x2e04 58 + #define RT5514_DSP_CTRL1 0x2f00 59 + #define RT5514_DSP_CTRL3 0x2f08 60 + #define RT5514_DSP_CTRL4 0x2f10 61 + #define RT5514_VENDOR_ID1 0x2ff0 62 + #define RT5514_VENDOR_ID2 0x2ff4 63 + 64 + #define RT5514_DSP_MAPPING 0x18000000 65 + 66 + /* RT5514_PWR_ANA1 (0x2004) */ 67 + #define RT5514_POW_LDO18_IN (0x1 << 5) 68 + #define RT5514_POW_LDO18_IN_BIT 5 69 + #define RT5514_POW_LDO18_ADC (0x1 << 4) 70 + #define RT5514_POW_LDO18_ADC_BIT 4 71 + #define RT5514_POW_LDO21 (0x1 << 3) 72 + #define RT5514_POW_LDO21_BIT 3 73 + #define RT5514_POW_BG_LDO18_IN (0x1 << 2) 74 + #define RT5514_POW_BG_LDO18_IN_BIT 2 75 + #define RT5514_POW_BG_LDO21 (0x1 << 1) 76 + #define RT5514_POW_BG_LDO21_BIT 1 77 + 78 + /* RT5514_PWR_ANA2 (0x2008) */ 79 + #define RT5514_POW_PLL1 (0x1 << 18) 80 + #define RT5514_POW_PLL1_BIT 18 81 + #define RT5514_POW_PLL1_LDO (0x1 << 16) 82 + #define RT5514_POW_PLL1_LDO_BIT 16 83 + #define RT5514_POW_BG_MBIAS (0x1 << 15) 84 + #define RT5514_POW_BG_MBIAS_BIT 15 85 + #define RT5514_POW_MBIAS (0x1 << 14) 86 + #define RT5514_POW_MBIAS_BIT 14 87 + #define RT5514_POW_VREF2 (0x1 << 13) 88 + #define RT5514_POW_VREF2_BIT 13 89 + #define RT5514_POW_VREF1 (0x1 << 12) 90 + #define RT5514_POW_VREF1_BIT 12 91 + #define RT5514_POWR_LDO16 (0x1 << 11) 92 + #define RT5514_POWR_LDO16_BIT 11 93 + #define RT5514_POWL_LDO16 (0x1 << 10) 94 + #define RT5514_POWL_LDO16_BIT 10 95 + #define RT5514_POW_ADC2 (0x1 << 9) 96 + #define RT5514_POW_ADC2_BIT 9 97 + #define RT5514_POW_INPUT_BUF (0x1 << 8) 98 + #define RT5514_POW_INPUT_BUF_BIT 8 99 + #define RT5514_POW_ADC1_R (0x1 << 7) 100 + #define RT5514_POW_ADC1_R_BIT 7 101 + #define RT5514_POW_ADC1_L (0x1 << 6) 102 + #define RT5514_POW_ADC1_L_BIT 6 103 + #define RT5514_POW2_BSTR (0x1 << 5) 104 + #define RT5514_POW2_BSTR_BIT 5 105 + #define RT5514_POW2_BSTL (0x1 << 4) 106 + #define RT5514_POW2_BSTL_BIT 4 107 + #define RT5514_POW_BSTR (0x1 << 3) 108 + #define RT5514_POW_BSTR_BIT 3 109 + #define RT5514_POW_BSTL (0x1 << 2) 110 + #define RT5514_POW_BSTL_BIT 2 111 + #define RT5514_POW_ADCFEDR (0x1 << 1) 112 + #define RT5514_POW_ADCFEDR_BIT 1 113 + #define RT5514_POW_ADCFEDL (0x1 << 0) 114 + #define RT5514_POW_ADCFEDL_BIT 0 115 + 116 + /* RT5514_I2S_CTRL1 (0x2010) */ 117 + #define RT5514_TDM_MODE (0x1 << 28) 118 + #define RT5514_TDM_MODE_SFT 28 119 + #define RT5514_I2S_LR_MASK (0x1 << 26) 120 + #define RT5514_I2S_LR_SFT 26 121 + #define RT5514_I2S_LR_NOR (0x0 << 26) 122 + #define RT5514_I2S_LR_INV (0x1 << 26) 123 + #define RT5514_I2S_BP_MASK (0x1 << 25) 124 + #define RT5514_I2S_BP_SFT 25 125 + #define RT5514_I2S_BP_NOR (0x0 << 25) 126 + #define RT5514_I2S_BP_INV (0x1 << 25) 127 + #define RT5514_I2S_DF_MASK (0x7 << 16) 128 + #define RT5514_I2S_DF_SFT 16 129 + #define RT5514_I2S_DF_I2S (0x0 << 16) 130 + #define RT5514_I2S_DF_LEFT (0x1 << 16) 131 + #define RT5514_I2S_DF_PCM_A (0x2 << 16) 132 + #define RT5514_I2S_DF_PCM_B (0x3 << 16) 133 + #define RT5514_TDMSLOT_SEL_RX_MASK (0x3 << 10) 134 + #define RT5514_TDMSLOT_SEL_RX_SFT 10 135 + #define RT5514_TDMSLOT_SEL_RX_4CH (0x1 << 10) 136 + #define RT5514_CH_LEN_RX_MASK (0x3 << 8) 137 + #define RT5514_CH_LEN_RX_SFT 8 138 + #define RT5514_CH_LEN_RX_16 (0x0 << 8) 139 + #define RT5514_CH_LEN_RX_20 (0x1 << 8) 140 + #define RT5514_CH_LEN_RX_24 (0x2 << 8) 141 + #define RT5514_CH_LEN_RX_32 (0x3 << 8) 142 + #define RT5514_TDMSLOT_SEL_TX_MASK (0x3 << 6) 143 + #define RT5514_TDMSLOT_SEL_TX_SFT 6 144 + #define RT5514_TDMSLOT_SEL_TX_4CH (0x1 << 6) 145 + #define RT5514_CH_LEN_TX_MASK (0x3 << 4) 146 + #define RT5514_CH_LEN_TX_SFT 4 147 + #define RT5514_CH_LEN_TX_16 (0x0 << 4) 148 + #define RT5514_CH_LEN_TX_20 (0x1 << 4) 149 + #define RT5514_CH_LEN_TX_24 (0x2 << 4) 150 + #define RT5514_CH_LEN_TX_32 (0x3 << 4) 151 + #define RT5514_I2S_DL_MASK (0x3 << 0) 152 + #define RT5514_I2S_DL_SFT 0 153 + #define RT5514_I2S_DL_16 (0x0 << 0) 154 + #define RT5514_I2S_DL_20 (0x1 << 0) 155 + #define RT5514_I2S_DL_24 (0x2 << 0) 156 + #define RT5514_I2S_DL_8 (0x3 << 0) 157 + 158 + /* RT5514_DIG_SOURCE_CTRL (0x20a4) */ 159 + #define RT5514_AD1_DMIC_INPUT_SEL (0x1 << 1) 160 + #define RT5514_AD1_DMIC_INPUT_SEL_SFT 1 161 + #define RT5514_AD0_DMIC_INPUT_SEL (0x1 << 0) 162 + #define RT5514_AD0_DMIC_INPUT_SEL_SFT 0 163 + 164 + /* RT5514_PLL_SOURCE_CTRL (0x2100) */ 165 + #define RT5514_PLL_1_SEL_MASK (0x7 << 12) 166 + #define RT5514_PLL_1_SEL_SFT 12 167 + #define RT5514_PLL_1_SEL_SCLK (0x3 << 12) 168 + #define RT5514_PLL_1_SEL_MCLK (0x4 << 12) 169 + 170 + /* RT5514_CLK_CTRL1 (0x2104) */ 171 + #define RT5514_CLK_AD_ANA1_EN (0x1 << 31) 172 + #define RT5514_CLK_AD_ANA1_EN_BIT 31 173 + #define RT5514_CLK_AD1_EN (0x1 << 24) 174 + #define RT5514_CLK_AD1_EN_BIT 24 175 + #define RT5514_CLK_AD0_EN (0x1 << 23) 176 + #define RT5514_CLK_AD0_EN_BIT 23 177 + #define RT5514_CLK_DMIC_OUT_SEL_MASK (0x7 << 8) 178 + #define RT5514_CLK_DMIC_OUT_SEL_SFT 8 179 + 180 + /* RT5514_CLK_CTRL2 (0x2108) */ 181 + #define RT5514_CLK_SYS_DIV_OUT_MASK (0x7 << 8) 182 + #define RT5514_CLK_SYS_DIV_OUT_SFT 8 183 + #define RT5514_SEL_ADC_OSR_MASK (0x7 << 4) 184 + #define RT5514_SEL_ADC_OSR_SFT 4 185 + #define RT5514_CLK_SYS_PRE_SEL_MASK (0x3 << 0) 186 + #define RT5514_CLK_SYS_PRE_SEL_SFT 0 187 + #define RT5514_CLK_SYS_PRE_SEL_MCLK (0x2 << 0) 188 + #define RT5514_CLK_SYS_PRE_SEL_PLL (0x3 << 0) 189 + 190 + /* RT5514_DOWNFILTER_CTRL (0x2190 0x2194 0x21a0 0x21a4) */ 191 + #define RT5514_AD_DMIC_MIX (0x1 << 11) 192 + #define RT5514_AD_DMIC_MIX_BIT 11 193 + #define RT5514_AD_AD_MIX (0x1 << 10) 194 + #define RT5514_AD_AD_MIX_BIT 10 195 + #define RT5514_AD_AD_MUTE (0x1 << 7) 196 + #define RT5514_AD_AD_MUTE_BIT 7 197 + #define RT5514_AD_GAIN_MASK (0x7f << 0) 198 + #define RT5514_AD_GAIN_SFT 0 199 + 200 + /* RT5514_ANA_CTRL_MICBST (0x2220) */ 201 + #define RT5514_SEL_BSTL_MASK (0xf << 4) 202 + #define RT5514_SEL_BSTL_SFT 4 203 + #define RT5514_SEL_BSTR_MASK (0xf << 0) 204 + #define RT5514_SEL_BSTR_SFT 0 205 + 206 + /* RT5514_ANA_CTRL_PLL1_1 (0x2260) */ 207 + #define RT5514_PLL_K_MAX 0x1f 208 + #define RT5514_PLL_K_MASK (RT5514_PLL_K_MAX << 16) 209 + #define RT5514_PLL_K_SFT 16 210 + #define RT5514_PLL_N_MAX 0x1ff 211 + #define RT5514_PLL_N_MASK (RT5514_PLL_N_MAX << 7) 212 + #define RT5514_PLL_N_SFT 4 213 + #define RT5514_PLL_M_MAX 0xf 214 + #define RT5514_PLL_M_MASK (RT5514_PLL_M_MAX << 0) 215 + #define RT5514_PLL_M_SFT 0 216 + 217 + /* RT5514_ANA_CTRL_PLL1_2 (0x2264) */ 218 + #define RT5514_PLL_M_BP (0x1 << 2) 219 + #define RT5514_PLL_M_BP_SFT 2 220 + #define RT5514_PLL_K_BP (0x1 << 1) 221 + #define RT5514_PLL_K_BP_SFT 1 222 + #define RT5514_EN_LDO_PLL1 (0x1 << 0) 223 + #define RT5514_EN_LDO_PLL1_BIT 0 224 + 225 + #define RT5514_PLL_INP_MAX 40000000 226 + #define RT5514_PLL_INP_MIN 256000 227 + 228 + /* System Clock Source */ 229 + enum { 230 + RT5514_SCLK_S_MCLK, 231 + RT5514_SCLK_S_PLL1, 232 + }; 233 + 234 + /* PLL1 Source */ 235 + enum { 236 + RT5514_PLL1_S_MCLK, 237 + RT5514_PLL1_S_BCLK, 238 + }; 239 + 240 + struct rt5514_priv { 241 + struct snd_soc_codec *codec; 242 + struct regmap *i2c_regmap, *regmap; 243 + int sysclk; 244 + int sysclk_src; 245 + int lrck; 246 + int bclk; 247 + int pll_src; 248 + int pll_in; 249 + int pll_out; 250 + }; 251 + 252 + #endif /* __RT5514_H__ */