^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // soc-card.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) // Copyright (C) 2019 Renesas Electronics Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <sound/jack.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define soc_card_ret(dai, ret) _soc_card_ret(dai, __func__, ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) static inline int _soc_card_ret(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) const char *func, int ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) switch (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) case -EPROBE_DEFER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) case -ENOTSUPP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) dev_err(card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) "ASoC: error at %s on %s: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) func, card->name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct snd_card *card = soc_card->snd_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct snd_kcontrol *kctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) if (unlikely(!name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) list_for_each_entry(kctl, &card->controls, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return kctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * snd_soc_card_jack_new - Create a new jack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * @card: ASoC card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * @id: an identifying string for this jack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * @type: a bitmask of enum snd_jack_type values that can be detected by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * this jack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * @jack: structure to use for the jack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * @pins: Array of jack pins to be added to the jack or NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * @num_pins: Number of elements in the @pins array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * Creates a new jack object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * Returns zero if successful, or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * On success jack will be initialised.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct snd_soc_jack *jack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct snd_soc_jack_pin *pins, unsigned int num_pins)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) mutex_init(&jack->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) jack->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) INIT_LIST_HEAD(&jack->pins);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) INIT_LIST_HEAD(&jack->jack_zones);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) ret = snd_jack_new(card->snd_card, id, type, &jack->jack, false, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (num_pins)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ret = snd_soc_jack_add_pins(jack, num_pins, pins);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return soc_card_ret(card, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) EXPORT_SYMBOL_GPL(snd_soc_card_jack_new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int snd_soc_card_suspend_pre(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (card->suspend_pre)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ret = card->suspend_pre(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return soc_card_ret(card, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int snd_soc_card_suspend_post(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (card->suspend_post)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) ret = card->suspend_post(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return soc_card_ret(card, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int snd_soc_card_resume_pre(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (card->resume_pre)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) ret = card->resume_pre(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return soc_card_ret(card, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int snd_soc_card_resume_post(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (card->resume_post)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ret = card->resume_post(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return soc_card_ret(card, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int snd_soc_card_probe(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (card->probe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int ret = card->probe(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return soc_card_ret(card, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * It has "card->probe" and "card->late_probe" callbacks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * So, set "probed" flag here, because it needs to care
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * about "late_probe".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * snd_soc_bind_card()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * snd_soc_card_late_probe()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) card->probed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int snd_soc_card_late_probe(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (card->late_probe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) int ret = card->late_probe(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return soc_card_ret(card, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * It has "card->probe" and "card->late_probe" callbacks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * and "late_probe" callback is called after "probe".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * This means, we can set "card->probed" flag afer "late_probe"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * for all cases.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * snd_soc_bind_card()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * snd_soc_card_probe()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) card->probed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int snd_soc_card_remove(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (card->probed &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) card->remove)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) ret = card->remove(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) card->probed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return soc_card_ret(card, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int snd_soc_card_set_bias_level(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) enum snd_soc_bias_level level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (card && card->set_bias_level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ret = card->set_bias_level(card, dapm, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return soc_card_ret(card, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) int snd_soc_card_set_bias_level_post(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) enum snd_soc_bias_level level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (card && card->set_bias_level_post)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) ret = card->set_bias_level_post(card, dapm, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return soc_card_ret(card, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) int snd_soc_card_add_dai_link(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct snd_soc_dai_link *dai_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (card->add_dai_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) ret = card->add_dai_link(card, dai_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return soc_card_ret(card, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) EXPORT_SYMBOL_GPL(snd_soc_card_add_dai_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) void snd_soc_card_remove_dai_link(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct snd_soc_dai_link *dai_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (card->remove_dai_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) card->remove_dai_link(card, dai_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) EXPORT_SYMBOL_GPL(snd_soc_card_remove_dai_link);