odroidc2-mainline: Add the kernel config and patches

This still doesn't 100% work correctly.  I haven't yet tested adding an
initrd would would likely make the kernel/u-boot bits a non-issue, that
testing will happen later.
This commit is contained in:
Steev Klimaszewski
2018-07-25 15:58:08 -05:00
parent 23fba66373
commit d01a1bfd2b
23 changed files with 12237 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,53 @@
From a14c74cd31c50b4008b4160e516671c5e05e0254 Mon Sep 17 00:00:00 2001
From: Neil Armstrong <narmstrong@baylibre.com>
Date: Wed, 13 Jun 2018 14:05:07 +0200
Subject: [PATCH 01/21] clk: meson-gxbb: set fclk_div2 as CLK_IS_CRITICAL
On Amlogic Meson GXBB & GXL platforms, the SCPI Cortex-M4 Co-Processor
seems to be dependent on the FCLK_DIV2 to be operationnal.
The issue occured since v4.17-rc1 by freezing the kernel boot when
the 'schedutil' cpufreq governor was selected as default :
[ 12.071837] scpi_protocol scpi: SCP Protocol 0.0 Firmware 0.0.0 version
domain-0 init dvfs: 4
[ 12.087757] hctosys: unable to open rtc device (rtc0)
[ 12.087907] cfg80211: Loading compiled-in X.509 certificates for regulatory database
[ 12.102241] cfg80211: Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7'
But when disabling the MMC driver, the boot finished but cpufreq failed to
change the CPU frequency :
[ 12.153045] cpufreq: __target_index: Failed to change cpu frequency: -5
A bisect between v4.16 and v4.16-rc1 gave the 05f814402d61 commit to be
the first bad commit.
This commit added support for the missing clock gates before the fixed PLL
fixed dividers (FCLK_DIVx) and the clock framework basically disabled
all the unused fixed dividers, thus disabled a critical clock path for
the SCPI Co-Processor.
This patch simply sets the FCLK_DIV2 gate as critical to ensure
nobody can disable it.
Fixes: 05f814402d61 ("clk: meson: add fdiv clock gates")
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
drivers/clk/meson/gxbb.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 240658404367..177fffb9ebef 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -498,6 +498,7 @@ static struct clk_regmap gxbb_fclk_div2 = {
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "fclk_div2_div" },
.num_parents = 1,
+ .flags = CLK_IS_CRITICAL,
},
};
--
2.18.0

View File

@@ -0,0 +1,84 @@
From bc94a55c85422b420b515623e7e9b21edf8e1a72 Mon Sep 17 00:00:00 2001
From: Neil Armstrong <narmstrong@baylibre.com>
Date: Tue, 26 Jun 2018 09:37:39 +0200
Subject: [PATCH 02/21] ARM64: dts: meson-gxbb-nanopi-k2: Add HDMI, CEC and
CVBS nodes
The Amlogic Meson GXBB based Nanopi-K2 board has an HDMI connector
with CEC and CVBS available on the 40pin header.
This patch adds the nodes to enable HDMI, CEC and CVBS functionnalities.
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
.../boot/dts/amlogic/meson-gxbb-nanopi-k2.dts | 48 +++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
index 7d5709c37e95..cbe99bd4e06d 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
@@ -106,6 +106,42 @@
compatible = "mmc-pwrseq-emmc";
reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
};
+
+ /* CVBS is available on CON1 pin 36, disabled by default */
+ cvbs-connector {
+ compatible = "composite-video-connector";
+ status = "disabled";
+
+ port {
+ cvbs_connector_in: endpoint {
+ remote-endpoint = <&cvbs_vdac_out>;
+ };
+ };
+ };
+
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_connector_in: endpoint {
+ remote-endpoint = <&hdmi_tx_tmds_out>;
+ };
+ };
+ };
+};
+
+&cec_AO {
+ status = "okay";
+ pinctrl-0 = <&ao_cec_pins>;
+ pinctrl-names = "default";
+ hdmi-phandle = <&hdmi_tx>;
+};
+
+&cvbs_vdac_port {
+ cvbs_vdac_out: endpoint {
+ remote-endpoint = <&cvbs_connector_in>;
+ };
};
&ethmac {
@@ -137,6 +173,18 @@
};
};
+&hdmi_tx {
+ status = "okay";
+ pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
+ pinctrl-names = "default";
+};
+
+&hdmi_tx_tmds_port {
+ hdmi_tx_tmds_out: endpoint {
+ remote-endpoint = <&hdmi_connector_in>;
+ };
+};
+
&ir {
status = "okay";
pinctrl-0 = <&remote_input_ao_pins>;
--
2.18.0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
From 8efe6ad5f651af4dd687449a70c337631324b65d Mon Sep 17 00:00:00 2001
From: Jerome Brunet <jbrunet@baylibre.com>
Date: Mon, 13 Nov 2017 12:09:40 +0100
Subject: [PATCH 04/21] ARM64: defconfig: enable CEC support
Turn on CONFIG_CEC_SUPPORT and CONFIG_CEC_PLATFORM_DRIVERS
Turn on CONFIG_VIDEO_MESON_AO_CEC as module
Turn on CONFIG_DRM_DW_HDMI_CEC as module
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
arch/arm64/configs/defconfig | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index f9a186f6af8a..25846051b6b5 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -402,6 +402,7 @@ CONFIG_MEDIA_SUPPORT=m
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
+CONFIG_MEDIA_CEC_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_DVB_NET is not set
@@ -411,6 +412,8 @@ CONFIG_VIDEO_SAMSUNG_S5P_MFC=m
CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m
CONFIG_VIDEO_RENESAS_FCP=m
CONFIG_VIDEO_RENESAS_VSP1=m
+CONFIG_CEC_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_MESON_AO_CEC=m
CONFIG_DRM=m
CONFIG_DRM_NOUVEAU=m
CONFIG_DRM_EXYNOS=m
@@ -431,6 +434,7 @@ CONFIG_DRM_RCAR_LVDS=m
CONFIG_DRM_TEGRA=m
CONFIG_DRM_PANEL_SIMPLE=m
CONFIG_DRM_I2C_ADV7511=m
+CONFIG_DRM_DW_HDMI_CEC=m
CONFIG_DRM_VC4=m
CONFIG_DRM_HISI_HIBMC=m
CONFIG_DRM_HISI_KIRIN=m
--
2.18.0

View File

@@ -0,0 +1,48 @@
From 7673bee05a11e0d316f56cd3e2f21d4407052fc4 Mon Sep 17 00:00:00 2001
From: Jerome Brunet <jbrunet@baylibre.com>
Date: Tue, 19 Jun 2018 18:14:49 +0200
Subject: [PATCH 05/21] clk: meson: switch gxbb cts-amclk div to the generic
divider
clk-audio-divider was a (poor) attempt to use CCF rate propagation
while making sure the PLL rate would be high enough to work with
audio use cases. The result is far from optimal. We can do better
by carefully choosing the PLL rates for the audio use cases.
Doing so, we don't need to use clk-audio-divider anymore. The
generic will do
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
drivers/clk/meson/gxbb.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 177fffb9ebef..69a58cbb29ee 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -982,17 +982,15 @@ static struct clk_regmap gxbb_cts_amclk_sel = {
};
static struct clk_regmap gxbb_cts_amclk_div = {
- .data = &(struct meson_clk_audio_div_data){
- .div = {
- .reg_off = HHI_AUD_CLK_CNTL,
- .shift = 0,
- .width = 8,
- },
+ .data = &(struct clk_regmap_div_data) {
+ .offset = HHI_AUD_CLK_CNTL,
+ .shift = 0,
+ .width = 8,
.flags = CLK_DIVIDER_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
.name = "cts_amclk_div",
- .ops = &meson_clk_audio_divider_ops,
+ .ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "cts_amclk_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
--
2.18.0

View File

@@ -0,0 +1,51 @@
From ddbc6160b2cfa047c963077baae58b314e6f21e3 Mon Sep 17 00:00:00 2001
From: Jerome Brunet <jbrunet@baylibre.com>
Date: Tue, 19 Jun 2018 18:23:28 +0200
Subject: [PATCH 06/21] clk: meson: remove unused clk-audio-divider driver
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
drivers/clk/meson/Makefile | 2 +-
drivers/clk/meson/clkc.h | 7 -------
2 files changed, 1 insertion(+), 8 deletions(-)
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index d0d13aeb369a..e40fea96069b 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -2,7 +2,7 @@
# Makefile for Meson specific clk
#
-obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o clk-audio-divider.o
+obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o
obj-$(CONFIG_COMMON_CLK_MESON_AO) += meson-aoclk.o
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-32k.o
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
index 2fb084330ee9..48db02424f02 100644
--- a/drivers/clk/meson/clkc.h
+++ b/drivers/clk/meson/clkc.h
@@ -91,11 +91,6 @@ struct meson_clk_mpll_data {
#define CLK_MESON_MPLL_ROUND_CLOSEST BIT(0)
-struct meson_clk_audio_div_data {
- struct parm div;
- u8 flags;
-};
-
#define MESON_GATE(_name, _reg, _bit) \
struct clk_regmap _name = { \
.data = &(struct clk_regmap_gate_data){ \
@@ -117,7 +112,5 @@ extern const struct clk_ops meson_clk_pll_ops;
extern const struct clk_ops meson_clk_cpu_ops;
extern const struct clk_ops meson_clk_mpll_ro_ops;
extern const struct clk_ops meson_clk_mpll_ops;
-extern const struct clk_ops meson_clk_audio_divider_ro_ops;
-extern const struct clk_ops meson_clk_audio_divider_ops;
#endif /* __CLKC_H */
--
2.18.0

View File

@@ -0,0 +1,311 @@
From 6486fe80144b88cfe65e581b53c01e54afa9ba59 Mon Sep 17 00:00:00 2001
From: Jerome Brunet <jbrunet@baylibre.com>
Date: Thu, 30 Mar 2017 11:49:55 +0200
Subject: [PATCH 07/21] ASoC: meson: add meson audio core driver
This patch adds support for the audio core driver for the Amlogic Meson SoC
family. The purpose of this driver is to properly reset the audio block and
provide register access for the different devices scattered in this address
space. This includes output and input DMAs, pcm, i2s and spdif dai, card
level routing, internal codec for the gxl variant
For more information, please refer to the section 5 of the public datasheet
of the S905 (gxbb). This datasheet is available here: [0].
[0]: http://dn.odroid.com/S905/DataSheet/S905_Public_Datasheet_V1.1.4.pdf
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
sound/soc/Kconfig | 1 +
sound/soc/Makefile | 1 +
sound/soc/meson/Kconfig | 9 ++
sound/soc/meson/Makefile | 3 +
sound/soc/meson/audio-core.c | 190 +++++++++++++++++++++++++++++++++++
sound/soc/meson/audio-core.h | 28 ++++++
6 files changed, 232 insertions(+)
create mode 100644 sound/soc/meson/Kconfig
create mode 100644 sound/soc/meson/Makefile
create mode 100644 sound/soc/meson/audio-core.c
create mode 100644 sound/soc/meson/audio-core.h
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 41af6b9cc350..1cf11cf51e1d 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -57,6 +57,7 @@ source "sound/soc/kirkwood/Kconfig"
source "sound/soc/img/Kconfig"
source "sound/soc/intel/Kconfig"
source "sound/soc/mediatek/Kconfig"
+source "sound/soc/meson/Kconfig"
source "sound/soc/mxs/Kconfig"
source "sound/soc/pxa/Kconfig"
source "sound/soc/qcom/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 06389a5385d7..62a5f87c3cfc 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_SND_SOC) += jz4740/
obj-$(CONFIG_SND_SOC) += img/
obj-$(CONFIG_SND_SOC) += intel/
obj-$(CONFIG_SND_SOC) += mediatek/
+obj-$(CONFIG_SND_SOC) += meson/
obj-$(CONFIG_SND_SOC) += mxs/
obj-$(CONFIG_SND_SOC) += nuc900/
obj-$(CONFIG_SND_SOC) += omap/
diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig
new file mode 100644
index 000000000000..ca0e3e981a99
--- /dev/null
+++ b/sound/soc/meson/Kconfig
@@ -0,0 +1,9 @@
+menuconfig SND_SOC_MESON
+ tristate "ASoC support for Amlogic Meson SoCs"
+ depends on ARCH_MESON
+ select MFD_CORE
+ select REGMAP_MMIO
+ help
+ Say Y or M if you want to add support for codecs attached to
+ the Amlogic Meson SoCs Audio interfaces. You will also need to
+ select the audio interfaces to support below.
diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile
new file mode 100644
index 000000000000..22028abb5624
--- /dev/null
+++ b/sound/soc/meson/Makefile
@@ -0,0 +1,3 @@
+snd-soc-meson-audio-core-objs := audio-core.o
+
+obj-$(CONFIG_SND_SOC_MESON) += snd-soc-meson-audio-core.o
diff --git a/sound/soc/meson/audio-core.c b/sound/soc/meson/audio-core.c
new file mode 100644
index 000000000000..99993ec4a5cc
--- /dev/null
+++ b/sound/soc/meson/audio-core.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2017 BayLibre, SAS
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include "audio-core.h"
+
+#define DRV_NAME "meson-audio-core"
+
+static const char * const acore_clock_names[] = { "aiu_top",
+ "aiu_glue",
+ "audin" };
+
+static int meson_acore_init_clocks(struct device *dev)
+{
+ struct clk *clock;
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(acore_clock_names); i++) {
+ clock = devm_clk_get(dev, acore_clock_names[i]);
+ if (IS_ERR(clock)) {
+ if (PTR_ERR(clock) != -EPROBE_DEFER)
+ dev_err(dev, "Failed to get %s clock\n",
+ acore_clock_names[i]);
+ return PTR_ERR(clock);
+ }
+
+ ret = clk_prepare_enable(clock);
+ if (ret) {
+ dev_err(dev, "Failed to enable %s clock\n",
+ acore_clock_names[i]);
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(dev,
+ (void(*)(void *))clk_disable_unprepare,
+ clock);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const char * const acore_reset_names[] = { "aiu",
+ "audin" };
+
+static int meson_acore_init_resets(struct device *dev)
+{
+ struct reset_control *reset;
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(acore_reset_names); i++) {
+ reset = devm_reset_control_get_exclusive(dev,
+ acore_reset_names[i]);
+ if (IS_ERR(reset)) {
+ if (PTR_ERR(reset) != -EPROBE_DEFER)
+ dev_err(dev, "Failed to get %s reset\n",
+ acore_reset_names[i]);
+ return PTR_ERR(reset);
+ }
+
+ ret = reset_control_reset(reset);
+ if (ret) {
+ dev_err(dev, "Failed to pulse %s reset\n",
+ acore_reset_names[i]);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static const struct regmap_config meson_acore_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static const struct mfd_cell meson_acore_devs[] = {
+ {
+ .name = "meson-i2s-dai",
+ .of_compatible = "amlogic,meson-i2s-dai",
+ },
+ {
+ .name = "meson-spdif-dai",
+ .of_compatible = "amlogic,meson-spdif-dai",
+ },
+ {
+ .name = "meson-aiu-i2s-dma",
+ .of_compatible = "amlogic,meson-aiu-i2s-dma",
+ },
+ {
+ .name = "meson-aiu-spdif-dma",
+ .of_compatible = "amlogic,meson-aiu-spdif-dma",
+ },
+};
+
+static int meson_acore_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct meson_audio_core_data *data;
+ struct resource *res;
+ void __iomem *regs;
+ int ret;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, data);
+
+ ret = meson_acore_init_clocks(dev);
+ if (ret)
+ return ret;
+
+ ret = meson_acore_init_resets(dev);
+ if (ret)
+ return ret;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aiu");
+ regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+
+ data->aiu = devm_regmap_init_mmio(dev, regs,
+ &meson_acore_regmap_config);
+ if (IS_ERR(data->aiu)) {
+ dev_err(dev, "Couldn't create the AIU regmap\n");
+ return PTR_ERR(data->aiu);
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "audin");
+ regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+
+ data->audin = devm_regmap_init_mmio(dev, regs,
+ &meson_acore_regmap_config);
+ if (IS_ERR(data->audin)) {
+ dev_err(dev, "Couldn't create the AUDIN regmap\n");
+ return PTR_ERR(data->audin);
+ }
+
+ return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, meson_acore_devs,
+ ARRAY_SIZE(meson_acore_devs), NULL, 0,
+ NULL);
+}
+
+static const struct of_device_id meson_acore_of_match[] = {
+ { .compatible = "amlogic,meson-audio-core", },
+ { .compatible = "amlogic,meson-gxbb-audio-core", },
+ { .compatible = "amlogic,meson-gxl-audio-core", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, meson_acore_of_match);
+
+static struct platform_driver meson_acore_pdrv = {
+ .probe = meson_acore_probe,
+ .driver = {
+ .name = DRV_NAME,
+ .of_match_table = meson_acore_of_match,
+ },
+};
+module_platform_driver(meson_acore_pdrv);
+
+MODULE_DESCRIPTION("Meson Audio Core Driver");
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/meson/audio-core.h b/sound/soc/meson/audio-core.h
new file mode 100644
index 000000000000..6e7a24cdc4a9
--- /dev/null
+++ b/sound/soc/meson/audio-core.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 BayLibre, SAS
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MESON_AUDIO_CORE_H_
+#define _MESON_AUDIO_CORE_H_
+
+struct meson_audio_core_data {
+ struct regmap *aiu;
+ struct regmap *audin;
+};
+
+#endif /* _MESON_AUDIO_CORE_H_ */
--
2.18.0

View File

@@ -0,0 +1,360 @@
From ef9065cecd78f62b97e5301b4489929119c9aabc Mon Sep 17 00:00:00 2001
From: Jerome Brunet <jbrunet@baylibre.com>
Date: Thu, 30 Mar 2017 12:00:10 +0200
Subject: [PATCH 08/21] ASoC: meson: add register definitions
Add the register definition for the AIU and AUDIN blocks
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
sound/soc/meson/aiu-regs.h | 182 +++++++++++++++++++++++++++++++++++
sound/soc/meson/audin-regs.h | 148 ++++++++++++++++++++++++++++
2 files changed, 330 insertions(+)
create mode 100644 sound/soc/meson/aiu-regs.h
create mode 100644 sound/soc/meson/audin-regs.h
diff --git a/sound/soc/meson/aiu-regs.h b/sound/soc/meson/aiu-regs.h
new file mode 100644
index 000000000000..67391e64fe1c
--- /dev/null
+++ b/sound/soc/meson/aiu-regs.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2017 BayLibre, SAS
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _AIU_REGS_H_
+#define _AIU_REGS_H_
+
+#define AIU_958_BPF 0x000
+#define AIU_958_BRST 0x004
+#define AIU_958_LENGTH 0x008
+#define AIU_958_PADDSIZE 0x00C
+#define AIU_958_MISC 0x010
+#define AIU_958_FORCE_LEFT 0x014 /* Unknown */
+#define AIU_958_DISCARD_NUM 0x018
+#define AIU_958_DCU_FF_CTRL 0x01C
+#define AIU_958_CHSTAT_L0 0x020
+#define AIU_958_CHSTAT_L1 0x024
+#define AIU_958_CTRL 0x028
+#define AIU_958_RPT 0x02C
+#define AIU_I2S_MUTE_SWAP 0x030
+#define AIU_I2S_SOURCE_DESC 0x034
+#define AIU_I2S_MED_CTRL 0x038
+#define AIU_I2S_MED_THRESH 0x03C
+#define AIU_I2S_DAC_CFG 0x040
+#define AIU_I2S_SYNC 0x044 /* Unknown */
+#define AIU_I2S_MISC 0x048
+#define AIU_I2S_OUT_CFG 0x04C
+#define AIU_I2S_FF_CTRL 0x050 /* Unknown */
+#define AIU_RST_SOFT 0x054
+#define AIU_CLK_CTRL 0x058
+#define AIU_MIX_ADCCFG 0x05C
+#define AIU_MIX_CTRL 0x060
+#define AIU_CLK_CTRL_MORE 0x064
+#define AIU_958_POP 0x068
+#define AIU_MIX_GAIN 0x06C
+#define AIU_958_SYNWORD1 0x070
+#define AIU_958_SYNWORD2 0x074
+#define AIU_958_SYNWORD3 0x078
+#define AIU_958_SYNWORD1_MASK 0x07C
+#define AIU_958_SYNWORD2_MASK 0x080
+#define AIU_958_SYNWORD3_MASK 0x084
+#define AIU_958_FFRDOUT_THD 0x088
+#define AIU_958_LENGTH_PER_PAUSE 0x08C
+#define AIU_958_PAUSE_NUM 0x090
+#define AIU_958_PAUSE_PAYLOAD 0x094
+#define AIU_958_AUTO_PAUSE 0x098
+#define AIU_958_PAUSE_PD_LENGTH 0x09C
+#define AIU_CODEC_DAC_LRCLK_CTRL 0x0A0
+#define AIU_CODEC_ADC_LRCLK_CTRL 0x0A4
+#define AIU_HDMI_CLK_DATA_CTRL 0x0A8
+#define AIU_CODEC_CLK_DATA_CTRL 0x0AC
+#define AIU_ACODEC_CTRL 0x0B0
+#define AIU_958_CHSTAT_R0 0x0C0
+#define AIU_958_CHSTAT_R1 0x0C4
+#define AIU_958_VALID_CTRL 0x0C8
+#define AIU_AUDIO_AMP_REG0 0x0F0 /* Unknown */
+#define AIU_AUDIO_AMP_REG1 0x0F4 /* Unknown */
+#define AIU_AUDIO_AMP_REG2 0x0F8 /* Unknown */
+#define AIU_AUDIO_AMP_REG3 0x0FC /* Unknown */
+#define AIU_AIFIFO2_CTRL 0x100
+#define AIU_AIFIFO2_STATUS 0x104
+#define AIU_AIFIFO2_GBIT 0x108
+#define AIU_AIFIFO2_CLB 0x10C
+#define AIU_CRC_CTRL 0x110
+#define AIU_CRC_STATUS 0x114
+#define AIU_CRC_SHIFT_REG 0x118
+#define AIU_CRC_IREG 0x11C
+#define AIU_CRC_CAL_REG1 0x120
+#define AIU_CRC_CAL_REG0 0x124
+#define AIU_CRC_POLY_COEF1 0x128
+#define AIU_CRC_POLY_COEF0 0x12C
+#define AIU_CRC_BIT_SIZE1 0x130
+#define AIU_CRC_BIT_SIZE0 0x134
+#define AIU_CRC_BIT_CNT1 0x138
+#define AIU_CRC_BIT_CNT0 0x13C
+#define AIU_AMCLK_GATE_HI 0x140
+#define AIU_AMCLK_GATE_LO 0x144
+#define AIU_AMCLK_MSR 0x148
+#define AIU_AUDAC_CTRL0 0x14C /* Unknown */
+#define AIU_DELTA_SIGMA0 0x154 /* Unknown */
+#define AIU_DELTA_SIGMA1 0x158 /* Unknown */
+#define AIU_DELTA_SIGMA2 0x15C /* Unknown */
+#define AIU_DELTA_SIGMA3 0x160 /* Unknown */
+#define AIU_DELTA_SIGMA4 0x164 /* Unknown */
+#define AIU_DELTA_SIGMA5 0x168 /* Unknown */
+#define AIU_DELTA_SIGMA6 0x16C /* Unknown */
+#define AIU_DELTA_SIGMA7 0x170 /* Unknown */
+#define AIU_DELTA_SIGMA_LCNTS 0x174 /* Unknown */
+#define AIU_DELTA_SIGMA_RCNTS 0x178 /* Unknown */
+#define AIU_MEM_I2S_START_PTR 0x180
+#define AIU_MEM_I2S_RD_PTR 0x184
+#define AIU_MEM_I2S_END_PTR 0x188
+#define AIU_MEM_I2S_MASKS 0x18C
+#define AIU_MEM_I2S_CONTROL 0x190
+#define AIU_MEM_IEC958_START_PTR 0x194
+#define AIU_MEM_IEC958_RD_PTR 0x198
+#define AIU_MEM_IEC958_END_PTR 0x19C
+#define AIU_MEM_IEC958_MASKS 0x1A0
+#define AIU_MEM_IEC958_CONTROL 0x1A4
+#define AIU_MEM_AIFIFO2_START_PTR 0x1A8
+#define AIU_MEM_AIFIFO2_CURR_PTR 0x1AC
+#define AIU_MEM_AIFIFO2_END_PTR 0x1B0
+#define AIU_MEM_AIFIFO2_BYTES_AVAIL 0x1B4
+#define AIU_MEM_AIFIFO2_CONTROL 0x1B8
+#define AIU_MEM_AIFIFO2_MAN_WP 0x1BC
+#define AIU_MEM_AIFIFO2_MAN_RP 0x1C0
+#define AIU_MEM_AIFIFO2_LEVEL 0x1C4
+#define AIU_MEM_AIFIFO2_BUF_CNTL 0x1C8
+#define AIU_MEM_I2S_MAN_WP 0x1CC
+#define AIU_MEM_I2S_MAN_RP 0x1D0
+#define AIU_MEM_I2S_LEVEL 0x1D4
+#define AIU_MEM_I2S_BUF_CNTL 0x1D8
+#define AIU_MEM_I2S_BUF_WRAP_COUNT 0x1DC
+#define AIU_MEM_I2S_MEM_CTL 0x1E0
+#define AIU_MEM_IEC958_MEM_CTL 0x1E4
+#define AIU_MEM_IEC958_WRAP_COUNT 0x1E8
+#define AIU_MEM_IEC958_IRQ_LEVEL 0x1EC
+#define AIU_MEM_IEC958_MAN_WP 0x1F0
+#define AIU_MEM_IEC958_MAN_RP 0x1F4
+#define AIU_MEM_IEC958_LEVEL 0x1F8
+#define AIU_MEM_IEC958_BUF_CNTL 0x1FC
+#define AIU_AIFIFO_CTRL 0x200
+#define AIU_AIFIFO_STATUS 0x204
+#define AIU_AIFIFO_GBIT 0x208
+#define AIU_AIFIFO_CLB 0x20C
+#define AIU_MEM_AIFIFO_START_PTR 0x210
+#define AIU_MEM_AIFIFO_CURR_PTR 0x214
+#define AIU_MEM_AIFIFO_END_PTR 0x218
+#define AIU_MEM_AIFIFO_BYTES_AVAIL 0x21C
+#define AIU_MEM_AIFIFO_CONTROL 0x220
+#define AIU_MEM_AIFIFO_MAN_WP 0x224
+#define AIU_MEM_AIFIFO_MAN_RP 0x228
+#define AIU_MEM_AIFIFO_LEVEL 0x22C
+#define AIU_MEM_AIFIFO_BUF_CNTL 0x230
+#define AIU_MEM_AIFIFO_BUF_WRAP_COUNT 0x234
+#define AIU_MEM_AIFIFO2_BUF_WRAP_COUNT 0x238
+#define AIU_MEM_AIFIFO_MEM_CTL 0x23C
+#define AIFIFO_TIME_STAMP_CNTL 0x240
+#define AIFIFO_TIME_STAMP_SYNC_0 0x244
+#define AIFIFO_TIME_STAMP_SYNC_1 0x248
+#define AIFIFO_TIME_STAMP_0 0x24C
+#define AIFIFO_TIME_STAMP_1 0x250
+#define AIFIFO_TIME_STAMP_2 0x254
+#define AIFIFO_TIME_STAMP_3 0x258
+#define AIFIFO_TIME_STAMP_LENGTH 0x25C
+#define AIFIFO2_TIME_STAMP_CNTL 0x260
+#define AIFIFO2_TIME_STAMP_SYNC_0 0x264
+#define AIFIFO2_TIME_STAMP_SYNC_1 0x268
+#define AIFIFO2_TIME_STAMP_0 0x26C
+#define AIFIFO2_TIME_STAMP_1 0x270
+#define AIFIFO2_TIME_STAMP_2 0x274
+#define AIFIFO2_TIME_STAMP_3 0x278
+#define AIFIFO2_TIME_STAMP_LENGTH 0x27C
+#define IEC958_TIME_STAMP_CNTL 0x280
+#define IEC958_TIME_STAMP_SYNC_0 0x284
+#define IEC958_TIME_STAMP_SYNC_1 0x288
+#define IEC958_TIME_STAMP_0 0x28C
+#define IEC958_TIME_STAMP_1 0x290
+#define IEC958_TIME_STAMP_2 0x294
+#define IEC958_TIME_STAMP_3 0x298
+#define IEC958_TIME_STAMP_LENGTH 0x29C
+#define AIU_MEM_AIFIFO2_MEM_CTL 0x2A0
+#define AIU_I2S_CBUS_DDR_CNTL 0x2A4
+#define AIU_I2S_CBUS_DDR_WDATA 0x2A8
+#define AIU_I2S_CBUS_DDR_ADDR 0x2AC
+
+#endif /* _AIU_REGS_H_ */
diff --git a/sound/soc/meson/audin-regs.h b/sound/soc/meson/audin-regs.h
new file mode 100644
index 000000000000..f224610e80e7
--- /dev/null
+++ b/sound/soc/meson/audin-regs.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2017 BayLibre, SAS
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _AUDIN_REGS_H_
+#define _AUDIN_REGS_H_
+
+/*
+ * Note :
+ * Datasheet issue page 196
+ * AUDIN_MUTE_VAL 0x35 => impossible: Already assigned to AUDIN_FIFO1_PTR
+ * AUDIN_FIFO1_PTR is more likely to be correct here since surrounding registers
+ * also deal with AUDIN_FIFO1
+ *
+ * Clarification needed from Amlogic
+ */
+
+#define AUDIN_SPDIF_MODE 0x000
+#define AUDIN_SPDIF_FS_CLK_RLTN 0x004
+#define AUDIN_SPDIF_CHNL_STS_A 0x008
+#define AUDIN_SPDIF_CHNL_STS_B 0x00C
+#define AUDIN_SPDIF_MISC 0x010
+#define AUDIN_SPDIF_NPCM_PCPD 0x014
+#define AUDIN_SPDIF_END 0x03C /* Unknown */
+#define AUDIN_I2SIN_CTRL 0x040
+#define AUDIN_SOURCE_SEL 0x044
+#define AUDIN_DECODE_FORMAT 0x048
+#define AUDIN_DECODE_CONTROL_STATUS 0x04C
+#define AUDIN_DECODE_CHANNEL_STATUS_A_0 0x050
+#define AUDIN_DECODE_CHANNEL_STATUS_A_1 0x054
+#define AUDIN_DECODE_CHANNEL_STATUS_A_2 0x058
+#define AUDIN_DECODE_CHANNEL_STATUS_A_3 0x05C
+#define AUDIN_DECODE_CHANNEL_STATUS_A_4 0x060
+#define AUDIN_DECODE_CHANNEL_STATUS_A_5 0x064
+#define AUDIN_FIFO0_START 0x080
+#define AUDIN_FIFO0_END 0x084
+#define AUDIN_FIFO0_PTR 0x088
+#define AUDIN_FIFO0_INTR 0x08C
+#define AUDIN_FIFO0_RDPTR 0x090
+#define AUDIN_FIFO0_CTRL 0x094
+#define AUDIN_FIFO0_CTRL1 0x098
+#define AUDIN_FIFO0_LVL0 0x09C
+#define AUDIN_FIFO0_LVL1 0x0A0
+#define AUDIN_FIFO0_LVL2 0x0A4
+#define AUDIN_FIFO0_REQID 0x0C0
+#define AUDIN_FIFO0_WRAP 0x0C4
+#define AUDIN_FIFO1_START 0x0CC
+#define AUDIN_FIFO1_END 0x0D0
+#define AUDIN_FIFO1_PTR 0x0D4
+#define AUDIN_FIFO1_INTR 0x0D8
+#define AUDIN_FIFO1_RDPTR 0x0DC
+#define AUDIN_FIFO1_CTRL 0x0E0
+#define AUDIN_FIFO1_CTRL1 0x0E4
+#define AUDIN_FIFO1_LVL0 0x100
+#define AUDIN_FIFO1_LVL1 0x104
+#define AUDIN_FIFO1_LVL2 0x108
+#define AUDIN_FIFO1_REQID 0x10C
+#define AUDIN_FIFO1_WRAP 0x110
+#define AUDIN_FIFO2_START 0x114
+#define AUDIN_FIFO2_END 0x118
+#define AUDIN_FIFO2_PTR 0x11C
+#define AUDIN_FIFO2_INTR 0x120
+#define AUDIN_FIFO2_RDPTR 0x124
+#define AUDIN_FIFO2_CTRL 0x128
+#define AUDIN_FIFO2_CTRL1 0x12C
+#define AUDIN_FIFO2_LVL0 0x130
+#define AUDIN_FIFO2_LVL1 0x134
+#define AUDIN_FIFO2_LVL2 0x138
+#define AUDIN_FIFO2_REQID 0x13C
+#define AUDIN_FIFO2_WRAP 0x140
+#define AUDIN_INT_CTRL 0x144
+#define AUDIN_FIFO_INT 0x148
+#define PCMIN_CTRL0 0x180
+#define PCMIN_CTRL1 0x184
+#define PCMIN1_CTRL0 0x188
+#define PCMIN1_CTRL1 0x18C
+#define PCMOUT_CTRL0 0x1C0
+#define PCMOUT_CTRL1 0x1C4
+#define PCMOUT_CTRL2 0x1C8
+#define PCMOUT_CTRL3 0x1CC
+#define PCMOUT1_CTRL0 0x1D0
+#define PCMOUT1_CTRL1 0x1D4
+#define PCMOUT1_CTRL2 0x1D8
+#define PCMOUT1_CTRL3 0x1DC
+#define AUDOUT_CTRL 0x200
+#define AUDOUT_CTRL1 0x204
+#define AUDOUT_BUF0_STA 0x208
+#define AUDOUT_BUF0_EDA 0x20C
+#define AUDOUT_BUF0_WPTR 0x210
+#define AUDOUT_BUF1_STA 0x214
+#define AUDOUT_BUF1_EDA 0x218
+#define AUDOUT_BUF1_WPTR 0x21C
+#define AUDOUT_FIFO_RPTR 0x220
+#define AUDOUT_INTR_PTR 0x224
+#define AUDOUT_FIFO_STS 0x228
+#define AUDOUT1_CTRL 0x240
+#define AUDOUT1_CTRL1 0x244
+#define AUDOUT1_BUF0_STA 0x248
+#define AUDOUT1_BUF0_EDA 0x24C
+#define AUDOUT1_BUF0_WPTR 0x250
+#define AUDOUT1_BUF1_STA 0x254
+#define AUDOUT1_BUF1_EDA 0x258
+#define AUDOUT1_BUF1_WPTR 0x25C
+#define AUDOUT1_FIFO_RPTR 0x260
+#define AUDOUT1_INTR_PTR 0x264
+#define AUDOUT1_FIFO_STS 0x268
+#define AUDIN_HDMI_MEAS_CTRL 0x280
+#define AUDIN_HDMI_MEAS_CYCLES_M1 0x284
+#define AUDIN_HDMI_MEAS_INTR_MASKN 0x288
+#define AUDIN_HDMI_MEAS_INTR_STAT 0x28C
+#define AUDIN_HDMI_REF_CYCLES_STAT_0 0x290
+#define AUDIN_HDMI_REF_CYCLES_STAT_1 0x294
+#define AUDIN_HDMIRX_AFIFO_STAT 0x298
+#define AUDIN_FIFO0_PIO_STS 0x2C0
+#define AUDIN_FIFO0_PIO_RDL 0x2C4
+#define AUDIN_FIFO0_PIO_RDH 0x2C8
+#define AUDIN_FIFO1_PIO_STS 0x2CC
+#define AUDIN_FIFO1_PIO_RDL 0x2D0
+#define AUDIN_FIFO1_PIO_RDH 0x2D4
+#define AUDIN_FIFO2_PIO_STS 0x2D8
+#define AUDIN_FIFO2_PIO_RDL 0x2DC
+#define AUDIN_FIFO2_PIO_RDH 0x2E0
+#define AUDOUT_FIFO_PIO_STS 0x2E4
+#define AUDOUT_FIFO_PIO_WRL 0x2E8
+#define AUDOUT_FIFO_PIO_WRH 0x2EC
+#define AUDOUT1_FIFO_PIO_STS 0x2F0 /* Unknown */
+#define AUDOUT1_FIFO_PIO_WRL 0x2F4 /* Unknown */
+#define AUDOUT1_FIFO_PIO_WRH 0x2F8 /* Unknown */
+#define AUD_RESAMPLE_CTRL0 0x2FC
+#define AUD_RESAMPLE_CTRL1 0x300
+#define AUD_RESAMPLE_STATUS 0x304
+
+#endif /* _AUDIN_REGS_H_ */
--
2.18.0

View File

@@ -0,0 +1,419 @@
From 5141d439ad763571f6ad26e7aa52b9aabea1816a Mon Sep 17 00:00:00 2001
From: Jerome Brunet <jbrunet@baylibre.com>
Date: Thu, 30 Mar 2017 12:14:40 +0200
Subject: [PATCH 09/21] ASoC: meson: add aiu i2s dma support
Add support for the i2s output dma which is part of the AIU block
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
sound/soc/meson/Kconfig | 7 +
sound/soc/meson/Makefile | 2 +
sound/soc/meson/aiu-i2s-dma.c | 370 ++++++++++++++++++++++++++++++++++
3 files changed, 379 insertions(+)
create mode 100644 sound/soc/meson/aiu-i2s-dma.c
diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig
index ca0e3e981a99..88fbfc264146 100644
--- a/sound/soc/meson/Kconfig
+++ b/sound/soc/meson/Kconfig
@@ -7,3 +7,10 @@ menuconfig SND_SOC_MESON
Say Y or M if you want to add support for codecs attached to
the Amlogic Meson SoCs Audio interfaces. You will also need to
select the audio interfaces to support below.
+
+config SND_SOC_MESON_I2S
+ tristate "Meson i2s interface"
+ depends on SND_SOC_MESON
+ help
+ Say Y or M if you want to add support for i2s dma driver for Amlogic
+ Meson SoCs.
diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile
index 22028abb5624..273f27590773 100644
--- a/sound/soc/meson/Makefile
+++ b/sound/soc/meson/Makefile
@@ -1,3 +1,5 @@
snd-soc-meson-audio-core-objs := audio-core.o
+snd-soc-meson-aiu-i2s-dma-objs := aiu-i2s-dma.o
obj-$(CONFIG_SND_SOC_MESON) += snd-soc-meson-audio-core.o
+obj-$(CONFIG_SND_SOC_MESON_I2S) += snd-soc-meson-aiu-i2s-dma.o
diff --git a/sound/soc/meson/aiu-i2s-dma.c b/sound/soc/meson/aiu-i2s-dma.c
new file mode 100644
index 000000000000..2684bd0db19e
--- /dev/null
+++ b/sound/soc/meson/aiu-i2s-dma.c
@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2017 BayLibre, SAS
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "aiu-regs.h"
+#include "audio-core.h"
+
+#define DRV_NAME "meson-aiu-i2s-dma"
+
+struct aiu_i2s_dma {
+ struct meson_audio_core_data *core;
+ struct clk *fast;
+ int irq;
+};
+
+#define AIU_MEM_I2S_BUF_CNTL_INIT BIT(0)
+#define AIU_MEM_I2S_CONTROL_INIT BIT(0)
+#define AIU_MEM_I2S_CONTROL_FILL_EN BIT(1)
+#define AIU_MEM_I2S_CONTROL_EMPTY_EN BIT(2)
+#define AIU_MEM_I2S_CONTROL_MODE_16BIT BIT(6)
+#define AIU_MEM_I2S_CONTROL_BUSY BIT(7)
+#define AIU_MEM_I2S_CONTROL_DATA_READY BIT(8)
+#define AIU_MEM_I2S_CONTROL_LEVEL_CNTL BIT(9)
+#define AIU_MEM_I2S_MASKS_IRQ_BLOCK_MASK GENMASK(31, 16)
+#define AIU_MEM_I2S_MASKS_IRQ_BLOCK(n) ((n) << 16)
+#define AIU_MEM_I2S_MASKS_CH_MEM_MASK GENMASK(15, 8)
+#define AIU_MEM_I2S_MASKS_CH_MEM(ch) ((ch) << 8)
+#define AIU_MEM_I2S_MASKS_CH_RD_MASK GENMASK(7, 0)
+#define AIU_MEM_I2S_MASKS_CH_RD(ch) ((ch) << 0)
+#define AIU_RST_SOFT_I2S_FAST_DOMAIN BIT(0)
+#define AIU_RST_SOFT_I2S_SLOW_DOMAIN BIT(1)
+
+/*
+ * The DMA works by i2s "blocks" (or DMA burst). The burst size and the memory
+ * layout expected depends on the mode of operation.
+ *
+ * - Normal mode: The channels are expected to be packed in 32 bytes groups
+ * interleaved the buffer. AIU_MEM_I2S_MASKS_CH_MEM is a bitfield representing
+ * the channels present in memory. AIU_MEM_I2S_MASKS_CH_MEM represents the
+ * channels read by the DMA. This is very flexible but the unsual memory layout
+ * makes it less easy to deal with. The burst size is 32 bytes times the number
+ * of channels read.
+ *
+ * - Split mode:
+ * Classical channel interleaved frame organisation. In this mode,
+ * AIU_MEM_I2S_MASKS_CH_MEM and AIU_MEM_I2S_MASKS_CH_MEM must be set to 0xff and
+ * the burst size is fixed to 256 bytes. The input can be either 2 or 8
+ * channels.
+ *
+ * The following driver implements the split mode.
+ */
+
+#define AIU_I2S_DMA_BURST 256
+
+static struct snd_pcm_hardware aiu_i2s_dma_hw = {
+ .info = (SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE),
+
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE),
+
+ /*
+ * TODO: The DMA can change the endianness, the msb position
+ * and deal with unsigned - support this later on
+ */
+
+ .rate_min = 8000,
+ .rate_max = 192000,
+ .channels_min = 2,
+ .channels_max = 8,
+ .period_bytes_min = AIU_I2S_DMA_BURST,
+ .period_bytes_max = AIU_I2S_DMA_BURST * 65535,
+ .periods_min = 2,
+ .periods_max = UINT_MAX,
+ .buffer_bytes_max = 1 * 1024 * 1024,
+ .fifo_size = 0,
+};
+
+static struct aiu_i2s_dma *aiu_i2s_dma_priv(struct snd_pcm_substream *s)
+{
+ struct snd_soc_pcm_runtime *rtd = s->private_data;
+ struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
+
+ return snd_soc_component_get_drvdata(component);
+}
+
+static snd_pcm_uframes_t
+aiu_i2s_dma_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct aiu_i2s_dma *priv = aiu_i2s_dma_priv(substream);
+ unsigned int addr;
+ int ret;
+
+ ret = regmap_read(priv->core->aiu, AIU_MEM_I2S_RD_PTR,
+ &addr);
+ if (ret)
+ return 0;
+
+ return bytes_to_frames(runtime, addr - (unsigned int)runtime->dma_addr);
+}
+
+static void __dma_enable(struct aiu_i2s_dma *priv, bool enable)
+{
+ unsigned int en_mask = (AIU_MEM_I2S_CONTROL_FILL_EN |
+ AIU_MEM_I2S_CONTROL_EMPTY_EN);
+
+ regmap_update_bits(priv->core->aiu, AIU_MEM_I2S_CONTROL, en_mask,
+ enable ? en_mask : 0);
+
+}
+
+static int aiu_i2s_dma_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct aiu_i2s_dma *priv = aiu_i2s_dma_priv(substream);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ __dma_enable(priv, true);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_STOP:
+ __dma_enable(priv, false);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void __dma_init_mem(struct aiu_i2s_dma *priv)
+{
+ regmap_update_bits(priv->core->aiu, AIU_MEM_I2S_CONTROL,
+ AIU_MEM_I2S_CONTROL_INIT,
+ AIU_MEM_I2S_CONTROL_INIT);
+ regmap_update_bits(priv->core->aiu, AIU_MEM_I2S_BUF_CNTL,
+ AIU_MEM_I2S_BUF_CNTL_INIT,
+ AIU_MEM_I2S_BUF_CNTL_INIT);
+
+ regmap_update_bits(priv->core->aiu, AIU_MEM_I2S_CONTROL,
+ AIU_MEM_I2S_CONTROL_INIT,
+ 0);
+ regmap_update_bits(priv->core->aiu, AIU_MEM_I2S_BUF_CNTL,
+ AIU_MEM_I2S_BUF_CNTL_INIT,
+ 0);
+}
+
+static int aiu_i2s_dma_prepare(struct snd_pcm_substream *substream)
+{
+ struct aiu_i2s_dma *priv = aiu_i2s_dma_priv(substream);
+
+ __dma_init_mem(priv);
+
+ return 0;
+}
+
+static int aiu_i2s_dma_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct aiu_i2s_dma *priv = aiu_i2s_dma_priv(substream);
+ int ret;
+ u32 burst_num, mem_ctl;
+ dma_addr_t end_ptr;
+
+ ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+ if (ret < 0)
+ return ret;
+
+ /* Setup memory layout */
+ if (params_physical_width(params) == 16)
+ mem_ctl = AIU_MEM_I2S_CONTROL_MODE_16BIT;
+ else
+ mem_ctl = 0;
+
+ regmap_update_bits(priv->core->aiu, AIU_MEM_I2S_CONTROL,
+ AIU_MEM_I2S_CONTROL_MODE_16BIT,
+ mem_ctl);
+
+ /* Initialize memory pointers */
+ regmap_write(priv->core->aiu, AIU_MEM_I2S_START_PTR, runtime->dma_addr);
+ regmap_write(priv->core->aiu, AIU_MEM_I2S_RD_PTR, runtime->dma_addr);
+
+ /* The end pointer is the address of the last valid block */
+ end_ptr = runtime->dma_addr + runtime->dma_bytes - AIU_I2S_DMA_BURST;
+ regmap_write(priv->core->aiu, AIU_MEM_I2S_END_PTR, end_ptr);
+
+ /* Memory masks */
+ burst_num = params_period_bytes(params) / AIU_I2S_DMA_BURST;
+ regmap_write(priv->core->aiu, AIU_MEM_I2S_MASKS,
+ AIU_MEM_I2S_MASKS_CH_RD(0xff) |
+ AIU_MEM_I2S_MASKS_CH_MEM(0xff) |
+ AIU_MEM_I2S_MASKS_IRQ_BLOCK(burst_num));
+
+ return 0;
+}
+
+static int aiu_i2s_dma_hw_free(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_lib_free_pages(substream);
+}
+
+
+static irqreturn_t aiu_i2s_dma_irq_block(int irq, void *dev_id)
+{
+ struct snd_pcm_substream *playback = dev_id;
+
+ snd_pcm_period_elapsed(playback);
+
+ return IRQ_HANDLED;
+}
+
+static int aiu_i2s_dma_open(struct snd_pcm_substream *substream)
+{
+ struct aiu_i2s_dma *priv = aiu_i2s_dma_priv(substream);
+ int ret;
+
+ snd_soc_set_runtime_hwparams(substream, &aiu_i2s_dma_hw);
+
+ /*
+ * Make sure the buffer and period size are multiple of the DMA burst
+ * size
+ */
+ ret = snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+ AIU_I2S_DMA_BURST);
+ if (ret)
+ return ret;
+
+ ret = snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+ AIU_I2S_DMA_BURST);
+ if (ret)
+ return ret;
+
+ /* Request the I2S DDR irq */
+ ret = request_irq(priv->irq, aiu_i2s_dma_irq_block, 0,
+ DRV_NAME, substream);
+ if (ret)
+ return ret;
+
+ /* Power up the i2s fast domain - can't write the registers w/o it */
+ ret = clk_prepare_enable(priv->fast);
+ if (ret)
+ return ret;
+
+ /* Make sure the dma is initially disabled */
+ __dma_enable(priv, false);
+
+ return 0;
+}
+
+static int aiu_i2s_dma_close(struct snd_pcm_substream *substream)
+{
+ struct aiu_i2s_dma *priv = aiu_i2s_dma_priv(substream);
+
+ clk_disable_unprepare(priv->fast);
+ free_irq(priv->irq, substream);
+
+ return 0;
+}
+
+static const struct snd_pcm_ops aiu_i2s_dma_ops = {
+ .open = aiu_i2s_dma_open,
+ .close = aiu_i2s_dma_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = aiu_i2s_dma_hw_params,
+ .hw_free = aiu_i2s_dma_hw_free,
+ .prepare = aiu_i2s_dma_prepare,
+ .pointer = aiu_i2s_dma_pointer,
+ .trigger = aiu_i2s_dma_trigger,
+};
+
+static int aiu_i2s_dma_new(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_card *card = rtd->card->snd_card;
+ size_t size = aiu_i2s_dma_hw.buffer_bytes_max;
+
+ return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
+ SNDRV_DMA_TYPE_DEV,
+ card->dev, size, size);
+}
+
+static const struct snd_soc_component_driver aiu_i2s_platform = {
+ .ops = &aiu_i2s_dma_ops,
+ .pcm_new = aiu_i2s_dma_new,
+ .name = DRV_NAME,
+};
+
+static int aiu_i2s_dma_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct aiu_i2s_dma *priv;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, priv);
+ priv->core = dev_get_drvdata(dev->parent);
+
+ priv->fast = devm_clk_get(dev, "fast");
+ if (IS_ERR(priv->fast)) {
+ if (PTR_ERR(priv->fast) != -EPROBE_DEFER)
+ dev_err(dev, "Can't get i2s fast domain clock\n");
+ return PTR_ERR(priv->fast);
+ }
+
+ priv->irq = platform_get_irq(pdev, 0);
+ if (priv->irq <= 0) {
+ dev_err(dev, "Can't get i2s ddr irq\n");
+ return priv->irq;
+ }
+
+ return devm_snd_soc_register_component(dev, &aiu_i2s_platform,
+ NULL, 0);
+}
+
+static const struct of_device_id aiu_i2s_dma_of_match[] = {
+ { .compatible = "amlogic,meson-aiu-i2s-dma", },
+ { .compatible = "amlogic,meson-gxbb-aiu-i2s-dma", },
+ { .compatible = "amlogic,meson-gxl-aiu-i2s-dma", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, aiu_i2s_dma_of_match);
+
+static struct platform_driver aiu_i2s_dma_pdrv = {
+ .probe = aiu_i2s_dma_probe,
+ .driver = {
+ .name = DRV_NAME,
+ .of_match_table = aiu_i2s_dma_of_match,
+ },
+};
+module_platform_driver(aiu_i2s_dma_pdrv);
+
+MODULE_DESCRIPTION("Meson AIU i2s DMA ASoC Driver");
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
+MODULE_LICENSE("GPL v2");
--
2.18.0

View File

@@ -0,0 +1,514 @@
From a5eaab662bb676374fd4275d41f209383ecc9130 Mon Sep 17 00:00:00 2001
From: Jerome Brunet <jbrunet@baylibre.com>
Date: Thu, 30 Mar 2017 12:17:27 +0200
Subject: [PATCH 10/21] ASoC: meson: add initial i2s dai support
Add support for the i2s dai found on Amlogic Meson SoC family.
With this initial implementation, only playback is supported.
Capture will be part of furture work.
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
sound/soc/meson/Kconfig | 2 +-
sound/soc/meson/Makefile | 2 +
sound/soc/meson/i2s-dai.c | 465 ++++++++++++++++++++++++++++++++++++++
3 files changed, 468 insertions(+), 1 deletion(-)
create mode 100644 sound/soc/meson/i2s-dai.c
diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig
index 88fbfc264146..478f29a2a3b2 100644
--- a/sound/soc/meson/Kconfig
+++ b/sound/soc/meson/Kconfig
@@ -12,5 +12,5 @@ config SND_SOC_MESON_I2S
tristate "Meson i2s interface"
depends on SND_SOC_MESON
help
- Say Y or M if you want to add support for i2s dma driver for Amlogic
+ Say Y or M if you want to add support for i2s driver for Amlogic
Meson SoCs.
diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile
index 273f27590773..ea06ddee39d1 100644
--- a/sound/soc/meson/Makefile
+++ b/sound/soc/meson/Makefile
@@ -1,5 +1,7 @@
snd-soc-meson-audio-core-objs := audio-core.o
snd-soc-meson-aiu-i2s-dma-objs := aiu-i2s-dma.o
+snd-soc-meson-i2s-dai-objs := i2s-dai.o
obj-$(CONFIG_SND_SOC_MESON) += snd-soc-meson-audio-core.o
obj-$(CONFIG_SND_SOC_MESON_I2S) += snd-soc-meson-aiu-i2s-dma.o
+obj-$(CONFIG_SND_SOC_MESON_I2S) += snd-soc-meson-i2s-dai.o
diff --git a/sound/soc/meson/i2s-dai.c b/sound/soc/meson/i2s-dai.c
new file mode 100644
index 000000000000..1008af8d3972
--- /dev/null
+++ b/sound/soc/meson/i2s-dai.c
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2017 BayLibre, SAS
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+
+#include "aiu-regs.h"
+#include "audio-core.h"
+
+#define DRV_NAME "meson-i2s-dai"
+
+struct meson_i2s_dai {
+ struct meson_audio_core_data *core;
+ struct clk *mclk;
+ struct clk *bclks;
+ struct clk *iface;
+ struct clk *fast;
+ bool bclks_idle;
+};
+
+#define AIU_CLK_CTRL_I2S_DIV_EN BIT(0)
+#define AIU_CLK_CTRL_I2S_DIV_MASK GENMASK(3, 2)
+#define AIU_CLK_CTRL_AOCLK_POLARITY_MASK BIT(6)
+#define AIU_CLK_CTRL_AOCLK_POLARITY_NORMAL (0 << 6)
+#define AIU_CLK_CTRL_AOCLK_POLARITY_INVERTED (1 << 6)
+#define AIU_CLK_CTRL_ALRCLK_POLARITY_MASK BIT(7)
+#define AIU_CLK_CTRL_ALRCLK_POLARITY_NORMAL (0 << 7)
+#define AIU_CLK_CTRL_ALRCLK_POLARITY_INVERTED (1 << 7)
+#define AIU_CLK_CTRL_ALRCLK_SKEW_MASK GENMASK(9, 8)
+#define AIU_CLK_CTRL_ALRCLK_LEFT_J (0 << 8)
+#define AIU_CLK_CTRL_ALRCLK_I2S (1 << 8)
+#define AIU_CLK_CTRL_ALRCLK_RIGHT_J (2 << 8)
+#define AIU_CLK_CTRL_MORE_I2S_DIV_MASK GENMASK(5, 0)
+#define AIU_CLK_CTRL_MORE_I2S_DIV(div) (((div) - 1) << 0)
+#define AIU_CODEC_DAC_LRCLK_CTRL_DIV_MASK GENMASK(11, 0)
+#define AIU_CODEC_DAC_LRCLK_CTRL_DIV(div) (((div) - 1) << 0)
+#define AIU_I2S_DAC_CFG_PAYLOAD_SIZE_MASK GENMASK(1, 0)
+#define AIU_I2S_DAC_CFG_AOCLK_32 (0 << 0)
+#define AIU_I2S_DAC_CFG_AOCLK_48 (2 << 0)
+#define AIU_I2S_DAC_CFG_AOCLK_64 (3 << 0)
+#define AIU_I2S_MISC_HOLD_EN BIT(2)
+#define AIU_I2S_SOURCE_DESC_MODE_8CH BIT(0)
+#define AIU_I2S_SOURCE_DESC_MODE_24BIT BIT(5)
+#define AIU_I2S_SOURCE_DESC_MODE_32BIT BIT(9)
+#define AIU_I2S_SOURCE_DESC_MODE_SPLIT BIT(11)
+
+static void __hold(struct meson_i2s_dai *priv, bool enable)
+{
+ regmap_update_bits(priv->core->aiu, AIU_I2S_MISC,
+ AIU_I2S_MISC_HOLD_EN,
+ enable ? AIU_I2S_MISC_HOLD_EN : 0);
+}
+
+static void __divider_enable(struct meson_i2s_dai *priv, bool enable)
+{
+ regmap_update_bits(priv->core->aiu, AIU_CLK_CTRL,
+ AIU_CLK_CTRL_I2S_DIV_EN,
+ enable ? AIU_CLK_CTRL_I2S_DIV_EN : 0);
+}
+
+static void __playback_start(struct meson_i2s_dai *priv)
+{
+ __divider_enable(priv, true);
+ __hold(priv, false);
+}
+
+static void __playback_stop(struct meson_i2s_dai *priv, bool clk_force)
+{
+ __hold(priv, true);
+ /* Disable the bit clks if necessary */
+ if (clk_force || !priv->bclks_idle)
+ __divider_enable(priv, false);
+}
+
+static int meson_i2s_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct meson_i2s_dai *priv = snd_soc_dai_get_drvdata(dai);
+ bool clk_force_stop = false;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ __playback_start(priv);
+ return 0;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ clk_force_stop = true;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ __playback_stop(priv, clk_force_stop);
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int __bclks_set_rate(struct meson_i2s_dai *priv, unsigned int srate,
+ unsigned int width)
+{
+ unsigned int fs;
+
+ /* Get the oversampling factor */
+ fs = DIV_ROUND_CLOSEST(clk_get_rate(priv->mclk), srate);
+
+ /*
+ * This DAI is usually connected to the dw-hdmi which does not support
+ * bclk being 32 * lrclk or 48 * lrclk
+ * Restrict to blck = 64 * lrclk
+ */
+ if (fs % 64)
+ return -EINVAL;
+
+ /* Set the divider between lrclk and bclk */
+ regmap_update_bits(priv->core->aiu, AIU_I2S_DAC_CFG,
+ AIU_I2S_DAC_CFG_PAYLOAD_SIZE_MASK,
+ AIU_I2S_DAC_CFG_AOCLK_64);
+
+ regmap_update_bits(priv->core->aiu, AIU_CODEC_DAC_LRCLK_CTRL,
+ AIU_CODEC_DAC_LRCLK_CTRL_DIV_MASK,
+ AIU_CODEC_DAC_LRCLK_CTRL_DIV(64));
+
+ /* Use CLK_MORE for the i2s divider */
+ regmap_update_bits(priv->core->aiu, AIU_CLK_CTRL,
+ AIU_CLK_CTRL_I2S_DIV_MASK,
+ 0);
+
+ regmap_update_bits(priv->core->aiu, AIU_CLK_CTRL_MORE,
+ AIU_CLK_CTRL_MORE_I2S_DIV_MASK,
+ AIU_CLK_CTRL_MORE_I2S_DIV(fs / 64));
+
+ return 0;
+}
+
+static int __setup_desc(struct meson_i2s_dai *priv, unsigned int width,
+ unsigned int channels)
+{
+ u32 desc = 0;
+
+ switch (width) {
+ case 24:
+ /*
+ * For some reason, 24 bits wide audio don't play well
+ * if the 32 bits mode is not set
+ */
+ desc |= (AIU_I2S_SOURCE_DESC_MODE_24BIT |
+ AIU_I2S_SOURCE_DESC_MODE_32BIT);
+ break;
+ case 16:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ switch (channels) {
+ case 2: /* Nothing to do */
+ break;
+ case 8:
+ /* TODO: Still requires testing ... */
+ desc |= AIU_I2S_SOURCE_DESC_MODE_8CH;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(priv->core->aiu, AIU_I2S_SOURCE_DESC,
+ AIU_I2S_SOURCE_DESC_MODE_8CH |
+ AIU_I2S_SOURCE_DESC_MODE_24BIT |
+ AIU_I2S_SOURCE_DESC_MODE_32BIT,
+ desc);
+
+ return 0;
+}
+
+static int meson_i2s_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct meson_i2s_dai *priv = snd_soc_dai_get_drvdata(dai);
+ unsigned int width = params_width(params);
+ unsigned int channels = params_channels(params);
+ unsigned int rate = params_rate(params);
+ int ret;
+
+ ret = __setup_desc(priv, width, channels);
+ if (ret) {
+ dev_err(dai->dev, "Unable set to set i2s description\n");
+ return ret;
+ }
+
+ ret = __bclks_set_rate(priv, rate, width);
+ if (ret) {
+ dev_err(dai->dev, "Unable set to the i2s clock rates\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int meson_i2s_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct meson_i2s_dai *priv = snd_soc_dai_get_drvdata(dai);
+ u32 val;
+
+ if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
+ return -EINVAL;
+
+ /* DAI output mode */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ val = AIU_CLK_CTRL_ALRCLK_I2S;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ val = AIU_CLK_CTRL_ALRCLK_LEFT_J;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ val = AIU_CLK_CTRL_ALRCLK_RIGHT_J;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(priv->core->aiu, AIU_CLK_CTRL,
+ AIU_CLK_CTRL_ALRCLK_SKEW_MASK,
+ val);
+
+ /* DAI clock polarity */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_IB_IF:
+ /* Invert both clocks */
+ val = AIU_CLK_CTRL_ALRCLK_POLARITY_INVERTED |
+ AIU_CLK_CTRL_AOCLK_POLARITY_INVERTED;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ /* Invert bit clock */
+ val = AIU_CLK_CTRL_ALRCLK_POLARITY_NORMAL |
+ AIU_CLK_CTRL_AOCLK_POLARITY_INVERTED;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ /* Invert frame clock */
+ val = AIU_CLK_CTRL_ALRCLK_POLARITY_INVERTED |
+ AIU_CLK_CTRL_AOCLK_POLARITY_NORMAL;
+ break;
+ case SND_SOC_DAIFMT_NB_NF:
+ /* Normal clocks */
+ val = AIU_CLK_CTRL_ALRCLK_POLARITY_NORMAL |
+ AIU_CLK_CTRL_AOCLK_POLARITY_NORMAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(priv->core->aiu, AIU_CLK_CTRL,
+ AIU_CLK_CTRL_ALRCLK_POLARITY_MASK |
+ AIU_CLK_CTRL_AOCLK_POLARITY_MASK,
+ val);
+
+ switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
+ case SND_SOC_DAIFMT_CONT:
+ priv->bclks_idle = true;
+ break;
+ case SND_SOC_DAIFMT_GATED:
+ priv->bclks_idle = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int meson_i2s_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+ unsigned int freq, int dir)
+{
+ struct meson_i2s_dai *priv = snd_soc_dai_get_drvdata(dai);
+ int ret;
+
+ if (WARN_ON(clk_id != 0))
+ return -EINVAL;
+
+ if (dir == SND_SOC_CLOCK_IN)
+ return 0;
+
+ ret = clk_set_rate(priv->mclk, freq);
+ if (ret) {
+ dev_err(dai->dev, "Failed to set sysclk to %uHz", freq);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int meson_i2s_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct meson_i2s_dai *priv = snd_soc_dai_get_drvdata(dai);
+ int ret;
+
+ /* Power up the i2s fast domain - can't write the registers w/o it */
+ ret = clk_prepare_enable(priv->fast);
+ if (ret)
+ goto out_clk_fast;
+
+ /* Make sure nothing gets out of the DAI yet */
+ __hold(priv, true);
+
+ /* I2S encoder needs the mixer interface gate */
+ ret = clk_prepare_enable(priv->iface);
+ if (ret)
+ goto out_clk_iface;
+
+ /* Enable the i2s master clock */
+ ret = clk_prepare_enable(priv->mclk);
+ if (ret)
+ goto out_mclk;
+
+ /* Enable the bit clock gate */
+ ret = clk_prepare_enable(priv->bclks);
+ if (ret)
+ goto out_bclks;
+
+ /* Make sure the interface expect a memory layout we can work with */
+ regmap_update_bits(priv->core->aiu, AIU_I2S_SOURCE_DESC,
+ AIU_I2S_SOURCE_DESC_MODE_SPLIT,
+ AIU_I2S_SOURCE_DESC_MODE_SPLIT);
+
+ return 0;
+
+out_bclks:
+ clk_disable_unprepare(priv->mclk);
+out_mclk:
+ clk_disable_unprepare(priv->iface);
+out_clk_iface:
+ clk_disable_unprepare(priv->fast);
+out_clk_fast:
+ return ret;
+}
+
+static void meson_i2s_dai_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct meson_i2s_dai *priv = snd_soc_dai_get_drvdata(dai);
+
+ clk_disable_unprepare(priv->bclks);
+ clk_disable_unprepare(priv->mclk);
+ clk_disable_unprepare(priv->iface);
+ clk_disable_unprepare(priv->fast);
+}
+
+static const struct snd_soc_dai_ops meson_i2s_dai_ops = {
+ .startup = meson_i2s_dai_startup,
+ .shutdown = meson_i2s_dai_shutdown,
+ .trigger = meson_i2s_dai_trigger,
+ .hw_params = meson_i2s_dai_hw_params,
+ .set_fmt = meson_i2s_dai_set_fmt,
+ .set_sysclk = meson_i2s_dai_set_sysclk,
+};
+
+static struct snd_soc_dai_driver meson_i2s_dai = {
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE)
+ },
+ .ops = &meson_i2s_dai_ops,
+};
+
+static const struct snd_soc_component_driver meson_i2s_dai_component = {
+ .name = DRV_NAME,
+};
+
+static int meson_i2s_dai_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct meson_i2s_dai *priv;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, priv);
+ priv->core = dev_get_drvdata(dev->parent);
+
+ priv->fast = devm_clk_get(dev, "fast");
+ if (IS_ERR(priv->fast)) {
+ if (PTR_ERR(priv->fast) != -EPROBE_DEFER)
+ dev_err(dev, "Can't get the i2s fast domain clock\n");
+ return PTR_ERR(priv->fast);
+ }
+
+ priv->iface = devm_clk_get(dev, "iface");
+ if (IS_ERR(priv->iface)) {
+ if (PTR_ERR(priv->iface) != -EPROBE_DEFER)
+ dev_err(dev, "Can't get i2s dai clock gate\n");
+ return PTR_ERR(priv->iface);
+ }
+
+ priv->bclks = devm_clk_get(dev, "bclks");
+ if (IS_ERR(priv->bclks)) {
+ if (PTR_ERR(priv->bclks) != -EPROBE_DEFER)
+ dev_err(dev, "Can't get bit clocks gate\n");
+ return PTR_ERR(priv->bclks);
+ }
+
+ priv->mclk = devm_clk_get(dev, "mclk");
+ if (IS_ERR(priv->mclk)) {
+ if (PTR_ERR(priv->mclk) != -EPROBE_DEFER)
+ dev_err(dev, "failed to get the i2s master clock\n");
+ return PTR_ERR(priv->mclk);
+ }
+
+ return devm_snd_soc_register_component(dev, &meson_i2s_dai_component,
+ &meson_i2s_dai, 1);
+}
+
+static const struct of_device_id meson_i2s_dai_of_match[] = {
+ { .compatible = "amlogic,meson-i2s-dai", },
+ { .compatible = "amlogic,meson-gxbb-i2s-dai", },
+ { .compatible = "amlogic,meson-gxl-i2s-dai", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, meson_i2s_dai_of_match);
+
+static struct platform_driver meson_i2s_dai_pdrv = {
+ .probe = meson_i2s_dai_probe,
+ .driver = {
+ .name = DRV_NAME,
+ .of_match_table = meson_i2s_dai_of_match,
+ },
+};
+module_platform_driver(meson_i2s_dai_pdrv);
+
+MODULE_DESCRIPTION("Meson i2s DAI ASoC Driver");
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
+MODULE_LICENSE("GPL v2");
--
2.18.0

View File

@@ -0,0 +1,441 @@
From 9d30eb1c60ba967c4c5dd27a602bd3fb12e8edf0 Mon Sep 17 00:00:00 2001
From: Jerome Brunet <jbrunet@baylibre.com>
Date: Thu, 30 Mar 2017 13:43:52 +0200
Subject: [PATCH 11/21] ASoC: meson: add aiu spdif dma support
Add support for the spdif output dma which is part of the AIU block
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
sound/soc/meson/Kconfig | 7 +
sound/soc/meson/Makefile | 2 +
sound/soc/meson/aiu-spdif-dma.c | 388 ++++++++++++++++++++++++++++++++
3 files changed, 397 insertions(+)
create mode 100644 sound/soc/meson/aiu-spdif-dma.c
diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig
index 478f29a2a3b2..3fb93b9fd107 100644
--- a/sound/soc/meson/Kconfig
+++ b/sound/soc/meson/Kconfig
@@ -14,3 +14,10 @@ config SND_SOC_MESON_I2S
help
Say Y or M if you want to add support for i2s driver for Amlogic
Meson SoCs.
+
+config SND_SOC_MESON_SPDIF
+ tristate "Meson spdif interface"
+ depends on SND_SOC_MESON
+ help
+ Say Y or M if you want to add support for spdif dma driver for Amlogic
+ Meson SoCs.
diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile
index ea06ddee39d1..cef9a9d675da 100644
--- a/sound/soc/meson/Makefile
+++ b/sound/soc/meson/Makefile
@@ -1,7 +1,9 @@
snd-soc-meson-audio-core-objs := audio-core.o
snd-soc-meson-aiu-i2s-dma-objs := aiu-i2s-dma.o
+snd-soc-meson-aiu-spdif-dma-objs := aiu-spdif-dma.o
snd-soc-meson-i2s-dai-objs := i2s-dai.o
obj-$(CONFIG_SND_SOC_MESON) += snd-soc-meson-audio-core.o
obj-$(CONFIG_SND_SOC_MESON_I2S) += snd-soc-meson-aiu-i2s-dma.o
obj-$(CONFIG_SND_SOC_MESON_I2S) += snd-soc-meson-i2s-dai.o
+obj-$(CONFIG_SND_SOC_MESON_SPDIF) += snd-soc-meson-aiu-spdif-dma.o
diff --git a/sound/soc/meson/aiu-spdif-dma.c b/sound/soc/meson/aiu-spdif-dma.c
new file mode 100644
index 000000000000..81c3b856fbf9
--- /dev/null
+++ b/sound/soc/meson/aiu-spdif-dma.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2017 BayLibre, SAS
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "aiu-regs.h"
+#include "audio-core.h"
+
+#define DRV_NAME "meson-aiu-spdif-dma"
+
+struct aiu_spdif_dma {
+ struct meson_audio_core_data *core;
+ struct clk *fast;
+ int irq;
+};
+
+#define AIU_958_DCU_FF_CTRL_EN BIT(0)
+#define AIU_958_DCU_FF_CTRL_AUTO_DISABLE BIT(1)
+#define AIU_958_DCU_FF_CTRL_IRQ_MODE_MASK GENMASK(3, 2)
+#define AIU_958_DCU_FF_CTRL_IRQ_OUT_THD BIT(2)
+#define AIU_958_DCU_FF_CTRL_IRQ_FRAME_READ BIT(3)
+#define AIU_958_DCU_FF_CTRL_SYNC_HEAD_EN BIT(4)
+#define AIU_958_DCU_FF_CTRL_BYTE_SEEK BIT(5)
+#define AIU_958_DCU_FF_CTRL_CONTINUE BIT(6)
+#define AIU_MEM_IEC958_BUF_CNTL_INIT BIT(0)
+#define AIU_MEM_IEC958_CONTROL_INIT BIT(0)
+#define AIU_MEM_IEC958_CONTROL_FILL_EN BIT(1)
+#define AIU_MEM_IEC958_CONTROL_EMPTY_EN BIT(2)
+#define AIU_MEM_IEC958_CONTROL_ENDIAN_MASK GENMASK(5, 3)
+#define AIU_MEM_IEC958_CONTROL_RD_DDR BIT(6)
+#define AIU_MEM_IEC958_CONTROL_MODE_16BIT BIT(7)
+#define AIU_MEM_IEC958_MASKS_CH_MEM_MASK GENMASK(15, 8)
+#define AIU_MEM_IEC958_MASKS_CH_MEM(ch) ((ch) << 8)
+#define AIU_MEM_IEC958_MASKS_CH_RD_MASK GENMASK(7, 0)
+#define AIU_MEM_IEC958_MASKS_CH_RD(ch) ((ch) << 0)
+
+#define AIU_SPDIF_DMA_BURST 8
+#define AIU_SPDIF_BPF_MAX USHRT_MAX
+
+static struct snd_pcm_hardware aiu_spdif_dma_hw = {
+ .info = (SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE),
+
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE),
+
+ .rates = (SNDRV_PCM_RATE_32000 |
+ SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_192000),
+ /*
+ * TODO: The DMA can change the endianness, the msb position
+ * and deal with unsigned - support this later on
+ */
+
+ .channels_min = 2,
+ .channels_max = 2,
+ .period_bytes_min = AIU_SPDIF_DMA_BURST,
+ .period_bytes_max = AIU_SPDIF_BPF_MAX,
+ .periods_min = 2,
+ .periods_max = UINT_MAX,
+ .buffer_bytes_max = 1 * 1024 * 1024,
+ .fifo_size = 0,
+};
+
+static struct aiu_spdif_dma *aiu_spdif_dma_priv(struct snd_pcm_substream *s)
+{
+ struct snd_soc_pcm_runtime *rtd = s->private_data;
+ struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
+
+ return snd_soc_component_get_drvdata(component);
+}
+
+static snd_pcm_uframes_t
+aiu_spdif_dma_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct aiu_spdif_dma *priv = aiu_spdif_dma_priv(substream);
+ unsigned int addr;
+ int ret;
+
+ ret = regmap_read(priv->core->aiu, AIU_MEM_IEC958_RD_PTR,
+ &addr);
+ if (ret)
+ return 0;
+
+ return bytes_to_frames(runtime, addr - (unsigned int)runtime->dma_addr);
+}
+
+static void __dma_enable(struct aiu_spdif_dma *priv, bool enable)
+{
+ unsigned int en_mask = (AIU_MEM_IEC958_CONTROL_FILL_EN |
+ AIU_MEM_IEC958_CONTROL_EMPTY_EN);
+
+ regmap_update_bits(priv->core->aiu, AIU_MEM_IEC958_CONTROL, en_mask,
+ enable ? en_mask : 0);
+}
+
+static void __dcu_fifo_enable(struct aiu_spdif_dma *priv, bool enable)
+{
+ regmap_update_bits(priv->core->aiu, AIU_958_DCU_FF_CTRL,
+ AIU_958_DCU_FF_CTRL_EN,
+ enable ? AIU_958_DCU_FF_CTRL_EN : 0);
+}
+
+static int aiu_spdif_dma_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct aiu_spdif_dma *priv = aiu_spdif_dma_priv(substream);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ __dcu_fifo_enable(priv, true);
+ __dma_enable(priv, true);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_STOP:
+ __dma_enable(priv, false);
+ __dcu_fifo_enable(priv, false);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void __dma_init_mem(struct aiu_spdif_dma *priv)
+{
+ regmap_update_bits(priv->core->aiu, AIU_MEM_IEC958_CONTROL,
+ AIU_MEM_IEC958_CONTROL_INIT,
+ AIU_MEM_IEC958_CONTROL_INIT);
+ regmap_update_bits(priv->core->aiu, AIU_MEM_IEC958_BUF_CNTL,
+ AIU_MEM_IEC958_BUF_CNTL_INIT,
+ AIU_MEM_IEC958_BUF_CNTL_INIT);
+
+ regmap_update_bits(priv->core->aiu, AIU_MEM_IEC958_CONTROL,
+ AIU_MEM_IEC958_CONTROL_INIT,
+ 0);
+ regmap_update_bits(priv->core->aiu, AIU_MEM_IEC958_BUF_CNTL,
+ AIU_MEM_IEC958_BUF_CNTL_INIT,
+ 0);
+}
+
+static int aiu_spdif_dma_prepare(struct snd_pcm_substream *substream)
+{
+ struct aiu_spdif_dma *priv = aiu_spdif_dma_priv(substream);
+
+ __dma_init_mem(priv);
+
+ return 0;
+}
+
+static int __setup_memory_layout(struct aiu_spdif_dma *priv,
+ unsigned int width)
+{
+ u32 mem_ctl = AIU_MEM_IEC958_CONTROL_RD_DDR;
+
+ if (width == 16)
+ mem_ctl |= AIU_MEM_IEC958_CONTROL_MODE_16BIT;
+
+ regmap_update_bits(priv->core->aiu, AIU_MEM_IEC958_CONTROL,
+ AIU_MEM_IEC958_CONTROL_ENDIAN_MASK |
+ AIU_MEM_IEC958_CONTROL_MODE_16BIT |
+ AIU_MEM_IEC958_CONTROL_RD_DDR,
+ mem_ctl);
+
+ return 0;
+}
+
+static int aiu_spdif_dma_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct aiu_spdif_dma *priv = aiu_spdif_dma_priv(substream);
+ int ret;
+ dma_addr_t end_ptr;
+
+ ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+ if (ret < 0)
+ return ret;
+
+ ret = __setup_memory_layout(priv, params_physical_width(params));
+ if (ret)
+ return ret;
+
+ /* Initialize memory pointers */
+ regmap_write(priv->core->aiu,
+ AIU_MEM_IEC958_START_PTR, runtime->dma_addr);
+ regmap_write(priv->core->aiu,
+ AIU_MEM_IEC958_RD_PTR, runtime->dma_addr);
+
+ /* The end pointer is the address of the last valid block */
+ end_ptr = runtime->dma_addr + runtime->dma_bytes - AIU_SPDIF_DMA_BURST;
+ regmap_write(priv->core->aiu, AIU_MEM_IEC958_END_PTR, end_ptr);
+
+ /* Memory masks */
+ regmap_write(priv->core->aiu, AIU_MEM_IEC958_MASKS,
+ AIU_MEM_IEC958_MASKS_CH_RD(0xff) |
+ AIU_MEM_IEC958_MASKS_CH_MEM(0xff));
+
+ /* Setup the number bytes read by the FIFO between each IRQ */
+ regmap_write(priv->core->aiu, AIU_958_BPF, params_period_bytes(params));
+
+ /*
+ * AUTO_DISABLE and SYNC_HEAD are enabled by default but
+ * this should be disabled in PCM (uncompressed) mode
+ */
+ regmap_update_bits(priv->core->aiu, AIU_958_DCU_FF_CTRL,
+ AIU_958_DCU_FF_CTRL_AUTO_DISABLE |
+ AIU_958_DCU_FF_CTRL_IRQ_MODE_MASK |
+ AIU_958_DCU_FF_CTRL_SYNC_HEAD_EN,
+ AIU_958_DCU_FF_CTRL_IRQ_FRAME_READ);
+
+ return 0;
+}
+
+static int aiu_spdif_dma_hw_free(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static irqreturn_t aiu_spdif_dma_irq(int irq, void *dev_id)
+{
+ struct snd_pcm_substream *playback = dev_id;
+
+ snd_pcm_period_elapsed(playback);
+
+ return IRQ_HANDLED;
+}
+
+static int aiu_spdif_dma_open(struct snd_pcm_substream *substream)
+{
+ struct aiu_spdif_dma *priv = aiu_spdif_dma_priv(substream);
+ int ret;
+
+ snd_soc_set_runtime_hwparams(substream, &aiu_spdif_dma_hw);
+
+ /*
+ * Make sure the buffer and period size are multiple of the DMA burst
+ * size
+ */
+ ret = snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+ AIU_SPDIF_DMA_BURST);
+ if (ret)
+ return ret;
+
+ ret = snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+ AIU_SPDIF_DMA_BURST);
+ if (ret)
+ return ret;
+
+ /* Request the SPDIF DDR irq */
+ ret = request_irq(priv->irq, aiu_spdif_dma_irq, 0,
+ DRV_NAME, substream);
+ if (ret)
+ return ret;
+
+ /* Power up the spdif fast domain - can't write the register w/o it */
+ ret = clk_prepare_enable(priv->fast);
+ if (ret)
+ return ret;
+
+ /* Make sure the dma is initially halted */
+ __dma_enable(priv, false);
+ __dcu_fifo_enable(priv, false);
+
+ return 0;
+}
+
+static int aiu_spdif_dma_close(struct snd_pcm_substream *substream)
+{
+ struct aiu_spdif_dma *priv = aiu_spdif_dma_priv(substream);
+
+ clk_disable_unprepare(priv->fast);
+ free_irq(priv->irq, substream);
+
+ return 0;
+}
+
+static const struct snd_pcm_ops aiu_spdif_dma_ops = {
+ .open = aiu_spdif_dma_open,
+ .close = aiu_spdif_dma_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = aiu_spdif_dma_hw_params,
+ .hw_free = aiu_spdif_dma_hw_free,
+ .prepare = aiu_spdif_dma_prepare,
+ .pointer = aiu_spdif_dma_pointer,
+ .trigger = aiu_spdif_dma_trigger,
+};
+
+static int aiu_spdif_dma_new(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_card *card = rtd->card->snd_card;
+ size_t size = aiu_spdif_dma_hw.buffer_bytes_max;
+
+ return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
+ SNDRV_DMA_TYPE_DEV,
+ card->dev, size, size);
+}
+
+static const struct snd_soc_component_driver aiu_spdif_platform = {
+ .ops = &aiu_spdif_dma_ops,
+ .pcm_new = aiu_spdif_dma_new,
+ .name = DRV_NAME,
+};
+
+static int aiu_spdif_dma_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct aiu_spdif_dma *priv;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, priv);
+ priv->core = dev_get_drvdata(dev->parent);
+
+ priv->fast = devm_clk_get(dev, "fast");
+ if (IS_ERR(priv->fast)) {
+ if (PTR_ERR(priv->fast) != -EPROBE_DEFER)
+ dev_err(dev, "Can't get spdif fast domain clock\n");
+ return PTR_ERR(priv->fast);
+ }
+
+ priv->irq = platform_get_irq(pdev, 0);
+ if (priv->irq <= 0) {
+ dev_err(dev, "Can't get spdif ddr irq\n");
+ return priv->irq;
+ }
+
+ return devm_snd_soc_register_component(dev, &aiu_spdif_platform,
+ NULL, 0);
+}
+
+static const struct of_device_id aiu_spdif_dma_of_match[] = {
+ { .compatible = "amlogic,meson-aiu-spdif-dma", },
+ { .compatible = "amlogic,meson-gxbb-aiu-spdif-dma", },
+ { .compatible = "amlogic,meson-gxl-aiu-spdif-dma", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, aiu_spdif_dma_of_match);
+
+static struct platform_driver aiu_spdif_dma_pdrv = {
+ .probe = aiu_spdif_dma_probe,
+ .driver = {
+ .name = DRV_NAME,
+ .of_match_table = aiu_spdif_dma_of_match,
+ },
+};
+module_platform_driver(aiu_spdif_dma_pdrv);
+
+MODULE_DESCRIPTION("Meson AIU spdif DMA ASoC Driver");
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
+MODULE_LICENSE("GPL");
--
2.18.0

View File

@@ -0,0 +1,429 @@
From 1545fc36c9b5cd9ea28dadfc1140e8290923e27b Mon Sep 17 00:00:00 2001
From: Jerome Brunet <jbrunet@baylibre.com>
Date: Thu, 30 Mar 2017 13:46:03 +0200
Subject: [PATCH 12/21] ASoC: meson: add initial spdif dai support
Add support for the spdif dai found on Amlogic Meson SoC family.
With this initial implementation, only uncompressed pcm playback
from the spdif dma is supported. Future work will add compressed
support, pcm playback from i2s dma and capture.
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
sound/soc/meson/Kconfig | 3 +-
sound/soc/meson/Makefile | 2 +
sound/soc/meson/spdif-dai.c | 374 ++++++++++++++++++++++++++++++++++++
3 files changed, 378 insertions(+), 1 deletion(-)
create mode 100644 sound/soc/meson/spdif-dai.c
diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig
index 3fb93b9fd107..301d3a3c07ad 100644
--- a/sound/soc/meson/Kconfig
+++ b/sound/soc/meson/Kconfig
@@ -18,6 +18,7 @@ config SND_SOC_MESON_I2S
config SND_SOC_MESON_SPDIF
tristate "Meson spdif interface"
depends on SND_SOC_MESON
+ select SND_PCM_IEC958
help
- Say Y or M if you want to add support for spdif dma driver for Amlogic
+ Say Y or M if you want to add support for spdif driver for Amlogic
Meson SoCs.
diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile
index cef9a9d675da..bc4391c50e34 100644
--- a/sound/soc/meson/Makefile
+++ b/sound/soc/meson/Makefile
@@ -2,8 +2,10 @@ snd-soc-meson-audio-core-objs := audio-core.o
snd-soc-meson-aiu-i2s-dma-objs := aiu-i2s-dma.o
snd-soc-meson-aiu-spdif-dma-objs := aiu-spdif-dma.o
snd-soc-meson-i2s-dai-objs := i2s-dai.o
+snd-soc-meson-spdif-dai-objs := spdif-dai.o
obj-$(CONFIG_SND_SOC_MESON) += snd-soc-meson-audio-core.o
obj-$(CONFIG_SND_SOC_MESON_I2S) += snd-soc-meson-aiu-i2s-dma.o
obj-$(CONFIG_SND_SOC_MESON_I2S) += snd-soc-meson-i2s-dai.o
obj-$(CONFIG_SND_SOC_MESON_SPDIF) += snd-soc-meson-aiu-spdif-dma.o
+obj-$(CONFIG_SND_SOC_MESON_SPDIF) += snd-soc-meson-spdif-dai.o
diff --git a/sound/soc/meson/spdif-dai.c b/sound/soc/meson/spdif-dai.c
new file mode 100644
index 000000000000..e7630007c84b
--- /dev/null
+++ b/sound/soc/meson/spdif-dai.c
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2017 BayLibre, SAS
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <sound/pcm_iec958.h>
+
+#include "aiu-regs.h"
+#include "audio-core.h"
+
+#define DRV_NAME "meson-spdif-dai"
+
+struct meson_spdif_dai {
+ struct meson_audio_core_data *core;
+ struct clk *iface;
+ struct clk *fast;
+ struct clk *mclk_i958;
+ struct clk *mclk;
+};
+
+#define AIU_CLK_CTRL_958_DIV_EN BIT(1)
+#define AIU_CLK_CTRL_958_DIV_MASK GENMASK(5, 4)
+#define AIU_CLK_CTRL_958_DIV_MORE BIT(12)
+#define AIU_MEM_IEC958_CONTROL_MODE_LINEAR BIT(8)
+#define AIU_958_CTRL_HOLD_EN BIT(0)
+#define AIU_958_MISC_NON_PCM BIT(0)
+#define AIU_958_MISC_MODE_16BITS BIT(1)
+#define AIU_958_MISC_16BITS_ALIGN_MASK GENMASK(6, 5)
+#define AIU_958_MISC_16BITS_ALIGN(val) ((val) << 5)
+#define AIU_958_MISC_MODE_32BITS BIT(7)
+#define AIU_958_MISC_32BITS_SHIFT_MASK GENMASK(10, 8)
+#define AIU_958_MISC_32BITS_SHIFT(val) ((val) << 8)
+#define AIU_958_MISC_U_FROM_STREAM BIT(12)
+#define AIU_958_MISC_FORCE_LR BIT(13)
+
+#define AIU_CS_WORD_LEN 4
+
+static void __hold(struct meson_spdif_dai *priv, bool enable)
+{
+ regmap_update_bits(priv->core->aiu, AIU_958_CTRL,
+ AIU_958_CTRL_HOLD_EN,
+ enable ? AIU_958_CTRL_HOLD_EN : 0);
+}
+
+static void __divider_enable(struct meson_spdif_dai *priv, bool enable)
+{
+ regmap_update_bits(priv->core->aiu, AIU_CLK_CTRL,
+ AIU_CLK_CTRL_958_DIV_EN,
+ enable ? AIU_CLK_CTRL_958_DIV_EN : 0);
+}
+
+static void __playback_start(struct meson_spdif_dai *priv)
+{
+ __divider_enable(priv, true);
+ __hold(priv, false);
+}
+
+static void __playback_stop(struct meson_spdif_dai *priv)
+{
+ __hold(priv, true);
+ __divider_enable(priv, false);
+}
+
+static int meson_spdif_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct meson_spdif_dai *priv = snd_soc_dai_get_drvdata(dai);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ __playback_start(priv);
+ return 0;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ __playback_stop(priv);
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int __setup_spdif_clk(struct meson_spdif_dai *priv, unsigned int rate)
+{
+ unsigned int mrate;
+
+ /* Leave the internal divisor alone */
+ regmap_update_bits(priv->core->aiu, AIU_CLK_CTRL,
+ AIU_CLK_CTRL_958_DIV_MASK |
+ AIU_CLK_CTRL_958_DIV_MORE,
+ 0);
+
+ /* 2 * 32bits per subframe * 2 channels = 128 */
+ mrate = rate * 128;
+ return clk_set_rate(priv->mclk, mrate);
+}
+
+static int __setup_cs_word(struct meson_spdif_dai *priv,
+ struct snd_pcm_hw_params *params)
+{
+ u8 cs[AIU_CS_WORD_LEN];
+ u32 val;
+ int ret;
+
+ ret = snd_pcm_create_iec958_consumer_hw_params(params, cs,
+ AIU_CS_WORD_LEN);
+ if (ret < 0)
+ return -EINVAL;
+
+ /* Write the 1st half word */
+ val = cs[1] | cs[0] << 8;
+ regmap_write(priv->core->aiu, AIU_958_CHSTAT_L0, val);
+ regmap_write(priv->core->aiu, AIU_958_CHSTAT_R0, val);
+
+ /* Write the 2nd half word */
+ val = cs[3] | cs[2] << 8;
+ regmap_write(priv->core->aiu, AIU_958_CHSTAT_L1, val);
+ regmap_write(priv->core->aiu, AIU_958_CHSTAT_R1, val);
+
+ return 0;
+}
+
+static int __setup_pcm_fmt(struct meson_spdif_dai *priv,
+ unsigned int width)
+{
+ u32 val = 0;
+
+ switch (width) {
+ case 16:
+ val |= AIU_958_MISC_MODE_16BITS;
+ val |= AIU_958_MISC_16BITS_ALIGN(2);
+ break;
+ case 32:
+ case 24:
+ /*
+ * Looks like this should only be set for 32bits mode, but the
+ * vendor kernel sets it like this for 24bits as well, let's
+ * try and see
+ */
+ val |= AIU_958_MISC_MODE_32BITS;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* No idea what this actually does, copying the vendor kernel for now */
+ val |= AIU_958_MISC_FORCE_LR;
+ val |= AIU_958_MISC_U_FROM_STREAM;
+
+ regmap_update_bits(priv->core->aiu, AIU_958_MISC,
+ AIU_958_MISC_NON_PCM |
+ AIU_958_MISC_MODE_16BITS |
+ AIU_958_MISC_16BITS_ALIGN_MASK |
+ AIU_958_MISC_MODE_32BITS |
+ AIU_958_MISC_FORCE_LR,
+ val);
+
+ return 0;
+}
+
+static int meson_spdif_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct meson_spdif_dai *priv = snd_soc_dai_get_drvdata(dai);
+ int ret;
+
+ ret = __setup_spdif_clk(priv, params_rate(params));
+ if (ret) {
+ dev_err(dai->dev, "Unable to set the spdif clock\n");
+ return ret;
+ }
+
+ ret = __setup_cs_word(priv, params);
+ if (ret) {
+ dev_err(dai->dev, "Unable to set the channel status word\n");
+ return ret;
+ }
+
+ ret = __setup_pcm_fmt(priv, params_width(params));
+ if (ret) {
+ dev_err(dai->dev, "Unable to set the pcm format\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int meson_spdif_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct meson_spdif_dai *priv = snd_soc_dai_get_drvdata(dai);
+ int ret;
+
+ /* Power up the spdif fast domain - can't write the registers w/o it */
+ ret = clk_prepare_enable(priv->fast);
+ if (ret)
+ goto out_clk_fast;
+
+ /* Make sure nothing gets out of the DAI yet*/
+ __hold(priv, true);
+
+ ret = clk_set_parent(priv->mclk, priv->mclk_i958);
+ if (ret)
+ return ret;
+
+ /* Enable the clock gate */
+ ret = clk_prepare_enable(priv->iface);
+ if (ret)
+ goto out_clk_iface;
+
+ /* Enable the spdif clock */
+ ret = clk_prepare_enable(priv->mclk);
+ if (ret)
+ goto out_mclk;
+
+ /*
+ * Make sure the interface expect a memory layout we can work with
+ * MEM prefixed register usually belong to the DMA, but when the spdif
+ * DAI takes data from the i2s buffer, we need to make sure it works in
+ * split mode and not the "normal mode" (channel samples packed in
+ * 32 bytes groups)
+ */
+ regmap_update_bits(priv->core->aiu, AIU_MEM_IEC958_CONTROL,
+ AIU_MEM_IEC958_CONTROL_MODE_LINEAR,
+ AIU_MEM_IEC958_CONTROL_MODE_LINEAR);
+
+ return 0;
+
+out_mclk:
+ clk_disable_unprepare(priv->iface);
+out_clk_iface:
+ clk_disable_unprepare(priv->fast);
+out_clk_fast:
+ return ret;
+}
+
+static void meson_spdif_dai_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct meson_spdif_dai *priv = snd_soc_dai_get_drvdata(dai);
+
+ clk_disable_unprepare(priv->iface);
+ clk_disable_unprepare(priv->mclk);
+ clk_disable_unprepare(priv->fast);
+}
+
+static const struct snd_soc_dai_ops meson_spdif_dai_ops = {
+ .startup = meson_spdif_dai_startup,
+ .shutdown = meson_spdif_dai_shutdown,
+ .trigger = meson_spdif_dai_trigger,
+ .hw_params = meson_spdif_dai_hw_params,
+};
+
+static struct snd_soc_dai_driver meson_spdif_dai = {
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = (SNDRV_PCM_RATE_32000 |
+ SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_192000),
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE)
+ },
+ .ops = &meson_spdif_dai_ops,
+};
+
+static const struct snd_soc_component_driver meson_spdif_dai_component = {
+ .name = DRV_NAME,
+};
+
+static int meson_spdif_dai_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct meson_spdif_dai *priv;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, priv);
+ priv->core = dev_get_drvdata(dev->parent);
+
+ priv->fast = devm_clk_get(dev, "fast");
+ if (IS_ERR(priv->fast)) {
+ if (PTR_ERR(priv->fast) != -EPROBE_DEFER)
+ dev_err(dev, "Can't get spdif fast domain clockt\n");
+ return PTR_ERR(priv->fast);
+ }
+
+ priv->iface = devm_clk_get(dev, "iface");
+ if (IS_ERR(priv->iface)) {
+ if (PTR_ERR(priv->iface) != -EPROBE_DEFER)
+ dev_err(dev,
+ "Can't get the dai clock gate\n");
+ return PTR_ERR(priv->iface);
+ }
+
+ priv->mclk_i958 = devm_clk_get(dev, "mclk_i958");
+ if (IS_ERR(priv->mclk_i958)) {
+ if (PTR_ERR(priv->mclk_i958) != -EPROBE_DEFER)
+ dev_err(dev, "Can't get the spdif master clock\n");
+ return PTR_ERR(priv->mclk_i958);
+ }
+
+ /*
+ * TODO: the spdif dai can also get its data from the i2s fifo.
+ * For this use-case, the DAI driver will need to get the i2s master
+ * clock in order to reparent the spdif clock from cts_mclk_i958 to
+ * cts_amclk
+ */
+
+ priv->mclk = devm_clk_get(dev, "mclk");
+ if (IS_ERR(priv->mclk)) {
+ if (PTR_ERR(priv->mclk) != -EPROBE_DEFER)
+ dev_err(dev, "Can't get the spdif input mux clock\n");
+ return PTR_ERR(priv->mclk);
+ }
+
+ return devm_snd_soc_register_component(dev, &meson_spdif_dai_component,
+ &meson_spdif_dai, 1);
+}
+
+static const struct of_device_id meson_spdif_dai_of_match[] = {
+ { .compatible = "amlogic,meson-spdif-dai", },
+ { .compatible = "amlogic,meson-gxbb-spdif-dai", },
+ { .compatible = "amlogic,meson-gxl-spdif-dai", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, meson_spdif_dai_of_match);
+
+static struct platform_driver meson_spdif_dai_pdrv = {
+ .probe = meson_spdif_dai_probe,
+ .driver = {
+ .name = DRV_NAME,
+ .of_match_table = meson_spdif_dai_of_match,
+ },
+};
+module_platform_driver(meson_spdif_dai_pdrv);
+
+MODULE_DESCRIPTION("Meson spdif DAI ASoC Driver");
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
+MODULE_LICENSE("GPL v2");
--
2.18.0

View File

@@ -0,0 +1,32 @@
From ba4e96a6686b91a4711ee31308d18b47ee93e793 Mon Sep 17 00:00:00 2001
From: Jerome Brunet <jbrunet@baylibre.com>
Date: Fri, 31 Mar 2017 15:55:03 +0200
Subject: [PATCH 13/21] ARM64: defconfig: enable audio support for meson SoCs
as module
Add audio support for meson SoCs. This includes the audio core
driver and the i2s and spdif output interfaces
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
arch/arm64/configs/defconfig | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 25846051b6b5..ae1f77492a7d 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -451,6 +451,10 @@ CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
CONFIG_SND_BCM2835_SOC_I2S=m
+CONFIG_SND_SOC_MESON=m
+CONFIG_SND_SOC_MESON_I2S=m
+CONFIG_SND_SOC_MESON_SPDIF=m
+CONFIG_SND_SOC_RCAR=y
CONFIG_SND_SOC_SAMSUNG=y
CONFIG_SND_SOC_RCAR=m
CONFIG_SND_SOC_AK4613=m
--
2.18.0

View File

@@ -0,0 +1,189 @@
From 96a0e1456b91652fc7adf03f70222c0d68278eff Mon Sep 17 00:00:00 2001
From: Jerome Brunet <jbrunet@baylibre.com>
Date: Thu, 30 Mar 2017 15:19:04 +0200
Subject: [PATCH 14/21] ARM64: dts: meson-gx: add audio controller nodes
Add audio controller nodes for Amlogic meson gxbb and gxl.
This includes the audio-core node, the i2s and spdif DAIs, i2s and spdif
aiu DMAs.
Audio on this SoC family is still a work in progress. More nodes are likely
to be added later on (pcm DAIs, input DMAs, etc ...)
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
arch/arm64/boot/dts/amlogic/meson-gx.dtsi | 35 ++++++++++++++++++
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 39 +++++++++++++++++++++
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 38 ++++++++++++++++++++
3 files changed, 112 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
index b8dc4dbb391b..6b64b63f2a68 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
@@ -203,6 +203,41 @@
#reset-cells = <1>;
};
+ audio: audio@5400 {
+ compatible = "amlogic,meson-audio-core";
+ reg = <0x0 0x5400 0x0 0x2ac>,
+ <0x0 0xa000 0x0 0x304>;
+ reg-names = "aiu", "audin";
+ status = "disabled";
+
+ aiu_i2s_dma: aiu_i2s_dma {
+ #sound-dai-cells = <0>;
+ compatible = "amlogic,meson-aiu-i2s-dma";
+ interrupts = <GIC_SPI 48 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
+ aiu_spdif_dma: aiu_spdif_dma {
+ #sound-dai-cells = <0>;
+ compatible = "amlogic,meson-aiu-spdif-dma";
+ interrupts = <GIC_SPI 50 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
+ i2s_dai: i2s_dai {
+ #sound-dai-cells = <0>;
+ compatible = "amlogic,meson-i2s-dai";
+ status = "disabled";
+ };
+
+ spdif_dai: spdif_dai {
+ #sound-dai-cells = <0>;
+ compatible = "amlogic,meson-spdif-dai";
+ status = "disabled";
+ };
+
+ };
+
uart_A: serial@84c0 {
compatible = "amlogic,meson-gx-uart";
reg = <0x0 0x84c0 0x0 0x18>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 98cbba6809ca..79132496691f 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -659,6 +659,35 @@
};
};
+&audio {
+ clocks = <&clkc CLKID_AIU>,
+ <&clkc CLKID_AIU_GLUE>,
+ <&clkc CLKID_I2S_SPDIF>;
+ clock-names = "aiu_top", "aiu_glue", "audin";
+ resets = <&reset RESET_AIU>,
+ <&reset RESET_AUDIN>;
+ reset-names = "aiu", "audin";
+};
+
+&aiu_i2s_dma {
+ clocks = <&clkc CLKID_I2S_OUT>;
+ clock-names = "fast";
+};
+
+&aiu_spdif_dma {
+ clocks = <&clkc CLKID_IEC958>;
+ clock-names = "fast";
+
+};
+
+&i2s_dai {
+ clocks = <&clkc CLKID_I2S_OUT>,
+ <&clkc CLKID_MIXER_IFACE>,
+ <&clkc CLKID_AOCLK_GATE>,
+ <&clkc CLKID_CTS_AMCLK>;
+ clock-names = "fast", "iface", "bclks", "mclk";
+};
+
&pwrc_vpu {
resets = <&reset RESET_VIU>,
<&reset RESET_VENC>,
@@ -741,6 +770,15 @@
num-cs = <1>;
};
+&spdif_dai {
+ clocks = <&clkc CLKID_IEC958>,
+ <&clkc CLKID_IEC958_GATE>,
+ <&clkc CLKID_CTS_MCLK_I958>,
+ <&clkc CLKID_CTS_AMCLK>,
+ <&clkc CLKID_CTS_I958>;
+ clock-names = "fast", "iface", "mclk_i958", "mclk_i2s", "mclk";
+};
+
&spifc {
clocks = <&clkc CLKID_SPI>;
};
@@ -774,3 +812,4 @@
compatible = "amlogic,meson-gxbb-vpu", "amlogic,meson-gx-vpu";
power-domains = <&pwrc_vpu>;
};
+
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
index c87a80e9bcc6..20922cdc2c23 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
@@ -660,6 +660,34 @@
};
};
+&audio {
+ clocks = <&clkc CLKID_AIU>,
+ <&clkc CLKID_AIU_GLUE>,
+ <&clkc CLKID_I2S_SPDIF>;
+ clock-names = "aiu_top", "aiu_glue", "audin";
+ resets = <&reset RESET_AIU>,
+ <&reset RESET_AUDIN>;
+ reset-names = "aiu", "audin";
+};
+
+&aiu_i2s_dma {
+ clocks = <&clkc CLKID_I2S_OUT>;
+ clock-names = "fast";
+};
+
+&aiu_spdif_dma {
+ clocks = <&clkc CLKID_IEC958>;
+ clock-names = "fast";
+};
+
+&i2s_dai {
+ clocks = <&clkc CLKID_I2S_OUT>,
+ <&clkc CLKID_MIXER_IFACE>,
+ <&clkc CLKID_AOCLK_GATE>,
+ <&clkc CLKID_CTS_AMCLK>;
+ clock-names = "fast", "iface", "bclks", "mclk";
+};
+
&pwrc_vpu {
resets = <&reset RESET_VIU>,
<&reset RESET_VENC>,
@@ -742,6 +770,15 @@
num-cs = <1>;
};
+&spdif_dai {
+ clocks = <&clkc CLKID_IEC958>,
+ <&clkc CLKID_IEC958_GATE>,
+ <&clkc CLKID_CTS_MCLK_I958>,
+ <&clkc CLKID_CTS_AMCLK>,
+ <&clkc CLKID_CTS_I958>;
+ clock-names = "fast", "iface", "mclk_i958", "mclk_i2s", "mclk";
+};
+
&spifc {
clocks = <&clkc CLKID_SPI>;
};
@@ -775,3 +812,4 @@
compatible = "amlogic,meson-gxl-vpu", "amlogic,meson-gx-vpu";
power-domains = <&pwrc_vpu>;
};
+
--
2.18.0

View File

@@ -0,0 +1,55 @@
From 97b0b5c8926cc6d9705aa799331e84ec07d52e41 Mon Sep 17 00:00:00 2001
From: Jerome Brunet <jbrunet@baylibre.com>
Date: Fri, 7 Jul 2017 17:39:21 +0200
Subject: [PATCH 15/21] snd: meson: activate HDMI audio path
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
sound/soc/meson/i2s-dai.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/sound/soc/meson/i2s-dai.c b/sound/soc/meson/i2s-dai.c
index 1008af8d3972..63fe098ecf82 100644
--- a/sound/soc/meson/i2s-dai.c
+++ b/sound/soc/meson/i2s-dai.c
@@ -56,8 +56,19 @@ struct meson_i2s_dai {
#define AIU_CLK_CTRL_ALRCLK_RIGHT_J (2 << 8)
#define AIU_CLK_CTRL_MORE_I2S_DIV_MASK GENMASK(5, 0)
#define AIU_CLK_CTRL_MORE_I2S_DIV(div) (((div) - 1) << 0)
+#define AIU_CLK_CTRL_MORE_HDMI_TX_SEL_MASK BIT(6)
+#define AIU_CLK_CTRL_MORE_HDMI_TX_I958_CLK (0 << 6)
+#define AIU_CLK_CTRL_MORE_HDMI_TX_INT_CLK (1 << 6)
#define AIU_CODEC_DAC_LRCLK_CTRL_DIV_MASK GENMASK(11, 0)
#define AIU_CODEC_DAC_LRCLK_CTRL_DIV(div) (((div) - 1) << 0)
+#define AIU_HDMI_CLK_DATA_CTRL_CLK_SEL_MASK GENMASK(1, 0)
+#define AIU_HDMI_CLK_DATA_CTRL_CLK_DISABLE (0 << 0)
+#define AIU_HDMI_CLK_DATA_CTRL_CLK_PCM (1 << 0)
+#define AIU_HDMI_CLK_DATA_CTRL_CLK_I2S (2 << 0)
+#define AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_MASK GENMASK(5, 4)
+#define AIU_HDMI_CLK_DATA_CTRL_DATA_MUTE (0 << 4)
+#define AIU_HDMI_CLK_DATA_CTRL_DATA_PCM (1 << 4)
+#define AIU_HDMI_CLK_DATA_CTRL_DATA_I2S (2 << 4)
#define AIU_I2S_DAC_CFG_PAYLOAD_SIZE_MASK GENMASK(1, 0)
#define AIU_I2S_DAC_CFG_AOCLK_32 (0 << 0)
#define AIU_I2S_DAC_CFG_AOCLK_48 (2 << 0)
@@ -221,6 +232,17 @@ static int meson_i2s_dai_hw_params(struct snd_pcm_substream *substream,
return ret;
}
+ /* Quick and dirty hack for HDMI */
+ regmap_update_bits(priv->core->aiu, AIU_HDMI_CLK_DATA_CTRL,
+ AIU_HDMI_CLK_DATA_CTRL_CLK_SEL_MASK |
+ AIU_HDMI_CLK_DATA_CTRL_DATA_SEL_MASK,
+ AIU_HDMI_CLK_DATA_CTRL_CLK_I2S |
+ AIU_HDMI_CLK_DATA_CTRL_DATA_I2S);
+
+ regmap_update_bits(priv->core->aiu, AIU_CLK_CTRL_MORE,
+ AIU_CLK_CTRL_MORE_HDMI_TX_SEL_MASK,
+ AIU_CLK_CTRL_MORE_HDMI_TX_INT_CLK);
+
return 0;
}
--
2.18.0

View File

@@ -0,0 +1,22 @@
From 6c58bdeef341501efbef53d55ad42c51d209b15f Mon Sep 17 00:00:00 2001
From: Jerome Brunet <jbrunet@baylibre.com>
Date: Tue, 14 Feb 2017 19:18:04 +0100
Subject: [PATCH 16/21] drm/meson: select dw-hdmi i2s audio for meson hdmi
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
drivers/gpu/drm/meson/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/meson/Kconfig b/drivers/gpu/drm/meson/Kconfig
index 3ce51d8dfe1c..02d400b8795c 100644
--- a/drivers/gpu/drm/meson/Kconfig
+++ b/drivers/gpu/drm/meson/Kconfig
@@ -13,3 +13,4 @@ config DRM_MESON_DW_HDMI
depends on DRM_MESON
default y if DRM_MESON
select DRM_DW_HDMI
+ select DRM_DW_HDMI_I2S_AUDIO
--
2.18.0

View File

@@ -0,0 +1,38 @@
From 09c16799996246ff509b857608f0e202dde8dc50 Mon Sep 17 00:00:00 2001
From: Jerome Brunet <jbrunet@baylibre.com>
Date: Wed, 20 Sep 2017 18:01:26 +0200
Subject: [PATCH 17/21] ARM64: dts: meson-gx: add sound-dai-cells to HDMI node
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 1 +
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 1 +
2 files changed, 2 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 79132496691f..2a4d506bad4e 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -305,6 +305,7 @@
<&clkc CLKID_CLK81>,
<&clkc CLKID_GCLK_VENCI_INT0>;
clock-names = "isfr", "iahb", "venci";
+ #sound-dai-cells = <0>;
};
&sysctrl {
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
index 20922cdc2c23..9f4b6185a61d 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
@@ -257,6 +257,7 @@
<&clkc CLKID_CLK81>,
<&clkc CLKID_GCLK_VENCI_INT0>;
clock-names = "isfr", "iahb", "venci";
+ #sound-dai-cells = <0>;
};
&sysctrl {
--
2.18.0

View File

@@ -0,0 +1,864 @@
From bc719ab54052fc27f8089820dee4dd85373ff6b4 Mon Sep 17 00:00:00 2001
From: Jerome Brunet <jbrunet@baylibre.com>
Date: Wed, 20 Sep 2017 18:10:08 +0200
Subject: [PATCH 18/21] ARM64: dts: meson: activate hdmi audio HDMI enabled
boards
This patch activate audio over HDMI on selected boards
Please note that this audio support is based on WIP changes
This should be considered as preview and it does not reflect
the audio I expect to see merged
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
.../boot/dts/amlogic/meson-gx-p23x-q20x.dtsi | 45 +++++++++++++++++++
.../boot/dts/amlogic/meson-gxbb-nanopi-k2.dts | 45 +++++++++++++++++++
.../dts/amlogic/meson-gxbb-nexbox-a95x.dts | 45 +++++++++++++++++++
.../boot/dts/amlogic/meson-gxbb-odroidc2.dts | 45 +++++++++++++++++++
.../boot/dts/amlogic/meson-gxbb-p20x.dtsi | 45 +++++++++++++++++++
.../boot/dts/amlogic/meson-gxbb-wetek.dtsi | 45 +++++++++++++++++++
.../amlogic/meson-gxl-s905x-khadas-vim.dts | 45 +++++++++++++++++++
.../amlogic/meson-gxl-s905x-libretech-cc.dts | 45 +++++++++++++++++++
.../amlogic/meson-gxl-s905x-nexbox-a95x.dts | 45 +++++++++++++++++++
.../boot/dts/amlogic/meson-gxl-s905x-p212.dts | 45 +++++++++++++++++++
.../dts/amlogic/meson-gxm-khadas-vim2.dts | 45 +++++++++++++++++++
.../boot/dts/amlogic/meson-gxm-nexbox-a1.dts | 45 +++++++++++++++++++
12 files changed, 540 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
index 88e712ea757a..319512e36e57 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
@@ -95,6 +95,39 @@
};
};
};
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "meson-gx-audio";
+
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ simple-audio-card,dai-link@0 {
+ /* HDMI Output */
+ format = "i2s";
+ mclk-fs = <256>;
+ bitclock-master = <&i2s_dai>;
+ frame-master = <&i2s_dai>;
+
+ plat {
+ sound-dai = <&aiu_i2s_dma>;
+ };
+
+ cpu {
+ sound-dai = <&i2s_dai>;
+ };
+
+ codec {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
};
&cec_AO {
@@ -104,6 +137,14 @@
hdmi-phandle = <&hdmi_tx>;
};
+&audio {
+ status = "okay";
+};
+
+&aiu_i2s_dma {
+ status = "okay";
+};
+
&cvbs_vdac_port {
cvbs_vdac_out: endpoint {
remote-endpoint = <&cvbs_connector_in>;
@@ -126,6 +167,10 @@
};
};
+&i2s_dai {
+ status = "okay";
+};
+
&ir {
status = "okay";
pinctrl-0 = <&remote_input_ao_pins>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
index cbe99bd4e06d..5b10de9a0bad 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
@@ -88,6 +88,39 @@
clock-names = "ext_clock";
};
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "meson-gx-audio";
+
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ simple-audio-card,dai-link@0 {
+ /* HDMI Output */
+ format = "i2s";
+ mclk-fs = <256>;
+ bitclock-master = <&i2s_dai>;
+ frame-master = <&i2s_dai>;
+
+ plat {
+ sound-dai = <&aiu_i2s_dma>;
+ };
+
+ cpu {
+ sound-dai = <&i2s_dai>;
+ };
+
+ codec {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
+
vcc1v8: regulator-vcc1v8 {
compatible = "regulator-fixed";
regulator-name = "VCC1.8V";
@@ -131,6 +164,14 @@
};
};
+&audio {
+ status = "okay";
+};
+
+&aiu_i2s_dma {
+ status = "okay";
+};
+
&cec_AO {
status = "okay";
pinctrl-0 = <&ao_cec_pins>;
@@ -185,6 +226,10 @@
};
};
+&i2s_dai {
+ status = "okay";
+};
+
&ir {
status = "okay";
pinctrl-0 = <&remote_input_ao_pins>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
index 4cf7f6e80c6a..ff87bdc7ddbf 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
@@ -119,6 +119,39 @@
clock-names = "ext_clock";
};
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "meson-gx-audio";
+
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ simple-audio-card,dai-link@0 {
+ /* HDMI Output */
+ format = "i2s";
+ mclk-fs = <256>;
+ bitclock-master = <&i2s_dai>;
+ frame-master = <&i2s_dai>;
+
+ plat {
+ sound-dai = <&aiu_i2s_dma>;
+ };
+
+ cpu {
+ sound-dai = <&i2s_dai>;
+ };
+
+ codec {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
+
cvbs-connector {
compatible = "composite-video-connector";
@@ -154,6 +187,14 @@
hdmi-phandle = <&hdmi_tx>;
};
+&audio {
+ status = "okay";
+};
+
+&aiu_i2s_dma {
+ status = "okay";
+};
+
&ethmac {
status = "okay";
pinctrl-0 = <&eth_rmii_pins>;
@@ -190,6 +231,10 @@
};
};
+&i2s_dai {
+ status = "okay";
+};
+
&ir {
status = "okay";
pinctrl-0 = <&remote_input_ao_pins>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index 54954b314a45..3da33090b8fe 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -110,6 +110,39 @@
};
};
};
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "meson-gx-audio";
+
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ simple-audio-card,dai-link@0 {
+ /* HDMI Output */
+ format = "i2s";
+ mclk-fs = <256>;
+ bitclock-master = <&i2s_dai>;
+ frame-master = <&i2s_dai>;
+
+ plat {
+ sound-dai = <&aiu_i2s_dma>;
+ };
+
+ cpu {
+ sound-dai = <&i2s_dai>;
+ };
+
+ codec {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
};
&cec_AO {
@@ -119,6 +152,14 @@
hdmi-phandle = <&hdmi_tx>;
};
+&audio {
+ status = "okay";
+};
+
+&aiu_i2s_dma {
+ status = "okay";
+};
+
&ethmac {
status = "okay";
pinctrl-0 = <&eth_rgmii_pins>;
@@ -181,6 +222,10 @@
pinctrl-names = "default";
};
+&i2s_dai {
+ status = "okay";
+};
+
&ir {
status = "okay";
pinctrl-0 = <&remote_input_ao_pins>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
index ce862266b9aa..84eb93b4229f 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
@@ -113,6 +113,39 @@
};
};
};
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "meson-gx-audio";
+
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ simple-audio-card,dai-link@0 {
+ /* HDMI Output */
+ format = "i2s";
+ mclk-fs = <256>;
+ bitclock-master = <&i2s_dai>;
+ frame-master = <&i2s_dai>;
+
+ plat {
+ sound-dai = <&aiu_i2s_dma>;
+ };
+
+ cpu {
+ sound-dai = <&i2s_dai>;
+ };
+
+ codec {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
};
&cec_AO {
@@ -122,6 +155,14 @@
hdmi-phandle = <&hdmi_tx>;
};
+&audio {
+ status = "okay";
+};
+
+&aiu_i2s_dma {
+ status = "okay";
+};
+
&cvbs_vdac_port {
cvbs_vdac_out: endpoint {
remote-endpoint = <&cvbs_connector_in>;
@@ -140,6 +181,10 @@
};
};
+&i2s_dai {
+ status = "okay";
+};
+
&ir {
status = "okay";
pinctrl-0 = <&remote_input_ao_pins>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi
index 70325b273bd2..7d1f1726f29d 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi
@@ -105,6 +105,47 @@
};
};
};
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "meson-gx-audio";
+
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ simple-audio-card,dai-link@0 {
+ /* HDMI Output */
+ format = "i2s";
+ mclk-fs = <256>;
+ bitclock-master = <&i2s_dai>;
+ frame-master = <&i2s_dai>;
+
+ plat {
+ sound-dai = <&aiu_i2s_dma>;
+ };
+
+ cpu {
+ sound-dai = <&i2s_dai>;
+ };
+
+ codec {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
+};
+
+&audio {
+ status = "okay";
+};
+
+&aiu_i2s_dma {
+ status = "okay";
};
&cec_AO {
@@ -159,6 +200,10 @@
};
};
+&i2s_dai {
+ status = "okay";
+};
+
&ir {
status = "okay";
pinctrl-0 = <&remote_input_ao_pins>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
index d32cf3846370..f053595ebdc4 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
@@ -65,6 +65,39 @@
};
};
};
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "meson-gx-audio";
+
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ simple-audio-card,dai-link@0 {
+ /* HDMI Output */
+ format = "i2s";
+ mclk-fs = <256>;
+ bitclock-master = <&i2s_dai>;
+ frame-master = <&i2s_dai>;
+
+ plat {
+ sound-dai = <&aiu_i2s_dma>;
+ };
+
+ cpu {
+ sound-dai = <&i2s_dai>;
+ };
+
+ codec {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
};
&cec_AO {
@@ -74,6 +107,14 @@
hdmi-phandle = <&hdmi_tx>;
};
+&audio {
+ status = "okay";
+};
+
+&aiu_i2s_dma {
+ status = "okay";
+};
+
&hdmi_tx {
status = "okay";
pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
@@ -86,6 +127,10 @@
};
};
+&i2s_dai {
+ status = "okay";
+};
+
&i2c_A {
status = "okay";
pinctrl-0 = <&i2c_a_pins>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts
index f63bceb88caa..f56969efffba 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts
@@ -84,6 +84,39 @@
regulator-always-on;
};
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "meson-gx-audio";
+
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ simple-audio-card,dai-link@0 {
+ /* HDMI Output */
+ format = "i2s";
+ mclk-fs = <256>;
+ bitclock-master = <&i2s_dai>;
+ frame-master = <&i2s_dai>;
+
+ plat {
+ sound-dai = <&aiu_i2s_dma>;
+ };
+
+ cpu {
+ sound-dai = <&i2s_dai>;
+ };
+
+ codec {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
+
vcc_3v3: regulator-vcc_3v3 {
compatible = "regulator-fixed";
regulator-name = "VCC_3V3";
@@ -130,6 +163,14 @@
hdmi-phandle = <&hdmi_tx>;
};
+&audio {
+ status = "okay";
+};
+
+&aiu_i2s_dma {
+ status = "okay";
+};
+
&cvbs_vdac_port {
cvbs_vdac_out: endpoint {
remote-endpoint = <&cvbs_connector_in>;
@@ -151,6 +192,10 @@
pinctrl-names = "default";
};
+&i2s_dai {
+ status = "okay";
+};
+
&hdmi_tx {
status = "okay";
pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts
index 6739697be1de..e3e777f665c0 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts
@@ -102,6 +102,39 @@
};
};
};
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "meson-gx-audio";
+
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ simple-audio-card,dai-link@0 {
+ /* HDMI Output */
+ format = "i2s";
+ mclk-fs = <256>;
+ bitclock-master = <&i2s_dai>;
+ frame-master = <&i2s_dai>;
+
+ plat {
+ sound-dai = <&aiu_i2s_dma>;
+ };
+
+ cpu {
+ sound-dai = <&i2s_dai>;
+ };
+
+ codec {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
};
&cec_AO {
@@ -111,6 +144,14 @@
hdmi-phandle = <&hdmi_tx>;
};
+&audio {
+ status = "okay";
+};
+
+&aiu_i2s_dma {
+ status = "okay";
+};
+
&cvbs_vdac_port {
cvbs_vdac_out: endpoint {
remote-endpoint = <&cvbs_connector_in>;
@@ -135,6 +176,10 @@
};
};
+&i2s_dai {
+ status = "okay";
+};
+
&ir {
status = "okay";
pinctrl-0 = <&remote_input_ao_pins>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts
index 5896e8a5d86b..f8c66a7972b3 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts
@@ -32,6 +32,39 @@
};
};
};
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "meson-gx-audio";
+
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ simple-audio-card,dai-link@0 {
+ /* HDMI Output */
+ format = "i2s";
+ mclk-fs = <256>;
+ bitclock-master = <&i2s_dai>;
+ frame-master = <&i2s_dai>;
+
+ plat {
+ sound-dai = <&aiu_i2s_dma>;
+ };
+
+ cpu {
+ sound-dai = <&i2s_dai>;
+ };
+
+ codec {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
};
&cec_AO {
@@ -41,12 +74,24 @@
hdmi-phandle = <&hdmi_tx>;
};
+&audio {
+ status = "okay";
+};
+
+&aiu_i2s_dma {
+ status = "okay";
+};
+
&cvbs_vdac_port {
cvbs_vdac_out: endpoint {
remote-endpoint = <&cvbs_connector_in>;
};
};
+&i2s_dai {
+ status = "okay";
+};
+
&hdmi_tx {
status = "okay";
pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
index 0868da476e41..ea71261f1855 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
@@ -85,6 +85,39 @@
};
};
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "meson-gx-audio";
+
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ simple-audio-card,dai-link@0 {
+ /* HDMI Output */
+ format = "i2s";
+ mclk-fs = <256>;
+ bitclock-master = <&i2s_dai>;
+ frame-master = <&i2s_dai>;
+
+ plat {
+ sound-dai = <&aiu_i2s_dma>;
+ };
+
+ cpu {
+ sound-dai = <&i2s_dai>;
+ };
+
+ codec {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
+
pwmleds {
compatible = "pwm-leds";
@@ -205,6 +238,14 @@
hdmi-phandle = <&hdmi_tx>;
};
+&audio {
+ status = "okay";
+};
+
+&aiu_i2s_dma {
+ status = "okay";
+};
+
&cpu0 {
#cooling-cells = <2>;
};
@@ -255,6 +296,10 @@
};
};
+&i2s_dai {
+ status = "okay";
+};
+
&i2c_A {
status = "okay";
pinctrl-0 = <&i2c_a_pins>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
index f7a1cffab4a8..b9c5e6444daa 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
@@ -75,6 +75,39 @@
};
};
};
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "meson-gx-audio";
+
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ simple-audio-card,dai-link@0 {
+ /* HDMI Output */
+ format = "i2s";
+ mclk-fs = <256>;
+ bitclock-master = <&i2s_dai>;
+ frame-master = <&i2s_dai>;
+
+ plat {
+ sound-dai = <&aiu_i2s_dma>;
+ };
+
+ cpu {
+ sound-dai = <&i2s_dai>;
+ };
+
+ codec {
+ sound-dai = <&hdmi_tx>;
+ };
+ };
+ };
};
&cec_AO {
@@ -84,6 +117,14 @@
hdmi-phandle = <&hdmi_tx>;
};
+&audio {
+ status = "okay";
+};
+
+&aiu_i2s_dma {
+ status = "okay";
+};
+
&cvbs_vdac_port {
cvbs_vdac_out: endpoint {
remote-endpoint = <&cvbs_connector_in>;
@@ -129,6 +170,10 @@
};
};
+&i2s_dai {
+ status = "okay";
+};
+
&ir {
status = "okay";
pinctrl-0 = <&remote_input_ao_pins>;
--
2.18.0

View File

@@ -0,0 +1,78 @@
From 5aeac5cbf34078e6ee256ec8684ec95d5c6e5064 Mon Sep 17 00:00:00 2001
From: Neil Armstrong <narmstrong@baylibre.com>
Date: Mon, 2 Jul 2018 12:21:55 +0200
Subject: [PATCH 19/21] drm: bridge: dw-hdmi: Use AUTO CTS setup mode when
non-AHB audio
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 41 ++++++++++++++---------
1 file changed, 26 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 3c136f2b954f..a68ffbb0ce3e 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -430,8 +430,12 @@ static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts,
/* nshift factor = 0 */
hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
- hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
- HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
+ /* Use Auto CTS mode with CTS is unknown */
+ if (cts)
+ hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
+ HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
+ else
+ hdmi_writeb(hdmi, 0, HDMI_AUD_CTS3);
hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
@@ -501,24 +505,31 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
{
unsigned long ftdms = pixel_clk;
unsigned int n, cts;
+ u8 config3;
u64 tmp;
n = hdmi_compute_n(sample_rate, pixel_clk);
- /*
- * Compute the CTS value from the N value. Note that CTS and N
- * can be up to 20 bits in total, so we need 64-bit math. Also
- * note that our TDMS clock is not fully accurate; it is accurate
- * to kHz. This can introduce an unnecessary remainder in the
- * calculation below, so we don't try to warn about that.
- */
- tmp = (u64)ftdms * n;
- do_div(tmp, 128 * sample_rate);
- cts = tmp;
+ config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
- dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n",
- __func__, sample_rate, ftdms / 1000000, (ftdms / 1000) % 1000,
- n, cts);
+ if (config3 & HDMI_CONFIG3_AHBAUDDMA) {
+ /*
+ * Compute the CTS value from the N value. Note that CTS and N
+ * can be up to 20 bits in total, so we need 64-bit math. Also
+ * note that our TDMS clock is not fully accurate; it is
+ * accurate to kHz. This can introduce an unnecessary remainder
+ * in the calculation below, so we don't try to warn about that.
+ */
+ tmp = (u64)ftdms * n;
+ do_div(tmp, 128 * sample_rate);
+ cts = tmp;
+
+ dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n",
+ __func__, sample_rate,
+ ftdms / 1000000, (ftdms / 1000) % 1000,
+ n, cts);
+ } else
+ cts = 0;
spin_lock_irq(&hdmi->audio_lock);
hdmi->audio_n = n;
--
2.18.0

View File

@@ -0,0 +1,40 @@
From 2facc1501a79a8a8a2ad8792977a7011abc87adf Mon Sep 17 00:00:00 2001
From: Neil Armstrong <narmstrong@baylibre.com>
Date: Wed, 28 Feb 2018 16:07:18 +0100
Subject: [PATCH 20/21] drm/meson: Call drm_crtc_vblank_on /
drm_crtc_vblank_off
Make sure that the CRTC code will call the enable/disable_vblank hooks.
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
drivers/gpu/drm/meson/meson_crtc.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c
index 05520202c967..4dd0df0fd607 100644
--- a/drivers/gpu/drm/meson/meson_crtc.c
+++ b/drivers/gpu/drm/meson/meson_crtc.c
@@ -102,6 +102,8 @@ static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
priv->io_base + _REG(VPP_MISC));
priv->viu.osd1_enabled = true;
+
+ drm_crtc_vblank_on(crtc);
}
static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
@@ -110,6 +112,10 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
struct meson_drm *priv = meson_crtc->priv;
+ DRM_DEBUG_DRIVER("\n");
+
+ drm_crtc_vblank_off(crtc);
+
priv->viu.osd1_enabled = false;
priv->viu.osd1_commit = false;
--
2.18.0

View File

@@ -0,0 +1,36 @@
From cc003c1fada0ef753e1cc28c921c59066e069828 Mon Sep 17 00:00:00 2001
From: Neil Armstrong <narmstrong@baylibre.com>
Date: Tue, 10 Jul 2018 15:00:45 +0200
Subject: [PATCH 21/21] media: platform: meson-ao-cec: make busy TX warning
silent
Switch to dev_dbg for the busy TX message to avoid having a flood of:
[ 228.064570] meson-ao-cec c8100100.cec: meson_ao_cec_transmit: busy TX: aborting
[ 230.368489] meson-ao-cec c8100100.cec: meson_ao_cec_transmit: busy TX: aborting
[ 234.208655] meson-ao-cec c8100100.cec: meson_ao_cec_transmit: busy TX: aborting
[ 236.512558] meson-ao-cec c8100100.cec: meson_ao_cec_transmit: busy TX: aborting
This message is only a debug hint and not an error.
Fixes: 7ec2c0f72cb1 ("media: platform: Add Amlogic Meson AO CEC Controller driver")
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
drivers/media/platform/meson/ao-cec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/platform/meson/ao-cec.c b/drivers/media/platform/meson/ao-cec.c
index 8040a6285c3f..cd4be38ab5ac 100644
--- a/drivers/media/platform/meson/ao-cec.c
+++ b/drivers/media/platform/meson/ao-cec.c
@@ -524,7 +524,7 @@ static int meson_ao_cec_transmit(struct cec_adapter *adap, u8 attempts,
return ret;
if (reg == TX_BUSY) {
- dev_err(&ao_cec->pdev->dev, "%s: busy TX: aborting\n",
+ dev_dbg(&ao_cec->pdev->dev, "%s: busy TX: aborting\n",
__func__);
meson_ao_cec_write(ao_cec, CEC_TX_MSG_CMD, TX_ABORT, &ret);
}
--
2.18.0

View File

@@ -0,0 +1,37 @@
From 90dc377aa5ed708a38a010e6861b468cd9373f4f Mon Sep 17 00:00:00 2001
From: Neil Armstrong <narmstrong@baylibre.com>
Date: Tue, 28 Feb 2017 15:23:42 +0100
Subject: [PATCH] Disable DRM_FORMAT_ARGB8888 to make X armsoc work cirrectly
---
drivers/gpu/drm/meson/meson_plane.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
index a32d3b6e2e12e..7ab8f4472c741 100644
--- a/drivers/gpu/drm/meson/meson_plane.c
+++ b/drivers/gpu/drm/meson/meson_plane.c
@@ -117,6 +117,7 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
priv->viu.osd1_blk0_cfg[0] |= OSD_OUTPUT_COLOR_RGB;
switch (fb->format->format) {
+ case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_XRGB8888:
/* For XRGB, replace the pixel's alpha by 0xFF */
writel_bits_relaxed(OSD_REPLACE_EN, OSD_REPLACE_EN,
@@ -124,6 +125,7 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
OSD_COLOR_MATRIX_32_ARGB;
break;
+#if 0
case DRM_FORMAT_ARGB8888:
/* For ARGB, use the pixel's alpha */
writel_bits_relaxed(OSD_REPLACE_EN, 0,
@@ -131,6 +133,7 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
OSD_COLOR_MATRIX_32_ARGB;
break;
+#endif
case DRM_FORMAT_RGB888:
priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_24 |
OSD_COLOR_MATRIX_24_RGB;