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 static inline bool avs_mach_singular_ssp(struct snd_soc_acpi_mach *mach) 15 { 16 return hweight_long(mach->mach_params.i2s_link_mask) == 1; 17 } 18 19 static inline u32 avs_mach_ssp_port(struct snd_soc_acpi_mach *mach) 20 { 21 return __ffs(mach->mach_params.i2s_link_mask); 22 } 23 24 static inline bool avs_mach_singular_tdm(struct snd_soc_acpi_mach *mach, u32 port) 25 { 26 unsigned long *tdms = mach->pdata; 27 28 return !tdms || (hweight_long(tdms[port]) == 1); 29 } 30 31 static inline u32 avs_mach_ssp_tdm(struct snd_soc_acpi_mach *mach, u32 port) 32 { 33 unsigned long *tdms = mach->pdata; 34 35 return tdms ? __ffs(tdms[port]) : 0; 36 } 37 38 static inline int avs_mach_get_ssp_tdm(struct device *dev, struct snd_soc_acpi_mach *mach, 39 int *ssp_port, int *tdm_slot) 40 { 41 int port; 42 43 if (!avs_mach_singular_ssp(mach)) { 44 dev_err(dev, "Invalid SSP configuration\n"); 45 return -EINVAL; 46 } 47 port = avs_mach_ssp_port(mach); 48 49 if (!avs_mach_singular_tdm(mach, port)) { 50 dev_err(dev, "Invalid TDM configuration\n"); 51 return -EINVAL; 52 } 53 *ssp_port = port; 54 *tdm_slot = avs_mach_ssp_tdm(mach, *ssp_port); 55 56 return 0; 57 } 58 59 /* 60 * Macro to easily generate format strings 61 */ 62 #define AVS_STRING_FMT(prefix, suffix, ssp, tdm) \ 63 (tdm) ? prefix "%d:%d" suffix : prefix "%d" suffix, (ssp), (tdm) 64 65 #endif 66