summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2018-07-11 10:23:16 -0400
committerTakashi Iwai <tiwai@suse.de>2018-07-17 16:25:48 -0400
commita57942bfdd61b46df94021c9c33b8faaae5b65e1 (patch)
treeb07a8f8c109a0101230fce793dc186d10e0d172e
parent82887c0beb1ee6b33eed8318d8e8d41c5b3eddae (diff)
ALSA: hda: Make audio component support more generic
This is the final step for more generic support of DRM audio component. The generic audio component code is now moved to its own file, and the symbols are renamed from snd_hac_i915_* to snd_hdac_acomp_*, respectively. The generic code is enabled via the new kconfig, CONFIG_SND_HDA_COMPONENT, while CONFIG_SND_HDA_I915 is kept as the super-class. Along with the split, three new callbacks are added to audio_ops: pin2port is for providing the conversion between the pin number and the widget id, and master_bind/master_unbin are called at binding / unbinding the master component, respectively. All these are optional, but used in i915 implementation and also other later implementations. A note about the new snd_hdac_acomp_init() function: there is a slight difference between this and the old snd_hdac_i915_init(). The latter (still) synchronizes with the master component binding, i.e. it assures that the relevant DRM component gets bound when it returns, or gives a negative error. Meanwhile the new function doesn't synchronize but just leaves as is. It's the responsibility by the caller's side to synchronize, or the caller may accept the asynchronous binding on the fly. v1->v2: Fix missing NULL check in master_bind/unbind Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--drivers/gpu/drm/i915/Kconfig1
-rw-r--r--include/drm/drm_audio_component.h23
-rw-r--r--include/sound/hda_component.h61
-rw-r--r--include/sound/hda_i915.h39
-rw-r--r--sound/hda/Kconfig7
-rw-r--r--sound/hda/Makefile1
-rw-r--r--sound/hda/hdac_component.c335
-rw-r--r--sound/hda/hdac_i915.c343
-rw-r--r--sound/pci/hda/patch_hdmi.c50
-rw-r--r--sound/soc/codecs/hdac_hdmi.c8
10 files changed, 486 insertions, 382 deletions
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index dfd95889f4b7..5c607f2c707b 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -23,6 +23,7 @@ config DRM_I915
23 select SYNC_FILE 23 select SYNC_FILE
24 select IOSF_MBI 24 select IOSF_MBI
25 select CRC32 25 select CRC32
26 select SND_HDA_I915 if SND_HDA_CORE
26 help 27 help
27 Choose this option if you have a system that has "Intel Graphics 28 Choose this option if you have a system that has "Intel Graphics
28 Media Accelerator" or "HD Graphics" integrated graphics, 29 Media Accelerator" or "HD Graphics" integrated graphics,
diff --git a/include/drm/drm_audio_component.h b/include/drm/drm_audio_component.h
index e85689f212c2..4923b00328c1 100644
--- a/include/drm/drm_audio_component.h
+++ b/include/drm/drm_audio_component.h
@@ -4,6 +4,8 @@
4#ifndef _DRM_AUDIO_COMPONENT_H_ 4#ifndef _DRM_AUDIO_COMPONENT_H_
5#define _DRM_AUDIO_COMPONENT_H_ 5#define _DRM_AUDIO_COMPONENT_H_
6 6
7struct drm_audio_component;
8
7/** 9/**
8 * struct drm_audio_component_ops - Ops implemented by DRM driver, called by hda driver 10 * struct drm_audio_component_ops - Ops implemented by DRM driver, called by hda driver
9 */ 11 */
@@ -72,6 +74,27 @@ struct drm_audio_component_audio_ops {
72 * mode). 74 * mode).
73 */ 75 */
74 void (*pin_eld_notify)(void *audio_ptr, int port, int pipe); 76 void (*pin_eld_notify)(void *audio_ptr, int port, int pipe);
77 /**
78 * @pin2port: Check and convert from pin node to port number
79 *
80 * Called by HDA driver to check and convert from the pin widget node
81 * number to a port number in the graphics side.
82 */
83 int (*pin2port)(void *audio_ptr, int pin);
84 /**
85 * @master_bind: (Optional) component master bind callback
86 *
87 * Called at binding master component, for HDA codec-specific
88 * handling of dynamic binding.
89 */
90 int (*master_bind)(struct device *dev, struct drm_audio_component *);
91 /**
92 * @master_unbind: (Optional) component master unbind callback
93 *
94 * Called at unbinding master component, for HDA codec-specific
95 * handling of dynamic unbinding.
96 */
97 void (*master_unbind)(struct device *dev, struct drm_audio_component *);
75}; 98};
76 99
77/** 100/**
diff --git a/include/sound/hda_component.h b/include/sound/hda_component.h
new file mode 100644
index 000000000000..78626cde7081
--- /dev/null
+++ b/include/sound/hda_component.h
@@ -0,0 +1,61 @@
1// SPDX-License-Identifier: GPL-2.0
2// HD-Audio helpers to sync with DRM driver
3
4#ifndef __SOUND_HDA_COMPONENT_H
5#define __SOUND_HDA_COMPONENT_H
6
7#include <drm/drm_audio_component.h>
8
9#ifdef CONFIG_SND_HDA_COMPONENT
10int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable);
11int snd_hdac_display_power(struct hdac_bus *bus, bool enable);
12int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid,
13 int dev_id, int rate);
14int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
15 bool *audio_enabled, char *buffer, int max_bytes);
16int snd_hdac_acomp_init(struct hdac_bus *bus,
17 const struct drm_audio_component_audio_ops *aops,
18 int (*match_master)(struct device *, void *),
19 size_t extra_size);
20int snd_hdac_acomp_exit(struct hdac_bus *bus);
21int snd_hdac_acomp_register_notifier(struct hdac_bus *bus,
22 const struct drm_audio_component_audio_ops *ops);
23#else
24static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable)
25{
26 return 0;
27}
28static inline int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
29{
30 return 0;
31}
32static inline int snd_hdac_sync_audio_rate(struct hdac_device *codec,
33 hda_nid_t nid, int dev_id, int rate)
34{
35 return 0;
36}
37static inline int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid,
38 int dev_id, bool *audio_enabled,
39 char *buffer, int max_bytes)
40{
41 return -ENODEV;
42}
43static inline int snd_hdac_acomp_init(struct hdac_bus *bus,
44 const struct drm_audio_component_audio_ops *aops,
45 int (*match_master)(struct device *, void *),
46 size_t extra_size)
47{
48 return -ENODEV;
49}
50static inline int snd_hdac_acomp_exit(struct hdac_bus *bus)
51{
52 return 0;
53}
54static inline int snd_hdac_acomp_register_notifier(struct hdac_bus *bus,
55 const struct drm_audio_component_audio_ops *ops)
56{
57 return -ENODEV;
58}
59#endif
60
61#endif /* __SOUND_HDA_COMPONENT_H */
diff --git a/include/sound/hda_i915.h b/include/sound/hda_i915.h
index 648263791559..6b79614a893b 100644
--- a/include/sound/hda_i915.h
+++ b/include/sound/hda_i915.h
@@ -5,56 +5,23 @@
5#ifndef __SOUND_HDA_I915_H 5#ifndef __SOUND_HDA_I915_H
6#define __SOUND_HDA_I915_H 6#define __SOUND_HDA_I915_H
7 7
8#include <drm/drm_audio_component.h> 8#include "hda_component.h"
9 9
10#ifdef CONFIG_SND_HDA_I915 10#ifdef CONFIG_SND_HDA_I915
11int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable);
12int snd_hdac_display_power(struct hdac_bus *bus, bool enable);
13void snd_hdac_i915_set_bclk(struct hdac_bus *bus); 11void snd_hdac_i915_set_bclk(struct hdac_bus *bus);
14int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid,
15 int dev_id, int rate);
16int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
17 bool *audio_enabled, char *buffer, int max_bytes);
18int snd_hdac_i915_init(struct hdac_bus *bus); 12int snd_hdac_i915_init(struct hdac_bus *bus);
19int snd_hdac_i915_exit(struct hdac_bus *bus);
20int snd_hdac_i915_register_notifier(struct hdac_bus *bus,
21 const struct drm_audio_component_audio_ops *ops);
22#else 13#else
23static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable)
24{
25 return 0;
26}
27static inline int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
28{
29 return 0;
30}
31static inline void snd_hdac_i915_set_bclk(struct hdac_bus *bus) 14static inline void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
32{ 15{
33} 16}
34static inline int snd_hdac_sync_audio_rate(struct hdac_device *codec,
35 hda_nid_t nid, int dev_id, int rate)
36{
37 return 0;
38}
39static inline int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid,
40 int dev_id, bool *audio_enabled,
41 char *buffer, int max_bytes)
42{
43 return -ENODEV;
44}
45static inline int snd_hdac_i915_init(struct hdac_bus *bus) 17static inline int snd_hdac_i915_init(struct hdac_bus *bus)
46{ 18{
47 return -ENODEV; 19 return -ENODEV;
48} 20}
21#endif
49static inline int snd_hdac_i915_exit(struct hdac_bus *bus) 22static inline int snd_hdac_i915_exit(struct hdac_bus *bus)
50{ 23{
51 return 0; 24 return snd_hdac_acomp_exit(bus);
52} 25}
53static inline int snd_hdac_i915_register_notifier(struct hdac_bus *bus,
54 const struct drm_audio_component_audio_ops *ops)
55{
56 return -ENODEV;
57}
58#endif
59 26
60#endif /* __SOUND_HDA_I915_H */ 27#endif /* __SOUND_HDA_I915_H */
diff --git a/sound/hda/Kconfig b/sound/hda/Kconfig
index 3129546398d0..2d90e11b3eaa 100644
--- a/sound/hda/Kconfig
+++ b/sound/hda/Kconfig
@@ -5,11 +5,12 @@ config SND_HDA_CORE
5config SND_HDA_DSP_LOADER 5config SND_HDA_DSP_LOADER
6 bool 6 bool
7 7
8config SND_HDA_COMPONENT
9 bool
10
8config SND_HDA_I915 11config SND_HDA_I915
9 bool 12 bool
10 default y 13 select SND_HDA_COMPONENT
11 depends on DRM_I915
12 depends on SND_HDA_CORE
13 14
14config SND_HDA_EXT_CORE 15config SND_HDA_EXT_CORE
15 tristate 16 tristate
diff --git a/sound/hda/Makefile b/sound/hda/Makefile
index e4e726f2ce98..2160202e2dc1 100644
--- a/sound/hda/Makefile
+++ b/sound/hda/Makefile
@@ -6,6 +6,7 @@ snd-hda-core-objs += trace.o
6CFLAGS_trace.o := -I$(src) 6CFLAGS_trace.o := -I$(src)
7 7
8# for sync with i915 gfx driver 8# for sync with i915 gfx driver
9snd-hda-core-$(CONFIG_SND_HDA_COMPONENT) += hdac_component.o
9snd-hda-core-$(CONFIG_SND_HDA_I915) += hdac_i915.o 10snd-hda-core-$(CONFIG_SND_HDA_I915) += hdac_i915.o
10 11
11obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o 12obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o
diff --git a/sound/hda/hdac_component.c b/sound/hda/hdac_component.c
new file mode 100644
index 000000000000..6e46a9c73aed
--- /dev/null
+++ b/sound/hda/hdac_component.c
@@ -0,0 +1,335 @@
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 <sound/core.h>
9#include <sound/hdaudio.h>
10#include <sound/hda_component.h>
11#include <sound/hda_register.h>
12
13static void hdac_acomp_release(struct device *dev, void *res)
14{
15}
16
17static struct drm_audio_component *hdac_get_acomp(struct device *dev)
18{
19 return devres_find(dev, hdac_acomp_release, NULL, NULL);
20}
21
22/**
23 * snd_hdac_set_codec_wakeup - Enable / disable HDMI/DP codec wakeup
24 * @bus: HDA core bus
25 * @enable: enable or disable the wakeup
26 *
27 * This function is supposed to be used only by a HD-audio controller
28 * driver that needs the interaction with graphics driver.
29 *
30 * This function should be called during the chip reset, also called at
31 * resume for updating STATESTS register read.
32 *
33 * Returns zero for success or a negative error code.
34 */
35int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable)
36{
37 struct drm_audio_component *acomp = bus->audio_component;
38
39 if (!acomp || !acomp->ops)
40 return -ENODEV;
41
42 if (!acomp->ops->codec_wake_override)
43 return 0;
44
45 dev_dbg(bus->dev, "%s codec wakeup\n",
46 enable ? "enable" : "disable");
47
48 acomp->ops->codec_wake_override(acomp->dev, enable);
49
50 return 0;
51}
52EXPORT_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 * @enable: power up or down
58 *
59 * This function is supposed to be used only by a HD-audio controller
60 * driver that needs the interaction with graphics driver.
61 *
62 * This function manages a refcount and calls the get_power() and
63 * put_power() ops accordingly, toggling the codec wakeup, too.
64 *
65 * Returns zero for success or a negative error code.
66 */
67int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
68{
69 struct drm_audio_component *acomp = bus->audio_component;
70
71 if (!acomp || !acomp->ops)
72 return -ENODEV;
73
74 dev_dbg(bus->dev, "display power %s\n",
75 enable ? "enable" : "disable");
76
77 if (enable) {
78 if (!bus->drm_power_refcount++) {
79 if (acomp->ops->get_power)
80 acomp->ops->get_power(acomp->dev);
81 snd_hdac_set_codec_wakeup(bus, true);
82 snd_hdac_set_codec_wakeup(bus, false);
83 }
84 } else {
85 WARN_ON(!bus->drm_power_refcount);
86 if (!--bus->drm_power_refcount)
87 if (acomp->ops->put_power)
88 acomp->ops->put_power(acomp->dev);
89 }
90
91 return 0;
92}
93EXPORT_SYMBOL_GPL(snd_hdac_display_power);
94
95/**
96 * snd_hdac_sync_audio_rate - Set N/CTS based on the sample rate
97 * @codec: HDA codec
98 * @nid: the pin widget NID
99 * @dev_id: device identifier
100 * @rate: the sample rate to set
101 *
102 * This function is supposed to be used only by a HD-audio controller
103 * driver that needs the interaction with graphics driver.
104 *
105 * This function sets N/CTS value based on the given sample rate.
106 * Returns zero for success, or a negative error code.
107 */
108int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid,
109 int dev_id, int rate)
110{
111 struct hdac_bus *bus = codec->bus;
112 struct drm_audio_component *acomp = bus->audio_component;
113 int port, pipe;
114
115 if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate)
116 return -ENODEV;
117 port = nid;
118 if (acomp->audio_ops && acomp->audio_ops->pin2port) {
119 port = acomp->audio_ops->pin2port(codec, nid);
120 if (port < 0)
121 return -EINVAL;
122 }
123 pipe = dev_id;
124 return acomp->ops->sync_audio_rate(acomp->dev, port, pipe, rate);
125}
126EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate);
127
128/**
129 * snd_hdac_acomp_get_eld - Get the audio state and ELD via component
130 * @codec: HDA codec
131 * @nid: the pin widget NID
132 * @dev_id: device identifier
133 * @audio_enabled: the pointer to store the current audio state
134 * @buffer: the buffer pointer to store ELD bytes
135 * @max_bytes: the max bytes to be stored on @buffer
136 *
137 * This function is supposed to be used only by a HD-audio controller
138 * driver that needs the interaction with graphics driver.
139 *
140 * This function queries the current state of the audio on the given
141 * digital port and fetches the ELD bytes onto the given buffer.
142 * It returns the number of bytes for the total ELD data, zero for
143 * invalid ELD, or a negative error code.
144 *
145 * The return size is the total bytes required for the whole ELD bytes,
146 * thus it may be over @max_bytes. If it's over @max_bytes, it implies
147 * that only a part of ELD bytes have been fetched.
148 */
149int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
150 bool *audio_enabled, char *buffer, int max_bytes)
151{
152 struct hdac_bus *bus = codec->bus;
153 struct drm_audio_component *acomp = bus->audio_component;
154 int port, pipe;
155
156 if (!acomp || !acomp->ops || !acomp->ops->get_eld)
157 return -ENODEV;
158
159 port = nid;
160 if (acomp->audio_ops && acomp->audio_ops->pin2port) {
161 port = acomp->audio_ops->pin2port(codec, nid);
162 if (port < 0)
163 return -EINVAL;
164 }
165 pipe = dev_id;
166 return acomp->ops->get_eld(acomp->dev, port, pipe, audio_enabled,
167 buffer, max_bytes);
168}
169EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld);
170
171static int hdac_component_master_bind(struct device *dev)
172{
173 struct drm_audio_component *acomp = hdac_get_acomp(dev);
174 int ret;
175
176 if (WARN_ON(!acomp))
177 return -EINVAL;
178
179 ret = component_bind_all(dev, acomp);
180 if (ret < 0)
181 return ret;
182
183 if (WARN_ON(!(acomp->dev && acomp->ops))) {
184 ret = -EINVAL;
185 goto out_unbind;
186 }
187
188 /* pin the module to avoid dynamic unbinding, but only if given */
189 if (!try_module_get(acomp->ops->owner)) {
190 ret = -ENODEV;
191 goto out_unbind;
192 }
193
194 if (acomp->audio_ops && acomp->audio_ops->master_bind) {
195 ret = acomp->audio_ops->master_bind(dev, acomp);
196 if (ret < 0)
197 goto module_put;
198 }
199
200 return 0;
201
202 module_put:
203 module_put(acomp->ops->owner);
204out_unbind:
205 component_unbind_all(dev, acomp);
206
207 return ret;
208}
209
210static void hdac_component_master_unbind(struct device *dev)
211{
212 struct drm_audio_component *acomp = hdac_get_acomp(dev);
213
214 if (acomp->audio_ops && acomp->audio_ops->master_unbind)
215 acomp->audio_ops->master_unbind(dev, acomp);
216 module_put(acomp->ops->owner);
217 component_unbind_all(dev, acomp);
218 WARN_ON(acomp->ops || acomp->dev);
219}
220
221static const struct component_master_ops hdac_component_master_ops = {
222 .bind = hdac_component_master_bind,
223 .unbind = hdac_component_master_unbind,
224};
225
226/**
227 * snd_hdac_acomp_register_notifier - Register audio component ops
228 * @bus: HDA core bus
229 * @aops: audio component ops
230 *
231 * This function is supposed to be used only by a HD-audio controller
232 * driver that needs the interaction with graphics driver.
233 *
234 * This function sets the given ops to be called by the graphics driver.
235 *
236 * Returns zero for success or a negative error code.
237 */
238int snd_hdac_acomp_register_notifier(struct hdac_bus *bus,
239 const struct drm_audio_component_audio_ops *aops)
240{
241 if (!bus->audio_component)
242 return -ENODEV;
243
244 bus->audio_component->audio_ops = aops;
245 return 0;
246}
247EXPORT_SYMBOL_GPL(snd_hdac_acomp_register_notifier);
248
249/**
250 * snd_hdac_acomp_init - Initialize audio component
251 * @bus: HDA core bus
252 * @match_master: match function for finding components
253 * @extra_size: Extra bytes to allocate
254 *
255 * This function is supposed to be used only by a HD-audio controller
256 * driver that needs the interaction with graphics driver.
257 *
258 * This function initializes and sets up the audio component to communicate
259 * with graphics driver.
260 *
261 * Unlike snd_hdac_i915_init(), this function doesn't synchronize with the
262 * binding with the DRM component. Each caller needs to sync via master_bind
263 * audio_ops.
264 *
265 * Returns zero for success or a negative error code.
266 */
267int snd_hdac_acomp_init(struct hdac_bus *bus,
268 const struct drm_audio_component_audio_ops *aops,
269 int (*match_master)(struct device *, void *),
270 size_t extra_size)
271{
272 struct component_match *match = NULL;
273 struct device *dev = bus->dev;
274 struct drm_audio_component *acomp;
275 int ret;
276
277 if (WARN_ON(hdac_get_acomp(dev)))
278 return -EBUSY;
279
280 acomp = devres_alloc(hdac_acomp_release, sizeof(*acomp) + extra_size,
281 GFP_KERNEL);
282 if (!acomp)
283 return -ENOMEM;
284 acomp->audio_ops = aops;
285 bus->audio_component = acomp;
286 devres_add(dev, acomp);
287
288 component_match_add(dev, &match, match_master, bus);
289 ret = component_master_add_with_match(dev, &hdac_component_master_ops,
290 match);
291 if (ret < 0)
292 goto out_err;
293
294 return 0;
295
296out_err:
297 bus->audio_component = NULL;
298 devres_destroy(dev, hdac_acomp_release, NULL, NULL);
299 dev_info(dev, "failed to add audio component master (%d)\n", ret);
300
301 return ret;
302}
303EXPORT_SYMBOL_GPL(snd_hdac_acomp_init);
304
305/**
306 * snd_hdac_acomp_exit - Finalize audio component
307 * @bus: HDA core bus
308 *
309 * This function is supposed to be used only by a HD-audio controller
310 * driver that needs the interaction with graphics driver.
311 *
312 * This function releases the audio component that has been used.
313 *
314 * Returns zero for success or a negative error code.
315 */
316int snd_hdac_acomp_exit(struct hdac_bus *bus)
317{
318 struct device *dev = bus->dev;
319 struct drm_audio_component *acomp = bus->audio_component;
320
321 if (!acomp)
322 return 0;
323
324 WARN_ON(bus->drm_power_refcount);
325 if (bus->drm_power_refcount > 0 && acomp->ops)
326 acomp->ops->put_power(acomp->dev);
327
328 component_master_del(dev, &hdac_component_master_ops);
329
330 bus->audio_component = NULL;
331 devres_destroy(dev, hdac_acomp_release, NULL, NULL);
332
333 return 0;
334}
335EXPORT_SYMBOL_GPL(snd_hdac_acomp_exit);
diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c
index 861b77bbc7df..8f2aa8bc1185 100644
--- a/sound/hda/hdac_i915.c
+++ b/sound/hda/hdac_i915.c
@@ -15,96 +15,11 @@
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/pci.h> 17#include <linux/pci.h>
18#include <linux/component.h>
19#include <drm/drm_audio_component.h>
20#include <sound/core.h> 18#include <sound/core.h>
21#include <sound/hdaudio.h> 19#include <sound/hdaudio.h>
22#include <sound/hda_i915.h> 20#include <sound/hda_i915.h>
23#include <sound/hda_register.h> 21#include <sound/hda_register.h>
24 22
25static void hdac_acomp_release(struct device *dev, void *res)
26{
27}
28
29static struct drm_audio_component *hdac_get_acomp(struct device *dev)
30{
31 return devres_find(dev, hdac_acomp_release, NULL, NULL);
32}
33
34/**
35 * snd_hdac_set_codec_wakeup - Enable / disable HDMI/DP codec wakeup
36 * @bus: HDA core bus
37 * @enable: enable or disable the wakeup
38 *
39 * This function is supposed to be used only by a HD-audio controller
40 * driver that needs the interaction with i915 graphics.
41 *
42 * This function should be called during the chip reset, also called at
43 * resume for updating STATESTS register read.
44 *
45 * Returns zero for success or a negative error code.
46 */
47int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable)
48{
49 struct drm_audio_component *acomp = bus->audio_component;
50
51 if (!acomp || !acomp->ops)
52 return -ENODEV;
53
54 if (!acomp->ops->codec_wake_override) {
55 dev_warn(bus->dev,
56 "Invalid codec wake callback\n");
57 return 0;
58 }
59
60 dev_dbg(bus->dev, "%s codec wakeup\n",
61 enable ? "enable" : "disable");
62
63 acomp->ops->codec_wake_override(acomp->dev, enable);
64
65 return 0;
66}
67EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup);
68
69/**
70 * snd_hdac_display_power - Power up / down the power refcount
71 * @bus: HDA core bus
72 * @enable: power up or down
73 *
74 * This function is supposed to be used only by a HD-audio controller
75 * driver that needs the interaction with i915 graphics.
76 *
77 * This function manages a refcount and calls the i915 get_power() and
78 * put_power() ops accordingly, toggling the codec wakeup, too.
79 *
80 * Returns zero for success or a negative error code.
81 */
82int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
83{
84 struct drm_audio_component *acomp = bus->audio_component;
85
86 if (!acomp || !acomp->ops)
87 return -ENODEV;
88
89 dev_dbg(bus->dev, "display power %s\n",
90 enable ? "enable" : "disable");
91
92 if (enable) {
93 if (!bus->drm_power_refcount++) {
94 acomp->ops->get_power(acomp->dev);
95 snd_hdac_set_codec_wakeup(bus, true);
96 snd_hdac_set_codec_wakeup(bus, false);
97 }
98 } else {
99 WARN_ON(!bus->drm_power_refcount);
100 if (!--bus->drm_power_refcount)
101 acomp->ops->put_power(acomp->dev);
102 }
103
104 return 0;
105}
106EXPORT_SYMBOL_GPL(snd_hdac_display_power);
107
108#define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \ 23#define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \
109 ((pci)->device == 0x0c0c) || \ 24 ((pci)->device == 0x0c0c) || \
110 ((pci)->device == 0x0d0c) || \ 25 ((pci)->device == 0x0d0c) || \
@@ -165,183 +80,11 @@ void snd_hdac_i915_set_bclk(struct hdac_bus *bus)
165} 80}
166EXPORT_SYMBOL_GPL(snd_hdac_i915_set_bclk); 81EXPORT_SYMBOL_GPL(snd_hdac_i915_set_bclk);
167 82
168/* There is a fixed mapping between audio pin node and display port. 83static int i915_component_master_match(struct device *dev, void *data)
169 * on SNB, IVY, HSW, BSW, SKL, BXT, KBL:
170 * Pin Widget 5 - PORT B (port = 1 in i915 driver)
171 * Pin Widget 6 - PORT C (port = 2 in i915 driver)
172 * Pin Widget 7 - PORT D (port = 3 in i915 driver)
173 *
174 * on VLV, ILK:
175 * Pin Widget 4 - PORT B (port = 1 in i915 driver)
176 * Pin Widget 5 - PORT C (port = 2 in i915 driver)
177 * Pin Widget 6 - PORT D (port = 3 in i915 driver)
178 */
179static int pin2port(struct hdac_device *codec, hda_nid_t pin_nid)
180{
181 int base_nid;
182
183 switch (codec->vendor_id) {
184 case 0x80860054: /* ILK */
185 case 0x80862804: /* ILK */
186 case 0x80862882: /* VLV */
187 base_nid = 3;
188 break;
189 default:
190 base_nid = 4;
191 break;
192 }
193
194 if (WARN_ON(pin_nid <= base_nid || pin_nid > base_nid + 3))
195 return -1;
196 return pin_nid - base_nid;
197}
198
199/**
200 * snd_hdac_sync_audio_rate - Set N/CTS based on the sample rate
201 * @codec: HDA codec
202 * @nid: the pin widget NID
203 * @dev_id: device identifier
204 * @rate: the sample rate to set
205 *
206 * This function is supposed to be used only by a HD-audio controller
207 * driver that needs the interaction with i915 graphics.
208 *
209 * This function sets N/CTS value based on the given sample rate.
210 * Returns zero for success, or a negative error code.
211 */
212int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid,
213 int dev_id, int rate)
214{ 84{
215 struct hdac_bus *bus = codec->bus;
216 struct drm_audio_component *acomp = bus->audio_component;
217 int port, pipe;
218
219 if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate)
220 return -ENODEV;
221 port = pin2port(codec, nid);
222 if (port < 0)
223 return -EINVAL;
224 pipe = dev_id;
225 return acomp->ops->sync_audio_rate(acomp->dev, port, pipe, rate);
226}
227EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate);
228
229/**
230 * snd_hdac_acomp_get_eld - Get the audio state and ELD via component
231 * @codec: HDA codec
232 * @nid: the pin widget NID
233 * @dev_id: device identifier
234 * @audio_enabled: the pointer to store the current audio state
235 * @buffer: the buffer pointer to store ELD bytes
236 * @max_bytes: the max bytes to be stored on @buffer
237 *
238 * This function is supposed to be used only by a HD-audio controller
239 * driver that needs the interaction with i915 graphics.
240 *
241 * This function queries the current state of the audio on the given
242 * digital port and fetches the ELD bytes onto the given buffer.
243 * It returns the number of bytes for the total ELD data, zero for
244 * invalid ELD, or a negative error code.
245 *
246 * The return size is the total bytes required for the whole ELD bytes,
247 * thus it may be over @max_bytes. If it's over @max_bytes, it implies
248 * that only a part of ELD bytes have been fetched.
249 */
250int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
251 bool *audio_enabled, char *buffer, int max_bytes)
252{
253 struct hdac_bus *bus = codec->bus;
254 struct drm_audio_component *acomp = bus->audio_component;
255 int port, pipe;
256
257 if (!acomp || !acomp->ops || !acomp->ops->get_eld)
258 return -ENODEV;
259
260 port = pin2port(codec, nid);
261 if (port < 0)
262 return -EINVAL;
263
264 pipe = dev_id;
265 return acomp->ops->get_eld(acomp->dev, port, pipe, audio_enabled,
266 buffer, max_bytes);
267}
268EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld);
269
270static int hdac_component_master_bind(struct device *dev)
271{
272 struct drm_audio_component *acomp = hdac_get_acomp(dev);
273 int ret;
274
275 ret = component_bind_all(dev, acomp);
276 if (ret < 0)
277 return ret;
278
279 if (WARN_ON(!(acomp->dev && acomp->ops && acomp->ops->get_power &&
280 acomp->ops->put_power && acomp->ops->get_cdclk_freq))) {
281 ret = -EINVAL;
282 goto out_unbind;
283 }
284
285 /*
286 * Atm, we don't support dynamic unbinding initiated by the child
287 * component, so pin its containing module until we unbind.
288 */
289 if (!try_module_get(acomp->ops->owner)) {
290 ret = -ENODEV;
291 goto out_unbind;
292 }
293
294 return 0;
295
296out_unbind:
297 component_unbind_all(dev, acomp);
298
299 return ret;
300}
301
302static void hdac_component_master_unbind(struct device *dev)
303{
304 struct drm_audio_component *acomp = hdac_get_acomp(dev);
305
306 module_put(acomp->ops->owner);
307 component_unbind_all(dev, acomp);
308 WARN_ON(acomp->ops || acomp->dev);
309}
310
311static const struct component_master_ops hdac_component_master_ops = {
312 .bind = hdac_component_master_bind,
313 .unbind = hdac_component_master_unbind,
314};
315
316static int hdac_component_master_match(struct device *dev, void *data)
317{
318 /* i915 is the only supported component */
319 return !strcmp(dev->driver->name, "i915"); 85 return !strcmp(dev->driver->name, "i915");
320} 86}
321 87
322/**
323 * snd_hdac_i915_register_notifier - Register i915 audio component ops
324 * @bus: HDA core bus
325 * @aops: i915 audio component ops
326 *
327 * This function is supposed to be used only by a HD-audio controller
328 * driver that needs the interaction with i915 graphics.
329 *
330 * This function sets the given ops to be called by the i915 graphics driver.
331 *
332 * Returns zero for success or a negative error code.
333 */
334int snd_hdac_i915_register_notifier(struct hdac_bus *bus,
335 const struct drm_audio_component_audio_ops *aops)
336{
337 if (!bus->audio_component)
338 return -ENODEV;
339
340 bus->audio_component->audio_ops = aops;
341 return 0;
342}
343EXPORT_SYMBOL_GPL(snd_hdac_i915_register_notifier);
344
345/* check whether intel graphics is present */ 88/* check whether intel graphics is present */
346static bool i915_gfx_present(void) 89static bool i915_gfx_present(void)
347{ 90{
@@ -368,84 +111,26 @@ static bool i915_gfx_present(void)
368 */ 111 */
369int snd_hdac_i915_init(struct hdac_bus *bus) 112int snd_hdac_i915_init(struct hdac_bus *bus)
370{ 113{
371 struct component_match *match = NULL;
372 struct device *dev = bus->dev;
373 struct i915_audio_component *i915_acomp;
374 struct drm_audio_component *acomp; 114 struct drm_audio_component *acomp;
375 int ret; 115 int err;
376
377 if (WARN_ON(hdac_get_acomp(dev)))
378 return -EBUSY;
379 116
380 if (!i915_gfx_present()) 117 if (!i915_gfx_present())
381 return -ENODEV; 118 return -ENODEV;
382 119
383 i915_acomp = devres_alloc(hdac_acomp_release, sizeof(*i915_acomp), 120 err = snd_hdac_acomp_init(bus, NULL,
384 GFP_KERNEL); 121 i915_component_master_match,
385 if (!i915_acomp) 122 sizeof(struct i915_audio_component) - sizeof(*acomp));
386 return -ENOMEM; 123 if (err < 0)
387 acomp = &i915_acomp->base; 124 return err;
388 bus->audio_component = acomp; 125 acomp = bus->audio_component;
389 devres_add(dev, acomp); 126 if (!acomp)
390 127 return -ENODEV;
391 component_match_add(dev, &match, hdac_component_master_match, bus); 128 if (!acomp->ops)
392 ret = component_master_add_with_match(dev, &hdac_component_master_ops, 129 request_module("i915");
393 match);
394 if (ret < 0)
395 goto out_err;
396
397 /*
398 * Atm, we don't support deferring the component binding, so make sure
399 * i915 is loaded and that the binding successfully completes.
400 */
401 request_module("i915");
402
403 if (!acomp->ops) { 130 if (!acomp->ops) {
404 ret = -ENODEV; 131 snd_hdac_acomp_exit(bus);
405 goto out_master_del; 132 return -ENODEV;
406 } 133 }
407 dev_dbg(dev, "bound to i915 component master\n");
408
409 return 0; 134 return 0;
410out_master_del:
411 component_master_del(dev, &hdac_component_master_ops);
412out_err:
413 bus->audio_component = NULL;
414 devres_destroy(dev, hdac_acomp_release, NULL, NULL);
415 dev_info(dev, "failed to add i915 component master (%d)\n", ret);
416
417 return ret;
418} 135}
419EXPORT_SYMBOL_GPL(snd_hdac_i915_init); 136EXPORT_SYMBOL_GPL(snd_hdac_i915_init);
420
421/**
422 * snd_hdac_i915_exit - Finalize i915 audio component
423 * @bus: HDA core bus
424 *
425 * This function is supposed to be used only by a HD-audio controller
426 * driver that needs the interaction with i915 graphics.
427 *
428 * This function releases the i915 audio component that has been used.
429 *
430 * Returns zero for success or a negative error code.
431 */
432int snd_hdac_i915_exit(struct hdac_bus *bus)
433{
434 struct device *dev = bus->dev;
435 struct drm_audio_component *acomp = bus->audio_component;
436
437 if (!acomp)
438 return 0;
439
440 WARN_ON(bus->drm_power_refcount);
441 if (bus->drm_power_refcount > 0 && acomp->ops)
442 acomp->ops->put_power(acomp->dev);
443
444 component_master_del(dev, &hdac_component_master_ops);
445
446 bus->audio_component = NULL;
447 devres_destroy(dev, hdac_acomp_release, NULL, NULL);
448
449 return 0;
450}
451EXPORT_SYMBOL_GPL(snd_hdac_i915_exit);
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index bf174a013f2d..1de5491fb9bf 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -183,7 +183,7 @@ struct hdmi_spec {
183 hda_nid_t vendor_nid; 183 hda_nid_t vendor_nid;
184}; 184};
185 185
186#ifdef CONFIG_SND_HDA_I915 186#ifdef CONFIG_SND_HDA_COMPONENT
187static inline bool codec_has_acomp(struct hda_codec *codec) 187static inline bool codec_has_acomp(struct hda_codec *codec)
188{ 188{
189 struct hdmi_spec *spec = codec->spec; 189 struct hdmi_spec *spec = codec->spec;
@@ -2288,7 +2288,7 @@ static void generic_hdmi_free(struct hda_codec *codec)
2288 int pin_idx, pcm_idx; 2288 int pin_idx, pcm_idx;
2289 2289
2290 if (codec_has_acomp(codec)) 2290 if (codec_has_acomp(codec))
2291 snd_hdac_i915_register_notifier(&codec->bus->core, NULL); 2291 snd_hdac_acomp_register_notifier(&codec->bus->core, NULL);
2292 2292
2293 for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { 2293 for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
2294 struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); 2294 struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
@@ -2471,6 +2471,38 @@ static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2471 snd_hda_codec_set_power_to_all(codec, fg, power_state); 2471 snd_hda_codec_set_power_to_all(codec, fg, power_state);
2472} 2472}
2473 2473
2474/* There is a fixed mapping between audio pin node and display port.
2475 * on SNB, IVY, HSW, BSW, SKL, BXT, KBL:
2476 * Pin Widget 5 - PORT B (port = 1 in i915 driver)
2477 * Pin Widget 6 - PORT C (port = 2 in i915 driver)
2478 * Pin Widget 7 - PORT D (port = 3 in i915 driver)
2479 *
2480 * on VLV, ILK:
2481 * Pin Widget 4 - PORT B (port = 1 in i915 driver)
2482 * Pin Widget 5 - PORT C (port = 2 in i915 driver)
2483 * Pin Widget 6 - PORT D (port = 3 in i915 driver)
2484 */
2485static int intel_base_nid(struct hda_codec *codec)
2486{
2487 switch (codec->core.vendor_id) {
2488 case 0x80860054: /* ILK */
2489 case 0x80862804: /* ILK */
2490 case 0x80862882: /* VLV */
2491 return 4;
2492 default:
2493 return 5;
2494 }
2495}
2496
2497static int intel_pin2port(void *audio_ptr, int pin_nid)
2498{
2499 int base_nid = intel_base_nid(audio_ptr);
2500
2501 if (WARN_ON(pin_nid < base_nid || pin_nid >= base_nid + 3))
2502 return -1;
2503 return pin_nid - base_nid + 1; /* intel port is 1-based */
2504}
2505
2474static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) 2506static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe)
2475{ 2507{
2476 struct hda_codec *codec = audio_ptr; 2508 struct hda_codec *codec = audio_ptr;
@@ -2481,16 +2513,7 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe)
2481 if (port < 1 || port > 3) 2513 if (port < 1 || port > 3)
2482 return; 2514 return;
2483 2515
2484 switch (codec->core.vendor_id) { 2516 pin_nid = port + intel_base_nid(codec) - 1; /* intel port is 1-based */
2485 case 0x80860054: /* ILK */
2486 case 0x80862804: /* ILK */
2487 case 0x80862882: /* VLV */
2488 pin_nid = port + 0x03;
2489 break;
2490 default:
2491 pin_nid = port + 0x04;
2492 break;
2493 }
2494 2517
2495 /* skip notification during system suspend (but not in runtime PM); 2518 /* skip notification during system suspend (but not in runtime PM);
2496 * the state will be updated at resume 2519 * the state will be updated at resume
@@ -2517,8 +2540,9 @@ static void register_i915_notifier(struct hda_codec *codec)
2517 * We need make sure audio_ptr is really setup 2540 * We need make sure audio_ptr is really setup
2518 */ 2541 */
2519 wmb(); 2542 wmb();
2543 spec->drm_audio_ops.pin2port = intel_pin2port;
2520 spec->drm_audio_ops.pin_eld_notify = intel_pin_eld_notify; 2544 spec->drm_audio_ops.pin_eld_notify = intel_pin_eld_notify;
2521 snd_hdac_i915_register_notifier(&codec->bus->core, 2545 snd_hdac_acomp_register_notifier(&codec->bus->core,
2522 &spec->drm_audio_ops); 2546 &spec->drm_audio_ops);
2523} 2547}
2524 2548
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index 2b7c33db4ded..4748a9d5de3b 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -1530,6 +1530,11 @@ free_widgets:
1530 return ret; 1530 return ret;
1531} 1531}
1532 1532
1533static int hdac_hdmi_pin2port(void *aptr, int pin)
1534{
1535 return pin - 4; /* map NID 0x05 -> port #1 */
1536}
1537
1533static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) 1538static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe)
1534{ 1539{
1535 struct hdac_device *hdev = aptr; 1540 struct hdac_device *hdev = aptr;
@@ -1584,6 +1589,7 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe)
1584} 1589}
1585 1590
1586static struct drm_audio_component_audio_ops aops = { 1591static struct drm_audio_component_audio_ops aops = {
1592 .pin2port = hdac_hdmi_pin2port,
1587 .pin_eld_notify = hdac_hdmi_eld_notify_cb, 1593 .pin_eld_notify = hdac_hdmi_eld_notify_cb,
1588}; 1594};
1589 1595
@@ -1812,7 +1818,7 @@ static int hdmi_codec_probe(struct snd_soc_component *component)
1812 return ret; 1818 return ret;
1813 1819
1814 aops.audio_ptr = hdev; 1820 aops.audio_ptr = hdev;
1815 ret = snd_hdac_i915_register_notifier(hdev->bus, &aops); 1821 ret = snd_hdac_acomp_register_notifier(hdev->bus, &aops);
1816 if (ret < 0) { 1822 if (ret < 0) {
1817 dev_err(&hdev->dev, "notifier register failed: err: %d\n", ret); 1823 dev_err(&hdev->dev, "notifier register failed: err: %d\n", ret);
1818 return ret; 1824 return ret;