diff options
-rw-r--r-- | drivers/gpu/drm/i915/Kconfig | 1 | ||||
-rw-r--r-- | include/drm/drm_audio_component.h | 23 | ||||
-rw-r--r-- | include/sound/hda_component.h | 61 | ||||
-rw-r--r-- | include/sound/hda_i915.h | 39 | ||||
-rw-r--r-- | sound/hda/Kconfig | 7 | ||||
-rw-r--r-- | sound/hda/Makefile | 1 | ||||
-rw-r--r-- | sound/hda/hdac_component.c | 335 | ||||
-rw-r--r-- | sound/hda/hdac_i915.c | 343 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 50 | ||||
-rw-r--r-- | sound/soc/codecs/hdac_hdmi.c | 8 |
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 | ||
7 | struct 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 | ||
10 | int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable); | ||
11 | int snd_hdac_display_power(struct hdac_bus *bus, bool enable); | ||
12 | int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, | ||
13 | int dev_id, int rate); | ||
14 | int 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); | ||
16 | int 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); | ||
20 | int snd_hdac_acomp_exit(struct hdac_bus *bus); | ||
21 | int snd_hdac_acomp_register_notifier(struct hdac_bus *bus, | ||
22 | const struct drm_audio_component_audio_ops *ops); | ||
23 | #else | ||
24 | static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) | ||
25 | { | ||
26 | return 0; | ||
27 | } | ||
28 | static inline int snd_hdac_display_power(struct hdac_bus *bus, bool enable) | ||
29 | { | ||
30 | return 0; | ||
31 | } | ||
32 | static 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 | } | ||
37 | static 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 | } | ||
43 | static 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 | } | ||
50 | static inline int snd_hdac_acomp_exit(struct hdac_bus *bus) | ||
51 | { | ||
52 | return 0; | ||
53 | } | ||
54 | static 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 |
11 | int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable); | ||
12 | int snd_hdac_display_power(struct hdac_bus *bus, bool enable); | ||
13 | void snd_hdac_i915_set_bclk(struct hdac_bus *bus); | 11 | void snd_hdac_i915_set_bclk(struct hdac_bus *bus); |
14 | int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, | ||
15 | int dev_id, int rate); | ||
16 | int 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); | ||
18 | int snd_hdac_i915_init(struct hdac_bus *bus); | 12 | int snd_hdac_i915_init(struct hdac_bus *bus); |
19 | int snd_hdac_i915_exit(struct hdac_bus *bus); | ||
20 | int snd_hdac_i915_register_notifier(struct hdac_bus *bus, | ||
21 | const struct drm_audio_component_audio_ops *ops); | ||
22 | #else | 13 | #else |
23 | static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable) | ||
24 | { | ||
25 | return 0; | ||
26 | } | ||
27 | static inline int snd_hdac_display_power(struct hdac_bus *bus, bool enable) | ||
28 | { | ||
29 | return 0; | ||
30 | } | ||
31 | static inline void snd_hdac_i915_set_bclk(struct hdac_bus *bus) | 14 | static inline void snd_hdac_i915_set_bclk(struct hdac_bus *bus) |
32 | { | 15 | { |
33 | } | 16 | } |
34 | static 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 | } | ||
39 | static 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 | } | ||
45 | static inline int snd_hdac_i915_init(struct hdac_bus *bus) | 17 | static inline int snd_hdac_i915_init(struct hdac_bus *bus) |
46 | { | 18 | { |
47 | return -ENODEV; | 19 | return -ENODEV; |
48 | } | 20 | } |
21 | #endif | ||
49 | static inline int snd_hdac_i915_exit(struct hdac_bus *bus) | 22 | static inline int snd_hdac_i915_exit(struct hdac_bus *bus) |
50 | { | 23 | { |
51 | return 0; | 24 | return snd_hdac_acomp_exit(bus); |
52 | } | 25 | } |
53 | static 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 | |||
5 | config SND_HDA_DSP_LOADER | 5 | config SND_HDA_DSP_LOADER |
6 | bool | 6 | bool |
7 | 7 | ||
8 | config SND_HDA_COMPONENT | ||
9 | bool | ||
10 | |||
8 | config SND_HDA_I915 | 11 | config 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 | ||
14 | config SND_HDA_EXT_CORE | 15 | config 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 | |||
6 | CFLAGS_trace.o := -I$(src) | 6 | CFLAGS_trace.o := -I$(src) |
7 | 7 | ||
8 | # for sync with i915 gfx driver | 8 | # for sync with i915 gfx driver |
9 | snd-hda-core-$(CONFIG_SND_HDA_COMPONENT) += hdac_component.o | ||
9 | snd-hda-core-$(CONFIG_SND_HDA_I915) += hdac_i915.o | 10 | snd-hda-core-$(CONFIG_SND_HDA_I915) += hdac_i915.o |
10 | 11 | ||
11 | obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o | 12 | obj-$(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 | |||
13 | static void hdac_acomp_release(struct device *dev, void *res) | ||
14 | { | ||
15 | } | ||
16 | |||
17 | static 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 | */ | ||
35 | int 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 | } | ||
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 | * @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 | */ | ||
67 | int 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 | } | ||
93 | EXPORT_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 | */ | ||
108 | int 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 | } | ||
126 | EXPORT_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 | */ | ||
149 | int 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 | } | ||
169 | EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld); | ||
170 | |||
171 | static 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); | ||
204 | out_unbind: | ||
205 | component_unbind_all(dev, acomp); | ||
206 | |||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | static 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 | |||
221 | static 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 | */ | ||
238 | int 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 | } | ||
247 | EXPORT_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 | */ | ||
267 | int 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 | |||
296 | out_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 | } | ||
303 | EXPORT_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 | */ | ||
316 | int 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 | } | ||
335 | EXPORT_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 | ||
25 | static void hdac_acomp_release(struct device *dev, void *res) | ||
26 | { | ||
27 | } | ||
28 | |||
29 | static 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 | */ | ||
47 | int 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 | } | ||
67 | EXPORT_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 | */ | ||
82 | int 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 | } | ||
106 | EXPORT_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 | } |
166 | EXPORT_SYMBOL_GPL(snd_hdac_i915_set_bclk); | 81 | EXPORT_SYMBOL_GPL(snd_hdac_i915_set_bclk); |
167 | 82 | ||
168 | /* There is a fixed mapping between audio pin node and display port. | 83 | static 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 | */ | ||
179 | static 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 | */ | ||
212 | int 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 | } | ||
227 | EXPORT_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 | */ | ||
250 | int 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 | } | ||
268 | EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld); | ||
269 | |||
270 | static 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 | |||
296 | out_unbind: | ||
297 | component_unbind_all(dev, acomp); | ||
298 | |||
299 | return ret; | ||
300 | } | ||
301 | |||
302 | static 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 | |||
311 | static const struct component_master_ops hdac_component_master_ops = { | ||
312 | .bind = hdac_component_master_bind, | ||
313 | .unbind = hdac_component_master_unbind, | ||
314 | }; | ||
315 | |||
316 | static 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 | */ | ||
334 | int 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 | } | ||
343 | EXPORT_SYMBOL_GPL(snd_hdac_i915_register_notifier); | ||
344 | |||
345 | /* check whether intel graphics is present */ | 88 | /* check whether intel graphics is present */ |
346 | static bool i915_gfx_present(void) | 89 | static bool i915_gfx_present(void) |
347 | { | 90 | { |
@@ -368,84 +111,26 @@ static bool i915_gfx_present(void) | |||
368 | */ | 111 | */ |
369 | int snd_hdac_i915_init(struct hdac_bus *bus) | 112 | int 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; |
410 | out_master_del: | ||
411 | component_master_del(dev, &hdac_component_master_ops); | ||
412 | out_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 | } |
419 | EXPORT_SYMBOL_GPL(snd_hdac_i915_init); | 136 | EXPORT_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 | */ | ||
432 | int 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 | } | ||
451 | EXPORT_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 |
187 | static inline bool codec_has_acomp(struct hda_codec *codec) | 187 | static 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 | */ | ||
2485 | static 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 | |||
2497 | static 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 | |||
2474 | static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) | 2506 | static 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 | ||
1533 | static int hdac_hdmi_pin2port(void *aptr, int pin) | ||
1534 | { | ||
1535 | return pin - 4; /* map NID 0x05 -> port #1 */ | ||
1536 | } | ||
1537 | |||
1533 | static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) | 1538 | static 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 | ||
1586 | static struct drm_audio_component_audio_ops aops = { | 1591 | static 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; |