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 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 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