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