xref: /linux/sound/soc/generic/audio-graph-card2-custom-sample.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
195373f36SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0
295373f36SKuninori Morimoto //
395373f36SKuninori Morimoto // audio-graph-card2-custom-sample.c
495373f36SKuninori Morimoto //
595373f36SKuninori Morimoto // Copyright (C) 2020 Renesas Electronics Corp.
695373f36SKuninori Morimoto // Copyright (C) 2020 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
795373f36SKuninori Morimoto //
87a31da79SAndy Shevchenko #include <linux/device.h>
97a31da79SAndy Shevchenko #include <linux/mod_devicetable.h>
1095373f36SKuninori Morimoto #include <linux/module.h>
1195373f36SKuninori Morimoto #include <linux/platform_device.h>
1295373f36SKuninori Morimoto #include <sound/graph_card.h>
1395373f36SKuninori Morimoto 
1495373f36SKuninori Morimoto /*
1595373f36SKuninori Morimoto  * Custom driver can have own priv
16b4b7de99SKuninori Morimoto  * which includes simple_util_priv.
1795373f36SKuninori Morimoto  */
1895373f36SKuninori Morimoto struct custom_priv {
19b4b7de99SKuninori Morimoto 	struct simple_util_priv simple_priv;
2095373f36SKuninori Morimoto 
2195373f36SKuninori Morimoto 	/* custom driver's own params */
2295373f36SKuninori Morimoto 	int custom_params;
2395373f36SKuninori Morimoto };
2495373f36SKuninori Morimoto 
2595373f36SKuninori Morimoto /* You can get custom_priv from simple_priv */
2695373f36SKuninori Morimoto #define simple_to_custom(simple) container_of((simple), struct custom_priv, simple_priv)
2795373f36SKuninori Morimoto 
custom_card_probe(struct snd_soc_card * card)2895373f36SKuninori Morimoto static int custom_card_probe(struct snd_soc_card *card)
2995373f36SKuninori Morimoto {
30b4b7de99SKuninori Morimoto 	struct simple_util_priv *simple_priv = snd_soc_card_get_drvdata(card);
3195373f36SKuninori Morimoto 	struct custom_priv *custom_priv = simple_to_custom(simple_priv);
3295373f36SKuninori Morimoto 	struct device *dev = simple_priv_to_dev(simple_priv);
3395373f36SKuninori Morimoto 
3495373f36SKuninori Morimoto 	dev_info(dev, "custom probe\n");
3595373f36SKuninori Morimoto 
3695373f36SKuninori Morimoto 	custom_priv->custom_params = 1;
3795373f36SKuninori Morimoto 
3895373f36SKuninori Morimoto 	/* you can use generic probe function */
39b4b7de99SKuninori Morimoto 	return graph_util_card_probe(card);
4095373f36SKuninori Morimoto }
4195373f36SKuninori Morimoto 
custom_hook_pre(struct simple_util_priv * priv)42b4b7de99SKuninori Morimoto static int custom_hook_pre(struct simple_util_priv *priv)
4395373f36SKuninori Morimoto {
4495373f36SKuninori Morimoto 	struct device *dev = simple_priv_to_dev(priv);
4595373f36SKuninori Morimoto 
4695373f36SKuninori Morimoto 	/* You can custom before parsing */
4795373f36SKuninori Morimoto 	dev_info(dev, "hook : %s\n", __func__);
4895373f36SKuninori Morimoto 
4995373f36SKuninori Morimoto 	return 0;
5095373f36SKuninori Morimoto }
5195373f36SKuninori Morimoto 
custom_hook_post(struct simple_util_priv * priv)52b4b7de99SKuninori Morimoto static int custom_hook_post(struct simple_util_priv *priv)
5395373f36SKuninori Morimoto {
5495373f36SKuninori Morimoto 	struct device *dev = simple_priv_to_dev(priv);
5595373f36SKuninori Morimoto 	struct snd_soc_card *card;
5695373f36SKuninori Morimoto 
5795373f36SKuninori Morimoto 	/* You can custom after parsing */
5895373f36SKuninori Morimoto 	dev_info(dev, "hook : %s\n", __func__);
5995373f36SKuninori Morimoto 
6095373f36SKuninori Morimoto 	/* overwrite .probe sample */
6195373f36SKuninori Morimoto 	card = simple_priv_to_card(priv);
6295373f36SKuninori Morimoto 	card->probe = custom_card_probe;
6395373f36SKuninori Morimoto 
6495373f36SKuninori Morimoto 	return 0;
6595373f36SKuninori Morimoto }
6695373f36SKuninori Morimoto 
custom_normal(struct simple_util_priv * priv,struct device_node * lnk,struct link_info * li)67b4b7de99SKuninori Morimoto static int custom_normal(struct simple_util_priv *priv,
6895373f36SKuninori Morimoto 			 struct device_node *lnk,
6995373f36SKuninori Morimoto 			 struct link_info *li)
7095373f36SKuninori Morimoto {
7195373f36SKuninori Morimoto 	struct device *dev = simple_priv_to_dev(priv);
7295373f36SKuninori Morimoto 
7395373f36SKuninori Morimoto 	/*
7495373f36SKuninori Morimoto 	 * You can custom Normal parsing
7595373f36SKuninori Morimoto 	 * before/affter audio_graph2_link_normal()
7695373f36SKuninori Morimoto 	 */
7795373f36SKuninori Morimoto 	dev_info(dev, "hook : %s\n", __func__);
7895373f36SKuninori Morimoto 
7995373f36SKuninori Morimoto 	return audio_graph2_link_normal(priv, lnk, li);
8095373f36SKuninori Morimoto }
8195373f36SKuninori Morimoto 
custom_dpcm(struct simple_util_priv * priv,struct device_node * lnk,struct link_info * li)82b4b7de99SKuninori Morimoto static int custom_dpcm(struct simple_util_priv *priv,
8395373f36SKuninori Morimoto 		       struct device_node *lnk,
8495373f36SKuninori Morimoto 		       struct link_info *li)
8595373f36SKuninori Morimoto {
8695373f36SKuninori Morimoto 	struct device *dev = simple_priv_to_dev(priv);
8795373f36SKuninori Morimoto 
8895373f36SKuninori Morimoto 	/*
8995373f36SKuninori Morimoto 	 * You can custom DPCM parsing
9095373f36SKuninori Morimoto 	 * before/affter audio_graph2_link_dpcm()
9195373f36SKuninori Morimoto 	 */
9295373f36SKuninori Morimoto 	dev_info(dev, "hook : %s\n", __func__);
9395373f36SKuninori Morimoto 
9495373f36SKuninori Morimoto 	return audio_graph2_link_dpcm(priv, lnk, li);
9595373f36SKuninori Morimoto }
9695373f36SKuninori Morimoto 
custom_c2c(struct simple_util_priv * priv,struct device_node * lnk,struct link_info * li)97b4b7de99SKuninori Morimoto static int custom_c2c(struct simple_util_priv *priv,
9895373f36SKuninori Morimoto 		      struct device_node *lnk,
9995373f36SKuninori Morimoto 		      struct link_info *li)
10095373f36SKuninori Morimoto {
10195373f36SKuninori Morimoto 	struct device *dev = simple_priv_to_dev(priv);
10295373f36SKuninori Morimoto 
10395373f36SKuninori Morimoto 	/*
10495373f36SKuninori Morimoto 	 * You can custom Codec2Codec parsing
10595373f36SKuninori Morimoto 	 * before/affter audio_graph2_link_c2c()
10695373f36SKuninori Morimoto 	 */
10795373f36SKuninori Morimoto 	dev_info(dev, "hook : %s\n", __func__);
10895373f36SKuninori Morimoto 
10995373f36SKuninori Morimoto 	return audio_graph2_link_c2c(priv, lnk, li);
11095373f36SKuninori Morimoto }
11195373f36SKuninori Morimoto 
11295373f36SKuninori Morimoto /*
11395373f36SKuninori Morimoto  * audio-graph-card2 has many hooks for your customizing.
11495373f36SKuninori Morimoto  */
11595373f36SKuninori Morimoto static struct graph2_custom_hooks custom_hooks = {
11695373f36SKuninori Morimoto 	.hook_pre	= custom_hook_pre,
11795373f36SKuninori Morimoto 	.hook_post	= custom_hook_post,
11895373f36SKuninori Morimoto 	.custom_normal	= custom_normal,
11995373f36SKuninori Morimoto 	.custom_dpcm	= custom_dpcm,
12095373f36SKuninori Morimoto 	.custom_c2c	= custom_c2c,
12195373f36SKuninori Morimoto };
12295373f36SKuninori Morimoto 
custom_startup(struct snd_pcm_substream * substream)12395373f36SKuninori Morimoto static int custom_startup(struct snd_pcm_substream *substream)
12495373f36SKuninori Morimoto {
125b4b7de99SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
126b4b7de99SKuninori Morimoto 	struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
12795373f36SKuninori Morimoto 	struct device *dev = simple_priv_to_dev(priv);
12895373f36SKuninori Morimoto 
12995373f36SKuninori Morimoto 	dev_info(dev, "custom startup\n");
13095373f36SKuninori Morimoto 
131b4b7de99SKuninori Morimoto 	return simple_util_startup(substream);
13295373f36SKuninori Morimoto }
13395373f36SKuninori Morimoto 
13495373f36SKuninori Morimoto /* You can use custom ops */
13595373f36SKuninori Morimoto static const struct snd_soc_ops custom_ops = {
13695373f36SKuninori Morimoto 	.startup	= custom_startup,
137b4b7de99SKuninori Morimoto 	.shutdown	= simple_util_shutdown,
138b4b7de99SKuninori Morimoto 	.hw_params	= simple_util_hw_params,
13995373f36SKuninori Morimoto };
14095373f36SKuninori Morimoto 
custom_probe(struct platform_device * pdev)14195373f36SKuninori Morimoto static int custom_probe(struct platform_device *pdev)
14295373f36SKuninori Morimoto {
14395373f36SKuninori Morimoto 	struct custom_priv *custom_priv;
144b4b7de99SKuninori Morimoto 	struct simple_util_priv *simple_priv;
14595373f36SKuninori Morimoto 	struct device *dev = &pdev->dev;
14695373f36SKuninori Morimoto 	int ret;
14795373f36SKuninori Morimoto 
14895373f36SKuninori Morimoto 	custom_priv = devm_kzalloc(dev, sizeof(*custom_priv), GFP_KERNEL);
14995373f36SKuninori Morimoto 	if (!custom_priv)
15095373f36SKuninori Morimoto 		return -ENOMEM;
15195373f36SKuninori Morimoto 
15295373f36SKuninori Morimoto 	simple_priv		= &custom_priv->simple_priv;
15395373f36SKuninori Morimoto 	simple_priv->ops	= &custom_ops; /* customize dai_link ops */
15495373f36SKuninori Morimoto 
155ad58151fSKuninori Morimoto 	/* "audio-graph-card2-custom-sample" is too long */
156ad58151fSKuninori Morimoto 	simple_priv->snd_card.name = "card2-custom";
157ad58151fSKuninori Morimoto 
15895373f36SKuninori Morimoto 	/* use audio-graph-card2 parsing with own custom hooks */
15995373f36SKuninori Morimoto 	ret = audio_graph2_parse_of(simple_priv, dev, &custom_hooks);
16095373f36SKuninori Morimoto 	if (ret < 0)
16195373f36SKuninori Morimoto 		return ret;
16295373f36SKuninori Morimoto 
16395373f36SKuninori Morimoto 	/* customize more if needed */
16495373f36SKuninori Morimoto 
16595373f36SKuninori Morimoto 	return 0;
16695373f36SKuninori Morimoto }
16795373f36SKuninori Morimoto 
16895373f36SKuninori Morimoto static const struct of_device_id custom_of_match[] = {
16995373f36SKuninori Morimoto 	{ .compatible = "audio-graph-card2-custom-sample", },
17095373f36SKuninori Morimoto 	{},
17195373f36SKuninori Morimoto };
17295373f36SKuninori Morimoto MODULE_DEVICE_TABLE(of, custom_of_match);
17395373f36SKuninori Morimoto 
17495373f36SKuninori Morimoto static struct platform_driver custom_card = {
17595373f36SKuninori Morimoto 	.driver = {
17695373f36SKuninori Morimoto 		.name = "audio-graph-card2-custom-sample",
17795373f36SKuninori Morimoto 		.of_match_table = custom_of_match,
17895373f36SKuninori Morimoto 	},
17995373f36SKuninori Morimoto 	.probe	= custom_probe,
180*130af75bSUwe Kleine-König 	.remove = simple_util_remove,
18195373f36SKuninori Morimoto };
18295373f36SKuninori Morimoto module_platform_driver(custom_card);
18395373f36SKuninori Morimoto 
18495373f36SKuninori Morimoto MODULE_ALIAS("platform:asoc-audio-graph-card2-custom-sample");
18595373f36SKuninori Morimoto MODULE_LICENSE("GPL v2");
18695373f36SKuninori Morimoto MODULE_DESCRIPTION("ASoC Audio Graph Card2 Custom Sample");
18795373f36SKuninori Morimoto MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
188