123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- // SPDX-License-Identifier: GPL-2.0
- //
- // audio-graph-card2-custom-sample.c
- //
- // Copyright (C) 2020 Renesas Electronics Corp.
- // Copyright (C) 2020 Kuninori Morimoto <[email protected]>
- //
- #include <linux/module.h>
- #include <linux/of_gpio.h>
- #include <linux/platform_device.h>
- #include <sound/graph_card.h>
- /*
- * Custom driver can have own priv
- * which includes asoc_simple_priv.
- */
- struct custom_priv {
- struct asoc_simple_priv simple_priv;
- /* custom driver's own params */
- int custom_params;
- };
- /* You can get custom_priv from simple_priv */
- #define simple_to_custom(simple) container_of((simple), struct custom_priv, simple_priv)
- static int custom_card_probe(struct snd_soc_card *card)
- {
- struct asoc_simple_priv *simple_priv = snd_soc_card_get_drvdata(card);
- struct custom_priv *custom_priv = simple_to_custom(simple_priv);
- struct device *dev = simple_priv_to_dev(simple_priv);
- dev_info(dev, "custom probe\n");
- custom_priv->custom_params = 1;
- /* you can use generic probe function */
- return asoc_graph_card_probe(card);
- }
- static int custom_hook_pre(struct asoc_simple_priv *priv)
- {
- struct device *dev = simple_priv_to_dev(priv);
- /* You can custom before parsing */
- dev_info(dev, "hook : %s\n", __func__);
- return 0;
- }
- static int custom_hook_post(struct asoc_simple_priv *priv)
- {
- struct device *dev = simple_priv_to_dev(priv);
- struct snd_soc_card *card;
- /* You can custom after parsing */
- dev_info(dev, "hook : %s\n", __func__);
- /* overwrite .probe sample */
- card = simple_priv_to_card(priv);
- card->probe = custom_card_probe;
- return 0;
- }
- static int custom_normal(struct asoc_simple_priv *priv,
- struct device_node *lnk,
- struct link_info *li)
- {
- struct device *dev = simple_priv_to_dev(priv);
- /*
- * You can custom Normal parsing
- * before/affter audio_graph2_link_normal()
- */
- dev_info(dev, "hook : %s\n", __func__);
- return audio_graph2_link_normal(priv, lnk, li);
- }
- static int custom_dpcm(struct asoc_simple_priv *priv,
- struct device_node *lnk,
- struct link_info *li)
- {
- struct device *dev = simple_priv_to_dev(priv);
- /*
- * You can custom DPCM parsing
- * before/affter audio_graph2_link_dpcm()
- */
- dev_info(dev, "hook : %s\n", __func__);
- return audio_graph2_link_dpcm(priv, lnk, li);
- }
- static int custom_c2c(struct asoc_simple_priv *priv,
- struct device_node *lnk,
- struct link_info *li)
- {
- struct device *dev = simple_priv_to_dev(priv);
- /*
- * You can custom Codec2Codec parsing
- * before/affter audio_graph2_link_c2c()
- */
- dev_info(dev, "hook : %s\n", __func__);
- return audio_graph2_link_c2c(priv, lnk, li);
- }
- /*
- * audio-graph-card2 has many hooks for your customizing.
- */
- static struct graph2_custom_hooks custom_hooks = {
- .hook_pre = custom_hook_pre,
- .hook_post = custom_hook_post,
- .custom_normal = custom_normal,
- .custom_dpcm = custom_dpcm,
- .custom_c2c = custom_c2c,
- };
- static int custom_startup(struct snd_pcm_substream *substream)
- {
- struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
- struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
- struct device *dev = simple_priv_to_dev(priv);
- dev_info(dev, "custom startup\n");
- return asoc_simple_startup(substream);
- }
- /* You can use custom ops */
- static const struct snd_soc_ops custom_ops = {
- .startup = custom_startup,
- .shutdown = asoc_simple_shutdown,
- .hw_params = asoc_simple_hw_params,
- };
- static int custom_probe(struct platform_device *pdev)
- {
- struct custom_priv *custom_priv;
- struct asoc_simple_priv *simple_priv;
- struct device *dev = &pdev->dev;
- int ret;
- custom_priv = devm_kzalloc(dev, sizeof(*custom_priv), GFP_KERNEL);
- if (!custom_priv)
- return -ENOMEM;
- simple_priv = &custom_priv->simple_priv;
- simple_priv->ops = &custom_ops; /* customize dai_link ops */
- /* use audio-graph-card2 parsing with own custom hooks */
- ret = audio_graph2_parse_of(simple_priv, dev, &custom_hooks);
- if (ret < 0)
- return ret;
- /* customize more if needed */
- return 0;
- }
- static const struct of_device_id custom_of_match[] = {
- { .compatible = "audio-graph-card2-custom-sample", },
- {},
- };
- MODULE_DEVICE_TABLE(of, custom_of_match);
- static struct platform_driver custom_card = {
- .driver = {
- .name = "audio-graph-card2-custom-sample",
- .of_match_table = custom_of_match,
- },
- .probe = custom_probe,
- .remove = asoc_simple_remove,
- };
- module_platform_driver(custom_card);
- MODULE_ALIAS("platform:asoc-audio-graph-card2-custom-sample");
- MODULE_LICENSE("GPL v2");
- MODULE_DESCRIPTION("ASoC Audio Graph Card2 Custom Sample");
- MODULE_AUTHOR("Kuninori Morimoto <[email protected]>");
|