mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
ALSA: hda/realtek: Support ACPI Notification framework via component binding
For systems which have support for ACPI notifications, add a mechanism to register a handler for ACPI notifications and then call the acpi_notify api on the bound components. Registering a handler in the Realtek HDA driver, allows a single handler to be registered, which then calls into all the components, rather than attempting to register the same handler multiple times, once for each component. Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com> Link: https://lore.kernel.org/r/20230921162849.1988124-3-sbinding@opensource.cirrus.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
502629a755
commit
7ce669334c
@ -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,12 +6705,91 @@ static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
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_acpi(struct device *dev)
|
||||
{
|
||||
struct hda_codec *cdc = dev_to_hda_codec(dev);
|
||||
struct alc_spec *spec = cdc->spec;
|
||||
bool support_notifications = false;
|
||||
struct acpi_device *adev;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
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_acpi(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))
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
#else
|
||||
static int comp_bind_acpi(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void comp_unbind_acpi(struct device *dev)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static int comp_bind(struct device *dev)
|
||||
{
|
||||
struct hda_codec *cdc = dev_to_hda_codec(dev);
|
||||
struct alc_spec *spec = cdc->spec;
|
||||
int ret;
|
||||
|
||||
return component_bind_all(dev, spec->comps);
|
||||
ret = component_bind_all(dev, spec->comps);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return comp_bind_acpi(dev);
|
||||
}
|
||||
|
||||
static void comp_unbind(struct device *dev)
|
||||
@ -6717,6 +6797,7 @@ static void comp_unbind(struct device *dev)
|
||||
struct hda_codec *cdc = dev_to_hda_codec(dev);
|
||||
struct alc_spec *spec = cdc->spec;
|
||||
|
||||
comp_unbind_acpi(dev);
|
||||
component_unbind_all(dev, spec->comps);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user