mbox series

[v3,00/25] ASoC: qcom: Add support to QDSP based Audio

Message ID 20180213165837.1620-1-srinivas.kandagatla@linaro.org
Headers show
Series ASoC: qcom: Add support to QDSP based Audio | expand

Message

Srinivas Kandagatla Feb. 13, 2018, 4:58 p.m. UTC
From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>


This patchset aims to provide a basic version of QCOM DSP based
audio support which is available in downstream andriod kernels.
This patchset support audio playback on HDMI-RX, MI2S, SLIMBus and
will add support to other features as we move on.

QDSP has both static and dynamic modules. static modules like AFE
(Audio FrontEnd), ADM (Audio Device Manager), ASM(Audio Stream Manager)
and CORE to provide this audio services.
All these services use APR (Asynchronous Packet Router) protocol
via smd/glink transport to communicate with Application processor.
More details on each module is availble in there respective patch.

This patchset is tested on DB820c, with HDMI audio playback, MI2S on DB410c
on top of mainline, Also tested SLIMBus analog audio using wcd9355
with an additional patches.

Here is my test branch incase somone want to try these patches
https://git.linaro.org/people/srinivas.kandagatla/linux.git/log/?h=v4.16-rc1-dsp-audio-v3

Here is block diagram to give a quick overview of the components


  +---------+          +---------+         +---------+   
  |  q6asm  |          |q6routing|         | q6afe   | 
  |  fedai  | <------> |  mixers | <-----> | bedai   |  
  +---------+          +---------+         +---------+   
      ^                     ^                   ^
      |                     |                   |
      |  +------------------+----------------+  |       
      |  |                  |                |  |       
      v  v                  v                v  v       
  +---------+          +---------+         +---------+ 
  |   q6ASM |          |  q6ADM  |         |   q6AFE |  
  +---------+          +---------+         +---------+  
      ^                     ^                   ^          ^
      |                     |                   | CPU Side |
------+---------------------+-------------------+--------
      |                     |                   |
      |                     |APR(smd/glink)     | 
      |                     |                   |
      |  +------------------+----------------+  |
      |  |                  |                |  |
+-----+--+-----------------------------------+--+-------
      |  |                  |                |  | QDSP Side |
      v  v                  v                v  v           v
 +---------+          +---------+         +---------+
 |   ASM   | <------> |   ADM   | <-----> |   AFE   |
 +---------+          +---------+         +---------+
                                               ^
                                               | 
                           +-------------------+
                           |
---------------------------+--------------------------
                           |            Audio I/O |
                           v                      v
    +--------------------------------------------------+
    |                Audio devices                     |
    | CODEC | HDMI-TX | PCM  | SLIMBUS | I2S |MI2S |...|
    |                                                  |
    +--------------------------------------------------+

Changes since v2 (https://lwn.net/Articles/741472/)
- fixed locking issues with ASM and APR.
- Added support to MI2S and SLIMBus ports
- moved dma device to apr.
- added dt bindings for ASM, ADM, AFE.
- Fixed dt bindings for msm8996 sound card.
- added compatible strings to ASM, ADM, AFE modules.
- Cleaned up common code as suggested in review.
- converted sound card driver to proper apr client driver.
- Fixed various issues spotted by Banajit and Kasam.
- Tested on DB410c, DB820c for both analog and digital playbacks.
- Exported q6core functions as suggested by Rohit.
- Fixed various issues with dsp carsh/recover usecase.
- Added multiple ASM streams as requested in review.

Srinivas Kandagatla (25):
  dt-bindings: soc: qcom: Add bindings for APR bus
  soc: qcom: add support to APR bus driver
  ASoC: qcom: qdsp6: Add common qdsp6 helper functions
  dt-bindings: sound: qcom: Add bindings for q6afe
  ASoC: qcom: qdsp6: Add support to Q6AFE
  dt-bindings: sound: qcom: Add bindings for q6adm
  ASoC: qcom: qdsp6: Add support to Q6ADM
  dt-bindings: sound: qcom: Add bindings for q6asm
  ASoC: qcom: qdsp6: Add support to Q6ASM
  ASoC: qcom: q6asm: Add support to memory map and unmap
  ASoC: qcom: q6asm: add support to audio stream apis
  ASoC: qcom: qdsp6: Add support to Q6CORE
  ASoC: qcom: qdsp6: Add support to q6routing driver
  ASoC: qcom: qdsp6: Add support to q6afe dai driver
  ASoC: qcom: qdsp6: Add support to q6asm dai driver
  ASoC: qcom: q6afe: add SLIMBus port Support
  ASoC: qcom: q6afe-dai: add support to slim afe dais
  ASoC: qcom: q6routing: add support to all SLIMBus Mixers
  ASoC: qcom: q6afe: add support to MI2S ports
  ASoC: qcom: q6afe: add support to MI2S sysclks
  ASoC: qcom: q6afe-dai: add support to 4 MI2S ports
  ASoC: qcom: q6routing: add support to MI2S Mixers
  dt-bindings: sound: qcom: Add devicetree bindings for apq8096
  ASoC: qcom: apq8096: Add db820c machine driver
  arm64: dts: msm8996: db820c: Add sound card support

 .../devicetree/bindings/soc/qcom/qcom,apr.txt      |   83 ++
 .../devicetree/bindings/sound/qcom,apq8096.txt     |   89 ++
 .../devicetree/bindings/sound/qcom,q6adm.txt       |   31 +
 .../devicetree/bindings/sound/qcom,q6afe.txt       |   38 +
 .../devicetree/bindings/sound/qcom,q6asm.txt       |   38 +
 arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi       |   44 +-
 arch/arm64/boot/dts/qcom/msm8996.dtsi              |   62 ++
 drivers/soc/qcom/Kconfig                           |    9 +
 drivers/soc/qcom/Makefile                          |    1 +
 drivers/soc/qcom/apr.c                             |  381 +++++++
 include/dt-bindings/soc/qcom,apr.h                 |   27 +
 include/dt-bindings/sound/qcom,q6afe.h             |   33 +
 include/dt-bindings/sound/qcom,q6asm.h             |   22 +
 include/linux/mod_devicetable.h                    |   11 +
 include/linux/soc/qcom/apr.h                       |  131 +++
 sound/soc/qcom/Kconfig                             |   42 +
 sound/soc/qcom/Makefile                            |    5 +
 sound/soc/qcom/apq8096.c                           |  173 ++++
 sound/soc/qcom/qdsp6/Makefile                      |    5 +
 sound/soc/qcom/qdsp6/q6adm.c                       |  634 ++++++++++++
 sound/soc/qcom/qdsp6/q6adm.h                       |   29 +
 sound/soc/qcom/qdsp6/q6afe-dai.c                   |  645 ++++++++++++
 sound/soc/qcom/qdsp6/q6afe.c                       |  875 ++++++++++++++++
 sound/soc/qcom/qdsp6/q6afe.h                       |   74 ++
 sound/soc/qcom/qdsp6/q6asm-dai.c                   |  621 ++++++++++++
 sound/soc/qcom/qdsp6/q6asm.c                       | 1063 ++++++++++++++++++++
 sound/soc/qcom/qdsp6/q6asm.h                       |   66 ++
 sound/soc/qcom/qdsp6/q6core.c                      |  235 +++++
 sound/soc/qcom/qdsp6/q6core.h                      |    9 +
 sound/soc/qcom/qdsp6/q6dsp-common.c                |   67 ++
 sound/soc/qcom/qdsp6/q6dsp-common.h                |   24 +
 sound/soc/qcom/qdsp6/q6dsp-errno.h                 |   97 ++
 sound/soc/qcom/qdsp6/q6routing.c                   |  758 ++++++++++++++
 sound/soc/qcom/qdsp6/q6routing.h                   |    9 +
 34 files changed, 6430 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/soc/qcom/qcom,apr.txt
 create mode 100644 Documentation/devicetree/bindings/sound/qcom,apq8096.txt
 create mode 100644 Documentation/devicetree/bindings/sound/qcom,q6adm.txt
 create mode 100644 Documentation/devicetree/bindings/sound/qcom,q6afe.txt
 create mode 100644 Documentation/devicetree/bindings/sound/qcom,q6asm.txt
 create mode 100644 drivers/soc/qcom/apr.c
 create mode 100644 include/dt-bindings/soc/qcom,apr.h
 create mode 100644 include/dt-bindings/sound/qcom,q6afe.h
 create mode 100644 include/dt-bindings/sound/qcom,q6asm.h
 create mode 100644 include/linux/soc/qcom/apr.h
 create mode 100644 sound/soc/qcom/apq8096.c
 create mode 100644 sound/soc/qcom/qdsp6/Makefile
 create mode 100644 sound/soc/qcom/qdsp6/q6adm.c
 create mode 100644 sound/soc/qcom/qdsp6/q6adm.h
 create mode 100644 sound/soc/qcom/qdsp6/q6afe-dai.c
 create mode 100644 sound/soc/qcom/qdsp6/q6afe.c
 create mode 100644 sound/soc/qcom/qdsp6/q6afe.h
 create mode 100644 sound/soc/qcom/qdsp6/q6asm-dai.c
 create mode 100644 sound/soc/qcom/qdsp6/q6asm.c
 create mode 100644 sound/soc/qcom/qdsp6/q6asm.h
 create mode 100644 sound/soc/qcom/qdsp6/q6core.c
 create mode 100644 sound/soc/qcom/qdsp6/q6core.h
 create mode 100644 sound/soc/qcom/qdsp6/q6dsp-common.c
 create mode 100644 sound/soc/qcom/qdsp6/q6dsp-common.h
 create mode 100644 sound/soc/qcom/qdsp6/q6dsp-errno.h
 create mode 100644 sound/soc/qcom/qdsp6/q6routing.c
 create mode 100644 sound/soc/qcom/qdsp6/q6routing.h

-- 
2.15.1

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

Comments

Srinivas Kandagatla Feb. 20, 2018, 9:34 a.m. UTC | #1
Thanks for your review comments



On 19/02/18 10:30, Rohit Kumar wrote:
>> diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile

>> index d5280355c24f..748f5e891dcf 100644

>> --- a/sound/soc/qcom/Makefile

>> +++ b/sound/soc/qcom/Makefile

>> @@ -13,6 +13,11 @@ obj-$(CONFIG_SND_SOC_LPASS_APQ8016) += 

>> snd-soc-lpass-apq8016.o

>>   # Machine

>>   snd-soc-storm-objs := storm.o

>>   snd-soc-apq8016-sbc-objs := apq8016_sbc.o

>> +snd-soc-msm8996-objs := apq8096.o

> This needs to be moved out of this patch


Will fix it in next version.

>>   obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o

>>   obj-$(CONFIG_SND_SOC_APQ8016_SBC) += snd-soc-apq8016-sbc.o

>> +obj-$(CONFIG_SND_SOC_MSM8996) += snd-soc-msm8996.o

>> +

>> +#DSP lib 

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Srinivas Kandagatla Feb. 20, 2018, 9:36 a.m. UTC | #2
Thanks for testing this out,

On 19/02/18 10:32, Rohit Kumar wrote:
>>

>> diff --git a/sound/soc/qcom/qdsp6/Makefile 

>> b/sound/soc/qcom/qdsp6/Makefile

>> index 660afcab98fd..c7833842b878 100644

>> --- a/sound/soc/qcom/qdsp6/Makefile

>> +++ b/sound/soc/qcom/qdsp6/Makefile

>> @@ -1,5 +1,5 @@

>>   obj-$(CONFIG_SND_SOC_QDSP6_COMMON) += q6dsp-common.o

>> -obj-$(CONFIG_SND_SOC_QDSP6_AFE) += q6afe.o

>> +obj-$(CONFIG_SND_SOC_QDSP6_AFE) += q6afe.o q6afe-dai.o

> depmod: ERROR: Cycle detected: q6afe -> q6afe_dai -> q6afe

> need to use like:

> +qdsp6_afe-objs := q6afe.o q6afe-dai.o

> +obj-$(CONFIG_SND_SOC_QDSP6_AFE) += qdsp6_afe.o

> similarly for asm and adm



Yep, will fix this in next version,

thanks,
srini
>>   obj-$(CONFIG_SND_SOC_QDSP6_ADM) += q6adm.o q6routing.o

>>   obj-$(CONFIG_SND_SOC_QDSP6_ASM) += q6asm.o

>>   obj-$(CONFIG_SND_SOC_QDSP6_CORE) += q6core.o

>> diff --git a/sound/soc/qcom/qdsp6/q6afe-dai.c 

>> b/sound/soc/qcom/qdsp6/q6afe-dai.c

>> new file mode 100644

>> index 000000000000..f6a618e9db9e 

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Mark Brown March 1, 2018, 8:41 p.m. UTC | #3
On Tue, Feb 13, 2018 at 04:58:16PM +0000, srinivas.kandagatla@linaro.org wrote:
> From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>


Please submit patches using subject lines reflecting the style for the
subsystem.  This makes it easier for people to identify relevant
patches.  Look at what existing commits in the area you're changing are
doing and make sure your subject lines visually resemble what they're
doing.

> +- but must contain the following property:

> +

> +- compatible:

> +- qcom,apr-svc-id

> +- qcom,apr-svc-name

> +- #sound-dai-cells


Property or properties?  It's a bit surprising that both the ID and the
name are mandatory, does the name actually get used for non-diagnostic
reasons?
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Mark Brown March 1, 2018, 8:42 p.m. UTC | #4
On Mon, Feb 19, 2018 at 04:00:32PM +0530, Rohit Kumar wrote:
> 

> On 2/13/2018 10:28 PM, srinivas.kandagatla@linaro.org wrote:

> > From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>

> > 

> > This patch adds support to Q6AFE (Audio Front End) module on Q6DSP.

> > 

> > AFE module sits right at the other end of cpu where the codec/audio

> > devices are connected.


Please delete unneeded context from mails when replying.  Doing this
makes it much easier to find your reply in the message, helping ensure
it won't be missed by people scrolling through the irrelevant quoted
material.
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Mark Brown March 1, 2018, 8:59 p.m. UTC | #5
On Tue, Feb 13, 2018 at 04:58:17PM +0000, srinivas.kandagatla@linaro.org wrote:

> +// SPDX-License-Identifier: GPL-2.0

> +#ifndef __DT_BINDINGS_Q6_AFE_H__

> +#define __DT_BINDINGS_Q6_AFE_H__

> +

> +/* Audio Front End (AFE) Ports */

> +#define AFE_PORT_HDMI_RX	8

> +

> +#endif /* __DT_BINDINGS_Q6_AFE_H__ */


Please use a C++ comment here as well for consistency, it looks more
intentional.

> +config SND_SOC_QDSP6_AFE

> +	tristate

> +	default n

> +


n is the default anyway, no need to specify it (I know some uses already
slipped through here but it'd be better to fix those).

> index 000000000000..0a5af06bb50e

> --- /dev/null

> +++ b/sound/soc/qcom/qdsp6/q6afe.c

> @@ -0,0 +1,520 @@

> +// SPDX-License-Identifier: GPL-2.0

> +/*

> + * Copyright (c) 2011-2017, The Linux Foundation

> + * Copyright (c) 2018, Linaro Limited

> + */


Same here with the comment, just make the whole comment a C++ comment
rather than having one comment using both styles.  Similar things apply
elsewhere.

> +/* Port map of index vs real hw port ids */

> +static struct afe_port_map port_maps[AFE_PORT_MAX] = {

> +	[AFE_PORT_HDMI_RX] = { AFE_PORT_ID_MULTICHAN_HDMI_RX,

> +				AFE_PORT_HDMI_RX, 1, 1},

> +};


Is this not device specific in any way?  It looks likely to be.

> +static struct q6afe_port *afe_find_port(struct q6afe *afe, int token)

> +{

> +	struct q6afe_port *p = NULL;

> +

> +	spin_lock(&afe->port_list_lock);

> +	list_for_each_entry(p, &afe->port_list, node)

> +		if (p->token == token)

> +			break;

> +

> +	spin_unlock(&afe->port_list_lock);


Why do we need to lock the port list, what are we protecting it against?
We don't write here which suggests either there's some kind of race
condition in this lookup or the lock is not doing anything.

> +static int afe_callback(struct apr_device *adev,

> +			struct apr_client_message *data)

> +{

> +	struct q6afe *afe = dev_get_drvdata(&adev->dev);

> +	struct aprv2_ibasic_rsp_result_t *res;

> +	struct q6afe_port *port;

> +

> +	if (!data->payload_size)

> +		return 0;

> +

> +	res = data->payload;

> +	if (data->opcode == APR_BASIC_RSP_RESULT) {

> +		if (res->status) {


Shouldn't we use a switch statement here in case we want to handle
something else?

> +		switch (res->opcode) {

> +		case AFE_PORT_CMD_SET_PARAM_V2:

> +		case AFE_PORT_CMD_DEVICE_STOP:

> +		case AFE_PORT_CMD_DEVICE_START:

> +			afe->state = AFE_CMD_RESP_AVAIL;

> +			port = afe_find_port(afe, data->token);

> +			if (port)

> +				wake_up(&port->wait);


No locking here?  It seems a bit odd that the AFE global state is being
set to say there's a response available but we wake a specific port.

> +	ret = apr_send_pkt(afe->apr, data);

> +	if (ret < 0) {

> +		dev_err(afe->dev, "packet not transmitted\n");

> +		ret = -EINVAL;

> +		goto err;


Why squash the error code here?  We don't even print it.

> +	}

> +

> +	ret = wait_event_timeout(*wait, (afe->state == AFE_CMD_RESP_AVAIL),

> +				 msecs_to_jiffies(TIMEOUT_MS));

> +	if (!ret) {

> +		ret = -ETIMEDOUT;

> +	} else if (afe->status > 0) {

> +		dev_err(afe->dev, "DSP returned error[%s]\n",

> +		       q6dsp_strerror(afe->status));

> +		ret = q6dsp_errno(afe->status);


If we time out here and the DSP delivers a response later it looks like
we'll get data corruption - the DSP will happily deliver the response
into shared state.

> +static int afe_port_start(struct q6afe_port *port,

> +			  union afe_port_config *afe_config)

> +{

> +	struct afe_audioif_config_command config = {0,};

> +	struct q6afe *afe = port->afe;

> +	int port_id = port->id;

> +	int ret, param_id = port->cfg_type;

> +

> +	config.port = *afe_config;

> +

> +	ret  = q6afe_port_set_param_v2(port, &config, param_id,

> +				       sizeof(*afe_config));

> +	if (ret) {

> +		dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n",

> +			port_id, ret);

> +		return ret;

> +	}

> +	return afe_send_cmd_port_start(port);


Why not just inline this function here?  It appears to have only this
user.

> +	int index = 0;


We set index to 0...
> +

> +	port_id = port->id;

> +	index = port->token;


...the unconditionally overwrite it?

> +/**

> + * q6afe_port_start() - Start a afe port

> + *

> + * @port: Instance of port to start

> + *

> + * Return: Will be an negative on packet size on success.

> + */

> +int q6afe_port_start(struct q6afe_port *port)

> +{

> +	return afe_port_start(port, &port->port_cfg);

> +}

> +EXPORT_SYMBOL_GPL(q6afe_port_start);


This is the third level of wrapper for the port start command in this
file.  Do we *really* need all these wrappers?

> +struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id)

> +{


> +	port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);

> +	if (!port)

> +		return ERR_PTR(-ENOMEM);


The _port_get_ function is allocating data but...

> +/**

> + * q6afe_port_put() - Release port reference

> + *

> + * @port: Instance of port to put

> + */

> +void q6afe_port_put(struct q6afe_port *port)

> +{

> +	struct q6afe *afe = port->afe;

> +

> +	spin_lock(&afe->port_list_lock);

> +	list_del(&port->node);

> +	spin_unlock(&afe->port_list_lock);

> +}

> +EXPORT_SYMBOL_GPL(q6afe_port_put);


...the _port_put() function isn't freeing it.  That seems leaky.  I'm
also a bit worried about this being a spinlock that we're using for
allocation, and not even spin_lock_irqsave().  Presumably this is
protecting against interrupts otherwise we'd not need a spinlock but
for that to work we'd need the _irqsave()?
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Mark Brown March 1, 2018, 9:28 p.m. UTC | #6
On Tue, Feb 13, 2018 at 04:58:22PM +0000, srinivas.kandagatla@linaro.org wrote:

> +	num_regions = is_contiguous ? 1 : periods;

> +	buf_sz = is_contiguous ? (period_sz * periods) : period_sz;


Please write normal if statements, it's much easier to read.

> +	buf_sz = PAGE_ALIGN(buf_sz);


I don't understand what this is doing, buf_sz is a length not an address
so why are we attempting to align it?
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Mark Brown March 1, 2018, 9:33 p.m. UTC | #7
On Tue, Feb 13, 2018 at 04:58:23PM +0000, srinivas.kandagatla@linaro.org wrote:

>  	uint32_t used;

> @@ -131,7 +191,7 @@ static int q6asm_apr_send_session_pkt(struct q6asm *a, struct audio_client *ac,

>  

>  	rc = wait_event_timeout(a->mem_wait, (a->mem_state <= 0), 5 * HZ);

>  	if (!rc) {

> -		dev_err(a->dev, "CMD timeout \n");

> +		dev_err(a->dev, "CMD timeout\n");

>  		rc = -ETIMEDOUT;

>  	} else if (a->mem_state < 0) {

>  		rc =  q6dsp_errno(a->mem_state);


This should be folded into whatever patch is being fixed.

> +	open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V3;

> +	open.mode_flags = 0x00;

> +	open.mode_flags |= ASM_LEGACY_STREAM_SESSION;


What is a legacy stream and why are we using it in new code?
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Mark Brown March 2, 2018, 12:50 p.m. UTC | #8
On Tue, Feb 13, 2018 at 04:58:26PM +0000, srinivas.kandagatla@linaro.org wrote:

> +static int q6hdmi_format_put(struct snd_kcontrol *kcontrol,

> +				struct snd_ctl_elem_value *ucontrol)

> +{

> +	struct q6afe_dai_data *dai_data = kcontrol->private_data;

> +	int value = ucontrol->value.integer.value[0];

> +

> +	dai_data->port_config[AFE_PORT_HDMI_RX].hdmi.datatype = value;

> +

> +	return 0;

> +}


No validation, and do we not need to tell a currently running stream if
the format changed on it (or block such changes if they're not going to
work, which seems more likely)?

> +static int q6hdmi_hw_params(struct snd_pcm_substream *substream,

> +				struct snd_pcm_hw_params *params,

> +				struct snd_soc_dai *dai)

> +{

> +	struct q6afe_dai_data *dai_data = q6afe_get_dai_data(dai->dev);

> +	int channels = params_channels(params);

> +	struct q6afe_hdmi_cfg *hdmi = &dai_data->port_config[dai->id].hdmi;

> +

> +	hdmi->sample_rate = params_rate(params);

> +	switch (params_format(params)) {

> +	case SNDRV_PCM_FORMAT_S16_LE:

> +		hdmi->bit_width = 16;

> +		break;

> +	case SNDRV_PCM_FORMAT_S24_LE:

> +		hdmi->bit_width = 24;

> +		break;

> +	}


This silently accepts invalid values.

> +	/*refer to HDMI spec CEA-861-E: Table 28 Audio InfoFrame Data Byte 4*/


Coding style, spaces around the /* */.

> +static int q6afe_dai_startup(struct snd_pcm_substream *substream,

> +				struct snd_soc_dai *dai)

> +{

> +	struct q6afe_dai_data *dai_data = q6afe_get_dai_data(dai->dev);

> +

> +	dai_data->is_port_started[dai->id] = false;

> +

> +	return 0;

> +}


If this is needed it makes me a bit worried that we've got some kind of
bug with not shutting things down properly somewhere - what's going on
here?

> +static void q6afe_dai_shutdown(struct snd_pcm_substream *substream,

> +				struct snd_soc_dai *dai)

> +{

> +	struct q6afe_dai_data *dai_data = q6afe_get_dai_data(dai->dev);

> +	int rc;

> +

> +	rc = q6afe_port_stop(dai_data->port[dai->id]);

> +	if (rc < 0)

> +		dev_err(dai->dev, "fail to close AFE port\n");


Better to print the error code so users have more information to debug
the problem.

> +			.stream_name = "HDMI Playback",

> +			.rates = SNDRV_PCM_RATE_48000 |

> +				 SNDRV_PCM_RATE_96000 |

> +			 SNDRV_PCM_RATE_192000,


Indentation again.

> +static int q6afe_of_xlate_dai_name(struct snd_soc_component *component,

> +				   struct of_phandle_args *args,

> +				   const char **dai_name)

> +{

> +	int id = args->args[0];

> +	int i, ret = -EINVAL;


Coding style, don't mix initialization in with other variable
declarations on the same line like this.

> +int q6afe_dai_dev_remove(struct device *dev)

> +{

> +	return 0;

> +}


Remove empty functions, if they can't be removed it's probably not OK
for them to be empty either.
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Srinivas Kandagatla March 2, 2018, 1:52 p.m. UTC | #9
Thanks for the review comments,

On 02/03/18 12:50, Mark Brown wrote:
> On Tue, Feb 13, 2018 at 04:58:26PM +0000, srinivas.kandagatla@linaro.org wrote:

> 

>> +static int q6hdmi_format_put(struct snd_kcontrol *kcontrol,

>> +				struct snd_ctl_elem_value *ucontrol)

>> +{

>> +	struct q6afe_dai_data *dai_data = kcontrol->private_data;

>> +	int value = ucontrol->value.integer.value[0];

>> +

>> +	dai_data->port_config[AFE_PORT_HDMI_RX].hdmi.datatype = value;

>> +

>> +	return 0;

>> +}

> 

> No validation, and do we not need to tell a currently running stream if

> the format changed on it (or block such changes if they're not going to

> work, which seems more likely)?

Yes, It would not work if the stream is running.
This mixer has to be setup before the stream/port is prepared/started.
TBH, I have no means to test Compr format, I should probably remove this 
control until am able to test this format.

> 

>> +static int q6hdmi_hw_params(struct snd_pcm_substream *substream,

>> +				struct snd_pcm_hw_params *params,

>> +				struct snd_soc_dai *dai)

>> +{

>> +	struct q6afe_dai_data *dai_data = q6afe_get_dai_data(dai->dev);

>> +	int channels = params_channels(params);

>> +	struct q6afe_hdmi_cfg *hdmi = &dai_data->port_config[dai->id].hdmi;

>> +

>> +	hdmi->sample_rate = params_rate(params);

>> +	switch (params_format(params)) {

>> +	case SNDRV_PCM_FORMAT_S16_LE:

>> +		hdmi->bit_width = 16;

>> +		break;

>> +	case SNDRV_PCM_FORMAT_S24_LE:

>> +		hdmi->bit_width = 24;

>> +		break;

>> +	}

> 

> This silently accepts invalid values.

> 

Yep, I will fix this in next version.

>> +	/*refer to HDMI spec CEA-861-E: Table 28 Audio InfoFrame Data Byte 4*/

> 

> Coding style, spaces around the /* */.

Agreed! Will fix it in next version.

> 

>> +static int q6afe_dai_startup(struct snd_pcm_substream *substream,

>> +				struct snd_soc_dai *dai)

>> +{

>> +	struct q6afe_dai_data *dai_data = q6afe_get_dai_data(dai->dev);

>> +

>> +	dai_data->is_port_started[dai->id] = false;

>> +

>> +	return 0;

>> +}

> 

> If this is needed it makes me a bit worried that we've got some kind of

> bug with not shutting things down properly somewhere - what's going on

> here?


This looks over done, we do not need to set this flag in startup, as it 
would be properly reset in shutdown.

Will remove this function totally as its not required.

> 

>> +static void q6afe_dai_shutdown(struct snd_pcm_substream *substream,

>> +				struct snd_soc_dai *dai)

>> +{

>> +	struct q6afe_dai_data *dai_data = q6afe_get_dai_data(dai->dev);

>> +	int rc;

>> +

>> +	rc = q6afe_port_stop(dai_data->port[dai->id]);

>> +	if (rc < 0)

>> +		dev_err(dai->dev, "fail to close AFE port\n");

> 

> Better to print the error code so users have more information to debug

> the problem.


Yep.

> 

>> +			.stream_name = "HDMI Playback",

>> +			.rates = SNDRV_PCM_RATE_48000 |

>> +				 SNDRV_PCM_RATE_96000 |

>> +			 SNDRV_PCM_RATE_192000,

> 

> Indentation again.

Will sort it out in next version.
> 

>> +static int q6afe_of_xlate_dai_name(struct snd_soc_component *component,

>> +				   struct of_phandle_args *args,

>> +				   const char **dai_name)

>> +{

>> +	int id = args->args[0];

>> +	int i, ret = -EINVAL;

> 

> Coding style, don't mix initialization in with other variable

> declarations on the same line like this.


Will fix all such instances in next version.

> 

>> +int q6afe_dai_dev_remove(struct device *dev)

>> +{

>> +	return 0;

>> +}

> 

> Remove empty functions, if they can't be removed it's probably not OK

> for them to be empty either.

Sure will do that.

> 

thanks,
srini
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Mark Brown March 2, 2018, 5:54 p.m. UTC | #10
On Fri, Mar 02, 2018 at 01:13:17PM +0000, Srinivas Kandagatla wrote:
> On 01/03/18 20:59, Mark Brown wrote:

> > On Tue, Feb 13, 2018 at 04:58:17PM +0000, srinivas.kandagatla@linaro.org wrote:


> > > +static struct afe_port_map port_maps[AFE_PORT_MAX] = {

> > > +	[AFE_PORT_HDMI_RX] = { AFE_PORT_ID_MULTICHAN_HDMI_RX,

> > > +				AFE_PORT_HDMI_RX, 1, 1},

> > > +};


> > Is this not device specific in any way?  It looks likely to be.


> It is specific to Audio firmware build.

> AFAIK, DSP port IDs are consistent across a given range of AVS firmware

> builds. So far I have seen them not change in any of the B family SoCs.

> However on older A family SOCs these are very different numbers. Which is

> where ADSP version info would help select correct map.


Can we have some documentation of this in the code please?

> > > +static struct q6afe_port *afe_find_port(struct q6afe *afe, int token)

> > > +{

> > > +	struct q6afe_port *p = NULL;

> > > +

> > > +	spin_lock(&afe->port_list_lock);

> > > +	list_for_each_entry(p, &afe->port_list, node)

> > > +		if (p->token == token)

> > > +			break;

> > > +

> > > +	spin_unlock(&afe->port_list_lock);


> > Why do we need to lock the port list, what are we protecting it against?


> This is just to protect the list from anyone deleting this.


> Its very rare but the use case could be somelike the adsp is up and we are

> in the middle of finding a port and then adsp went down or crashed we would

> delete an entry in the list.


If that's what we're protecting against then this also needs to do
something to ensure that the port we looked up doesn't get deallocated
before or while we look at it.

> > > +int q6afe_port_start(struct q6afe_port *port)

> > > +{

> > > +	return afe_port_start(port, &port->port_cfg);

> > > +}

> > > +EXPORT_SYMBOL_GPL(q6afe_port_start);


> > This is the third level of wrapper for the port start command in this

> > file.  Do we *really* need all these wrappers?


> Intention here is that we have plans to support different version of ADSP,

> on A family this command is different, so having this wrapper would help

> tackle this use-case.


Why not just take out the level of wrapper for now then add it in when
there's actually an abstraction in there?  The code might end up looking
different anyway.
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Srinivas Kandagatla March 2, 2018, 6:51 p.m. UTC | #11
Thanks for the review comments,


On 02/03/18 17:54, Mark Brown wrote:
> On Fri, Mar 02, 2018 at 01:13:17PM +0000, Srinivas Kandagatla wrote:

>> On 01/03/18 20:59, Mark Brown wrote:

>>> On Tue, Feb 13, 2018 at 04:58:17PM +0000, srinivas.kandagatla@linaro.org wrote:

> 

>>>> +static struct afe_port_map port_maps[AFE_PORT_MAX] = {

>>>> +	[AFE_PORT_HDMI_RX] = { AFE_PORT_ID_MULTICHAN_HDMI_RX,

>>>> +				AFE_PORT_HDMI_RX, 1, 1},

>>>> +};

> 

>>> Is this not device specific in any way?  It looks likely to be.

> 

>> It is specific to Audio firmware build.

>> AFAIK, DSP port IDs are consistent across a given range of AVS firmware

>> builds. So far I have seen them not change in any of the B family SoCs.

>> However on older A family SOCs these are very different numbers. Which is

>> where ADSP version info would help select correct map.

> 

> Can we have some documentation of this in the code please?

> 

Sure, I will add documentation in next version.

>>>> +static struct q6afe_port *afe_find_port(struct q6afe *afe, int token)

>>>> +{

>>>> +	struct q6afe_port *p = NULL;

>>>> +

>>>> +	spin_lock(&afe->port_list_lock);

>>>> +	list_for_each_entry(p, &afe->port_list, node)

>>>> +		if (p->token == token)

>>>> +			break;

>>>> +

>>>> +	spin_unlock(&afe->port_list_lock);

> 

>>> Why do we need to lock the port list, what are we protecting it against?

> 

>> This is just to protect the list from anyone deleting this.

> 

>> Its very rare but the use case could be somelike the adsp is up and we are

>> in the middle of finding a port and then adsp went down or crashed we would

>> delete an entry in the list.

> 

> If that's what we're protecting against then this also needs to do

> something to ensure that the port we looked up doesn't get deallocated

> before or while we look at it.

Yes, I will take closer look at all possible paths before sending next 
version.
> 

>>>> +int q6afe_port_start(struct q6afe_port *port)

>>>> +{

>>>> +	return afe_port_start(port, &port->port_cfg);

>>>> +}

>>>> +EXPORT_SYMBOL_GPL(q6afe_port_start);

> 

>>> This is the third level of wrapper for the port start command in this

>>> file.  Do we *really* need all these wrappers?

> 

>> Intention here is that we have plans to support different version of ADSP,

>> on A family this command is different, so having this wrapper would help

>> tackle this use-case.

> 

> Why not just take out the level of wrapper for now then add it in when

> there's actually an abstraction in there?  The code might end up looking

> different anyway.

Okay, I can do that, will remove extra abstraction layer.

thanks,
srini
> 

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Srinivas Kandagatla March 6, 2018, 9:26 a.m. UTC | #12
Thanks for the review,

On 01/03/18 21:28, Mark Brown wrote:
> On Tue, Feb 13, 2018 at 04:58:22PM +0000, srinivas.kandagatla@linaro.org wrote:

> 

>> +	num_regions = is_contiguous ? 1 : periods;

>> +	buf_sz = is_contiguous ? (period_sz * periods) : period_sz;

> 

> Please write normal if statements, it's much easier to read.

> 


Sure, will fix it in next version.
>> +	buf_sz = PAGE_ALIGN(buf_sz);

> 

> I don't understand what this is doing, buf_sz is a length not an address

> so why are we attempting to align it?


Yes, this is a requirement form the DSP side that the size is multiple 
of 4KB. I will fix this properly in next version.

thanks,
srini
> 

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel