0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk.h>
0009 #include <linux/gpio/consumer.h>
0010 #include <linux/mfd/wm8994/registers.h>
0011 #include <linux/module.h>
0012 #include <linux/of.h>
0013 #include <linux/of_device.h>
0014 #include <linux/of_gpio.h>
0015 #include <linux/regulator/consumer.h>
0016 #include <sound/jack.h>
0017 #include <sound/soc.h>
0018 #include <sound/soc-dapm.h>
0019
0020 #include "i2s.h"
0021 #include "../codecs/wm8994.h"
0022
0023
0024
0025
0026
0027 #define MCLK1_RATE 24000000U
0028 #define MCLK2_RATE 32768U
0029 #define DEFAULT_FLL1_RATE 11289600U
0030
0031 struct midas_priv {
0032 struct regulator *reg_mic_bias;
0033 struct regulator *reg_submic_bias;
0034 struct gpio_desc *gpio_fm_sel;
0035 struct gpio_desc *gpio_lineout_sel;
0036 unsigned int fll1_rate;
0037
0038 struct snd_soc_jack headset_jack;
0039 };
0040
0041 static int midas_start_fll1(struct snd_soc_pcm_runtime *rtd, unsigned int rate)
0042 {
0043 struct snd_soc_card *card = rtd->card;
0044 struct midas_priv *priv = snd_soc_card_get_drvdata(card);
0045 struct snd_soc_dai *aif1_dai = asoc_rtd_to_codec(rtd, 0);
0046 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0047 int ret;
0048
0049 if (!rate)
0050 rate = priv->fll1_rate;
0051
0052
0053
0054
0055 if (!rate)
0056 rate = DEFAULT_FLL1_RATE;
0057
0058 if (rate != priv->fll1_rate && priv->fll1_rate) {
0059
0060 ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2,
0061 MCLK2_RATE, SND_SOC_CLOCK_IN);
0062 if (ret < 0) {
0063 dev_err(card->dev, "Unable to switch to MCLK2: %d\n", ret);
0064 return ret;
0065 }
0066 }
0067
0068 ret = snd_soc_dai_set_pll(aif1_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1,
0069 MCLK1_RATE, rate);
0070 if (ret < 0) {
0071 dev_err(card->dev, "Failed to set FLL1 rate: %d\n", ret);
0072 return ret;
0073 }
0074 priv->fll1_rate = rate;
0075
0076 ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_FLL1,
0077 priv->fll1_rate, SND_SOC_CLOCK_IN);
0078 if (ret < 0) {
0079 dev_err(card->dev, "Failed to set SYSCLK source: %d\n", ret);
0080 return ret;
0081 }
0082
0083 ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_OPCLK, 0,
0084 SAMSUNG_I2S_OPCLK_PCLK);
0085 if (ret < 0) {
0086 dev_err(card->dev, "Failed to set OPCLK source: %d\n", ret);
0087 return ret;
0088 }
0089
0090 return 0;
0091 }
0092
0093 static int midas_stop_fll1(struct snd_soc_pcm_runtime *rtd)
0094 {
0095 struct snd_soc_card *card = rtd->card;
0096 struct midas_priv *priv = snd_soc_card_get_drvdata(card);
0097 struct snd_soc_dai *aif1_dai = asoc_rtd_to_codec(rtd, 0);
0098 int ret;
0099
0100 ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2,
0101 MCLK2_RATE, SND_SOC_CLOCK_IN);
0102 if (ret < 0) {
0103 dev_err(card->dev, "Unable to switch to MCLK2: %d\n", ret);
0104 return ret;
0105 }
0106
0107 ret = snd_soc_dai_set_pll(aif1_dai, WM8994_FLL1, 0, 0, 0);
0108 if (ret < 0) {
0109 dev_err(card->dev, "Unable to stop FLL1: %d\n", ret);
0110 return ret;
0111 }
0112
0113 priv->fll1_rate = 0;
0114
0115 return 0;
0116 }
0117
0118 static int midas_aif1_hw_params(struct snd_pcm_substream *substream,
0119 struct snd_pcm_hw_params *params)
0120 {
0121 struct snd_soc_pcm_runtime *rtd = substream->private_data;
0122 unsigned int pll_out;
0123
0124
0125 if (params_rate(params) == 8000 || params_rate(params) == 11025)
0126 pll_out = params_rate(params) * 512;
0127 else
0128 pll_out = params_rate(params) * 256;
0129
0130 return midas_start_fll1(rtd, pll_out);
0131 }
0132
0133 static const struct snd_soc_ops midas_aif1_ops = {
0134 .hw_params = midas_aif1_hw_params,
0135 };
0136
0137
0138
0139
0140
0141 static int midas_ext_spkmode(struct snd_soc_dapm_widget *w,
0142 struct snd_kcontrol *kcontrol, int event)
0143 {
0144 struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
0145 int ret = 0;
0146
0147 switch (event) {
0148 case SND_SOC_DAPM_PRE_PMU:
0149 ret = snd_soc_component_update_bits(codec, WM8994_SPKOUT_MIXERS,
0150 WM8994_SPKMIXR_TO_SPKOUTL_MASK,
0151 WM8994_SPKMIXR_TO_SPKOUTL);
0152 break;
0153 case SND_SOC_DAPM_POST_PMD:
0154 ret = snd_soc_component_update_bits(codec, WM8994_SPKOUT_MIXERS,
0155 WM8994_SPKMIXR_TO_SPKOUTL_MASK,
0156 0);
0157 break;
0158 }
0159
0160 return ret;
0161 }
0162
0163 static int midas_mic_bias(struct snd_soc_dapm_widget *w,
0164 struct snd_kcontrol *kcontrol, int event)
0165 {
0166 struct snd_soc_card *card = w->dapm->card;
0167 struct midas_priv *priv = snd_soc_card_get_drvdata(card);
0168
0169 switch (event) {
0170 case SND_SOC_DAPM_PRE_PMU:
0171 return regulator_enable(priv->reg_mic_bias);
0172 case SND_SOC_DAPM_POST_PMD:
0173 return regulator_disable(priv->reg_mic_bias);
0174 }
0175
0176 return 0;
0177 }
0178
0179 static int midas_submic_bias(struct snd_soc_dapm_widget *w,
0180 struct snd_kcontrol *kcontrol, int event)
0181 {
0182 struct snd_soc_card *card = w->dapm->card;
0183 struct midas_priv *priv = snd_soc_card_get_drvdata(card);
0184
0185 switch (event) {
0186 case SND_SOC_DAPM_PRE_PMU:
0187 return regulator_enable(priv->reg_submic_bias);
0188 case SND_SOC_DAPM_POST_PMD:
0189 return regulator_disable(priv->reg_submic_bias);
0190 }
0191
0192 return 0;
0193 }
0194
0195 static int midas_fm_set(struct snd_soc_dapm_widget *w,
0196 struct snd_kcontrol *kcontrol, int event)
0197 {
0198 struct snd_soc_card *card = w->dapm->card;
0199 struct midas_priv *priv = snd_soc_card_get_drvdata(card);
0200
0201 if (!priv->gpio_fm_sel)
0202 return 0;
0203
0204 switch (event) {
0205 case SND_SOC_DAPM_PRE_PMU:
0206 gpiod_set_value_cansleep(priv->gpio_fm_sel, 1);
0207 break;
0208 case SND_SOC_DAPM_POST_PMD:
0209 gpiod_set_value_cansleep(priv->gpio_fm_sel, 0);
0210 break;
0211 }
0212
0213 return 0;
0214 }
0215
0216 static int midas_line_set(struct snd_soc_dapm_widget *w,
0217 struct snd_kcontrol *kcontrol, int event)
0218 {
0219 struct snd_soc_card *card = w->dapm->card;
0220 struct midas_priv *priv = snd_soc_card_get_drvdata(card);
0221
0222 if (!priv->gpio_lineout_sel)
0223 return 0;
0224
0225 switch (event) {
0226 case SND_SOC_DAPM_PRE_PMU:
0227 gpiod_set_value_cansleep(priv->gpio_lineout_sel, 1);
0228 break;
0229 case SND_SOC_DAPM_POST_PMD:
0230 gpiod_set_value_cansleep(priv->gpio_lineout_sel, 0);
0231 break;
0232 }
0233
0234 return 0;
0235 }
0236
0237 static const struct snd_kcontrol_new midas_controls[] = {
0238 SOC_DAPM_PIN_SWITCH("HP"),
0239
0240 SOC_DAPM_PIN_SWITCH("SPK"),
0241 SOC_DAPM_PIN_SWITCH("RCV"),
0242
0243 SOC_DAPM_PIN_SWITCH("LINE"),
0244 SOC_DAPM_PIN_SWITCH("HDMI"),
0245
0246 SOC_DAPM_PIN_SWITCH("Main Mic"),
0247 SOC_DAPM_PIN_SWITCH("Sub Mic"),
0248 SOC_DAPM_PIN_SWITCH("Headset Mic"),
0249
0250 SOC_DAPM_PIN_SWITCH("FM In"),
0251 };
0252
0253 static const struct snd_soc_dapm_widget midas_dapm_widgets[] = {
0254 SND_SOC_DAPM_HP("HP", NULL),
0255
0256 SND_SOC_DAPM_SPK("SPK", midas_ext_spkmode),
0257 SND_SOC_DAPM_SPK("RCV", NULL),
0258
0259
0260 SND_SOC_DAPM_LINE("LINE", midas_line_set),
0261 SND_SOC_DAPM_LINE("HDMI", NULL),
0262 SND_SOC_DAPM_LINE("FM In", midas_fm_set),
0263
0264 SND_SOC_DAPM_MIC("Headset Mic", NULL),
0265 SND_SOC_DAPM_MIC("Main Mic", midas_mic_bias),
0266 SND_SOC_DAPM_MIC("Sub Mic", midas_submic_bias),
0267 };
0268
0269 static int midas_set_bias_level(struct snd_soc_card *card,
0270 struct snd_soc_dapm_context *dapm,
0271 enum snd_soc_bias_level level)
0272 {
0273 struct snd_soc_pcm_runtime *rtd = snd_soc_get_pcm_runtime(card,
0274 &card->dai_link[0]);
0275 struct snd_soc_dai *aif1_dai = asoc_rtd_to_codec(rtd, 0);
0276
0277 if (dapm->dev != aif1_dai->dev)
0278 return 0;
0279
0280 switch (level) {
0281 case SND_SOC_BIAS_STANDBY:
0282 return midas_stop_fll1(rtd);
0283 case SND_SOC_BIAS_PREPARE:
0284 return midas_start_fll1(rtd, 0);
0285 default:
0286 break;
0287 }
0288
0289 return 0;
0290 }
0291
0292 static int midas_late_probe(struct snd_soc_card *card)
0293 {
0294 struct snd_soc_pcm_runtime *rtd = snd_soc_get_pcm_runtime(card,
0295 &card->dai_link[0]);
0296 struct snd_soc_dai *aif1_dai = asoc_rtd_to_codec(rtd, 0);
0297 struct midas_priv *priv = snd_soc_card_get_drvdata(card);
0298 int ret;
0299
0300
0301 ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2, MCLK2_RATE,
0302 SND_SOC_CLOCK_IN);
0303 if (ret < 0) {
0304 dev_err(aif1_dai->dev, "Failed to switch to MCLK2: %d\n", ret);
0305 return ret;
0306 }
0307
0308 ret = snd_soc_card_jack_new(card, "Headset",
0309 SND_JACK_HEADSET | SND_JACK_MECHANICAL |
0310 SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 |
0311 SND_JACK_BTN_3 | SND_JACK_BTN_4 | SND_JACK_BTN_5,
0312 &priv->headset_jack);
0313 if (ret)
0314 return ret;
0315
0316 wm8958_mic_detect(aif1_dai->component, &priv->headset_jack,
0317 NULL, NULL, NULL, NULL);
0318 return 0;
0319 }
0320
0321 static struct snd_soc_dai_driver midas_ext_dai[] = {
0322 {
0323 .name = "Voice call",
0324 .playback = {
0325 .channels_min = 1,
0326 .channels_max = 2,
0327 .rate_min = 8000,
0328 .rate_max = 16000,
0329 .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
0330 .formats = SNDRV_PCM_FMTBIT_S16_LE,
0331 },
0332 .capture = {
0333 .channels_min = 1,
0334 .channels_max = 2,
0335 .rate_min = 8000,
0336 .rate_max = 16000,
0337 .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
0338 .formats = SNDRV_PCM_FMTBIT_S16_LE,
0339 },
0340 },
0341 {
0342 .name = "Bluetooth",
0343 .playback = {
0344 .channels_min = 1,
0345 .channels_max = 2,
0346 .rate_min = 8000,
0347 .rate_max = 16000,
0348 .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
0349 .formats = SNDRV_PCM_FMTBIT_S16_LE,
0350 },
0351 .capture = {
0352 .channels_min = 1,
0353 .channels_max = 2,
0354 .rate_min = 8000,
0355 .rate_max = 16000,
0356 .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
0357 .formats = SNDRV_PCM_FMTBIT_S16_LE,
0358 },
0359 },
0360 };
0361
0362 static const struct snd_soc_component_driver midas_component = {
0363 .name = "midas-audio",
0364 };
0365
0366 SND_SOC_DAILINK_DEFS(wm1811_hifi,
0367 DAILINK_COMP_ARRAY(COMP_EMPTY()),
0368 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif1")),
0369 DAILINK_COMP_ARRAY(COMP_EMPTY()));
0370
0371 SND_SOC_DAILINK_DEFS(wm1811_voice,
0372 DAILINK_COMP_ARRAY(COMP_EMPTY()),
0373 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif2")),
0374 DAILINK_COMP_ARRAY(COMP_EMPTY()));
0375
0376 SND_SOC_DAILINK_DEFS(wm1811_bt,
0377 DAILINK_COMP_ARRAY(COMP_EMPTY()),
0378 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif3")),
0379 DAILINK_COMP_ARRAY(COMP_EMPTY()));
0380
0381 static struct snd_soc_dai_link midas_dai[] = {
0382 {
0383 .name = "WM8994 AIF1",
0384 .stream_name = "HiFi Primary",
0385 .ops = &midas_aif1_ops,
0386 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
0387 SND_SOC_DAIFMT_CBM_CFM,
0388 SND_SOC_DAILINK_REG(wm1811_hifi),
0389 }, {
0390 .name = "WM1811 Voice",
0391 .stream_name = "Voice call",
0392 .ignore_suspend = 1,
0393 SND_SOC_DAILINK_REG(wm1811_voice),
0394 }, {
0395 .name = "WM1811 BT",
0396 .stream_name = "Bluetooth",
0397 .ignore_suspend = 1,
0398 SND_SOC_DAILINK_REG(wm1811_bt),
0399 },
0400 };
0401
0402 static struct snd_soc_card midas_card = {
0403 .name = "Midas WM1811",
0404 .owner = THIS_MODULE,
0405
0406 .dai_link = midas_dai,
0407 .num_links = ARRAY_SIZE(midas_dai),
0408 .controls = midas_controls,
0409 .num_controls = ARRAY_SIZE(midas_controls),
0410 .dapm_widgets = midas_dapm_widgets,
0411 .num_dapm_widgets = ARRAY_SIZE(midas_dapm_widgets),
0412
0413 .set_bias_level = midas_set_bias_level,
0414 .late_probe = midas_late_probe,
0415 };
0416
0417 static int midas_probe(struct platform_device *pdev)
0418 {
0419 struct device_node *cpu_dai_node = NULL, *codec_dai_node = NULL;
0420 struct device_node *cpu = NULL, *codec = NULL;
0421 struct snd_soc_card *card = &midas_card;
0422 struct device *dev = &pdev->dev;
0423 static struct snd_soc_dai_link *dai_link;
0424 struct midas_priv *priv;
0425 int ret, i;
0426
0427 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0428 if (!priv)
0429 return -ENOMEM;
0430
0431 snd_soc_card_set_drvdata(card, priv);
0432 card->dev = dev;
0433
0434 priv->reg_mic_bias = devm_regulator_get(dev, "mic-bias");
0435 if (IS_ERR(priv->reg_mic_bias)) {
0436 dev_err(dev, "Failed to get mic bias regulator\n");
0437 return PTR_ERR(priv->reg_mic_bias);
0438 }
0439
0440 priv->reg_submic_bias = devm_regulator_get(dev, "submic-bias");
0441 if (IS_ERR(priv->reg_submic_bias)) {
0442 dev_err(dev, "Failed to get submic bias regulator\n");
0443 return PTR_ERR(priv->reg_submic_bias);
0444 }
0445
0446 priv->gpio_fm_sel = devm_gpiod_get_optional(dev, "fm-sel", GPIOD_OUT_HIGH);
0447 if (IS_ERR(priv->gpio_fm_sel)) {
0448 dev_err(dev, "Failed to get FM selection GPIO\n");
0449 return PTR_ERR(priv->gpio_fm_sel);
0450 }
0451
0452 priv->gpio_lineout_sel = devm_gpiod_get_optional(dev, "lineout-sel",
0453 GPIOD_OUT_HIGH);
0454 if (IS_ERR(priv->gpio_lineout_sel)) {
0455 dev_err(dev, "Failed to get line out selection GPIO\n");
0456 return PTR_ERR(priv->gpio_lineout_sel);
0457 }
0458
0459 ret = snd_soc_of_parse_card_name(card, "model");
0460 if (ret < 0) {
0461 dev_err(dev, "Card name is not specified\n");
0462 return ret;
0463 }
0464
0465 ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing");
0466 if (ret < 0) {
0467 dev_err(dev, "Audio routing invalid/unspecified\n");
0468 return ret;
0469 }
0470
0471 cpu = of_get_child_by_name(dev->of_node, "cpu");
0472 if (!cpu)
0473 return -EINVAL;
0474
0475 codec = of_get_child_by_name(dev->of_node, "codec");
0476 if (!codec) {
0477 of_node_put(cpu);
0478 return -EINVAL;
0479 }
0480
0481 cpu_dai_node = of_parse_phandle(cpu, "sound-dai", 0);
0482 of_node_put(cpu);
0483 if (!cpu_dai_node) {
0484 dev_err(dev, "parsing cpu/sound-dai failed\n");
0485 of_node_put(codec);
0486 return -EINVAL;
0487 }
0488
0489 codec_dai_node = of_parse_phandle(codec, "sound-dai", 0);
0490 of_node_put(codec);
0491 if (!codec_dai_node) {
0492 dev_err(dev, "audio-codec property invalid/missing\n");
0493 ret = -EINVAL;
0494 goto put_cpu_dai_node;
0495 }
0496
0497 for_each_card_prelinks(card, i, dai_link) {
0498 dai_link->codecs->of_node = codec_dai_node;
0499 dai_link->cpus->of_node = cpu_dai_node;
0500 dai_link->platforms->of_node = cpu_dai_node;
0501 }
0502
0503 ret = devm_snd_soc_register_component(dev, &midas_component,
0504 midas_ext_dai, ARRAY_SIZE(midas_ext_dai));
0505 if (ret < 0) {
0506 dev_err(dev, "Failed to register component: %d\n", ret);
0507 goto put_codec_dai_node;
0508 }
0509
0510 ret = devm_snd_soc_register_card(dev, card);
0511 if (ret < 0) {
0512 dev_err(dev, "Failed to register card: %d\n", ret);
0513 goto put_codec_dai_node;
0514 }
0515
0516 return 0;
0517
0518 put_codec_dai_node:
0519 of_node_put(codec_dai_node);
0520 put_cpu_dai_node:
0521 of_node_put(cpu_dai_node);
0522 return ret;
0523 }
0524
0525 static const struct of_device_id midas_of_match[] = {
0526 { .compatible = "samsung,midas-audio" },
0527 { },
0528 };
0529 MODULE_DEVICE_TABLE(of, midas_of_match);
0530
0531 static struct platform_driver midas_driver = {
0532 .driver = {
0533 .name = "midas-audio",
0534 .of_match_table = midas_of_match,
0535 .pm = &snd_soc_pm_ops,
0536 },
0537 .probe = midas_probe,
0538 };
0539 module_platform_driver(midas_driver);
0540
0541 MODULE_AUTHOR("Simon Shields <simon@lineageos.org>");
0542 MODULE_DESCRIPTION("ASoC support for Midas");
0543 MODULE_LICENSE("GPL v2");