brintos

brintos / linux-shallow public Read only

0
0
Text · 5.8 KiB · 8e9546f Raw
259 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// soc-card.c4//5// Copyright (C) 2019 Renesas Electronics Corp.6// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>7//8 9#include <linux/lockdep.h>10#include <linux/rwsem.h>11#include <sound/soc.h>12#include <sound/jack.h>13 14#define soc_card_ret(dai, ret) _soc_card_ret(dai, __func__, ret)15static inline int _soc_card_ret(struct snd_soc_card *card,16				const char *func, int ret)17{18	switch (ret) {19	case -EPROBE_DEFER:20	case -ENOTSUPP:21	case 0:22		break;23	default:24		dev_err(card->dev,25			"ASoC: error at %s on %s: %d\n",26			func, card->name, ret);27	}28 29	return ret;30}31 32struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,33					       const char *name)34{35	if (unlikely(!name))36		return NULL;37 38	return snd_ctl_find_id_mixer(soc_card->snd_card, name);39}40EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol);41 42static int jack_new(struct snd_soc_card *card, const char *id, int type,43		    struct snd_soc_jack *jack, bool initial_kctl)44{45	mutex_init(&jack->mutex);46	jack->card = card;47	INIT_LIST_HEAD(&jack->pins);48	INIT_LIST_HEAD(&jack->jack_zones);49	BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier);50 51	return snd_jack_new(card->snd_card, id, type, &jack->jack, initial_kctl, false);52}53 54/**55 * snd_soc_card_jack_new - Create a new jack without pins56 * @card:  ASoC card57 * @id:    an identifying string for this jack58 * @type:  a bitmask of enum snd_jack_type values that can be detected by59 *         this jack60 * @jack:  structure to use for the jack61 *62 * Creates a new jack object without pins. If adding pins later,63 * snd_soc_card_jack_new_pins() should be used instead with 0 as num_pins64 * argument.65 *66 * Returns zero if successful, or a negative error code on failure.67 * On success jack will be initialised.68 */69int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type,70			  struct snd_soc_jack *jack)71{72	return soc_card_ret(card, jack_new(card, id, type, jack, true));73}74EXPORT_SYMBOL_GPL(snd_soc_card_jack_new);75 76/**77 * snd_soc_card_jack_new_pins - Create a new jack with pins78 * @card:  ASoC card79 * @id:    an identifying string for this jack80 * @type:  a bitmask of enum snd_jack_type values that can be detected by81 *         this jack82 * @jack:  structure to use for the jack83 * @pins:  Array of jack pins to be added to the jack or NULL84 * @num_pins: Number of elements in the @pins array85 *86 * Creates a new jack object with pins. If not adding pins,87 * snd_soc_card_jack_new() should be used instead.88 *89 * Returns zero if successful, or a negative error code on failure.90 * On success jack will be initialised.91 */92int snd_soc_card_jack_new_pins(struct snd_soc_card *card, const char *id,93			       int type, struct snd_soc_jack *jack,94			       struct snd_soc_jack_pin *pins,95			       unsigned int num_pins)96{97	int ret;98 99	ret = jack_new(card, id, type, jack, false);100	if (ret)101		goto end;102 103	if (num_pins)104		ret = snd_soc_jack_add_pins(jack, num_pins, pins);105end:106	return soc_card_ret(card, ret);107}108EXPORT_SYMBOL_GPL(snd_soc_card_jack_new_pins);109 110int snd_soc_card_suspend_pre(struct snd_soc_card *card)111{112	int ret = 0;113 114	if (card->suspend_pre)115		ret = card->suspend_pre(card);116 117	return soc_card_ret(card, ret);118}119 120int snd_soc_card_suspend_post(struct snd_soc_card *card)121{122	int ret = 0;123 124	if (card->suspend_post)125		ret = card->suspend_post(card);126 127	return soc_card_ret(card, ret);128}129 130int snd_soc_card_resume_pre(struct snd_soc_card *card)131{132	int ret = 0;133 134	if (card->resume_pre)135		ret = card->resume_pre(card);136 137	return soc_card_ret(card, ret);138}139 140int snd_soc_card_resume_post(struct snd_soc_card *card)141{142	int ret = 0;143 144	if (card->resume_post)145		ret = card->resume_post(card);146 147	return soc_card_ret(card, ret);148}149 150int snd_soc_card_probe(struct snd_soc_card *card)151{152	if (card->probe) {153		int ret = card->probe(card);154 155		if (ret < 0)156			return soc_card_ret(card, ret);157 158		/*159		 * It has "card->probe" and "card->late_probe" callbacks.160		 * So, set "probed" flag here, because it needs to care161		 * about "late_probe".162		 *163		 * see164		 *	snd_soc_bind_card()165		 *	snd_soc_card_late_probe()166		 */167		card->probed = 1;168	}169 170	return 0;171}172 173int snd_soc_card_late_probe(struct snd_soc_card *card)174{175	if (card->late_probe) {176		int ret = card->late_probe(card);177 178		if (ret < 0)179			return soc_card_ret(card, ret);180	}181 182	/*183	 * It has "card->probe" and "card->late_probe" callbacks,184	 * and "late_probe" callback is called after "probe".185	 * This means, we can set "card->probed" flag afer "late_probe"186	 * for all cases.187	 *188	 * see189	 *	snd_soc_bind_card()190	 *	snd_soc_card_probe()191	 */192	card->probed = 1;193 194	return 0;195}196 197void snd_soc_card_fixup_controls(struct snd_soc_card *card)198{199	if (card->fixup_controls)200		card->fixup_controls(card);201}202 203int snd_soc_card_remove(struct snd_soc_card *card)204{205	int ret = 0;206 207	if (card->probed &&208	    card->remove)209		ret = card->remove(card);210 211	card->probed = 0;212 213	return soc_card_ret(card, ret);214}215 216int snd_soc_card_set_bias_level(struct snd_soc_card *card,217				struct snd_soc_dapm_context *dapm,218				enum snd_soc_bias_level level)219{220	int ret = 0;221 222	if (card && card->set_bias_level)223		ret = card->set_bias_level(card, dapm, level);224 225	return soc_card_ret(card, ret);226}227 228int snd_soc_card_set_bias_level_post(struct snd_soc_card *card,229				     struct snd_soc_dapm_context *dapm,230				     enum snd_soc_bias_level level)231{232	int ret = 0;233 234	if (card && card->set_bias_level_post)235		ret = card->set_bias_level_post(card, dapm, level);236 237	return soc_card_ret(card, ret);238}239 240int snd_soc_card_add_dai_link(struct snd_soc_card *card,241			      struct snd_soc_dai_link *dai_link)242{243	int ret = 0;244 245	if (card->add_dai_link)246		ret = card->add_dai_link(card, dai_link);247 248	return soc_card_ret(card, ret);249}250EXPORT_SYMBOL_GPL(snd_soc_card_add_dai_link);251 252void snd_soc_card_remove_dai_link(struct snd_soc_card *card,253				  struct snd_soc_dai_link *dai_link)254{255	if (card->remove_dai_link)256		card->remove_dai_link(card, dai_link);257}258EXPORT_SYMBOL_GPL(snd_soc_card_remove_dai_link);259