Re: [PATCH V3 1/9] ASoC: amd: ps: create platform devices based on acp config

From: Mukunda,Vijendar
Date: Thu Jun 08 2023 - 01:20:25 EST


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