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