2020-07-17 12:03:19

by Cheng-Yi Chiang

[permalink] [raw]
Subject: [PATCH 1/2] ASoC: qcom: dt-bindings: Add sc7180 machine bindings

Add devicetree bindings documentation file for sc7180 sound card.

Signed-off-by: Cheng-Yi Chiang <[email protected]>
---
.../bindings/sound/qcom,sc7180.yaml | 123 ++++++++++++++++++
1 file changed, 123 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/qcom,sc7180.yaml

diff --git a/Documentation/devicetree/bindings/sound/qcom,sc7180.yaml b/Documentation/devicetree/bindings/sound/qcom,sc7180.yaml
new file mode 100644
index 000000000000..d60d2880d991
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,sc7180.yaml
@@ -0,0 +1,123 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/qcom,sc7180.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies Inc. SC7180 ASoC sound card driver
+
+maintainers:
+ - Rohit kumar <[email protected]>
+ - Cheng-Yi Chiang <[email protected]>
+
+description: |
+ This binding describes the SC7180 sound card, which uses LPASS for audio.
+
+definitions:
+
+ link-name:
+ description: Indicates dai-link name and PCM stream name.
+ $ref: /schemas/types.yaml#/definitions/string
+ maxItems: 1
+
+ dai:
+ type: object
+ properties:
+ sound-dai:
+ maxItems: 1
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ description: phandle array of the codec or CPU DAI
+
+ required:
+ - sound-dai
+
+ unidirectional:
+ description: Specify direction of unidirectional dai link.
+ 0 for playback only. 1 for capture only.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,sc7180-sndcard
+
+ audio-routing:
+ $ref: /schemas/types.yaml#/definitions/non-unique-string-array
+ description: |-
+ A list of the connections between audio components. Each entry is a
+ pair of strings, the first being the connection's sink, the second
+ being the connection's source.
+
+ model:
+ $ref: /schemas/types.yaml#/definitions/string
+ description: User specified audio sound card name
+
+patternProperties:
+ "^dai-link-[0-9]+$":
+ description: |
+ Each subnode represents a dai link. Subnodes of each dai links would be
+ cpu/codec dais.
+
+ type: object
+
+ properties:
+ link-name:
+ $ref: "#/definitions/link-name"
+
+ unidirectional:
+ $ref: "#/definitions/unidirectional"
+
+ cpu:
+ $ref: "#/definitions/dai"
+
+ codec:
+ $ref: "#/definitions/dai"
+
+ required:
+ - link-name
+ - cpu
+ - codec
+
+ additionalProperties: false
+
+examples:
+
+ - |
+ snd {
+ compatible = "qcom,sc7180-sndcard";
+ model = "sc7180-snd-card";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&sec_mi2s_active &sec_mi2s_dout_active
+ &sec_mi2s_ws_active &pri_mi2s_active
+ &pri_mi2s_dout_active &pri_mi2s_ws_active
+ &pri_mi2s_din_active &pri_mi2s_mclk_active>;
+
+ audio-routing =
+ "Headphone Jack", "HPOL",
+ "Headphone Jack", "HPOR";
+
+ dai-link-0 {
+ link-name = "MultiMedia0";
+ cpu {
+ sound-dai = <&lpass_cpu 0>;
+ };
+
+ codec {
+ sound-dai = <&alc5682 0>;
+ };
+ };
+
+ dai-link-1 {
+ link-name = "MultiMedia1";
+ unidirectional = <0>;
+ cpu {
+ sound-dai = <&lpass_cpu 1>;
+ };
+
+ codec {
+ sound-dai = <&max98357a>;
+ };
+ };
+ };
--
2.28.0.rc0.105.gf9edc3c819-goog


2020-07-17 12:05:29

by Cheng-Yi Chiang

[permalink] [raw]
Subject: [PATCH 2/2] ASoC: qcom: sc7180: Add machine driver for sound card registration

From: Ajit Pandey <[email protected]>

Add new driver to register sound card on sc7180 trogdor board and
do the required configuration for lpass cpu dai and external codecs
connected over MI2S interfaces.

Signed-off-by: Ajit Pandey <[email protected]>
Signed-off-by: Cheng-Yi Chiang <[email protected]>
---
Note:
- This patch depends on this patch series so it is not ready to be merged now.
ASoC: qcom: Add support for SC7180 lpass variant https://patchwork.kernel.org/cover/11650649/
- The patch is made by the collaboration of
Cheng-Yi Chiang <[email protected]>
Rohit kumar <[email protected]>
Ajit Pandey <[email protected]>
But Ajit has left codeaurora.
- We may reduce the duplicate code of sc7180_parse_of and qcom_snd_parse_of in snd/soc/qcom/common.c.
However, qcom_snd_parse_of has specific logic with qdsp. In this initial version, to keep it simple,
I choose to only implement needed device property parsing by sc7180 sound card in sc7180_parse_of.

Thanks for the review!

sound/soc/qcom/Kconfig | 11 ++
sound/soc/qcom/Makefile | 2 +
sound/soc/qcom/sc7180.c | 410 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 423 insertions(+)
create mode 100644 sound/soc/qcom/sc7180.c

diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig
index cfca0f730c61..4adc2362865b 100644
--- a/sound/soc/qcom/Kconfig
+++ b/sound/soc/qcom/Kconfig
@@ -109,3 +109,14 @@ config SND_SOC_SDM845
To add support for audio on Qualcomm Technologies Inc.
SDM845 SoC-based systems.
Say Y if you want to use audio device on this SoCs.
+
+config SND_SOC_SC7180
+ tristate "SoC Machine driver for SC7180 boards"
+ depends on SND_SOC_QCOM
+ select SND_SOC_LPASS_SC7180
+ select SND_SOC_MAX98357A
+ select SND_SOC_RT5682
+ help
+ To add support for audio on Qualcomm Technologies Inc.
+ SC7180 SoC-based systems.
+ Say Y if you want to use audio device on this SoCs.
diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile
index 41b2c7a23a4d..3f6275d90526 100644
--- a/sound/soc/qcom/Makefile
+++ b/sound/soc/qcom/Makefile
@@ -15,12 +15,14 @@ snd-soc-storm-objs := storm.o
snd-soc-apq8016-sbc-objs := apq8016_sbc.o
snd-soc-apq8096-objs := apq8096.o
snd-soc-sdm845-objs := sdm845.o
+snd-soc-sc7180-objs := sc7180.o
snd-soc-qcom-common-objs := common.o

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-apq8096.o
obj-$(CONFIG_SND_SOC_SDM845) += snd-soc-sdm845.o
+obj-$(CONFIG_SND_SOC_SC7180) += snd-soc-sc7180.o
obj-$(CONFIG_SND_SOC_QCOM_COMMON) += snd-soc-qcom-common.o

#DSP lib
diff --git a/sound/soc/qcom/sc7180.c b/sound/soc/qcom/sc7180.c
new file mode 100644
index 000000000000..cbe6b487d432
--- /dev/null
+++ b/sound/soc/qcom/sc7180.c
@@ -0,0 +1,410 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * sc7180.c -- ALSA SoC Machine driver for SC7180
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/jack.h>
+#include <sound/soc.h>
+#include <uapi/linux/input-event-codes.h>
+#include <dt-bindings/sound/sc7180-lpass.h>
+#include "../codecs/rt5682.h"
+#include "common.h"
+#include "lpass.h"
+
+#define DEFAULT_SAMPLE_RATE_48K 48000
+#define DEFAULT_MCLK_RATE 19200000
+#define RT5682_PLL1_FREQ (48000 * 512)
+
+int sc7180_parse_of(struct snd_soc_card *card)
+{
+ struct device_node *np;
+ struct device_node *codec = NULL;
+ struct device_node *platform = NULL;
+ struct device_node *cpu = NULL;
+ struct device *dev = card->dev;
+ struct snd_soc_dai_link *link;
+ struct of_phandle_args args;
+ struct snd_soc_dai_link_component *dlc;
+ int ret, num_links, dir;
+
+ ret = snd_soc_of_parse_card_name(card, "model");
+ if (ret) {
+ dev_err(dev, "Error parsing card name: %d\n", ret);
+ return ret;
+ }
+
+ /* DAPM routes */
+ if (of_property_read_bool(dev->of_node, "audio-routing")) {
+ ret = snd_soc_of_parse_audio_routing(card,
+ "audio-routing");
+ if (ret)
+ return ret;
+ }
+
+ /* Populate links */
+ num_links = of_get_child_count(dev->of_node);
+
+ /* Allocate the DAI link array */
+ card->dai_link = kcalloc(num_links, sizeof(*link), GFP_KERNEL);
+ if (!card->dai_link)
+ return -ENOMEM;
+
+ card->num_links = num_links;
+ link = card->dai_link;
+
+ for_each_child_of_node(dev->of_node, np) {
+ dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL);
+ if (!dlc)
+ return -ENOMEM;
+
+ link->cpus = &dlc[0];
+ link->platforms = &dlc[1];
+
+ link->num_cpus = 1;
+ link->num_platforms = 1;
+
+ ret = of_property_read_string(np, "link-name", &link->name);
+ if (ret) {
+ dev_err(card->dev, "error getting codec dai_link name\n");
+ goto err;
+ }
+
+ of_property_read_u32(np, "unidirectional", &dir);
+ if (dir == 0)
+ link->playback_only = 1;
+ else if (dir == 1)
+ link->capture_only = 1;
+
+ cpu = of_get_child_by_name(np, "cpu");
+ codec = of_get_child_by_name(np, "codec");
+
+ if (!cpu) {
+ dev_err(dev, "%s: Can't find cpu DT node\n",
+ link->name);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = of_parse_phandle_with_args(cpu, "sound-dai",
+ "#sound-dai-cells", 0, &args);
+ if (ret) {
+ dev_err(card->dev, "%s: error getting cpu phandle\n",
+ link->name);
+ goto err;
+ }
+ link->cpus->of_node = args.np;
+ link->id = args.args[0];
+
+ ret = snd_soc_of_get_dai_name(cpu, &link->cpus->dai_name);
+ if (ret) {
+ dev_err(card->dev, "%s: error getting cpu dai name\n",
+ link->name);
+ goto err;
+ }
+
+ if (codec) {
+ ret = snd_soc_of_get_dai_link_codecs(dev, codec, link);
+ if (ret < 0) {
+ dev_err(card->dev, "%s: codec dai not found\n",
+ link->name);
+ goto err;
+ }
+ } else {
+ dlc = devm_kzalloc(dev, sizeof(*dlc), GFP_KERNEL);
+ if (!dlc)
+ return -ENOMEM;
+
+ link->codecs = dlc;
+ link->num_codecs = 1;
+
+ link->codecs->dai_name = "snd-soc-dummy-dai";
+ link->codecs->name = "snd-soc-dummy";
+ }
+
+ link->platforms->of_node = link->cpus->of_node;
+ link->stream_name = link->name;
+ link++;
+
+ of_node_put(cpu);
+ of_node_put(codec);
+ }
+
+ return 0;
+err:
+ of_node_put(np);
+ of_node_put(cpu);
+ of_node_put(codec);
+ of_node_put(platform);
+ kfree(card->dai_link);
+ return ret;
+}
+
+struct sc7180_snd_data {
+ struct snd_soc_jack jack;
+ bool jack_setup;
+ struct snd_soc_card *card;
+ u32 pri_mi2s_clk_count;
+};
+
+static int sc7180_snd_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+ int ret = 0;
+
+ switch (cpu_dai->id) {
+ case MI2S_PRIMARY:
+ break;
+ case MI2S_SECONDARY:
+ break;
+ default:
+ pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
+ break;
+ }
+ return ret;
+}
+
+static void sc7180_jack_free(struct snd_jack *jack)
+{
+ struct snd_soc_component *component = jack->private_data;
+
+ snd_soc_component_set_jack(component, NULL, NULL);
+}
+
+static int sc7180_dai_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_component *component;
+ struct snd_soc_card *card = rtd->card;
+ struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+ struct sc7180_snd_data *pdata = snd_soc_card_get_drvdata(card);
+ struct snd_jack *jack;
+ int rval;
+
+ if (!pdata->jack_setup) {
+ rval = snd_soc_card_jack_new(
+ card, "Headset Jack",
+ SND_JACK_HEADSET |
+ SND_JACK_HEADPHONE |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3,
+ &pdata->jack, NULL, 0);
+
+ if (rval < 0) {
+ dev_err(card->dev, "Unable to add Headphone Jack\n");
+ return rval;
+ }
+
+ jack = pdata->jack.jack;
+
+ snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_jack_set_key(jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+ snd_jack_set_key(jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+ snd_jack_set_key(jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
+ pdata->jack_setup = true;
+ }
+
+ switch (cpu_dai->id) {
+ case MI2S_PRIMARY:
+ jack = pdata->jack.jack;
+ component = codec_dai->component;
+
+ jack->private_data = component;
+ jack->private_free = sc7180_jack_free;
+ rval = snd_soc_component_set_jack(component,
+ &pdata->jack, NULL);
+ if (rval != 0 && rval != -EOPNOTSUPP) {
+ dev_warn(card->dev, "Failed to set jack: %d\n", rval);
+ return rval;
+ }
+ break;
+ case MI2S_SECONDARY:
+ break;
+ default:
+ pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
+ break;
+ }
+
+ return 0;
+}
+
+static int sc7180_snd_startup(struct snd_pcm_substream *substream)
+{
+ unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBS_CFS;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
+ struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+ int ret;
+
+ switch (cpu_dai->id) {
+ case MI2S_PRIMARY:
+ codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S;
+ if (++data->pri_mi2s_clk_count == 1) {
+ snd_soc_dai_set_sysclk(cpu_dai,
+ LPASS_MCLK0,
+ DEFAULT_MCLK_RATE,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ }
+ snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
+
+ /* Configure PLL1 for codec */
+ ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
+ DEFAULT_MCLK_RATE, RT5682_PLL1_FREQ);
+ if (ret < 0) {
+ dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
+ return ret;
+ }
+
+ /* Configure sysclk for codec */
+ ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1,
+ RT5682_PLL1_FREQ,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n",
+ ret);
+
+ break;
+ case MI2S_SECONDARY:
+ break;
+ default:
+ pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
+ break;
+ }
+ return 0;
+}
+
+static void sc7180_snd_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
+ struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+
+ switch (cpu_dai->id) {
+ case MI2S_PRIMARY:
+ if (--data->pri_mi2s_clk_count == 0) {
+ snd_soc_dai_set_sysclk(cpu_dai,
+ LPASS_MCLK0,
+ 0,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ }
+ break;
+ case MI2S_SECONDARY:
+ break;
+ default:
+ pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
+ break;
+ }
+}
+
+static const struct snd_soc_ops sc7180_be_ops = {
+ .hw_params = sc7180_snd_hw_params,
+ .startup = sc7180_snd_startup,
+ .shutdown = sc7180_snd_shutdown,
+};
+
+static const struct snd_soc_dapm_widget sc7180_snd_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+};
+
+static void sc7180_add_ops(struct snd_soc_card *card)
+{
+ struct snd_soc_dai_link *link;
+ int i;
+
+ for_each_card_prelinks(card, i, link) {
+ link->ops = &sc7180_be_ops;
+ link->init = sc7180_dai_init;
+ }
+}
+
+static int sc7180_snd_platform_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card;
+ struct sc7180_snd_data *data;
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ card = kzalloc(sizeof(*card), GFP_KERNEL);
+ if (!card)
+ return -ENOMEM;
+
+ /* Allocate the private data */
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto data_alloc_fail;
+ }
+
+ card->dapm_widgets = sc7180_snd_widgets;
+ card->num_dapm_widgets = ARRAY_SIZE(sc7180_snd_widgets);
+ card->dev = dev;
+ dev_set_drvdata(dev, card);
+ ret = sc7180_parse_of(card);
+ if (ret) {
+ dev_err(dev, "Error parsing OF data\n");
+ goto parse_dt_fail;
+ }
+
+ data->card = card;
+ snd_soc_card_set_drvdata(card, data);
+
+ sc7180_add_ops(card);
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(dev, "Sound card registration failed\n");
+ goto register_card_fail;
+ }
+ return ret;
+
+register_card_fail:
+ kfree(card->dai_link);
+parse_dt_fail:
+ kfree(data);
+data_alloc_fail:
+ kfree(card);
+ return ret;
+}
+
+static int sc7180_snd_platform_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = dev_get_drvdata(&pdev->dev);
+ struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
+
+ snd_soc_unregister_card(card);
+ kfree(card->dai_link);
+ kfree(data);
+ kfree(card);
+ return 0;
+}
+
+static const struct of_device_id sc7180_snd_device_id[] = {
+ { .compatible = "qcom,sc7180-sndcard" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, sc7180_snd_device_id);
+
+static struct platform_driver sc7180_snd_driver = {
+ .probe = sc7180_snd_platform_probe,
+ .remove = sc7180_snd_platform_remove,
+ .driver = {
+ .name = "msm-snd-sc7180",
+ .of_match_table = sc7180_snd_device_id,
+ },
+};
+module_platform_driver(sc7180_snd_driver);
+
+MODULE_DESCRIPTION("sc7180 ASoC Machine Driver");
+MODULE_LICENSE("GPL v2");
--
2.28.0.rc0.105.gf9edc3c819-goog

2020-07-17 14:45:54

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 2/2] ASoC: qcom: sc7180: Add machine driver for sound card registration

Hi Cheng-Yi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on asoc/for-next]
[also build test ERROR on linux/master linus/master v5.8-rc5 next-20200717]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/0day-ci/linux/commits/Cheng-Yi-Chiang/ASoC-qcom-dt-bindings-Add-sc7180-machine-bindings/20200717-200317
base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
config: riscv-allyesconfig (attached as .config)
compiler: riscv64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=riscv

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>

All errors (new ones prefixed by >>):

>> sound/soc/qcom/sc7180.c:17:10: fatal error: dt-bindings/sound/sc7180-lpass.h: No such file or directory
17 | #include <dt-bindings/sound/sc7180-lpass.h>
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

vim +17 sound/soc/qcom/sc7180.c

> 17 #include <dt-bindings/sound/sc7180-lpass.h>
18 #include "../codecs/rt5682.h"
19 #include "common.h"
20 #include "lpass.h"
21

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]


Attachments:
(No filename) (1.68 kB)
.config.gz (63.67 kB)
Download all attachments

2020-07-17 15:02:54

by Doug Anderson

[permalink] [raw]
Subject: Re: [PATCH 1/2] ASoC: qcom: dt-bindings: Add sc7180 machine bindings

Hi,

On Fri, Jul 17, 2020 at 5:02 AM Cheng-Yi Chiang <[email protected]> wrote:
>
> Add devicetree bindings documentation file for sc7180 sound card.
>
> Signed-off-by: Cheng-Yi Chiang <[email protected]>
> ---
> .../bindings/sound/qcom,sc7180.yaml | 123 ++++++++++++++++++
> 1 file changed, 123 insertions(+)

A bit of a mechanical review since my audio knowledge is not strong.


> create mode 100644 Documentation/devicetree/bindings/sound/qcom,sc7180.yaml
>
> diff --git a/Documentation/devicetree/bindings/sound/qcom,sc7180.yaml b/Documentation/devicetree/bindings/sound/qcom,sc7180.yaml
> new file mode 100644
> index 000000000000..d60d2880d991
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/qcom,sc7180.yaml
> @@ -0,0 +1,123 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/qcom,sc7180.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Qualcomm Technologies Inc. SC7180 ASoC sound card driver
> +
> +maintainers:
> + - Rohit kumar <[email protected]>
> + - Cheng-Yi Chiang <[email protected]>
> +
> +description: |
> + This binding describes the SC7180 sound card, which uses LPASS for audio.

nit: you don't need the pipe at the end of the "description" line.
That means that newlines are important and you don't need it.


> +definitions:

I haven't yet seen much yaml using definitions like this. It feels
like overkill for some of these properties, especially ones that are
only ever used once in the "properties:" section and are/or are really
simple.


> + link-name:
> + description: Indicates dai-link name and PCM stream name.
> + $ref: /schemas/types.yaml#/definitions/string
> + maxItems: 1
> +
> + dai:
> + type: object
> + properties:
> + sound-dai:
> + maxItems: 1
> + $ref: /schemas/types.yaml#/definitions/phandle-array
> + description: phandle array of the codec or CPU DAI
> +
> + required:
> + - sound-dai
> +
> + unidirectional:
> + description: Specify direction of unidirectional dai link.
> + 0 for playback only. 1 for capture only.
> + $ref: /schemas/types.yaml#/definitions/uint32

So if the property isn't there then it's _not_ unidirectional and if
it is there then this specifies the direction, right? I almost wonder
if this should just be two boolean properties, like:

playback-only;
capture-only;

...but I guess I'd leave it to Rob and/or Mark to say what they liked
better. In any case if you keep it how you have it then you should
use yaml to force it to be either 0 or 1 if present.


> +
> +properties:
> + compatible:
> + contains:
> + enum:
> + - qcom,sc7180-sndcard

Just:

properties:
compatible:
const: qcom,sc7180-sndcard



> + audio-routing:
> + $ref: /schemas/types.yaml#/definitions/non-unique-string-array
> + description: |-
> + A list of the connections between audio components. Each entry is a
> + pair of strings, the first being the connection's sink, the second
> + being the connection's source.

You don't need the "|-" after the "description:". That says newlines
are important but strip the newline from the end.


> + model:
> + $ref: /schemas/types.yaml#/definitions/string
> + description: User specified audio sound card name
> +
> +patternProperties:
> + "^dai-link-[0-9]+$":
> + description: |
> + Each subnode represents a dai link. Subnodes of each dai links would be
> + cpu/codec dais.

From looking at "simple-card.yaml", I'm gonna guess that instead of
encoding the link number in the name of the node that you should
actually use a unit address and a reg in the subnodes.

...also, again your description doesn't need the "|" at the end.
Maybe <https://yaml-multiline.info/> will be useful to you?


> + type: object
> +
> + properties:
> + link-name:
> + $ref: "#/definitions/link-name"
> +
> + unidirectional:
> + $ref: "#/definitions/unidirectional"
> +
> + cpu:
> + $ref: "#/definitions/dai"
> +
> + codec:
> + $ref: "#/definitions/dai"
> +
> + required:
> + - link-name
> + - cpu
> + - codec
> +
> + additionalProperties: false
> +
> +examples:
> +
> + - |
> + snd {

Can you use the full node name "sound" here?


> + compatible = "qcom,sc7180-sndcard";
> + model = "sc7180-snd-card";
> +
> + pinctrl-names = "default";
> + pinctrl-0 = <&sec_mi2s_active &sec_mi2s_dout_active
> + &sec_mi2s_ws_active &pri_mi2s_active
> + &pri_mi2s_dout_active &pri_mi2s_ws_active
> + &pri_mi2s_din_active &pri_mi2s_mclk_active>;

I think pinctrl is usually not in the dt examples.

...also, shouldn't the mi2s pinctrl be in the i2s nodes, not in the
overall sound node?


> + audio-routing =
> + "Headphone Jack", "HPOL",
> + "Headphone Jack", "HPOR";
> +
> + dai-link-0 {
> + link-name = "MultiMedia0";
> + cpu {
> + sound-dai = <&lpass_cpu 0>;
> + };
> +
> + codec {
> + sound-dai = <&alc5682 0>;
> + };
> + };
> +
> + dai-link-1 {
> + link-name = "MultiMedia1";
> + unidirectional = <0>;
> + cpu {
> + sound-dai = <&lpass_cpu 1>;
> + };
> +
> + codec {
> + sound-dai = <&max98357a>;
> + };
> + };
> + };
> --
> 2.28.0.rc0.105.gf9edc3c819-goog
>

2020-07-19 04:31:22

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 2/2] ASoC: qcom: sc7180: Add machine driver for sound card registration

Hi Cheng-Yi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on asoc/for-next]
[also build test ERROR on linux/master linus/master v5.8-rc5 next-20200717]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/0day-ci/linux/commits/Cheng-Yi-Chiang/ASoC-qcom-dt-bindings-Add-sc7180-machine-bindings/20200717-200317
base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
config: x86_64-allyesconfig (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project ed6b578040a85977026c93bf4188f996148f3218)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install x86_64 cross compiling tool for clang build
# apt-get install binutils-x86-64-linux-gnu
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>

All errors (new ones prefixed by >>):

>> sound/soc/qcom/sc7180.c:17:10: fatal error: 'dt-bindings/sound/sc7180-lpass.h' file not found
#include <dt-bindings/sound/sc7180-lpass.h>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

vim +17 sound/soc/qcom/sc7180.c

> 17 #include <dt-bindings/sound/sc7180-lpass.h>
18 #include "../codecs/rt5682.h"
19 #include "common.h"
20 #include "lpass.h"
21

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]


Attachments:
(No filename) (1.83 kB)
.config.gz (73.62 kB)
Download all attachments

2020-07-20 02:48:03

by Tzung-Bi Shih

[permalink] [raw]
Subject: Re: [PATCH 2/2] ASoC: qcom: sc7180: Add machine driver for sound card registration

On Fri, Jul 17, 2020 at 8:02 PM Cheng-Yi Chiang <[email protected]> wrote:
> diff --git a/sound/soc/qcom/sc7180.c b/sound/soc/qcom/sc7180.c
> new file mode 100644
> index 000000000000..cbe6b487d432
> --- /dev/null
> +++ b/sound/soc/qcom/sc7180.c
> @@ -0,0 +1,410 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2020, The Linux Foundation. All rights reserved.
> + *
> + * sc7180.c -- ALSA SoC Machine driver for SC7180
> + */
Use "//" for all lines (see https://lkml.org/lkml/2020/5/14/332).

> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of_device.h>
> +#include <sound/core.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/jack.h>
> +#include <sound/soc.h>
> +#include <uapi/linux/input-event-codes.h>
> +#include <dt-bindings/sound/sc7180-lpass.h>
> +#include "../codecs/rt5682.h"
> +#include "common.h"
> +#include "lpass.h"
Insert a blank line in between <...> and "..." and sort the list
alphabetically to make it less likely to conflict.

> +static int sc7180_snd_hw_params(struct snd_pcm_substream *substream,
> + struct snd_pcm_hw_params *params)
> +{
Dummy function? Or is it still work in progress?

> + struct snd_soc_pcm_runtime *rtd = substream->private_data;
> + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
> + int ret = 0;
> +
> + switch (cpu_dai->id) {
> + case MI2S_PRIMARY:
> + break;
> + case MI2S_SECONDARY:
> + break;
> + default:
> + pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
-EINVAL.

> +static int sc7180_dai_init(struct snd_soc_pcm_runtime *rtd)
> +{
> + struct snd_soc_component *component;
> + struct snd_soc_card *card = rtd->card;
> + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
> + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
> + struct sc7180_snd_data *pdata = snd_soc_card_get_drvdata(card);
> + struct snd_jack *jack;
> + int rval;
> +
> + if (!pdata->jack_setup) {
> + rval = snd_soc_card_jack_new(
> + card, "Headset Jack",
> + SND_JACK_HEADSET |
> + SND_JACK_HEADPHONE |
> + SND_JACK_BTN_0 | SND_JACK_BTN_1 |
> + SND_JACK_BTN_2 | SND_JACK_BTN_3,
> + &pdata->jack, NULL, 0);
> +
> + if (rval < 0) {
> + dev_err(card->dev, "Unable to add Headphone Jack\n");
> + return rval;
> + }
> +
> + jack = pdata->jack.jack;
> +
> + snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
> + snd_jack_set_key(jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
> + snd_jack_set_key(jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
> + snd_jack_set_key(jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
> + pdata->jack_setup = true;
This block is something I don't expect to be in "dai_init" (i.e. there
is only 1 headset jack, why do we need to run the code for n times).

> + switch (cpu_dai->id) {
> + case MI2S_PRIMARY:
> + jack = pdata->jack.jack;
> + component = codec_dai->component;
> +
> + jack->private_data = component;
> + jack->private_free = sc7180_jack_free;
> + rval = snd_soc_component_set_jack(component,
> + &pdata->jack, NULL);
> + if (rval != 0 && rval != -EOPNOTSUPP) {
> + dev_warn(card->dev, "Failed to set jack: %d\n", rval);
> + return rval;
> + }
> + break;
> + case MI2S_SECONDARY:
> + break;
> + default:
> + pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
-EINVAL.

> +static int sc7180_snd_startup(struct snd_pcm_substream *substream)
> +{
> + unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBS_CFS;
> + struct snd_soc_pcm_runtime *rtd = substream->private_data;
> + struct snd_soc_card *card = rtd->card;
> + struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
> + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
> + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
> + int ret;
> +
> + switch (cpu_dai->id) {
> + case MI2S_PRIMARY:
> + codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S;
If the format is fixed, could it put somewhere statically?

> + if (++data->pri_mi2s_clk_count == 1) {
Don't it need to be atomic?

> + snd_soc_dai_set_sysclk(cpu_dai,
> + LPASS_MCLK0,
> + DEFAULT_MCLK_RATE,
> + SNDRV_PCM_STREAM_PLAYBACK);
> + }
> + snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
> +
> + /* Configure PLL1 for codec */
> + ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
> + DEFAULT_MCLK_RATE, RT5682_PLL1_FREQ);
> + if (ret < 0) {
> + dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
> + return ret;
> + }
> +
> + /* Configure sysclk for codec */
> + ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1,
> + RT5682_PLL1_FREQ,
> + SND_SOC_CLOCK_IN);
> + if (ret < 0)
> + dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n",
> + ret);
> +
> + break;
> + case MI2S_SECONDARY:
> + break;
> + default:
> + pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
-EINVAL.

> +static void sc7180_snd_shutdown(struct snd_pcm_substream *substream)
> +{
> + struct snd_soc_pcm_runtime *rtd = substream->private_data;
> + struct snd_soc_card *card = rtd->card;
> + struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
> + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
> +
> + switch (cpu_dai->id) {
> + case MI2S_PRIMARY:
> + if (--data->pri_mi2s_clk_count == 0) {
Atomic?

> + snd_soc_dai_set_sysclk(cpu_dai,
> + LPASS_MCLK0,
> + 0,
> + SNDRV_PCM_STREAM_PLAYBACK);
> + }
> + break;
> + case MI2S_SECONDARY:
> + break;
> + default:
> + pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
-EINVAL.

> +static int sc7180_snd_platform_probe(struct platform_device *pdev)
> +{
> + struct snd_soc_card *card;
> + struct sc7180_snd_data *data;
> + struct device *dev = &pdev->dev;
> + int ret;
> +
> + card = kzalloc(sizeof(*card), GFP_KERNEL);
> + if (!card)
> + return -ENOMEM;
Looks like you don't need to allocate the card in runtime. Also you
need to use the devm version if needed.

> + /* Allocate the private data */
> + data = kzalloc(sizeof(*data), GFP_KERNEL);
Use devm.

> + card->dapm_widgets = sc7180_snd_widgets;
> + card->num_dapm_widgets = ARRAY_SIZE(sc7180_snd_widgets);
Can the struct snd_soc_card allocate statically?

> + sc7180_add_ops(card);
> + ret = snd_soc_register_card(card);
devm.


I didn't dive into the logic too much. Would need another round
review if any newer version.

2020-07-21 11:31:45

by Cheng-Yi Chiang

[permalink] [raw]
Subject: Re: [PATCH 1/2] ASoC: qcom: dt-bindings: Add sc7180 machine bindings

On Fri, Jul 17, 2020 at 11:03 PM Doug Anderson <[email protected]> wrote:
>
> Hi,
>

Thanks for the review!

> On Fri, Jul 17, 2020 at 5:02 AM Cheng-Yi Chiang <[email protected]> wrote:
> >
> > Add devicetree bindings documentation file for sc7180 sound card.
> >
> > Signed-off-by: Cheng-Yi Chiang <[email protected]>
> > ---
> > .../bindings/sound/qcom,sc7180.yaml | 123 ++++++++++++++++++
> > 1 file changed, 123 insertions(+)
>
> A bit of a mechanical review since my audio knowledge is not strong.
>
>
> > create mode 100644 Documentation/devicetree/bindings/sound/qcom,sc7180.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/sound/qcom,sc7180.yaml b/Documentation/devicetree/bindings/sound/qcom,sc7180.yaml
> > new file mode 100644
> > index 000000000000..d60d2880d991
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/sound/qcom,sc7180.yaml
> > @@ -0,0 +1,123 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/sound/qcom,sc7180.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Qualcomm Technologies Inc. SC7180 ASoC sound card driver
> > +
> > +maintainers:
> > + - Rohit kumar <[email protected]>
> > + - Cheng-Yi Chiang <[email protected]>
> > +
> > +description: |
> > + This binding describes the SC7180 sound card, which uses LPASS for audio.
>
> nit: you don't need the pipe at the end of the "description" line.
> That means that newlines are important and you don't need it.
>
>
Thanks for the explanation. Fixed in v2.
> > +definitions:
>
> I haven't yet seen much yaml using definitions like this. It feels
> like overkill for some of these properties, especially ones that are
> only ever used once in the "properties:" section and are/or are really
> simple.
>
>
ACK. In v2 I only kept dai definition and removed others.

> > + link-name:
> > + description: Indicates dai-link name and PCM stream name.
> > + $ref: /schemas/types.yaml#/definitions/string
> > + maxItems: 1
> > +
> > + dai:
> > + type: object
> > + properties:
> > + sound-dai:
> > + maxItems: 1
> > + $ref: /schemas/types.yaml#/definitions/phandle-array
> > + description: phandle array of the codec or CPU DAI
> > +
> > + required:
> > + - sound-dai
> > +
> > + unidirectional:
> > + description: Specify direction of unidirectional dai link.
> > + 0 for playback only. 1 for capture only.
> > + $ref: /schemas/types.yaml#/definitions/uint32
>
> So if the property isn't there then it's _not_ unidirectional and if
> it is there then this specifies the direction, right? I almost wonder
> if this should just be two boolean properties, like:
>
> playback-only;
> capture-only;
>
> ...but I guess I'd leave it to Rob and/or Mark to say what they liked
> better. In any case if you keep it how you have it then you should
> use yaml to force it to be either 0 or 1 if present.
>
>
ACK
Use playback-only and capture-only in v2 instead.

> > +
> > +properties:
> > + compatible:
> > + contains:
> > + enum:
> > + - qcom,sc7180-sndcard
>
> Just:
>
> properties:
> compatible:
> const: qcom,sc7180-sndcard
>
>

Fixed in v2.

>
> > + audio-routing:
> > + $ref: /schemas/types.yaml#/definitions/non-unique-string-array
> > + description: |-
> > + A list of the connections between audio components. Each entry is a
> > + pair of strings, the first being the connection's sink, the second
> > + being the connection's source.
>
> You don't need the "|-" after the "description:". That says newlines
> are important but strip the newline from the end.
>
Fixed in v2.
>
> > + model:
> > + $ref: /schemas/types.yaml#/definitions/string
> > + description: User specified audio sound card name
> > +
> > +patternProperties:
> > + "^dai-link-[0-9]+$":
> > + description: |
> > + Each subnode represents a dai link. Subnodes of each dai links would be
> > + cpu/codec dais.
>
> From looking at "simple-card.yaml", I'm gonna guess that instead of
> encoding the link number in the name of the node that you should
> actually use a unit address and a reg in the subnodes.

Thanks for the explanation. Fixed in v2.
I think this naming is better, although there is no usage in the
machine driver for the reg.

>
> ...also, again your description doesn't need the "|" at the end.
> Maybe <https://yaml-multiline.info/> will be useful to you?
>
>

Thanks for the explanation and the pointer!

> > + type: object
> > +
> > + properties:
> > + link-name:
> > + $ref: "#/definitions/link-name"
> > +
> > + unidirectional:
> > + $ref: "#/definitions/unidirectional"
> > +
> > + cpu:
> > + $ref: "#/definitions/dai"
> > +
> > + codec:
> > + $ref: "#/definitions/dai"
> > +
> > + required:
> > + - link-name
> > + - cpu
> > + - codec
> > +
> > + additionalProperties: false
> > +
> > +examples:
> > +
> > + - |
> > + snd {
>
> Can you use the full node name "sound" here?
>
>
Fixed in v2.
> > + compatible = "qcom,sc7180-sndcard";
> > + model = "sc7180-snd-card";
> > +
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&sec_mi2s_active &sec_mi2s_dout_active
> > + &sec_mi2s_ws_active &pri_mi2s_active
> > + &pri_mi2s_dout_active &pri_mi2s_ws_active
> > + &pri_mi2s_din_active &pri_mi2s_mclk_active>;
>
> I think pinctrl is usually not in the dt examples.
>
Fixed in v2.

> ...also, shouldn't the mi2s pinctrl be in the i2s nodes, not in the
> overall sound node?

Yes. Thanks for pointing this out. Fixed in dts file in chromium.

>
>
> > + audio-routing =
> > + "Headphone Jack", "HPOL",
> > + "Headphone Jack", "HPOR";
> > +
> > + dai-link-0 {
> > + link-name = "MultiMedia0";
> > + cpu {
> > + sound-dai = <&lpass_cpu 0>;
> > + };
> > +
> > + codec {
> > + sound-dai = <&alc5682 0>;
> > + };
> > + };
> > +
> > + dai-link-1 {
> > + link-name = "MultiMedia1";
> > + unidirectional = <0>;
> > + cpu {
> > + sound-dai = <&lpass_cpu 1>;
> > + };
> > +
> > + codec {
> > + sound-dai = <&max98357a>;
> > + };
> > + };
> > + };
> > --
> > 2.28.0.rc0.105.gf9edc3c819-goog
> >

2020-07-21 11:37:22

by Cheng-Yi Chiang

[permalink] [raw]
Subject: Re: [PATCH 2/2] ASoC: qcom: sc7180: Add machine driver for sound card registration

Hi Tzung-Bi,
Thanks for the review!
On Mon, Jul 20, 2020 at 10:47 AM Tzung-Bi Shih <[email protected]> wrote:
>
> On Fri, Jul 17, 2020 at 8:02 PM Cheng-Yi Chiang <[email protected]> wrote:
> > diff --git a/sound/soc/qcom/sc7180.c b/sound/soc/qcom/sc7180.c
> > new file mode 100644
> > index 000000000000..cbe6b487d432
> > --- /dev/null
> > +++ b/sound/soc/qcom/sc7180.c
> > @@ -0,0 +1,410 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (c) 2020, The Linux Foundation. All rights reserved.
> > + *
> > + * sc7180.c -- ALSA SoC Machine driver for SC7180
> > + */
> Use "//" for all lines (see https://lkml.org/lkml/2020/5/14/332).
>

Thanks for the pointer. Fixed in v2.

> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/of_device.h>
> > +#include <sound/core.h>
> > +#include <sound/pcm.h>
> > +#include <sound/pcm_params.h>
> > +#include <sound/jack.h>
> > +#include <sound/soc.h>
> > +#include <uapi/linux/input-event-codes.h>
> > +#include <dt-bindings/sound/sc7180-lpass.h>
> > +#include "../codecs/rt5682.h"
> > +#include "common.h"
> > +#include "lpass.h"
> Insert a blank line in between <...> and "..." and sort the list
> alphabetically to make it less likely to conflict.

Fixed in v2.

>
> > +static int sc7180_snd_hw_params(struct snd_pcm_substream *substream,
> > + struct snd_pcm_hw_params *params)
> > +{
> Dummy function? Or is it still work in progress?
>
Removed in v2.

> > + struct snd_soc_pcm_runtime *rtd = substream->private_data;
> > + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
> > + int ret = 0;
> > +
> > + switch (cpu_dai->id) {
> > + case MI2S_PRIMARY:
> > + break;
> > + case MI2S_SECONDARY:
> > + break;
> > + default:
> > + pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
> -EINVAL.
>
Removed in v2.
> > +static int sc7180_dai_init(struct snd_soc_pcm_runtime *rtd)
> > +{
> > + struct snd_soc_component *component;
> > + struct snd_soc_card *card = rtd->card;
> > + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
> > + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
> > + struct sc7180_snd_data *pdata = snd_soc_card_get_drvdata(card);
> > + struct snd_jack *jack;
> > + int rval;
> > +
> > + if (!pdata->jack_setup) {
> > + rval = snd_soc_card_jack_new(
> > + card, "Headset Jack",
> > + SND_JACK_HEADSET |
> > + SND_JACK_HEADPHONE |
> > + SND_JACK_BTN_0 | SND_JACK_BTN_1 |
> > + SND_JACK_BTN_2 | SND_JACK_BTN_3,
> > + &pdata->jack, NULL, 0);
> > +
> > + if (rval < 0) {
> > + dev_err(card->dev, "Unable to add Headphone Jack\n");
> > + return rval;
> > + }
> > +
> > + jack = pdata->jack.jack;
> > +
> > + snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
> > + snd_jack_set_key(jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
> > + snd_jack_set_key(jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
> > + snd_jack_set_key(jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
> > + pdata->jack_setup = true;
> This block is something I don't expect to be in "dai_init" (i.e. there
> is only 1 headset jack, why do we need to run the code for n times).
>
Thanks for the suggestion. In v2 I am using aux device so this
function is cleaned up to be specific to aux device for jack
detection.

> > + switch (cpu_dai->id) {
> > + case MI2S_PRIMARY:
> > + jack = pdata->jack.jack;
> > + component = codec_dai->component;
> > +
> > + jack->private_data = component;
> > + jack->private_free = sc7180_jack_free;
> > + rval = snd_soc_component_set_jack(component,
> > + &pdata->jack, NULL);
> > + if (rval != 0 && rval != -EOPNOTSUPP) {
> > + dev_warn(card->dev, "Failed to set jack: %d\n", rval);
> > + return rval;
> > + }
> > + break;
> > + case MI2S_SECONDARY:
> > + break;
> > + default:
> > + pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
> -EINVAL.
>
Removed in v2.
> > +static int sc7180_snd_startup(struct snd_pcm_substream *substream)
> > +{
> > + unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBS_CFS;
> > + struct snd_soc_pcm_runtime *rtd = substream->private_data;
> > + struct snd_soc_card *card = rtd->card;
> > + struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
> > + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
> > + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
> > + int ret;
> > +
> > + switch (cpu_dai->id) {
> > + case MI2S_PRIMARY:
> > + codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S;
> If the format is fixed, could it put somewhere statically?
>
Fixed in v2.
> > + if (++data->pri_mi2s_clk_count == 1) {
> Don't it need to be atomic?
>
soc_pcm_open and soc_pcm_close are protected by card->pcm_mutex so
they will happen in sequence.

> > + snd_soc_dai_set_sysclk(cpu_dai,
> > + LPASS_MCLK0,
> > + DEFAULT_MCLK_RATE,
> > + SNDRV_PCM_STREAM_PLAYBACK);
> > + }
> > + snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
> > +
> > + /* Configure PLL1 for codec */
> > + ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
> > + DEFAULT_MCLK_RATE, RT5682_PLL1_FREQ);
> > + if (ret < 0) {
> > + dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
> > + return ret;
> > + }
> > +
> > + /* Configure sysclk for codec */
> > + ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1,
> > + RT5682_PLL1_FREQ,
> > + SND_SOC_CLOCK_IN);
> > + if (ret < 0)
> > + dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n",
> > + ret);
> > +
> > + break;
> > + case MI2S_SECONDARY:
> > + break;
> > + default:
> > + pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
> -EINVAL.
Fixed in v2
>
> > +static void sc7180_snd_shutdown(struct snd_pcm_substream *substream)
> > +{
> > + struct snd_soc_pcm_runtime *rtd = substream->private_data;
> > + struct snd_soc_card *card = rtd->card;
> > + struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
> > + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
> > +
> > + switch (cpu_dai->id) {
> > + case MI2S_PRIMARY:
> > + if (--data->pri_mi2s_clk_count == 0) {
> Atomic?
ditto
>
> > + snd_soc_dai_set_sysclk(cpu_dai,
> > + LPASS_MCLK0,
> > + 0,
> > + SNDRV_PCM_STREAM_PLAYBACK);
> > + }
> > + break;
> > + case MI2S_SECONDARY:
> > + break;
> > + default:
> > + pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
> -EINVAL.
>
not needed since this returns void
> > +static int sc7180_snd_platform_probe(struct platform_device *pdev)
> > +{
> > + struct snd_soc_card *card;
> > + struct sc7180_snd_data *data;
> > + struct device *dev = &pdev->dev;
> > + int ret;
> > +
> > + card = kzalloc(sizeof(*card), GFP_KERNEL);
> > + if (!card)
> > + return -ENOMEM;
> Looks like you don't need to allocate the card in runtime. Also you
> need to use the devm version if needed.
>
Thanks for the great suggestion. In v2 I am using a static sound card.
Also, use devm wherever possible to greatly simplify the code.

> > + /* Allocate the private data */
> > + data = kzalloc(sizeof(*data), GFP_KERNEL);
> Use devm.
>
Fixed in v2.
> > + card->dapm_widgets = sc7180_snd_widgets;
> > + card->num_dapm_widgets = ARRAY_SIZE(sc7180_snd_widgets);
> Can the struct snd_soc_card allocate statically?
>
Fixed in v2.
> > + sc7180_add_ops(card);
> > + ret = snd_soc_register_card(card);
> devm.
>
>
> I didn't dive into the logic too much. Would need another round
> review if any newer version.

Thanks again.