mbox series

[v4,00/17] ASoC: Intel: AVS - Audio DSP for cAVS

Message ID 20220309204029.89040-1-cezary.rojewski@intel.com
Headers show
Series ASoC: Intel: AVS - Audio DSP for cAVS | expand

Message

Cezary Rojewski March 9, 2022, 8:40 p.m. UTC
A continuation of cleanup work of Intel SST solutions found in
sound/soc/intel/. With two major chapters released last year catpt [1]
and removal of haswell solution [2], time has come for Skylake-driver.

Througout 2019, 2020 and 2021 Skylake-driver has had many fixes applied
and even attempts of refactors as seen in fundamental overhaul [3], IPC
flow adjustments [4] and LARGE_CONFIG overhaul [5] series.
Unfortunately, story repeats itself - problems are found within the core
of a driver. Painting it with different colors does not change the fact
that is it still a house of cards. As changes needed to address those
issues would make Skylake solution incompatible with its previous
revisions, a decision has been made to provide a new solution instead.
In time it would deprecate and replace Skylake-driver.

That solution has been called AVS - from AudioDSP architecture name:
Audio-Voice-Speech. It is meant to provide support for the exact same
range of platforms as its predecessor: SKL, KBL, AML and APL.

Note: this series is dependent upon HDA-series [6] which exposes several
codec-organization functions allowing for reduced code size on
avs-driver side.

Note: this series does not add fully functional driver as its size would
get out of control. Here, focus is put on adding IPC protocol and code
loading code.


Changes v3 -> v4:
- noted the limitations of LARGE_CONFIG_GET handler and dropped
  non-inclusive wording as requested by Pierre and Ranjani
- code loading flow now verifies if power downing non-MAIN_CORE fails
- commented kfree() usage in FW_CONFIG and HW_CONFIG getters


Changes v2 -> v3:
- fixed variable initialization errors mentioned by sparse


Changes v1 -> v2:
Almost all updates here are thanks to feedback from Pierre.

- several comments and few kernel-docs have been added in areas which
  felt more or less unclear
- avs_ipc_wait_busy_completion() now spins up to 'repeats_left' number
  of times before giving up
- 'adsp_ba' field of struct avs_dev has been renamed to 'dsp_ba'
- 'dops' field of struct avs_spec has been renamed to 'dsp_ops'
- IPC abstraction has been simplified: SKL_ADSP_REG_HIP* regs are used
  directly
- fixed allnoconfig with AVS enabled compilation issues
- fixed code loading error paths: previously requested firmware is now
  released before function return to the caller
- code and function arguments tied to D0IX support have been removed
  from this patchset and will be part of followup series adding that
  feature instead
- enriched dev_err() messages in avs_dsp_get_core() and
  avs_dsp_put_core()
- numerous wording fixes used in power/reset/stall DSP operations


Changes RFC v1 [7]: -> v1:
- separated HDA codec-organization patches, path and topology handling,
  PCM and complementary features such as recovery from this series to
  ease the review process
- fixed EXPORT_SYMBOL_GPL for exported members of ASoC framework
- result of stall() is now checked when sending ROM message
- result of snd_hdac_ext_stream_set_spib() is now checked when loading
  basefw
- if basefw is not ready, notification processing is now skipped
- documented several topology parsing helpers


Changes [internal] RFC v2 -> [public] RFC v1:
- dropped any sysfs related changes from this series, moved to follow up
  one
- dropped entire subscription-mechanism found in ipc.c. Handlers that
  are delegated to service certain firmware notifications are now called
  directly
- fixed kernel doc for snd_soc_dapm_new_dai_widgets() as reported by ikp
- prefixed snd_hda_codec_device_init() as suggested by Amadeo
- improved comments for d0ix transitions for APL-based platforms as
  suggested by Pierre
- a ton of spelling related fixes in most of the commit messages
- fixed remaining warnings pointed by scan-build (variable assigned but
  not used)
- replaced most of 'cAVS X.Y' expression usages with 'platform-based'
  equivalents as suggested by Pierre e.g.: cAVS 1.5 -> SKL-based


Changes [internal] RFC v1 -> [internal] RFC v2:
- fixed memleak caused by lack of kfree(vols) if memory allocation fails
  in avs_peakvol_create() as reported by Curtis
- fixed missing 'i' iterator incrementation in avs_widget_ready()
  causing reference loss as reported by Curtis
- replace hardcode: 0x40 usage with snd_hdac_calc_stream_format as
  suggested by Curtis.
  In consequence, readability for all code loading (CL) procedues has
  increased and such approach auto-documents the CL stream preparation

- updated behavior of all index-fetching functions found in utils.c:
  avs_module_entry_index(), avs_module_id_entry_index() and follow ups:
  avs_get_module_entry(), avs_get_module_id_entry() to better conform to
  linux-kernel standard when no entry is found (return -ENOENT) rather
  than C++ standard (return -1, what in kernel case translated to -EPERM)
  as suggested by Curtis and Peter
- several suggestions have been made regarding spacing, and so far, I've
  agreed and applied with all of them. None proposed seemed out of place
  or redundant

- avs_path_stop() renamed to avs_path_pause() pipeline states are
  represented by RESET/PAUSED/RUNNING. avs_path_reset() and
  avs_path_run() were already there and avs_path_stop() just didn't look
  cohesive
- added missing parsers for num_output_pin and num_input_pin which are
  required for custom modules such as WAVES or DSM
- dropped 'priv_param_length' from custom module descriptor as this
  field is obsolete in firmware

- parse_dictionary() has been split into parse_dictionary_header() and
  parse_dictionary_entries() to drop code duplication present in several
  parsing function which could not re-use entire parse_dictionary()
- added avs_tplg_vendor_array_lookup_next() and
  avs_tplg_vendor_entry_next() to drop code duplicated present in several
  parsing functions. This change greatly impacted readability of all
  parsers
- parsing helpers such avs_tplg_vendor_array_lookup() now return offset
  by updating specified in function argument list u32 *offset variable.
  This is to address problem when u32 offset would be greater than max
  int, which is the return type for these functions
- AVS_DEFINE_PTR_PARSER() macro has been introduced to drop code
  duplication for all ptr-parsing users

- all struct avs_path_module creators have had their declaration
  updated: function argument *owner ceased to exist as it could already
  be accessed by mod->owner

- fixed the order of operation for conditional paths (e.g.: echo
  reference) so these are no longer controlled by "source" path and
  instead are impacted by state changes of source and sink paths both.
  Previously only source path e.g. playback sourcing echo reference
  would trigger RUNNING status for conditional path. Equivalent RUNNING
  on WoV path which is in this case sink path, would not do so, leading
  to order-of-operation problems. Behavior has been changed to: both
  source and sink need to be RUNNING for conditional path to be set to
  RUNNING too. PAUSED for either source or sink will cause PAUSED
  transition for conditional path.
- to achieve the above, path states are now saved in 'state' i.e. new
  u32 field for struct avs_path

- resigned from fw_filename field usage in favour of newly added
  tplg_filename for machine board descriptors as suggested by Pierre
- platform descriptor fields have had their names update better reflect
  their purpose as suggested by Pierre
- fixed comp_list missing locking when manipulated
- all message senders now accept request as pointer as suggeseted by
  Peter
- resigned of AZX_ usage for all ADSP-related registers, leaving them
  only for HOST memory space related operations
- fixed disable path for core DSP operations: power/reset/stall as
  reported by Peter

- safety when locking between received responses (reply vs notification)
  has been lowered as suggested by Pierre. Most usages are not performed
  in IRQ context and none is done in hard-IRQ one
- s/master/main/ plus AVS_MAIN_CORE_MASK has replaced ->master_mask
- several functions have had their logging updated - logs have been
  moved to lower level functions as suggested by Pierre
- hdac_ext_stream usage has been streamlined to estream, hdac_streams
  are represented by hstream instead
- hw_params() are resilient to scenarios when they are called mutliple
  times as reported by Pierre
- avs_dsp_enable() now collapses if any of its steps fails as reported
  by Pierre and Peter
- avs_module_ida_empty() now returns value of type bool as suggested by
  Bard


[1]: https://www.spinics.net/lists/alsa-devel/msg116440.html
[2]: https://www.spinics.net/lists/alsa-devel/msg116901.html
[3]: https://www.spinics.net/lists/alsa-devel/msg94199.html
[4]: https://www.spinics.net/lists/alsa-devel/msg92588.html
[5]: https://lore.kernel.org/all/20190808181549.12521-1-cezary.rojewski@intel.com/
[6]: https://lore.kernel.org/alsa-devel/20220207114906.3759800-1-cezary.rojewski@intel.com/T/#t
[7]: https://lore.kernel.org/all/20211208111301.1817725-1-cezary.rojewski@intel.com/


Cezary Rojewski (17):
  ALSA: hda: Add helper macros for DSP capable devices
  ASoC: Export DAI register and widget ctor and dctor functions
  ASoC: Intel: Introduce AVS driver
  ASoC: Intel: avs: Inter process communication
  ASoC: Intel: avs: Add code loading requests
  ASoC: Intel: avs: Add pipeline management requests
  ASoC: Intel: avs: Add module management requests
  ASoC: Intel: avs: Add power management requests
  ASoC: Intel: avs: Add ROM requests
  ASoC: Intel: avs: Add basefw runtime-parameter requests
  ASoC: Intel: avs: Firmware resources management utilities
  ASoC: Intel: avs: Declare module configuration types
  ASoC: Intel: avs: Dynamic firmware resources management
  ASoC: Intel: avs: General code loading flow
  ASoC: Intel: avs: Implement CLDMA transfer
  ASoC: Intel: avs: Code loading over CLDMA
  ASoC: Intel: avs: Code loading over HDA

 include/sound/hdaudio.h         |   2 +
 include/sound/hdaudio_ext.h     |  50 +++
 include/sound/soc-dapm.h        |   1 +
 sound/soc/intel/Kconfig         |  12 +
 sound/soc/intel/Makefile        |   1 +
 sound/soc/intel/avs/Makefile    |   6 +
 sound/soc/intel/avs/avs.h       | 248 +++++++++++
 sound/soc/intel/avs/cldma.c     | 317 ++++++++++++++
 sound/soc/intel/avs/cldma.h     |  29 ++
 sound/soc/intel/avs/core.c      |  62 +++
 sound/soc/intel/avs/dsp.c       | 303 +++++++++++++
 sound/soc/intel/avs/ipc.c       | 393 +++++++++++++++++
 sound/soc/intel/avs/loader.c    | 610 ++++++++++++++++++++++++++
 sound/soc/intel/avs/messages.c  | 699 +++++++++++++++++++++++++++++
 sound/soc/intel/avs/messages.h  | 753 ++++++++++++++++++++++++++++++++
 sound/soc/intel/avs/registers.h |  75 ++++
 sound/soc/intel/avs/utils.c     | 301 +++++++++++++
 sound/soc/soc-core.c            |   1 +
 sound/soc/soc-dapm.c            |  15 +
 19 files changed, 3878 insertions(+)
 create mode 100644 sound/soc/intel/avs/Makefile
 create mode 100644 sound/soc/intel/avs/avs.h
 create mode 100644 sound/soc/intel/avs/cldma.c
 create mode 100644 sound/soc/intel/avs/cldma.h
 create mode 100644 sound/soc/intel/avs/core.c
 create mode 100644 sound/soc/intel/avs/dsp.c
 create mode 100644 sound/soc/intel/avs/ipc.c
 create mode 100644 sound/soc/intel/avs/loader.c
 create mode 100644 sound/soc/intel/avs/messages.c
 create mode 100644 sound/soc/intel/avs/messages.h
 create mode 100644 sound/soc/intel/avs/registers.h
 create mode 100644 sound/soc/intel/avs/utils.c

Comments

Pierre-Louis Bossart March 9, 2022, 9:58 p.m. UTC | #1
> diff --git a/sound/soc/intel/avs/Makefile b/sound/soc/intel/avs/Makefile
> new file mode 100644
> index 000000000000..5f7976a95fe2
> --- /dev/null
> +++ b/sound/soc/intel/avs/Makefile
> @@ -0,0 +1,5 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +
> +snd-soc-avs-objs := dsp.o
> +
> +obj-$(CONFIG_SND_SOC_INTEL_AVS) += snd-soc-avs.o

nit-pick: snd-soc-intel-avs?

avs is not a clear mapping to Intel platforms


> +/*
> + * struct avs_dev - Intel HD-Audio driver data
> + *
> + * @dev: PCI device
> + * @dsp_ba: DSP bar address

not sure it's only limited to DSP, is it?

> + * @spec: platform-specific descriptor
> + */
> +struct avs_dev {
> +	struct hda_bus base;
> +	struct device *dev;
> +
> +	void __iomem *dsp_ba;
> +	const struct avs_spec *spec;
> +};

> +int avs_dsp_core_reset(struct avs_dev *adev, u32 core_mask, bool reset)
> +{
> +	u32 value, mask, reg;
> +	int ret;
> +
> +	mask = AVS_ADSPCS_CRST_MASK(core_mask);
> +	value = reset ? mask : 0;
> +
> +	snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPCS, mask, value);
> +
> +	ret = snd_hdac_adsp_readl_poll(adev, AVS_ADSP_REG_ADSPCS,
> +				       reg, (reg & mask) == value,
> +				       AVS_ADSPCS_INTERVAL_US,
> +				       AVS_ADSPCS_TIMEOUT_US);
> +	if (ret)
> +		dev_err(adev->dev, "core_mask %d %s reset failed: %d\n",
> +			core_mask, reset ? "enter" : "exit", ret);

nit-pick: reset %s "entry" "exit"

> +
> +	return ret;
> +}
> +
Pierre-Louis Bossart March 9, 2022, 10:16 p.m. UTC | #2
> +/*
> + * avs_ipc_delete_instance - Delete module instance
> + *
> + * @adev: Driver context
> + * @module_id: Module-type id
> + * @instance_id: Unique module instance id
> + *
> + * Argument verification, as well as pipeline state checks are done by the
> + * firmware.
> + *
> + * Note: only standalone modules i.e. without a parent pipeline shall be
> + * deleted using this IPC message. In all other cases, pipeline owning the
> + * modules peforms cleanup automatically when it is deleted.

typo: performs

checkpatch.pl --strict --codespell would detect all this for you.

> + */
> +int avs_ipc_delete_instance(struct avs_dev *adev, u16 module_id, u8 instance_id)
> +{
> +	union avs_module_msg msg = AVS_MODULE_REQUEST(DELETE_INSTANCE);
> +	struct avs_ipc_msg request = {{0}};
> +	int ret;
> +
> +	msg.module_id = module_id;
> +	msg.instance_id = instance_id;
> +	request.header = msg.val;
> +
> +	ret = avs_dsp_send_msg(adev, &request, NULL);
> +	if (ret)
> +		avs_ipc_err(adev, &request, "delete instance", ret);
> +
> +	return ret;
> +}
Pierre-Louis Bossart March 9, 2022, 10:36 p.m. UTC | #3
>   /*
>    * struct avs_dev - Intel HD-Audio driver data
>    *
>    * @dev: PCI device
>    * @dsp_ba: DSP bar address
>    * @spec: platform-specific descriptor
> + * @fw_cfg: Firmware configuration, obtained through FW_CONFIG message
> + * @hw_cfg: Hardware configuration, obtained through HW_CONFIG message
> + * @mods_info: Available module-types, obtained through MODULES_INFO message

is this just for the base firmware? If this includes the extensions, how 
are the module types defined?

> + * @mod_idas: Module instance ID pool, one per module-type
> + * @modres_mutex: For synchronizing any @mods_info updates
> + * @ppl_ida: Pipeline instance ID pool
> + * @fw_list: List of libraries loaded, including base firmware
>    */
>   struct avs_dev {
>   	struct hda_bus base;
> @@ -68,6 +82,14 @@ struct avs_dev {
>   	const struct avs_spec *spec;
>   	struct avs_ipc *ipc;
>   
> +	struct avs_fw_cfg fw_cfg;
> +	struct avs_hw_cfg hw_cfg;
> +	struct avs_mods_info *mods_info;
> +	struct ida **mod_idas;
> +	struct mutex modres_mutex;
> +	struct ida ppl_ida;
> +	struct list_head fw_list;
> +
>   	struct completion fw_ready;
>   };

> +/* Caller responsible for holding adev->modres_mutex. */
> +static int
> +avs_module_ida_alloc(struct avs_dev *adev, struct avs_mods_info *newinfo, bool purge)
> +{
> +	struct avs_mods_info *oldinfo = adev->mods_info;
> +	struct ida **ida_ptrs;
> +	u32 tocopy_count = 0;
> +	int i;
> +
> +	if (!purge && oldinfo) {
> +		if (oldinfo->count >= newinfo->count)
> +			dev_warn(adev->dev, "refreshing %d modules info with %d\n",
> +				 oldinfo->count, newinfo->count);
> +		tocopy_count = oldinfo->count;
> +	}
> +
> +	ida_ptrs = kcalloc(newinfo->count, sizeof(*ida_ptrs), GFP_KERNEL);
> +	if (!ida_ptrs)
> +		return -ENOMEM;
> +
> +	if (tocopy_count)
> +		memcpy(ida_ptrs, adev->mod_idas, tocopy_count * sizeof(*ida_ptrs));
> +
> +	for (i = tocopy_count; i < newinfo->count; i++) {
> +		ida_ptrs[i] = kzalloc(sizeof(**ida_ptrs), GFP_KERNEL);
> +		if (!ida_ptrs[i]) {
> +			while (i--)
> +				kfree(ida_ptrs[i]);

it's a bit hairy to play with the loop counter, I would jump to an error 
handling label to make it clearer.
> +
> +			kfree(ida_ptrs);
> +			return -ENOMEM;
> +		}
> +
> +		ida_init(ida_ptrs[i]);
> +	}
> +
> +	/* If old elements have been reused, don't wipe them. */

the comment is very odd, there's either a free() or a destroy() 
happening below...

> +	if (tocopy_count)
> +		kfree(adev->mod_idas);
> +	else
> +		avs_module_ida_destroy(adev);
> +
> +	adev->mod_idas = ida_ptrs;
> +	return 0;
> +}

> +int avs_module_id_alloc(struct avs_dev *adev, u16 module_id)
> +{
> +	int ret, idx, max_id;
> +
> +	mutex_lock(&adev->modres_mutex);
> +
> +	idx = avs_module_id_entry_index(adev, module_id);
> +	if (idx == -ENOENT) {
> +		WARN(1, "invalid module id: %d", module_id);

dev_err() seems to be more than enough, why would you add a complete 
call trace?

> +		ret = -EINVAL;
> +		goto exit;
> +	}
> +	max_id = adev->mods_info->entries[idx].instance_max_count - 1;
> +	ret = ida_alloc_max(adev->mod_idas[idx], max_id, GFP_KERNEL);
> +exit:
> +	mutex_unlock(&adev->modres_mutex);
> +	return ret;
> +}
> +
> +void avs_module_id_free(struct avs_dev *adev, u16 module_id, u8 instance_id)
> +{
> +	int idx;
> +
> +	mutex_lock(&adev->modres_mutex);
> +
> +	idx = avs_module_id_entry_index(adev, module_id);
> +	if (idx == -ENOENT) {
> +		WARN(1, "invalid module id: %d", module_id);

same WARN is over-engineered.

> +		goto exit;
> +	}
> +
> +	ida_free(adev->mod_idas[idx], instance_id);
> +exit:
> +	mutex_unlock(&adev->modres_mutex);
> +}
> +
> +/*

I am running out of time and will resume this review next week.
Takashi Iwai March 10, 2022, 1:30 p.m. UTC | #4
On Wed, 09 Mar 2022 21:40:13 +0100,
Cezary Rojewski wrote:
> 
> HDAudio drivers make heavy use of I/O operations. Declare a range of
> update, read and write helpers similar to those available for HDAudio
> legacy driver. These macros are used by AVS driver to improve code
> readability.
> 
> Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>

Acked-by: Takashi Iwai <tiwai@suse.de>


thanks,

Takashi

> ---
>  include/sound/hdaudio.h     |  2 ++
>  include/sound/hdaudio_ext.h | 50 +++++++++++++++++++++++++++++++++++++
>  2 files changed, 52 insertions(+)
> 
> diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h
> index 6a90ce405e60..69907260b9ce 100644
> --- a/include/sound/hdaudio.h
> +++ b/include/sound/hdaudio.h
> @@ -448,6 +448,8 @@ static inline u16 snd_hdac_reg_readw(struct hdac_bus *bus, void __iomem *addr)
>  
>  #define snd_hdac_reg_writel(bus, addr, val)	writel(val, addr)
>  #define snd_hdac_reg_readl(bus, addr)	readl(addr)
> +#define snd_hdac_reg_writeq(bus, addr, val)	writeq(val, addr)
> +#define snd_hdac_reg_readq(bus, addr)		readq(addr)
>  
>  /*
>   * macros for easy use
> diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h
> index b0c8e4936168..d26234f9ee46 100644
> --- a/include/sound/hdaudio_ext.h
> +++ b/include/sound/hdaudio_ext.h
> @@ -2,6 +2,8 @@
>  #ifndef __SOUND_HDAUDIO_EXT_H
>  #define __SOUND_HDAUDIO_EXT_H
>  
> +#include <linux/io-64-nonatomic-lo-hi.h>
> +#include <linux/iopoll.h>
>  #include <sound/hdaudio.h>
>  
>  int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev,
> @@ -144,6 +146,54 @@ void snd_hdac_ext_bus_link_power(struct hdac_device *codec, bool enable);
>  	writew(((readw(addr + reg) & ~(mask)) | (val)), \
>  		addr + reg)
>  
> +#define snd_hdac_adsp_writeb(chip, reg, value) \
> +	snd_hdac_reg_writeb(chip, (chip)->dsp_ba + (reg), value)
> +#define snd_hdac_adsp_readb(chip, reg) \
> +	snd_hdac_reg_readb(chip, (chip)->dsp_ba + (reg))
> +#define snd_hdac_adsp_writew(chip, reg, value) \
> +	snd_hdac_reg_writew(chip, (chip)->dsp_ba + (reg), value)
> +#define snd_hdac_adsp_readw(chip, reg) \
> +	snd_hdac_reg_readw(chip, (chip)->dsp_ba + (reg))
> +#define snd_hdac_adsp_writel(chip, reg, value) \
> +	snd_hdac_reg_writel(chip, (chip)->dsp_ba + (reg), value)
> +#define snd_hdac_adsp_readl(chip, reg) \
> +	snd_hdac_reg_readl(chip, (chip)->dsp_ba + (reg))
> +#define snd_hdac_adsp_writeq(chip, reg, value) \
> +	snd_hdac_reg_writeq(chip, (chip)->dsp_ba + (reg), value)
> +#define snd_hdac_adsp_readq(chip, reg) \
> +	snd_hdac_reg_readq(chip, (chip)->dsp_ba + (reg))
> +
> +#define snd_hdac_adsp_updateb(chip, reg, mask, val) \
> +	snd_hdac_adsp_writeb(chip, reg, \
> +			(snd_hdac_adsp_readb(chip, reg) & ~(mask)) | (val))
> +#define snd_hdac_adsp_updatew(chip, reg, mask, val) \
> +	snd_hdac_adsp_writew(chip, reg, \
> +			(snd_hdac_adsp_readw(chip, reg) & ~(mask)) | (val))
> +#define snd_hdac_adsp_updatel(chip, reg, mask, val) \
> +	snd_hdac_adsp_writel(chip, reg, \
> +			(snd_hdac_adsp_readl(chip, reg) & ~(mask)) | (val))
> +#define snd_hdac_adsp_updateq(chip, reg, mask, val) \
> +	snd_hdac_adsp_writeq(chip, reg, \
> +			(snd_hdac_adsp_readq(chip, reg) & ~(mask)) | (val))
> +
> +#define snd_hdac_adsp_readb_poll(chip, reg, val, cond, delay_us, timeout_us) \
> +	readb_poll_timeout((chip)->dsp_ba + (reg), val, cond, \
> +			   delay_us, timeout_us)
> +#define snd_hdac_adsp_readw_poll(chip, reg, val, cond, delay_us, timeout_us) \
> +	readw_poll_timeout((chip)->dsp_ba + (reg), val, cond, \
> +			   delay_us, timeout_us)
> +#define snd_hdac_adsp_readl_poll(chip, reg, val, cond, delay_us, timeout_us) \
> +	readl_poll_timeout((chip)->dsp_ba + (reg), val, cond, \
> +			   delay_us, timeout_us)
> +#define snd_hdac_adsp_readq_poll(chip, reg, val, cond, delay_us, timeout_us) \
> +	readq_poll_timeout((chip)->dsp_ba + (reg), val, cond, \
> +			   delay_us, timeout_us)
> +#define snd_hdac_stream_readb_poll(strm, reg, val, cond, delay_us, timeout_us) \
> +	readb_poll_timeout((strm)->sd_addr + AZX_REG_ ## reg, val, cond, \
> +			   delay_us, timeout_us)
> +#define snd_hdac_stream_readl_poll(strm, reg, val, cond, delay_us, timeout_us) \
> +	readl_poll_timeout((strm)->sd_addr + AZX_REG_ ## reg, val, cond, \
> +			   delay_us, timeout_us)
>  
>  struct hdac_ext_device;
>  
> -- 
> 2.25.1
>
Cezary Rojewski March 10, 2022, 5:11 p.m. UTC | #5
On 2022-03-09 11:36 PM, Pierre-Louis Bossart wrote:
> I am running out of time and will resume this review next week.

Hello,

I don't believe any of the comments provided are a strong reason for 
re-send. Given that last revisions were mostly related to addressing 
comments, rewords and explaining stuff, series is in good shape and 
ready for merge. As I already stated, team continues to work on the 
subject and there are more patch-series to come.


Regards,
Czarek
Mark Brown March 11, 2022, 12:10 p.m. UTC | #6
On Thu, Mar 10, 2022 at 06:11:31PM +0100, Cezary Rojewski wrote:

> I don't believe any of the comments provided are a strong reason for
> re-send. Given that last revisions were mostly related to addressing
> comments, rewords and explaining stuff, series is in good shape and ready
> for merge. As I already stated, team continues to work on the subject and
> there are more patch-series to come.

It'd be good to get the WARN()s fixed.
Cezary Rojewski March 11, 2022, 3:28 p.m. UTC | #7
On 2022-03-11 1:10 PM, Mark Brown wrote:
> On Thu, Mar 10, 2022 at 06:11:31PM +0100, Cezary Rojewski wrote:
> 
>> I don't believe any of the comments provided are a strong reason for
>> re-send. Given that last revisions were mostly related to addressing
>> comments, rewords and explaining stuff, series is in good shape and ready
>> for merge. As I already stated, team continues to work on the subject and
>> there are more patch-series to come.
> 
> It'd be good to get the WARN()s fixed.


Ack. Addressed in v5.
Cezary Rojewski March 11, 2022, 3:32 p.m. UTC | #8
On 2022-03-09 10:58 PM, Pierre-Louis Bossart wrote:
>> diff --git a/sound/soc/intel/avs/Makefile b/sound/soc/intel/avs/Makefile
>> new file mode 100644
>> index 000000000000..5f7976a95fe2
>> --- /dev/null
>> +++ b/sound/soc/intel/avs/Makefile
>> @@ -0,0 +1,5 @@
>> +# SPDX-License-Identifier: GPL-2.0-only
>> +
>> +snd-soc-avs-objs := dsp.o
>> +
>> +obj-$(CONFIG_SND_SOC_INTEL_AVS) += snd-soc-avs.o
> 
> nit-pick: snd-soc-intel-avs?
> 
> avs is not a clear mapping to Intel platforms


We already have snd_soc_catpt : (

>> +/*
>> + * struct avs_dev - Intel HD-Audio driver data
>> + *
>> + * @dev: PCI device
>> + * @dsp_ba: DSP bar address
> 
> not sure it's only limited to DSP, is it?


Well, this space is classified as: "Host Device Memory Space (Audio DSP)".

>> + * @spec: platform-specific descriptor
>> + */
>> +struct avs_dev {
>> +    struct hda_bus base;
>> +    struct device *dev;
>> +
>> +    void __iomem *dsp_ba;
>> +    const struct avs_spec *spec;
>> +};
> 
>> +int avs_dsp_core_reset(struct avs_dev *adev, u32 core_mask, bool reset)
>> +{
>> +    u32 value, mask, reg;
>> +    int ret;
>> +
>> +    mask = AVS_ADSPCS_CRST_MASK(core_mask);
>> +    value = reset ? mask : 0;
>> +
>> +    snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPCS, mask, value);
>> +
>> +    ret = snd_hdac_adsp_readl_poll(adev, AVS_ADSP_REG_ADSPCS,
>> +                       reg, (reg & mask) == value,
>> +                       AVS_ADSPCS_INTERVAL_US,
>> +                       AVS_ADSPCS_TIMEOUT_US);
>> +    if (ret)
>> +        dev_err(adev->dev, "core_mask %d %s reset failed: %d\n",
>> +            core_mask, reset ? "enter" : "exit", ret);
> 
> nit-pick: reset %s "entry" "exit"


I did align with what's already present in sound/hda/hdac_controller.c. 
It's done the other way around there. My personal opinion is: it sounds 
more logically the way it is currently - but I'm not a native English 
speaker.

>> +
>> +    return ret;
>> +}
>> +
>
Cezary Rojewski March 11, 2022, 3:40 p.m. UTC | #9
On 2022-03-09 11:16 PM, Pierre-Louis Bossart wrote:
> 
>> +/*
>> + * avs_ipc_delete_instance - Delete module instance
>> + *
>> + * @adev: Driver context
>> + * @module_id: Module-type id
>> + * @instance_id: Unique module instance id
>> + *
>> + * Argument verification, as well as pipeline state checks are done 
>> by the
>> + * firmware.
>> + *
>> + * Note: only standalone modules i.e. without a parent pipeline shall be
>> + * deleted using this IPC message. In all other cases, pipeline 
>> owning the
>> + * modules peforms cleanup automatically when it is deleted.
> 
> typo: performs
> 
> checkpatch.pl --strict --codespell would detect all this for you.


Ack.
Cezary Rojewski March 11, 2022, 3:46 p.m. UTC | #10
On 2022-03-09 11:36 PM, Pierre-Louis Bossart wrote:
> 
>>   /*
>>    * struct avs_dev - Intel HD-Audio driver data
>>    *
>>    * @dev: PCI device
>>    * @dsp_ba: DSP bar address
>>    * @spec: platform-specific descriptor
>> + * @fw_cfg: Firmware configuration, obtained through FW_CONFIG message
>> + * @hw_cfg: Hardware configuration, obtained through HW_CONFIG message
>> + * @mods_info: Available module-types, obtained through MODULES_INFO 
>> message
> 
> is this just for the base firmware? If this includes the extensions, how 
> are the module types defined?


Only base firmware is able to process MODULE_INFO getter. So, every time 
driver loads a library, this info gets updated internally on the 
firmware side. We make use of said getter to retrieve up-to-date 
information and cache in ->mods_info for later use. ->mods_info is a 
member of type struct avs_mods_info with each enter represented by 
struct avs_module_info. These are introduced with all the basefw runtime 
parameters.

>> + * @mod_idas: Module instance ID pool, one per module-type
>> + * @modres_mutex: For synchronizing any @mods_info updates
>> + * @ppl_ida: Pipeline instance ID pool
>> + * @fw_list: List of libraries loaded, including base firmware
>>    */
>>   struct avs_dev {
>>       struct hda_bus base;
>> @@ -68,6 +82,14 @@ struct avs_dev {
>>       const struct avs_spec *spec;
>>       struct avs_ipc *ipc;
>> +    struct avs_fw_cfg fw_cfg;
>> +    struct avs_hw_cfg hw_cfg;
>> +    struct avs_mods_info *mods_info;
>> +    struct ida **mod_idas;
>> +    struct mutex modres_mutex;
>> +    struct ida ppl_ida;
>> +    struct list_head fw_list;
>> +
>>       struct completion fw_ready;
>>   };

...

>> +    if (tocopy_count)
>> +        kfree(adev->mod_idas);
>> +    else
>> +        avs_module_ida_destroy(adev);
>> +
>> +    adev->mod_idas = ida_ptrs;
>> +    return 0;
>> +}
> 
>> +int avs_module_id_alloc(struct avs_dev *adev, u16 module_id)
>> +{
>> +    int ret, idx, max_id;
>> +
>> +    mutex_lock(&adev->modres_mutex);
>> +
>> +    idx = avs_module_id_entry_index(adev, module_id);
>> +    if (idx == -ENOENT) {
>> +        WARN(1, "invalid module id: %d", module_id);
> 
> dev_err() seems to be more than enough, why would you add a complete 
> call trace?
> 
>> +        ret = -EINVAL;
>> +        goto exit;
>> +    }
>> +    max_id = adev->mods_info->entries[idx].instance_max_count - 1;
>> +    ret = ida_alloc_max(adev->mod_idas[idx], max_id, GFP_KERNEL);
>> +exit:
>> +    mutex_unlock(&adev->modres_mutex);
>> +    return ret;
>> +}
>> +
>> +void avs_module_id_free(struct avs_dev *adev, u16 module_id, u8 
>> instance_id)
>> +{
>> +    int idx;
>> +
>> +    mutex_lock(&adev->modres_mutex);
>> +
>> +    idx = avs_module_id_entry_index(adev, module_id);
>> +    if (idx == -ENOENT) {
>> +        WARN(1, "invalid module id: %d", module_id);
> 
> same WARN is over-engineered.


Ack for both.


Regards,
Czarek
Pierre-Louis Bossart March 11, 2022, 3:59 p.m. UTC | #11
On 3/11/22 09:46, Cezary Rojewski wrote:
> On 2022-03-09 11:36 PM, Pierre-Louis Bossart wrote:
>>
>>>   /*
>>>    * struct avs_dev - Intel HD-Audio driver data
>>>    *
>>>    * @dev: PCI device
>>>    * @dsp_ba: DSP bar address
>>>    * @spec: platform-specific descriptor
>>> + * @fw_cfg: Firmware configuration, obtained through FW_CONFIG message
>>> + * @hw_cfg: Hardware configuration, obtained through HW_CONFIG message
>>> + * @mods_info: Available module-types, obtained through MODULES_INFO 
>>> message
>>
>> is this just for the base firmware? If this includes the extensions, 
>> how are the module types defined?
> 
> 
> Only base firmware is able to process MODULE_INFO getter. So, every time 
> driver loads a library, this info gets updated internally on the 
> firmware side. We make use of said getter to retrieve up-to-date 
> information and cache in ->mods_info for later use. ->mods_info is a 
> member of type struct avs_mods_info with each enter represented by 
> struct avs_module_info. These are introduced with all the basefw runtime 
> parameters.

you clarified the mechanism but not the definition of 'module-type'?

the definition doesn't really help.

struct avs_module_type {
	u32 load_type:4;
	u32 auto_start:1;
	u32 domain_ll:1;
	u32 domain_dp:1;
	u32 lib_code:1;
	u32 rsvd:24;
} __packed;

I see nothing that would e.g. identify a mixer from a gain. The 
definition of 'type' seems to refer to low-level properties, not what 
the module actually does?
Cezary Rojewski March 11, 2022, 5:20 p.m. UTC | #12
On 2022-03-11 4:59 PM, Pierre-Louis Bossart wrote:
> On 3/11/22 09:46, Cezary Rojewski wrote:
>> On 2022-03-09 11:36 PM, Pierre-Louis Bossart wrote:
>>>
>>>>   /*
>>>>    * struct avs_dev - Intel HD-Audio driver data
>>>>    *
>>>>    * @dev: PCI device
>>>>    * @dsp_ba: DSP bar address
>>>>    * @spec: platform-specific descriptor
>>>> + * @fw_cfg: Firmware configuration, obtained through FW_CONFIG message
>>>> + * @hw_cfg: Hardware configuration, obtained through HW_CONFIG message
>>>> + * @mods_info: Available module-types, obtained through 
>>>> MODULES_INFO message
>>>
>>> is this just for the base firmware? If this includes the extensions, 
>>> how are the module types defined?
>>
>>
>> Only base firmware is able to process MODULE_INFO getter. So, every 
>> time driver loads a library, this info gets updated internally on the 
>> firmware side. We make use of said getter to retrieve up-to-date 
>> information and cache in ->mods_info for later use. ->mods_info is a 
>> member of type struct avs_mods_info with each enter represented by 
>> struct avs_module_info. These are introduced with all the basefw 

Sorry for the typo: s/avs_module_info/avs_module_entry/.

>> runtime parameters.
> 
> you clarified the mechanism but not the definition of 'module-type'?
> 
> the definition doesn't really help.
> 
> struct avs_module_type {
>      u32 load_type:4;
>      u32 auto_start:1;
>      u32 domain_ll:1;
>      u32 domain_dp:1;
>      u32 lib_code:1;
>      u32 rsvd:24;
> } __packed;
> 
> I see nothing that would e.g. identify a mixer from a gain. The 
> definition of 'type' seems to refer to low-level properties, not what 
> the module actually does?


There is no "module-type" enum that software can rely on. We rely on 
hardcoded GUIDs instead. "module-type" is represented by struct 
avs_module_entry (per type) in context of MODULE_INFO IPC. All these 
names are indented to match firmware equivalents to make it easier to 
switch between the two worlds.


Regards,
Czarek
Pierre-Louis Bossart March 11, 2022, 8:30 p.m. UTC | #13
On 3/11/22 11:20, Cezary Rojewski wrote:
> On 2022-03-11 4:59 PM, Pierre-Louis Bossart wrote:
>> On 3/11/22 09:46, Cezary Rojewski wrote:
>>> On 2022-03-09 11:36 PM, Pierre-Louis Bossart wrote:
>>>>
>>>>>   /*
>>>>>    * struct avs_dev - Intel HD-Audio driver data
>>>>>    *
>>>>>    * @dev: PCI device
>>>>>    * @dsp_ba: DSP bar address
>>>>>    * @spec: platform-specific descriptor
>>>>> + * @fw_cfg: Firmware configuration, obtained through FW_CONFIG 
>>>>> message
>>>>> + * @hw_cfg: Hardware configuration, obtained through HW_CONFIG 
>>>>> message
>>>>> + * @mods_info: Available module-types, obtained through 
>>>>> MODULES_INFO message
>>>>
>>>> is this just for the base firmware? If this includes the extensions, 
>>>> how are the module types defined?
>>>
>>>
>>> Only base firmware is able to process MODULE_INFO getter. So, every 
>>> time driver loads a library, this info gets updated internally on the 
>>> firmware side. We make use of said getter to retrieve up-to-date 
>>> information and cache in ->mods_info for later use. ->mods_info is a 
>>> member of type struct avs_mods_info with each enter represented by 
>>> struct avs_module_info. These are introduced with all the basefw 
> 
> Sorry for the typo: s/avs_module_info/avs_module_entry/.
> 
>>> runtime parameters.
>>
>> you clarified the mechanism but not the definition of 'module-type'?
>>
>> the definition doesn't really help.
>>
>> struct avs_module_type {
>>      u32 load_type:4;
>>      u32 auto_start:1;
>>      u32 domain_ll:1;
>>      u32 domain_dp:1;
>>      u32 lib_code:1;
>>      u32 rsvd:24;
>> } __packed;
>>
>> I see nothing that would e.g. identify a mixer from a gain. The 
>> definition of 'type' seems to refer to low-level properties, not what 
>> the module actually does?
> 
> 
> There is no "module-type" enum that software can rely on. We rely on 
> hardcoded GUIDs instead. "module-type" is represented by struct 
> avs_module_entry (per type) in context of MODULE_INFO IPC. All these 
> names are indented to match firmware equivalents to make it easier to 
> switch between the two worlds.

So the initial kernel-doc I commented on is still quite convoluted, you 
are referring to a 'module-type' that's not really well defined or 
useful for a driver.

Given the definition:

struct avs_mods_info {
	u32 count;
	struct avs_module_entry entries[];
} __packed;


wouldn't this be simpler/less confusing:

"
@mods_info: Available array of module entries, obtained through
MODULES_INFO message
"

?
Cezary Rojewski March 14, 2022, 5:59 p.m. UTC | #14
On 2022-03-11 9:30 PM, Pierre-Louis Bossart wrote:
> On 3/11/22 11:20, Cezary Rojewski wrote:


...

>> Sorry for the typo: s/avs_module_info/avs_module_entry/.
>>
>>>> runtime parameters.
>>>
>>> you clarified the mechanism but not the definition of 'module-type'?
>>>
>>> the definition doesn't really help.
>>>
>>> struct avs_module_type {
>>>      u32 load_type:4;
>>>      u32 auto_start:1;
>>>      u32 domain_ll:1;
>>>      u32 domain_dp:1;
>>>      u32 lib_code:1;
>>>      u32 rsvd:24;
>>> } __packed;
>>>
>>> I see nothing that would e.g. identify a mixer from a gain. The 
>>> definition of 'type' seems to refer to low-level properties, not what 
>>> the module actually does?
>>
>>
>> There is no "module-type" enum that software can rely on. We rely on 
>> hardcoded GUIDs instead. "module-type" is represented by struct 
>> avs_module_entry (per type) in context of MODULE_INFO IPC. All these 
>> names are indented to match firmware equivalents to make it easier to 
>> switch between the two worlds.
> 
> So the initial kernel-doc I commented on is still quite convoluted, you 
> are referring to a 'module-type' that's not really well defined or 
> useful for a driver.
> 
> Given the definition:
> 
> struct avs_mods_info {
>      u32 count;
>      struct avs_module_entry entries[];
> } __packed;
> 
> 
> wouldn't this be simpler/less confusing:
> 
> "
> @mods_info: Available array of module entries, obtained through
> MODULES_INFO message
> "

The major problem is the convoluted naming within the firmware itself.

The decision for the naming all the members as they are is dictated by 
the fact that there is much, much higher chance for Intel audio software 
or firmware developer to do some major/meaningful changes to the 
avs-driver as the kernel grows than a person outside that circle. Not 
everyone might agree, but that's the democratic decision made by the 
team in the early days of this driver. And thus, having close 
name-matching between the driver and the firmware makes it easier for 
given developer to switch between the two projects.

Agree on the rewording. There are probably more of such wordings within 
the code so this might span more than 1 file.


Regards,
Czarek