1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Copyright(c) 2021-2022 Intel Corporation 4 // 5 // Author: Cezary Rojewski <cezary.rojewski@intel.com> 6 // 7 8 #include <sound/soc.h> 9 #include <sound/hda_codec.h> 10 #include "hda.h" 11 12 static int hda_codec_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 13 { 14 struct hda_pcm_stream *stream_info; 15 struct hda_codec *codec; 16 struct hda_pcm *pcm; 17 int ret; 18 19 codec = dev_to_hda_codec(dai->dev); 20 stream_info = snd_soc_dai_get_dma_data(dai, substream); 21 pcm = container_of(stream_info, struct hda_pcm, stream[substream->stream]); 22 23 dev_dbg(dai->dev, "open stream codec: %08x, info: %p, pcm: %p %s substream: %p\n", 24 codec->core.vendor_id, stream_info, pcm, pcm->name, substream); 25 26 snd_hda_codec_pcm_get(pcm); 27 28 ret = stream_info->ops.open(stream_info, codec, substream); 29 if (ret < 0) { 30 dev_err(dai->dev, "codec open failed: %d\n", ret); 31 snd_hda_codec_pcm_put(pcm); 32 return ret; 33 } 34 35 return 0; 36 } 37 38 static void hda_codec_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 39 { 40 struct hda_pcm_stream *stream_info; 41 struct hda_codec *codec; 42 struct hda_pcm *pcm; 43 int ret; 44 45 codec = dev_to_hda_codec(dai->dev); 46 stream_info = snd_soc_dai_get_dma_data(dai, substream); 47 pcm = container_of(stream_info, struct hda_pcm, stream[substream->stream]); 48 49 dev_dbg(dai->dev, "close stream codec: %08x, info: %p, pcm: %p %s substream: %p\n", 50 codec->core.vendor_id, stream_info, pcm, pcm->name, substream); 51 52 ret = stream_info->ops.close(stream_info, codec, substream); 53 if (ret < 0) 54 dev_err(dai->dev, "codec close failed: %d\n", ret); 55 56 snd_hda_codec_pcm_put(pcm); 57 } 58 59 static int hda_codec_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 60 { 61 struct hda_pcm_stream *stream_info; 62 struct hda_codec *codec; 63 64 codec = dev_to_hda_codec(dai->dev); 65 stream_info = snd_soc_dai_get_dma_data(dai, substream); 66 67 snd_hda_codec_cleanup(codec, stream_info, substream); 68 69 return 0; 70 } 71 72 static int hda_codec_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 73 { 74 struct snd_pcm_runtime *runtime = substream->runtime; 75 struct hda_pcm_stream *stream_info; 76 struct hdac_stream *stream; 77 struct hda_codec *codec; 78 unsigned int format; 79 unsigned int bits; 80 int ret; 81 82 codec = dev_to_hda_codec(dai->dev); 83 stream = substream->runtime->private_data; 84 stream_info = snd_soc_dai_get_dma_data(dai, substream); 85 86 bits = snd_hdac_stream_format_bits(runtime->format, runtime->subformat, 87 stream_info->maxbps); 88 format = snd_hdac_stream_format(runtime->channels, bits, runtime->rate); 89 90 ret = snd_hda_codec_prepare(codec, stream_info, stream->stream_tag, format, substream); 91 if (ret < 0) { 92 dev_err(dai->dev, "codec prepare failed: %d\n", ret); 93 return ret; 94 } 95 96 return 0; 97 } 98 99 const struct snd_soc_dai_ops snd_soc_hda_codec_dai_ops = { 100 .startup = hda_codec_dai_startup, 101 .shutdown = hda_codec_dai_shutdown, 102 .hw_free = hda_codec_dai_hw_free, 103 .prepare = hda_codec_dai_prepare, 104 }; 105 EXPORT_SYMBOL_GPL(snd_soc_hda_codec_dai_ops); 106