From 1f93a7dfd1f8d5ff7a5c53246c7534fe2332d6f4 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 11 Dec 2023 02:46:07 +0000 Subject: [PATCH] add audio --- kernel/sound/hda/hdac_device.c | 78 +++++++++++++++++++-------------------- 1 files changed, 38 insertions(+), 40 deletions(-) diff --git a/kernel/sound/hda/hdac_device.c b/kernel/sound/hda/hdac_device.c index 58b53a4..b7e5032 100644 --- a/kernel/sound/hda/hdac_device.c +++ b/kernel/sound/hda/hdac_device.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * HD-audio codec core device */ @@ -19,7 +20,7 @@ static void default_release(struct device *dev) { - snd_hdac_device_exit(container_of(dev, struct hdac_device, dev)); + snd_hdac_device_exit(dev_to_hdac_dev(dev)); } /** @@ -55,6 +56,8 @@ codec->bus = bus; codec->addr = addr; codec->type = HDA_DEV_CORE; + mutex_init(&codec->widget_lock); + mutex_init(&codec->regmap_lock); pm_runtime_set_active(&codec->dev); pm_runtime_get_noresume(&codec->dev); atomic_set(&codec->in_pm, 0); @@ -88,7 +91,7 @@ fg = codec->afg ? codec->afg : codec->mfg; - err = snd_hdac_refresh_widgets(codec, false); + err = snd_hdac_refresh_widgets(codec); if (err < 0) goto error; @@ -134,7 +137,7 @@ /** * snd_hdac_device_register - register the hd-audio codec base device - * codec: the device to register + * @codec: the device to register */ int snd_hdac_device_register(struct hdac_device *codec) { @@ -143,7 +146,9 @@ err = device_add(&codec->dev); if (err < 0) return err; + mutex_lock(&codec->widget_lock); err = hda_widget_sysfs_init(codec); + mutex_unlock(&codec->widget_lock); if (err < 0) { device_del(&codec->dev); return err; @@ -155,12 +160,14 @@ /** * snd_hdac_device_unregister - unregister the hd-audio codec base device - * codec: the device to unregister + * @codec: the device to unregister */ void snd_hdac_device_unregister(struct hdac_device *codec) { if (device_is_registered(&codec->dev)) { + mutex_lock(&codec->widget_lock); hda_widget_sysfs_exit(codec); + mutex_unlock(&codec->widget_lock); device_del(&codec->dev); snd_hdac_bus_remove_device(codec->bus, codec); } @@ -199,7 +206,7 @@ */ int snd_hdac_codec_modalias(struct hdac_device *codec, char *buf, size_t size) { - return snprintf(buf, size, "hdaudio:v%08Xr%08Xa%02X\n", + return scnprintf(buf, size, "hdaudio:v%08Xr%08Xa%02X\n", codec->vendor_id, codec->revision_id, codec->type); } EXPORT_SYMBOL_GPL(snd_hdac_codec_modalias); @@ -214,8 +221,8 @@ * * Return an encoded command verb or -1 for error. */ -unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid, - unsigned int verb, unsigned int parm) +static unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid, + unsigned int verb, unsigned int parm) { u32 val, addr; @@ -233,7 +240,6 @@ val |= parm; return val; } -EXPORT_SYMBOL_GPL(snd_hdac_make_cmd); /** * snd_hdac_exec_verb - execute an encoded verb @@ -254,7 +260,6 @@ return codec->exec_verb(codec, cmd, flags, res); return snd_hdac_bus_exec_verb(codec->bus, codec->addr, cmd, res); } -EXPORT_SYMBOL_GPL(snd_hdac_exec_verb); /** @@ -278,6 +283,10 @@ /** * _snd_hdac_read_parm - read a parmeter + * @codec: the codec object + * @nid: NID to read a parameter + * @parm: parameter to read + * @res: pointer to store the read value * * This function returns zero or an error unlike snd_hdac_read_parm(). */ @@ -391,30 +400,35 @@ /** * snd_hdac_refresh_widgets - Reset the widget start/end nodes * @codec: the codec object - * @sysfs: re-initialize sysfs tree, too */ -int snd_hdac_refresh_widgets(struct hdac_device *codec, bool sysfs) +int snd_hdac_refresh_widgets(struct hdac_device *codec) { hda_nid_t start_nid; - int nums, err; + int nums, err = 0; + /* + * Serialize against multiple threads trying to update the sysfs + * widgets array. + */ + mutex_lock(&codec->widget_lock); nums = snd_hdac_get_sub_nodes(codec, codec->afg, &start_nid); if (!start_nid || nums <= 0 || nums >= 0xff) { dev_err(&codec->dev, "cannot read sub nodes for FG 0x%02x\n", codec->afg); - return -EINVAL; + err = -EINVAL; + goto unlock; } - if (sysfs) { - err = hda_widget_sysfs_reinit(codec, start_nid, nums); - if (err < 0) - return err; - } + err = hda_widget_sysfs_reinit(codec, start_nid, nums); + if (err < 0) + goto unlock; codec->num_nodes = nums; codec->start_nid = start_nid; codec->end_nid = start_nid + nums; - return 0; +unlock: + mutex_unlock(&codec->widget_lock); + return err; } EXPORT_SYMBOL_GPL(snd_hdac_refresh_widgets); @@ -624,30 +638,13 @@ EXPORT_SYMBOL_GPL(snd_hdac_power_down_pm); #endif -/** - * snd_hdac_link_power - Enable/disable the link power for a codec - * @codec: the codec object - * @bool: enable or disable the link power - */ -int snd_hdac_link_power(struct hdac_device *codec, bool enable) -{ - if (!codec->link_power_control) - return 0; - - if (codec->bus->ops->link_power) - return codec->bus->ops->link_power(codec->bus, enable); - else - return -EINVAL; -} -EXPORT_SYMBOL_GPL(snd_hdac_link_power); - /* codec vendor labels */ struct hda_vendor_id { unsigned int id; const char *name; }; -static struct hda_vendor_id hda_vendor_ids[] = { +static const struct hda_vendor_id hda_vendor_ids[] = { { 0x1002, "ATI" }, { 0x1013, "Cirrus Logic" }, { 0x1057, "Motorola" }, @@ -663,6 +660,7 @@ { 0x14f1, "Conexant" }, { 0x17e8, "Chrontel" }, { 0x1854, "LG" }, + { 0x19e5, "Huawei" }, { 0x1aec, "Wolfson Microelectronics" }, { 0x1af4, "QEMU" }, { 0x434d, "C-Media" }, @@ -702,7 +700,7 @@ (AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \ (((div) - 1) << AC_FMT_DIV_SHIFT)) -static struct hda_rate_tbl rate_bits[] = { +static const struct hda_rate_tbl rate_bits[] = { /* rate in Hz, ALSA rate bitmask, HDA format value */ /* autodetected value used in snd_hda_query_supported_pcm */ @@ -1071,9 +1069,9 @@ * snd_hdac_sync_power_state - wait until actual power state matches * with the target state * - * @hdac: the HDAC device + * @codec: the HDAC device * @nid: NID to send the command - * @target_state: target state to check for + * @power_state: target power state to wait for * * Return power state or PS_ERROR if codec rejects GET verb. */ -- Gitblit v1.6.2