diff options
Diffstat (limited to 'sound/hda/hda_bus_type.c')
-rw-r--r-- | sound/hda/hda_bus_type.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/sound/hda/hda_bus_type.c b/sound/hda/hda_bus_type.c new file mode 100644 index 0000000000..4cd94178df --- /dev/null +++ b/sound/hda/hda_bus_type.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * HD-audio bus + */ +#include <linux/init.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/export.h> +#include <sound/hdaudio.h> + +MODULE_DESCRIPTION("HD-audio bus"); +MODULE_LICENSE("GPL"); + +/** + * hdac_get_device_id - gets the hdac device id entry + * @hdev: HD-audio core device + * @drv: HD-audio codec driver + * + * Compares the hdac device vendor_id and revision_id to the hdac_device + * driver id_table and returns the matching device id entry. + */ +const struct hda_device_id * +hdac_get_device_id(struct hdac_device *hdev, struct hdac_driver *drv) +{ + if (drv->id_table) { + const struct hda_device_id *id = drv->id_table; + + while (id->vendor_id) { + if (hdev->vendor_id == id->vendor_id && + (!id->rev_id || id->rev_id == hdev->revision_id)) + return id; + id++; + } + } + + return NULL; +} +EXPORT_SYMBOL_GPL(hdac_get_device_id); + +static int hdac_codec_match(struct hdac_device *dev, struct hdac_driver *drv) +{ + if (hdac_get_device_id(dev, drv)) + return 1; + else + return 0; +} + +static int hda_bus_match(struct device *dev, struct device_driver *drv) +{ + struct hdac_device *hdev = dev_to_hdac_dev(dev); + struct hdac_driver *hdrv = drv_to_hdac_driver(drv); + + if (hdev->type != hdrv->type) + return 0; + + /* + * if driver provided a match function use that otherwise we will + * use hdac_codec_match function + */ + if (hdrv->match) + return hdrv->match(hdev, hdrv); + else + return hdac_codec_match(hdev, hdrv); + return 1; +} + +static int hda_uevent(const struct device *dev, struct kobj_uevent_env *env) +{ + char modalias[32]; + + snd_hdac_codec_modalias(dev_to_hdac_dev(dev), modalias, + sizeof(modalias)); + if (add_uevent_var(env, "MODALIAS=%s", modalias)) + return -ENOMEM; + return 0; +} + +struct bus_type snd_hda_bus_type = { + .name = "hdaudio", + .match = hda_bus_match, + .uevent = hda_uevent, +}; +EXPORT_SYMBOL_GPL(snd_hda_bus_type); + +static int __init hda_bus_init(void) +{ + return bus_register(&snd_hda_bus_type); +} + +static void __exit hda_bus_exit(void) +{ + bus_unregister(&snd_hda_bus_type); +} + +subsys_initcall(hda_bus_init); +module_exit(hda_bus_exit); |