Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Copyright(c) 2021-2022 Intel Corporation. All rights reserved.
0004 //
0005 // Author: Cezary Rojewski <cezary.rojewski@intel.com>
0006 //
0007 
0008 #include <sound/soc.h>
0009 #include <sound/hda_codec.h>
0010 #include "hda.h"
0011 
0012 static int hda_codec_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
0013 {
0014     struct hda_pcm_stream *stream_info;
0015     struct hda_codec *codec;
0016     struct hda_pcm *pcm;
0017     int ret;
0018 
0019     codec = dev_to_hda_codec(dai->dev);
0020     stream_info = snd_soc_dai_get_dma_data(dai, substream);
0021     pcm = container_of(stream_info, struct hda_pcm, stream[substream->stream]);
0022 
0023     dev_dbg(dai->dev, "open stream codec: %08x, info: %p, pcm: %p %s substream: %p\n",
0024         codec->core.vendor_id, stream_info, pcm, pcm->name, substream);
0025 
0026     snd_hda_codec_pcm_get(pcm);
0027 
0028     ret = stream_info->ops.open(stream_info, codec, substream);
0029     if (ret < 0) {
0030         dev_err(dai->dev, "codec open failed: %d\n", ret);
0031         snd_hda_codec_pcm_put(pcm);
0032         return ret;
0033     }
0034 
0035     return 0;
0036 }
0037 
0038 static void hda_codec_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
0039 {
0040     struct hda_pcm_stream *stream_info;
0041     struct hda_codec *codec;
0042     struct hda_pcm *pcm;
0043     int ret;
0044 
0045     codec = dev_to_hda_codec(dai->dev);
0046     stream_info = snd_soc_dai_get_dma_data(dai, substream);
0047     pcm = container_of(stream_info, struct hda_pcm, stream[substream->stream]);
0048 
0049     dev_dbg(dai->dev, "close stream codec: %08x, info: %p, pcm: %p %s substream: %p\n",
0050         codec->core.vendor_id, stream_info, pcm, pcm->name, substream);
0051 
0052     ret = stream_info->ops.close(stream_info, codec, substream);
0053     if (ret < 0)
0054         dev_err(dai->dev, "codec close failed: %d\n", ret);
0055 
0056     snd_hda_codec_pcm_put(pcm);
0057 }
0058 
0059 static int hda_codec_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
0060 {
0061     struct hda_pcm_stream *stream_info;
0062     struct hda_codec *codec;
0063 
0064     codec = dev_to_hda_codec(dai->dev);
0065     stream_info = snd_soc_dai_get_dma_data(dai, substream);
0066 
0067     snd_hda_codec_cleanup(codec, stream_info, substream);
0068 
0069     return 0;
0070 }
0071 
0072 static int hda_codec_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
0073 {
0074     struct snd_pcm_runtime *runtime = substream->runtime;
0075     struct hda_pcm_stream *stream_info;
0076     struct hdac_stream *stream;
0077     struct hda_codec *codec;
0078     unsigned int format;
0079     int ret;
0080 
0081     codec = dev_to_hda_codec(dai->dev);
0082     stream = substream->runtime->private_data;
0083     stream_info = snd_soc_dai_get_dma_data(dai, substream);
0084     format = snd_hdac_calc_stream_format(runtime->rate, runtime->channels, runtime->format,
0085                          runtime->sample_bits, 0);
0086 
0087     ret = snd_hda_codec_prepare(codec, stream_info, stream->stream_tag, format, substream);
0088     if (ret < 0) {
0089         dev_err(dai->dev, "codec prepare failed: %d\n", ret);
0090         return ret;
0091     }
0092 
0093     return 0;
0094 }
0095 
0096 const struct snd_soc_dai_ops snd_soc_hda_codec_dai_ops = {
0097     .startup = hda_codec_dai_startup,
0098     .shutdown = hda_codec_dai_shutdown,
0099     .hw_free = hda_codec_dai_hw_free,
0100     .prepare = hda_codec_dai_prepare,
0101 };
0102 EXPORT_SYMBOL_GPL(snd_soc_hda_codec_dai_ops);