mirror of
https://github.com/Fishwaldo/build.git
synced 2025-07-23 05:18:55 +00:00
* Move Meson64 to 5.6.y * Move Meson64 U-boot to 2020.04 Tested on Odroid C2 * Merge, replace and update patches from Khadas branch
281 lines
8.8 KiB
Diff
281 lines
8.8 KiB
Diff
From 9f5f213c7a2ff61f25ebba0906a9598983cf1e9e Mon Sep 17 00:00:00 2001
|
|
From: Jerome Brunet <jbrunet@baylibre.com>
|
|
Date: Thu, 13 Feb 2020 16:51:55 +0100
|
|
Subject: [PATCH 016/101] FROMGIT: ASoC: meson: aiu: add hdmi codec control
|
|
support
|
|
|
|
Add the codec to codec component which handles the routing between
|
|
the audio producers (PCM and I2S) and the synopsys hdmi controller
|
|
on the amlogic GX SoC family
|
|
|
|
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
|
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
|
---
|
|
sound/soc/meson/Kconfig | 2 +
|
|
sound/soc/meson/Makefile | 1 +
|
|
sound/soc/meson/aiu-codec-ctrl.c | 152 +++++++++++++++++++++++++++++++
|
|
sound/soc/meson/aiu.c | 34 ++++++-
|
|
sound/soc/meson/aiu.h | 8 ++
|
|
5 files changed, 196 insertions(+), 1 deletion(-)
|
|
create mode 100644 sound/soc/meson/aiu-codec-ctrl.c
|
|
|
|
diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig
|
|
index ca269dedfc7f..19de97ae4ce9 100644
|
|
--- a/sound/soc/meson/Kconfig
|
|
+++ b/sound/soc/meson/Kconfig
|
|
@@ -4,7 +4,9 @@ menu "ASoC support for Amlogic platforms"
|
|
|
|
config SND_MESON_AIU
|
|
tristate "Amlogic AIU"
|
|
+ select SND_MESON_CODEC_GLUE
|
|
select SND_PCM_IEC958
|
|
+ imply SND_SOC_HDMI_CODEC if DRM_MESON_DW_HDMI
|
|
help
|
|
Select Y or M to add support for the Audio output subsystem found
|
|
in the Amlogic GX SoC family
|
|
diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile
|
|
index a7b79d717288..3b21f648e322 100644
|
|
--- a/sound/soc/meson/Makefile
|
|
+++ b/sound/soc/meson/Makefile
|
|
@@ -1,6 +1,7 @@
|
|
# SPDX-License-Identifier: (GPL-2.0 OR MIT)
|
|
|
|
snd-soc-meson-aiu-objs := aiu.o
|
|
+snd-soc-meson-aiu-objs += aiu-codec-ctrl.o
|
|
snd-soc-meson-aiu-objs += aiu-encoder-i2s.o
|
|
snd-soc-meson-aiu-objs += aiu-encoder-spdif.o
|
|
snd-soc-meson-aiu-objs += aiu-fifo.o
|
|
diff --git a/sound/soc/meson/aiu-codec-ctrl.c b/sound/soc/meson/aiu-codec-ctrl.c
|
|
new file mode 100644
|
|
index 000000000000..8646a953e3b3
|
|
--- /dev/null
|
|
+++ b/sound/soc/meson/aiu-codec-ctrl.c
|
|
@@ -0,0 +1,152 @@
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
+//
|
|
+// Copyright (c) 2020 BayLibre, SAS.
|
|
+// Author: Jerome Brunet <jbrunet@baylibre.com>
|
|
+
|
|
+#include <linux/bitfield.h>
|
|
+#include <sound/pcm_params.h>
|
|
+#include <sound/soc.h>
|
|
+#include <sound/soc-dai.h>
|
|
+
|
|
+#include <dt-bindings/sound/meson-aiu.h>
|
|
+#include "aiu.h"
|
|
+#include "meson-codec-glue.h"
|
|
+
|
|
+#define CTRL_CLK_SEL GENMASK(1, 0)
|
|
+#define CTRL_DATA_SEL_SHIFT 4
|
|
+#define CTRL_DATA_SEL (0x3 << CTRL_DATA_SEL_SHIFT)
|
|
+
|
|
+static const char * const aiu_codec_ctrl_mux_texts[] = {
|
|
+ "DISABLED", "PCM", "I2S",
|
|
+};
|
|
+
|
|
+static int aiu_codec_ctrl_mux_put_enum(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_component *component =
|
|
+ snd_soc_dapm_kcontrol_component(kcontrol);
|
|
+ struct snd_soc_dapm_context *dapm =
|
|
+ snd_soc_dapm_kcontrol_dapm(kcontrol);
|
|
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
|
+ unsigned int mux, changed;
|
|
+
|
|
+ mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]);
|
|
+ changed = snd_soc_component_test_bits(component, e->reg,
|
|
+ CTRL_DATA_SEL,
|
|
+ FIELD_PREP(CTRL_DATA_SEL, mux));
|
|
+
|
|
+ if (!changed)
|
|
+ return 0;
|
|
+
|
|
+ /* Force disconnect of the mux while updating */
|
|
+ snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL);
|
|
+
|
|
+ /* Reset the source first */
|
|
+ snd_soc_component_update_bits(component, e->reg,
|
|
+ CTRL_CLK_SEL |
|
|
+ CTRL_DATA_SEL,
|
|
+ FIELD_PREP(CTRL_CLK_SEL, 0) |
|
|
+ FIELD_PREP(CTRL_DATA_SEL, 0));
|
|
+
|
|
+ /* Set the appropriate source */
|
|
+ snd_soc_component_update_bits(component, e->reg,
|
|
+ CTRL_CLK_SEL |
|
|
+ CTRL_DATA_SEL,
|
|
+ FIELD_PREP(CTRL_CLK_SEL, mux) |
|
|
+ FIELD_PREP(CTRL_DATA_SEL, mux));
|
|
+
|
|
+ snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static SOC_ENUM_SINGLE_DECL(aiu_hdmi_ctrl_mux_enum, AIU_HDMI_CLK_DATA_CTRL,
|
|
+ CTRL_DATA_SEL_SHIFT,
|
|
+ aiu_codec_ctrl_mux_texts);
|
|
+
|
|
+static const struct snd_kcontrol_new aiu_hdmi_ctrl_mux =
|
|
+ SOC_DAPM_ENUM_EXT("HDMI Source", aiu_hdmi_ctrl_mux_enum,
|
|
+ snd_soc_dapm_get_enum_double,
|
|
+ aiu_codec_ctrl_mux_put_enum);
|
|
+
|
|
+static const struct snd_soc_dapm_widget aiu_hdmi_ctrl_widgets[] = {
|
|
+ SND_SOC_DAPM_MUX("HDMI CTRL SRC", SND_SOC_NOPM, 0, 0,
|
|
+ &aiu_hdmi_ctrl_mux),
|
|
+};
|
|
+
|
|
+static const struct snd_soc_dai_ops aiu_codec_ctrl_input_ops = {
|
|
+ .hw_params = meson_codec_glue_input_hw_params,
|
|
+ .set_fmt = meson_codec_glue_input_set_fmt,
|
|
+};
|
|
+
|
|
+static const struct snd_soc_dai_ops aiu_codec_ctrl_output_ops = {
|
|
+ .startup = meson_codec_glue_output_startup,
|
|
+};
|
|
+
|
|
+#define AIU_CODEC_CTRL_FORMATS \
|
|
+ (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
|
|
+ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE | \
|
|
+ SNDRV_PCM_FMTBIT_S32_LE)
|
|
+
|
|
+#define AIU_CODEC_CTRL_STREAM(xname, xsuffix) \
|
|
+{ \
|
|
+ .stream_name = xname " " xsuffix, \
|
|
+ .channels_min = 1, \
|
|
+ .channels_max = 8, \
|
|
+ .rate_min = 5512, \
|
|
+ .rate_max = 192000, \
|
|
+ .formats = AIU_CODEC_CTRL_FORMATS, \
|
|
+}
|
|
+
|
|
+#define AIU_CODEC_CTRL_INPUT(xname) { \
|
|
+ .name = "CODEC CTRL " xname, \
|
|
+ .playback = AIU_CODEC_CTRL_STREAM(xname, "Playback"), \
|
|
+ .ops = &aiu_codec_ctrl_input_ops, \
|
|
+ .probe = meson_codec_glue_input_dai_probe, \
|
|
+ .remove = meson_codec_glue_input_dai_remove, \
|
|
+}
|
|
+
|
|
+#define AIU_CODEC_CTRL_OUTPUT(xname) { \
|
|
+ .name = "CODEC CTRL " xname, \
|
|
+ .capture = AIU_CODEC_CTRL_STREAM(xname, "Capture"), \
|
|
+ .ops = &aiu_codec_ctrl_output_ops, \
|
|
+}
|
|
+
|
|
+static struct snd_soc_dai_driver aiu_hdmi_ctrl_dai_drv[] = {
|
|
+ [CTRL_I2S] = AIU_CODEC_CTRL_INPUT("HDMI I2S IN"),
|
|
+ [CTRL_PCM] = AIU_CODEC_CTRL_INPUT("HDMI PCM IN"),
|
|
+ [CTRL_OUT] = AIU_CODEC_CTRL_OUTPUT("HDMI OUT"),
|
|
+};
|
|
+
|
|
+static const struct snd_soc_dapm_route aiu_hdmi_ctrl_routes[] = {
|
|
+ { "HDMI CTRL SRC", "I2S", "HDMI I2S IN Playback" },
|
|
+ { "HDMI CTRL SRC", "PCM", "HDMI PCM IN Playback" },
|
|
+ { "HDMI OUT Capture", NULL, "HDMI CTRL SRC" },
|
|
+};
|
|
+
|
|
+static int aiu_hdmi_of_xlate_dai_name(struct snd_soc_component *component,
|
|
+ struct of_phandle_args *args,
|
|
+ const char **dai_name)
|
|
+{
|
|
+ return aiu_of_xlate_dai_name(component, args, dai_name, AIU_HDMI);
|
|
+}
|
|
+
|
|
+static const struct snd_soc_component_driver aiu_hdmi_ctrl_component = {
|
|
+ .name = "AIU HDMI Codec Control",
|
|
+ .dapm_widgets = aiu_hdmi_ctrl_widgets,
|
|
+ .num_dapm_widgets = ARRAY_SIZE(aiu_hdmi_ctrl_widgets),
|
|
+ .dapm_routes = aiu_hdmi_ctrl_routes,
|
|
+ .num_dapm_routes = ARRAY_SIZE(aiu_hdmi_ctrl_routes),
|
|
+ .of_xlate_dai_name = aiu_hdmi_of_xlate_dai_name,
|
|
+ .endianness = 1,
|
|
+ .non_legacy_dai_naming = 1,
|
|
+};
|
|
+
|
|
+int aiu_hdmi_ctrl_register_component(struct device *dev)
|
|
+{
|
|
+ return aiu_add_component(dev, &aiu_hdmi_ctrl_component,
|
|
+ aiu_hdmi_ctrl_dai_drv,
|
|
+ ARRAY_SIZE(aiu_hdmi_ctrl_dai_drv),
|
|
+ "hdmi");
|
|
+}
|
|
+
|
|
diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c
|
|
index a62aced9b687..b765dfb70726 100644
|
|
--- a/sound/soc/meson/aiu.c
|
|
+++ b/sound/soc/meson/aiu.c
|
|
@@ -71,6 +71,26 @@ int aiu_of_xlate_dai_name(struct snd_soc_component *component,
|
|
return 0;
|
|
}
|
|
|
|
+int aiu_add_component(struct device *dev,
|
|
+ const struct snd_soc_component_driver *component_driver,
|
|
+ struct snd_soc_dai_driver *dai_drv,
|
|
+ int num_dai,
|
|
+ const char *debugfs_prefix)
|
|
+{
|
|
+ struct snd_soc_component *component;
|
|
+
|
|
+ component = devm_kzalloc(dev, sizeof(*component), GFP_KERNEL);
|
|
+ if (!component)
|
|
+ return -ENOMEM;
|
|
+
|
|
+#ifdef CONFIG_DEBUG_FS
|
|
+ component->debugfs_prefix = debugfs_prefix;
|
|
+#endif
|
|
+
|
|
+ return snd_soc_add_component(dev, component, component_driver,
|
|
+ dai_drv, num_dai);
|
|
+}
|
|
+
|
|
static int aiu_cpu_of_xlate_dai_name(struct snd_soc_component *component,
|
|
struct of_phandle_args *args,
|
|
const char **dai_name)
|
|
@@ -313,9 +333,21 @@ static int aiu_probe(struct platform_device *pdev)
|
|
ret = snd_soc_register_component(dev, &aiu_cpu_component,
|
|
aiu_cpu_dai_drv,
|
|
ARRAY_SIZE(aiu_cpu_dai_drv));
|
|
- if (ret)
|
|
+ if (ret) {
|
|
dev_err(dev, "Failed to register cpu component\n");
|
|
+ return ret;
|
|
+ }
|
|
|
|
+ /* Register the hdmi codec control component */
|
|
+ ret = aiu_hdmi_ctrl_register_component(dev);
|
|
+ if (ret) {
|
|
+ dev_err(dev, "Failed to register hdmi control component\n");
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+err:
|
|
+ snd_soc_unregister_component(dev);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h
|
|
index a3488027b9d5..9242ab1ab64b 100644
|
|
--- a/sound/soc/meson/aiu.h
|
|
+++ b/sound/soc/meson/aiu.h
|
|
@@ -45,6 +45,14 @@ int aiu_of_xlate_dai_name(struct snd_soc_component *component,
|
|
const char **dai_name,
|
|
unsigned int component_id);
|
|
|
|
+int aiu_add_component(struct device *dev,
|
|
+ const struct snd_soc_component_driver *component_driver,
|
|
+ struct snd_soc_dai_driver *dai_drv,
|
|
+ int num_dai,
|
|
+ const char *debugfs_prefix);
|
|
+
|
|
+int aiu_hdmi_ctrl_register_component(struct device *dev);
|
|
+
|
|
int aiu_fifo_i2s_dai_probe(struct snd_soc_dai *dai);
|
|
int aiu_fifo_spdif_dai_probe(struct snd_soc_dai *dai);
|
|
|
|
--
|
|
2.17.1
|
|
|