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