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