1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Copyright(c) 2021-2022 Intel Corporation. All rights reserved. 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 int ret; 80 81 codec = dev_to_hda_codec(dai->dev); 82 stream = substream->runtime->private_data; 83 stream_info = snd_soc_dai_get_dma_data(dai, substream); 84 format = snd_hdac_calc_stream_format(runtime->rate, runtime->channels, runtime->format, 85 runtime->sample_bits, 0); 86 87 ret = snd_hda_codec_prepare(codec, stream_info, stream->stream_tag, format, substream); 88 if (ret < 0) { 89 dev_err(dai->dev, "codec prepare failed: %d\n", ret); 90 return ret; 91 } 92 93 return 0; 94 } 95 96 const struct snd_soc_dai_ops snd_soc_hda_codec_dai_ops = { 97 .startup = hda_codec_dai_startup, 98 .shutdown = hda_codec_dai_shutdown, 99 .hw_free = hda_codec_dai_hw_free, 100 .prepare = hda_codec_dai_prepare, 101 }; 102 EXPORT_SYMBOL_GPL(snd_soc_hda_codec_dai_ops); 103