Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/mediatek/mt8173/mt8173-max98090.c
26488 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* mt8173-max98090.c -- MT8173 MAX98090 ALSA SoC machine driver
4
*
5
* Copyright (c) 2015 MediaTek Inc.
6
* Author: Koro Chen <[email protected]>
7
*/
8
9
#include <linux/module.h>
10
#include <sound/soc.h>
11
#include <sound/jack.h>
12
#include "../../codecs/max98090.h"
13
14
static struct snd_soc_jack mt8173_max98090_jack;
15
16
static struct snd_soc_jack_pin mt8173_max98090_jack_pins[] = {
17
{
18
.pin = "Headphone",
19
.mask = SND_JACK_HEADPHONE,
20
},
21
{
22
.pin = "Headset Mic",
23
.mask = SND_JACK_MICROPHONE,
24
},
25
};
26
27
static const struct snd_soc_dapm_widget mt8173_max98090_widgets[] = {
28
SND_SOC_DAPM_SPK("Speaker", NULL),
29
SND_SOC_DAPM_MIC("Int Mic", NULL),
30
SND_SOC_DAPM_HP("Headphone", NULL),
31
SND_SOC_DAPM_MIC("Headset Mic", NULL),
32
};
33
34
static const struct snd_soc_dapm_route mt8173_max98090_routes[] = {
35
{"Speaker", NULL, "SPKL"},
36
{"Speaker", NULL, "SPKR"},
37
{"DMICL", NULL, "Int Mic"},
38
{"Headphone", NULL, "HPL"},
39
{"Headphone", NULL, "HPR"},
40
{"Headset Mic", NULL, "MICBIAS"},
41
{"IN34", NULL, "Headset Mic"},
42
};
43
44
static const struct snd_kcontrol_new mt8173_max98090_controls[] = {
45
SOC_DAPM_PIN_SWITCH("Speaker"),
46
SOC_DAPM_PIN_SWITCH("Int Mic"),
47
SOC_DAPM_PIN_SWITCH("Headphone"),
48
SOC_DAPM_PIN_SWITCH("Headset Mic"),
49
};
50
51
static int mt8173_max98090_hw_params(struct snd_pcm_substream *substream,
52
struct snd_pcm_hw_params *params)
53
{
54
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
55
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
56
57
return snd_soc_dai_set_sysclk(codec_dai, 0, params_rate(params) * 256,
58
SND_SOC_CLOCK_IN);
59
}
60
61
static const struct snd_soc_ops mt8173_max98090_ops = {
62
.hw_params = mt8173_max98090_hw_params,
63
};
64
65
static int mt8173_max98090_init(struct snd_soc_pcm_runtime *runtime)
66
{
67
int ret;
68
struct snd_soc_card *card = runtime->card;
69
struct snd_soc_component *component = snd_soc_rtd_to_codec(runtime, 0)->component;
70
71
/* enable jack detection */
72
ret = snd_soc_card_jack_new_pins(card, "Headphone", SND_JACK_HEADSET,
73
&mt8173_max98090_jack,
74
mt8173_max98090_jack_pins,
75
ARRAY_SIZE(mt8173_max98090_jack_pins));
76
if (ret) {
77
dev_err(card->dev, "Can't create a new Jack %d\n", ret);
78
return ret;
79
}
80
81
return max98090_mic_detect(component, &mt8173_max98090_jack);
82
}
83
84
SND_SOC_DAILINK_DEFS(playback,
85
DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
86
DAILINK_COMP_ARRAY(COMP_DUMMY()),
87
DAILINK_COMP_ARRAY(COMP_EMPTY()));
88
89
SND_SOC_DAILINK_DEFS(capture,
90
DAILINK_COMP_ARRAY(COMP_CPU("VUL")),
91
DAILINK_COMP_ARRAY(COMP_DUMMY()),
92
DAILINK_COMP_ARRAY(COMP_EMPTY()));
93
94
SND_SOC_DAILINK_DEFS(hifi,
95
DAILINK_COMP_ARRAY(COMP_CPU("I2S")),
96
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),
97
DAILINK_COMP_ARRAY(COMP_EMPTY()));
98
99
/* Digital audio interface glue - connects codec <---> CPU */
100
static struct snd_soc_dai_link mt8173_max98090_dais[] = {
101
/* Front End DAI links */
102
{
103
.name = "MAX98090 Playback",
104
.stream_name = "MAX98090 Playback",
105
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
106
.dynamic = 1,
107
.playback_only = 1,
108
SND_SOC_DAILINK_REG(playback),
109
},
110
{
111
.name = "MAX98090 Capture",
112
.stream_name = "MAX98090 Capture",
113
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
114
.dynamic = 1,
115
.capture_only = 1,
116
SND_SOC_DAILINK_REG(capture),
117
},
118
/* Back End DAI links */
119
{
120
.name = "Codec",
121
.no_pcm = 1,
122
.init = mt8173_max98090_init,
123
.ops = &mt8173_max98090_ops,
124
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
125
SND_SOC_DAIFMT_CBC_CFC,
126
SND_SOC_DAILINK_REG(hifi),
127
},
128
};
129
130
static struct snd_soc_card mt8173_max98090_card = {
131
.name = "mt8173-max98090",
132
.owner = THIS_MODULE,
133
.dai_link = mt8173_max98090_dais,
134
.num_links = ARRAY_SIZE(mt8173_max98090_dais),
135
.controls = mt8173_max98090_controls,
136
.num_controls = ARRAY_SIZE(mt8173_max98090_controls),
137
.dapm_widgets = mt8173_max98090_widgets,
138
.num_dapm_widgets = ARRAY_SIZE(mt8173_max98090_widgets),
139
.dapm_routes = mt8173_max98090_routes,
140
.num_dapm_routes = ARRAY_SIZE(mt8173_max98090_routes),
141
};
142
143
static int mt8173_max98090_dev_probe(struct platform_device *pdev)
144
{
145
struct snd_soc_card *card = &mt8173_max98090_card;
146
struct device_node *codec_node, *platform_node;
147
struct snd_soc_dai_link *dai_link;
148
int ret, i;
149
150
platform_node = of_parse_phandle(pdev->dev.of_node,
151
"mediatek,platform", 0);
152
if (!platform_node) {
153
dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
154
return -EINVAL;
155
}
156
for_each_card_prelinks(card, i, dai_link) {
157
if (dai_link->platforms->name)
158
continue;
159
dai_link->platforms->of_node = platform_node;
160
}
161
162
codec_node = of_parse_phandle(pdev->dev.of_node,
163
"mediatek,audio-codec", 0);
164
if (!codec_node) {
165
dev_err(&pdev->dev,
166
"Property 'audio-codec' missing or invalid\n");
167
ret = -EINVAL;
168
goto put_platform_node;
169
}
170
for_each_card_prelinks(card, i, dai_link) {
171
if (dai_link->codecs->name)
172
continue;
173
dai_link->codecs->of_node = codec_node;
174
}
175
card->dev = &pdev->dev;
176
177
ret = devm_snd_soc_register_card(&pdev->dev, card);
178
179
of_node_put(codec_node);
180
181
put_platform_node:
182
of_node_put(platform_node);
183
return ret;
184
}
185
186
static const struct of_device_id mt8173_max98090_dt_match[] = {
187
{ .compatible = "mediatek,mt8173-max98090", },
188
{ }
189
};
190
MODULE_DEVICE_TABLE(of, mt8173_max98090_dt_match);
191
192
static struct platform_driver mt8173_max98090_driver = {
193
.driver = {
194
.name = "mt8173-max98090",
195
.of_match_table = mt8173_max98090_dt_match,
196
.pm = &snd_soc_pm_ops,
197
},
198
.probe = mt8173_max98090_dev_probe,
199
};
200
201
module_platform_driver(mt8173_max98090_driver);
202
203
/* Module information */
204
MODULE_DESCRIPTION("MT8173 MAX98090 ALSA SoC machine driver");
205
MODULE_AUTHOR("Koro Chen <[email protected]>");
206
MODULE_LICENSE("GPL v2");
207
MODULE_ALIAS("platform:mt8173-max98090");
208
209
210