On 07/06/23 22:17, Limonciello, Mario wrote: > > On 6/7/2023 1:35 AM, Mukunda,Vijendar wrote: >> On 06/06/23 19:30, Pierre-Louis Bossart wrote: >>> >>>> +/** >>>> + * acp_pdev_mask corresponds to platform device mask based on audio endpoint combinations. >>>> + * acp_pdev_mask will be calculated based on ACPI Scan under ACP PCI device and >>>> + * ACP PIN Configuration. >>>> + * Based acp_pdev_mask, platform devices will be created. >>>> + * Below are possible platform device combinations. >>>> + * 1) ACP PDM Controller, dmic-codec, machine driver platform device node >>>> + * 2) ACP PDM Controller , dmic-codec, SW0 SoundWire manager instance, platform device for >>>> + * SoundWire DMA driver >>>> + * 3) SW0, SW1 SoundWire manager instances, platform device for SoundWire DMA driver >>>> + * 4) ACP PDM Controller, dmic-codec, SDW0, SDW1 manager instances, platform device for >>>> + * SoundWire DMA driver >>>> + * ACP63_PDM_DEV_MASK corresponds to platform device mask for ACP PDM controller. >>>> + * ACP63_SDW_DEV_MASK corresponds to platform device mask for SDW manager instances. >>>> + * ACP63_SDW_PDM_DEV_MASK corresponds to platform device mask for ACP PDM + SDW manager combination >>>> + */ >>>> +enum acp_pdev_mask { >>>> + ACP63_PDM_DEV_MASK = 1, >>>> + ACP63_SDW_DEV_MASK, >>>> + ACP63_SDW_PDM_DEV_MASK, >>>> +}; >>> This does not look like a mask, the definitions prevent bit-wise >>> operations from happening. >>> >>> Either use BIT(0), BIT(1), BIT(2) or GENMASK(1, 0), or demote this to a >>> regular enum (e.g. pdev_config or something) >> ACP63_PDM_DEV_MASK - Will be set only PDM config is selected. >> ACP63_SDW_DEV_MASK - will be set only when SDW config is selected. >> ACP63_SDW_PDM_DEV_MASK - will be set only when ACP PDM + SDW config is selected. >> >> We have already added comments for above masks definitions in code. >> Our intention is to use it as a mask. >> We don't think it breaks anything. >> Currently, we have only one extra check for SDW case, in suspend/resume scenario. >> Based on SoundWire power mode, ACP PCI driver should invoke acp_deinit/acp_init() >> calls in suspend/resume callbacks. >> For this, we have added check for pdev_mask. If pdev_mask is set to ACP63_SDW_DEV_MASK >> (2) or ACP63_SDW_PDM_DEV_MASK(3), in this case only by checking SoundWire power mode >> invoke acp_deinit/acp_init() sequence. This is already in place. >> >> There won't be any extra checks will be added in the future. >> As per our understanding, it's good to go. >> > I think the problem is in use of the word "mask" in this context. > That usually means that you can do a bitwise operation on it. > Really it's behaving more like an "enum" does. > > In patch 9 you have the following code: > > + if (adata->pdev_mask & ACP63_SDW_DEV_MASK) { > > That's checking if bits 0 and 1 are both set. > > But if in the future a new set of hypothetical device types was introduced > that mapped out to values "4" and "5" then you might end up with matches > in the code that don't make sense. > > So it makes more sense to do one of these solutions: > > 1) rename this adev->pdev_mask to be adev->pdev_config and then in patch 9 > to use something like this: > > if (adev->pdev_config == ACP63_SDW_DEV_CONFIG) > > 2) re-assign it so each config gets a single bit and keep the patch 9 behavior. > PDM is BIT(0), SDW is BIT(1) PDM + SDW is BIT(2) etc. > > Either way that will ensure that you never have an unexpected match. > Unexpected matches can be more likely as the code base grows and it's used for > more platforms and configs. I think Mask word is created confusion here. These changes are specific to PS platform only. To avoid further confusion, we will rename the pdev_mask as pdev_config. "if (adata->pdev_mask & ACP63_SDW_DEV_MASK)" condition check can be refactored. will fix it and post V4 patch set. > >> >> >>>> + >>>> struct pdm_stream_instance { >>>> u16 num_pages; >>>> u16 channels; >>>> @@ -95,14 +144,38 @@ struct pdm_dev_data { >>>> struct snd_pcm_substream *capture_stream; >>>> }; >>>> +/** >>>> + * struct acp63_dev_data - acp pci driver context >>>> + * @acp63_base: acp mmio base >>>> + * @res: resource >>>> + * @pdev: array of child platform device node structures >>>> + * @acp_lock: used to protect acp common registers >>>> + * @sdw_fw_node: SoundWire controller fw node handle >>>> + * @pdev_mask: platform device mask >>>> + * @pdev_count: platform devices count >>>> + * @pdm_dev_index: pdm platform device index >>>> + * @sdw_manager_count: SoundWire manager instance count >>>> + * @sdw0_dev_index: SoundWire Manager-0 platform device index >>>> + * @sdw1_dev_index: SoundWire Manager-1 platform device index >>>> + * @sdw_dma_dev_index: SoundWire DMA controller platform device index >>>> + * @acp_reset: flag set to true when bus reset is applied across all >>>> + * the active SoundWire manager instances >>>> + */ >>>> + >>>> struct acp63_dev_data { >>>> void __iomem *acp63_base; >>>> struct resource *res; >>>> struct platform_device *pdev[ACP63_DEVS]; >>>> struct mutex acp_lock; /* protect shared registers */ >>>> + struct fwnode_handle *sdw_fw_node; >>>> u16 pdev_mask; >>>> u16 pdev_count; >>>> u16 pdm_dev_index; >>>> + u8 sdw_manager_count; >>>> + u16 sdw0_dev_index; >>>> + u16 sdw1_dev_index; >>>> + u16 sdw_dma_dev_index; >>>> + bool acp_reset; >>>> }; >>>> int snd_amd_acp_find_config(struct pci_dev *pci); >>>> diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c >>>> index 54752d6040d6..816c22e7f1ab 100644 >>>> --- a/sound/soc/amd/ps/pci-ps.c >>>> +++ b/sound/soc/amd/ps/pci-ps.c >>>> @@ -6,6 +6,7 @@ >>>> */ >>>> #include <linux/pci.h> >>>> +#include <linux/bitops.h> >>>> #include <linux/module.h> >>>> #include <linux/io.h> >>>> #include <linux/delay.h> >>>> @@ -15,6 +16,7 @@ >>>> #include <sound/pcm_params.h> >>>> #include <linux/pm_runtime.h> >>>> #include <linux/iopoll.h> >>>> +#include <linux/soundwire/sdw_amd.h> >>>> #include "acp63.h" >>>> @@ -119,37 +121,162 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id) >>>> return IRQ_NONE; >>>> } >>>> -static void get_acp63_device_config(u32 config, struct pci_dev *pci, >>>> - struct acp63_dev_data *acp_data) >>>> +static int sdw_amd_scan_controller(struct device *dev) >>>> +{ >>>> + struct acp63_dev_data *acp_data; >>>> + struct fwnode_handle *link; >>>> + char name[32]; >>>> + u32 sdw_manager_bitmap; >>>> + u8 count = 0; >>>> + u32 acp_sdw_power_mode = 0; >>>> + int index; >>>> + int ret; >>>> + >>>> + acp_data = dev_get_drvdata(dev); >>>> + acp_data->acp_reset = true; >>>> + /* Found controller, find links supported */ >>>> + ret = fwnode_property_read_u32_array((acp_data->sdw_fw_node), "mipi-sdw-manager-list", >>>> + &sdw_manager_bitmap, 1); >>> IIRC this is only defined in the DisCo 2.0 spec, previous editions had a >>> 'mipi-master-count'. A comment would not hurt to point to the minimal >>> DisCo spec version. >> We will add comment. >>>> + >>>> + if (ret) { >>>> + dev_err(dev, "Failed to read mipi-sdw-manager-list: %d\n", ret); >>>> + return -EINVAL; >>>> + } >>>> + count = hweight32(sdw_manager_bitmap); >>>> + /* Check count is within bounds */ >>>> + if (count > AMD_SDW_MAX_MANAGERS) { >>>> + dev_err(dev, "Manager count %d exceeds max %d\n", count, AMD_SDW_MAX_MANAGERS); >>>> + return -EINVAL; >>>> + } >>>> + >>>> + if (!count) { >>>> + dev_dbg(dev, "No SoundWire Managers detected\n"); >>>> + return -EINVAL; >>>> + } >>>> + dev_dbg(dev, "ACPI reports %d SoundWire Manager devices\n", count); >>>> + acp_data->sdw_manager_count = count; >>>> + for (index = 0; index < count; index++) { >>>> + snprintf(name, sizeof(name), "mipi-sdw-link-%d-subproperties", index); >>>> + link = fwnode_get_named_child_node(acp_data->sdw_fw_node, name); >>>> + if (!link) { >>>> + dev_err(dev, "Manager node %s not found\n", name); >>>> + return -EIO; >>>> + } >>>> + >>>> + ret = fwnode_property_read_u32(link, "amd-sdw-power-mode", &acp_sdw_power_mode); >>>> + if (ret) >>>> + return ret; >>>> + /* >>>> + * when SoundWire configuration is selected from acp pin config, >>>> + * based on manager instances count, acp init/de-init sequence should be >>>> + * executed as part of PM ops only when Bus reset is applied for the active >>>> + * SoundWire manager instances. >>>> + */ >>>> + if (acp_sdw_power_mode != AMD_SDW_POWER_OFF_MODE) { >>>> + acp_data->acp_reset = false; >>>> + return 0; >>>> + } >>>> + } >>>> + return 0; >>>> +} >>>> + >>>> +static int get_acp63_device_config(u32 config, struct pci_dev *pci, struct acp63_dev_data *acp_data) >>>> { >>>> struct acpi_device *dmic_dev; >>>> + struct acpi_device *sdw_dev; >>>> const union acpi_object *obj; >>>> bool is_dmic_dev = false; >>>> + bool is_sdw_dev = false; >>>> + int ret; >>>> dmic_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), ACP63_DMIC_ADDR, 0); >>>> if (dmic_dev) { >>>> + /* is_dmic_dev flag will be set when ACP PDM controller device exists */ >>>> if (!acpi_dev_get_property(dmic_dev, "acp-audio-device-type", >>> usually properties start with the 'mipi-' or 'vendor-' prefix. Is there >>> a missing 'amd-' here or is 'acp-' unique enough? >> It's not SoundWire related MIPI/Vendor property. >> Our BIOS changes are freeze. We can't modify this one as of this moment. >> We will consider it for next platform. > > Besides impact to BIOS it also has impact to drivers in other > operating systems as well. So changing a property name is not > something that can be taken lightly. > Agreed. > I'd also point out the use of the ACPI property is localized to > an AMD specific driver not generic code. >