@@ -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 */
@@ -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);
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@linux.intel.com> --- include/sound/hda_component.h | 5 +++++ sound/hda/hdac_component.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+)