Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  1// SPDX-License-Identifier: GPL-2.0
  2//
  3// audio-graph-card2-custom-sample.c
  4//
  5// Copyright (C) 2020 Renesas Electronics Corp.
  6// Copyright (C) 2020 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
  7//
  8#include <linux/device.h>
  9#include <linux/mod_devicetable.h>
 10#include <linux/module.h>
 11#include <linux/platform_device.h>
 12#include <sound/graph_card.h>
 13
 14/*
 15 * Custom driver can have own priv
 16 * which includes simple_util_priv.
 17 */
 18struct custom_priv {
 19	struct simple_util_priv simple_priv;
 20
 21	/* custom driver's own params */
 22	int custom_params;
 23};
 24
 25/* You can get custom_priv from simple_priv */
 26#define simple_to_custom(simple) container_of((simple), struct custom_priv, simple_priv)
 27
 28static int custom_card_probe(struct snd_soc_card *card)
 29{
 30	struct simple_util_priv *simple_priv = snd_soc_card_get_drvdata(card);
 31	struct custom_priv *custom_priv = simple_to_custom(simple_priv);
 32	struct device *dev = simple_priv_to_dev(simple_priv);
 33
 34	dev_info(dev, "custom probe\n");
 35
 36	custom_priv->custom_params = 1;
 37
 38	/* you can use generic probe function */
 39	return graph_util_card_probe(card);
 40}
 41
 42static int custom_hook_pre(struct simple_util_priv *priv)
 43{
 44	struct device *dev = simple_priv_to_dev(priv);
 45
 46	/* You can custom before parsing */
 47	dev_info(dev, "hook : %s\n", __func__);
 48
 49	return 0;
 50}
 51
 52static int custom_hook_post(struct simple_util_priv *priv)
 53{
 54	struct device *dev = simple_priv_to_dev(priv);
 55	struct snd_soc_card *card;
 56
 57	/* You can custom after parsing */
 58	dev_info(dev, "hook : %s\n", __func__);
 59
 60	/* overwrite .probe sample */
 61	card = simple_priv_to_card(priv);
 62	card->probe = custom_card_probe;
 63
 64	return 0;
 65}
 66
 67static int custom_normal(struct simple_util_priv *priv,
 68			 struct device_node *lnk,
 69			 struct link_info *li)
 70{
 71	struct device *dev = simple_priv_to_dev(priv);
 72
 73	/*
 74	 * You can custom Normal parsing
 75	 * before/affter audio_graph2_link_normal()
 76	 */
 77	dev_info(dev, "hook : %s\n", __func__);
 78
 79	return audio_graph2_link_normal(priv, lnk, li);
 80}
 81
 82static int custom_dpcm(struct simple_util_priv *priv,
 83		       struct device_node *lnk,
 84		       struct link_info *li)
 85{
 86	struct device *dev = simple_priv_to_dev(priv);
 87
 88	/*
 89	 * You can custom DPCM parsing
 90	 * before/affter audio_graph2_link_dpcm()
 91	 */
 92	dev_info(dev, "hook : %s\n", __func__);
 93
 94	return audio_graph2_link_dpcm(priv, lnk, li);
 95}
 96
 97static int custom_c2c(struct simple_util_priv *priv,
 98		      struct device_node *lnk,
 99		      struct link_info *li)
100{
101	struct device *dev = simple_priv_to_dev(priv);
102
103	/*
104	 * You can custom Codec2Codec parsing
105	 * before/affter audio_graph2_link_c2c()
106	 */
107	dev_info(dev, "hook : %s\n", __func__);
108
109	return audio_graph2_link_c2c(priv, lnk, li);
110}
111
112/*
113 * audio-graph-card2 has many hooks for your customizing.
114 */
115static struct graph2_custom_hooks custom_hooks = {
116	.hook_pre	= custom_hook_pre,
117	.hook_post	= custom_hook_post,
118	.custom_normal	= custom_normal,
119	.custom_dpcm	= custom_dpcm,
120	.custom_c2c	= custom_c2c,
121};
122
123static int custom_startup(struct snd_pcm_substream *substream)
124{
125	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
126	struct simple_util_priv *priv = snd_soc_card_get_drvdata(rtd->card);
127	struct device *dev = simple_priv_to_dev(priv);
128
129	dev_info(dev, "custom startup\n");
130
131	return simple_util_startup(substream);
132}
133
134/* You can use custom ops */
135static const struct snd_soc_ops custom_ops = {
136	.startup	= custom_startup,
137	.shutdown	= simple_util_shutdown,
138	.hw_params	= simple_util_hw_params,
139};
140
141static int custom_probe(struct platform_device *pdev)
142{
143	struct custom_priv *custom_priv;
144	struct simple_util_priv *simple_priv;
145	struct device *dev = &pdev->dev;
146	int ret;
147
148	custom_priv = devm_kzalloc(dev, sizeof(*custom_priv), GFP_KERNEL);
149	if (!custom_priv)
150		return -ENOMEM;
151
152	simple_priv		= &custom_priv->simple_priv;
153	simple_priv->ops	= &custom_ops; /* customize dai_link ops */
154
155	/* "audio-graph-card2-custom-sample" is too long */
156	simple_priv->snd_card.name = "card2-custom";
157
158	/* use audio-graph-card2 parsing with own custom hooks */
159	ret = audio_graph2_parse_of(simple_priv, dev, &custom_hooks);
160	if (ret < 0)
161		return ret;
162
163	/* customize more if needed */
164
165	return 0;
166}
167
168static const struct of_device_id custom_of_match[] = {
169	{ .compatible = "audio-graph-card2-custom-sample", },
170	{},
171};
172MODULE_DEVICE_TABLE(of, custom_of_match);
173
174static struct platform_driver custom_card = {
175	.driver = {
176		.name = "audio-graph-card2-custom-sample",
177		.of_match_table = custom_of_match,
178	},
179	.probe	= custom_probe,
180	.remove = simple_util_remove,
181};
182module_platform_driver(custom_card);
183
184MODULE_ALIAS("platform:asoc-audio-graph-card2-custom-sample");
185MODULE_LICENSE("GPL v2");
186MODULE_DESCRIPTION("ASoC Audio Graph Card2 Custom Sample");
187MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");