1 // SPDX-License-Identifier: GPL-2.0-only 2 // This file incorporates work covered by the following copyright notice: 3 // Copyright (c) 2020 Intel Corporation 4 // Copyright (c) 2024 Advanced Micro Devices, Inc. 5 // 6 // soc_sdw_maxim - Helpers to handle maxim codecs 7 // codec devices from generic machine driver 8 9 #include <linux/device.h> 10 #include <linux/errno.h> 11 #include <sound/control.h> 12 #include <sound/soc.h> 13 #include <sound/soc-acpi.h> 14 #include <sound/soc-dapm.h> 15 #include <sound/soc_sdw_utils.h> 16 17 static int maxim_part_id; 18 #define SOC_SDW_PART_ID_MAX98363 0x8363 19 #define SOC_SDW_PART_ID_MAX98373 0x8373 20 21 static const struct snd_soc_dapm_route max_98373_dapm_routes[] = { 22 { "Left Spk", NULL, "Left BE_OUT" }, 23 { "Right Spk", NULL, "Right BE_OUT" }, 24 }; 25 26 int asoc_sdw_maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) 27 { 28 struct snd_soc_card *card = rtd->card; 29 int ret; 30 31 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 32 "%s spk:mx%04x", 33 card->components, maxim_part_id); 34 if (!card->components) 35 return -ENOMEM; 36 37 dev_dbg(card->dev, "soundwire maxim card components assigned : %s\n", 38 card->components); 39 40 ret = snd_soc_dapm_add_routes(&card->dapm, max_98373_dapm_routes, 2); 41 if (ret) 42 dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); 43 44 return ret; 45 } 46 EXPORT_SYMBOL_NS(asoc_sdw_maxim_spk_rtd_init, SND_SOC_SDW_UTILS); 47 48 static int asoc_sdw_mx8373_enable_spk_pin(struct snd_pcm_substream *substream, bool enable) 49 { 50 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 51 struct snd_soc_dai *codec_dai; 52 struct snd_soc_dai *cpu_dai; 53 int ret; 54 int j; 55 56 /* set spk pin by playback only */ 57 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 58 return 0; 59 60 cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 61 for_each_rtd_codec_dais(rtd, j, codec_dai) { 62 struct snd_soc_dapm_context *dapm = 63 snd_soc_component_get_dapm(cpu_dai->component); 64 char pin_name[16]; 65 66 snprintf(pin_name, ARRAY_SIZE(pin_name), "%s Spk", 67 codec_dai->component->name_prefix); 68 69 if (enable) 70 ret = snd_soc_dapm_enable_pin(dapm, pin_name); 71 else 72 ret = snd_soc_dapm_disable_pin(dapm, pin_name); 73 74 if (!ret) 75 snd_soc_dapm_sync(dapm); 76 } 77 78 return 0; 79 } 80 81 static int asoc_sdw_mx8373_prepare(struct snd_pcm_substream *substream) 82 { 83 int ret; 84 85 /* according to soc_pcm_prepare dai link prepare is called first */ 86 ret = asoc_sdw_prepare(substream); 87 if (ret < 0) 88 return ret; 89 90 return asoc_sdw_mx8373_enable_spk_pin(substream, true); 91 } 92 93 static int asoc_sdw_mx8373_hw_free(struct snd_pcm_substream *substream) 94 { 95 int ret; 96 97 /* according to soc_pcm_hw_free dai link free is called first */ 98 ret = asoc_sdw_hw_free(substream); 99 if (ret < 0) 100 return ret; 101 102 return asoc_sdw_mx8373_enable_spk_pin(substream, false); 103 } 104 105 static const struct snd_soc_ops max_98373_sdw_ops = { 106 .startup = asoc_sdw_startup, 107 .prepare = asoc_sdw_mx8373_prepare, 108 .trigger = asoc_sdw_trigger, 109 .hw_params = asoc_sdw_hw_params, 110 .hw_free = asoc_sdw_mx8373_hw_free, 111 .shutdown = asoc_sdw_shutdown, 112 }; 113 114 static int asoc_sdw_mx8373_sdw_late_probe(struct snd_soc_card *card) 115 { 116 struct snd_soc_dapm_context *dapm = &card->dapm; 117 118 /* Disable Left and Right Spk pin after boot */ 119 snd_soc_dapm_disable_pin(dapm, "Left Spk"); 120 snd_soc_dapm_disable_pin(dapm, "Right Spk"); 121 return snd_soc_dapm_sync(dapm); 122 } 123 124 int asoc_sdw_maxim_init(struct snd_soc_card *card, 125 struct snd_soc_dai_link *dai_links, 126 struct asoc_sdw_codec_info *info, 127 bool playback) 128 { 129 info->amp_num++; 130 131 maxim_part_id = info->part_id; 132 switch (maxim_part_id) { 133 case SOC_SDW_PART_ID_MAX98363: 134 /* Default ops are set in function init_dai_link. 135 * called as part of function create_sdw_dailink 136 */ 137 break; 138 case SOC_SDW_PART_ID_MAX98373: 139 info->codec_card_late_probe = asoc_sdw_mx8373_sdw_late_probe; 140 dai_links->ops = &max_98373_sdw_ops; 141 break; 142 default: 143 dev_err(card->dev, "Invalid maxim_part_id %#x\n", maxim_part_id); 144 return -EINVAL; 145 } 146 return 0; 147 } 148 EXPORT_SYMBOL_NS(asoc_sdw_maxim_init, SND_SOC_SDW_UTILS); 149
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.