188 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// audio-graph-card2-custom-sample.c4//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 priv16 * 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 parsing75 * 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 parsing90 * 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 parsing105 * 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>");188