2020-09-07 10:03:57

by Cheng-Yi Chiang

[permalink] [raw]
Subject: [PATCH v7 0/3] Add documentation and machine driver for SC7180 sound card

Note:
- The machine driver 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.
- This patch series needs HDMI DAI name defined in sc7180-lpass.h.
https://patchwork.kernel.org/patch/11745565/

Changes from v1 to v2:
- Ducumentation: Addressed all suggestions from Doug.
- Machine driver:
- Fix comment style for license.
- Sort includes.
- Remove sc7180_snd_hw_params.
- Remove sc7180_dai_init and use aux device instead for headset jack registration.
- Statically define format for Primary MI2S.
- Atomic is not a concern because there is mutex in card to make sure
startup and shutdown happen sequentially.
- Fix missing return -EINVAL in startup.
- Use static sound card.
- Use devm_kzalloc to avoid kfree.

Changes from v2 to v3:
- Ducumentation: Addressed suggestions from Srini.
- Machine driver:
- Reuse qcom_snd_parse_of to parse properties.
- Remove playback-only and capture-only.
- Misc fixes to address comments.

Changes from v3 to v4:
- Ducumentation: Addressed suggestions from Rob.
- Remove definition of dai.
- Use 'sound-dai: true' for sound-dai schema.
- Add reg property to pass 'make dt_binding_check' check although reg is not used in the driver.
- Machine driver:
- Add Reviewed-by: Tzung-Bi Shih <[email protected]>

Changes from v4 to v5:
- Documentation: Addressed suggestions from Rob.
- Add definition for "#address-cells" and "#size-cells".
- Add additionalProperties: false
- Add required properties.

Changes from v5 to v6:
- Documentation: Addressed suggestions from Rob.
- Drop contains in compatible strings.
- Only allow dai-link@[0-9]
- Remove reg ref since it has a type definition already.

Changes from v6 to v7
- Documentation:
- Add headset-jack and hdmi-jack to specify the codec
responsible for jack detection.
- HDMI codec driver:
- Use component set_jack ops instead of exporting hdmi_codec_set_jack_detect.
- Machine driver:
- Removed aux device following Stephan's suggestion.
- Use headset-jack and hdmi-jack to specify the codec
responsible for jack detection.
- Add support for HDMI(actually DP) playback.

Ajit Pandey (1):
ASoC: qcom: sc7180: Add machine driver for sound card registration

Cheng-Yi Chiang (2):
ASoC: hdmi-codec: Use set_jack ops to set jack
ASoC: qcom: dt-bindings: Add sc7180 machine bindings

.../bindings/sound/qcom,sc7180.yaml | 143 +++++++++
include/sound/hdmi-codec.h | 3 -
sound/soc/codecs/hdmi-codec.c | 12 +-
sound/soc/mediatek/mt8173/mt8173-rt5650.c | 5 +-
.../mediatek/mt8183/mt8183-da7219-max98357.c | 5 +-
.../mt8183/mt8183-mt6358-ts3a227-max98357.c | 5 +-
sound/soc/qcom/Kconfig | 12 +
sound/soc/qcom/Makefile | 2 +
sound/soc/qcom/sc7180.c | 288 ++++++++++++++++++
sound/soc/rockchip/rockchip_max98090.c | 3 +-
10 files changed, 456 insertions(+), 22 deletions(-)
create mode 100644 Documentation/devicetree/bindings/sound/qcom,sc7180.yaml
create mode 100644 sound/soc/qcom/sc7180.c

--
2.28.0.526.ge36021eeef-goog


2020-09-07 10:05:06

by Cheng-Yi Chiang

[permalink] [raw]
Subject: [PATCH v7 3/3] 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]>
Reviewed-by: Tzung-Bi Shih <[email protected]>
---
sound/soc/qcom/Kconfig | 12 ++
sound/soc/qcom/Makefile | 2 +
sound/soc/qcom/sc7180.c | 288 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 302 insertions(+)
create mode 100644 sound/soc/qcom/sc7180.c

diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig
index a607ace8b089..0459185ee243 100644
--- a/sound/soc/qcom/Kconfig
+++ b/sound/soc/qcom/Kconfig
@@ -116,4 +116,16 @@ config SND_SOC_SDM845
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 I2C
+ select SND_SOC_QCOM_COMMON
+ select SND_SOC_LPASS_SC7180
+ select SND_SOC_MAX98357A
+ select SND_SOC_RT5682_I2C
+ 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.
+
endif #SND_SOC_QCOM
diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile
index 7972c9479ab0..0cdcbf367ef1 100644
--- a/sound/soc/qcom/Makefile
+++ b/sound/soc/qcom/Makefile
@@ -17,12 +17,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..175a2f36842c
--- /dev/null
+++ b/sound/soc/qcom/sc7180.c
@@ -0,0 +1,288 @@
+// 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 <dt-bindings/sound/sc7180-lpass.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <uapi/linux/input-event-codes.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)
+
+struct sc7180_snd_data {
+ u32 pri_mi2s_clk_count;
+ struct snd_soc_jack hs_jack;
+ struct device_node *hs_jack_of_node;
+ struct snd_soc_jack hdmi_jack;
+ struct device_node *hdmi_jack_of_node;
+};
+
+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_headset_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct sc7180_snd_data *pdata = snd_soc_card_get_drvdata(card);
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+ struct snd_soc_component *component = codec_dai->component;
+ struct snd_jack *jack;
+ int rval;
+
+ 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->hs_jack, NULL, 0);
+
+ if (rval < 0) {
+ dev_err(card->dev, "Unable to add Headset Jack\n");
+ return rval;
+ }
+
+ jack = pdata->hs_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);
+
+ jack->private_data = component;
+ jack->private_free = sc7180_jack_free;
+
+ return snd_soc_component_set_jack(component, &pdata->hs_jack, NULL);
+}
+
+static int sc7180_hdmi_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct sc7180_snd_data *pdata = snd_soc_card_get_drvdata(card);
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+ struct snd_soc_component *component = codec_dai->component;
+ struct snd_jack *jack;
+ int rval;
+
+ rval = snd_soc_card_jack_new(
+ card, "HDMI Jack",
+ SND_JACK_LINEOUT,
+ &pdata->hdmi_jack, NULL, 0);
+
+ if (rval < 0) {
+ dev_err(card->dev, "Unable to add HDMI Jack\n");
+ return rval;
+ }
+
+ jack = pdata->hdmi_jack.jack;
+ jack->private_data = component;
+ jack->private_free = sc7180_jack_free;
+
+ return snd_soc_component_set_jack(component, &pdata->hdmi_jack, NULL);
+}
+
+static int sc7180_snd_startup(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);
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+ int ret;
+
+ switch (cpu_dai->id) {
+ case MI2S_PRIMARY:
+ 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,
+ SND_SOC_DAIFMT_CBS_CFS |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_I2S);
+
+ /* 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) {
+ 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)
+ dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n",
+ ret);
+
+ break;
+ case MI2S_SECONDARY:
+ break;
+ case HDMI:
+ break;
+ default:
+ dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
+ cpu_dai->id);
+ return -EINVAL;
+ }
+ 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;
+ case HDMI:
+ break;
+ default:
+ dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
+ cpu_dai->id);
+ break;
+ }
+}
+
+static const struct snd_soc_ops sc7180_ops = {
+ .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 struct snd_soc_card sc7180_card = {
+ .owner = THIS_MODULE,
+ .dapm_widgets = sc7180_snd_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sc7180_snd_widgets),
+};
+
+static int sc7180_parse_headset_jack_of(struct sc7180_snd_data *data, struct device *dev)
+{
+ data->hs_jack_of_node = of_parse_phandle(dev->of_node, "headset-jack", 0);
+ if (!data->hs_jack_of_node)
+ return -EINVAL;
+ return 0;
+}
+
+static int sc7180_parse_hdmi_jack_of(struct sc7180_snd_data *data, struct device *dev)
+{
+ data->hdmi_jack_of_node = of_parse_phandle(
+ dev->of_node, "hdmi-jack", 0);
+ if (!data->hdmi_jack_of_node)
+ return -EINVAL;
+ return 0;
+}
+
+static void sc7180_add_ops(struct snd_soc_card *card)
+{
+ struct snd_soc_dai_link *link;
+ int i;
+ struct sc7180_snd_data *pdata = snd_soc_card_get_drvdata(card);
+
+ for_each_card_prelinks(card, i, link) {
+ link->ops = &sc7180_ops;
+ if (link->codecs &&
+ link->codecs->of_node == pdata->hs_jack_of_node) {
+ link->init = sc7180_headset_init;
+ }
+ if (link->codecs &&
+ link->codecs->of_node == pdata->hdmi_jack_of_node) {
+ link->init = sc7180_hdmi_init;
+ }
+ }
+}
+
+static int sc7180_snd_platform_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &sc7180_card;
+ struct sc7180_snd_data *data;
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ /* Allocate the private data */
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ card->dev = dev;
+
+ ret = qcom_snd_parse_of(card);
+ if (ret) {
+ dev_err(dev, "Error parsing OF data\n");
+ return ret;
+ }
+
+ snd_soc_card_set_drvdata(card, data);
+
+ ret = sc7180_parse_headset_jack_of(data, dev);
+ if (ret) {
+ dev_err(dev, "Failed to parse OF for headset jack device\n");
+ return ret;
+ }
+
+ ret = sc7180_parse_hdmi_jack_of(data, dev);
+ if (ret) {
+ dev_err(dev, "Failed to parse OF for hdmi jack device\n");
+ return ret;
+ }
+
+ sc7180_add_ops(card);
+
+ return devm_snd_soc_register_card(dev, card);
+}
+
+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,
+ .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.526.ge36021eeef-goog

2020-09-07 17:51:20

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v7 3/3] 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 next-20200903]
[cannot apply to linux/master sound/for-next rockchip/for-next linus/master v5.9-rc4]
[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/Add-documentation-and-machine-driver-for-SC7180-sound-card/20200907-180250
base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
config: nios2-allyesconfig (attached as .config)
compiler: nios2-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=nios2

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: In function 'sc7180_snd_startup':
>> sound/soc/qcom/sc7180.c:144:7: error: 'HDMI' undeclared (first use in this function)
144 | case HDMI:
| ^~~~
sound/soc/qcom/sc7180.c:144:7: note: each undeclared identifier is reported only once for each function it appears in
sound/soc/qcom/sc7180.c: In function 'sc7180_snd_shutdown':
sound/soc/qcom/sc7180.c:172:7: error: 'HDMI' undeclared (first use in this function)
172 | case HDMI:
| ^~~~

# https://github.com/0day-ci/linux/commit/54ab0f3cb3682429fc199d9b30572f67a967b30b
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Cheng-Yi-Chiang/Add-documentation-and-machine-driver-for-SC7180-sound-card/20200907-180250
git checkout 54ab0f3cb3682429fc199d9b30572f67a967b30b
vim +/HDMI +144 sound/soc/qcom/sc7180.c

101
102 static int sc7180_snd_startup(struct snd_pcm_substream *substream)
103 {
104 struct snd_soc_pcm_runtime *rtd = substream->private_data;
105 struct snd_soc_card *card = rtd->card;
106 struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
107 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
108 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
109 int ret;
110
111 switch (cpu_dai->id) {
112 case MI2S_PRIMARY:
113 if (++data->pri_mi2s_clk_count == 1) {
114 snd_soc_dai_set_sysclk(cpu_dai,
115 LPASS_MCLK0,
116 DEFAULT_MCLK_RATE,
117 SNDRV_PCM_STREAM_PLAYBACK);
118 }
119
120 snd_soc_dai_set_fmt(codec_dai,
121 SND_SOC_DAIFMT_CBS_CFS |
122 SND_SOC_DAIFMT_NB_NF |
123 SND_SOC_DAIFMT_I2S);
124
125 /* Configure PLL1 for codec */
126 ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
127 DEFAULT_MCLK_RATE, RT5682_PLL1_FREQ);
128 if (ret) {
129 dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
130 return ret;
131 }
132
133 /* Configure sysclk for codec */
134 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1,
135 RT5682_PLL1_FREQ,
136 SND_SOC_CLOCK_IN);
137 if (ret)
138 dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n",
139 ret);
140
141 break;
142 case MI2S_SECONDARY:
143 break;
> 144 case HDMI:
145 break;
146 default:
147 dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
148 cpu_dai->id);
149 return -EINVAL;
150 }
151 return 0;
152 }
153

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


Attachments:
(No filename) (3.91 kB)
.config.gz (55.86 kB)
Download all attachments