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