Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright(c) 2015-18 Intel Corporation.
0003 
0004 /*
0005  * hdac_hda.c - ASoC extensions to reuse the legacy HDA codec drivers
0006  * with ASoC platform drivers. These APIs are called by the legacy HDA
0007  * codec drivers using hdac_ext_bus_ops ops.
0008  */
0009 
0010 #include <linux/init.h>
0011 #include <linux/delay.h>
0012 #include <linux/module.h>
0013 #include <linux/pm_runtime.h>
0014 #include <sound/pcm_params.h>
0015 #include <sound/soc.h>
0016 #include <sound/hdaudio_ext.h>
0017 #include <sound/hda_i915.h>
0018 #include <sound/hda_codec.h>
0019 #include <sound/hda_register.h>
0020 
0021 #include "hdac_hda.h"
0022 
0023 #define STUB_FORMATS    (SNDRV_PCM_FMTBIT_S8 | \
0024             SNDRV_PCM_FMTBIT_U8 | \
0025             SNDRV_PCM_FMTBIT_S16_LE | \
0026             SNDRV_PCM_FMTBIT_U16_LE | \
0027             SNDRV_PCM_FMTBIT_S24_LE | \
0028             SNDRV_PCM_FMTBIT_U24_LE | \
0029             SNDRV_PCM_FMTBIT_S32_LE | \
0030             SNDRV_PCM_FMTBIT_U32_LE | \
0031             SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
0032 
0033 #define STUB_HDMI_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
0034                  SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
0035                  SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
0036                  SNDRV_PCM_RATE_192000)
0037 
0038 static int hdac_hda_dai_open(struct snd_pcm_substream *substream,
0039                  struct snd_soc_dai *dai);
0040 static void hdac_hda_dai_close(struct snd_pcm_substream *substream,
0041                    struct snd_soc_dai *dai);
0042 static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream,
0043                 struct snd_soc_dai *dai);
0044 static int hdac_hda_dai_hw_params(struct snd_pcm_substream *substream,
0045                   struct snd_pcm_hw_params *params,
0046                   struct snd_soc_dai *dai);
0047 static int hdac_hda_dai_hw_free(struct snd_pcm_substream *substream,
0048                 struct snd_soc_dai *dai);
0049 static int hdac_hda_dai_set_stream(struct snd_soc_dai *dai, void *stream,
0050                    int direction);
0051 static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt,
0052                          struct snd_soc_dai *dai);
0053 
0054 static const struct snd_soc_dai_ops hdac_hda_dai_ops = {
0055     .startup = hdac_hda_dai_open,
0056     .shutdown = hdac_hda_dai_close,
0057     .prepare = hdac_hda_dai_prepare,
0058     .hw_params = hdac_hda_dai_hw_params,
0059     .hw_free = hdac_hda_dai_hw_free,
0060     .set_stream = hdac_hda_dai_set_stream,
0061 };
0062 
0063 static struct snd_soc_dai_driver hdac_hda_dais[] = {
0064 {
0065     .id = HDAC_ANALOG_DAI_ID,
0066     .name = "Analog Codec DAI",
0067     .ops = &hdac_hda_dai_ops,
0068     .playback = {
0069         .stream_name    = "Analog Codec Playback",
0070         .channels_min   = 1,
0071         .channels_max   = 16,
0072         .rates      = SNDRV_PCM_RATE_8000_192000,
0073         .formats    = STUB_FORMATS,
0074         .sig_bits   = 24,
0075     },
0076     .capture = {
0077         .stream_name    = "Analog Codec Capture",
0078         .channels_min   = 1,
0079         .channels_max   = 16,
0080         .rates = SNDRV_PCM_RATE_8000_192000,
0081         .formats = STUB_FORMATS,
0082         .sig_bits = 24,
0083     },
0084 },
0085 {
0086     .id = HDAC_DIGITAL_DAI_ID,
0087     .name = "Digital Codec DAI",
0088     .ops = &hdac_hda_dai_ops,
0089     .playback = {
0090         .stream_name    = "Digital Codec Playback",
0091         .channels_min   = 1,
0092         .channels_max   = 16,
0093         .rates          = SNDRV_PCM_RATE_8000_192000,
0094         .formats        = STUB_FORMATS,
0095         .sig_bits = 24,
0096     },
0097     .capture = {
0098         .stream_name    = "Digital Codec Capture",
0099         .channels_min   = 1,
0100         .channels_max   = 16,
0101         .rates = SNDRV_PCM_RATE_8000_192000,
0102         .formats = STUB_FORMATS,
0103         .sig_bits = 24,
0104     },
0105 },
0106 {
0107     .id = HDAC_ALT_ANALOG_DAI_ID,
0108     .name = "Alt Analog Codec DAI",
0109     .ops = &hdac_hda_dai_ops,
0110     .playback = {
0111         .stream_name    = "Alt Analog Codec Playback",
0112         .channels_min   = 1,
0113         .channels_max   = 16,
0114         .rates      = SNDRV_PCM_RATE_8000_192000,
0115         .formats    = STUB_FORMATS,
0116         .sig_bits   = 24,
0117     },
0118     .capture = {
0119         .stream_name    = "Alt Analog Codec Capture",
0120         .channels_min   = 1,
0121         .channels_max   = 16,
0122         .rates = SNDRV_PCM_RATE_8000_192000,
0123         .formats = STUB_FORMATS,
0124         .sig_bits = 24,
0125     },
0126 },
0127 {
0128     .id = HDAC_HDMI_0_DAI_ID,
0129     .name = "intel-hdmi-hifi1",
0130     .ops = &hdac_hda_dai_ops,
0131     .playback = {
0132         .stream_name    = "hifi1",
0133         .channels_min   = 1,
0134         .channels_max   = 32,
0135         .rates          = STUB_HDMI_RATES,
0136         .formats        = STUB_FORMATS,
0137         .sig_bits = 24,
0138     },
0139 },
0140 {
0141     .id = HDAC_HDMI_1_DAI_ID,
0142     .name = "intel-hdmi-hifi2",
0143     .ops = &hdac_hda_dai_ops,
0144     .playback = {
0145         .stream_name    = "hifi2",
0146         .channels_min   = 1,
0147         .channels_max   = 32,
0148         .rates          = STUB_HDMI_RATES,
0149         .formats        = STUB_FORMATS,
0150         .sig_bits = 24,
0151     },
0152 },
0153 {
0154     .id = HDAC_HDMI_2_DAI_ID,
0155     .name = "intel-hdmi-hifi3",
0156     .ops = &hdac_hda_dai_ops,
0157     .playback = {
0158         .stream_name    = "hifi3",
0159         .channels_min   = 1,
0160         .channels_max   = 32,
0161         .rates          = STUB_HDMI_RATES,
0162         .formats        = STUB_FORMATS,
0163         .sig_bits = 24,
0164     },
0165 },
0166 {
0167     .id = HDAC_HDMI_3_DAI_ID,
0168     .name = "intel-hdmi-hifi4",
0169     .ops = &hdac_hda_dai_ops,
0170     .playback = {
0171         .stream_name    = "hifi4",
0172         .channels_min   = 1,
0173         .channels_max   = 32,
0174         .rates          = STUB_HDMI_RATES,
0175         .formats        = STUB_FORMATS,
0176         .sig_bits = 24,
0177     },
0178 },
0179 
0180 };
0181 
0182 static int hdac_hda_dai_set_stream(struct snd_soc_dai *dai,
0183                    void *stream, int direction)
0184 {
0185     struct snd_soc_component *component = dai->component;
0186     struct hdac_hda_priv *hda_pvt;
0187     struct hdac_hda_pcm *pcm;
0188     struct hdac_stream *hstream;
0189 
0190     if (!stream)
0191         return -EINVAL;
0192 
0193     hda_pvt = snd_soc_component_get_drvdata(component);
0194     pcm = &hda_pvt->pcm[dai->id];
0195     hstream = (struct hdac_stream *)stream;
0196 
0197     pcm->stream_tag[direction] = hstream->stream_tag;
0198 
0199     return 0;
0200 }
0201 
0202 static int hdac_hda_dai_hw_params(struct snd_pcm_substream *substream,
0203                   struct snd_pcm_hw_params *params,
0204                   struct snd_soc_dai *dai)
0205 {
0206     struct snd_soc_component *component = dai->component;
0207     struct hdac_hda_priv *hda_pvt;
0208     unsigned int format_val;
0209     unsigned int maxbps;
0210 
0211     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
0212         maxbps = dai->driver->playback.sig_bits;
0213     else
0214         maxbps = dai->driver->capture.sig_bits;
0215 
0216     hda_pvt = snd_soc_component_get_drvdata(component);
0217     format_val = snd_hdac_calc_stream_format(params_rate(params),
0218                          params_channels(params),
0219                          params_format(params),
0220                          maxbps,
0221                          0);
0222     if (!format_val) {
0223         dev_err(dai->dev,
0224             "invalid format_val, rate=%d, ch=%d, format=%d, maxbps=%d\n",
0225             params_rate(params), params_channels(params),
0226             params_format(params), maxbps);
0227 
0228         return -EINVAL;
0229     }
0230 
0231     hda_pvt->pcm[dai->id].format_val[substream->stream] = format_val;
0232     return 0;
0233 }
0234 
0235 static int hdac_hda_dai_hw_free(struct snd_pcm_substream *substream,
0236                 struct snd_soc_dai *dai)
0237 {
0238     struct snd_soc_component *component = dai->component;
0239     struct hdac_hda_priv *hda_pvt;
0240     struct hda_pcm_stream *hda_stream;
0241     struct hda_pcm *pcm;
0242 
0243     hda_pvt = snd_soc_component_get_drvdata(component);
0244     pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai);
0245     if (!pcm)
0246         return -EINVAL;
0247 
0248     hda_stream = &pcm->stream[substream->stream];
0249     snd_hda_codec_cleanup(&hda_pvt->codec, hda_stream, substream);
0250 
0251     return 0;
0252 }
0253 
0254 static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream,
0255                 struct snd_soc_dai *dai)
0256 {
0257     struct snd_soc_component *component = dai->component;
0258     struct hda_pcm_stream *hda_stream;
0259     struct hdac_hda_priv *hda_pvt;
0260     struct hdac_device *hdev;
0261     unsigned int format_val;
0262     struct hda_pcm *pcm;
0263     unsigned int stream;
0264     int ret = 0;
0265 
0266     hda_pvt = snd_soc_component_get_drvdata(component);
0267     hdev = &hda_pvt->codec.core;
0268     pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai);
0269     if (!pcm)
0270         return -EINVAL;
0271 
0272     hda_stream = &pcm->stream[substream->stream];
0273 
0274     stream = hda_pvt->pcm[dai->id].stream_tag[substream->stream];
0275     format_val = hda_pvt->pcm[dai->id].format_val[substream->stream];
0276 
0277     ret = snd_hda_codec_prepare(&hda_pvt->codec, hda_stream,
0278                     stream, format_val, substream);
0279     if (ret < 0)
0280         dev_err(&hdev->dev, "codec prepare failed %d\n", ret);
0281 
0282     return ret;
0283 }
0284 
0285 static int hdac_hda_dai_open(struct snd_pcm_substream *substream,
0286                  struct snd_soc_dai *dai)
0287 {
0288     struct snd_soc_component *component = dai->component;
0289     struct hdac_hda_priv *hda_pvt;
0290     struct hda_pcm_stream *hda_stream;
0291     struct hda_pcm *pcm;
0292 
0293     hda_pvt = snd_soc_component_get_drvdata(component);
0294     pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai);
0295     if (!pcm)
0296         return -EINVAL;
0297 
0298     snd_hda_codec_pcm_get(pcm);
0299 
0300     hda_stream = &pcm->stream[substream->stream];
0301 
0302     return hda_stream->ops.open(hda_stream, &hda_pvt->codec, substream);
0303 }
0304 
0305 static void hdac_hda_dai_close(struct snd_pcm_substream *substream,
0306                    struct snd_soc_dai *dai)
0307 {
0308     struct snd_soc_component *component = dai->component;
0309     struct hdac_hda_priv *hda_pvt;
0310     struct hda_pcm_stream *hda_stream;
0311     struct hda_pcm *pcm;
0312 
0313     hda_pvt = snd_soc_component_get_drvdata(component);
0314     pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai);
0315     if (!pcm)
0316         return;
0317 
0318     hda_stream = &pcm->stream[substream->stream];
0319 
0320     hda_stream->ops.close(hda_stream, &hda_pvt->codec, substream);
0321 
0322     snd_hda_codec_pcm_put(pcm);
0323 }
0324 
0325 static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt,
0326                          struct snd_soc_dai *dai)
0327 {
0328     struct hda_codec *hcodec = &hda_pvt->codec;
0329     struct hda_pcm *cpcm;
0330     const char *pcm_name;
0331 
0332     /*
0333      * map DAI ID to the closest matching PCM name, using the naming
0334      * scheme used by hda-codec snd_hda_gen_build_pcms() and for
0335      * HDMI in hda_codec patch_hdmi.c)
0336      */
0337 
0338     switch (dai->id) {
0339     case HDAC_ANALOG_DAI_ID:
0340         pcm_name = "Analog";
0341         break;
0342     case HDAC_DIGITAL_DAI_ID:
0343         pcm_name = "Digital";
0344         break;
0345     case HDAC_ALT_ANALOG_DAI_ID:
0346         pcm_name = "Alt Analog";
0347         break;
0348     case HDAC_HDMI_0_DAI_ID:
0349         pcm_name = "HDMI 0";
0350         break;
0351     case HDAC_HDMI_1_DAI_ID:
0352         pcm_name = "HDMI 1";
0353         break;
0354     case HDAC_HDMI_2_DAI_ID:
0355         pcm_name = "HDMI 2";
0356         break;
0357     case HDAC_HDMI_3_DAI_ID:
0358         pcm_name = "HDMI 3";
0359         break;
0360     default:
0361         dev_err(&hcodec->core.dev, "invalid dai id %d\n", dai->id);
0362         return NULL;
0363     }
0364 
0365     list_for_each_entry(cpcm, &hcodec->pcm_list_head, list) {
0366         if (strstr(cpcm->name, pcm_name)) {
0367             if (strcmp(pcm_name, "Analog") == 0) {
0368                 if (strstr(cpcm->name, "Alt Analog"))
0369                     continue;
0370             }
0371             return cpcm;
0372         }
0373     }
0374 
0375     dev_err(&hcodec->core.dev, "didn't find PCM for DAI %s\n", dai->name);
0376     return NULL;
0377 }
0378 
0379 static bool is_hdmi_codec(struct hda_codec *hcodec)
0380 {
0381     struct hda_pcm *cpcm;
0382 
0383     list_for_each_entry(cpcm, &hcodec->pcm_list_head, list) {
0384         if (cpcm->pcm_type == HDA_PCM_TYPE_HDMI)
0385             return true;
0386     }
0387 
0388     return false;
0389 }
0390 
0391 static int hdac_hda_codec_probe(struct snd_soc_component *component)
0392 {
0393     struct hdac_hda_priv *hda_pvt =
0394             snd_soc_component_get_drvdata(component);
0395     struct snd_soc_dapm_context *dapm =
0396             snd_soc_component_get_dapm(component);
0397     struct hdac_device *hdev = &hda_pvt->codec.core;
0398     struct hda_codec *hcodec = &hda_pvt->codec;
0399     struct hdac_ext_link *hlink;
0400     hda_codec_patch_t patch;
0401     int ret;
0402 
0403     hlink = snd_hdac_ext_bus_get_link(hdev->bus, dev_name(&hdev->dev));
0404     if (!hlink) {
0405         dev_err(&hdev->dev, "hdac link not found\n");
0406         return -EIO;
0407     }
0408 
0409     snd_hdac_ext_bus_link_get(hdev->bus, hlink);
0410 
0411     /*
0412      * Ensure any HDA display is powered at codec probe.
0413      * After snd_hda_codec_device_new(), display power is
0414      * managed by runtime PM.
0415      */
0416     if (hda_pvt->need_display_power)
0417         snd_hdac_display_power(hdev->bus,
0418                        HDA_CODEC_IDX_CONTROLLER, true);
0419 
0420     ret = snd_hda_codec_device_new(hcodec->bus, component->card->snd_card,
0421                        hdev->addr, hcodec, true);
0422     if (ret < 0) {
0423         dev_err(&hdev->dev, "failed to create hda codec %d\n", ret);
0424         goto error_no_pm;
0425     }
0426     /*
0427      * Overwrite type to HDA_DEV_ASOC since it is a ASoC driver
0428      * hda_codec.c will check this flag to determine if unregister
0429      * device is needed.
0430      */
0431     hdev->type = HDA_DEV_ASOC;
0432 
0433     /*
0434      * snd_hda_codec_device_new decrements the usage count so call get pm
0435      * else the device will be powered off
0436      */
0437     pm_runtime_get_noresume(&hdev->dev);
0438 
0439     hcodec->bus->card = dapm->card->snd_card;
0440 
0441     ret = snd_hda_codec_set_name(hcodec, hcodec->preset->name);
0442     if (ret < 0) {
0443         dev_err(&hdev->dev, "name failed %s\n", hcodec->preset->name);
0444         goto error_pm;
0445     }
0446 
0447     ret = snd_hdac_regmap_init(&hcodec->core);
0448     if (ret < 0) {
0449         dev_err(&hdev->dev, "regmap init failed\n");
0450         goto error_pm;
0451     }
0452 
0453     patch = (hda_codec_patch_t)hcodec->preset->driver_data;
0454     if (patch) {
0455         ret = patch(hcodec);
0456         if (ret < 0) {
0457             dev_err(&hdev->dev, "patch failed %d\n", ret);
0458             goto error_regmap;
0459         }
0460     } else {
0461         dev_dbg(&hdev->dev, "no patch file found\n");
0462     }
0463 
0464     /* configure codec for 1:1 PCM:DAI mapping */
0465     hcodec->mst_no_extra_pcms = 1;
0466 
0467     ret = snd_hda_codec_parse_pcms(hcodec);
0468     if (ret < 0) {
0469         dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret);
0470         goto error_patch;
0471     }
0472 
0473     /* HDMI controls need to be created in machine drivers */
0474     if (!is_hdmi_codec(hcodec)) {
0475         ret = snd_hda_codec_build_controls(hcodec);
0476         if (ret < 0) {
0477             dev_err(&hdev->dev, "unable to create controls %d\n",
0478                 ret);
0479             goto error_patch;
0480         }
0481     }
0482 
0483     hcodec->core.lazy_cache = true;
0484 
0485     if (hda_pvt->need_display_power)
0486         snd_hdac_display_power(hdev->bus,
0487                        HDA_CODEC_IDX_CONTROLLER, false);
0488 
0489     /* match for forbid call in snd_hda_codec_device_new() */
0490     pm_runtime_allow(&hdev->dev);
0491 
0492     /*
0493      * hdac_device core already sets the state to active and calls
0494      * get_noresume. So enable runtime and set the device to suspend.
0495      * pm_runtime_enable is also called during codec registeration
0496      */
0497     pm_runtime_put(&hdev->dev);
0498     pm_runtime_suspend(&hdev->dev);
0499 
0500     return 0;
0501 
0502 error_patch:
0503     if (hcodec->patch_ops.free)
0504         hcodec->patch_ops.free(hcodec);
0505 error_regmap:
0506     snd_hdac_regmap_exit(hdev);
0507 error_pm:
0508     pm_runtime_put(&hdev->dev);
0509 error_no_pm:
0510     snd_hdac_ext_bus_link_put(hdev->bus, hlink);
0511     return ret;
0512 }
0513 
0514 static void hdac_hda_codec_remove(struct snd_soc_component *component)
0515 {
0516     struct hdac_hda_priv *hda_pvt =
0517               snd_soc_component_get_drvdata(component);
0518     struct hdac_device *hdev = &hda_pvt->codec.core;
0519     struct hda_codec *codec = &hda_pvt->codec;
0520     struct hdac_ext_link *hlink = NULL;
0521 
0522     hlink = snd_hdac_ext_bus_get_link(hdev->bus, dev_name(&hdev->dev));
0523     if (!hlink) {
0524         dev_err(&hdev->dev, "hdac link not found\n");
0525         return;
0526     }
0527 
0528     pm_runtime_disable(&hdev->dev);
0529     snd_hdac_ext_bus_link_put(hdev->bus, hlink);
0530 
0531     if (codec->patch_ops.free)
0532         codec->patch_ops.free(codec);
0533 
0534     snd_hda_codec_cleanup_for_unbind(codec);
0535 }
0536 
0537 static const struct snd_soc_dapm_route hdac_hda_dapm_routes[] = {
0538     {"AIF1TX", NULL, "Codec Input Pin1"},
0539     {"AIF2TX", NULL, "Codec Input Pin2"},
0540     {"AIF3TX", NULL, "Codec Input Pin3"},
0541 
0542     {"Codec Output Pin1", NULL, "AIF1RX"},
0543     {"Codec Output Pin2", NULL, "AIF2RX"},
0544     {"Codec Output Pin3", NULL, "AIF3RX"},
0545 };
0546 
0547 static const struct snd_soc_dapm_widget hdac_hda_dapm_widgets[] = {
0548     /* Audio Interface */
0549     SND_SOC_DAPM_AIF_IN("AIF1RX", "Analog Codec Playback", 0,
0550                 SND_SOC_NOPM, 0, 0),
0551     SND_SOC_DAPM_AIF_IN("AIF2RX", "Digital Codec Playback", 0,
0552                 SND_SOC_NOPM, 0, 0),
0553     SND_SOC_DAPM_AIF_IN("AIF3RX", "Alt Analog Codec Playback", 0,
0554                 SND_SOC_NOPM, 0, 0),
0555     SND_SOC_DAPM_AIF_OUT("AIF1TX", "Analog Codec Capture", 0,
0556                  SND_SOC_NOPM, 0, 0),
0557     SND_SOC_DAPM_AIF_OUT("AIF2TX", "Digital Codec Capture", 0,
0558                  SND_SOC_NOPM, 0, 0),
0559     SND_SOC_DAPM_AIF_OUT("AIF3TX", "Alt Analog Codec Capture", 0,
0560                  SND_SOC_NOPM, 0, 0),
0561 
0562     /* Input Pins */
0563     SND_SOC_DAPM_INPUT("Codec Input Pin1"),
0564     SND_SOC_DAPM_INPUT("Codec Input Pin2"),
0565     SND_SOC_DAPM_INPUT("Codec Input Pin3"),
0566 
0567     /* Output Pins */
0568     SND_SOC_DAPM_OUTPUT("Codec Output Pin1"),
0569     SND_SOC_DAPM_OUTPUT("Codec Output Pin2"),
0570     SND_SOC_DAPM_OUTPUT("Codec Output Pin3"),
0571 };
0572 
0573 static const struct snd_soc_component_driver hdac_hda_codec = {
0574     .probe          = hdac_hda_codec_probe,
0575     .remove         = hdac_hda_codec_remove,
0576     .dapm_widgets       = hdac_hda_dapm_widgets,
0577     .num_dapm_widgets   = ARRAY_SIZE(hdac_hda_dapm_widgets),
0578     .dapm_routes        = hdac_hda_dapm_routes,
0579     .num_dapm_routes    = ARRAY_SIZE(hdac_hda_dapm_routes),
0580     .idle_bias_on       = false,
0581     .endianness     = 1,
0582 };
0583 
0584 static int hdac_hda_dev_probe(struct hdac_device *hdev)
0585 {
0586     struct hdac_ext_link *hlink;
0587     struct hdac_hda_priv *hda_pvt;
0588     int ret;
0589 
0590     /* hold the ref while we probe */
0591     hlink = snd_hdac_ext_bus_get_link(hdev->bus, dev_name(&hdev->dev));
0592     if (!hlink) {
0593         dev_err(&hdev->dev, "hdac link not found\n");
0594         return -EIO;
0595     }
0596     snd_hdac_ext_bus_link_get(hdev->bus, hlink);
0597 
0598     hda_pvt = hdac_to_hda_priv(hdev);
0599     if (!hda_pvt)
0600         return -ENOMEM;
0601 
0602     /* ASoC specific initialization */
0603     ret = devm_snd_soc_register_component(&hdev->dev,
0604                      &hdac_hda_codec, hdac_hda_dais,
0605                      ARRAY_SIZE(hdac_hda_dais));
0606     if (ret < 0) {
0607         dev_err(&hdev->dev, "failed to register HDA codec %d\n", ret);
0608         return ret;
0609     }
0610 
0611     dev_set_drvdata(&hdev->dev, hda_pvt);
0612     snd_hdac_ext_bus_link_put(hdev->bus, hlink);
0613 
0614     return ret;
0615 }
0616 
0617 static int hdac_hda_dev_remove(struct hdac_device *hdev)
0618 {
0619     /*
0620      * Resources are freed in hdac_hda_codec_remove(). This
0621      * function is kept to keep hda_codec_driver_remove() happy.
0622      */
0623     return 0;
0624 }
0625 
0626 static struct hdac_ext_bus_ops hdac_ops = {
0627     .hdev_attach = hdac_hda_dev_probe,
0628     .hdev_detach = hdac_hda_dev_remove,
0629 };
0630 
0631 struct hdac_ext_bus_ops *snd_soc_hdac_hda_get_ops(void)
0632 {
0633     return &hdac_ops;
0634 }
0635 EXPORT_SYMBOL_GPL(snd_soc_hdac_hda_get_ops);
0636 
0637 MODULE_LICENSE("GPL v2");
0638 MODULE_DESCRIPTION("ASoC Extensions for legacy HDA Drivers");
0639 MODULE_AUTHOR("Rakesh Ughreja<rakesh.a.ughreja@intel.com>");