From: Cheng-Yi Chiang <cychiang@chromium.org>
To: linux-kernel@vger.kernel.org
Cc: Mark Brown <broonie@kernel.org>, Taniya Das <tdas@codeaurora.org>,
Rohit kumar <rohitkr@codeaurora.org>,
Banajit Goswami <bgoswami@codeaurora.org>,
Patrick Lai <plai@codeaurora.org>, Andy Gross <agross@kernel.org>,
Bjorn Andersson <bjorn.andersson@linaro.org>,
Liam Girdwood <lgirdwood@gmail.com>,
Rob Herring <robh+dt@kernel.org>,
Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>,
Srini Kandagatla <srinivas.kandagatla@linaro.org>,
Stephan Gerhold <stephan@gerhold.net>,
Matthias Brugger <matthias.bgg@gmail.com>,
Heiko Stuebner <heiko@sntech.de>,
dianders@chromium.org, dgreid@chromium.org, tzungbi@chromium.org,
linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org,
alsa-devel@alsa-project.org, linux-mediatek@lists.infradead.org,
linux-rockchip@lists.infradead.org,
Ajit Pandey <ajitp@codeaurora.org>,
Cheng-Yi Chiang <cychiang@chromium.org>,
Tzung-Bi Shih <tzungbi@google.com>
Subject: [PATCH v7 3/3] ASoC: qcom: sc7180: Add machine driver for sound card registration
Date: Mon, 7 Sep 2020 18:00:39 +0800 [thread overview]
Message-ID: <20200907100039.1731457-4-cychiang@chromium.org> (raw)
In-Reply-To: <20200907100039.1731457-1-cychiang@chromium.org>
From: Ajit Pandey <ajitp@codeaurora.org>
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 <ajitp@codeaurora.org>
Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
Reviewed-by: Tzung-Bi Shih <tzungbi@google.com>
---
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
WARNING: multiple messages have this Message-ID (diff)
From: Cheng-Yi Chiang <cychiang@chromium.org>
To: linux-kernel@vger.kernel.org
Cc: Taniya Das <tdas@codeaurora.org>,
alsa-devel@alsa-project.org,
Banajit Goswami <bgoswami@codeaurora.org>,
Heiko Stuebner <heiko@sntech.de>,
Liam Girdwood <lgirdwood@gmail.com>,
Rohit kumar <rohitkr@codeaurora.org>,
Cheng-Yi Chiang <cychiang@chromium.org>,
Tzung-Bi Shih <tzungbi@google.com>,
Patrick Lai <plai@codeaurora.org>,
Ajit Pandey <ajitp@codeaurora.org>,
linux-rockchip@lists.infradead.org,
Andy Gross <agross@kernel.org>,
dgreid@chromium.org, devicetree@vger.kernel.org,
tzungbi@chromium.org, Stephan Gerhold <stephan@gerhold.net>,
linux-arm-msm@vger.kernel.org, Rob Herring <robh+dt@kernel.org>,
linux-mediatek@lists.infradead.org,
Matthias Brugger <matthias.bgg@gmail.com>,
Bjorn Andersson <bjorn.andersson@linaro.org>,
linux-arm-kernel@lists.infradead.org, dianders@chromium.org,
Takashi Iwai <tiwai@suse.com>, Mark Brown <broonie@kernel.org>,
Srini Kandagatla <srinivas.kandagatla@linaro.org>
Subject: [PATCH v7 3/3] ASoC: qcom: sc7180: Add machine driver for sound card registration
Date: Mon, 7 Sep 2020 18:00:39 +0800 [thread overview]
Message-ID: <20200907100039.1731457-4-cychiang@chromium.org> (raw)
In-Reply-To: <20200907100039.1731457-1-cychiang@chromium.org>
From: Ajit Pandey <ajitp@codeaurora.org>
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 <ajitp@codeaurora.org>
Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
Reviewed-by: Tzung-Bi Shih <tzungbi@google.com>
---
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
WARNING: multiple messages have this Message-ID (diff)
From: Cheng-Yi Chiang <cychiang@chromium.org>
To: linux-kernel@vger.kernel.org
Cc: Taniya Das <tdas@codeaurora.org>,
alsa-devel@alsa-project.org,
Banajit Goswami <bgoswami@codeaurora.org>,
Heiko Stuebner <heiko@sntech.de>,
Liam Girdwood <lgirdwood@gmail.com>,
Rohit kumar <rohitkr@codeaurora.org>,
Cheng-Yi Chiang <cychiang@chromium.org>,
Tzung-Bi Shih <tzungbi@google.com>,
Patrick Lai <plai@codeaurora.org>,
Ajit Pandey <ajitp@codeaurora.org>,
linux-rockchip@lists.infradead.org,
Andy Gross <agross@kernel.org>,
dgreid@chromium.org, Jaroslav Kysela <perex@perex.cz>,
devicetree@vger.kernel.org, tzungbi@chromium.org,
Stephan Gerhold <stephan@gerhold.net>,
linux-arm-msm@vger.kernel.org, Rob Herring <robh+dt@kernel.org>,
linux-mediatek@lists.infradead.org,
Matthias Brugger <matthias.bgg@gmail.com>,
Bjorn Andersson <bjorn.andersson@linaro.org>,
linux-arm-kernel@lists.infradead.org, dianders@chromium.org,
Takashi Iwai <tiwai@suse.com>, Mark Brown <broonie@kernel.org>,
Srini Kandagatla <srinivas.kandagatla@linaro.org>
Subject: [PATCH v7 3/3] ASoC: qcom: sc7180: Add machine driver for sound card registration
Date: Mon, 7 Sep 2020 18:00:39 +0800 [thread overview]
Message-ID: <20200907100039.1731457-4-cychiang@chromium.org> (raw)
In-Reply-To: <20200907100039.1731457-1-cychiang@chromium.org>
From: Ajit Pandey <ajitp@codeaurora.org>
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 <ajitp@codeaurora.org>
Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
Reviewed-by: Tzung-Bi Shih <tzungbi@google.com>
---
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
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
WARNING: multiple messages have this Message-ID (diff)
From: Cheng-Yi Chiang <cychiang@chromium.org>
To: linux-kernel@vger.kernel.org
Cc: Taniya Das <tdas@codeaurora.org>,
alsa-devel@alsa-project.org,
Banajit Goswami <bgoswami@codeaurora.org>,
Heiko Stuebner <heiko@sntech.de>,
Liam Girdwood <lgirdwood@gmail.com>,
Rohit kumar <rohitkr@codeaurora.org>,
Cheng-Yi Chiang <cychiang@chromium.org>,
Tzung-Bi Shih <tzungbi@google.com>,
Patrick Lai <plai@codeaurora.org>,
Ajit Pandey <ajitp@codeaurora.org>,
linux-rockchip@lists.infradead.org,
Andy Gross <agross@kernel.org>,
dgreid@chromium.org, Jaroslav Kysela <perex@perex.cz>,
devicetree@vger.kernel.org, tzungbi@chromium.org,
Stephan Gerhold <stephan@gerhold.net>,
linux-arm-msm@vger.kernel.org, Rob Herring <robh+dt@kernel.org>,
linux-mediatek@lists.infradead.org,
Matthias Brugger <matthias.bgg@gmail.com>,
Bjorn Andersson <bjorn.andersson@linaro.org>,
linux-arm-kernel@lists.infradead.org, dianders@chromium.org,
Takashi Iwai <tiwai@suse.com>, Mark Brown <broonie@kernel.org>,
Srini Kandagatla <srinivas.kandagatla@linaro.org>
Subject: [PATCH v7 3/3] ASoC: qcom: sc7180: Add machine driver for sound card registration
Date: Mon, 7 Sep 2020 18:00:39 +0800 [thread overview]
Message-ID: <20200907100039.1731457-4-cychiang@chromium.org> (raw)
In-Reply-To: <20200907100039.1731457-1-cychiang@chromium.org>
From: Ajit Pandey <ajitp@codeaurora.org>
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 <ajitp@codeaurora.org>
Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
Reviewed-by: Tzung-Bi Shih <tzungbi@google.com>
---
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
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
WARNING: multiple messages have this Message-ID (diff)
From: Cheng-Yi Chiang <cychiang@chromium.org>
To: linux-kernel@vger.kernel.org
Cc: Taniya Das <tdas@codeaurora.org>,
alsa-devel@alsa-project.org,
Banajit Goswami <bgoswami@codeaurora.org>,
Heiko Stuebner <heiko@sntech.de>,
Liam Girdwood <lgirdwood@gmail.com>,
Rohit kumar <rohitkr@codeaurora.org>,
Cheng-Yi Chiang <cychiang@chromium.org>,
Tzung-Bi Shih <tzungbi@google.com>,
Patrick Lai <plai@codeaurora.org>,
Ajit Pandey <ajitp@codeaurora.org>,
linux-rockchip@lists.infradead.org,
Andy Gross <agross@kernel.org>,
dgreid@chromium.org, Jaroslav Kysela <perex@perex.cz>,
devicetree@vger.kernel.org, tzungbi@chromium.org,
Stephan Gerhold <stephan@gerhold.net>,
linux-arm-msm@vger.kernel.org, Rob Herring <robh+dt@kernel.org>,
linux-mediatek@lists.infradead.org,
Matthias Brugger <matthias.bgg@gmail.com>,
Bjorn Andersson <bjorn.andersson@linaro.org>,
linux-arm-kernel@lists.infradead.org, dianders@chromium.org,
Takashi Iwai <tiwai@suse.com>, Mark Brown <broonie@kernel.org>,
Srini Kandagatla <srinivas.kandagatla@linaro.org>
Subject: [PATCH v7 3/3] ASoC: qcom: sc7180: Add machine driver for sound card registration
Date: Mon, 7 Sep 2020 18:00:39 +0800 [thread overview]
Message-ID: <20200907100039.1731457-4-cychiang@chromium.org> (raw)
In-Reply-To: <20200907100039.1731457-1-cychiang@chromium.org>
From: Ajit Pandey <ajitp@codeaurora.org>
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 <ajitp@codeaurora.org>
Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
Reviewed-by: Tzung-Bi Shih <tzungbi@google.com>
---
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
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2020-09-07 10:01 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-07 10:00 [PATCH v7 0/3] Add documentation and machine driver for SC7180 sound card Cheng-Yi Chiang
2020-09-07 10:00 ` Cheng-Yi Chiang
2020-09-07 10:00 ` Cheng-Yi Chiang
2020-09-07 10:00 ` Cheng-Yi Chiang
2020-09-07 10:00 ` Cheng-Yi Chiang
2020-09-07 10:00 ` [PATCH v7 1/3] ASoC: hdmi-codec: Use set_jack ops to set jack Cheng-Yi Chiang
2020-09-07 10:00 ` Cheng-Yi Chiang
2020-09-07 10:00 ` Cheng-Yi Chiang
2020-09-07 10:00 ` Cheng-Yi Chiang
2020-09-07 10:00 ` Cheng-Yi Chiang
2020-09-07 10:00 ` [PATCH v7 2/3] ASoC: qcom: dt-bindings: Add sc7180 machine bindings Cheng-Yi Chiang
2020-09-07 10:00 ` Cheng-Yi Chiang
2020-09-07 10:00 ` Cheng-Yi Chiang
2020-09-07 10:00 ` Cheng-Yi Chiang
2020-09-07 10:00 ` Cheng-Yi Chiang
2020-09-08 20:33 ` Rob Herring
2020-09-08 20:33 ` Rob Herring
2020-09-08 20:33 ` Rob Herring
2020-09-08 20:33 ` Rob Herring
2020-09-08 20:33 ` Rob Herring
2020-09-09 9:23 ` Cheng-yi Chiang
2020-09-09 9:23 ` Cheng-yi Chiang
2020-09-09 9:23 ` Cheng-yi Chiang
2020-09-09 9:23 ` Cheng-yi Chiang
2020-09-09 9:23 ` Cheng-yi Chiang
2020-09-09 10:19 ` Cheng-yi Chiang
2020-09-09 10:19 ` Cheng-yi Chiang
2020-09-09 10:19 ` Cheng-yi Chiang
2020-09-09 10:19 ` Cheng-yi Chiang
2020-09-09 10:19 ` Cheng-yi Chiang
2020-09-09 17:49 ` Rob Herring
2020-09-09 17:49 ` Rob Herring
2020-09-09 17:49 ` Rob Herring
2020-09-09 17:49 ` Rob Herring
2020-09-09 17:49 ` Rob Herring
2020-09-10 2:10 ` Cheng-yi Chiang
2020-09-10 2:10 ` Cheng-yi Chiang
2020-09-10 2:10 ` Cheng-yi Chiang
2020-09-10 2:10 ` Cheng-yi Chiang
2020-09-10 2:10 ` Cheng-yi Chiang
2020-09-10 11:02 ` Mark Brown
2020-09-10 11:02 ` Mark Brown
2020-09-10 11:02 ` Mark Brown
2020-09-10 11:02 ` Mark Brown
2020-09-10 11:02 ` Mark Brown
2020-09-07 10:00 ` Cheng-Yi Chiang [this message]
2020-09-07 10:00 ` [PATCH v7 3/3] ASoC: qcom: sc7180: Add machine driver for sound card registration Cheng-Yi Chiang
2020-09-07 10:00 ` Cheng-Yi Chiang
2020-09-07 10:00 ` Cheng-Yi Chiang
2020-09-07 10:00 ` Cheng-Yi Chiang
2020-09-07 12:08 ` kernel test robot
2020-09-07 12:08 ` kernel test robot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200907100039.1731457-4-cychiang@chromium.org \
--to=cychiang@chromium.org \
--cc=agross@kernel.org \
--cc=ajitp@codeaurora.org \
--cc=alsa-devel@alsa-project.org \
--cc=bgoswami@codeaurora.org \
--cc=bjorn.andersson@linaro.org \
--cc=broonie@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dgreid@chromium.org \
--cc=dianders@chromium.org \
--cc=heiko@sntech.de \
--cc=lgirdwood@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=linux-rockchip@lists.infradead.org \
--cc=matthias.bgg@gmail.com \
--cc=perex@perex.cz \
--cc=plai@codeaurora.org \
--cc=robh+dt@kernel.org \
--cc=rohitkr@codeaurora.org \
--cc=srinivas.kandagatla@linaro.org \
--cc=stephan@gerhold.net \
--cc=tdas@codeaurora.org \
--cc=tiwai@suse.com \
--cc=tzungbi@chromium.org \
--cc=tzungbi@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.