Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // soc-card.c
0004 //
0005 // Copyright (C) 2019 Renesas Electronics Corp.
0006 // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
0007 //
0008 #include <sound/soc.h>
0009 #include <sound/jack.h>
0010 
0011 #define soc_card_ret(dai, ret) _soc_card_ret(dai, __func__, ret)
0012 static inline int _soc_card_ret(struct snd_soc_card *card,
0013                 const char *func, int ret)
0014 {
0015     switch (ret) {
0016     case -EPROBE_DEFER:
0017     case -ENOTSUPP:
0018     case 0:
0019         break;
0020     default:
0021         dev_err(card->dev,
0022             "ASoC: error at %s on %s: %d\n",
0023             func, card->name, ret);
0024     }
0025 
0026     return ret;
0027 }
0028 
0029 struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
0030                            const char *name)
0031 {
0032     struct snd_card *card = soc_card->snd_card;
0033     struct snd_kcontrol *kctl;
0034 
0035     if (unlikely(!name))
0036         return NULL;
0037 
0038     list_for_each_entry(kctl, &card->controls, list)
0039         if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name)))
0040             return kctl;
0041     return NULL;
0042 }
0043 EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol);
0044 
0045 static int jack_new(struct snd_soc_card *card, const char *id, int type,
0046             struct snd_soc_jack *jack, bool initial_kctl)
0047 {
0048     mutex_init(&jack->mutex);
0049     jack->card = card;
0050     INIT_LIST_HEAD(&jack->pins);
0051     INIT_LIST_HEAD(&jack->jack_zones);
0052     BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier);
0053 
0054     return snd_jack_new(card->snd_card, id, type, &jack->jack, initial_kctl, false);
0055 }
0056 
0057 /**
0058  * snd_soc_card_jack_new - Create a new jack without pins
0059  * @card:  ASoC card
0060  * @id:    an identifying string for this jack
0061  * @type:  a bitmask of enum snd_jack_type values that can be detected by
0062  *         this jack
0063  * @jack:  structure to use for the jack
0064  *
0065  * Creates a new jack object without pins. If adding pins later,
0066  * snd_soc_card_jack_new_pins() should be used instead with 0 as num_pins
0067  * argument.
0068  *
0069  * Returns zero if successful, or a negative error code on failure.
0070  * On success jack will be initialised.
0071  */
0072 int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type,
0073               struct snd_soc_jack *jack)
0074 {
0075     return soc_card_ret(card, jack_new(card, id, type, jack, true));
0076 }
0077 EXPORT_SYMBOL_GPL(snd_soc_card_jack_new);
0078 
0079 /**
0080  * snd_soc_card_jack_new_pins - Create a new jack with pins
0081  * @card:  ASoC card
0082  * @id:    an identifying string for this jack
0083  * @type:  a bitmask of enum snd_jack_type values that can be detected by
0084  *         this jack
0085  * @jack:  structure to use for the jack
0086  * @pins:  Array of jack pins to be added to the jack or NULL
0087  * @num_pins: Number of elements in the @pins array
0088  *
0089  * Creates a new jack object with pins. If not adding pins,
0090  * snd_soc_card_jack_new() should be used instead.
0091  *
0092  * Returns zero if successful, or a negative error code on failure.
0093  * On success jack will be initialised.
0094  */
0095 int snd_soc_card_jack_new_pins(struct snd_soc_card *card, const char *id,
0096                    int type, struct snd_soc_jack *jack,
0097                    struct snd_soc_jack_pin *pins,
0098                    unsigned int num_pins)
0099 {
0100     int ret;
0101 
0102     ret = jack_new(card, id, type, jack, false);
0103     if (ret)
0104         goto end;
0105 
0106     if (num_pins)
0107         ret = snd_soc_jack_add_pins(jack, num_pins, pins);
0108 end:
0109     return soc_card_ret(card, ret);
0110 }
0111 EXPORT_SYMBOL_GPL(snd_soc_card_jack_new_pins);
0112 
0113 int snd_soc_card_suspend_pre(struct snd_soc_card *card)
0114 {
0115     int ret = 0;
0116 
0117     if (card->suspend_pre)
0118         ret = card->suspend_pre(card);
0119 
0120     return soc_card_ret(card, ret);
0121 }
0122 
0123 int snd_soc_card_suspend_post(struct snd_soc_card *card)
0124 {
0125     int ret = 0;
0126 
0127     if (card->suspend_post)
0128         ret = card->suspend_post(card);
0129 
0130     return soc_card_ret(card, ret);
0131 }
0132 
0133 int snd_soc_card_resume_pre(struct snd_soc_card *card)
0134 {
0135     int ret = 0;
0136 
0137     if (card->resume_pre)
0138         ret = card->resume_pre(card);
0139 
0140     return soc_card_ret(card, ret);
0141 }
0142 
0143 int snd_soc_card_resume_post(struct snd_soc_card *card)
0144 {
0145     int ret = 0;
0146 
0147     if (card->resume_post)
0148         ret = card->resume_post(card);
0149 
0150     return soc_card_ret(card, ret);
0151 }
0152 
0153 int snd_soc_card_probe(struct snd_soc_card *card)
0154 {
0155     if (card->probe) {
0156         int ret = card->probe(card);
0157 
0158         if (ret < 0)
0159             return soc_card_ret(card, ret);
0160 
0161         /*
0162          * It has "card->probe" and "card->late_probe" callbacks.
0163          * So, set "probed" flag here, because it needs to care
0164          * about "late_probe".
0165          *
0166          * see
0167          *  snd_soc_bind_card()
0168          *  snd_soc_card_late_probe()
0169          */
0170         card->probed = 1;
0171     }
0172 
0173     return 0;
0174 }
0175 
0176 int snd_soc_card_late_probe(struct snd_soc_card *card)
0177 {
0178     if (card->late_probe) {
0179         int ret = card->late_probe(card);
0180 
0181         if (ret < 0)
0182             return soc_card_ret(card, ret);
0183     }
0184 
0185     /*
0186      * It has "card->probe" and "card->late_probe" callbacks,
0187      * and "late_probe" callback is called after "probe".
0188      * This means, we can set "card->probed" flag afer "late_probe"
0189      * for all cases.
0190      *
0191      * see
0192      *  snd_soc_bind_card()
0193      *  snd_soc_card_probe()
0194      */
0195     card->probed = 1;
0196 
0197     return 0;
0198 }
0199 
0200 void snd_soc_card_fixup_controls(struct snd_soc_card *card)
0201 {
0202     if (card->fixup_controls)
0203         card->fixup_controls(card);
0204 }
0205 
0206 int snd_soc_card_remove(struct snd_soc_card *card)
0207 {
0208     int ret = 0;
0209 
0210     if (card->probed &&
0211         card->remove)
0212         ret = card->remove(card);
0213 
0214     card->probed = 0;
0215 
0216     return soc_card_ret(card, ret);
0217 }
0218 
0219 int snd_soc_card_set_bias_level(struct snd_soc_card *card,
0220                 struct snd_soc_dapm_context *dapm,
0221                 enum snd_soc_bias_level level)
0222 {
0223     int ret = 0;
0224 
0225     if (card && card->set_bias_level)
0226         ret = card->set_bias_level(card, dapm, level);
0227 
0228     return soc_card_ret(card, ret);
0229 }
0230 
0231 int snd_soc_card_set_bias_level_post(struct snd_soc_card *card,
0232                      struct snd_soc_dapm_context *dapm,
0233                      enum snd_soc_bias_level level)
0234 {
0235     int ret = 0;
0236 
0237     if (card && card->set_bias_level_post)
0238         ret = card->set_bias_level_post(card, dapm, level);
0239 
0240     return soc_card_ret(card, ret);
0241 }
0242 
0243 int snd_soc_card_add_dai_link(struct snd_soc_card *card,
0244                   struct snd_soc_dai_link *dai_link)
0245 {
0246     int ret = 0;
0247 
0248     if (card->add_dai_link)
0249         ret = card->add_dai_link(card, dai_link);
0250 
0251     return soc_card_ret(card, ret);
0252 }
0253 EXPORT_SYMBOL_GPL(snd_soc_card_add_dai_link);
0254 
0255 void snd_soc_card_remove_dai_link(struct snd_soc_card *card,
0256                   struct snd_soc_dai_link *dai_link)
0257 {
0258     if (card->remove_dai_link)
0259         card->remove_dai_link(card, dai_link);
0260 }
0261 EXPORT_SYMBOL_GPL(snd_soc_card_remove_dai_link);