@@ -303,6 +303,7 @@ struct hdac_bus {
/* i915 component interface */
struct i915_audio_component *audio_component;
+ struct mutex audio_component_lock;
int i915_power_refcount;
};
@@ -26,17 +26,31 @@ struct hdac_gfx_component {
const struct component_master_ops *ops;
};
+static struct i915_audio_component *bus_get_acomp(struct hdac_bus *bus)
+{
+ mutex_lock(&bus->audio_component_lock);
+ return bus->audio_component;
+}
+
+static void bus_put_acomp(struct hdac_bus *bus)
+{
+ mutex_lock(&bus->audio_component_lock);
+}
+
int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable)
{
- struct i915_audio_component *acomp = bus->audio_component;
+ struct i915_audio_component *acomp = bus_get_acomp(bus);
+ int ret = 0;
- if (!acomp || !acomp->ops)
- return -ENODEV;
+ if (!acomp || !acomp->ops) {
+ ret = -ENODEV;
+ goto out;
+ }
if (!acomp->ops->codec_wake_override) {
dev_warn(bus->dev,
"Invalid codec wake callback\n");
- return 0;
+ goto out;
}
dev_dbg(bus->dev, "%s codec wakeup\n",
@@ -44,16 +58,21 @@ int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable)
acomp->ops->codec_wake_override(acomp->dev, enable);
- return 0;
+ out:
+ bus_put_acomp(bus);
+ return ret;
}
EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup);
int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
{
- struct i915_audio_component *acomp = bus->audio_component;
+ struct i915_audio_component *acomp = bus_get_acomp(bus);
+ int ret = 0;
- if (!acomp || !acomp->ops)
- return -ENODEV;
+ if (!acomp || !acomp->ops) {
+ ret = -ENODEV;
+ goto out;
+ }
dev_dbg(bus->dev, "display power %s\n",
enable ? "enable" : "disable");
@@ -70,18 +89,22 @@ int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
acomp->ops->put_power(acomp->dev);
}
- return 0;
+ out:
+ bus_put_acomp(bus);
+ return ret;
}
EXPORT_SYMBOL_GPL(snd_hdac_display_power);
int snd_hdac_get_display_clk(struct hdac_bus *bus)
{
- struct i915_audio_component *acomp = bus->audio_component;
+ struct i915_audio_component *acomp = bus_get_acomp(bus);
+ int ret;
if (!acomp || !acomp->ops)
- return -ENODEV;
-
- return acomp->ops->get_cdclk_freq(acomp->dev);
+ ret = -ENODEV;
+ ret = acomp->ops->get_cdclk_freq(acomp->dev);
+ bus_put_acomp(bus);
+ return ret;
}
EXPORT_SYMBOL_GPL(snd_hdac_get_display_clk);
@@ -89,14 +112,14 @@ static int hdac_component_master_bind(struct device *dev)
{
struct hdac_device *codec = dev_to_hdac_dev(dev);
struct hdac_bus *bus = codec->bus;
- struct i915_audio_component *acomp = bus->audio_component;
+ struct i915_audio_component *acomp = bus_get_acomp(bus);
struct hdac_gfx_component *hda_comp =
container_of(acomp, struct hdac_gfx_component, acomp);
int ret;
ret = component_bind_all(dev, acomp);
if (ret < 0)
- return ret;
+ goto out_unlock;
if (WARN_ON(!(acomp->dev && acomp->ops && acomp->ops->get_power &&
acomp->ops->put_power && acomp->ops->get_cdclk_freq))) {
@@ -125,7 +148,8 @@ static int hdac_component_master_bind(struct device *dev)
out_unbind:
component_unbind_all(dev, acomp);
-
+ out_unlock:
+ bus_put_acomp(bus);
return ret;
}
@@ -133,7 +157,7 @@ static void hdac_component_master_unbind(struct device *dev)
{
struct hdac_device *codec = dev_to_hdac_dev(dev);
struct hdac_bus *bus = codec->bus;
- struct i915_audio_component *acomp = bus->audio_component;
+ struct i915_audio_component *acomp = bus_get_acomp(bus);
struct hdac_gfx_component *hda_comp =
container_of(acomp, struct hdac_gfx_component, acomp);
@@ -142,6 +166,7 @@ static void hdac_component_master_unbind(struct device *dev)
module_put(acomp->ops->owner);
component_unbind_all(dev, acomp);
WARN_ON(acomp->ops || acomp->dev);
+ bus_put_acomp(bus);
}
static const struct component_master_ops hdac_component_master_ops = {
@@ -159,12 +184,13 @@ int snd_hdac_i915_register_notifier(struct hdac_device *codec,
const struct i915_audio_component_audio_ops *aops)
{
struct hdac_bus *bus = codec->bus;
- struct i915_audio_component *acomp = bus->audio_component;
+ struct i915_audio_component *acomp = bus_get_acomp(bus);
if (WARN_ON(!acomp))
return -ENODEV;
acomp->audio_ops = aops;
+ bus_put_acomp(bus);
return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_i915_register_notifier);
@@ -179,6 +205,7 @@ int snd_hdac_i915_init(struct hdac_bus *bus,
hda_comp = kzalloc(sizeof(*hda_comp), GFP_KERNEL);
if (!hda_comp)
return -ENOMEM;
+ mutex_init(&bus->audio_component_lock);
bus->audio_component = &hda_comp->acomp;
hda_comp->ops = codec_ops;