Message ID | 20230908133421.2483508-2-sbinding@opensource.cirrus.com |
---|---|
State | Superseded |
Headers | show |
Series | Support mute notifications for CS35L41 HDA | expand |
Hi Stefan, kernel test robot noticed the following build errors: [auto build test ERROR on tiwai-sound/for-next] [also build test ERROR on tiwai-sound/for-linus linus/master next-20230908] [cannot apply to v6.5] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Stefan-Binding/ALSA-hda-cs35l41-Support-mute-notifications-for-CS35L41-HDA/20230908-213735 base: https://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git for-next patch link: https://lore.kernel.org/r/20230908133421.2483508-2-sbinding%40opensource.cirrus.com patch subject: [PATCH v2 1/2] ALSA: hda: cs35l41: Support mute notifications for CS35L41 HDA config: x86_64-buildonly-randconfig-002-20230909 (https://download.01.org/0day-ci/archive/20230909/202309090456.mBm0zTlw-lkp@intel.com/config) compiler: clang version 16.0.4 (https://github.com/llvm/llvm-project.git ae42196bc493ffe877a7e3dff8be32035dea4d07) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230909/202309090456.mBm0zTlw-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202309090456.mBm0zTlw-lkp@intel.com/ All errors (new ones prefixed by >>): >> sound/pci/hda/patch_realtek.c:6718:31: error: call to undeclared function 'acpi_device_handle'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] spec->comps[i].acpi_notify(acpi_device_handle(spec->comps[i].adev), event, ^ >> sound/pci/hda/patch_realtek.c:6718:31: error: incompatible integer to pointer conversion passing 'int' to parameter of type 'acpi_handle' (aka 'void *') [-Wint-conversion] spec->comps[i].acpi_notify(acpi_device_handle(spec->comps[i].adev), event, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sound/pci/hda/patch_realtek.c:6737:7: error: call to undeclared function 'acpi_device_handle'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] if (!acpi_device_handle(adev)) ^ >> sound/pci/hda/patch_realtek.c:6745:41: error: incomplete definition of type 'struct acpi_device' ret = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, ~~~~^ include/linux/acpi.h:790:8: note: forward declaration of 'struct acpi_device' struct acpi_device; ^ sound/pci/hda/patch_realtek.c:6766:7: error: call to undeclared function 'acpi_device_handle'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] if (!acpi_device_handle(adev)) ^ sound/pci/hda/patch_realtek.c:6769:39: error: incomplete definition of type 'struct acpi_device' ret = acpi_remove_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, ~~~~^ include/linux/acpi.h:790:8: note: forward declaration of 'struct acpi_device' struct acpi_device; ^ 6 errors generated. vim +/acpi_device_handle +6718 sound/pci/hda/patch_realtek.c 6707 6708 static void comp_acpi_device_notify(acpi_handle handle, u32 event, void *data) 6709 { 6710 struct hda_codec *cdc = data; 6711 struct alc_spec *spec = cdc->spec; 6712 int i; 6713 6714 codec_info(cdc, "ACPI Notification %d\n", event); 6715 6716 for (i = 0; i < HDA_MAX_COMPONENTS; i++) { 6717 if (spec->comps[i].dev && spec->comps[i].acpi_notify) > 6718 spec->comps[i].acpi_notify(acpi_device_handle(spec->comps[i].adev), event, 6719 spec->comps[i].dev); 6720 } 6721 } 6722 6723 static int comp_bind(struct device *dev) 6724 { 6725 struct hda_codec *cdc = dev_to_hda_codec(dev); 6726 struct alc_spec *spec = cdc->spec; 6727 struct acpi_device *adev; 6728 bool support_notifications = false; 6729 int ret; 6730 int i; 6731 6732 ret = component_bind_all(dev, spec->comps); 6733 if (ret) 6734 return ret; 6735 6736 adev = spec->comps[0].adev; 6737 if (!acpi_device_handle(adev)) 6738 return 0; 6739 6740 for (i = 0; i < HDA_MAX_COMPONENTS; i++) 6741 support_notifications = support_notifications || 6742 spec->comps[i].acpi_notifications_supported; 6743 6744 if (support_notifications) { > 6745 ret = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, 6746 comp_acpi_device_notify, cdc); 6747 if (ret < 0) { 6748 codec_warn(cdc, "Failed to install notify handler: %d\n", ret); 6749 return 0; 6750 } 6751 6752 codec_dbg(cdc, "Notify handler installed\n"); 6753 } 6754 6755 return 0; 6756 } 6757
Hi Stefan, kernel test robot noticed the following build errors: [auto build test ERROR on tiwai-sound/for-next] [also build test ERROR on tiwai-sound/for-linus linus/master next-20230908] [cannot apply to v6.5] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Stefan-Binding/ALSA-hda-cs35l41-Support-mute-notifications-for-CS35L41-HDA/20230908-213735 base: https://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git for-next patch link: https://lore.kernel.org/r/20230908133421.2483508-2-sbinding%40opensource.cirrus.com patch subject: [PATCH v2 1/2] ALSA: hda: cs35l41: Support mute notifications for CS35L41 HDA config: riscv-randconfig-001-20230909 (https://download.01.org/0day-ci/archive/20230909/202309090555.tnWpQ7Gh-lkp@intel.com/config) compiler: clang version 15.0.7 (https://github.com/llvm/llvm-project.git 8dfdcc7b7bf66834a761bd8de445840ef68e4d1a) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230909/202309090555.tnWpQ7Gh-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202309090555.tnWpQ7Gh-lkp@intel.com/ All errors (new ones prefixed by >>): >> sound/pci/hda/patch_realtek.c:6718:31: error: call to undeclared function 'acpi_device_handle'; ISO C99 and later do not support implicit function declarations [-Werror,-Wimplicit-function-declaration] spec->comps[i].acpi_notify(acpi_device_handle(spec->comps[i].adev), event, ^ sound/pci/hda/patch_realtek.c:6718:31: error: incompatible integer to pointer conversion passing 'int' to parameter of type 'acpi_handle' (aka 'void *') [-Wint-conversion] spec->comps[i].acpi_notify(acpi_device_handle(spec->comps[i].adev), event, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sound/pci/hda/patch_realtek.c:6737:7: error: call to undeclared function 'acpi_device_handle'; ISO C99 and later do not support implicit function declarations [-Werror,-Wimplicit-function-declaration] if (!acpi_device_handle(adev)) ^ sound/pci/hda/patch_realtek.c:6745:41: error: incomplete definition of type 'struct acpi_device' ret = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, ~~~~^ include/linux/acpi.h:790:8: note: forward declaration of 'struct acpi_device' struct acpi_device; ^ sound/pci/hda/patch_realtek.c:6766:7: error: call to undeclared function 'acpi_device_handle'; ISO C99 and later do not support implicit function declarations [-Werror,-Wimplicit-function-declaration] if (!acpi_device_handle(adev)) ^ sound/pci/hda/patch_realtek.c:6769:39: error: incomplete definition of type 'struct acpi_device' ret = acpi_remove_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, ~~~~^ include/linux/acpi.h:790:8: note: forward declaration of 'struct acpi_device' struct acpi_device; ^ 6 errors generated. vim +/acpi_device_handle +6718 sound/pci/hda/patch_realtek.c 6707 6708 static void comp_acpi_device_notify(acpi_handle handle, u32 event, void *data) 6709 { 6710 struct hda_codec *cdc = data; 6711 struct alc_spec *spec = cdc->spec; 6712 int i; 6713 6714 codec_info(cdc, "ACPI Notification %d\n", event); 6715 6716 for (i = 0; i < HDA_MAX_COMPONENTS; i++) { 6717 if (spec->comps[i].dev && spec->comps[i].acpi_notify) > 6718 spec->comps[i].acpi_notify(acpi_device_handle(spec->comps[i].adev), event, 6719 spec->comps[i].dev); 6720 } 6721 } 6722
diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index f9b77353c266..18ca00c0a8cd 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -33,6 +33,9 @@ #define CAL_AMBIENT_DSP_CTL_NAME "CAL_AMBIENT" #define CAL_DSP_CTL_TYPE 5 #define CAL_DSP_CTL_ALG 205 +#define CS35L41_UUID "50d90cdc-3de4-4f18-b528-c7fe3b71f40d" +#define CS35L41_DSM_GET_MUTE 5 +#define CS35L41_NOTIFY_EVENT 0x91 static bool firmware_autostart = 1; module_param(firmware_autostart, bool, 0444); @@ -520,6 +523,31 @@ static void cs35l41_hda_play_start(struct device *dev) } +static void cs35l41_mute(struct device *dev, bool mute) +{ + struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); + struct regmap *reg = cs35l41->regmap; + + dev_dbg(dev, "Mute(%d:%d) Playback Started: %d\n", mute, cs35l41->mute_override, + cs35l41->playback_started); + + if (cs35l41->playback_started) { + if (mute || cs35l41->mute_override) { + dev_dbg(dev, "Muting\n"); + regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute)); + } else { + dev_dbg(dev, "Unmuting\n"); + if (cs35l41->firmware_running) { + regmap_multi_reg_write(reg, cs35l41_hda_unmute_dsp, + ARRAY_SIZE(cs35l41_hda_unmute_dsp)); + } else { + regmap_multi_reg_write(reg, cs35l41_hda_unmute, + ARRAY_SIZE(cs35l41_hda_unmute)); + } + } + } +} + static void cs35l41_hda_play_done(struct device *dev) { struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); @@ -529,13 +557,7 @@ static void cs35l41_hda_play_done(struct device *dev) cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 1, NULL, cs35l41->firmware_running); - if (cs35l41->firmware_running) { - regmap_multi_reg_write(reg, cs35l41_hda_unmute_dsp, - ARRAY_SIZE(cs35l41_hda_unmute_dsp)); - } else { - regmap_multi_reg_write(reg, cs35l41_hda_unmute, - ARRAY_SIZE(cs35l41_hda_unmute)); - } + cs35l41_mute(dev, false); } static void cs35l41_hda_pause_start(struct device *dev) @@ -545,7 +567,7 @@ static void cs35l41_hda_pause_start(struct device *dev) dev_dbg(dev, "Pause (Start)\n"); - regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute)); + cs35l41_mute(dev, true); cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 0, NULL, cs35l41->firmware_running); } @@ -1073,6 +1095,53 @@ static int cs35l41_create_controls(struct cs35l41_hda *cs35l41) return 0; } +static bool cs35l41_dsm_supported(acpi_handle handle, unsigned int commands) +{ + guid_t guid; + + guid_parse(CS35L41_UUID, &guid); + + return acpi_check_dsm(handle, &guid, 0, BIT(commands)); +} + +static int cs35l41_get_acpi_mute_state(struct cs35l41_hda *cs35l41, acpi_handle handle) +{ + guid_t guid; + union acpi_object *ret; + int mute = -ENODEV; + + guid_parse(CS35L41_UUID, &guid); + + if (cs35l41_dsm_supported(handle, CS35L41_DSM_GET_MUTE)) { + ret = acpi_evaluate_dsm(handle, &guid, 0, CS35L41_DSM_GET_MUTE, NULL); + mute = *ret->buffer.pointer; + dev_dbg(cs35l41->dev, "CS35L41_DSM_GET_MUTE: %d\n", mute); + } + + dev_dbg(cs35l41->dev, "%s: %d\n", __func__, mute); + + return mute; +} + +static void cs35l41_acpi_device_notify(acpi_handle handle, u32 event, struct device *dev) +{ + struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); + int mute; + + if (event != CS35L41_NOTIFY_EVENT) + return; + + mute = cs35l41_get_acpi_mute_state(cs35l41, handle); + if (mute < 0) { + dev_warn(cs35l41->dev, "Unable to retrieve mute state: %d\n", mute); + return; + } + + dev_dbg(cs35l41->dev, "Requesting mute value: %d\n", mute); + cs35l41->mute_override = (mute > 0); + cs35l41_mute(cs35l41->dev, cs35l41->mute_override); +} + static int cs35l41_hda_bind(struct device *dev, struct device *master, void *master_data) { struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); @@ -1114,6 +1183,14 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas comps->playback_hook = cs35l41_hda_playback_hook; comps->pre_playback_hook = cs35l41_hda_pre_playback_hook; comps->post_playback_hook = cs35l41_hda_post_playback_hook; + comps->acpi_notify = cs35l41_acpi_device_notify; + comps->adev = cs35l41->dacpi; + + comps->acpi_notifications_supported = cs35l41_dsm_supported(acpi_device_handle(comps->adev), + CS35L41_DSM_GET_MUTE); + + cs35l41->mute_override = cs35l41_get_acpi_mute_state(cs35l41, + acpi_device_handle(cs35l41->dacpi)) > 0; mutex_unlock(&cs35l41->fw_mutex); @@ -1387,8 +1464,8 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i return -ENODEV; } + cs35l41->dacpi = adev; physdev = get_device(acpi_get_first_physical_node(adev)); - acpi_dev_put(adev); sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev)); if (IS_ERR(sub)) @@ -1498,6 +1575,7 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i hw_cfg->valid = false; hw_cfg->gpio1.valid = false; hw_cfg->gpio2.valid = false; + acpi_dev_put(cs35l41->dacpi); put_physdev: put_device(physdev); @@ -1601,10 +1679,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i if (ret) goto err; - ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_hda_mute, - ARRAY_SIZE(cs35l41_hda_mute)); - if (ret) - goto err; + cs35l41_mute(cs35l41->dev, true); INIT_WORK(&cs35l41->fw_load_work, cs35l41_fw_load_work); mutex_init(&cs35l41->fw_mutex); @@ -1641,6 +1716,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type)) gpiod_set_value_cansleep(cs35l41->reset_gpio, 0); gpiod_put(cs35l41->reset_gpio); + acpi_dev_put(cs35l41->dacpi); kfree(cs35l41->acpi_subsystem_id); return ret; @@ -1659,6 +1735,8 @@ void cs35l41_hda_remove(struct device *dev) component_del(cs35l41->dev, &cs35l41_hda_comp_ops); + acpi_dev_put(cs35l41->dacpi); + pm_runtime_put_noidle(cs35l41->dev); if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type)) diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h index b93bf762976e..ce3f2bb6ffd0 100644 --- a/sound/pci/hda/cs35l41_hda.h +++ b/sound/pci/hda/cs35l41_hda.h @@ -10,6 +10,7 @@ #ifndef __CS35L41_HDA_H__ #define __CS35L41_HDA_H__ +#include <linux/acpi.h> #include <linux/efi.h> #include <linux/regulator/consumer.h> #include <linux/gpio/consumer.h> @@ -70,6 +71,8 @@ struct cs35l41_hda { bool halo_initialized; bool playback_started; struct cs_dsp cs_dsp; + struct acpi_device *dacpi; + bool mute_override; }; enum halo_state { diff --git a/sound/pci/hda/hda_component.h b/sound/pci/hda/hda_component.h index f170aec967c1..bbd6f0ed16c1 100644 --- a/sound/pci/hda/hda_component.h +++ b/sound/pci/hda/hda_component.h @@ -6,6 +6,7 @@ * Cirrus Logic International Semiconductor Ltd. */ +#include <linux/acpi.h> #include <linux/component.h> #define HDA_MAX_COMPONENTS 4 @@ -15,6 +16,9 @@ struct hda_component { struct device *dev; char name[HDA_MAX_NAME_SIZE]; struct hda_codec *codec; + struct acpi_device *adev; + bool acpi_notifications_supported; + void (*acpi_notify)(acpi_handle handle, u32 event, struct device *dev); void (*pre_playback_hook)(struct device *dev, int action); void (*playback_hook)(struct device *dev, int action); void (*post_playback_hook)(struct device *dev, int action); diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b7e78bfcffd8..d70d7410f455 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -10,6 +10,7 @@ * Jonathan Woithe <jwoithe@just42.net> */ +#include <linux/acpi.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/slab.h> @@ -6704,19 +6705,73 @@ static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec, } } +static void comp_acpi_device_notify(acpi_handle handle, u32 event, void *data) +{ + struct hda_codec *cdc = data; + struct alc_spec *spec = cdc->spec; + int i; + + codec_info(cdc, "ACPI Notification %d\n", event); + + for (i = 0; i < HDA_MAX_COMPONENTS; i++) { + if (spec->comps[i].dev && spec->comps[i].acpi_notify) + spec->comps[i].acpi_notify(acpi_device_handle(spec->comps[i].adev), event, + spec->comps[i].dev); + } +} + static int comp_bind(struct device *dev) { struct hda_codec *cdc = dev_to_hda_codec(dev); struct alc_spec *spec = cdc->spec; + struct acpi_device *adev; + bool support_notifications = false; + int ret; + int i; + + ret = component_bind_all(dev, spec->comps); + if (ret) + return ret; - return component_bind_all(dev, spec->comps); + adev = spec->comps[0].adev; + if (!acpi_device_handle(adev)) + return 0; + + for (i = 0; i < HDA_MAX_COMPONENTS; i++) + support_notifications = support_notifications || + spec->comps[i].acpi_notifications_supported; + + if (support_notifications) { + ret = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, + comp_acpi_device_notify, cdc); + if (ret < 0) { + codec_warn(cdc, "Failed to install notify handler: %d\n", ret); + return 0; + } + + codec_dbg(cdc, "Notify handler installed\n"); + } + + return 0; } static void comp_unbind(struct device *dev) { struct hda_codec *cdc = dev_to_hda_codec(dev); struct alc_spec *spec = cdc->spec; + struct acpi_device *adev; + int ret; + + adev = spec->comps[0].adev; + if (!acpi_device_handle(adev)) + goto unbind; + + ret = acpi_remove_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, + comp_acpi_device_notify); + if (ret < 0) + codec_warn(cdc, "Failed to uninstall notify handler: %d\n", ret); +unbind: component_unbind_all(dev, spec->comps); }