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