In current HDA component implementation, HDA controller drivers use snd_hdac_acomp_init() and pass it the HDA bus instance (hdac_bus). When registration to component framework is done, the HDA controller device instance 'hdac_bus->dev' is used. In the component bind/unbind callbacks, only the device handle is passed as context, and it is not possible to look up the HDA bus instance. Fix this gap by adding a separate devres entry for the bus handle. Signed-off-by: Kai Vehmanen <kai.vehmanen@xxxxxxxxxxxxxxx> --- include/sound/hda_component.h | 5 +++++ sound/hda/hdac_component.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/include/sound/hda_component.h b/include/sound/hda_component.h index d4804c72d959..476cc4e2083c 100644 --- a/include/sound/hda_component.h +++ b/include/sound/hda_component.h @@ -25,6 +25,7 @@ int snd_hdac_acomp_init(struct hdac_bus *bus, int snd_hdac_acomp_exit(struct hdac_bus *bus); int snd_hdac_acomp_register_notifier(struct hdac_bus *bus, const struct drm_audio_component_audio_ops *ops); +struct hdac_bus *snd_hdac_acomp_get_bus(struct device *dev); #else static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) { @@ -62,6 +63,10 @@ static inline int snd_hdac_acomp_register_notifier(struct hdac_bus *bus, { return -ENODEV; } +static struct hdac_bus *snd_hdac_acomp_get_bus(struct device *dev) +{ + return NULL; +} #endif #endif /* __SOUND_HDA_COMPONENT_H */ diff --git a/sound/hda/hdac_component.c b/sound/hda/hdac_component.c index 89126c6fd216..d9d2675982f0 100644 --- a/sound/hda/hdac_component.c +++ b/sound/hda/hdac_component.c @@ -19,6 +19,29 @@ static struct drm_audio_component *hdac_get_acomp(struct device *dev) return devres_find(dev, hdac_acomp_release, NULL, NULL); } +static void hdac_acomp_bus_release(struct device *dev, void *res) +{ +} + +/** + * snd_hdac_acomp_get_bus - Get HDA core bus instance + * @dev: device + * + * If audio component registration has been done, this function + * will return the matching HDA core bus. Returns NULL otherwise. + */ +struct hdac_bus *snd_hdac_acomp_get_bus(struct device *dev) +{ + struct drm_audio_component *acomp = hdac_get_acomp(dev); + struct hdac_bus **bus = + devres_find(dev, hdac_acomp_bus_release, NULL, NULL); + if (!acomp || !*bus) + return NULL; + + return *bus; +} +EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_bus); + /** * snd_hdac_set_codec_wakeup - Enable / disable HDMI/DP codec wakeup * @bus: HDA core bus @@ -286,6 +309,7 @@ int snd_hdac_acomp_init(struct hdac_bus *bus, struct component_match *match = NULL; struct device *dev = bus->dev; struct drm_audio_component *acomp; + struct hdac_bus **bus_ptr; int ret; if (WARN_ON(hdac_get_acomp(dev))) @@ -299,6 +323,14 @@ int snd_hdac_acomp_init(struct hdac_bus *bus, bus->audio_component = acomp; devres_add(dev, acomp); + bus_ptr = devres_alloc(hdac_acomp_bus_release, sizeof(*bus_ptr), GFP_KERNEL); + if (!bus_ptr) { + ret = -ENOMEM; + goto out_err_busptr; + } + *bus_ptr = bus; + devres_add(dev, bus_ptr); + component_match_add_typed(dev, &match, match_master, bus); ret = component_master_add_with_match(dev, &hdac_component_master_ops, match); @@ -308,6 +340,8 @@ int snd_hdac_acomp_init(struct hdac_bus *bus, return 0; out_err: + devres_destroy(dev, hdac_acomp_bus_release, NULL, NULL); +out_err_busptr: bus->audio_component = NULL; devres_destroy(dev, hdac_acomp_release, NULL, NULL); dev_info(dev, "failed to add audio component master (%d)\n", ret); -- 2.28.0