1// SPDX-License-Identifier: GPL-2.0
2// Copyright(c) 2015-18 Intel Corporation.
3
4/*
5 * hdac_hda.c - ASoC extensions to reuse the legacy HDA codec drivers
6 * with ASoC platform drivers. These APIs are called by the legacy HDA
7 * codec drivers using hdac_ext_bus_ops ops.
8 */
9
10#include <linux/firmware.h>
11#include <linux/init.h>
12#include <linux/delay.h>
13#include <linux/module.h>
14#include <linux/pm_runtime.h>
15#include <sound/pcm_params.h>
16#include <sound/soc.h>
17#include <sound/hdaudio_ext.h>
18#include <sound/hda_i915.h>
19#include <sound/hda_codec.h>
20#include <sound/hda_register.h>
21
22#include "hdac_hda.h"
23
24#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
25 SNDRV_PCM_FMTBIT_U8 | \
26 SNDRV_PCM_FMTBIT_S16_LE | \
27 SNDRV_PCM_FMTBIT_U16_LE | \
28 SNDRV_PCM_FMTBIT_S24_LE | \
29 SNDRV_PCM_FMTBIT_U24_LE | \
30 SNDRV_PCM_FMTBIT_S32_LE | \
31 SNDRV_PCM_FMTBIT_U32_LE | \
32 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
33
34#define STUB_HDMI_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
35 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
36 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
37 SNDRV_PCM_RATE_192000)
38
39#ifdef CONFIG_SND_HDA_PATCH_LOADER
40static char *loadable_patch[HDA_MAX_CODECS];
41
42module_param_array_named(patch, loadable_patch, charp, NULL, 0444);
43MODULE_PARM_DESC(patch, "Patch file array for Intel HD audio interface. The array index is the codec address.");
44#endif
45
46static int hdac_hda_dai_open(struct snd_pcm_substream *substream,
47 struct snd_soc_dai *dai);
48static void hdac_hda_dai_close(struct snd_pcm_substream *substream,
49 struct snd_soc_dai *dai);
50static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream,
51 struct snd_soc_dai *dai);
52static int hdac_hda_dai_hw_params(struct snd_pcm_substream *substream,
53 struct snd_pcm_hw_params *params,
54 struct snd_soc_dai *dai);
55static int hdac_hda_dai_hw_free(struct snd_pcm_substream *substream,
56 struct snd_soc_dai *dai);
57static int hdac_hda_dai_set_stream(struct snd_soc_dai *dai, void *stream,
58 int direction);
59static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt,
60 struct snd_soc_dai *dai);
61
62static const struct snd_soc_dai_ops hdac_hda_dai_ops = {
63 .startup = hdac_hda_dai_open,
64 .shutdown = hdac_hda_dai_close,
65 .prepare = hdac_hda_dai_prepare,
66 .hw_params = hdac_hda_dai_hw_params,
67 .hw_free = hdac_hda_dai_hw_free,
68 .set_stream = hdac_hda_dai_set_stream,
69};
70
71static struct snd_soc_dai_driver hdac_hda_dais[] = {
72{
73 .id = HDAC_ANALOG_DAI_ID,
74 .name = "Analog Codec DAI",
75 .ops = &hdac_hda_dai_ops,
76 .playback = {
77 .stream_name = "Analog Codec Playback",
78 .channels_min = 1,
79 .channels_max = 16,
80 .rates = SNDRV_PCM_RATE_8000_192000,
81 .formats = STUB_FORMATS,
82 .sig_bits = 24,
83 },
84 .capture = {
85 .stream_name = "Analog Codec Capture",
86 .channels_min = 1,
87 .channels_max = 16,
88 .rates = SNDRV_PCM_RATE_8000_192000,
89 .formats = STUB_FORMATS,
90 .sig_bits = 24,
91 },
92},
93{
94 .id = HDAC_DIGITAL_DAI_ID,
95 .name = "Digital Codec DAI",
96 .ops = &hdac_hda_dai_ops,
97 .playback = {
98 .stream_name = "Digital Codec Playback",
99 .channels_min = 1,
100 .channels_max = 16,
101 .rates = SNDRV_PCM_RATE_8000_192000,
102 .formats = STUB_FORMATS,
103 .sig_bits = 24,
104 },
105 .capture = {
106 .stream_name = "Digital Codec Capture",
107 .channels_min = 1,
108 .channels_max = 16,
109 .rates = SNDRV_PCM_RATE_8000_192000,
110 .formats = STUB_FORMATS,
111 .sig_bits = 24,
112 },
113},
114{
115 .id = HDAC_ALT_ANALOG_DAI_ID,
116 .name = "Alt Analog Codec DAI",
117 .ops = &hdac_hda_dai_ops,
118 .playback = {
119 .stream_name = "Alt Analog Codec Playback",
120 .channels_min = 1,
121 .channels_max = 16,
122 .rates = SNDRV_PCM_RATE_8000_192000,
123 .formats = STUB_FORMATS,
124 .sig_bits = 24,
125 },
126 .capture = {
127 .stream_name = "Alt Analog Codec Capture",
128 .channels_min = 1,
129 .channels_max = 16,
130 .rates = SNDRV_PCM_RATE_8000_192000,
131 .formats = STUB_FORMATS,
132 .sig_bits = 24,
133 },
134},
135};
136
137static struct snd_soc_dai_driver hdac_hda_hdmi_dais[] = {
138{
139 .id = HDAC_HDMI_0_DAI_ID,
140 .name = "intel-hdmi-hifi1",
141 .ops = &hdac_hda_dai_ops,
142 .playback = {
143 .stream_name = "hifi1",
144 .channels_min = 1,
145 .channels_max = 32,
146 .rates = STUB_HDMI_RATES,
147 .formats = STUB_FORMATS,
148 .sig_bits = 24,
149 },
150},
151{
152 .id = HDAC_HDMI_1_DAI_ID,
153 .name = "intel-hdmi-hifi2",
154 .ops = &hdac_hda_dai_ops,
155 .playback = {
156 .stream_name = "hifi2",
157 .channels_min = 1,
158 .channels_max = 32,
159 .rates = STUB_HDMI_RATES,
160 .formats = STUB_FORMATS,
161 .sig_bits = 24,
162 },
163},
164{
165 .id = HDAC_HDMI_2_DAI_ID,
166 .name = "intel-hdmi-hifi3",
167 .ops = &hdac_hda_dai_ops,
168 .playback = {
169 .stream_name = "hifi3",
170 .channels_min = 1,
171 .channels_max = 32,
172 .rates = STUB_HDMI_RATES,
173 .formats = STUB_FORMATS,
174 .sig_bits = 24,
175 },
176},
177{
178 .id = HDAC_HDMI_3_DAI_ID,
179 .name = "intel-hdmi-hifi4",
180 .ops = &hdac_hda_dai_ops,
181 .playback = {
182 .stream_name = "hifi4",
183 .channels_min = 1,
184 .channels_max = 32,
185 .rates = STUB_HDMI_RATES,
186 .formats = STUB_FORMATS,
187 .sig_bits = 24,
188 },
189},
190
191};
192
193static int hdac_hda_dai_set_stream(struct snd_soc_dai *dai,
194 void *stream, int direction)
195{
196 struct snd_soc_component *component = dai->component;
197 struct hdac_hda_priv *hda_pvt;
198 struct hdac_hda_pcm *pcm;
199 struct hdac_stream *hstream;
200
201 if (!stream)
202 return -EINVAL;
203
204 hda_pvt = snd_soc_component_get_drvdata(c: component);
205 pcm = &hda_pvt->pcm[dai->id];
206 hstream = (struct hdac_stream *)stream;
207
208 pcm->stream_tag[direction] = hstream->stream_tag;
209
210 return 0;
211}
212
213static int hdac_hda_dai_hw_params(struct snd_pcm_substream *substream,
214 struct snd_pcm_hw_params *params,
215 struct snd_soc_dai *dai)
216{
217 struct snd_soc_component *component = dai->component;
218 struct hdac_hda_priv *hda_pvt;
219 unsigned int format_val;
220 unsigned int maxbps;
221 unsigned int bits;
222
223 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
224 maxbps = dai->driver->playback.sig_bits;
225 else
226 maxbps = dai->driver->capture.sig_bits;
227 bits = snd_hdac_stream_format_bits(format: params_format(p: params), SNDRV_PCM_SUBFORMAT_STD, maxbits: maxbps);
228
229 hda_pvt = snd_soc_component_get_drvdata(c: component);
230 format_val = snd_hdac_stream_format(channels: params_channels(p: params), bits, rate: params_rate(p: params));
231 if (!format_val) {
232 dev_err(dai->dev,
233 "invalid format_val, rate=%d, ch=%d, format=%d, maxbps=%d\n",
234 params_rate(params), params_channels(params),
235 params_format(params), maxbps);
236
237 return -EINVAL;
238 }
239
240 hda_pvt->pcm[dai->id].format_val[substream->stream] = format_val;
241 return 0;
242}
243
244static int hdac_hda_dai_hw_free(struct snd_pcm_substream *substream,
245 struct snd_soc_dai *dai)
246{
247 struct snd_soc_component *component = dai->component;
248 struct hdac_hda_priv *hda_pvt;
249 struct hda_pcm_stream *hda_stream;
250 struct hda_pcm *pcm;
251
252 hda_pvt = snd_soc_component_get_drvdata(c: component);
253 pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai);
254 if (!pcm)
255 return -EINVAL;
256
257 hda_stream = &pcm->stream[substream->stream];
258 snd_hda_codec_cleanup(codec: hda_pvt->codec, hinfo: hda_stream, substream);
259
260 return 0;
261}
262
263static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream,
264 struct snd_soc_dai *dai)
265{
266 struct snd_soc_component *component = dai->component;
267 struct hda_pcm_stream *hda_stream;
268 struct hdac_hda_priv *hda_pvt;
269 struct hdac_device *hdev;
270 unsigned int format_val;
271 struct hda_pcm *pcm;
272 unsigned int stream;
273 int ret = 0;
274
275 hda_pvt = snd_soc_component_get_drvdata(c: component);
276 hdev = &hda_pvt->codec->core;
277 pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai);
278 if (!pcm)
279 return -EINVAL;
280
281 hda_stream = &pcm->stream[substream->stream];
282
283 stream = hda_pvt->pcm[dai->id].stream_tag[substream->stream];
284 format_val = hda_pvt->pcm[dai->id].format_val[substream->stream];
285
286 ret = snd_hda_codec_prepare(codec: hda_pvt->codec, hinfo: hda_stream,
287 stream, format: format_val, substream);
288 if (ret < 0)
289 dev_err(&hdev->dev, "codec prepare failed %d\n", ret);
290
291 return ret;
292}
293
294static int hdac_hda_dai_open(struct snd_pcm_substream *substream,
295 struct snd_soc_dai *dai)
296{
297 struct snd_soc_component *component = dai->component;
298 struct hdac_hda_priv *hda_pvt;
299 struct hda_pcm_stream *hda_stream;
300 struct hda_pcm *pcm;
301
302 hda_pvt = snd_soc_component_get_drvdata(c: component);
303 pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai);
304 if (!pcm)
305 return -EINVAL;
306
307 snd_hda_codec_pcm_get(pcm);
308
309 hda_stream = &pcm->stream[substream->stream];
310
311 return hda_stream->ops.open(hda_stream, hda_pvt->codec, substream);
312}
313
314static void hdac_hda_dai_close(struct snd_pcm_substream *substream,
315 struct snd_soc_dai *dai)
316{
317 struct snd_soc_component *component = dai->component;
318 struct hdac_hda_priv *hda_pvt;
319 struct hda_pcm_stream *hda_stream;
320 struct hda_pcm *pcm;
321
322 hda_pvt = snd_soc_component_get_drvdata(c: component);
323 pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai);
324 if (!pcm)
325 return;
326
327 hda_stream = &pcm->stream[substream->stream];
328
329 hda_stream->ops.close(hda_stream, hda_pvt->codec, substream);
330
331 snd_hda_codec_pcm_put(pcm);
332}
333
334static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt,
335 struct snd_soc_dai *dai)
336{
337 struct hda_codec *hcodec = hda_pvt->codec;
338 struct hda_pcm *cpcm;
339 const char *pcm_name;
340
341 /*
342 * map DAI ID to the closest matching PCM name, using the naming
343 * scheme used by hda-codec snd_hda_gen_build_pcms() and for
344 * HDMI in hda_codec patch_hdmi.c)
345 */
346
347 switch (dai->id) {
348 case HDAC_ANALOG_DAI_ID:
349 pcm_name = "Analog";
350 break;
351 case HDAC_DIGITAL_DAI_ID:
352 pcm_name = "Digital";
353 break;
354 case HDAC_ALT_ANALOG_DAI_ID:
355 pcm_name = "Alt Analog";
356 break;
357 case HDAC_HDMI_0_DAI_ID:
358 pcm_name = "HDMI 0";
359 break;
360 case HDAC_HDMI_1_DAI_ID:
361 pcm_name = "HDMI 1";
362 break;
363 case HDAC_HDMI_2_DAI_ID:
364 pcm_name = "HDMI 2";
365 break;
366 case HDAC_HDMI_3_DAI_ID:
367 pcm_name = "HDMI 3";
368 break;
369 default:
370 dev_err(&hcodec->core.dev, "invalid dai id %d\n", dai->id);
371 return NULL;
372 }
373
374 list_for_each_entry(cpcm, &hcodec->pcm_list_head, list) {
375 if (strstr(cpcm->name, pcm_name)) {
376 if (strcmp(pcm_name, "Analog") == 0) {
377 if (strstr(cpcm->name, "Alt Analog"))
378 continue;
379 }
380 return cpcm;
381 }
382 }
383
384 dev_err(&hcodec->core.dev, "didn't find PCM for DAI %s\n", dai->name);
385 return NULL;
386}
387
388static bool is_hdmi_codec(struct hda_codec *hcodec)
389{
390 struct hda_pcm *cpcm;
391
392 list_for_each_entry(cpcm, &hcodec->pcm_list_head, list) {
393 if (cpcm->pcm_type == HDA_PCM_TYPE_HDMI)
394 return true;
395 }
396
397 return false;
398}
399
400static int hdac_hda_codec_probe(struct snd_soc_component *component)
401{
402 struct hdac_hda_priv *hda_pvt =
403 snd_soc_component_get_drvdata(c: component);
404 struct snd_soc_dapm_context *dapm =
405 snd_soc_component_get_dapm(component);
406 struct hdac_device *hdev = &hda_pvt->codec->core;
407 struct hda_codec *hcodec = hda_pvt->codec;
408 struct hdac_ext_link *hlink;
409 hda_codec_patch_t patch;
410 int ret;
411
412 hlink = snd_hdac_ext_bus_get_hlink_by_name(bus: hdev->bus, codec_name: dev_name(dev: &hdev->dev));
413 if (!hlink) {
414 dev_err(&hdev->dev, "hdac link not found\n");
415 return -EIO;
416 }
417
418 snd_hdac_ext_bus_link_get(bus: hdev->bus, hlink);
419
420 /*
421 * Ensure any HDA display is powered at codec probe.
422 * After snd_hda_codec_device_new(), display power is
423 * managed by runtime PM.
424 */
425 if (hda_pvt->need_display_power)
426 snd_hdac_display_power(bus: hdev->bus,
427 HDA_CODEC_IDX_CONTROLLER, enable: true);
428
429 ret = snd_hda_codec_device_new(bus: hcodec->bus, card: component->card->snd_card,
430 codec_addr: hdev->addr, codec: hcodec, snddev_managed: true);
431 if (ret < 0) {
432 dev_err(&hdev->dev, "failed to create hda codec %d\n", ret);
433 goto error_no_pm;
434 }
435
436#ifdef CONFIG_SND_HDA_PATCH_LOADER
437 if (loadable_patch[hda_pvt->dev_index] && *loadable_patch[hda_pvt->dev_index]) {
438 const struct firmware *fw;
439
440 dev_info(&hdev->dev, "Applying patch firmware '%s'\n",
441 loadable_patch[hda_pvt->dev_index]);
442 ret = request_firmware(fw: &fw, name: loadable_patch[hda_pvt->dev_index],
443 device: &hdev->dev);
444 if (ret < 0)
445 goto error_no_pm;
446 if (fw) {
447 ret = snd_hda_load_patch(bus: hcodec->bus, size: fw->size, buf: fw->data);
448 if (ret < 0) {
449 dev_err(&hdev->dev, "failed to load hda patch %d\n", ret);
450 goto error_no_pm;
451 }
452 release_firmware(fw);
453 }
454 }
455#endif
456 /*
457 * Overwrite type to HDA_DEV_ASOC since it is a ASoC driver
458 * hda_codec.c will check this flag to determine if unregister
459 * device is needed.
460 */
461 hdev->type = HDA_DEV_ASOC;
462
463 /*
464 * snd_hda_codec_device_new decrements the usage count so call get pm
465 * else the device will be powered off
466 */
467 pm_runtime_get_noresume(dev: &hdev->dev);
468
469 hcodec->bus->card = dapm->card->snd_card;
470
471 ret = snd_hda_codec_set_name(codec: hcodec, name: hcodec->preset->name);
472 if (ret < 0) {
473 dev_err(&hdev->dev, "name failed %s\n", hcodec->preset->name);
474 goto error_pm;
475 }
476
477 ret = snd_hdac_regmap_init(codec: &hcodec->core);
478 if (ret < 0) {
479 dev_err(&hdev->dev, "regmap init failed\n");
480 goto error_pm;
481 }
482
483 patch = (hda_codec_patch_t)hcodec->preset->driver_data;
484 if (patch) {
485 ret = patch(hcodec);
486 if (ret < 0) {
487 dev_err(&hdev->dev, "patch failed %d\n", ret);
488 goto error_regmap;
489 }
490 } else {
491 dev_dbg(&hdev->dev, "no patch file found\n");
492 }
493
494 ret = snd_hda_codec_parse_pcms(codec: hcodec);
495 if (ret < 0) {
496 dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret);
497 goto error_patch;
498 }
499
500 /* HDMI controls need to be created in machine drivers */
501 if (!is_hdmi_codec(hcodec)) {
502 ret = snd_hda_codec_build_controls(codec: hcodec);
503 if (ret < 0) {
504 dev_err(&hdev->dev, "unable to create controls %d\n",
505 ret);
506 goto error_patch;
507 }
508 }
509
510 hcodec->core.lazy_cache = true;
511
512 if (hda_pvt->need_display_power)
513 snd_hdac_display_power(bus: hdev->bus,
514 HDA_CODEC_IDX_CONTROLLER, enable: false);
515
516 /* match for forbid call in snd_hda_codec_device_new() */
517 pm_runtime_allow(dev: &hdev->dev);
518
519 /*
520 * hdac_device core already sets the state to active and calls
521 * get_noresume. So enable runtime and set the device to suspend.
522 * pm_runtime_enable is also called during codec registeration
523 */
524 pm_runtime_put(dev: &hdev->dev);
525 pm_runtime_suspend(dev: &hdev->dev);
526
527 return 0;
528
529error_patch:
530 if (hcodec->patch_ops.free)
531 hcodec->patch_ops.free(hcodec);
532error_regmap:
533 snd_hdac_regmap_exit(codec: hdev);
534error_pm:
535 pm_runtime_put(dev: &hdev->dev);
536error_no_pm:
537 snd_hdac_ext_bus_link_put(bus: hdev->bus, hlink);
538 return ret;
539}
540
541static void hdac_hda_codec_remove(struct snd_soc_component *component)
542{
543 struct hdac_hda_priv *hda_pvt =
544 snd_soc_component_get_drvdata(c: component);
545 struct hdac_device *hdev = &hda_pvt->codec->core;
546 struct hda_codec *codec = hda_pvt->codec;
547 struct hdac_ext_link *hlink = NULL;
548
549 hlink = snd_hdac_ext_bus_get_hlink_by_name(bus: hdev->bus, codec_name: dev_name(dev: &hdev->dev));
550 if (!hlink) {
551 dev_err(&hdev->dev, "hdac link not found\n");
552 return;
553 }
554
555 pm_runtime_disable(dev: &hdev->dev);
556 snd_hdac_ext_bus_link_put(bus: hdev->bus, hlink);
557
558 if (codec->patch_ops.free)
559 codec->patch_ops.free(codec);
560
561 snd_hda_codec_cleanup_for_unbind(codec);
562}
563
564static const struct snd_soc_dapm_route hdac_hda_dapm_routes[] = {
565 {"AIF1TX", NULL, "Codec Input Pin1"},
566 {"AIF2TX", NULL, "Codec Input Pin2"},
567 {"AIF3TX", NULL, "Codec Input Pin3"},
568
569 {"Codec Output Pin1", NULL, "AIF1RX"},
570 {"Codec Output Pin2", NULL, "AIF2RX"},
571 {"Codec Output Pin3", NULL, "AIF3RX"},
572};
573
574static const struct snd_soc_dapm_widget hdac_hda_dapm_widgets[] = {
575 /* Audio Interface */
576 SND_SOC_DAPM_AIF_IN("AIF1RX", "Analog Codec Playback", 0,
577 SND_SOC_NOPM, 0, 0),
578 SND_SOC_DAPM_AIF_IN("AIF2RX", "Digital Codec Playback", 0,
579 SND_SOC_NOPM, 0, 0),
580 SND_SOC_DAPM_AIF_IN("AIF3RX", "Alt Analog Codec Playback", 0,
581 SND_SOC_NOPM, 0, 0),
582 SND_SOC_DAPM_AIF_OUT("AIF1TX", "Analog Codec Capture", 0,
583 SND_SOC_NOPM, 0, 0),
584 SND_SOC_DAPM_AIF_OUT("AIF2TX", "Digital Codec Capture", 0,
585 SND_SOC_NOPM, 0, 0),
586 SND_SOC_DAPM_AIF_OUT("AIF3TX", "Alt Analog Codec Capture", 0,
587 SND_SOC_NOPM, 0, 0),
588
589 /* Input Pins */
590 SND_SOC_DAPM_INPUT("Codec Input Pin1"),
591 SND_SOC_DAPM_INPUT("Codec Input Pin2"),
592 SND_SOC_DAPM_INPUT("Codec Input Pin3"),
593
594 /* Output Pins */
595 SND_SOC_DAPM_OUTPUT("Codec Output Pin1"),
596 SND_SOC_DAPM_OUTPUT("Codec Output Pin2"),
597 SND_SOC_DAPM_OUTPUT("Codec Output Pin3"),
598};
599
600static const struct snd_soc_component_driver hdac_hda_codec = {
601 .probe = hdac_hda_codec_probe,
602 .remove = hdac_hda_codec_remove,
603 .dapm_widgets = hdac_hda_dapm_widgets,
604 .num_dapm_widgets = ARRAY_SIZE(hdac_hda_dapm_widgets),
605 .dapm_routes = hdac_hda_dapm_routes,
606 .num_dapm_routes = ARRAY_SIZE(hdac_hda_dapm_routes),
607 .idle_bias_on = false,
608 .endianness = 1,
609};
610
611static const struct snd_soc_component_driver hdac_hda_hdmi_codec = {
612 .probe = hdac_hda_codec_probe,
613 .remove = hdac_hda_codec_remove,
614 .idle_bias_on = false,
615 .endianness = 1,
616};
617
618static int hdac_hda_dev_probe(struct hdac_device *hdev)
619{
620 struct hdac_hda_priv *hda_pvt = dev_get_drvdata(dev: &hdev->dev);
621 struct hdac_ext_link *hlink;
622 int ret;
623
624 /* hold the ref while we probe */
625 hlink = snd_hdac_ext_bus_get_hlink_by_name(bus: hdev->bus, codec_name: dev_name(dev: &hdev->dev));
626 if (!hlink) {
627 dev_err(&hdev->dev, "hdac link not found\n");
628 return -EIO;
629 }
630 snd_hdac_ext_bus_link_get(bus: hdev->bus, hlink);
631
632 /* ASoC specific initialization */
633 if (hda_pvt->need_display_power)
634 ret = devm_snd_soc_register_component(dev: &hdev->dev,
635 component_driver: &hdac_hda_hdmi_codec, dai_drv: hdac_hda_hdmi_dais,
636 ARRAY_SIZE(hdac_hda_hdmi_dais));
637 else
638 ret = devm_snd_soc_register_component(dev: &hdev->dev,
639 component_driver: &hdac_hda_codec, dai_drv: hdac_hda_dais,
640 ARRAY_SIZE(hdac_hda_dais));
641
642 if (ret < 0) {
643 dev_err(&hdev->dev, "failed to register HDA codec %d\n", ret);
644 return ret;
645 }
646
647 snd_hdac_ext_bus_link_put(bus: hdev->bus, hlink);
648
649 return ret;
650}
651
652static int hdac_hda_dev_remove(struct hdac_device *hdev)
653{
654 /*
655 * Resources are freed in hdac_hda_codec_remove(). This
656 * function is kept to keep hda_codec_driver_remove() happy.
657 */
658 return 0;
659}
660
661static struct hdac_ext_bus_ops hdac_ops = {
662 .hdev_attach = hdac_hda_dev_probe,
663 .hdev_detach = hdac_hda_dev_remove,
664};
665
666struct hdac_ext_bus_ops *snd_soc_hdac_hda_get_ops(void)
667{
668 return &hdac_ops;
669}
670EXPORT_SYMBOL_GPL(snd_soc_hdac_hda_get_ops);
671
672MODULE_LICENSE("GPL v2");
673MODULE_DESCRIPTION("ASoC Extensions for legacy HDA Drivers");
674MODULE_AUTHOR("Rakesh Ughreja<rakesh.a.ughreja@intel.com>");
675

source code of linux/sound/soc/codecs/hdac_hda.c