summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;