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
hda_codec_dai_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)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
hda_codec_dai_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)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
hda_codec_dai_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)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
hda_codec_dai_prepare(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)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