xref: /linux/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c (revision cdd30ebb1b9f36159d66f088b61aee264e649d7a)
1 // SPDX-License-Identifier: GPL-2.0-only
2 // This file incorporates work covered by the following copyright notice:
3 // Copyright (c) 2024 Intel Corporation.
4 
5 /*
6  *  soc_sdw_rt_mf_sdca
7  *  - Helpers to handle RT Multifunction Codec from generic machine driver
8  */
9 
10 #include <linux/device.h>
11 #include <linux/errno.h>
12 #include <linux/soundwire/sdw.h>
13 #include <linux/soundwire/sdw_type.h>
14 #include <sound/control.h>
15 #include <sound/soc.h>
16 #include <sound/soc-acpi.h>
17 #include <sound/soc-dapm.h>
18 #include <sound/soc_sdw_utils.h>
19 
20 #define CODEC_NAME_SIZE	6
21 
22 /* dapm routes for RT-SPK will be registered dynamically */
23 static const struct snd_soc_dapm_route rt712_spk_map[] = {
24 	{ "Speaker", NULL, "rt712 SPOL" },
25 	{ "Speaker", NULL, "rt712 SPOR" },
26 };
27 
28 static const struct snd_soc_dapm_route rt721_spk_map[] = {
29 	{ "Speaker", NULL, "rt721 SPK" },
30 };
31 
32 static const struct snd_soc_dapm_route rt722_spk_map[] = {
33 	{ "Speaker", NULL, "rt722 SPK" },
34 };
35 
36 /* Structure to map codec names to respective route arrays and sizes */
37 struct codec_route_map {
38 	const char *codec_name;
39 	const struct snd_soc_dapm_route *route_map;
40 	size_t route_size;
41 };
42 
43 /* Codec route maps array */
44 static const struct codec_route_map codec_routes[] = {
45 	{ "rt712", rt712_spk_map, ARRAY_SIZE(rt712_spk_map) },
46 	{ "rt721", rt721_spk_map, ARRAY_SIZE(rt721_spk_map) },
47 	{ "rt722", rt722_spk_map, ARRAY_SIZE(rt722_spk_map) },
48 };
49 
get_codec_route_map(const char * codec_name)50 static const struct codec_route_map *get_codec_route_map(const char *codec_name)
51 {
52 	for (size_t i = 0; i < ARRAY_SIZE(codec_routes); i++) {
53 		if (strcmp(codec_routes[i].codec_name, codec_name) == 0)
54 			return &codec_routes[i];
55 	}
56 	return NULL;
57 }
58 
asoc_sdw_rt_mf_sdca_spk_rtd_init(struct snd_soc_pcm_runtime * rtd,struct snd_soc_dai * dai)59 int asoc_sdw_rt_mf_sdca_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
60 {
61 	struct snd_soc_card *card = rtd->card;
62 	char codec_name[CODEC_NAME_SIZE];
63 	int ret;
64 
65 	/* acquire codec name */
66 	snprintf(codec_name, CODEC_NAME_SIZE, "%s", dai->name);
67 
68 	/* acquire corresponding route map and size */
69 	const struct codec_route_map *route_map = get_codec_route_map(codec_name);
70 
71 	if (!route_map) {
72 		dev_err(rtd->dev, "failed to get codec name and route map\n");
73 		return -EINVAL;
74 	}
75 
76 	/* Update card components */
77 	card->components = devm_kasprintf(card->dev, GFP_KERNEL,
78 					  "%s spk:%s",
79 					  card->components, codec_name);
80 	if (!card->components)
81 		return -ENOMEM;
82 
83 	/* Add routes */
84 	ret = snd_soc_dapm_add_routes(&card->dapm, route_map->route_map, route_map->route_size);
85 	if (ret)
86 		dev_err(rtd->dev, "failed to add rt sdca spk map: %d\n", ret);
87 
88 	return ret;
89 }
90 EXPORT_SYMBOL_NS(asoc_sdw_rt_mf_sdca_spk_rtd_init, "SND_SOC_SDW_UTILS");
91