1*85565f80SUday M Bhat // SPDX-License-Identifier: GPL-2.0-only 2*85565f80SUday M Bhat // Copyright (c) 2020 Intel Corporation 3*85565f80SUday M Bhat // 4*85565f80SUday M Bhat // sof_sdw_max98373 - Helpers to handle 2x MAX98373 5*85565f80SUday M Bhat // codec devices from generic machine driver 6*85565f80SUday M Bhat 7*85565f80SUday M Bhat #include <linux/device.h> 8*85565f80SUday M Bhat #include <linux/errno.h> 9*85565f80SUday M Bhat #include <sound/control.h> 10*85565f80SUday M Bhat #include <sound/soc.h> 11*85565f80SUday M Bhat #include <sound/soc-acpi.h> 12*85565f80SUday M Bhat #include <sound/soc-dapm.h> 13*85565f80SUday M Bhat #include "sof_sdw_common.h" 14*85565f80SUday M Bhat #include "sof_maxim_common.h" 15*85565f80SUday M Bhat 16*85565f80SUday M Bhat static const struct snd_soc_dapm_widget mx8373_widgets[] = { 17*85565f80SUday M Bhat SND_SOC_DAPM_SPK("Left Spk", NULL), 18*85565f80SUday M Bhat SND_SOC_DAPM_SPK("Right Spk", NULL), 19*85565f80SUday M Bhat }; 20*85565f80SUday M Bhat 21*85565f80SUday M Bhat static const struct snd_kcontrol_new mx8373_controls[] = { 22*85565f80SUday M Bhat SOC_DAPM_PIN_SWITCH("Left Spk"), 23*85565f80SUday M Bhat SOC_DAPM_PIN_SWITCH("Right Spk"), 24*85565f80SUday M Bhat }; 25*85565f80SUday M Bhat 26*85565f80SUday M Bhat static int spk_init(struct snd_soc_pcm_runtime *rtd) 27*85565f80SUday M Bhat { 28*85565f80SUday M Bhat struct snd_soc_card *card = rtd->card; 29*85565f80SUday M Bhat int ret; 30*85565f80SUday M Bhat 31*85565f80SUday M Bhat card->components = devm_kasprintf(card->dev, GFP_KERNEL, 32*85565f80SUday M Bhat "%s spk:mx8373", 33*85565f80SUday M Bhat card->components); 34*85565f80SUday M Bhat if (!card->components) 35*85565f80SUday M Bhat return -ENOMEM; 36*85565f80SUday M Bhat 37*85565f80SUday M Bhat ret = snd_soc_add_card_controls(card, mx8373_controls, 38*85565f80SUday M Bhat ARRAY_SIZE(mx8373_controls)); 39*85565f80SUday M Bhat if (ret) { 40*85565f80SUday M Bhat dev_err(card->dev, "mx8373 ctrls addition failed: %d\n", ret); 41*85565f80SUday M Bhat return ret; 42*85565f80SUday M Bhat } 43*85565f80SUday M Bhat 44*85565f80SUday M Bhat ret = snd_soc_dapm_new_controls(&card->dapm, mx8373_widgets, 45*85565f80SUday M Bhat ARRAY_SIZE(mx8373_widgets)); 46*85565f80SUday M Bhat if (ret) { 47*85565f80SUday M Bhat dev_err(card->dev, "mx8373 widgets addition failed: %d\n", ret); 48*85565f80SUday M Bhat return ret; 49*85565f80SUday M Bhat } 50*85565f80SUday M Bhat 51*85565f80SUday M Bhat ret = snd_soc_dapm_add_routes(&card->dapm, max_98373_dapm_routes, 2); 52*85565f80SUday M Bhat if (ret) 53*85565f80SUday M Bhat dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); 54*85565f80SUday M Bhat 55*85565f80SUday M Bhat return ret; 56*85565f80SUday M Bhat } 57*85565f80SUday M Bhat 58*85565f80SUday M Bhat static int mx8373_enable_spk_pin(struct snd_pcm_substream *substream, bool enable) 59*85565f80SUday M Bhat { 60*85565f80SUday M Bhat struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 61*85565f80SUday M Bhat struct snd_soc_dai *codec_dai; 62*85565f80SUday M Bhat struct snd_soc_dai *cpu_dai; 63*85565f80SUday M Bhat int ret; 64*85565f80SUday M Bhat int j; 65*85565f80SUday M Bhat 66*85565f80SUday M Bhat /* set spk pin by playback only */ 67*85565f80SUday M Bhat if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 68*85565f80SUday M Bhat return 0; 69*85565f80SUday M Bhat 70*85565f80SUday M Bhat cpu_dai = asoc_rtd_to_cpu(rtd, 0); 71*85565f80SUday M Bhat for_each_rtd_codec_dais(rtd, j, codec_dai) { 72*85565f80SUday M Bhat struct snd_soc_dapm_context *dapm = 73*85565f80SUday M Bhat snd_soc_component_get_dapm(cpu_dai->component); 74*85565f80SUday M Bhat char pin_name[16]; 75*85565f80SUday M Bhat 76*85565f80SUday M Bhat snprintf(pin_name, ARRAY_SIZE(pin_name), "%s Spk", 77*85565f80SUday M Bhat codec_dai->component->name_prefix); 78*85565f80SUday M Bhat 79*85565f80SUday M Bhat if (enable) 80*85565f80SUday M Bhat ret = snd_soc_dapm_enable_pin(dapm, pin_name); 81*85565f80SUday M Bhat else 82*85565f80SUday M Bhat ret = snd_soc_dapm_disable_pin(dapm, pin_name); 83*85565f80SUday M Bhat 84*85565f80SUday M Bhat if (!ret) 85*85565f80SUday M Bhat snd_soc_dapm_sync(dapm); 86*85565f80SUday M Bhat } 87*85565f80SUday M Bhat 88*85565f80SUday M Bhat return 0; 89*85565f80SUday M Bhat } 90*85565f80SUday M Bhat 91*85565f80SUday M Bhat static int mx8373_sdw_prepare(struct snd_pcm_substream *substream) 92*85565f80SUday M Bhat { 93*85565f80SUday M Bhat int ret; 94*85565f80SUday M Bhat 95*85565f80SUday M Bhat /* according to soc_pcm_prepare dai link prepare is called first */ 96*85565f80SUday M Bhat ret = sdw_prepare(substream); 97*85565f80SUday M Bhat if (ret < 0) 98*85565f80SUday M Bhat return ret; 99*85565f80SUday M Bhat 100*85565f80SUday M Bhat return mx8373_enable_spk_pin(substream, true); 101*85565f80SUday M Bhat } 102*85565f80SUday M Bhat 103*85565f80SUday M Bhat static int mx8373_sdw_hw_free(struct snd_pcm_substream *substream) 104*85565f80SUday M Bhat { 105*85565f80SUday M Bhat int ret; 106*85565f80SUday M Bhat 107*85565f80SUday M Bhat /* according to soc_pcm_hw_free dai link free is called first */ 108*85565f80SUday M Bhat ret = sdw_hw_free(substream); 109*85565f80SUday M Bhat if (ret < 0) 110*85565f80SUday M Bhat return ret; 111*85565f80SUday M Bhat 112*85565f80SUday M Bhat return mx8373_enable_spk_pin(substream, false); 113*85565f80SUday M Bhat } 114*85565f80SUday M Bhat 115*85565f80SUday M Bhat static const struct snd_soc_ops max_98373_sdw_ops = { 116*85565f80SUday M Bhat .startup = sdw_startup, 117*85565f80SUday M Bhat .prepare = mx8373_sdw_prepare, 118*85565f80SUday M Bhat .trigger = sdw_trigger, 119*85565f80SUday M Bhat .hw_free = mx8373_sdw_hw_free, 120*85565f80SUday M Bhat .shutdown = sdw_shutdown, 121*85565f80SUday M Bhat }; 122*85565f80SUday M Bhat 123*85565f80SUday M Bhat static int mx8373_sdw_late_probe(struct snd_soc_card *card) 124*85565f80SUday M Bhat { 125*85565f80SUday M Bhat struct snd_soc_dapm_context *dapm = &card->dapm; 126*85565f80SUday M Bhat 127*85565f80SUday M Bhat /* Disable Left and Right Spk pin after boot */ 128*85565f80SUday M Bhat snd_soc_dapm_disable_pin(dapm, "Left Spk"); 129*85565f80SUday M Bhat snd_soc_dapm_disable_pin(dapm, "Right Spk"); 130*85565f80SUday M Bhat return snd_soc_dapm_sync(dapm); 131*85565f80SUday M Bhat } 132*85565f80SUday M Bhat 133*85565f80SUday M Bhat int sof_sdw_mx8373_init(struct snd_soc_card *card, 134*85565f80SUday M Bhat const struct snd_soc_acpi_link_adr *link, 135*85565f80SUday M Bhat struct snd_soc_dai_link *dai_links, 136*85565f80SUday M Bhat struct sof_sdw_codec_info *info, 137*85565f80SUday M Bhat bool playback) 138*85565f80SUday M Bhat { 139*85565f80SUday M Bhat info->amp_num++; 140*85565f80SUday M Bhat if (info->amp_num == 2) 141*85565f80SUday M Bhat dai_links->init = spk_init; 142*85565f80SUday M Bhat 143*85565f80SUday M Bhat info->codec_card_late_probe = mx8373_sdw_late_probe; 144*85565f80SUday M Bhat 145*85565f80SUday M Bhat dai_links->ops = &max_98373_sdw_ops; 146*85565f80SUday M Bhat 147*85565f80SUday M Bhat return 0; 148*85565f80SUday M Bhat } 149