| 1 | // SPDX-License-Identifier: GPL-2.0-only | 
|---|
| 2 | /* | 
|---|
| 3 | * HD-audio codec driver binding | 
|---|
| 4 | * Copyright (c) Takashi Iwai <tiwai@suse.de> | 
|---|
| 5 | */ | 
|---|
| 6 |  | 
|---|
| 7 | #include <linux/init.h> | 
|---|
| 8 | #include <linux/slab.h> | 
|---|
| 9 | #include <linux/mutex.h> | 
|---|
| 10 | #include <linux/module.h> | 
|---|
| 11 | #include <linux/export.h> | 
|---|
| 12 | #include <linux/pm.h> | 
|---|
| 13 | #include <sound/core.h> | 
|---|
| 14 | #include <sound/hda_codec.h> | 
|---|
| 15 | #include "hda_local.h" | 
|---|
| 16 | #include "hda_jack.h" | 
|---|
| 17 |  | 
|---|
| 18 | /* | 
|---|
| 19 | * find a matching codec id | 
|---|
| 20 | */ | 
|---|
| 21 | static int hda_codec_match(struct hdac_device *dev, const struct hdac_driver *drv) | 
|---|
| 22 | { | 
|---|
| 23 | struct hda_codec *codec = container_of(dev, struct hda_codec, core); | 
|---|
| 24 | const struct hda_codec_driver *driver = | 
|---|
| 25 | container_of(drv, struct hda_codec_driver, core); | 
|---|
| 26 | const struct hda_device_id *list; | 
|---|
| 27 | /* check probe_id instead of vendor_id if set */ | 
|---|
| 28 | u32 id = codec->probe_id ? codec->probe_id : codec->core.vendor_id; | 
|---|
| 29 | u32 rev_id = codec->core.revision_id; | 
|---|
| 30 |  | 
|---|
| 31 | for (list = driver->id; list->vendor_id; list++) { | 
|---|
| 32 | if (list->vendor_id == id && | 
|---|
| 33 | (!list->rev_id || list->rev_id == rev_id)) { | 
|---|
| 34 | codec->preset = list; | 
|---|
| 35 | return 1; | 
|---|
| 36 | } | 
|---|
| 37 | } | 
|---|
| 38 | return 0; | 
|---|
| 39 | } | 
|---|
| 40 |  | 
|---|
| 41 | /* process an unsolicited event */ | 
|---|
| 42 | static void hda_codec_unsol_event(struct hdac_device *dev, unsigned int ev) | 
|---|
| 43 | { | 
|---|
| 44 | struct hda_codec *codec = container_of(dev, struct hda_codec, core); | 
|---|
| 45 | struct hda_codec_driver *driver = hda_codec_to_driver(codec); | 
|---|
| 46 |  | 
|---|
| 47 | /* ignore unsol events during shutdown */ | 
|---|
| 48 | if (codec->card->shutdown || codec->bus->shutdown) | 
|---|
| 49 | return; | 
|---|
| 50 |  | 
|---|
| 51 | /* ignore unsol events during system suspend/resume */ | 
|---|
| 52 | if (codec->core.dev.power.power_state.event != PM_EVENT_ON) | 
|---|
| 53 | return; | 
|---|
| 54 |  | 
|---|
| 55 | if (driver->ops->unsol_event) | 
|---|
| 56 | driver->ops->unsol_event(codec, ev); | 
|---|
| 57 | } | 
|---|
| 58 |  | 
|---|
| 59 | /** | 
|---|
| 60 | * snd_hda_codec_set_name - set the codec name | 
|---|
| 61 | * @codec: the HDA codec | 
|---|
| 62 | * @name: name string to set | 
|---|
| 63 | */ | 
|---|
| 64 | int snd_hda_codec_set_name(struct hda_codec *codec, const char *name) | 
|---|
| 65 | { | 
|---|
| 66 | int err; | 
|---|
| 67 |  | 
|---|
| 68 | if (!name) | 
|---|
| 69 | return 0; | 
|---|
| 70 | err = snd_hdac_device_set_chip_name(codec: &codec->core, name); | 
|---|
| 71 | if (err < 0) | 
|---|
| 72 | return err; | 
|---|
| 73 |  | 
|---|
| 74 | /* update the mixer name */ | 
|---|
| 75 | if (!*codec->card->mixername || | 
|---|
| 76 | codec->bus->mixer_assigned >= codec->core.addr) { | 
|---|
| 77 | snprintf(buf: codec->card->mixername, | 
|---|
| 78 | size: sizeof(codec->card->mixername), fmt: "%s %s", | 
|---|
| 79 | codec->core.vendor_name, codec->core.chip_name); | 
|---|
| 80 | codec->bus->mixer_assigned = codec->core.addr; | 
|---|
| 81 | } | 
|---|
| 82 |  | 
|---|
| 83 | return 0; | 
|---|
| 84 | } | 
|---|
| 85 | EXPORT_SYMBOL_GPL(snd_hda_codec_set_name); | 
|---|
| 86 |  | 
|---|
| 87 | static int hda_codec_driver_probe(struct device *dev) | 
|---|
| 88 | { | 
|---|
| 89 | struct hda_codec *codec = dev_to_hda_codec(dev); | 
|---|
| 90 | struct module *owner = dev->driver->owner; | 
|---|
| 91 | struct hda_codec_driver *driver = hda_codec_to_driver(codec); | 
|---|
| 92 | int err; | 
|---|
| 93 |  | 
|---|
| 94 | if (codec->bus->core.ext_ops) { | 
|---|
| 95 | if (WARN_ON(!codec->bus->core.ext_ops->hdev_attach)) | 
|---|
| 96 | return -EINVAL; | 
|---|
| 97 | return codec->bus->core.ext_ops->hdev_attach(&codec->core); | 
|---|
| 98 | } | 
|---|
| 99 |  | 
|---|
| 100 | if (WARN_ON(!codec->preset)) | 
|---|
| 101 | return -EINVAL; | 
|---|
| 102 |  | 
|---|
| 103 | err = snd_hda_codec_set_name(codec, codec->preset->name); | 
|---|
| 104 | if (err < 0) | 
|---|
| 105 | goto error; | 
|---|
| 106 | err = snd_hdac_regmap_init(codec: &codec->core); | 
|---|
| 107 | if (err < 0) | 
|---|
| 108 | goto error; | 
|---|
| 109 |  | 
|---|
| 110 | if (!try_module_get(module: owner)) { | 
|---|
| 111 | err = -EINVAL; | 
|---|
| 112 | goto error; | 
|---|
| 113 | } | 
|---|
| 114 |  | 
|---|
| 115 | if (WARN_ON(!(driver->ops && driver->ops->probe))) { | 
|---|
| 116 | err = -EINVAL; | 
|---|
| 117 | goto error_module_put; | 
|---|
| 118 | } | 
|---|
| 119 |  | 
|---|
| 120 | err = driver->ops->probe(codec, codec->preset); | 
|---|
| 121 | if (err < 0) | 
|---|
| 122 | goto error_module_put; | 
|---|
| 123 | err = snd_hda_codec_build_pcms(codec); | 
|---|
| 124 | if (err < 0) | 
|---|
| 125 | goto error_module; | 
|---|
| 126 | err = snd_hda_codec_build_controls(codec); | 
|---|
| 127 | if (err < 0) | 
|---|
| 128 | goto error_module; | 
|---|
| 129 | /* only register after the bus probe finished; otherwise it's racy */ | 
|---|
| 130 | if (!codec->bus->bus_probing && codec->card->registered) { | 
|---|
| 131 | err = snd_card_register(card: codec->card); | 
|---|
| 132 | if (err < 0) | 
|---|
| 133 | goto error_module; | 
|---|
| 134 | snd_hda_codec_register(codec); | 
|---|
| 135 | } | 
|---|
| 136 |  | 
|---|
| 137 | codec->core.lazy_cache = true; | 
|---|
| 138 | return 0; | 
|---|
| 139 |  | 
|---|
| 140 | error_module: | 
|---|
| 141 | if (driver->ops->remove) | 
|---|
| 142 | driver->ops->remove(codec); | 
|---|
| 143 | error_module_put: | 
|---|
| 144 | module_put(module: owner); | 
|---|
| 145 |  | 
|---|
| 146 | error: | 
|---|
| 147 | snd_hda_codec_cleanup_for_unbind(codec); | 
|---|
| 148 | codec->preset = NULL; | 
|---|
| 149 | return err; | 
|---|
| 150 | } | 
|---|
| 151 |  | 
|---|
| 152 | static int hda_codec_driver_remove(struct device *dev) | 
|---|
| 153 | { | 
|---|
| 154 | struct hda_codec *codec = dev_to_hda_codec(dev); | 
|---|
| 155 | struct hda_codec_driver *driver = hda_codec_to_driver(codec); | 
|---|
| 156 |  | 
|---|
| 157 | if (codec->bus->core.ext_ops) { | 
|---|
| 158 | if (WARN_ON(!codec->bus->core.ext_ops->hdev_detach)) | 
|---|
| 159 | return -EINVAL; | 
|---|
| 160 | return codec->bus->core.ext_ops->hdev_detach(&codec->core); | 
|---|
| 161 | } | 
|---|
| 162 |  | 
|---|
| 163 | snd_hda_codec_disconnect_pcms(codec); | 
|---|
| 164 | snd_hda_jack_tbl_disconnect(codec); | 
|---|
| 165 | if (!refcount_dec_and_test(r: &codec->pcm_ref)) | 
|---|
| 166 | wait_event(codec->remove_sleep, !refcount_read(&codec->pcm_ref)); | 
|---|
| 167 | snd_power_sync_ref(card: codec->bus->card); | 
|---|
| 168 |  | 
|---|
| 169 | if (driver->ops->remove) | 
|---|
| 170 | driver->ops->remove(codec); | 
|---|
| 171 | snd_hda_codec_cleanup_for_unbind(codec); | 
|---|
| 172 | codec->preset = NULL; | 
|---|
| 173 | module_put(module: dev->driver->owner); | 
|---|
| 174 | return 0; | 
|---|
| 175 | } | 
|---|
| 176 |  | 
|---|
| 177 | static void hda_codec_driver_shutdown(struct device *dev) | 
|---|
| 178 | { | 
|---|
| 179 | snd_hda_codec_shutdown(dev_to_hda_codec(dev)); | 
|---|
| 180 | } | 
|---|
| 181 |  | 
|---|
| 182 | int __hda_codec_driver_register(struct hda_codec_driver *drv, const char *name, | 
|---|
| 183 | struct module *owner) | 
|---|
| 184 | { | 
|---|
| 185 | drv->core.driver.name = name; | 
|---|
| 186 | drv->core.driver.owner = owner; | 
|---|
| 187 | drv->core.driver.bus = &snd_hda_bus_type; | 
|---|
| 188 | drv->core.driver.probe = hda_codec_driver_probe; | 
|---|
| 189 | drv->core.driver.remove = hda_codec_driver_remove; | 
|---|
| 190 | drv->core.driver.shutdown = hda_codec_driver_shutdown; | 
|---|
| 191 | drv->core.driver.pm = pm_ptr(&hda_codec_driver_pm); | 
|---|
| 192 | drv->core.type = HDA_DEV_LEGACY; | 
|---|
| 193 | drv->core.match = hda_codec_match; | 
|---|
| 194 | drv->core.unsol_event = hda_codec_unsol_event; | 
|---|
| 195 | return driver_register(drv: &drv->core.driver); | 
|---|
| 196 | } | 
|---|
| 197 | EXPORT_SYMBOL_GPL(__hda_codec_driver_register); | 
|---|
| 198 |  | 
|---|
| 199 | void hda_codec_driver_unregister(struct hda_codec_driver *drv) | 
|---|
| 200 | { | 
|---|
| 201 | driver_unregister(drv: &drv->core.driver); | 
|---|
| 202 | } | 
|---|
| 203 | EXPORT_SYMBOL_GPL(hda_codec_driver_unregister); | 
|---|
| 204 |  | 
|---|
| 205 | static inline bool codec_probed(struct hda_codec *codec) | 
|---|
| 206 | { | 
|---|
| 207 | return device_attach(hda_codec_dev(codec)) > 0 && codec->preset; | 
|---|
| 208 | } | 
|---|
| 209 |  | 
|---|
| 210 | /* try to auto-load codec module */ | 
|---|
| 211 | static void request_codec_module(struct hda_codec *codec) | 
|---|
| 212 | { | 
|---|
| 213 | #ifdef MODULE | 
|---|
| 214 | char modalias[32]; | 
|---|
| 215 | const char *mod = NULL; | 
|---|
| 216 |  | 
|---|
| 217 | switch (codec->probe_id) { | 
|---|
| 218 | case HDA_CODEC_ID_GENERIC_HDMI: | 
|---|
| 219 | #if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI) | 
|---|
| 220 | mod = "snd-hda-codec-hdmi"; | 
|---|
| 221 | #endif | 
|---|
| 222 | break; | 
|---|
| 223 | case HDA_CODEC_ID_GENERIC: | 
|---|
| 224 | #if IS_MODULE(CONFIG_SND_HDA_GENERIC) | 
|---|
| 225 | mod = "snd-hda-codec-generic"; | 
|---|
| 226 | #endif | 
|---|
| 227 | break; | 
|---|
| 228 | default: | 
|---|
| 229 | snd_hdac_codec_modalias(&codec->core, modalias, sizeof(modalias)); | 
|---|
| 230 | mod = modalias; | 
|---|
| 231 | break; | 
|---|
| 232 | } | 
|---|
| 233 |  | 
|---|
| 234 | if (mod) | 
|---|
| 235 | request_module(mod); | 
|---|
| 236 | #endif /* MODULE */ | 
|---|
| 237 | } | 
|---|
| 238 |  | 
|---|
| 239 | /* try to auto-load and bind the codec module */ | 
|---|
| 240 | static void codec_bind_module(struct hda_codec *codec) | 
|---|
| 241 | { | 
|---|
| 242 | #ifdef MODULE | 
|---|
| 243 | request_codec_module(codec); | 
|---|
| 244 | if (codec_probed(codec)) | 
|---|
| 245 | return; | 
|---|
| 246 | #endif | 
|---|
| 247 | } | 
|---|
| 248 |  | 
|---|
| 249 | #if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) | 
|---|
| 250 | /* if all audio out widgets are digital, let's assume the codec as a HDMI/DP */ | 
|---|
| 251 | static bool is_likely_hdmi_codec(struct hda_codec *codec) | 
|---|
| 252 | { | 
|---|
| 253 | hda_nid_t nid; | 
|---|
| 254 |  | 
|---|
| 255 | /* | 
|---|
| 256 | * For ASoC users, if snd_hda_hdmi_codec module is denylisted and any | 
|---|
| 257 | * event causes i915 enumeration to fail, ->wcaps remains uninitialized. | 
|---|
| 258 | */ | 
|---|
| 259 | if (!codec->wcaps) | 
|---|
| 260 | return true; | 
|---|
| 261 |  | 
|---|
| 262 | for_each_hda_codec_node(nid, codec) { | 
|---|
| 263 | unsigned int wcaps = get_wcaps(codec, nid); | 
|---|
| 264 | switch (get_wcaps_type(wcaps)) { | 
|---|
| 265 | case AC_WID_AUD_IN: | 
|---|
| 266 | return false; /* HDMI parser supports only HDMI out */ | 
|---|
| 267 | case AC_WID_AUD_OUT: | 
|---|
| 268 | if (!(wcaps & AC_WCAP_DIGITAL)) | 
|---|
| 269 | return false; | 
|---|
| 270 | break; | 
|---|
| 271 | } | 
|---|
| 272 | } | 
|---|
| 273 | return true; | 
|---|
| 274 | } | 
|---|
| 275 | #else | 
|---|
| 276 | /* no HDMI codec parser support */ | 
|---|
| 277 | #define is_likely_hdmi_codec(codec)	false | 
|---|
| 278 | #endif /* CONFIG_SND_HDA_CODEC_HDMI */ | 
|---|
| 279 |  | 
|---|
| 280 | static int codec_bind_generic(struct hda_codec *codec) | 
|---|
| 281 | { | 
|---|
| 282 | if (codec->probe_id) | 
|---|
| 283 | return -ENODEV; | 
|---|
| 284 |  | 
|---|
| 285 | if (is_likely_hdmi_codec(codec)) { | 
|---|
| 286 | codec->probe_id = HDA_CODEC_ID_GENERIC_HDMI; | 
|---|
| 287 | request_codec_module(codec); | 
|---|
| 288 | if (codec_probed(codec)) | 
|---|
| 289 | return 0; | 
|---|
| 290 | } | 
|---|
| 291 |  | 
|---|
| 292 | codec->probe_id = HDA_CODEC_ID_GENERIC; | 
|---|
| 293 | request_codec_module(codec); | 
|---|
| 294 | if (codec_probed(codec)) | 
|---|
| 295 | return 0; | 
|---|
| 296 | return -ENODEV; | 
|---|
| 297 | } | 
|---|
| 298 |  | 
|---|
| 299 | #if IS_ENABLED(CONFIG_SND_HDA_GENERIC) | 
|---|
| 300 | #define is_generic_config(codec) \ | 
|---|
| 301 | (codec->modelname && !strcmp(codec->modelname, "generic")) | 
|---|
| 302 | #else | 
|---|
| 303 | #define is_generic_config(codec)	0 | 
|---|
| 304 | #endif | 
|---|
| 305 |  | 
|---|
| 306 | /** | 
|---|
| 307 | * snd_hda_codec_configure - (Re-)configure the HD-audio codec | 
|---|
| 308 | * @codec: the HDA codec | 
|---|
| 309 | * | 
|---|
| 310 | * Start parsing of the given codec tree and (re-)initialize the whole | 
|---|
| 311 | * codec driver binding. | 
|---|
| 312 | * | 
|---|
| 313 | * Returns 0 if successful or a negative error code. | 
|---|
| 314 | */ | 
|---|
| 315 | int snd_hda_codec_configure(struct hda_codec *codec) | 
|---|
| 316 | { | 
|---|
| 317 | int err; | 
|---|
| 318 |  | 
|---|
| 319 | if (codec->configured) | 
|---|
| 320 | return 0; | 
|---|
| 321 |  | 
|---|
| 322 | if (is_generic_config(codec)) | 
|---|
| 323 | codec->probe_id = HDA_CODEC_ID_GENERIC; | 
|---|
| 324 | else | 
|---|
| 325 | codec->probe_id = 0; | 
|---|
| 326 |  | 
|---|
| 327 | if (!device_is_registered(dev: &codec->core.dev)) { | 
|---|
| 328 | err = snd_hdac_device_register(codec: &codec->core); | 
|---|
| 329 | if (err < 0) | 
|---|
| 330 | return err; | 
|---|
| 331 | } | 
|---|
| 332 |  | 
|---|
| 333 | if (!codec->preset) | 
|---|
| 334 | codec_bind_module(codec); | 
|---|
| 335 | if (!codec->preset) { | 
|---|
| 336 | err = codec_bind_generic(codec); | 
|---|
| 337 | if (err < 0) { | 
|---|
| 338 | codec_dbg(codec, "Unable to bind the codec\n"); | 
|---|
| 339 | return err; | 
|---|
| 340 | } | 
|---|
| 341 | } | 
|---|
| 342 |  | 
|---|
| 343 | codec->configured = 1; | 
|---|
| 344 | return 0; | 
|---|
| 345 | } | 
|---|
| 346 | EXPORT_SYMBOL_GPL(snd_hda_codec_configure); | 
|---|
| 347 |  | 
|---|