1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright(c) 2023 Intel Corporation 4 * 5 * Authors: Cezary Rojewski <cezary.rojewski@intel.com> 6 * Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> 7 */ 8 9 #ifndef __SOUND_SOC_INTEL_AVS_UTILS_H 10 #define __SOUND_SOC_INTEL_AVS_UTILS_H 11 12 #include <sound/soc-acpi.h> 13 14 extern bool obsolete_card_names; 15 16 struct avs_mach_pdata { 17 struct hda_codec *codec; 18 unsigned long *tdms; 19 char *codec_name; /* DMIC only */ 20 21 bool obsolete_card_names; 22 }; 23 24 static inline bool avs_mach_singular_ssp(struct snd_soc_acpi_mach *mach) 25 { 26 return hweight_long(mach->mach_params.i2s_link_mask) == 1; 27 } 28 29 static inline u32 avs_mach_ssp_port(struct snd_soc_acpi_mach *mach) 30 { 31 return __ffs(mach->mach_params.i2s_link_mask); 32 } 33 34 static inline bool avs_mach_singular_tdm(struct snd_soc_acpi_mach *mach, u32 port) 35 { 36 struct avs_mach_pdata *pdata = mach->pdata; 37 unsigned long *tdms = pdata->tdms; 38 39 return !tdms || (hweight_long(tdms[port]) == 1); 40 } 41 42 static inline u32 avs_mach_ssp_tdm(struct snd_soc_acpi_mach *mach, u32 port) 43 { 44 struct avs_mach_pdata *pdata = mach->pdata; 45 unsigned long *tdms = pdata->tdms; 46 47 return tdms ? __ffs(tdms[port]) : 0; 48 } 49 50 static inline int avs_mach_get_ssp_tdm(struct device *dev, struct snd_soc_acpi_mach *mach, 51 int *ssp_port, int *tdm_slot) 52 { 53 int port; 54 55 if (!avs_mach_singular_ssp(mach)) { 56 dev_err(dev, "Invalid SSP configuration\n"); 57 return -EINVAL; 58 } 59 port = avs_mach_ssp_port(mach); 60 61 if (!avs_mach_singular_tdm(mach, port)) { 62 dev_err(dev, "Invalid TDM configuration\n"); 63 return -EINVAL; 64 } 65 *ssp_port = port; 66 *tdm_slot = avs_mach_ssp_tdm(mach, *ssp_port); 67 68 return 0; 69 } 70 71 /* 72 * Macro to easily generate format strings 73 */ 74 #define AVS_STRING_FMT(prefix, suffix, ssp, tdm) \ 75 (tdm) ? prefix "%d:%d" suffix : prefix "%d" suffix, (ssp), (tdm) 76 77 #endif 78