File Index
Files and directories
Sign in
FILE

mt8173-max98090.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/mediatek/mt8173/mt8173-max98090.c C
  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 <koro.chen@mediatek.com>
  7 */
  8
  9#include <linux/module.h>
 10#include <sound/soc.h>
 11#include <sound/jack.h>
 12#include "../../codecs/max98090.h"
 13
 14static struct snd_soc_jack mt8173_max98090_jack;
 15
 16static 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
 27static 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
 34static 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
 44static 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
 51static 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
 61static const struct snd_soc_ops mt8173_max98090_ops = {
 62	.hw_params = mt8173_max98090_hw_params,
 63};
 64
 65static 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
 84SND_SOC_DAILINK_DEFS(playback,
 85	DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
 86	DAILINK_COMP_ARRAY(COMP_DUMMY()),
 87	DAILINK_COMP_ARRAY(COMP_EMPTY()));
 88
 89SND_SOC_DAILINK_DEFS(capture,
 90	DAILINK_COMP_ARRAY(COMP_CPU("VUL")),
 91	DAILINK_COMP_ARRAY(COMP_DUMMY()),
 92	DAILINK_COMP_ARRAY(COMP_EMPTY()));
 93
 94SND_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 */
100static 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
130static 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
143static 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
181put_platform_node:
182	of_node_put(platform_node);
183	return ret;
184}
185
186static const struct of_device_id mt8173_max98090_dt_match[] = {
187	{ .compatible = "mediatek,mt8173-max98090", },
188	{ }
189};
190MODULE_DEVICE_TABLE(of, mt8173_max98090_dt_match);
191
192static 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
201module_platform_driver(mt8173_max98090_driver);
202
203/* Module information */
204MODULE_DESCRIPTION("MT8173 MAX98090 ALSA SoC machine driver");
205MODULE_AUTHOR("Koro Chen <koro.chen@mediatek.com>");
206MODULE_LICENSE("GPL v2");
207MODULE_ALIAS("platform:mt8173-max98090");
208
~/ Read-only file preview.