2 * hdac_i915.c - routines for sync between HD-A core and i915 display driver
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 #include <linux/init.h>
16 #include <linux/module.h>
17 #include <linux/pci.h>
18 #include <linux/component.h>
19 #include <drm/i915_component.h>
20 #include <sound/core.h>
21 #include <sound/hdaudio.h>
22 #include <sound/hda_i915.h>
24 static struct i915_audio_component
*hdac_acomp
;
26 int snd_hdac_set_codec_wakeup(struct hdac_bus
*bus
, bool enable
)
28 struct i915_audio_component
*acomp
= bus
->audio_component
;
30 if (!acomp
|| !acomp
->ops
)
33 if (!acomp
->ops
->codec_wake_override
) {
35 "Invalid codec wake callback\n");
39 dev_dbg(bus
->dev
, "%s codec wakeup\n",
40 enable
? "enable" : "disable");
42 acomp
->ops
->codec_wake_override(acomp
->dev
, enable
);
46 EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup
);
48 int snd_hdac_display_power(struct hdac_bus
*bus
, bool enable
)
50 struct i915_audio_component
*acomp
= bus
->audio_component
;
52 if (!acomp
|| !acomp
->ops
)
55 dev_dbg(bus
->dev
, "display power %s\n",
56 enable
? "enable" : "disable");
59 if (!bus
->i915_power_refcount
++)
60 acomp
->ops
->get_power(acomp
->dev
);
62 WARN_ON(!bus
->i915_power_refcount
);
63 if (!--bus
->i915_power_refcount
)
64 acomp
->ops
->put_power(acomp
->dev
);
69 EXPORT_SYMBOL_GPL(snd_hdac_display_power
);
71 int snd_hdac_get_display_clk(struct hdac_bus
*bus
)
73 struct i915_audio_component
*acomp
= bus
->audio_component
;
75 if (!acomp
|| !acomp
->ops
)
78 return acomp
->ops
->get_cdclk_freq(acomp
->dev
);
80 EXPORT_SYMBOL_GPL(snd_hdac_get_display_clk
);
82 static int hdac_component_master_bind(struct device
*dev
)
84 struct i915_audio_component
*acomp
= hdac_acomp
;
87 ret
= component_bind_all(dev
, acomp
);
91 if (WARN_ON(!(acomp
->dev
&& acomp
->ops
&& acomp
->ops
->get_power
&&
92 acomp
->ops
->put_power
&& acomp
->ops
->get_cdclk_freq
))) {
98 * Atm, we don't support dynamic unbinding initiated by the child
99 * component, so pin its containing module until we unbind.
101 if (!try_module_get(acomp
->ops
->owner
)) {
109 component_unbind_all(dev
, acomp
);
114 static void hdac_component_master_unbind(struct device
*dev
)
116 struct i915_audio_component
*acomp
= hdac_acomp
;
118 module_put(acomp
->ops
->owner
);
119 component_unbind_all(dev
, acomp
);
120 WARN_ON(acomp
->ops
|| acomp
->dev
);
123 static const struct component_master_ops hdac_component_master_ops
= {
124 .bind
= hdac_component_master_bind
,
125 .unbind
= hdac_component_master_unbind
,
128 static int hdac_component_master_match(struct device
*dev
, void *data
)
130 /* i915 is the only supported component */
131 return !strcmp(dev
->driver
->name
, "i915");
134 int snd_hdac_i915_init(struct hdac_bus
*bus
)
136 struct component_match
*match
= NULL
;
137 struct device
*dev
= bus
->dev
;
138 struct i915_audio_component
*acomp
;
141 acomp
= kzalloc(sizeof(*acomp
), GFP_KERNEL
);
144 bus
->audio_component
= acomp
;
147 component_match_add(dev
, &match
, hdac_component_master_match
, bus
);
148 ret
= component_master_add_with_match(dev
, &hdac_component_master_ops
,
154 * Atm, we don't support deferring the component binding, so make sure
155 * i915 is loaded and that the binding successfully completes.
157 request_module("i915");
163 dev_dbg(dev
, "bound to i915 component master\n");
167 component_master_del(dev
, &hdac_component_master_ops
);
170 bus
->audio_component
= NULL
;
171 dev_err(dev
, "failed to add i915 component master (%d)\n", ret
);
175 EXPORT_SYMBOL_GPL(snd_hdac_i915_init
);
177 int snd_hdac_i915_exit(struct hdac_bus
*bus
)
179 struct device
*dev
= bus
->dev
;
180 struct i915_audio_component
*acomp
= bus
->audio_component
;
185 WARN_ON(bus
->i915_power_refcount
);
186 if (bus
->i915_power_refcount
> 0 && acomp
->ops
)
187 acomp
->ops
->put_power(acomp
->dev
);
189 component_master_del(dev
, &hdac_component_master_ops
);
192 bus
->audio_component
= NULL
;
196 EXPORT_SYMBOL_GPL(snd_hdac_i915_exit
);