LCOV - code coverage report
Current view: top level - sound/pci/hda - hda_bind.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 125 0.0 %
Date: 2022-04-01 14:58:12 Functions: 0 10 0.0 %
Branches: 0 82 0.0 %

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

Generated by: LCOV version 1.14