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 // Copyright (c) 2024 Advanced Micro Devices, Inc. 5 6 /* 7 * soc_sdw_rt_dmic - Helpers to handle Realtek SDW DMIC 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/soc.h> 15 #include <sound/soc-acpi.h> 16 #include <sound/soc_sdw_utils.h> 17 #include <sound/sdca_function.h> 18 19 int asoc_sdw_rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) 20 { 21 struct snd_soc_card *card = rtd->card; 22 struct snd_soc_component *component; 23 struct sdw_slave *sdw_peripheral = NULL; 24 char *mic_name; 25 int rt1320_dmic_num = 0, part_id, i; 26 27 component = dai->component; 28 29 /* 30 * rt715-sdca (aka rt714) is a special case that uses different name in card->components 31 * and component->name_prefix. 32 */ 33 if (!strcmp(component->name_prefix, "rt714")) 34 mic_name = devm_kasprintf(card->dev, GFP_KERNEL, "rt715-sdca"); 35 else 36 mic_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s", component->name_prefix); 37 if (!mic_name) 38 return -ENOMEM; 39 40 /* 41 * If there is any rt1320/rt1321 DMIC belonging to this card, try to count the `cfg-mics` 42 * to be used in card->components. 43 * Note: The rt1320 drivers register the peripheral dev to component->dev, so get the 44 * sdw_peripheral from component->dev. 45 */ 46 if (is_sdw_slave(component->dev)) 47 sdw_peripheral = dev_to_sdw_dev(component->dev); 48 if (sdw_peripheral && 49 (sdw_peripheral->id.part_id == 0x1320 || sdw_peripheral->id.part_id == 0x1321)) { 50 part_id = sdw_peripheral->id.part_id; 51 /* 52 * This rtd init callback is called once, so count the rt1320/rt1321 with SDCA 53 * function SmartMic type in this card. 54 */ 55 for_each_card_components(card, component) { 56 if (!is_sdw_slave(component->dev)) 57 continue; 58 sdw_peripheral = dev_to_sdw_dev(component->dev); 59 if (sdw_peripheral->id.part_id != part_id) 60 continue; 61 for (i = 0; i < sdw_peripheral->sdca_data.num_functions; i++) { 62 if (sdw_peripheral->sdca_data.function[i].type == 63 SDCA_FUNCTION_TYPE_SMART_MIC) { 64 rt1320_dmic_num++; 65 break; 66 } 67 } 68 } 69 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 70 "%s mic:%s cfg-mics:%d", card->components, 71 mic_name, rt1320_dmic_num); 72 } else { 73 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 74 "%s mic:%s", card->components, 75 mic_name); 76 } 77 78 if (!card->components) 79 return -ENOMEM; 80 81 dev_dbg(card->dev, "card->components: %s\n", card->components); 82 83 return 0; 84 } 85 EXPORT_SYMBOL_NS(asoc_sdw_rt_dmic_rtd_init, "SND_SOC_SDW_UTILS"); 86