xref: /linux/sound/hda/hdac_component.c (revision 2c8d2a510c15c003749e43ac2b8e1bc79a7a00d6)
1 // SPDX-License-Identifier: GPL-2.0
2 // hdac_component.c - routines for sync between HD-A core and DRM driver
3 
4 #include <linux/init.h>
5 #include <linux/module.h>
6 #include <linux/pci.h>
7 #include <linux/component.h>
8 #include <linux/string_choices.h>
9 #include <sound/core.h>
10 #include <sound/hdaudio.h>
11 #include <sound/hda_component.h>
12 #include <sound/hda_register.h>
13 
14 static void hdac_acomp_release(struct device *dev, void *res)
15 {
16 }
17 
18 static struct drm_audio_component *hdac_get_acomp(struct device *dev)
19 {
20 	return devres_find(dev, hdac_acomp_release, NULL, NULL);
21 }
22 
23 /**
24  * snd_hdac_set_codec_wakeup - Enable / disable HDMI/DP codec wakeup
25  * @bus: HDA core bus
26  * @enable: enable or disable the wakeup
27  *
28  * This function is supposed to be used only by a HD-audio controller
29  * driver that needs the interaction with graphics driver.
30  *
31  * This function should be called during the chip reset, also called at
32  * resume for updating STATESTS register read.
33  *
34  * Returns zero for success or a negative error code.
35  */
36 int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable)
37 {
38 	struct drm_audio_component *acomp = bus->audio_component;
39 
40 	if (!acomp || !acomp->ops)
41 		return -ENODEV;
42 
43 	if (!acomp->ops->codec_wake_override)
44 		return 0;
45 
46 	dev_dbg(bus->dev, "%s codec wakeup\n", str_enable_disable(enable));
47 
48 	acomp->ops->codec_wake_override(acomp->dev, enable);
49 
50 	return 0;
51 }
52 EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup);
53 
54 /**
55  * snd_hdac_display_power - Power up / down the power refcount
56  * @bus: HDA core bus
57  * @idx: HDA codec address, pass HDA_CODEC_IDX_CONTROLLER for controller
58  * @enable: power up or down
59  *
60  * This function is used by either HD-audio controller or codec driver that
61  * needs the interaction with graphics driver.
62  *
63  * This function updates the power status, and calls the get_power() and
64  * put_power() ops accordingly, toggling the codec wakeup, too.
65  */
66 void snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable)
67 {
68 	struct drm_audio_component *acomp = bus->audio_component;
69 
70 	dev_dbg(bus->dev, "display power %s\n", str_enable_disable(enable));
71 
72 	mutex_lock(&bus->lock);
73 	if (enable)
74 		set_bit(idx, &bus->display_power_status);
75 	else
76 		clear_bit(idx, &bus->display_power_status);
77 
78 	if (!acomp || !acomp->ops)
79 		goto unlock;
80 
81 	if (bus->display_power_status) {
82 		if (!bus->display_power_active) {
83 			unsigned long cookie = -1;
84 
85 			if (acomp->ops->get_power)
86 				cookie = acomp->ops->get_power(acomp->dev);
87 
88 			snd_hdac_set_codec_wakeup(bus, true);
89 			snd_hdac_set_codec_wakeup(bus, false);
90 			bus->display_power_active = cookie;
91 		}
92 	} else {
93 		if (bus->display_power_active) {
94 			unsigned long cookie = bus->display_power_active;
95 
96 			if (acomp->ops->put_power)
97 				acomp->ops->put_power(acomp->dev, cookie);
98 
99 			bus->display_power_active = 0;
100 		}
101 	}
102  unlock:
103 	mutex_unlock(&bus->lock);
104 }
105 EXPORT_SYMBOL_GPL(snd_hdac_display_power);
106 
107 /**
108  * snd_hdac_sync_audio_rate - Set N/CTS based on the sample rate
109  * @codec: HDA codec
110  * @nid: the pin widget NID
111  * @dev_id: device identifier
112  * @rate: the sample rate to set
113  *
114  * This function is supposed to be used only by a HD-audio controller
115  * driver that needs the interaction with graphics driver.
116  *
117  * This function sets N/CTS value based on the given sample rate.
118  * Returns zero for success, or a negative error code.
119  */
120 int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid,
121 			     int dev_id, int rate)
122 {
123 	struct hdac_bus *bus = codec->bus;
124 	struct drm_audio_component *acomp = bus->audio_component;
125 	int port, pipe;
126 
127 	if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate)
128 		return -ENODEV;
129 	port = nid;
130 	if (acomp->audio_ops && acomp->audio_ops->pin2port) {
131 		port = acomp->audio_ops->pin2port(codec, nid);
132 		if (port < 0)
133 			return -EINVAL;
134 	}
135 	pipe = dev_id;
136 	return acomp->ops->sync_audio_rate(acomp->dev, port, pipe, rate);
137 }
138 EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate);
139 
140 /**
141  * snd_hdac_acomp_get_eld - Get the audio state and ELD via component
142  * @codec: HDA codec
143  * @nid: the pin widget NID
144  * @dev_id: device identifier
145  * @audio_enabled: the pointer to store the current audio state
146  * @buffer: the buffer pointer to store ELD bytes
147  * @max_bytes: the max bytes to be stored on @buffer
148  *
149  * This function is supposed to be used only by a HD-audio controller
150  * driver that needs the interaction with graphics driver.
151  *
152  * This function queries the current state of the audio on the given
153  * digital port and fetches the ELD bytes onto the given buffer.
154  * It returns the number of bytes for the total ELD data, zero for
155  * invalid ELD, or a negative error code.
156  *
157  * The return size is the total bytes required for the whole ELD bytes,
158  * thus it may be over @max_bytes.  If it's over @max_bytes, it implies
159  * that only a part of ELD bytes have been fetched.
160  */
161 int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
162 			   bool *audio_enabled, char *buffer, int max_bytes)
163 {
164 	struct hdac_bus *bus = codec->bus;
165 	struct drm_audio_component *acomp = bus->audio_component;
166 	int port, pipe;
167 
168 	if (!acomp || !acomp->ops || !acomp->ops->get_eld)
169 		return -ENODEV;
170 
171 	port = nid;
172 	if (acomp->audio_ops && acomp->audio_ops->pin2port) {
173 		port = acomp->audio_ops->pin2port(codec, nid);
174 		if (port < 0)
175 			return -EINVAL;
176 	}
177 	pipe = dev_id;
178 	return acomp->ops->get_eld(acomp->dev, port, pipe, audio_enabled,
179 				   buffer, max_bytes);
180 }
181 EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld);
182 
183 static int hdac_component_master_bind(struct device *dev)
184 {
185 	struct drm_audio_component *acomp = hdac_get_acomp(dev);
186 	int ret;
187 
188 	if (WARN_ON(!acomp))
189 		return -EINVAL;
190 
191 	ret = component_bind_all(dev, acomp);
192 	if (ret < 0)
193 		return ret;
194 
195 	if (WARN_ON(!(acomp->dev && acomp->ops))) {
196 		ret = -EINVAL;
197 		goto out_unbind;
198 	}
199 
200 	/* pin the module to avoid dynamic unbinding, but only if given */
201 	if (!try_module_get(acomp->ops->owner)) {
202 		ret = -ENODEV;
203 		goto out_unbind;
204 	}
205 
206 	if (acomp->audio_ops && acomp->audio_ops->master_bind) {
207 		ret = acomp->audio_ops->master_bind(dev, acomp);
208 		if (ret < 0)
209 			goto module_put;
210 	}
211 
212 	complete_all(&acomp->master_bind_complete);
213 	return 0;
214 
215  module_put:
216 	module_put(acomp->ops->owner);
217 out_unbind:
218 	component_unbind_all(dev, acomp);
219 	complete_all(&acomp->master_bind_complete);
220 
221 	return ret;
222 }
223 
224 static void hdac_component_master_unbind(struct device *dev)
225 {
226 	struct drm_audio_component *acomp = hdac_get_acomp(dev);
227 
228 	if (acomp->audio_ops && acomp->audio_ops->master_unbind)
229 		acomp->audio_ops->master_unbind(dev, acomp);
230 	module_put(acomp->ops->owner);
231 	component_unbind_all(dev, acomp);
232 	WARN_ON(acomp->ops || acomp->dev);
233 }
234 
235 static const struct component_master_ops hdac_component_master_ops = {
236 	.bind = hdac_component_master_bind,
237 	.unbind = hdac_component_master_unbind,
238 };
239 
240 /**
241  * snd_hdac_acomp_register_notifier - Register audio component ops
242  * @bus: HDA core bus
243  * @aops: audio component ops
244  *
245  * This function is supposed to be used only by a HD-audio controller
246  * driver that needs the interaction with graphics driver.
247  *
248  * This function sets the given ops to be called by the graphics driver.
249  *
250  * Returns zero for success or a negative error code.
251  */
252 int snd_hdac_acomp_register_notifier(struct hdac_bus *bus,
253 				    const struct drm_audio_component_audio_ops *aops)
254 {
255 	if (!bus->audio_component)
256 		return -ENODEV;
257 
258 	bus->audio_component->audio_ops = aops;
259 	return 0;
260 }
261 EXPORT_SYMBOL_GPL(snd_hdac_acomp_register_notifier);
262 
263 /**
264  * snd_hdac_acomp_init - Initialize audio component
265  * @bus: HDA core bus
266  * @aops: audio component ops
267  * @match_master: match function for finding components
268  * @extra_size: Extra bytes to allocate
269  *
270  * This function is supposed to be used only by a HD-audio controller
271  * driver that needs the interaction with graphics driver.
272  *
273  * This function initializes and sets up the audio component to communicate
274  * with graphics driver.
275  *
276  * Unlike snd_hdac_i915_init(), this function doesn't synchronize with the
277  * binding with the DRM component.  Each caller needs to sync via master_bind
278  * audio_ops.
279  *
280  * Returns zero for success or a negative error code.
281  */
282 int snd_hdac_acomp_init(struct hdac_bus *bus,
283 			const struct drm_audio_component_audio_ops *aops,
284 			int (*match_master)(struct device *, int, void *),
285 			size_t extra_size)
286 {
287 	struct component_match *match = NULL;
288 	struct device *dev = bus->dev;
289 	struct drm_audio_component *acomp;
290 	int ret;
291 
292 	if (WARN_ON(hdac_get_acomp(dev)))
293 		return -EBUSY;
294 
295 	acomp = devres_alloc(hdac_acomp_release, sizeof(*acomp) + extra_size,
296 			     GFP_KERNEL);
297 	if (!acomp)
298 		return -ENOMEM;
299 	acomp->audio_ops = aops;
300 	init_completion(&acomp->master_bind_complete);
301 	bus->audio_component = acomp;
302 	devres_add(dev, acomp);
303 
304 	component_match_add_typed(dev, &match, match_master, bus);
305 	ret = component_master_add_with_match(dev, &hdac_component_master_ops,
306 					      match);
307 	if (ret < 0)
308 		goto out_err;
309 
310 	return 0;
311 
312 out_err:
313 	bus->audio_component = NULL;
314 	devres_destroy(dev, hdac_acomp_release, NULL, NULL);
315 	dev_info(dev, "failed to add audio component master (%d)\n", ret);
316 
317 	return ret;
318 }
319 EXPORT_SYMBOL_GPL(snd_hdac_acomp_init);
320 
321 /**
322  * snd_hdac_acomp_exit - Finalize audio component
323  * @bus: HDA core bus
324  *
325  * This function is supposed to be used only by a HD-audio controller
326  * driver that needs the interaction with graphics driver.
327  *
328  * This function releases the audio component that has been used.
329  *
330  * Returns zero for success or a negative error code.
331  */
332 int snd_hdac_acomp_exit(struct hdac_bus *bus)
333 {
334 	struct device *dev = bus->dev;
335 	struct drm_audio_component *acomp = bus->audio_component;
336 
337 	if (!acomp)
338 		return 0;
339 
340 	if (WARN_ON(bus->display_power_active) && acomp->ops)
341 		acomp->ops->put_power(acomp->dev, bus->display_power_active);
342 
343 	bus->display_power_active = 0;
344 	bus->display_power_status = 0;
345 
346 	component_master_del(dev, &hdac_component_master_ops);
347 
348 	bus->audio_component = NULL;
349 	devres_destroy(dev, hdac_acomp_release, NULL, NULL);
350 
351 	return 0;
352 }
353 EXPORT_SYMBOL_GPL(snd_hdac_acomp_exit);
354