Commit | Line | Data |
---|---|---|
d8a766a1 TI |
1 | /* |
2 | * HD-audio codec driver binding | |
3 | * Copyright (c) Takashi Iwai <tiwai@suse.de> | |
4 | */ | |
5 | ||
6 | #include <linux/init.h> | |
7 | #include <linux/slab.h> | |
8 | #include <linux/mutex.h> | |
9 | #include <linux/module.h> | |
10 | #include <linux/export.h> | |
59ed1ead | 11 | #include <linux/pm.h> |
b2a0bafa | 12 | #include <linux/pm_runtime.h> |
d8a766a1 TI |
13 | #include <sound/core.h> |
14 | #include "hda_codec.h" | |
15 | #include "hda_local.h" | |
16 | ||
17 | /* codec vendor labels */ | |
18 | struct hda_vendor_id { | |
19 | unsigned int id; | |
20 | const char *name; | |
21 | }; | |
22 | ||
23 | static struct hda_vendor_id hda_vendor_ids[] = { | |
24 | { 0x1002, "ATI" }, | |
25 | { 0x1013, "Cirrus Logic" }, | |
26 | { 0x1057, "Motorola" }, | |
27 | { 0x1095, "Silicon Image" }, | |
28 | { 0x10de, "Nvidia" }, | |
29 | { 0x10ec, "Realtek" }, | |
30 | { 0x1102, "Creative" }, | |
31 | { 0x1106, "VIA" }, | |
32 | { 0x111d, "IDT" }, | |
33 | { 0x11c1, "LSI" }, | |
34 | { 0x11d4, "Analog Devices" }, | |
35 | { 0x13f6, "C-Media" }, | |
36 | { 0x14f1, "Conexant" }, | |
37 | { 0x17e8, "Chrontel" }, | |
38 | { 0x1854, "LG" }, | |
39 | { 0x1aec, "Wolfson Microelectronics" }, | |
40 | { 0x1af4, "QEMU" }, | |
41 | { 0x434d, "C-Media" }, | |
42 | { 0x8086, "Intel" }, | |
43 | { 0x8384, "SigmaTel" }, | |
44 | {} /* terminator */ | |
45 | }; | |
46 | ||
47 | /* | |
48 | * find a matching codec preset | |
49 | */ | |
e3d280fc | 50 | static int hda_codec_match(struct hdac_device *dev, struct hdac_driver *drv) |
d8a766a1 | 51 | { |
e3d280fc | 52 | struct hda_codec *codec = container_of(dev, struct hda_codec, core); |
d8a766a1 | 53 | struct hda_codec_driver *driver = |
e3d280fc | 54 | container_of(drv, struct hda_codec_driver, core); |
d8a766a1 TI |
55 | const struct hda_codec_preset *preset; |
56 | /* check probe_id instead of vendor_id if set */ | |
57 | u32 id = codec->probe_id ? codec->probe_id : codec->vendor_id; | |
58 | ||
59 | for (preset = driver->preset; preset->id; preset++) { | |
60 | u32 mask = preset->mask; | |
61 | ||
62 | if (preset->afg && preset->afg != codec->afg) | |
63 | continue; | |
64 | if (preset->mfg && preset->mfg != codec->mfg) | |
65 | continue; | |
66 | if (!mask) | |
67 | mask = ~0; | |
68 | if (preset->id == (id & mask) && | |
69 | (!preset->rev || preset->rev == codec->revision_id)) { | |
70 | codec->preset = preset; | |
71 | return 1; | |
72 | } | |
73 | } | |
74 | return 0; | |
75 | } | |
76 | ||
d068ebc2 TI |
77 | /* process an unsolicited event */ |
78 | static void hda_codec_unsol_event(struct hdac_device *dev, unsigned int ev) | |
79 | { | |
80 | struct hda_codec *codec = container_of(dev, struct hda_codec, core); | |
81 | ||
82 | if (codec->patch_ops.unsol_event) | |
83 | codec->patch_ops.unsol_event(codec, ev); | |
84 | } | |
85 | ||
d8a766a1 TI |
86 | /* reset the codec name from the preset */ |
87 | static int codec_refresh_name(struct hda_codec *codec, const char *name) | |
88 | { | |
89 | char tmp[16]; | |
90 | ||
91 | kfree(codec->chip_name); | |
92 | if (!name) { | |
93 | sprintf(tmp, "ID %x", codec->vendor_id & 0xffff); | |
94 | name = tmp; | |
95 | } | |
96 | codec->chip_name = kstrdup(name, GFP_KERNEL); | |
97 | return codec->chip_name ? 0 : -ENOMEM; | |
98 | } | |
99 | ||
100 | static int hda_codec_driver_probe(struct device *dev) | |
101 | { | |
102 | struct hda_codec *codec = dev_to_hda_codec(dev); | |
103 | struct module *owner = dev->driver->owner; | |
104 | int err; | |
105 | ||
106 | if (WARN_ON(!codec->preset)) | |
107 | return -EINVAL; | |
108 | ||
109 | err = codec_refresh_name(codec, codec->preset->name); | |
110 | if (err < 0) | |
111 | goto error; | |
112 | ||
113 | if (!try_module_get(owner)) { | |
114 | err = -EINVAL; | |
115 | goto error; | |
116 | } | |
117 | ||
118 | err = codec->preset->patch(codec); | |
bcd96557 TI |
119 | if (err < 0) |
120 | goto error_module; | |
121 | ||
122 | err = snd_hda_codec_build_pcms(codec); | |
123 | if (err < 0) | |
124 | goto error_module; | |
125 | err = snd_hda_codec_build_controls(codec); | |
126 | if (err < 0) | |
127 | goto error_module; | |
128 | if (codec->card->registered) { | |
129 | err = snd_card_register(codec->card); | |
130 | if (err < 0) | |
131 | goto error_module; | |
d8a766a1 TI |
132 | } |
133 | ||
134 | return 0; | |
135 | ||
bcd96557 TI |
136 | error_module: |
137 | module_put(owner); | |
138 | ||
d8a766a1 | 139 | error: |
bcd96557 | 140 | snd_hda_codec_cleanup_for_unbind(codec); |
d8a766a1 TI |
141 | return err; |
142 | } | |
143 | ||
144 | static int hda_codec_driver_remove(struct device *dev) | |
145 | { | |
146 | struct hda_codec *codec = dev_to_hda_codec(dev); | |
147 | ||
148 | if (codec->patch_ops.free) | |
149 | codec->patch_ops.free(codec); | |
9a6246ff | 150 | snd_hda_codec_cleanup_for_unbind(codec); |
d8a766a1 TI |
151 | module_put(dev->driver->owner); |
152 | return 0; | |
153 | } | |
154 | ||
b2a0bafa TI |
155 | static void hda_codec_driver_shutdown(struct device *dev) |
156 | { | |
157 | struct hda_codec *codec = dev_to_hda_codec(dev); | |
158 | ||
159 | if (!pm_runtime_suspended(dev) && codec->patch_ops.reboot_notify) | |
160 | codec->patch_ops.reboot_notify(codec); | |
161 | } | |
162 | ||
d8a766a1 TI |
163 | int __hda_codec_driver_register(struct hda_codec_driver *drv, const char *name, |
164 | struct module *owner) | |
165 | { | |
e3d280fc TI |
166 | drv->core.driver.name = name; |
167 | drv->core.driver.owner = owner; | |
168 | drv->core.driver.bus = &snd_hda_bus_type; | |
169 | drv->core.driver.probe = hda_codec_driver_probe; | |
170 | drv->core.driver.remove = hda_codec_driver_remove; | |
171 | drv->core.driver.shutdown = hda_codec_driver_shutdown; | |
172 | drv->core.driver.pm = &hda_codec_driver_pm; | |
173 | drv->core.type = HDA_DEV_LEGACY; | |
174 | drv->core.match = hda_codec_match; | |
d068ebc2 | 175 | drv->core.unsol_event = hda_codec_unsol_event; |
e3d280fc | 176 | return driver_register(&drv->core.driver); |
d8a766a1 TI |
177 | } |
178 | EXPORT_SYMBOL_GPL(__hda_codec_driver_register); | |
179 | ||
180 | void hda_codec_driver_unregister(struct hda_codec_driver *drv) | |
181 | { | |
e3d280fc | 182 | driver_unregister(&drv->core.driver); |
d8a766a1 TI |
183 | } |
184 | EXPORT_SYMBOL_GPL(hda_codec_driver_unregister); | |
185 | ||
186 | static inline bool codec_probed(struct hda_codec *codec) | |
187 | { | |
188 | return device_attach(hda_codec_dev(codec)) > 0 && codec->preset; | |
189 | } | |
190 | ||
191 | /* try to auto-load and bind the codec module */ | |
192 | static void codec_bind_module(struct hda_codec *codec) | |
193 | { | |
194 | #ifdef MODULE | |
195 | request_module("snd-hda-codec-id:%08x", codec->vendor_id); | |
196 | if (codec_probed(codec)) | |
197 | return; | |
198 | request_module("snd-hda-codec-id:%04x*", | |
199 | (codec->vendor_id >> 16) & 0xffff); | |
200 | if (codec_probed(codec)) | |
201 | return; | |
202 | #endif | |
203 | } | |
204 | ||
205 | /* store the codec vendor name */ | |
206 | static int get_codec_vendor_name(struct hda_codec *codec) | |
207 | { | |
208 | const struct hda_vendor_id *c; | |
209 | const char *vendor = NULL; | |
210 | u16 vendor_id = codec->vendor_id >> 16; | |
211 | char tmp[16]; | |
212 | ||
213 | for (c = hda_vendor_ids; c->id; c++) { | |
214 | if (c->id == vendor_id) { | |
215 | vendor = c->name; | |
216 | break; | |
217 | } | |
218 | } | |
219 | if (!vendor) { | |
220 | sprintf(tmp, "Generic %04x", vendor_id); | |
221 | vendor = tmp; | |
222 | } | |
223 | codec->vendor_name = kstrdup(vendor, GFP_KERNEL); | |
224 | if (!codec->vendor_name) | |
225 | return -ENOMEM; | |
226 | return 0; | |
227 | } | |
228 | ||
229 | #if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) | |
230 | /* if all audio out widgets are digital, let's assume the codec as a HDMI/DP */ | |
231 | static bool is_likely_hdmi_codec(struct hda_codec *codec) | |
232 | { | |
233 | hda_nid_t nid = codec->start_nid; | |
234 | int i; | |
235 | ||
236 | for (i = 0; i < codec->num_nodes; i++, nid++) { | |
237 | unsigned int wcaps = get_wcaps(codec, nid); | |
238 | switch (get_wcaps_type(wcaps)) { | |
239 | case AC_WID_AUD_IN: | |
240 | return false; /* HDMI parser supports only HDMI out */ | |
241 | case AC_WID_AUD_OUT: | |
242 | if (!(wcaps & AC_WCAP_DIGITAL)) | |
243 | return false; | |
244 | break; | |
245 | } | |
246 | } | |
247 | return true; | |
248 | } | |
249 | #else | |
250 | /* no HDMI codec parser support */ | |
251 | #define is_likely_hdmi_codec(codec) false | |
252 | #endif /* CONFIG_SND_HDA_CODEC_HDMI */ | |
253 | ||
254 | static int codec_bind_generic(struct hda_codec *codec) | |
255 | { | |
256 | if (codec->probe_id) | |
257 | return -ENODEV; | |
258 | ||
259 | if (is_likely_hdmi_codec(codec)) { | |
260 | codec->probe_id = HDA_CODEC_ID_GENERIC_HDMI; | |
261 | #if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI) | |
262 | request_module("snd-hda-codec-hdmi"); | |
263 | #endif | |
264 | if (codec_probed(codec)) | |
265 | return 0; | |
266 | } | |
267 | ||
268 | codec->probe_id = HDA_CODEC_ID_GENERIC; | |
269 | #if IS_MODULE(CONFIG_SND_HDA_GENERIC) | |
270 | request_module("snd-hda-codec-generic"); | |
271 | #endif | |
272 | if (codec_probed(codec)) | |
273 | return 0; | |
274 | return -ENODEV; | |
275 | } | |
276 | ||
277 | #if IS_ENABLED(CONFIG_SND_HDA_GENERIC) | |
278 | #define is_generic_config(codec) \ | |
279 | (codec->modelname && !strcmp(codec->modelname, "generic")) | |
280 | #else | |
281 | #define is_generic_config(codec) 0 | |
282 | #endif | |
283 | ||
284 | /** | |
285 | * snd_hda_codec_configure - (Re-)configure the HD-audio codec | |
286 | * @codec: the HDA codec | |
287 | * | |
288 | * Start parsing of the given codec tree and (re-)initialize the whole | |
289 | * patch instance. | |
290 | * | |
291 | * Returns 0 if successful or a negative error code. | |
292 | */ | |
293 | int snd_hda_codec_configure(struct hda_codec *codec) | |
294 | { | |
295 | int err; | |
296 | ||
297 | if (!codec->vendor_name) { | |
298 | err = get_codec_vendor_name(codec); | |
299 | if (err < 0) | |
300 | return err; | |
301 | } | |
302 | ||
303 | if (is_generic_config(codec)) | |
304 | codec->probe_id = HDA_CODEC_ID_GENERIC; | |
305 | else | |
306 | codec->probe_id = 0; | |
307 | ||
308 | err = device_add(hda_codec_dev(codec)); | |
309 | if (err < 0) | |
310 | return err; | |
311 | ||
312 | if (!codec->preset) | |
313 | codec_bind_module(codec); | |
314 | if (!codec->preset) { | |
315 | err = codec_bind_generic(codec); | |
316 | if (err < 0) { | |
317 | codec_err(codec, "Unable to bind the codec\n"); | |
318 | goto error; | |
319 | } | |
320 | } | |
321 | ||
322 | /* audio codec should override the mixer name */ | |
6efdd851 TI |
323 | if (codec->afg || !*codec->card->mixername) |
324 | snprintf(codec->card->mixername, | |
325 | sizeof(codec->card->mixername), | |
d8a766a1 TI |
326 | "%s %s", codec->vendor_name, codec->chip_name); |
327 | return 0; | |
328 | ||
329 | error: | |
330 | device_del(hda_codec_dev(codec)); | |
331 | return err; | |
332 | } | |
333 | EXPORT_SYMBOL_GPL(snd_hda_codec_configure); |