11793936bSKuninori Morimoto // SPDX-License-Identifier: GPL-2.0 21793936bSKuninori Morimoto // 31793936bSKuninori Morimoto // soc-card.c 41793936bSKuninori Morimoto // 51793936bSKuninori Morimoto // Copyright (C) 2019 Renesas Electronics Corp. 61793936bSKuninori Morimoto // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 71793936bSKuninori Morimoto // 8eba2eb24SRichard Fitzgerald 9eba2eb24SRichard Fitzgerald #include <linux/lockdep.h> 10eba2eb24SRichard Fitzgerald #include <linux/rwsem.h> 111793936bSKuninori Morimoto #include <sound/soc.h> 123359e9b6SKuninori Morimoto #include <sound/jack.h> 131793936bSKuninori Morimoto 141793936bSKuninori Morimoto #define soc_card_ret(dai, ret) _soc_card_ret(dai, __func__, ret) 151793936bSKuninori Morimoto static inline int _soc_card_ret(struct snd_soc_card *card, 161793936bSKuninori Morimoto const char *func, int ret) 171793936bSKuninori Morimoto { 181793936bSKuninori Morimoto switch (ret) { 191793936bSKuninori Morimoto case -EPROBE_DEFER: 201793936bSKuninori Morimoto case -ENOTSUPP: 211793936bSKuninori Morimoto case 0: 221793936bSKuninori Morimoto break; 231793936bSKuninori Morimoto default: 241793936bSKuninori Morimoto dev_err(card->dev, 251793936bSKuninori Morimoto "ASoC: error at %s on %s: %d\n", 261793936bSKuninori Morimoto func, card->name, ret); 271793936bSKuninori Morimoto } 281793936bSKuninori Morimoto 291793936bSKuninori Morimoto return ret; 301793936bSKuninori Morimoto } 31209c6cdfSKuninori Morimoto 32eba2eb24SRichard Fitzgerald struct snd_kcontrol *snd_soc_card_get_kcontrol_locked(struct snd_soc_card *soc_card, 33209c6cdfSKuninori Morimoto const char *name) 34209c6cdfSKuninori Morimoto { 35209c6cdfSKuninori Morimoto if (unlikely(!name)) 36209c6cdfSKuninori Morimoto return NULL; 37209c6cdfSKuninori Morimoto 38*897cc72bSRichard Fitzgerald return snd_ctl_find_id_mixer_locked(soc_card->snd_card, name); 39209c6cdfSKuninori Morimoto } 40eba2eb24SRichard Fitzgerald EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol_locked); 41eba2eb24SRichard Fitzgerald 42eba2eb24SRichard Fitzgerald struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, 43eba2eb24SRichard Fitzgerald const char *name) 44eba2eb24SRichard Fitzgerald { 45*897cc72bSRichard Fitzgerald if (unlikely(!name)) 46*897cc72bSRichard Fitzgerald return NULL; 47eba2eb24SRichard Fitzgerald 48*897cc72bSRichard Fitzgerald return snd_ctl_find_id_mixer(soc_card->snd_card, name); 49eba2eb24SRichard Fitzgerald } 50209c6cdfSKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol); 513359e9b6SKuninori Morimoto 5219aed2d6SAkihiko Odaki static int jack_new(struct snd_soc_card *card, const char *id, int type, 5319aed2d6SAkihiko Odaki struct snd_soc_jack *jack, bool initial_kctl) 5419aed2d6SAkihiko Odaki { 5519aed2d6SAkihiko Odaki mutex_init(&jack->mutex); 5619aed2d6SAkihiko Odaki jack->card = card; 5719aed2d6SAkihiko Odaki INIT_LIST_HEAD(&jack->pins); 5819aed2d6SAkihiko Odaki INIT_LIST_HEAD(&jack->jack_zones); 5919aed2d6SAkihiko Odaki BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); 6019aed2d6SAkihiko Odaki 6119aed2d6SAkihiko Odaki return snd_jack_new(card->snd_card, id, type, &jack->jack, initial_kctl, false); 6219aed2d6SAkihiko Odaki } 6319aed2d6SAkihiko Odaki 643359e9b6SKuninori Morimoto /** 6519aed2d6SAkihiko Odaki * snd_soc_card_jack_new - Create a new jack without pins 6619aed2d6SAkihiko Odaki * @card: ASoC card 6719aed2d6SAkihiko Odaki * @id: an identifying string for this jack 6819aed2d6SAkihiko Odaki * @type: a bitmask of enum snd_jack_type values that can be detected by 6919aed2d6SAkihiko Odaki * this jack 7019aed2d6SAkihiko Odaki * @jack: structure to use for the jack 7119aed2d6SAkihiko Odaki * 7219aed2d6SAkihiko Odaki * Creates a new jack object without pins. If adding pins later, 7319aed2d6SAkihiko Odaki * snd_soc_card_jack_new_pins() should be used instead with 0 as num_pins 7419aed2d6SAkihiko Odaki * argument. 7519aed2d6SAkihiko Odaki * 7619aed2d6SAkihiko Odaki * Returns zero if successful, or a negative error code on failure. 7719aed2d6SAkihiko Odaki * On success jack will be initialised. 7819aed2d6SAkihiko Odaki */ 7919aed2d6SAkihiko Odaki int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, 8019aed2d6SAkihiko Odaki struct snd_soc_jack *jack) 8119aed2d6SAkihiko Odaki { 8219aed2d6SAkihiko Odaki return soc_card_ret(card, jack_new(card, id, type, jack, true)); 8319aed2d6SAkihiko Odaki } 8419aed2d6SAkihiko Odaki EXPORT_SYMBOL_GPL(snd_soc_card_jack_new); 8519aed2d6SAkihiko Odaki 8619aed2d6SAkihiko Odaki /** 8719aed2d6SAkihiko Odaki * snd_soc_card_jack_new_pins - Create a new jack with pins 883359e9b6SKuninori Morimoto * @card: ASoC card 893359e9b6SKuninori Morimoto * @id: an identifying string for this jack 903359e9b6SKuninori Morimoto * @type: a bitmask of enum snd_jack_type values that can be detected by 913359e9b6SKuninori Morimoto * this jack 923359e9b6SKuninori Morimoto * @jack: structure to use for the jack 933359e9b6SKuninori Morimoto * @pins: Array of jack pins to be added to the jack or NULL 943359e9b6SKuninori Morimoto * @num_pins: Number of elements in the @pins array 953359e9b6SKuninori Morimoto * 9619aed2d6SAkihiko Odaki * Creates a new jack object with pins. If not adding pins, 9719aed2d6SAkihiko Odaki * snd_soc_card_jack_new() should be used instead. 983359e9b6SKuninori Morimoto * 993359e9b6SKuninori Morimoto * Returns zero if successful, or a negative error code on failure. 1003359e9b6SKuninori Morimoto * On success jack will be initialised. 1013359e9b6SKuninori Morimoto */ 10219aed2d6SAkihiko Odaki int snd_soc_card_jack_new_pins(struct snd_soc_card *card, const char *id, 10319aed2d6SAkihiko Odaki int type, struct snd_soc_jack *jack, 10419aed2d6SAkihiko Odaki struct snd_soc_jack_pin *pins, 10519aed2d6SAkihiko Odaki unsigned int num_pins) 1063359e9b6SKuninori Morimoto { 1073359e9b6SKuninori Morimoto int ret; 1083359e9b6SKuninori Morimoto 10919aed2d6SAkihiko Odaki ret = jack_new(card, id, type, jack, false); 1103359e9b6SKuninori Morimoto if (ret) 1113359e9b6SKuninori Morimoto goto end; 1123359e9b6SKuninori Morimoto 1133359e9b6SKuninori Morimoto if (num_pins) 1143359e9b6SKuninori Morimoto ret = snd_soc_jack_add_pins(jack, num_pins, pins); 1153359e9b6SKuninori Morimoto end: 1163359e9b6SKuninori Morimoto return soc_card_ret(card, ret); 1173359e9b6SKuninori Morimoto } 11819aed2d6SAkihiko Odaki EXPORT_SYMBOL_GPL(snd_soc_card_jack_new_pins); 119130dc08cSKuninori Morimoto 120130dc08cSKuninori Morimoto int snd_soc_card_suspend_pre(struct snd_soc_card *card) 121130dc08cSKuninori Morimoto { 122130dc08cSKuninori Morimoto int ret = 0; 123130dc08cSKuninori Morimoto 124130dc08cSKuninori Morimoto if (card->suspend_pre) 125130dc08cSKuninori Morimoto ret = card->suspend_pre(card); 126130dc08cSKuninori Morimoto 127130dc08cSKuninori Morimoto return soc_card_ret(card, ret); 128130dc08cSKuninori Morimoto } 129d17b60b2SKuninori Morimoto 130d17b60b2SKuninori Morimoto int snd_soc_card_suspend_post(struct snd_soc_card *card) 131d17b60b2SKuninori Morimoto { 132d17b60b2SKuninori Morimoto int ret = 0; 133d17b60b2SKuninori Morimoto 134d17b60b2SKuninori Morimoto if (card->suspend_post) 135d17b60b2SKuninori Morimoto ret = card->suspend_post(card); 136d17b60b2SKuninori Morimoto 137d17b60b2SKuninori Morimoto return soc_card_ret(card, ret); 138d17b60b2SKuninori Morimoto } 139934c752cSKuninori Morimoto 140934c752cSKuninori Morimoto int snd_soc_card_resume_pre(struct snd_soc_card *card) 141934c752cSKuninori Morimoto { 142934c752cSKuninori Morimoto int ret = 0; 143934c752cSKuninori Morimoto 144934c752cSKuninori Morimoto if (card->resume_pre) 145934c752cSKuninori Morimoto ret = card->resume_pre(card); 146934c752cSKuninori Morimoto 147934c752cSKuninori Morimoto return soc_card_ret(card, ret); 148934c752cSKuninori Morimoto } 149739443d1SKuninori Morimoto 150739443d1SKuninori Morimoto int snd_soc_card_resume_post(struct snd_soc_card *card) 151739443d1SKuninori Morimoto { 152739443d1SKuninori Morimoto int ret = 0; 153739443d1SKuninori Morimoto 154739443d1SKuninori Morimoto if (card->resume_post) 155739443d1SKuninori Morimoto ret = card->resume_post(card); 156739443d1SKuninori Morimoto 157739443d1SKuninori Morimoto return soc_card_ret(card, ret); 158739443d1SKuninori Morimoto } 15973de4b02SKuninori Morimoto 16073de4b02SKuninori Morimoto int snd_soc_card_probe(struct snd_soc_card *card) 16173de4b02SKuninori Morimoto { 16273de4b02SKuninori Morimoto if (card->probe) { 16373de4b02SKuninori Morimoto int ret = card->probe(card); 16473de4b02SKuninori Morimoto 16573de4b02SKuninori Morimoto if (ret < 0) 16673de4b02SKuninori Morimoto return soc_card_ret(card, ret); 16773de4b02SKuninori Morimoto 16873de4b02SKuninori Morimoto /* 16973de4b02SKuninori Morimoto * It has "card->probe" and "card->late_probe" callbacks. 17073de4b02SKuninori Morimoto * So, set "probed" flag here, because it needs to care 17173de4b02SKuninori Morimoto * about "late_probe". 17273de4b02SKuninori Morimoto * 17373de4b02SKuninori Morimoto * see 17473de4b02SKuninori Morimoto * snd_soc_bind_card() 17573de4b02SKuninori Morimoto * snd_soc_card_late_probe() 17673de4b02SKuninori Morimoto */ 17773de4b02SKuninori Morimoto card->probed = 1; 17873de4b02SKuninori Morimoto } 17973de4b02SKuninori Morimoto 18073de4b02SKuninori Morimoto return 0; 18173de4b02SKuninori Morimoto } 1825c0eac03SKuninori Morimoto 1835c0eac03SKuninori Morimoto int snd_soc_card_late_probe(struct snd_soc_card *card) 1845c0eac03SKuninori Morimoto { 1855c0eac03SKuninori Morimoto if (card->late_probe) { 1865c0eac03SKuninori Morimoto int ret = card->late_probe(card); 1875c0eac03SKuninori Morimoto 1885c0eac03SKuninori Morimoto if (ret < 0) 1895c0eac03SKuninori Morimoto return soc_card_ret(card, ret); 1905c0eac03SKuninori Morimoto } 1915c0eac03SKuninori Morimoto 1925c0eac03SKuninori Morimoto /* 1935c0eac03SKuninori Morimoto * It has "card->probe" and "card->late_probe" callbacks, 1945c0eac03SKuninori Morimoto * and "late_probe" callback is called after "probe". 1955c0eac03SKuninori Morimoto * This means, we can set "card->probed" flag afer "late_probe" 1965c0eac03SKuninori Morimoto * for all cases. 1975c0eac03SKuninori Morimoto * 1985c0eac03SKuninori Morimoto * see 1995c0eac03SKuninori Morimoto * snd_soc_bind_card() 2005c0eac03SKuninori Morimoto * snd_soc_card_probe() 2015c0eac03SKuninori Morimoto */ 2025c0eac03SKuninori Morimoto card->probed = 1; 2035c0eac03SKuninori Morimoto 2045c0eac03SKuninori Morimoto return 0; 2055c0eac03SKuninori Morimoto } 206b0275d95SKuninori Morimoto 207df4d27b1SMartin Povišer void snd_soc_card_fixup_controls(struct snd_soc_card *card) 208df4d27b1SMartin Povišer { 209df4d27b1SMartin Povišer if (card->fixup_controls) 210df4d27b1SMartin Povišer card->fixup_controls(card); 211df4d27b1SMartin Povišer } 212df4d27b1SMartin Povišer 213b0275d95SKuninori Morimoto int snd_soc_card_remove(struct snd_soc_card *card) 214b0275d95SKuninori Morimoto { 215b0275d95SKuninori Morimoto int ret = 0; 216b0275d95SKuninori Morimoto 217b0275d95SKuninori Morimoto if (card->probed && 218b0275d95SKuninori Morimoto card->remove) 219b0275d95SKuninori Morimoto ret = card->remove(card); 220b0275d95SKuninori Morimoto 221b0275d95SKuninori Morimoto card->probed = 0; 222b0275d95SKuninori Morimoto 223b0275d95SKuninori Morimoto return soc_card_ret(card, ret); 224b0275d95SKuninori Morimoto } 22539caefdaSKuninori Morimoto 22639caefdaSKuninori Morimoto int snd_soc_card_set_bias_level(struct snd_soc_card *card, 22739caefdaSKuninori Morimoto struct snd_soc_dapm_context *dapm, 22839caefdaSKuninori Morimoto enum snd_soc_bias_level level) 22939caefdaSKuninori Morimoto { 23039caefdaSKuninori Morimoto int ret = 0; 23139caefdaSKuninori Morimoto 23239caefdaSKuninori Morimoto if (card && card->set_bias_level) 23339caefdaSKuninori Morimoto ret = card->set_bias_level(card, dapm, level); 23439caefdaSKuninori Morimoto 23539caefdaSKuninori Morimoto return soc_card_ret(card, ret); 23639caefdaSKuninori Morimoto } 237d41278eaSKuninori Morimoto 238d41278eaSKuninori Morimoto int snd_soc_card_set_bias_level_post(struct snd_soc_card *card, 239d41278eaSKuninori Morimoto struct snd_soc_dapm_context *dapm, 240d41278eaSKuninori Morimoto enum snd_soc_bias_level level) 241d41278eaSKuninori Morimoto { 242d41278eaSKuninori Morimoto int ret = 0; 243d41278eaSKuninori Morimoto 244d41278eaSKuninori Morimoto if (card && card->set_bias_level_post) 245d41278eaSKuninori Morimoto ret = card->set_bias_level_post(card, dapm, level); 246d41278eaSKuninori Morimoto 247d41278eaSKuninori Morimoto return soc_card_ret(card, ret); 248d41278eaSKuninori Morimoto } 249cbc7a6b5SKuninori Morimoto 250cbc7a6b5SKuninori Morimoto int snd_soc_card_add_dai_link(struct snd_soc_card *card, 251cbc7a6b5SKuninori Morimoto struct snd_soc_dai_link *dai_link) 252cbc7a6b5SKuninori Morimoto { 253cbc7a6b5SKuninori Morimoto int ret = 0; 254cbc7a6b5SKuninori Morimoto 255cbc7a6b5SKuninori Morimoto if (card->add_dai_link) 256cbc7a6b5SKuninori Morimoto ret = card->add_dai_link(card, dai_link); 257cbc7a6b5SKuninori Morimoto 258cbc7a6b5SKuninori Morimoto return soc_card_ret(card, ret); 259cbc7a6b5SKuninori Morimoto } 260cbc7a6b5SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_card_add_dai_link); 261fcbbcc32SKuninori Morimoto 262fcbbcc32SKuninori Morimoto void snd_soc_card_remove_dai_link(struct snd_soc_card *card, 263fcbbcc32SKuninori Morimoto struct snd_soc_dai_link *dai_link) 264fcbbcc32SKuninori Morimoto { 265fcbbcc32SKuninori Morimoto if (card->remove_dai_link) 266fcbbcc32SKuninori Morimoto card->remove_dai_link(card, dai_link); 267fcbbcc32SKuninori Morimoto } 268fcbbcc32SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_card_remove_dai_link); 269